From 98609ecffcaef619e31044ac40b71b4fa8858357 Mon Sep 17 00:00:00 2001 From: SudhakarReddy Date: Wed, 22 Aug 2018 12:05:24 +0300 Subject: Improve coverage of multicloud-azure plugin Change-Id: I6cfbced1e6a2c0dc434fcdcb80f1b0e7cc4783f3 Issue-ID: MULTICLOUD-308 Signed-off-by: SudhakarReddy --- .gitignore | 3 +- .../azure/api_v2/api_router/controller_builder.py | 224 --------------------- azure/azure/api_v2/api_router/v0_controller.py | 3 +- azure/azure/swagger/nova_utils.py | 119 ----------- azure/azure/tests/test_syscomm.py | 37 ++++ 5 files changed, 40 insertions(+), 346 deletions(-) delete mode 100644 azure/azure/api_v2/api_router/controller_builder.py delete mode 100644 azure/azure/swagger/nova_utils.py create mode 100644 azure/azure/tests/test_syscomm.py diff --git a/.gitignore b/.gitignore index 64c410c..fd6e092 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ azure/build azure/dist azure/1.25.0 azure/*.egg-info -azure/logs/*.log \ No newline at end of file +azure/logs/*.log +azure/coverage.xml diff --git a/azure/azure/api_v2/api_router/controller_builder.py b/azure/azure/api_v2/api_router/controller_builder.py deleted file mode 100644 index ec66268..0000000 --- a/azure/azure/api_v2/api_router/controller_builder.py +++ /dev/null @@ -1,224 +0,0 @@ -# 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 -from keystoneauth1.identity import v2 as keystone_v2 -from keystoneauth1.identity import v3 as keystone_v3 -from keystoneauth1 import session -import pecan -from pecan import rest -import re - -from azure.api_v2.api_definition import utils -from azure.pub import exceptions -from azure.pub.msapi import extsys - - -OBJ_IN_ARRAY = "(\w+)\[(\d+)\]\.(\w+)" - - -def _get_vim_auth_session(vim_id, tenant_id): - """ Get the auth session to the given backend VIM """ - - try: - vim = extsys.get_vim_by_id(vim_id) - except exceptions.VimDriverAzureException as e: - return pecan.abort(500, str(e)) - - params = { - "auth_url": vim["url"], - "username": vim["userName"], - "password": vim["password"], - } - params["tenant_id"] = tenant_id - - if '/v2' in params["auth_url"]: - auth = keystone_v2.Password(**params) - else: - params["user_domain_name"] = vim["domain"] - params["project_domain_name"] = vim["domain"] - - if 'tenant_id' in params: - params["project_id"] = params.pop("tenant_id") - if 'tenant_name' in params: - params["project_name"] = params.pop("tenant_name") - if '/v3' not in params["auth_url"]: - params["auth_url"] = params["auth_url"] + "/v3", - auth = keystone_v3.Password(**params) - - return session.Session(auth=auth) - - -def _convert_default_value(default): - return {"None": None, "true": True, "false": False}[default] - - -def _property_exists(resource, attr, required=False): - if attr not in resource: - if required: - raise Exception("Required field %s is missed in VIM " - "resource %s", (attr, resource)) - else: - return False - - return True - - -def _convert_vim_res_to_mc_res(vim_resource, res_properties): - mc_resource = {} - for key in res_properties: - vim_res, attr = res_properties[key]["source"].split('.', 1) - # action = res_properties[key].get("action", "copy") - if re.match(OBJ_IN_ARRAY, attr): - attr, index, sub_attr = re.match(OBJ_IN_ARRAY, attr).groups() - if _property_exists(vim_resource[vim_res], attr): - mc_resource[key] = ( - vim_resource[vim_res][attr][int(index)][sub_attr]) - else: - if _property_exists(vim_resource[vim_res], attr, - res_properties[key].get("required")): - mc_resource[key] = vim_resource[vim_res][attr] - else: - if "default" in res_properties[key]: - mc_resource[key] = _convert_default_value( - res_properties[key]["default"]) - - return mc_resource - - -def _convert_mc_res_to_vim_res(mc_resource, res_properties): - vim_resource = {} - for key in res_properties: - vim_res, attr = res_properties[key]["source"].split('.', 1) - # action = res_properties[key].get("action", "copy") - if re.match(OBJ_IN_ARRAY, attr): - attr, index, sub_attr = re.match(OBJ_IN_ARRAY, attr).groups() - if _property_exists(mc_resource, key): - vim_resource[attr] = vim_resource.get(attr, []) - if vim_resource[attr]: - vim_resource[attr][0].update({sub_attr: mc_resource[key]}) - else: - vim_resource[attr].append({sub_attr: mc_resource[key]}) - else: - if _property_exists(mc_resource, key, - res_properties[key].get("required")): - vim_resource[attr] = mc_resource[key] - - return vim_resource - - -def _build_api_controller(api_meta): - # Assume that only one path - path, path_meta = api_meta['paths'].items()[0] - # url path is behind third slash. The first is vimid, the second is - # tenantid. - path = path.split("/")[3] - controller_name = path.upper() + "Controller" - delimiter = path_meta["vim_path"].find("/", 1) - service_type = path_meta["vim_path"][1:delimiter] - resource_url = path_meta["vim_path"][delimiter:] - - # Assume there is only one resource. - name, resource_meta = api_meta['definitions'].items()[0] - resource_properties = resource_meta['properties'] - - controller_meta = {} - if "get" in path_meta: - # Add the get method to controller. - @pecan.expose("json") - def _get(self, vim_id, tenant_id, resource_id): - """ General GET """ - session = _get_vim_auth_session(vim_id, tenant_id) - service = {'service_type': service_type, - 'interface': 'public'} - full_url = resource_url + "/%s" % resource_id - resp = session.get(full_url, endpoint_filter=service) - mc_res = _convert_vim_res_to_mc_res(resp.json(), - resource_properties) - mc_res.update({"vimName": vim_id, - "vimId": vim_id, - "tenantId": tenant_id, - "returnCode": 0}) - return mc_res - - controller_meta["get"] = _get - - if "get_all" in path_meta: - # Add the get_all method to controller. - @pecan.expose("json") - def _get_all(self, vim_id, tenant_id): - """ General GET all """ - session = _get_vim_auth_session(vim_id, tenant_id) - service = {'service_type': service_type, - 'interface': 'public'} - resp = session.get(resource_url, endpoint_filter=service) - vim_res = resp.json()[resource_meta['plural_vim_resource']] - mc_res = [_convert_vim_res_to_mc_res( - {resource_meta['vim_resource']: v}, - resource_properties) - for v in vim_res] - return {"vimName": vim_id, - resource_meta['plural']: mc_res, - "tenantId": tenant_id, - "vimid": vim_id} - - controller_meta["get_all"] = _get_all - - if "post" in path_meta: - # Add the post method to controller. - @pecan.expose("json") - def _post(self, vim_id, tenant_id): - """ General POST """ - session = _get_vim_auth_session(vim_id, tenant_id) - service = {'service_type': service_type, - 'interface': 'public'} - vim_res = _convert_mc_res_to_vim_res(pecan.request.json_body, - resource_properties) - - req_body = json.JSONEncoder().encode( - {resource_meta['vim_resource']: vim_res}) - resp = session.post(resource_url, - data=req_body, - endpoint_filter=service) - mc_res = _convert_vim_res_to_mc_res(resp.json(), - resource_properties) - mc_res.update({"vimName": vim_id, - "vimId": vim_id, - "tenantId": tenant_id, - "returnCode": 0}) - return mc_res - - controller_meta["post"] = _post - - if "delete" in path_meta: - # Add the delete method to controller. - @pecan.expose("json") - def _delete(self, vim_id, tenant_id, resource_id): - """ General DELETE """ - session = _get_vim_auth_session(vim_id, tenant_id) - service = {'service_type': service_type, - 'interface': 'public'} - full_url = resource_url + "/%s" % resource_id - session.delete(full_url, endpoint_filter=service) - - controller_meta["delete"] = _delete - - return path, type(controller_name, (rest.RestController,), controller_meta) - - -def insert_dynamic_controller(root_controller): - api_defs = utils.get_definition_list() - for d in api_defs: - path, con_class = _build_api_controller(d) - setattr(root_controller, path, con_class()) diff --git a/azure/azure/api_v2/api_router/v0_controller.py b/azure/azure/api_v2/api_router/v0_controller.py index 104597a..68aac1b 100644 --- a/azure/azure/api_v2/api_router/v0_controller.py +++ b/azure/azure/api_v2/api_router/v0_controller.py @@ -15,7 +15,6 @@ import pecan from pecan import rest -from azure.api_v2.api_router import controller_builder from azure.api_v2.api_router import swagger_json @@ -46,4 +45,4 @@ pecan.route(V0_Controller, "swagger.json", swagger_json.SwaggerJson()) # Insert API stem from yaml files. -controller_builder.insert_dynamic_controller(V0_Controller) +# controller_builder.insert_dynamic_controller(V0_Controller) diff --git a/azure/azure/swagger/nova_utils.py b/azure/azure/swagger/nova_utils.py deleted file mode 100644 index 86f10a2..0000000 --- a/azure/azure/swagger/nova_utils.py +++ /dev/null @@ -1,119 +0,0 @@ -# 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 server_formatter(server, interfaces=[]): - r = { - "id": server.id, - "name": server.name, - "tenantId": server.project_id, - "availabilityZone": server.availability_zone, - "flavorId": server.flavor_id or server.flavor['id'], - "volumeArray": [], - "metadata": [], - "securityGroups": [], - # TODO finish following attributes - "serverGroup": "", - "contextArray": [], - "userdata": server.user_data, - "nicArray": [], - "status": server.status - } - if interfaces: - r['nicArray'] = [{'portId': i.port_id} for i in interfaces] - elif server.networks: - r['nicArray'] = [{'portId': n['port']} for n in server.networks] - # TODO: wait sdk fix block_device_mapping - try: - if server.attached_volumes: - r["volumeArray"] = [{'volumeId': v['id']} - for v in server.attached_volumes] - elif server.block_device_mapping: - r["volumeArray"] = [{'volumeId': v['uuid']} - for v in server.block_device_mapping] - except ValueError: - r['volumeArray'] = [{'volumeId': ""}] - if server.image_id or server.image: - r['boot'] = { - 'type': 2, - 'imageId': server.image_id or server.image['id'] - } - else: - r['boot'] = { - 'type': 1, - 'volumeId': r['volumeArray'][0]['volumeId'] - } - if server.metadata: - r["metadata"] = [{'keyName': k, 'value': v} - for k, v in six.iteritems(server.metadata)] - if server.security_groups: - r["securityGroups"] = [i['name'] for i in server.security_groups] - return r - - -def flavor_formatter(flavor, extra_specs): - r = { - "id": flavor.id, - "name": flavor.name, - "vcpu": flavor.vcpus, - "memory": flavor.ram, - "disk": flavor.disk, - "ephemeral": flavor.ephemeral, - "swap": flavor.swap, - "isPublic": flavor.is_public} - if extra_specs: - r["extraSpecs"] = extra_specs_formatter(extra_specs) - return r - - -def extra_specs_formatter(extra_specs): - return [{"keyName": k, "value": v} - for k, v in six.iteritems(extra_specs.extra_specs)] - - -def server_limits_formatter(limits): - return { - # nova - 'maxPersonality': limits.absolute.personality, - 'maxPersonalitySize': limits.absolute.personality_size, - 'maxServerGroupMembers': limits.absolute.server_group_members, - 'maxServerGroups': limits.absolute.server_groups, - 'maxImageMeta': limits.absolute.image_meta, - 'maxTotalCores': limits.absolute.total_cores, - 'maxTotalInstances': limits.absolute.instances, - 'maxTotalKeypairs': limits.absolute.keypairs, - 'maxTotalRAMSize': limits.absolute.total_ram, - 'security_group_rules': limits.absolute.security_group_rules, - 'security_group': limits.absolute.security_groups, - - # cinder - # neutron - } - - -def service_formatter(service): - return { - 'service': service.binary, - 'name': service.host, - 'zone': service.zone, - } - - -def hypervisor_formatter(hypervisor): - return { - 'name': hypervisor.name, - 'cpu': hypervisor.vcpus, - 'disk_gb': hypervisor.local_disk_size, - 'memory_mb': hypervisor.memory_size, - } diff --git a/azure/azure/tests/test_syscomm.py b/azure/azure/tests/test_syscomm.py new file mode 100644 index 0000000..d700ed7 --- /dev/null +++ b/azure/azure/tests/test_syscomm.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. + +import unittest + +from azure.pub.utils import syscomm + + +class SyscommTest(unittest.TestCase): + + def test_keystone_version(self): + url = "http://a.com/test" + version = "v3" + expected = "http://a.com/test/v3" + self.assertEquals(expected, syscomm.keystoneVersion(url, version)) + + def test_verify_keystone(self): + param = \ + { + "auth": { + "tenantName": "12345", + "passwordCredentials": { + "username": "admin", + "password": "admin" + } + } + } + self.assertEquals(True, syscomm.verifyKeystoneV2(param)) -- cgit 1.2.3-korg