diff options
author | Yun Huang <yun.huang@windriver.com> | 2018-04-27 10:46:59 +0800 |
---|---|---|
committer | Yun Huang <yun.huang@windriver.com> | 2018-04-27 10:46:59 +0800 |
commit | 2af990cb191109ac34f843a49b8ab55f289c6802 (patch) | |
tree | 1135bca4d719370ecef2d8df7596051f38e41bf6 | |
parent | 003e6b5c17897e79ba98da2de086119b1d87304b (diff) |
Fix HPA features for newton
Change-Id: I1bc5525ae80c420341ea5a8822aef8bbc508de9d
Issue-ID: MULTICLOUD-206
Signed-off-by: Yun Huang <yun.huang@windriver.com>
-rw-r--r-- | newton/newton/registration/views/registration.py | 480 | ||||
-rw-r--r-- | newton/newton/registration/views/registration.py.bak | 286 |
2 files changed, 549 insertions, 217 deletions
diff --git a/newton/newton/registration/views/registration.py b/newton/newton/registration/views/registration.py index 9f28cdff..130b3f3c 100644 --- a/newton/newton/registration/views/registration.py +++ b/newton/newton/registration/views/registration.py @@ -18,12 +18,11 @@ import uuid import traceback from django.conf import settings -from keystoneauth1.exceptions import HttpError +from newton_base.registration import registration as newton_registration from common.exceptions import VimDriverNewtonException from common.msapi import extsys -from newton_base.registration import registration as newton_registration -from newton_base.openoapi.flavor import Flavors +from keystoneauth1.exceptions import HttpError logger = logging.getLogger(__name__) @@ -39,11 +38,7 @@ class Registry(newton_registration.Registry): def _discover_flavors(self, vimid="", session=None, viminfo=None): try: cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - cloud_extra_info_str = viminfo.get('cloud_extra_info') - if cloud_extra_info_str: - cloud_extra_info = json.loads(cloud_extra_info_str) - else: - cloud_extra_info = None + for flavor in self._get_list_resources( "/flavors/detail", "compute", session, viminfo, vimid, "flavors"): @@ -58,18 +53,19 @@ class Registry(newton_registration.Registry): 'flavor-is-public': flavor['os-flavor-access:is_public'], 'flavor-disabled': flavor['OS-FLV-DISABLED:disabled'], } - if flavor.get('link') and len(flavor['link']) > 0: - flavor_info['flavor-selflink'] = flavor['link'][0]['href'] or 'http://0.0.0.0', + + if flavor.get('links') and len(flavor['links']) > 0: + flavor_info['flavor-selflink'] = flavor['links'][0]['href'] or 'http://0.0.0.0' else: - flavor_info['flavor-selflink'] = 'http://0.0.0.0', + flavor_info['flavor-selflink'] = 'http://0.0.0.0' + + # add hpa capabilities + if (flavor['name'].find('onap.') == 0): + req_resouce = "/flavors/%s/os-extra_specs" % flavor['id'] + extraResp = self._get_list_resources(req_resouce, "compute", session, viminfo, vimid, "extra_specs") - if settings.AAI_SCHEMA_VERSION == "v13": - extraResp = Flavors._get_flavor_extra_specs(session, flavor['id']) - extraContent = extraResp.json() - hpa_capabilities = self._get_hpa_capabilities(vimid, flavor, - extraContent["extra_specs"], - cloud_extra_info) - flavor_info['hpa_capabilities'] = hpa_capabilities + hpa_capabilities = self._get_hpa_capabilities(flavor, extraResp, viminfo) + flavor_info['hpa-capabilities'] = {'hpa-capability': hpa_capabilities} self._update_resoure( cloud_owner, cloud_region_id, flavor['id'], @@ -85,202 +81,252 @@ class Registry(newton_registration.Registry): self._logger.error(traceback.format_exc()) return - def _get_hpa_capabilities(self, vimid, flavor, extra_specs, cloud_extra_info): - """Convert flavor information to HPA capabilities for AAI""" - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - - json_data = open('hpa.json').read() - hpa_dict = json.loads(json_data) - - capabilities = [] - - # Basic Capabilities - if set(hpa_dict['basicCapabilities']['hpa-attributes']).intersection(flavor): - capability = hpa_dict['basicCapabilities']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - capability['hpa-feature-attributes'] = self._get_capability_attributes( - flavor, - hpa_dict['basicCapabilities']['hpa-attributes']) - capabilities.append(capability) - - # Local Storage - if set(hpa_dict['localStorage']['hpa-attributes']).intersection(flavor): - capability = hpa_dict['localStorage']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - capability['hpa-feature-attributes'] = self._get_capability_attributes( - flavor, - hpa_dict['localStorage']['hpa-attributes']) - capabilities.append(capability) - - # CPU Topology - if set(hpa_dict['cpuTopology']['hpa-attributes']).intersection(extra_specs): - capability = hpa_dict['cpuTopology']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - capability['hpa-features-attributes'] = self._get_capability_attributes( - extra_specs, - hpa_dict['cpuTopology']['hpa-attributes']) - capabilities.append(capability) - - # CPU Pinning - if set(hpa_dict['cpuPinning']['hpa-attributes']).intersection(extra_specs): - capability = hpa_dict['cpuPinning']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - capability['hpa-features-attributes'] = self._get_capability_attributes( - extra_specs, - hpa_dict['cpuPinning']['hpa-attributes']) - capabilities.append(capability) - - # Huge Pages - if set(hpa_dict['hugePages']['hpa-attributes']).intersection(extra_specs): - capability = hpa_dict['hugePages']['info'] - if extra_specs['hw:mem_page_size'] not in ['small', 'large', 'any']: - unit = ''.join(i for i in extra_specs['hw:mem_page_size'] if not i.isdigit()) - if unit == '': - unit = 'KB' - hpa_dict['hugePages']['hpa-attributes']['hw:mem_page_size']['unit'] = unit - capability['hpa-capability-id'] = str(uuid.uuid4()) - capability['hpa-features-attributes'] = self._get_capability_attributes( - extra_specs, - hpa_dict['hugePages']['hpa-attributes']) - capabilities.append(capability) - - # NUMA - if "hw:numa_nodes" in extra_specs: - capability = hpa_dict['numa']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - # NUMA nodes are a special case and can't use the generic get attrs function - attributes = [] - attributes.append({ - 'hpa-attribute-key': hpa_dict['numa']['hpa-attributes']['hw:numa_nodes']['key'], - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(extra_specs['hw:numa_nodes']) - }) - for spec in extra_specs: - if spec.startswith('hw:numa_cpus'): - cpu_num = spec.split(":")[-1] - attributes.append({ - 'hpa-attribute-key': 'numaCpu-' + cpu_num, - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(extra_specs[spec]) - }) - elif spec.startswith('hw:numa_mem'): - mem_num = spec.split(":")[-1] - attributes.append({ - 'hpa-attribute-key': 'numaMem-' + mem_num, - 'hpa-attribute-value': '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}'.format(extra_specs[spec], - "GB") - }) - capability['hpa-features-attributes'] = attributes - capabilities.append(capability) - - # PCIe Passthrough - pci_devices = [spec for spec in extra_specs if spec.startswith("pci_passthrough:alias")] - for device in pci_devices: - capability = hpa_dict['pciePassthrough']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - # device will be in the form pci_passthrough:alias=ALIAS:COUNT, - # ALIAS is expected to be in the form <NAME>-<VENDOR_ID>-<DEVICE_ID> - device_info = extra_specs[device].split(":") - count = device_info[-1] - vendor_id = device_info[0].split("-")[1] - device_id = device_info[0].split("-")[2] - - attributes = [ - { - 'hpa-attribute-key': 'pciCount', - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(count) - }, - { - 'hpa-attribute-key': 'pciVendorId', - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(vendor_id) - }, - { - 'hpa-attribute-key': 'pciDeviceId', - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(device_id) - }, - { - 'hpa-attribute-key': 'functionType', - 'hpa-attribute-value': 'PCI-PASSTHROUGH' - } - ] - - capability['hpa-features-attributes'] = attributes - capabilities.append(capability) - - # SRIOV Devices - sriov_devices = [spec for spec in extra_specs if spec.startswith("aggregate_instance_extra_spec:sriov")] - for device in sriov_devices: - capability = hpa_dict['pciePassthrough']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - # device will be in the form aggregate_instance_extra_specs:sriov-device-<NAME>=<true/false>, - # NAME is expected to be in the form <NAME>-<VENDOR_ID>-<DEVICE_ID> - enabled = extra_specs[device] - count = 1 if enabled == "true" else 0 - vendor_id = device.split(":")[1].split("-")[3] - device_id = device.split(":")[1].split("-")[4] - - attributes = [ - { - 'hpa-attribute-key': 'pciCount', - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(count) - }, - { - 'hpa-attribute-key': 'pciVendorId', - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(vendor_id) - }, - { - 'hpa-attribute-key': 'pciDeviceId', - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(device_id) - }, - { - 'hpa-attribute-key': 'functionType', - 'hpa-attribute-value': 'SRIOV' - } - ] - - capability['hpa-features-attributes'] = attributes - capabilities.append(capability) - - - # OVS DPDK - if cloud_extra_info: - cloud_dpdk_info = cloud_extra_info.get('ovsDpdk') - capability = hpa_dict['ovsDpdk']['info'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - capability['architecture'] = cloud_dpdk_info.get('arch') - attributes = [ - { - 'hpa-attribute-key': cloud_dpdk_info.get('libname'), - 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(cloud_dpdk_info.get('libvalue')) - } - ] - capability['hpa-features-attributes'] = attributes - capabilities.append(capability) - - # Instruction Set Extensions - if "hw:capabilities:cpu_info:features" in extra_specs: - capability = hpa_dict['instructionSetExtensions'] - capability['hpa-capability-id'] = str(uuid.uuid4()) - attributes = [ - { - 'hpa-attribute-key': hpa_dict['instructionSetExtensions']['hpa-attributes']['hw:capabilities:cpu_info:features'], - 'hpa-attribute-value': '{{\"value\":[\"{0}\"]}}'.format(extra_specs['hw:capabilities:cpu_info:features']) - } - ] - capability['hpa-features-attributes'] = attributes - capabilities.append(capability) - - return capabilities - - def _get_capability_attributes(self, cloud_info, attributes): - result = [] - for attr in attributes: - if attr in cloud_info: - attribute = {'hpa-attribute-key': attributes[attr]['key']} - if attributes[attr]['unit']: - attribute['hpa-attribute-value'] = ( - '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}').format(cloud_info[attr], - attributes[attr]['unit']) - else: - attribute['hpa-attribute-value'] = '{{\"value\":\"{0}\"}}'.format(cloud_info[attr]) - - result.append(attribute) - return result + def _get_hpa_capabilities(self, flavor, extra_specs, viminfo): + hpa_caps = [] + + # Basic capabilties + caps_dict = self._get_hpa_basic_capabilities(flavor) + if len(caps_dict) > 0: + self._logger.debug("basic_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # cpupining capabilities + caps_dict = self._get_cpupinning_capabilities(extra_specs) + if len(caps_dict) > 0: + self._logger.debug("cpupining_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # cputopology capabilities + caps_dict = self._get_cputopology_capabilities(extra_specs) + if len(caps_dict) > 0: + self._logger.debug("cputopology_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # hugepages capabilities + caps_dict = self._get_hugepages_capabilities(extra_specs) + if len(caps_dict) > 0: + self._logger.debug("hugepages_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # numa capabilities + caps_dict = self._get_numa_capabilities(extra_specs) + if len(caps_dict) > 0: + self._logger.debug("numa_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # storage capabilities + caps_dict = self._get_storage_capabilities(flavor) + if len(caps_dict) > 0: + self._logger.debug("storage_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # CPU instruction set extension capabilities + caps_dict = self._get_instruction_set_capabilities(extra_specs) + if len(caps_dict) > 0: + self._logger.debug("instruction_set_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # PCI passthrough capabilities + caps_dict = self._get_pci_passthrough_capabilities(extra_specs) + if len(caps_dict) > 0: + self._logger.debug("pci_passthrough_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # ovsdpdk capabilities + caps_dict = self._get_ovsdpdk_capabilities(viminfo) + if len(caps_dict) > 0: + self._logger.debug("ovsdpdk_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + return hpa_caps + + def _get_hpa_basic_capabilities(self, flavor): + basic_capability = {} + feature_uuid = uuid.uuid4() + + basic_capability['hpa-capability-id'] = str(feature_uuid) + basic_capability['hpa-feature'] = 'basicCapabilities' + basic_capability['architecture'] = 'generic' + basic_capability['hpa-version'] = 'v1' + + basic_capability['hpa-feature-attributes'] = [] + basic_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'numVirtualCpu', + 'hpa-attribute-value':{'value': str(flavor['vcpus']) }}) + basic_capability['hpa-feature-attributes'].append({'hpa-attribute-key':'virtualMemSize', + 'hpa-attribute-value': {'value':str(flavor['ram']), 'unit':'MB'}}) + + return basic_capability + + def _get_cpupinning_capabilities(self, extra_specs): + cpupining_capability = {} + feature_uuid = uuid.uuid4() + + if extra_specs.has_key('hw:cpu_policy') or extra_specs.has_key('hw:cpu_thread_policy'): + cpupining_capability['hpa-capability-id'] = str(feature_uuid) + cpupining_capability['hpa-feature'] = 'cpuPinning' + cpupining_capability['architecture'] = 'generic' + cpupining_capability['hpa-version'] = 'v1' + + cpupining_capability['hpa-feature-attributes'] = [] + if extra_specs.has_key('hw:cpu_thread_policy'): + cpupining_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'logicalCpuThreadPinningPolicy', + 'hpa-attribute-value':{'value': str(extra_specs['hw:cpu_thread_policy'])}}) + if extra_specs.has_key('hw:cpu_policy'): + cpupining_capability['hpa-feature-attributes'].append({'hpa-attribute-key':'logicalCpuPinningPolicy', + 'hpa-attribute-value': {'value':str(extra_specs['hw:cpu_policy'])}}) + + return cpupining_capability + + def _get_cputopology_capabilities(self, extra_specs): + cputopology_capability = {} + feature_uuid = uuid.uuid4() + + if extra_specs.has_key('hw:cpu_sockets') or extra_specs.has_key('hw:cpu_cores') or extra_specs.has_key('hw:cpu_threads'): + cputopology_capability['hpa-capability-id'] = str(feature_uuid) + cputopology_capability['hpa-feature'] = 'cpuTopology' + cputopology_capability['architecture'] = 'generic' + cputopology_capability['hpa-version'] = 'v1' + + cputopology_capability['hpa-feature-attributes'] = [] + if extra_specs.has_key('hw:cpu_sockets'): + cputopology_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'numCpuSockets', + 'hpa-attribute-value':{'value': str(extra_specs['hw:cpu_sockets'])}}) + if extra_specs.has_key('hw:cpu_cores'): + cputopology_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'numCpuCores', + 'hpa-attribute-value':{'value': str(extra_specs['hw:cpu_cores'])}}) + if extra_specs.has_key('hw:cpu_threads'): + cputopology_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'numCpuThreads', + 'hpa-attribute-value':{'value': str(extra_specs['hw:cpu_threads'])}}) + + return cputopology_capability + + def _get_hugepages_capabilities(self, extra_specs): + hugepages_capability = {} + feature_uuid = uuid.uuid4() + + if extra_specs.has_key('hw:mem_page_size'): + hugepages_capability['hpa-capability-id'] = str(feature_uuid) + hugepages_capability['hpa-feature'] = 'hugePages' + hugepages_capability['architecture'] = 'generic' + hugepages_capability['hpa-version'] = 'v1' + + hugepages_capability['hpa-feature-attributes'] = [] + if extra_specs['hw:mem_page_size'] == 'large': + hugepages_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'memoryPageSize', + 'hpa-attribute-value':{'value': '2', + 'unit': 'MB'}}) + elif extra_specs['hw:mem_page_size'] == 'small': + hugepages_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'memoryPageSize', + 'hpa-attribute-value':{'value': '4', + 'unit': 'KB'}}) + elif extra_specs['hw:mem_page_size'] == 'any': + self._logger.info("Currently HPA feature memoryPageSize did not support 'any' page!!") + else : + hugepages_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'memoryPageSize', + 'hpa-attribute-value':{'value': str(extra_specs['hw:mem_page_size']), + 'unit': 'KB'}}) + + return hugepages_capability + + def _get_numa_capabilities(self, extra_specs): + numa_capability = {} + feature_uuid = uuid.uuid4() + + if extra_specs.has_key('hw:numa_nodes'): + numa_capability['hpa-capability-id'] = str(feature_uuid) + numa_capability['hpa-feature'] = 'numa' + numa_capability['architecture'] = 'generic' + numa_capability['hpa-version'] = 'v1' + + numa_capability['hpa-feature-attributes'] = [] + numa_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'numaNodes', + 'hpa-attribute-value':{'value': str(extra_specs['hw:numa_nodes'])}}) + + for num in range(0, int(extra_specs['hw:numa_nodes'])): + numa_cpu_node = "hw:numa_cpus.%s" % num + numa_mem_node = "hw:numa_mem.%s" % num + numacpu_key = "numaCpu-%s" % num + numamem_key = "numaMem-%s" % num + + if extra_specs.has_key(numa_cpu_node) and extra_specs.has_key(numa_mem_node): + numa_capability['hpa-feature-attributes'].append({'hpa-attribute-key': numacpu_key, + 'hpa-attribute-value':{'value': str(extra_specs[numa_cpu_node])}}) + numa_capability['hpa-feature-attributes'].append({'hpa-attribute-key': numamem_key, + 'hpa-attribute-value':{'value': str(extra_specs[numa_mem_node]),'unit':'MB'}}) + + return numa_capability + + def _get_storage_capabilities(self, flavor): + storage_capability = {} + feature_uuid = uuid.uuid4() + + storage_capability['hpa-capability-id'] = str(feature_uuid) + storage_capability['hpa-feature'] = 'localStorage' + storage_capability['architecture'] = 'generic' + storage_capability['hpa-version'] = 'v1' + + storage_capability['hpa-feature-attributes'] = [] + storage_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'diskSize', + 'hpa-attribute-value':{'value': str(flavor['disk']), 'unit':'GB'}}) + storage_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'swapMemSize', + 'hpa-attribute-value':{'value': str(flavor['swap']), 'unit':'MB'}}) + storage_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'ephemeralDiskSize', + 'hpa-attribute-value':{'value': str(flavor['OS-FLV-EXT-DATA:ephemeral']), 'unit':'GB'}}) + return storage_capability + + def _get_instruction_set_capabilities(self, extra_specs): + instruction_capability = {} + feature_uuid = uuid.uuid4() + + if extra_specs.has_key('hw:capabilities:cpu_info:features'): + instruction_capability['hpa-capability-id'] = str(feature_uuid) + instruction_capability['hpa-feature'] = 'instructionSetExtensions' + instruction_capability['architecture'] = 'Intel64' + instruction_capability['hpa-version'] = 'v1' + + instruction_capability['hpa-feature-attributes'] = [] + instruction_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'instructionSetExtensions', + 'hpa-attribute-value':{'value': str(extra_specs['hw:capabilities:cpu_info:features'])}}) + return instruction_capability + + def _get_pci_passthrough_capabilities(self, extra_specs): + instruction_capability = {} + feature_uuid = uuid.uuid4() + + if extra_specs.has_key('pci_passthrough:alias'): + value1 = extra_specs['pci_passthrough:alias'].split(':') + value2 = value1[0].split('-') + + instruction_capability['hpa-capability-id'] = str(feature_uuid) + instruction_capability['hpa-feature'] = 'pciePassthrough' + instruction_capability['architecture'] = str(value2[2]) + instruction_capability['hpa-version'] = 'v1' + + + instruction_capability['hpa-feature-attributes'] = [] + instruction_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'pciCount', + 'hpa-attribute-value':{'value': str(value1[1])}}) + instruction_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'pciVendorId', + 'hpa-attribute-value':{'value': str(value2[3])}}) + instruction_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'pciDeviceId', + 'hpa-attribute-value':{'value': str(value2[4])}}) + + return instruction_capability + + def _get_ovsdpdk_capabilities(self, viminfo): + ovsdpdk_capability = {} + feature_uuid = uuid.uuid4() + + cloud_extra_info_str = viminfo.get('cloud_extra_info') + if cloud_extra_info_str : + cloud_dpdk_info = cloud_extra_info_str.get("ovsDpdk") + if cloud_dpdk_info : + ovsdpdk_capability['hpa-capability-id'] = str(feature_uuid) + ovsdpdk_capability['hpa-feature'] = 'ovsDpdk' + ovsdpdk_capability['architecture'] = 'Intel64' + ovsdpdk_capability['hpa-version'] = 'v1' + + ovsdpdk_capability['hpa-feature-attributes'] = [] + ovsdpdk_capability['hpa-feature-attributes'].append({'hpa-attribute-key': str(cloud_dpdk_info.get("libname")), + 'hpa-attribute-value':{'value': str(cloud_dpdk_info.get("libversion"))}}) + return ovsdpdk_capability diff --git a/newton/newton/registration/views/registration.py.bak b/newton/newton/registration/views/registration.py.bak new file mode 100644 index 00000000..9f28cdff --- /dev/null +++ b/newton/newton/registration/views/registration.py.bak @@ -0,0 +1,286 @@ +# Copyright (c) 2017-2018 Wind River Systems, Inc. +# +# 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 logging +import json +import uuid +import traceback + +from django.conf import settings +from keystoneauth1.exceptions import HttpError + +from common.exceptions import VimDriverNewtonException +from common.msapi import extsys +from newton_base.registration import registration as newton_registration +from newton_base.openoapi.flavor import Flavors + +logger = logging.getLogger(__name__) + +# DEBUG=True + +class Registry(newton_registration.Registry): + + def __init__(self): + self.proxy_prefix = settings.MULTICLOUD_PREFIX + self.aai_base_url = settings.AAI_BASE_URL + self._logger = logger + + def _discover_flavors(self, vimid="", session=None, viminfo=None): + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + cloud_extra_info_str = viminfo.get('cloud_extra_info') + if cloud_extra_info_str: + cloud_extra_info = json.loads(cloud_extra_info_str) + else: + cloud_extra_info = None + for flavor in self._get_list_resources( + "/flavors/detail", "compute", session, viminfo, vimid, + "flavors"): + flavor_info = { + 'flavor-id': flavor['id'], + 'flavor-name': flavor['name'], + 'flavor-vcpus': flavor['vcpus'], + 'flavor-ram': flavor['ram'], + 'flavor-disk': flavor['disk'], + 'flavor-ephemeral': flavor['OS-FLV-EXT-DATA:ephemeral'], + 'flavor-swap': flavor['swap'], + 'flavor-is-public': flavor['os-flavor-access:is_public'], + 'flavor-disabled': flavor['OS-FLV-DISABLED:disabled'], + } + if flavor.get('link') and len(flavor['link']) > 0: + flavor_info['flavor-selflink'] = flavor['link'][0]['href'] or 'http://0.0.0.0', + else: + flavor_info['flavor-selflink'] = 'http://0.0.0.0', + + if settings.AAI_SCHEMA_VERSION == "v13": + extraResp = Flavors._get_flavor_extra_specs(session, flavor['id']) + extraContent = extraResp.json() + hpa_capabilities = self._get_hpa_capabilities(vimid, flavor, + extraContent["extra_specs"], + cloud_extra_info) + flavor_info['hpa_capabilities'] = hpa_capabilities + + self._update_resoure( + cloud_owner, cloud_region_id, flavor['id'], + flavor_info, "flavor") + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return + + def _get_hpa_capabilities(self, vimid, flavor, extra_specs, cloud_extra_info): + """Convert flavor information to HPA capabilities for AAI""" + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + + json_data = open('hpa.json').read() + hpa_dict = json.loads(json_data) + + capabilities = [] + + # Basic Capabilities + if set(hpa_dict['basicCapabilities']['hpa-attributes']).intersection(flavor): + capability = hpa_dict['basicCapabilities']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + capability['hpa-feature-attributes'] = self._get_capability_attributes( + flavor, + hpa_dict['basicCapabilities']['hpa-attributes']) + capabilities.append(capability) + + # Local Storage + if set(hpa_dict['localStorage']['hpa-attributes']).intersection(flavor): + capability = hpa_dict['localStorage']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + capability['hpa-feature-attributes'] = self._get_capability_attributes( + flavor, + hpa_dict['localStorage']['hpa-attributes']) + capabilities.append(capability) + + # CPU Topology + if set(hpa_dict['cpuTopology']['hpa-attributes']).intersection(extra_specs): + capability = hpa_dict['cpuTopology']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + capability['hpa-features-attributes'] = self._get_capability_attributes( + extra_specs, + hpa_dict['cpuTopology']['hpa-attributes']) + capabilities.append(capability) + + # CPU Pinning + if set(hpa_dict['cpuPinning']['hpa-attributes']).intersection(extra_specs): + capability = hpa_dict['cpuPinning']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + capability['hpa-features-attributes'] = self._get_capability_attributes( + extra_specs, + hpa_dict['cpuPinning']['hpa-attributes']) + capabilities.append(capability) + + # Huge Pages + if set(hpa_dict['hugePages']['hpa-attributes']).intersection(extra_specs): + capability = hpa_dict['hugePages']['info'] + if extra_specs['hw:mem_page_size'] not in ['small', 'large', 'any']: + unit = ''.join(i for i in extra_specs['hw:mem_page_size'] if not i.isdigit()) + if unit == '': + unit = 'KB' + hpa_dict['hugePages']['hpa-attributes']['hw:mem_page_size']['unit'] = unit + capability['hpa-capability-id'] = str(uuid.uuid4()) + capability['hpa-features-attributes'] = self._get_capability_attributes( + extra_specs, + hpa_dict['hugePages']['hpa-attributes']) + capabilities.append(capability) + + # NUMA + if "hw:numa_nodes" in extra_specs: + capability = hpa_dict['numa']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + # NUMA nodes are a special case and can't use the generic get attrs function + attributes = [] + attributes.append({ + 'hpa-attribute-key': hpa_dict['numa']['hpa-attributes']['hw:numa_nodes']['key'], + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(extra_specs['hw:numa_nodes']) + }) + for spec in extra_specs: + if spec.startswith('hw:numa_cpus'): + cpu_num = spec.split(":")[-1] + attributes.append({ + 'hpa-attribute-key': 'numaCpu-' + cpu_num, + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(extra_specs[spec]) + }) + elif spec.startswith('hw:numa_mem'): + mem_num = spec.split(":")[-1] + attributes.append({ + 'hpa-attribute-key': 'numaMem-' + mem_num, + 'hpa-attribute-value': '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}'.format(extra_specs[spec], + "GB") + }) + capability['hpa-features-attributes'] = attributes + capabilities.append(capability) + + # PCIe Passthrough + pci_devices = [spec for spec in extra_specs if spec.startswith("pci_passthrough:alias")] + for device in pci_devices: + capability = hpa_dict['pciePassthrough']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + # device will be in the form pci_passthrough:alias=ALIAS:COUNT, + # ALIAS is expected to be in the form <NAME>-<VENDOR_ID>-<DEVICE_ID> + device_info = extra_specs[device].split(":") + count = device_info[-1] + vendor_id = device_info[0].split("-")[1] + device_id = device_info[0].split("-")[2] + + attributes = [ + { + 'hpa-attribute-key': 'pciCount', + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(count) + }, + { + 'hpa-attribute-key': 'pciVendorId', + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(vendor_id) + }, + { + 'hpa-attribute-key': 'pciDeviceId', + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(device_id) + }, + { + 'hpa-attribute-key': 'functionType', + 'hpa-attribute-value': 'PCI-PASSTHROUGH' + } + ] + + capability['hpa-features-attributes'] = attributes + capabilities.append(capability) + + # SRIOV Devices + sriov_devices = [spec for spec in extra_specs if spec.startswith("aggregate_instance_extra_spec:sriov")] + for device in sriov_devices: + capability = hpa_dict['pciePassthrough']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + # device will be in the form aggregate_instance_extra_specs:sriov-device-<NAME>=<true/false>, + # NAME is expected to be in the form <NAME>-<VENDOR_ID>-<DEVICE_ID> + enabled = extra_specs[device] + count = 1 if enabled == "true" else 0 + vendor_id = device.split(":")[1].split("-")[3] + device_id = device.split(":")[1].split("-")[4] + + attributes = [ + { + 'hpa-attribute-key': 'pciCount', + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(count) + }, + { + 'hpa-attribute-key': 'pciVendorId', + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(vendor_id) + }, + { + 'hpa-attribute-key': 'pciDeviceId', + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(device_id) + }, + { + 'hpa-attribute-key': 'functionType', + 'hpa-attribute-value': 'SRIOV' + } + ] + + capability['hpa-features-attributes'] = attributes + capabilities.append(capability) + + + # OVS DPDK + if cloud_extra_info: + cloud_dpdk_info = cloud_extra_info.get('ovsDpdk') + capability = hpa_dict['ovsDpdk']['info'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + capability['architecture'] = cloud_dpdk_info.get('arch') + attributes = [ + { + 'hpa-attribute-key': cloud_dpdk_info.get('libname'), + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(cloud_dpdk_info.get('libvalue')) + } + ] + capability['hpa-features-attributes'] = attributes + capabilities.append(capability) + + # Instruction Set Extensions + if "hw:capabilities:cpu_info:features" in extra_specs: + capability = hpa_dict['instructionSetExtensions'] + capability['hpa-capability-id'] = str(uuid.uuid4()) + attributes = [ + { + 'hpa-attribute-key': hpa_dict['instructionSetExtensions']['hpa-attributes']['hw:capabilities:cpu_info:features'], + 'hpa-attribute-value': '{{\"value\":[\"{0}\"]}}'.format(extra_specs['hw:capabilities:cpu_info:features']) + } + ] + capability['hpa-features-attributes'] = attributes + capabilities.append(capability) + + return capabilities + + def _get_capability_attributes(self, cloud_info, attributes): + result = [] + for attr in attributes: + if attr in cloud_info: + attribute = {'hpa-attribute-key': attributes[attr]['key']} + if attributes[attr]['unit']: + attribute['hpa-attribute-value'] = ( + '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}').format(cloud_info[attr], + attributes[attr]['unit']) + else: + attribute['hpa-attribute-value'] = '{{\"value\":\"{0}\"}}'.format(cloud_info[attr]) + + result.append(attribute) + return result |