From: melian Date: Wed, 6 May 2020 09:53:27 +0000 (+0000) Subject: Feature 8178 VNF Repositories X-Git-Tag: v7.1.0rc1~2^2 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F55%2F8855%2F1;p=osm%2FLW-UI.git Feature 8178 VNF Repositories Change-Id: Ic1e34107157fe346df47755ad19a8101c25a0449 Signed-off-by: melian --- diff --git a/build-debpkg.sh b/build-debpkg.sh index 90553c3..f2c7af2 100755 --- a/build-debpkg.sh +++ b/build-debpkg.sh @@ -15,7 +15,7 @@ # under the License. -PKG_DIRECTORIES="authosm descriptorhandler instancehandler lib projecthandler sdnctrlhandler sf_t3d static template userhandler vimhandler packagehandler netslicehandler wimhandler rolehandler k8sclusterhandler k8srepohandler" +PKG_DIRECTORIES="authosm descriptorhandler instancehandler lib projecthandler sdnctrlhandler sf_t3d static template userhandler vimhandler packagehandler netslicehandler wimhandler rolehandler k8sclusterhandler k8srepohandler osmrepohandler" PKG_FILES="bower.json django.ini LICENSE manage.py nginx-app.conf README.md requirements.txt supervisor-app.conf .bowerrc entrypoint.sh package.json" MDG_NAME=lightui DEB_INSTALL=debian/osm-${MDG_NAME}.install diff --git a/lib/osm/osmclient/clientv2.py b/lib/osm/osmclient/clientv2.py index db37e49..9e9973c 100644 --- a/lib/osm/osmclient/clientv2.py +++ b/lib/osm/osmclient/clientv2.py @@ -1838,6 +1838,97 @@ class Client(object): result['data'] = Util.json_loads_byteified(r.text) return result + def osmr_get(self, token, id): + result = {'error': True, 'data': ''} + headers = {"accept": "application/json", + 'Authorization': 'Bearer {}'.format(token['id'])} + _url = "{0}/admin/v1/osmrepos/{1}".format(self._base_path, id) + try: + r = requests.get(_url, params=None, verify=False, + stream=True, headers=headers) + except Exception as e: + log.exception(e) + result['data'] = str(e) + return result + if r.status_code in (200, 201, 202, 204): + result['error'] = False + result['data'] = Util.json_loads_byteified(r.text) + return result + + def osmr_list(self, token): + result = {'error': True, 'data': ''} + headers = {"accept": "application/json", + 'Authorization': 'Bearer {}'.format(token['id'])} + _url = "{0}/admin/v1/osmrepos".format(self._base_path) + try: + r = requests.get(_url, params=None, verify=False, + stream=True, headers=headers) + except Exception as e: + log.exception(e) + result['data'] = str(e) + return result + if r.status_code in (200, 201, 202, 204): + result['error'] = False + result['data'] = Util.json_loads_byteified(r.text) + return result + + def osmr_create(self, token, cluster_data): + result = {'error': True, 'data': ''} + headers = {"Content-Type": "application/json", "accept": "application/json", + 'Authorization': 'Bearer {}'.format(token['id'])} + + _url = "{0}/admin/v1/osmrepos".format(self._base_path) + + try: + r = requests.post(_url, json=cluster_data, + verify=False, headers=headers) + except Exception as e: + log.exception(e) + result['data'] = str(e) + return result + if r.status_code in (200, 201, 202, 204): + result['error'] = False + result['data'] = Util.json_loads_byteified(r.text) + return result + + def osmr_update(self, token, id, cluster_data): + result = {'error': True, 'data': ''} + headers = {"Content-Type": "application/json", "accept": "application/json", + 'Authorization': 'Bearer {}'.format(token['id'])} + + _url = "{0}/admin/v1/osmrepos/{1}".format(self._base_path, id) + try: + r = requests.patch(_url, json=cluster_data, + verify=False, headers=headers) + except Exception as e: + log.exception(e) + result['data'] = str(e) + return result + if r.status_code in (200, 201, 202, 204): + result['error'] = False + else: + result['data'] = Util.json_loads_byteified(r.text) + return result + + def osmr_delete(self, token, id): + result = {'error': True, 'data': ''} + headers = {"Content-Type": "application/yaml", "accept": "application/json", + 'Authorization': 'Bearer {}'.format(token['id'])} + + _url = "{0}/admin/v1/osmrepos/{1}".format(self._base_path, id) + try: + r = requests.delete(_url, params=None, + verify=False, headers=headers) + except Exception as e: + log.exception(e) + result['data'] = str(e) + return result + if r.status_code in (200, 201, 202, 204): + result['error'] = False + else: + result['data'] = Util.json_loads_byteified(r.text) + return result + @staticmethod def md5(f): hash_md5 = hashlib.md5() diff --git a/osmrepohandler/__init__.py b/osmrepohandler/__init__.py new file mode 100644 index 0000000..340b024 --- /dev/null +++ b/osmrepohandler/__init__.py @@ -0,0 +1,15 @@ +# +# Copyright 2019 EveryUP Srl +# +# 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. +# \ No newline at end of file diff --git a/osmrepohandler/apps.py b/osmrepohandler/apps.py new file mode 100644 index 0000000..cc72e0a --- /dev/null +++ b/osmrepohandler/apps.py @@ -0,0 +1,22 @@ +# +# Copyright 2019 EveryUP Srl +# +# 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 __future__ import unicode_literals + +from django.apps import AppConfig + + +class OSMrepohandlerConfig(AppConfig): + name = 'osmrepohandler' diff --git a/osmrepohandler/models.py b/osmrepohandler/models.py new file mode 100644 index 0000000..3199b61 --- /dev/null +++ b/osmrepohandler/models.py @@ -0,0 +1,20 @@ +# +# Copyright 2019 EveryUP Srl +# +# 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 __future__ import unicode_literals + +from django.db import models + +# Create your models here. diff --git a/osmrepohandler/template/modal/osmrepo_details.html b/osmrepohandler/template/modal/osmrepo_details.html new file mode 100644 index 0000000..06a50c1 --- /dev/null +++ b/osmrepohandler/template/modal/osmrepo_details.html @@ -0,0 +1,39 @@ + + + \ No newline at end of file diff --git a/osmrepohandler/template/modal/osmrepo_register.html b/osmrepohandler/template/modal/osmrepo_register.html new file mode 100644 index 0000000..5ead65d --- /dev/null +++ b/osmrepohandler/template/modal/osmrepo_register.html @@ -0,0 +1,75 @@ + + + + + + diff --git a/osmrepohandler/template/modal/osmrepo_update.html b/osmrepohandler/template/modal/osmrepo_update.html new file mode 100644 index 0000000..d8dbb44 --- /dev/null +++ b/osmrepohandler/template/modal/osmrepo_update.html @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/osmrepohandler/template/osmrepo_list.html b/osmrepohandler/template/osmrepo_list.html new file mode 100644 index 0000000..709e599 --- /dev/null +++ b/osmrepohandler/template/osmrepo_list.html @@ -0,0 +1,195 @@ + + +{% 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 }} +
  • OSM repository
  • +{% endblock %} + +{% block content_body %} + {{ block.super }} + {% include 'modal/osmrepo_details.html' %} + {% include 'modal/osmrepo_register.html' %} + {% csrf_token %} +
    +
    + +
    +
    +

    Registered OSM repository

    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + +
    NameIdentifierUrlTypeCreatedModifiedActions
    +
    +
    +
    + +
    +{% endblock %} + +{% block resource_block %} + {{ block.super }} + + + + + + + + + + + + + + + + + + + + +{% endblock %} + +{% block footer %} + {% include "footer.html" %} +{% endblock %} \ No newline at end of file diff --git a/osmrepohandler/urls.py b/osmrepohandler/urls.py new file mode 100644 index 0000000..64e9d3e --- /dev/null +++ b/osmrepohandler/urls.py @@ -0,0 +1,26 @@ +# +# Copyright 2019 EveryUP Srl +# +# 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 osmrepohandler 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'), + url(r'^(?P[0-9a-z-]+)/update$', views.update, name='update'), +] \ No newline at end of file diff --git a/osmrepohandler/views.py b/osmrepohandler/views.py new file mode 100644 index 0000000..2b9299c --- /dev/null +++ b/osmrepohandler/views.py @@ -0,0 +1,107 @@ +# +# Copyright 2020 ATOS +# +# 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 sf_t3d.decorators import login_required +from django.http import HttpResponse +import json +import logging +import authosm.utils as osmutils +from lib.osm.osmclient.clientv2 import Client + +logging.basicConfig(level=logging.DEBUG) +log = logging.getLogger('osmrepohandler/view.py') + + +@login_required +def list(request): + user = osmutils.get_user(request) + project_id = user.project_id + result = {'project_id': project_id} + raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') + if 'application/json' not in raw_content_types: + return __response_handler(request, result, 'osmrepo_list.html') + client = Client() + result_client = client.osmr_list(user.get_token()) + + result['osmr'] = result_client['data'] if result_client and result_client['error'] is False else [] + + return __response_handler(request, result, 'osmrepo_list.html') + + +@login_required +def create(request): + user = osmutils.get_user(request) + project_id = user.project_id + result = {'project_id': project_id} + client = Client() + try: + new_osmr = { + "name": request.POST.get('name'), + "type": request.POST.get('type'), + "url": request.POST.get('url'), + "description": request.POST.get('description'), + } + except Exception as e: + return __response_handler(request, {'status': 400, 'code': 'BAD_REQUEST', 'detail': e.message}, url=None, status=400) + result = client.osmr_create(user.get_token(), new_osmr) + if result['error']: + return __response_handler(request, result['data'], url=None, status=result['data']['status'] if 'status' in result['data'] else 500) + else: + return __response_handler(request, result, 'osmr:list', to_redirect=True) + + +@login_required +def update(request, osmr_id=None): + user = osmutils.get_user(request) + try: + update_osmr_dict = request.POST.dict() + client = Client() + res = client.osmr_update(user.get_token(), osmr_id, update_osmr_dict) + except Exception as e: + log.exception(e) + return __response_handler(request, res, 'osmr:list', to_redirect=True) + + +@login_required +def show(request, osmr_id=None): + user = osmutils.get_user(request) + project_id = user.project_id + client = Client() + result_client = client.osmr_get(user.get_token(), osmr_id) + + return __response_handler(request, result_client) + + +@login_required +def delete(request, osmr_id=None): + user = osmutils.get_user(request) + try: + client = Client() + del_res = client.osmr_delete(user.get_token(), osmr_id) + except Exception as e: + log.exception(e) + return __response_handler(request, del_res, 'osmr:list', to_redirect=True) + + +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 or url is None: + return HttpResponse(json.dumps(data_res), content_type="application/json", *args, **kwargs) + elif to_redirect: + return redirect(url, *args, **kwargs) + else: + return render(request, url, data_res) diff --git a/projecthandler/template/project/osm/osm_project_left_sidebar.html b/projecthandler/template/project/osm/osm_project_left_sidebar.html index 5fdaf57..8955c13 100644 --- a/projecthandler/template/project/osm/osm_project_left_sidebar.html +++ b/projecthandler/template/project/osm/osm_project_left_sidebar.html @@ -137,7 +137,12 @@ limitations under the License. - + {% url "osm:list" as osmrepo_list_url %} +
  • + + OSM Repositories + +
  • {% url "wims:list" as wim_list_url %}
  • @@ -164,9 +169,8 @@ limitations under the License. Roles
  • - {% endif %} - \ No newline at end of file + diff --git a/sf_t3d/settings.py b/sf_t3d/settings.py index 528929d..560d05f 100644 --- a/sf_t3d/settings.py +++ b/sf_t3d/settings.py @@ -66,7 +66,8 @@ INSTALLED_APPS = [ 'rolehandler', 'netslicehandler', 'k8sclusterhandler', - 'k8srepohandler' + 'k8srepohandler', + 'osmrepohandler' ] @@ -109,6 +110,7 @@ TEMPLATES = [ os.path.join(BASE_DIR, 'netslicehandler', 'template'), os.path.join(BASE_DIR, 'k8sclusterhandler', 'template'), os.path.join(BASE_DIR, 'k8srepohandler', 'template'), + os.path.join(BASE_DIR, 'osmrepohandler', 'template'), ], 'APP_DIRS': True, 'OPTIONS': { diff --git a/sf_t3d/urls.py b/sf_t3d/urls.py index a908c13..96d6060 100644 --- a/sf_t3d/urls.py +++ b/sf_t3d/urls.py @@ -28,6 +28,7 @@ urlpatterns = [ url(r'^vims/', include('vimhandler.urls', namespace='vims'), name='vims_base'), url(r'^k8scluster/', include('k8sclusterhandler.urls', namespace='k8sc'), name='k8sc_base'), url(r'^k8srepo/', include('k8srepohandler.urls', namespace='k8sr'), name='k8sr_base'), + url(r'^osmrepo/', include('osmrepohandler.urls', namespace='osmr'), name='osmr_base'), url(r'^wims/', include('wimhandler.urls', namespace='wims'), name='wims_base'), url(r'^packages/', include('packagehandler.urls', namespace='packages'), name='packages_base'), url(r'^instances/', include('instancehandler.urls', namespace='instances'), name='instances_base'), diff --git a/static/src/osmrepohandler/osmrepos_list.js b/static/src/osmrepohandler/osmrepos_list.js new file mode 100644 index 0000000..ba32654 --- /dev/null +++ b/static/src/osmrepohandler/osmrepos_list.js @@ -0,0 +1,146 @@ +/* + Copyright 2019 EveryUP srl + + 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. +*/ + +function openModalRegisterOSMr(args) { + $('#modal_new_osmr').modal('show'); +} + +function showOSMr(osmr_id, osmr_name) { + var url_info = '/osmrepo/' + osmr_id; + var dialog = bootbox.dialog({ + message: '
    Loading...
    ', + closeButton: true + }); + $.ajax({ + url: url_info, + type: 'GET', + dataType: "json", + contentType: "application/json;charset=utf-8", + success: function (result) { + + if (result['data'] !== undefined) { + editorJSON.setValue(JSON.stringify(result['data'], null, "\t")); + editorJSON.setOption("autoRefresh", true); + dialog.modal('hide'); + $('#modal_show_osmr').modal('show'); + } + else { + dialog.modal('hide'); + bootbox.alert("An error occurred while retrieving the information."); + } + }, + error: function (result) { + dialog.modal('hide'); + bootbox.alert("An error occurred while retrieving the information."); + } + }); +} + +function deleteOSMr(osmr_id, osmr_name) { + var url = "/osmrepo/"+osmr_id+"/delete"; + bootbox.confirm("Are you sure want to delete " + osmr_name + "?", function (result) { + if (result) { + var dialog = bootbox.dialog({ + message: '
    Loading...
    ', + closeButton: true + }); + $.ajax({ + url: url, + type: 'GET', + dataType: "json", + contentType: "application/json;charset=utf-8", + success: function (result) { + if (result['error'] == true) { + dialog.modal('hide'); + bootbox.alert("An error occurred."); + } + else { + table.ajax.reload(); + dialog.modal('hide'); + } + }, + error: function (error) { + dialog.modal('hide'); + bootbox.alert("An error occurred."); + } + }); + } + }) +} + + +var editorJSON; + +$(document).ready(function () { + + var json_editor_settings = { + mode: "javascript", + showCursorWhenSelecting: true, + autofocus: true, + lineNumbers: true, + lineWrapping: true, + foldGutter: true, + gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], + autoCloseBrackets: true, + matchBrackets: true, + extraKeys: { + "F11": function (cm) { + cm.setOption("fullScreen", !cm.getOption("fullScreen")); + }, + "Esc": function (cm) { + if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false); + }, + "Ctrl-Q": function (cm) { + cm.foldCode(cm.getCursor()); + } + }, + theme: "neat", + keyMap: "sublime" + }; + var myJsonTextArea = document.getElementById("osmr_view_json"); + editorJSON = CodeMirror(function (elt) { + myJsonTextArea.parentNode.replaceChild(elt, myJsonTextArea); + }, json_editor_settings); + + $("#formCreateosmr").submit(function (event) { + event.preventDefault(); //prevent default action + var post_url = $(this).attr("action"); //get form action url + var request_method = $(this).attr("method"); //get form GET/POST method + var form_data = new FormData(this); //Encode form elements for submission + $.ajax({ + url: post_url, + type: request_method, + data: form_data, + headers: { + "Accept": 'application/json' + }, + contentType: false, + processData: false + }).done(function (response, textStatus, jqXHR) { + table.ajax.reload(); + $('#modal_new_osmr').modal('hide'); + }).fail(function (result) { + var data = result.responseJSON; + var title = "Error " + (data.code ? data.code : 'unknown'); + var message = data.detail ? data.detail : 'No detail available.'; + bootbox.alert({ + title: title, + message: message + }); + }); + }); + +});