diff options
Diffstat (limited to 'azure/multicloud_azure/swagger')
17 files changed, 1308 insertions, 0 deletions
diff --git a/azure/multicloud_azure/swagger/__init__.py b/azure/multicloud_azure/swagger/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/azure/multicloud_azure/swagger/__init__.py diff --git a/azure/multicloud_azure/swagger/compute_utils.py b/azure/multicloud_azure/swagger/compute_utils.py new file mode 100644 index 0000000..53bd587 --- /dev/null +++ b/azure/multicloud_azure/swagger/compute_utils.py @@ -0,0 +1,29 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +import six + + +def extra_specs_formatter(extra_specs): + return [{"keyName": k, "value": v} + for k, v in six.iteritems(extra_specs.extra_specs)] + + +def convert_vmsize_aai(vmsize): + + body = { + 'name': vmsize.name, + 'vcpus': vmsize.number_of_cores, + 'disk': vmsize.os_disk_size_in_mb, + 'ram': vmsize.memory_in_mb + } + return body diff --git a/azure/multicloud_azure/swagger/image_utils.py b/azure/multicloud_azure/swagger/image_utils.py new file mode 100644 index 0000000..a17565e --- /dev/null +++ b/azure/multicloud_azure/swagger/image_utils.py @@ -0,0 +1,65 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + +def image_formatter(image): + + image = image.to_dict() + properties = {} + if image.get("vmware_adaptertype"): + properties['vmware_adaptertype'] = image.get("vmware_adaptertype") + if image.get("vmware_ostype"): + properties['vmware_ostype'] = image.get("vmware_ostype") + + return { + 'id': image.get("id"), + 'name': image.get("name"), + 'imageType': image.get("disk_format"), + 'status': image.get("status"), + 'size': image.get("size"), + 'containerFormat': image.get("container_format"), + 'visibility': image.get("visibility"), + 'properties': properties + } + + +def vim_formatter(vim_info, tenantid): + + rsp = {} + rsp['vimId'] = vim_info.get('vimId') + rsp['vimName'] = vim_info.get('name') + rsp['tenantId'] = tenantid + return rsp + + +def sdk_param_formatter(data): + + param = {} + param['username'] = data.get('userName') + param['password'] = data.get('password') + param['auth_url'] = data.get('url') + param['project_id'] = data.get('tenant') + param['user_domain_name'] = 'default' + param['project_domain_name'] = 'default' + return param + + +def req_body_formatter(body): + + param = {} + param['name'] = body.get('name') + param['disk_format'] = body.get('imageType') + param['container_format'] = body.get('containerFormat') + param['visibility'] = body.get('visibility') + properties = body.get('properties', {}) + param.update(properties) + return param diff --git a/azure/multicloud_azure/swagger/multivim.flavor.swagger.json b/azure/multicloud_azure/swagger/multivim.flavor.swagger.json new file mode 100644 index 0000000..76e53f4 --- /dev/null +++ b/azure/multicloud_azure/swagger/multivim.flavor.swagger.json @@ -0,0 +1,365 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/api/multicloud_azure/v0/", + "tags": [ + { + "name": "MultiVIM Azure services" + } + ], + "paths": { + "/{vimid}/flavors": { + "post": { + "tags": [ + "vim flavors" + ], + "summary": "create a flavor", + "description": "create a flavor", + "operationId": "create_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim flavor request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimFlavor" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + }, + "get": { + "tags": [ + "vim flavors" + ], + "summary": "query vim flavors list", + "description": "query vim flavors list", + "operationId": "query_vim_flavors", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim flavors request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimFlavors" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorsInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + } + }, + "/{vimid}/flavors/{flavorid}": { + "delete": { + "tags": [ + "vim flavors" + ], + "summary": "delete specific vim flavor", + "description": "delete specific vim flavor", + "operationId": "delete_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "flavorid", + "in": "path", + "description": "vim flavor id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + }, + "get": { + "tags": [ + "vim flavors" + ], + "summary": "query specific vim flavor", + "description": "query specific vim flavor", + "operationId": "query_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "flavorid", + "in": "path", + "description": "vim flavor id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimFlavor": { + "type": "object", + "required": [ + "vcpu", + "name", + "memory", + "disk" + ], + "properties": { + "name": { + "type": "string", + "description": "flavor name" + }, + "vcpu": { + "type": "integer", + "description": "virtual cpu number" + }, + "memory": { + "type": "integer", + "description": "memory size" + }, + "disk": { + "type": "integer", + "description": "The size of the root disk" + }, + "ephemeral": { + "type": "integer", + "description": "The size of the ephemeral disk" + }, + "swap": { + "type": "integer", + "description": "The size of the swap disk" + }, + "isPublic": { + "type": "boolean", + "description": "whether the flavor is public" + }, + "extraSpecs": { + "type": "array", + "description": "list of extra specs", + "items": { + "$ref": "#/definitions/VimFlavorExtraSpecInfo" + } + } + } + }, + "VimFlavorExtraSpecInfo": { + "type": "object", + "properties": { + "keyName": { + "type": "string", + "description": "extra spec key" + }, + "value": { + "type": "string", + "description": "extra spec value" + } + } + }, + "ListVimFlavors": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "flavor name to filter flavor list" + }, + "limit": { + "type": "integer", + "description": "Requests a page size of items" + }, + "marker": { + "type": "string", + "description": "flavor ID of the last-seen item" + } + } + }, + "VimFlavorsInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "flavors" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "flavors": { + "type": "array", + "description": "flavor list information", + "items": { + "$ref": "#/definitions/VimFlavorInfo" + } + } + } + }, + "VimFlavorInfo": { + "type": "object", + "required": [ + "name", + "id", + "vcpu", + "memory", + "disk", + "ephemeral", + "swap", + "isPublic" + ], + "properties": { + "name": { + "type": "string", + "description": "flavor name" + }, + "id": { + "type": "string", + "description": "flavor UUID" + }, + "vcpu": { + "type": "integer", + "description": "virtual cpu number" + }, + "memory": { + "type": "integer", + "description": "memory size" + }, + "disk": { + "type": "integer", + "description": "The size of the root disk" + }, + "ephemeral": { + "type": "integer", + "description": "The size of the ephemeral disk" + }, + "swap": { + "type": "integer", + "description": "The size of the swap disk" + }, + "isPublic": { + "type": "boolean", + "description": "whether the flavor is public" + }, + "extraSpecs": { + "type": "array", + "description": "list of extra specs", + "items": { + "$ref": "#/definitions/VimFlavorExtraSpecInfo" + } + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/azure/multicloud_azure/swagger/tests.py b/azure/multicloud_azure/swagger/tests.py new file mode 100644 index 0000000..4631455 --- /dev/null +++ b/azure/multicloud_azure/swagger/tests.py @@ -0,0 +1,31 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +import unittest +# import json +from django.test import Client +from rest_framework import status + + +class SampleViewTest(unittest.TestCase): + def setUp(self): + self.client = Client() + + def tearDown(self): + pass + + def test_sample(self): + response = self.client.get("/api/multicloud-azure/v0/swagger.json") + self.assertEqual(status.HTTP_200_OK, + response.status_code, response.content) +# resp_data = json.loads(response.content) +# self.assertEqual({"status": "active"}, resp_data) diff --git a/azure/multicloud_azure/swagger/urls.py b/azure/multicloud_azure/swagger/urls.py new file mode 100644 index 0000000..6acd327 --- /dev/null +++ b/azure/multicloud_azure/swagger/urls.py @@ -0,0 +1,37 @@ +# Copyright (c) 2018 Amdocs +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +from django.conf.urls import url +from rest_framework.urlpatterns import format_suffix_patterns + +from multicloud_azure.swagger.views.swagger_json import SwaggerJsonView + + +# Registry +from multicloud_azure.swagger.views.registry.views import Registry +from multicloud_azure.swagger.views.registry.views import UnRegistry + + +urlpatterns = [ + # swagger + url(r'^api/multicloud-azure/v0/swagger.json$', SwaggerJsonView.as_view()), + + # Registry + url(r'^api/multicloud-azure/v0/(?P<vimid>[0-9a-z-A-Z\-\_]+)/registry$', + Registry.as_view()), + url(r'^api/multicloud-azure/v0/(?P<vimid>[0-9a-z-A-Z\-\_]+)$', + UnRegistry.as_view()), + +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/azure/multicloud_azure/swagger/utils.py b/azure/multicloud_azure/swagger/utils.py new file mode 100644 index 0000000..cb7e4f0 --- /dev/null +++ b/azure/multicloud_azure/swagger/utils.py @@ -0,0 +1,37 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" 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. + +import json +import os + + +def get_swagger_json_data(): + json_file = os.path.join(os.path.dirname( + __file__), 'multivim.flavor.swagger.json') + f = open(json_file) + json_data = json.JSONDecoder().decode(f.read()) + f.close() + # json_file = os.path.join(os.path.dirname( + # __file__), 'multivim.image.swagger.json') + # f = open(json_file) + # json_data_temp = json.JSONDecoder().decode(f.read()) + # f.close() + # json_data["paths"].update(json_data_temp["paths"]) + # json_data["definitions"].update(json_data_temp["definitions"]) + + json_data["basePath"] = "/api/multicloud-azure/v0/" + json_data["info"]["title"] = "MultiVIM driver \ + of Microsoft Azure Service NBI" + + return json_data diff --git a/azure/multicloud_azure/swagger/views.py b/azure/multicloud_azure/swagger/views.py new file mode 100644 index 0000000..d6ea65c --- /dev/null +++ b/azure/multicloud_azure/swagger/views.py @@ -0,0 +1,29 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +import logging +# import traceback + +# from rest_framework import status +from rest_framework.response import Response +from rest_framework.views import APIView + +# from multicloud_azure.pub.exceptions import VimDriverAzureException +from multicloud_azure.swagger import utils + +logger = logging.getLogger(__name__) + + +class SwaggerJsonView(APIView): + def get(self, request): + + return Response(utils.get_swagger_json_data()) diff --git a/azure/multicloud_azure/swagger/views/__init__.py b/azure/multicloud_azure/swagger/views/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/azure/multicloud_azure/swagger/views/__init__.py diff --git a/azure/multicloud_azure/swagger/views/flavor/__init__.py b/azure/multicloud_azure/swagger/views/flavor/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/azure/multicloud_azure/swagger/views/flavor/__init__.py diff --git a/azure/multicloud_azure/swagger/views/flavor/views.py b/azure/multicloud_azure/swagger/views/flavor/views.py new file mode 100644 index 0000000..c4eb060 --- /dev/null +++ b/azure/multicloud_azure/swagger/views/flavor/views.py @@ -0,0 +1,98 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +import json + +from rest_framework import status +from rest_framework.response import Response +from rest_framework.views import APIView + +from multicloud_azure.pub.msapi import extsys +from multicloud_azure.pub.vim.vimapi.compute import OperateFlavors +from multicloud_azure.swagger import compute_utils +from multicloud_azure.pub.exceptions import VimDriverAzureException + + +class FlavorsView(APIView): + + def post(self, request, vimid): + try: + create_req = json.loads(request.body) + except Exception as e: + return Response(data={'error': 'Fail to decode request body.'}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + try: + vim_info = extsys.get_vim_by_id(vimid) + except VimDriverAzureException as e: + return Response(data={'error': str(e)}, status=e.status_code) + + data = {'subscription_id': vim_info['cloud_extra_info'], + 'username': vim_info['username'], + 'password': vim_info['password'], + 'tenant_id': vim_info['default_tenant'], + 'region_id': vim_info['cloud_region']} + rsp = {'vimId': vim_info['cloud_extra_info'], + 'vimName': vim_info['name']} + flavor_name = create_req.get('name', None) + flavor_id = create_req.get('id', None) + flavors_op = OperateFlavors.OperateFlavors() + try: + target = flavor_id or flavor_name + flavor = flavors_op.find_flavor(data, target) + if flavor: + flavor, extra_specs = flavors_op.get_flavor( + data, flavor.id) + rsp['returnCode'] = 0 + else: + rsp['returnCode'] = 1 + flavor, extra_specs = flavors_op.create_flavor( + data, create_req) + flavor_dict = compute_utils.flavor_formatter(flavor, extra_specs) + except Exception as e: + if hasattr(e, "http_status"): + return Response(data={'error': str(e)}, status=e.http_status) + else: + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + rsp.update(flavor_dict) + return Response(data=rsp, status=status.HTTP_200_OK) + + def get(self, request, vimid): + try: + vim_info = extsys.get_vim_by_id(vimid) + except VimDriverAzureException as e: + return Response(data={'error': str(e)}, status=e.status_code) + + data = {'subscription_id': vim_info['cloud_extra_info'], + 'username': vim_info['username'], + 'password': vim_info['password'], + 'tenant_id': vim_info['default_tenant'], + 'region_id': vim_info['cloud_region_id']} + query = dict(request.query_params) + flavors_op = OperateFlavors.OperateFlavors() + try: + flavors_result = flavors_op.list_flavors(data, **query) + flavors_dict = [compute_utils.flavor_formatter(flavor, extra) + for flavor, extra in flavors_result] + except Exception as e: + if hasattr(e, "http_status"): + return Response(data={'error': str(e)}, status=e.http_status) + else: + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + rsp = {'vimId': vim_info['cloud_extra_info'], + 'vimName': vim_info['name'], + 'flavors': flavors_dict} + + return Response(data=rsp, status=status.HTTP_200_OK) diff --git a/azure/multicloud_azure/swagger/views/multivim.flavor.swagger.json b/azure/multicloud_azure/swagger/views/multivim.flavor.swagger.json new file mode 100644 index 0000000..76e53f4 --- /dev/null +++ b/azure/multicloud_azure/swagger/views/multivim.flavor.swagger.json @@ -0,0 +1,365 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/api/multicloud_azure/v0/", + "tags": [ + { + "name": "MultiVIM Azure services" + } + ], + "paths": { + "/{vimid}/flavors": { + "post": { + "tags": [ + "vim flavors" + ], + "summary": "create a flavor", + "description": "create a flavor", + "operationId": "create_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim flavor request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimFlavor" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + }, + "get": { + "tags": [ + "vim flavors" + ], + "summary": "query vim flavors list", + "description": "query vim flavors list", + "operationId": "query_vim_flavors", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim flavors request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimFlavors" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorsInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + } + }, + "/{vimid}/flavors/{flavorid}": { + "delete": { + "tags": [ + "vim flavors" + ], + "summary": "delete specific vim flavor", + "description": "delete specific vim flavor", + "operationId": "delete_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "flavorid", + "in": "path", + "description": "vim flavor id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + }, + "get": { + "tags": [ + "vim flavors" + ], + "summary": "query specific vim flavor", + "description": "query specific vim flavor", + "operationId": "query_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "flavorid", + "in": "path", + "description": "vim flavor id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimFlavor": { + "type": "object", + "required": [ + "vcpu", + "name", + "memory", + "disk" + ], + "properties": { + "name": { + "type": "string", + "description": "flavor name" + }, + "vcpu": { + "type": "integer", + "description": "virtual cpu number" + }, + "memory": { + "type": "integer", + "description": "memory size" + }, + "disk": { + "type": "integer", + "description": "The size of the root disk" + }, + "ephemeral": { + "type": "integer", + "description": "The size of the ephemeral disk" + }, + "swap": { + "type": "integer", + "description": "The size of the swap disk" + }, + "isPublic": { + "type": "boolean", + "description": "whether the flavor is public" + }, + "extraSpecs": { + "type": "array", + "description": "list of extra specs", + "items": { + "$ref": "#/definitions/VimFlavorExtraSpecInfo" + } + } + } + }, + "VimFlavorExtraSpecInfo": { + "type": "object", + "properties": { + "keyName": { + "type": "string", + "description": "extra spec key" + }, + "value": { + "type": "string", + "description": "extra spec value" + } + } + }, + "ListVimFlavors": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "flavor name to filter flavor list" + }, + "limit": { + "type": "integer", + "description": "Requests a page size of items" + }, + "marker": { + "type": "string", + "description": "flavor ID of the last-seen item" + } + } + }, + "VimFlavorsInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "flavors" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "flavors": { + "type": "array", + "description": "flavor list information", + "items": { + "$ref": "#/definitions/VimFlavorInfo" + } + } + } + }, + "VimFlavorInfo": { + "type": "object", + "required": [ + "name", + "id", + "vcpu", + "memory", + "disk", + "ephemeral", + "swap", + "isPublic" + ], + "properties": { + "name": { + "type": "string", + "description": "flavor name" + }, + "id": { + "type": "string", + "description": "flavor UUID" + }, + "vcpu": { + "type": "integer", + "description": "virtual cpu number" + }, + "memory": { + "type": "integer", + "description": "memory size" + }, + "disk": { + "type": "integer", + "description": "The size of the root disk" + }, + "ephemeral": { + "type": "integer", + "description": "The size of the ephemeral disk" + }, + "swap": { + "type": "integer", + "description": "The size of the swap disk" + }, + "isPublic": { + "type": "boolean", + "description": "whether the flavor is public" + }, + "extraSpecs": { + "type": "array", + "description": "list of extra specs", + "items": { + "$ref": "#/definitions/VimFlavorExtraSpecInfo" + } + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/azure/multicloud_azure/swagger/views/multivim.swagger.json b/azure/multicloud_azure/swagger/views/multivim.swagger.json new file mode 100644 index 0000000..de3419f --- /dev/null +++ b/azure/multicloud_azure/swagger/views/multivim.swagger.json @@ -0,0 +1,51 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/api/multicloud-azure/v0/", + "tags": [ + { + "name": "MultiVIM Azure services" + } + ], + "paths": { + "/{vimid}/registry": { + "post": { + "tags": [ + "vim registration" + ], + "summary": "vim registration API", + "description": "vim registration API", + "operationId": "vim_registration", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation" + }, + "404": { + "description": "the vim id is wrong" + }, + "500": { + "description": "error occured during the process" + } + } + } + } + } +} diff --git a/azure/multicloud_azure/swagger/views/registry/__init__.py b/azure/multicloud_azure/swagger/views/registry/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/azure/multicloud_azure/swagger/views/registry/__init__.py diff --git a/azure/multicloud_azure/swagger/views/registry/views.py b/azure/multicloud_azure/swagger/views/registry/views.py new file mode 100644 index 0000000..8464ce4 --- /dev/null +++ b/azure/multicloud_azure/swagger/views/registry/views.py @@ -0,0 +1,87 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + +import logging +import json + +from rest_framework import status +from rest_framework.response import Response +from rest_framework.views import APIView + +from multicloud_azure.pub.exceptions import VimDriverAzureException +from multicloud_azure.pub.msapi import extsys +from multicloud_azure.pub.utils.restcall import AAIClient +from multicloud_azure.pub.vim.vimapi.compute import OperateFlavors + + +logger = logging.getLogger(__name__) + + +class Registry(APIView): + def _get_flavors(self, auth_info): + flavors_op = OperateFlavors.OperateFlavors() + try: + flavors = flavors_op.list_flavors(auth_info) + except Exception as e: + logger.exception("get flavors error %(e)s", {"e": e}) + raise e + + rsp = {"flavors": flavors} + return rsp + + def post(self, request, vimid): + try: + vim_info = extsys.get_vim_by_id(vimid) + except VimDriverAzureException as e: + return Response(data={'error': str(e)}, status=e.status_code) + cloud_extra_info = json.loads(vim_info['cloud_extra_info']) + data = { + 'subscription_id': cloud_extra_info['subscription_id'], + 'username': vim_info['username'], + 'password': vim_info['password'], + 'tenant_id': vim_info['default_tenant'], + 'region_id': vim_info['cloud-region-id'] + } + rsp = {} + try: + logger.debug('Getting flavors') + flavors = self._get_flavors(data) + rsp.update(flavors) + # update A&AI + logger.debug('Put data into A&AI') + cloud_owner, cloud_region = extsys.split_vim_to_owner_region( + vimid) + aai_adapter = AAIClient(cloud_owner, cloud_region) + aai_adapter.update_vim(rsp) + except Exception as e: + if hasattr(e, "http_status"): + return Response(data={'error': str(e)}, status=e.http_status) + else: + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + return Response(data="", status=status.HTTP_200_OK) + + +class UnRegistry(APIView): + + def delete(self, request, vimid): + try: + cloud_owner, cloud_region = extsys.split_vim_to_owner_region( + vimid) + aai_adapter = AAIClient(cloud_owner, cloud_region) + aai_adapter.delete_vim() + except Exception as e: + return Response(data=e.message, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + return Response(data="", status=status.HTTP_204_NO_CONTENT) diff --git a/azure/multicloud_azure/swagger/views/swagger_json.py b/azure/multicloud_azure/swagger/views/swagger_json.py new file mode 100644 index 0000000..91c00dd --- /dev/null +++ b/azure/multicloud_azure/swagger/views/swagger_json.py @@ -0,0 +1,42 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + +import json +import logging +import os + +from rest_framework.response import Response +from rest_framework.views import APIView + + +logger = logging.getLogger(__name__) + + +class SwaggerJsonView(APIView): + def get(self, request): + json_file = os.path.join(os.path.dirname( + __file__), 'multivim.swagger.json') + f = open(json_file) + json_data = json.JSONDecoder().decode(f.read()) + f.close() + # json_file = os.path.join(os.path.dirname( + # __file__), 'multivim.image.swagger.json') + # f = open(json_file) + # json_data_temp = json.JSONDecoder().decode(f.read()) + # f.close() + # json_data["paths"].update(json_data_temp["paths"]) + # json_data["definitions"].update(json_data_temp["definitions"]) + json_data["basePath"] = "/api/multicloud-azure/v0/" + json_data["info"]["title"] = "MultiVIM \ + driver of Microsoft Azure Service NBI" + return Response(json_data) diff --git a/azure/multicloud_azure/swagger/volume_utils.py b/azure/multicloud_azure/swagger/volume_utils.py new file mode 100644 index 0000000..ae11285 --- /dev/null +++ b/azure/multicloud_azure/swagger/volume_utils.py @@ -0,0 +1,72 @@ +# Copyright (c) 2018 Amdocs +# +# 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 "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + +def volume_formatter(volume): + + attachments = [] + for attach in volume.attachments: + vim_attach = { + 'device': attach['device'], + 'volumeId': attach['volume_id'], + 'hostName': attach['host_name'], + 'Id': attach['attachment_id'], + 'serverId': attach['server_id'] + } + attachments.append(vim_attach) + + return { + 'id': volume.id, + 'name': volume.name, + 'createTime': volume.created_at, + 'status': volume.status, + 'type': volume.volume_type, + 'size': volume.size, + 'availabilityZone': volume.availability_zone, + 'attachments': attachments + } + + +def vim_formatter(vim_info, tenantid): + + rsp = {} + rsp['vimId'] = vim_info.get('vimId') + rsp['vimName'] = vim_info.get('name') + rsp['tenantId'] = tenantid + return rsp + + +def sdk_param_formatter(data): + + param = {} + param['username'] = data.get('userName') + param['password'] = data.get('password') + param['auth_url'] = data.get('url') + param['project_id'] = data.get('tenant') + param['user_domain_name'] = 'default' + param['project_domain_name'] = 'default' + return param + + +def req_body_formatter(body): + + param = {} + param['name'] = body.get('name') + param['size'] = body.get('volumeSize') + + if body.get('volumeType'): + param['volume_type'] = body.get('volumeType') + if body.get('availabilityZone'): + param['availability_zone'] = body.get('availabilityZone') + if body.get('imageId'): + param['image_id'] = body.get('imageId') + return param |