From a03da5e2aab552daa3e7ced70b3e90466c7c8b82 Mon Sep 17 00:00:00 2001 From: lombardof Date: Sat, 2 Jun 2018 18:36:44 +0200 Subject: [PATCH] sdn controllers: list, create, show Change-Id: I2d801be01ae1e56a2a44ca6f8ea32c7585e4d381 Signed-off-by: lombardof --- instancehandler/views.py | 4 +- lib/osm/osmclient/client.py | 40 +++++ .../project/osm/osm_project_left_sidebar.html | 6 + projecthandler/urls/project.py | 1 + sdnctrlhandler/__init__.py | 0 sdnctrlhandler/admin.py | 3 + sdnctrlhandler/apps.py | 7 + sdnctrlhandler/migrations/__init__.py | 0 sdnctrlhandler/models.py | 5 + .../template/modal/sdn_details.html | 50 +++++++ sdnctrlhandler/template/sdn_create.html | 139 ++++++++++++++++++ sdnctrlhandler/template/sdn_list.html | 95 ++++++++++++ sdnctrlhandler/tests.py | 3 + sdnctrlhandler/urls.py | 26 ++++ sdnctrlhandler/views.py | 89 +++++++++++ sf_t3d/settings.py | 4 +- sf_t3d/urls.py | 1 + static/src/sdnctrlhandler/sdn_list.js | 57 +++++++ vimhandler/views.py | 6 +- 19 files changed, 531 insertions(+), 5 deletions(-) create mode 100644 sdnctrlhandler/__init__.py create mode 100644 sdnctrlhandler/admin.py create mode 100644 sdnctrlhandler/apps.py create mode 100644 sdnctrlhandler/migrations/__init__.py create mode 100644 sdnctrlhandler/models.py create mode 100644 sdnctrlhandler/template/modal/sdn_details.html create mode 100644 sdnctrlhandler/template/sdn_create.html create mode 100644 sdnctrlhandler/template/sdn_list.html create mode 100644 sdnctrlhandler/tests.py create mode 100644 sdnctrlhandler/urls.py create mode 100644 sdnctrlhandler/views.py create mode 100644 static/src/sdnctrlhandler/sdn_list.js diff --git a/instancehandler/views.py b/instancehandler/views.py index a5118f6..ea5528d 100644 --- a/instancehandler/views.py +++ b/instancehandler/views.py @@ -30,7 +30,9 @@ def list(request, project_id=None, type=None): elif type == 'vnf': result = client.vnf_list() - return __response_handler(request, {'instances': result, 'type': type, 'project_id': project_id}, 'instance_list.html') + result = {'instances': result, 'type': type, 'project_id': project_id} + + return __response_handler(request, result, 'instance_list.html') @login_required diff --git a/lib/osm/osmclient/client.py b/lib/osm/osmclient/client.py index 7a2d908..a65808f 100644 --- a/lib/osm/osmclient/client.py +++ b/lib/osm/osmclient/client.py @@ -77,6 +77,46 @@ class Client(object): json=vim_data) return None + + def sdn_list(self): + token = self.get_token() + if token: + self._headers['Authorization'] = 'Bearer {}'.format(token) + self._headers['accept'] = 'application/json' + _url = "{0}/admin/v1/sdns".format(self._base_path) + return self._send_get(_url, headers=self._headers) + + def sdn_delete(self, id): + token = self.get_token() + if token: + self._headers['Authorization'] = 'Bearer {}'.format(token) + self._headers['accept'] = 'application/json' + _url = "{0}/admin/v1/sdns/{1}".format(self._base_path, id) + return self._send_delete(_url, headers=self._headers) + return None + + def sdn_get(self, id): + token = self.get_token() + if token: + self._headers['Authorization'] = 'Bearer {}'.format(token) + self._headers['accept'] = 'application/json' + _url = "{0}/admin/v1/sdns/{1}".format(self._base_path, id) + return self._send_get(_url, headers=self._headers) + return None + + def sdn_create(self, sdn_data): + token = self.get_token() + headers = {} + if token: + headers['Authorization'] = 'Bearer {}'.format(token) + headers['Content-Type'] = 'application/json' + headers['accept'] = 'application/json' + + _url = "{0}/admin/v1/sdns".format(self._base_path) + return self._send_post(_url, headers=headers, + json=sdn_data) + return None + def nsd_list(self): token = self.get_token() if token: diff --git a/projecthandler/template/project/osm/osm_project_left_sidebar.html b/projecthandler/template/project/osm/osm_project_left_sidebar.html index 808303e..495f85e 100644 --- a/projecthandler/template/project/osm/osm_project_left_sidebar.html +++ b/projecthandler/template/project/osm/osm_project_left_sidebar.html @@ -48,6 +48,12 @@ VNF Instances + {% url "projects:sdns:list" project_id=project_id as sdn_list_url %} +
  • + + SDN Controllers + +
  • CONFIG
  • {% url "vim:list" type='ns' as vim_list_url %}
  • diff --git a/projecthandler/urls/project.py b/projecthandler/urls/project.py index 2b2f824..eb88a9e 100644 --- a/projecthandler/urls/project.py +++ b/projecthandler/urls/project.py @@ -21,6 +21,7 @@ urlpatterns = [ url(r'^list/', views.user_projects, name='projects_list'), url(r'^new/', views.create_new_project, name='new_project'), url(r'^(?P\d+)/$', views.open_project, name='open_project'), + url(r'^(?P\d+)/sdn/', include('sdnctrlhandler.urls', namespace='sdns'), name='sdns_base'), url(r'^(?P\d+)/instances/', include('instancehandler.urls', namespace='instances'), name='instances_base'), url(r'^(?P\d+)/delete$', views.delete_project, name='delete_project'), url(r'^(?P\d+)/graph(/$)', views.graph, name='graph_view'), diff --git a/sdnctrlhandler/__init__.py b/sdnctrlhandler/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sdnctrlhandler/admin.py b/sdnctrlhandler/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/sdnctrlhandler/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/sdnctrlhandler/apps.py b/sdnctrlhandler/apps.py new file mode 100644 index 0000000..588547f --- /dev/null +++ b/sdnctrlhandler/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class SdnctrlhandlerConfig(AppConfig): + name = 'sdnctrlhandler' diff --git a/sdnctrlhandler/migrations/__init__.py b/sdnctrlhandler/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sdnctrlhandler/models.py b/sdnctrlhandler/models.py new file mode 100644 index 0000000..bd4b2ab --- /dev/null +++ b/sdnctrlhandler/models.py @@ -0,0 +1,5 @@ +from __future__ import unicode_literals + +from django.db import models + +# Create your models here. diff --git a/sdnctrlhandler/template/modal/sdn_details.html b/sdnctrlhandler/template/modal/sdn_details.html new file mode 100644 index 0000000..9658dfb --- /dev/null +++ b/sdnctrlhandler/template/modal/sdn_details.html @@ -0,0 +1,50 @@ + \ No newline at end of file diff --git a/sdnctrlhandler/template/sdn_create.html b/sdnctrlhandler/template/sdn_create.html new file mode 100644 index 0000000..a1aeadf --- /dev/null +++ b/sdnctrlhandler/template/sdn_create.html @@ -0,0 +1,139 @@ +{% extends "base.html" %} +{% load get %} +{% load staticfiles %} + + +{% block head_block %} + {{ block.super }} + +{% endblock %} +{% block title_header_big %} + {{ block.super }} +{% endblock %} +{% block left_sidebar %} + + {% include 'osm/osm_project_left_sidebar.html' %} + +{% endblock %} + + +{% block breadcrumb_body %} + {{ block.super }} +
  • SDN Controllers
  • +{% endblock %} + +{% block content_body %} + {{ block.super }} + +
    +
    +
    + {% csrf_token %} +
    +
    +

    New SDN Controller

    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    +{% endblock %} + +{% block resource_block %} + {{ block.super }} + + + + +{% endblock %} + +{% block footer %} + {% include "footer.html" %} +{% endblock %} \ No newline at end of file diff --git a/sdnctrlhandler/template/sdn_list.html b/sdnctrlhandler/template/sdn_list.html new file mode 100644 index 0000000..9b7386f --- /dev/null +++ b/sdnctrlhandler/template/sdn_list.html @@ -0,0 +1,95 @@ +{% extends "base.html" %} +{% load get %} +{% load staticfiles %} + + +{% block head_block %} + {{ block.super }} + +{% endblock %} +{% block title_header_big %} + {{ block.super }} +{% endblock %} +{% block left_sidebar %} + {% include 'osm/osm_project_left_sidebar.html' %} +{% endblock %} + + +{% block breadcrumb_body %} + {{ block.super }} +
  • SDN Controllers
  • +{% endblock %} + +{% block content_body %} + {{ block.super }} + {% include 'modal/sdn_details.html' %} + {% csrf_token %} +
    +
    + +
    +
    +

    Registered SDN Controllers

    + +
    +
    + + + + + + + + + + + + + + + {% for s in sdns %} + + + + + + + + + + + {% endfor %} + +
    IdNameTypeOperational StateIPPortActions
    {{ s|get:"_id" }}{{ s|get:"name" }}{{ s|get:"type" }}{{ s|get_sub:"_admin,operationalState"}}{{ s|get:"ip" }}{{ s|get:"port" }} +
    + + +
    +
    +
    +
    +
    + +
    +{% endblock %} + +{% block resource_block %} + {{ block.super }} + + + + + + +{% endblock %} + +{% block footer %} + {% include "footer.html" %} +{% endblock %} \ No newline at end of file diff --git a/sdnctrlhandler/tests.py b/sdnctrlhandler/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/sdnctrlhandler/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/sdnctrlhandler/urls.py b/sdnctrlhandler/urls.py new file mode 100644 index 0000000..93a5929 --- /dev/null +++ b/sdnctrlhandler/urls.py @@ -0,0 +1,26 @@ +# +# Copyright 2018 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from django.conf.urls import url +from sdnctrlhandler import views + +urlpatterns = [ + url(r'^list$', views.list, name='list'), + url(r'^create$', views.create, name='create'), + url(r'^(?P[0-9a-z-]+)/delete$', views.delete, name='delete'), + url(r'^(?P[0-9a-z-]+)', views.show, name='show'), + +] \ No newline at end of file diff --git a/sdnctrlhandler/views.py b/sdnctrlhandler/views.py new file mode 100644 index 0000000..0cd6692 --- /dev/null +++ b/sdnctrlhandler/views.py @@ -0,0 +1,89 @@ +# +# Copyright 2018 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from django.shortcuts import render, redirect +from django.contrib.auth.decorators import login_required +from django.http import JsonResponse +from lib.osm.osmclient.client import Client +import logging + +logging.basicConfig(level=logging.DEBUG) +log = logging.getLogger('view.py') + + +@login_required +def list(request, project_id): + client = Client() + result = client.sdn_list() + + result = { + 'project_id': project_id, + 'sdns': result + } + return __response_handler(request, result, 'sdn_list.html') + + +@login_required +def create(request, project_id): + result = {'project_id': project_id} + if request.method == 'GET': + return __response_handler(request, result, 'sdn_create.html') + else: + new_sdn_dict = request.POST.dict() + client = Client() + keys = ["name", + "type", + "version", + "dpid", + "ip", + "port", + "user", + "password"] + sdn_data = dict(filter(lambda i: i[0] in keys and len(i[1]) > 0, new_sdn_dict.items())) + sdn_data['port'] = int(sdn_data['port']) + + result = client.sdn_create(sdn_data) + + return __response_handler(request, result, 'projects:sdns:list', to_redirect=True, project_id=project_id) + + +@login_required +def delete(request, project_id, sdn_id=None): + try: + client = Client() + del_res = client.sdn_delete(sdn_id) + except Exception as e: + log.exception(e) + return __response_handler(request, {}, 'projects:sdns:list', to_redirect=True, project_id=project_id) + + +@login_required +def show(request, project_id, sdn_id=None): + client = Client() + datacenter = client.sdn_get(sdn_id) + return __response_handler(request, { + "sdn": datacenter + }, project_id=project_id) + + +def __response_handler(request, data_res, url=None, to_redirect=None, *args, **kwargs): + raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') + if 'application/json' in raw_content_types: + return JsonResponse(data_res) + elif to_redirect: + return redirect(url, *args, **kwargs) + else: + return render(request, url, data_res) diff --git a/sf_t3d/settings.py b/sf_t3d/settings.py index 619f4a2..658bafd 100644 --- a/sf_t3d/settings.py +++ b/sf_t3d/settings.py @@ -48,7 +48,8 @@ INSTALLED_APPS = [ 'sf_user', 'projecthandler', 'vimhandler', - 'instancehandler' + 'instancehandler', + 'sdnctrlhandler' ] MIDDLEWARE_CLASSES = [ @@ -80,6 +81,7 @@ TEMPLATES = [ os.path.join(BASE_DIR, 'projecthandler', 'template', 'project'), os.path.join(BASE_DIR, 'vimhandler', 'template'), os.path.join(BASE_DIR, 'instancehandler', 'template'), + os.path.join(BASE_DIR, 'sdnctrlhandler', 'template'), ], 'APP_DIRS': True, 'OPTIONS': { diff --git a/sf_t3d/urls.py b/sf_t3d/urls.py index 0784ed1..bea83a2 100644 --- a/sf_t3d/urls.py +++ b/sf_t3d/urls.py @@ -27,6 +27,7 @@ urlpatterns = [ url(r'^register', user_views.register_view, name='register_user'), url(r'^projects/', include('projecthandler.urls.project', namespace='projects'), name='projects_base'), url(r'^vims/', include('vimhandler.urls', namespace='vim'), name='vims_base'), + #url(r'^sdn/', include('sdnctrlhandler.urls', namespace='sdn'), name='sdns_base'), url(r'^$', views.home, name='home'), url(r'^home', views.home, name='home'), diff --git a/static/src/sdnctrlhandler/sdn_list.js b/static/src/sdnctrlhandler/sdn_list.js new file mode 100644 index 0000000..8069474 --- /dev/null +++ b/static/src/sdnctrlhandler/sdn_list.js @@ -0,0 +1,57 @@ +function deleteSDN(project_id, sdn_uuid) { + bootbox.confirm("Are you sure want to delete?", function (result) { + if (result) { + location.href = '/projects/' + project_id + '/sdn/' + sdn_uuid + '/delete' + } + }) +} + +function showSDN(project_id, sdn_uuid) { + var dialog = bootbox.dialog({ + message: '
    Loading...
    ', + closeButton: true + }); + + $.ajax({ + url: '/projects/' + project_id + '/sdn/' + sdn_uuid , + //url: '/sdn/' + sdn_uuid, + type: 'GET', + dataType: "json", + contentType: "application/json;charset=utf-8", + success: function (result) { + //$('#modal_show_vim_body').empty(); + var sdn = result.sdn; + if (sdn) { + $('#modal_show_sdn_body').find('span').text('-'); + for (var k in sdn) { + $('#' + k).text(sdn[k]) + } + if (sdn['_admin']) { + for (var i in sdn['_admin']) { + if (i === 'modified' || i === 'created') { + //$('#' + i).text(new Date(sdn['_admin'][i]* 1000).toUTCString()); + $('#' + i).text(moment(sdn['_admin'][i] * 1000).format('DD/MM/YY hh:mm:ss')); + } + else if (i === 'deployed') { + $('#' + i).text(JSON.stringify(sdn['_admin'][i])) + } + else + $('#' + i).text(sdn['_admin'][i]) + } + } + dialog.modal('hide'); + $('#modal_show_sdn').modal('show'); + } + else { + dialog.modal('hide'); + bootbox.alert("An error occurred while retrieving the SDN controller info."); + } + + }, + error: function (result) { + dialog.modal('hide'); + bootbox.alert("An error occurred while retrieving the SDN controller info."); + } + }); + +} \ No newline at end of file diff --git a/vimhandler/views.py b/vimhandler/views.py index 78e2e67..19b58ad 100644 --- a/vimhandler/views.py +++ b/vimhandler/views.py @@ -15,14 +15,14 @@ # from django.shortcuts import render, redirect -from django.contrib.auth.decorators import login_required, permission_required -from django.http import HttpResponse, JsonResponse +from django.contrib.auth.decorators import login_required +from django.http import JsonResponse from lib.osm.osmclient.client import Client import yaml import logging logging.basicConfig(level=logging.DEBUG) -log = logging.getLogger('helper.py') +log = logging.getLogger('view.py') @login_required def list(request): -- 2.17.1