diff options
author | Haibin Huang <haibin.huang@intel.com> | 2019-11-12 17:20:03 +0800 |
---|---|---|
committer | Haibin Huang <haibin.huang@intel.com> | 2020-01-20 16:31:46 +0800 |
commit | 5f8e9379af90e81ad4a4d27b8cf6afb6edb40569 (patch) | |
tree | 17061ffe8fee62f458aee7defbb5faf3b3cccbee | |
parent | 860d099f352eb762f1f181f189867ed2c3f322a9 (diff) |
Make hpa discovery as plugin
Issue-ID: MULTICLOUD-695
Change-Id: I04547cfe664dfed457a228c04dfdf71c96b0ded0
Signed-off-by: Haibin Huang <haibin.huang@intel.com>
-rw-r--r-- | hpa/.testr.conf | 8 | ||||
-rw-r--r-- | hpa/LICENSE | 26 | ||||
-rw-r--r-- | hpa/README.md | 16 | ||||
-rw-r--r-- | hpa/assembly.xml | 37 | ||||
-rw-r--r-- | hpa/hpa/__init__.py | 13 | ||||
-rw-r--r-- | hpa/hpa/base.py | 22 | ||||
-rw-r--r-- | hpa/hpa/hpa_discovery.py | 450 | ||||
-rwxr-xr-x | hpa/mvn-phase-script.sh | 83 | ||||
-rw-r--r-- | hpa/pom.xml | 199 | ||||
-rw-r--r-- | hpa/setup.py | 43 | ||||
-rw-r--r-- | hpa/tests/__init__.py | 1 | ||||
-rw-r--r-- | hpa/tests/test.py | 148 | ||||
-rw-r--r-- | hpa/tests/test_hpa_discovery.py | 105 | ||||
-rw-r--r-- | hpa/tox.ini | 8 | ||||
-rw-r--r-- | pom.xml | 1 |
15 files changed, 1160 insertions, 0 deletions
diff --git a/hpa/.testr.conf b/hpa/.testr.conf new file mode 100644 index 00000000..6e39851b --- /dev/null +++ b/hpa/.testr.conf @@ -0,0 +1,8 @@ +[DEFAULT] +test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ + OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ + OS_LOG_CAPTURE=${OS_LOG_CAPTURE:-1} \ + OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-160} \ + ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./hpa/tests/unit} $LISTOPT $IDOPTION +test_id_option=--load-list $IDFILE +test_list_option=--list diff --git a/hpa/LICENSE b/hpa/LICENSE new file mode 100644 index 00000000..fffadb02 --- /dev/null +++ b/hpa/LICENSE @@ -0,0 +1,26 @@ + +The following licence applies to all files in this and subdirectories. Licences +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have licence text +defaults to being covered by this text; not all files support the addition of +licenses. + +# +# ------------------------------------------------------------------------- +# Copyright (c) 2015-2017 AT&T Intellectual Property +# +# 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. +# +# ------------------------------------------------------------------------- +# + diff --git a/hpa/README.md b/hpa/README.md new file mode 100644 index 00000000..fe568ad6 --- /dev/null +++ b/hpa/README.md @@ -0,0 +1,16 @@ +# 1. compile hpa plugin +cd hpa +python setup.py compile + +# 2. install hpa plugin +cd hpa +python setup.py install + +# 3. test hpa plugin +cd hpa/test +# 3.1 test cloud extra info with dpdk +python test.py -f "dpdk" +# 3.2 test without cloud extra info +python test.py -t "windriver" +python test.py -t "starlingx" +python test.py -t "pike" diff --git a/hpa/assembly.xml b/hpa/assembly.xml new file mode 100644 index 00000000..18126dc6 --- /dev/null +++ b/hpa/assembly.xml @@ -0,0 +1,37 @@ +<!-- + Copyright (c) 2019 Intel Corporation. All rights reserved. + + 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. +--> +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>hpa</id> + <formats> + <format>zip</format> + </formats> + <fileSets> + <fileSet> + <includes> + <include>*/**</include> + </includes> + <excludes> + <exclude>**/*.pyc</exclude> + <exclude>target/**</exclude> + <exclude>docker/**</exclude> + <exclude>cover/**</exclude> + <exclude>pom.xml</exclude> + <exclude>assembly.xml</exclude> + <exclude>xunit-results.xml</exclude> + </excludes> + </fileSet> + </fileSets> + <baseDirectory>hpa</baseDirectory> +</assembly> diff --git a/hpa/hpa/__init__.py b/hpa/hpa/__init__.py new file mode 100644 index 00000000..81362a2b --- /dev/null +++ b/hpa/hpa/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. diff --git a/hpa/hpa/base.py b/hpa/hpa/base.py new file mode 100644 index 00000000..90eb6432 --- /dev/null +++ b/hpa/hpa/base.py @@ -0,0 +1,22 @@ +import abc + +import six + + +@six.add_metaclass(abc.ABCMeta) +class HPA_DiscoveryBase(object): + """Base class for example plugin used in the tutorial. + """ + + def __init__(self): + """do nothing""" + + @abc.abstractmethod + def get_hpa_capabilities(self, data): + """Get cpupinning capabilities. + + :param data: A dictionary with string keys and simple types as + values. + :type data: dict(str:?) + :returns: Iterable producing the formatted text. + """ diff --git a/hpa/hpa/hpa_discovery.py b/hpa/hpa/hpa_discovery.py new file mode 100644 index 00000000..69b9f222 --- /dev/null +++ b/hpa/hpa/hpa_discovery.py @@ -0,0 +1,450 @@ +import traceback +import uuid +import json +import logging +from hpa import base + + +def ignore_case_get(args, key, def_val=""): + if not key: + return def_val + if key in args: + return args[key] + for old_key in args: + if old_key.upper() == key.upper(): + return args[old_key] + return def_val + +class HPA_Discovery(base.HPA_DiscoveryBase): + """HPA Discovery implementation. + """ + def __init__(self): + if not hasattr(self, "_logger"): + self._logger = logging.getLogger("hpa_discovery") + self.fh = logging.FileHandler('discovery.log') + self.fh.setLevel(logging.INFO) + self._logger.addHandler(self.fh) + + def get_hpa_capabilities(self, data): + hpa_caps = [] + + # Basic capabilties + caps_dict = self._get_hpa_basic_capabilities(data) + 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_cpupining_capabilities(data) + 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(data) + 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(data) + 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(data) + 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(data) + 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(data) + 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(data) + if len(caps_dict) > 0: + self._logger.debug("pci_passthrough_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # SRIOV-NIC capabilities + caps_dict = self._get_sriov_nic_capabilities(data) + if len(caps_dict) > 0: + self._logger.debug("sriov_nic_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # ovsdpdk capabilities + caps_dict = self._get_ovsdpdk_capabilities(data) + if len(caps_dict) > 0: + self._logger.debug("ovsdpdk_capabilities_info: %s" % caps_dict) + hpa_caps.append(caps_dict) + + # self._logger.error("hpa_caps: %s" % (hpa_caps)) + return hpa_caps + + def _get_hpa_basic_capabilities(self, data): + basic_capability = {} + feature_uuid = uuid.uuid4() + flavor = data["flavor"] + + try: + 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\":\"{0}\"}}'.format(flavor['vcpus']) + }) + basic_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key':'virtualMemSize', + 'hpa-attribute-value': + '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}'.format(flavor['ram'],"MB") + }) + except Exception as e: + self._logger.error(traceback.format_exc()) + return ( + 11, e.message + ) + + return basic_capability + + def _get_cpupining_capabilities(self, data): + cpupining_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + + try: + if 'hw:cpu_policy' in extra_specs\ + or 'hw:cpu_thread_policy' in extra_specs: + 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 'hw:cpu_thread_policy' in extra_specs: + cpupining_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'logicalCpuThreadPinningPolicy', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format( + extra_specs['hw:cpu_thread_policy']) + }) + if 'hw:cpu_policy' in extra_specs: + cpupining_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key':'logicalCpuPinningPolicy', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format( + extra_specs['hw:cpu_policy']) + }) + except Exception: + self._logger.error(traceback.format_exc()) + + return cpupining_capability + + def _get_cputopology_capabilities(self, data): + cputopology_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + + try: + if 'hw:cpu_sockets' in extra_specs\ + or 'hw:cpu_cores' in extra_specs\ + or 'hw:cpu_threads' in extra_specs: + 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 'hw:cpu_sockets' in extra_specs: + cputopology_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'numCpuSockets', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(extra_specs['hw:cpu_sockets']) + }) + if 'hw:cpu_cores' in extra_specs: + cputopology_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'numCpuCores', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(extra_specs['hw:cpu_cores']) + }) + if 'hw:cpu_threads' in extra_specs: + cputopology_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'numCpuThreads', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(extra_specs['hw:cpu_threads']) + }) + except Exception: + self._logger.error(traceback.format_exc()) + + return cputopology_capability + + def _get_hugepages_capabilities(self, data): + hugepages_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + + try: + if 'hw:mem_page_size' in extra_specs: + 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\":\"{0}\",\"unit\":\"{1}\"}}'.format(2,"MB") + }) + elif extra_specs['hw:mem_page_size'] == 'small': + hugepages_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'memoryPageSize', + 'hpa-attribute-value': + '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}'.format(4,"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\":\"{0}\",\"unit\":\"{1}\"}}'.format(extra_specs['hw:mem_page_size'],"KB") + }) + except Exception: + self._logger.error(traceback.format_exc()) + + return hugepages_capability + + def _get_numa_capabilities(self, data): + numa_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + + try: + if 'hw:numa_nodes' in extra_specs: + 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\":\"{0}\"}}'.format(extra_specs['hw:numa_nodes'] or 0) + }) + + 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 numa_cpu_node in extra_specs and numa_mem_node in extra_specs: + numa_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': numacpu_key, + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(extra_specs[numa_cpu_node]) + }) + numa_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': numamem_key, + 'hpa-attribute-value': + '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}'.format(extra_specs[numa_mem_node],"MB") + }) + except Exception: + self._logger.error(traceback.format_exc()) + + return numa_capability + + def _get_storage_capabilities(self, data): + storage_capability = {} + feature_uuid = uuid.uuid4() + flavor = data["flavor"] + + try: + 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\":\"{0}\",\"unit\":\"{1}\"}}'.format( + flavor['disk'] or 0, "GB") + }) + storage_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'swapMemSize', + 'hpa-attribute-value': + '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}'.format( + flavor['swap'] or 0, "MB") + }) + storage_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'ephemeralDiskSize', + 'hpa-attribute-value': + '{{\"value\":\"{0}\",\"unit\":\"{1}\"}}'.format( + flavor['OS-FLV-EXT-DATA:ephemeral'] or 0, "GB") + }) + except Exception: + self._logger.error(traceback.format_exc()) + + return storage_capability + + def _get_instruction_set_capabilities(self, data): + instruction_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + + try: + if 'hw:capabilities:cpu_info:features' in extra_specs: + 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\":\"{0}\"}}'.format( + extra_specs['hw:capabilities:cpu_info:features']) + }) + except Exception: + self._logger.error(traceback.format_exc()) + + return instruction_capability + + def _get_pci_passthrough_capabilities(self, data): + pci_passthrough_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + + try: + + if 'pci_passthrough:alias' in extra_specs: + value1 = extra_specs['pci_passthrough:alias'].split(':') + value2 = value1[0].split('-') + + pci_passthrough_capability['hpa-capability-id'] = str(feature_uuid) + pci_passthrough_capability['hpa-feature'] = 'pciePassthrough' + pci_passthrough_capability['architecture'] = str(value2[2]) + pci_passthrough_capability['hpa-version'] = 'v1' + + + pci_passthrough_capability['hpa-feature-attributes'] = [] + pci_passthrough_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'pciCount', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(value1[1]) + }) + pci_passthrough_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'pciVendorId', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(value2[3]) + }) + pci_passthrough_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'pciDeviceId', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(value2[4]) + }) + except Exception: + self._logger.error(traceback.format_exc()) + + return pci_passthrough_capability + + def _get_sriov_nic_capabilities(self, data): + sriov_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + + try: + if 'aggregate_instance_extra_specs:sriov_nic' in extra_specs: + value1 = extra_specs['aggregate_instance_extra_specs:sriov_nic'].split(':') + value2 = value1[0].split('-', 5) + + sriov_capability['hpa-capability-id'] = str(feature_uuid) + sriov_capability['hpa-feature'] = 'sriovNICNetwork' + sriov_capability['architecture'] = str(value2[2]) + sriov_capability['hpa-version'] = 'v1' + + sriov_capability['hpa-feature-attributes'] = [] + sriov_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'pciCount', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(value1[1])}) + sriov_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'pciVendorId', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(value2[3])}) + sriov_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'pciDeviceId', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(value2[4])}) + sriov_capability['hpa-feature-attributes'].append( + {'hpa-attribute-key': 'physicalNetwork', + 'hpa-attribute-value': + '{{\"value\":\"{0}\"}}'.format(value2[5])}) + except Exception: + self._logger.error(traceback.format_exc()) + + return sriov_capability + + def _get_ovsdpdk_capabilities(self, data): + ovsdpdk_capability = {} + feature_uuid = uuid.uuid4() + extra_specs = data["extra_specs"] + viminfo = data["viminfo"] + vimtype = data["vimtype"] + libname = "dataProcessingAccelerationLibrary" + libversion = "12.1" + + try: + ovsdpdk_capability['hpa-capability-id'] = str(feature_uuid) + ovsdpdk_capability['hpa-feature'] = 'ovsDpdk' + ovsdpdk_capability['architecture'] = 'Intel64' + ovsdpdk_capability['hpa-version'] = 'v1' + + cloud_extra_info_str = viminfo.get('cloud_extra_info') + if cloud_extra_info_str in [None, '']: + if vimtype in ["windriver", "starlingx"]: + libname = "dataProcessingAccelerationLibrary" + libversion = "17.2" + else: + if not isinstance(cloud_extra_info_str, dict): + try: + cloud_extra_info_str = json.loads(cloud_extra_info_str) + except Exception as ex: + logger.error("Can not convert cloud extra info %s %s" % ( + str(ex), cloud_extra_info_str)) + return {} + if cloud_extra_info_str : + cloud_dpdk_info = cloud_extra_info_str.get("ovsDpdk") + if cloud_dpdk_info : + libname = cloud_dpdk_info.get("libname") + libversion = cloud_dpdk_info.get("libversion") + + ovsdpdk_capability['hpa-feature-attributes'] = [ + { + 'hpa-attribute-key': str(libname), + 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(libversion) + },] + except Exception: + self._logger.error(traceback.format_exc()) + + return ovsdpdk_capability diff --git a/hpa/mvn-phase-script.sh b/hpa/mvn-phase-script.sh new file mode 100755 index 00000000..6cc1b2bb --- /dev/null +++ b/hpa/mvn-phase-script.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# 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. + + +set -e + +echo "running script: [$0] for module [$1] at stage [$2]" + +export SETTINGS_FILE=${SETTINGS_FILE:-$HOME/.m2/settings.xml} +MVN_PROJECT_MODULEID="$1" +MVN_PHASE="$2" + + +FQDN="${MVN_PROJECT_GROUPID}.${MVN_PROJECT_ARTIFACTID}" +if [ "$MVN_PROJECT_MODULEID" == "__" ]; then + MVN_PROJECT_MODULEID="" +fi + +if [ -z "$WORKSPACE" ]; then + WORKSPACE=$(pwd) +fi + +# mvn phase in life cycle +MVN_PHASE="$2" + + +echo "MVN_PROJECT_MODULEID is [$MVN_PROJECT_MODULEID]" +echo "MVN_PHASE is [$MVN_PHASE]" +echo "MVN_PROJECT_GROUPID is [$MVN_PROJECT_GROUPID]" +echo "MVN_PROJECT_ARTIFACTID is [$MVN_PROJECT_ARTIFACTID]" +echo "MVN_PROJECT_VERSION is [$MVN_PROJECT_VERSION]" + +run_tox_test() +{ + set -x + echo $PWD + CURDIR=$(pwd) + TOXINIS=$(find . -name "tox.ini") + cd .. + for TOXINI in "${TOXINIS[@]}"; do + DIR=$(echo "$TOXINI" | rev | cut -f2- -d'/' | rev) + cd "${CURDIR}/${DIR}" + rm -rf ./venv-tox ./.tox + virtualenv ./venv-tox --python=python3 + source ./venv-tox/bin/activate + pip install --upgrade pip + pip install --upgrade tox argparse + pip freeze + cd ${CURDIR} + tox + deactivate + cd .. + rm -rf ./venv-tox ./.tox + done +} + + +case $MVN_PHASE in +clean) + echo "==> clean phase script" + rm -rf ./venv-* + ;; +test) + echo "==> test phase script" + run_tox_test + ;; +*) + echo "==> unprocessed phase" + ;; +esac + diff --git a/hpa/pom.xml b/hpa/pom.xml new file mode 100644 index 00000000..7d658344 --- /dev/null +++ b/hpa/pom.xml @@ -0,0 +1,199 @@ +<?xml version="1.0"?> +<!-- + Copyright (c) Intel 2020, 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>org.onap.multicloud.openstack</groupId> + <artifactId>multicloud-openstack-root</artifactId> + <version>1.5.3-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.multicloud.openstack</groupId> + <artifactId>multicloud-openstack-hpa</artifactId> + <version>1.5.3-SNAPSHOT</version> + <packaging>pom</packaging> + <name>multicloud-openstack-hpar</name> + <description>multicloud for hpa plugin</description> + <properties> + <encoding>UTF-8</encoding> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <nexusproxy>https://nexus.onap.org</nexusproxy> + <sonar.sources>.</sonar.sources> + <sonar.junit.reportsPath>xunit-results.xml</sonar.junit.reportsPath> + <sonar.python.coverage.reportPath>coverage.xml</sonar.python.coverage.reportPath> + <sonar.language>py</sonar.language> + <sonar.pluginName>Python</sonar.pluginName> + <sonar.inclusions>**/*.py</sonar.inclusions> + <sonar.exclusions>**/venv-tox/**,**/.tox/**, **/tests/**,setup.py</sonar.exclusions> + </properties> + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.2.1</version> + <configuration> + <executable>${project.basedir}/mvn-phase-script.sh</executable> + <environmentVariables> + <!-- make mvn properties as env for our script --> + <MVN_PROJECT_GROUPID>${project.groupId}</MVN_PROJECT_GROUPID> + <MVN_PROJECT_ARTIFACTID>${project.artifactId}</MVN_PROJECT_ARTIFACTID> + <MVN_PROJECT_VERSION>${project.version}</MVN_PROJECT_VERSION> + </environmentVariables> + </configuration> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.2.1</version> + <executions> + <execution> + <id>clean phase script</id> + <phase>clean</phase> + <goals> + <goal>exec</goal> + </goals> + <configuration> + <arguments> + <argument>__</argument> + <argument>clean</argument> + </arguments> + </configuration> + </execution> + <execution> + <id>test script</id> + <phase>test</phase> + <goals> + <goal>exec</goal> + </goals> + <configuration> + <arguments> + <argument>__</argument> + <argument>test</argument> + </arguments> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <appendAssemblyId>false</appendAssemblyId> + <descriptors> + <descriptor>assembly.xml</descriptor> + </descriptors> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>docker</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>3.1.0</version> + <executions> + <execution> + <id>copy-resources</id> + <phase>install</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <overwrite>true</overwrite> + <nonFilteredFileExtensions> + <nonFilteredFileExtension>zip</nonFilteredFileExtension> + </nonFilteredFileExtensions> + <outputDirectory>${project.basedir}/docker_target</outputDirectory> + <resources> + <resource> + <directory>${project.basedir}/docker</directory> + <filtering>true</filtering> + </resource> + <resource> + <directory>${project.basedir}/target</directory> + <filtering>true</filtering> + <includes> + <include>*.zip</include> + </includes> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.6</version> + <executions> + <execution> + <phase>install</phase> + <inherited>false</inherited> + <configuration> + <target> + <exec executable="docker"> + <arg value="build"/> + <arg value="-t"/> + <arg value="${CONTAINER_PUSH_REGISTRY}/onap/multicloud/openstack-hpa:${project.version}"/> + <arg value="docker_target"/> + </exec> + <exec executable="docker"> + <arg value="tag"/> + <arg value="${CONTAINER_PUSH_REGISTRY}/onap/multicloud/openstack-hpa:${project.version}"/> + <arg value="${CONTAINER_PUSH_REGISTRY}/onap/multicloud/openstack-hpa:latest"/> + </exec> + <exec executable="docker"> + <arg value="push"/> + <arg value="${CONTAINER_PUSH_REGISTRY}/onap/multicloud/openstack-hpa:${project.version}"/> + </exec> + <exec executable="docker"> + <arg value="push"/> + <arg value="${CONTAINER_PUSH_REGISTRY}/onap/multicloud/openstack-hpa:latest"/> + </exec> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <activation> + <activeByDefault>false</activeByDefault> + </activation> + </profile> + </profiles> +</project> diff --git a/hpa/setup.py b/hpa/setup.py new file mode 100644 index 00000000..93babd2a --- /dev/null +++ b/hpa/setup.py @@ -0,0 +1,43 @@ +from setuptools import setup, find_packages + +setup( + name='hpa', + version='1.0', + + description='HPA discovery package for stevedore', + + author='Haibin Huang', + author_email='haibin.huang@intel.com', + + url='https://opendev.org/openstack/stevedore', + + classifiers=['Development Status :: 3 - Alpha', + 'License :: OSI Approved :: Apache Software License', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.5', + 'Intended Audience :: Developers', + 'Environment :: Console', + ], + + platforms=['Any'], + + scripts=[], + + provides=['hpa', + ], + + packages=find_packages(), + install_requires=['stevedore'], + include_package_data=True, + + entry_points={ + 'hpa.discovery': [ + 'discovery = hpa.hpa_discovery:HPA_Discovery', + ], + }, + + zip_safe=False, +) diff --git a/hpa/tests/__init__.py b/hpa/tests/__init__.py new file mode 100644 index 00000000..792d6005 --- /dev/null +++ b/hpa/tests/__init__.py @@ -0,0 +1 @@ +# diff --git a/hpa/tests/test.py b/hpa/tests/test.py new file mode 100644 index 00000000..a9fdcd77 --- /dev/null +++ b/hpa/tests/test.py @@ -0,0 +1,148 @@ +from __future__ import print_function + +import argparse + +from stevedore import extension + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('-f', action='store', dest='dpdk', help='dpdk use?') + parser.add_argument('-t', action='store', dest='vimtype', help='vim type') + parser.add_argument('--version', action='version', version='%(prog)s 1.0') + results = parser.parse_args() + dpdk = results.dpdk + vimtype = results.vimtype + + flavor = { + "vcpus": 2, + "ram": "2048", + "disk": "2G", + "swap": False, + "OS-FLV-EXT-DATA:ephemeral": False + } + + # viminfo + viminfo = { + "createTime": "2017-04-01 02:22:27", + "domain": "Default", + "name": "TiS_R4", + "password": "admin", + "tenant": "admin", + "type": "openstack", + "url": "http://128.224.180.14:5000/v3", + "userName": "admin", + "vendor": "WindRiver", + "version": "newton", + "vimId": "windriver-hudson-dc_RegionOne", + 'cloud_owner': 'windriver-hudson-dc', + 'cloud_region_id': 'RegionOne', + 'insecure': 'True' + } + + # Add cloud_extra_info in convert_vim_info + viminfo_with_dpdk = { + "createTime": "2017-04-01 02:22:27", + "domain": "Default", + "name": "TiS_R4", + "password": "admin", + "tenant": "admin", + "type": "openstack", + "url": "http://128.224.180.14:5000/v3", + "userName": "admin", + "vendor": "WindRiver", + "version": "newton", + "vimId": "windriver-hudson-dc_RegionOne", + 'cloud_owner': 'windriver-hudson-dc', + 'cloud_region_id': 'RegionOne', + 'insecure': 'True', + 'cloud_extra_info': '{ \ + "ovsDpdk": { \ + "version": "v1", \ + "arch": "Intel64", \ + "libname": "dataProcessingAccelerationLibrary", \ + "libversion": "v12.1" \ + } \ + }' + } + + # flavor extra specs + extra_specs = [ + # HPA UT1: CPU-Pinning + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:cpu_policy": "dedicated", + "hw:cpu_thread_policy": "prefer" + }, + # HPA UT2: CPU-Topology + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:cpu_sockets": "2", + "hw:cpu_cores": "4", + "hw:cpu_threads": "16" + }, + # HPA UT3: mem_page_size + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:mem_page_size": "large" + }, + # HPA UT4: numa_nodes + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:numa_nodes": "2", + "hw:numa_cpus.0": "0,1", + "hw:numa_cpus.1": "2,3,4,5", + "hw:numa_mem.0": "2048", + "hw:numa_mem.1": "2048" + }, + # HPA UT5: instruction set + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:capabilities:cpu_info:features": "avx,acpi" + }, + # HPA UT6: pci passthrough + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "pci_passthrough:alias": "sriov-vf-intel-8086-15b3:4" + }, + # HPA UT7: sriov-nic + { + "aggregate_instance_extra_specs:sriov_nic": "sriov-nic-intel-8086-15b3-physnet-1:1", + "capabilities:cpu_info:model": "Haswell" + } + ] + + + def get_hpa_capabilities(ext, data): + return (ext.obj.get_hpa_capabilities(data)) + + extra_specs = [ + # HPA UT1: CPU-Pinning + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:cpu_policy": "dedicated", + "hw:cpu_thread_policy": "prefer" + }, + ] + if dpdk != "dpdk": + viminfo = viminfo + else: + viminfo = viminfo_with_dpdk + + for extra_spec in extra_specs: + data = {"flavor": flavor, "extra_specs": extra_spec, "viminfo": viminfo, "vimtype": vimtype} + mgr = extension.ExtensionManager( + namespace='hpa.discovery', + invoke_on_load=True, + ) + + results = mgr.map(get_hpa_capabilities, data) + print(results) diff --git a/hpa/tests/test_hpa_discovery.py b/hpa/tests/test_hpa_discovery.py new file mode 100644 index 00000000..c63f377f --- /dev/null +++ b/hpa/tests/test_hpa_discovery.py @@ -0,0 +1,105 @@ +import unittest + +from hpa import hpa_discovery + +class TestDiscovery(unittest.TestCase): + def test_hpa_discovery(self): + """ + Test that it can discovery hpa capability + """ + + flavor = { + "vcpus": 2, + "ram": "2048", + "disk": "2G", + "swap": False, + "OS-FLV-EXT-DATA:ephemeral": False + } + + # Add cloud_extra_info in convert_vim_info + viminfo = { + "createTime": "2017-04-01 02:22:27", + "domain": "Default", + "name": "TiS_R4", + "password": "admin", + "tenant": "admin", + "type": "openstack", + "url": "http://128.224.180.14:5000/v3", + "userName": "admin", + "vendor": "WindRiver", + "version": "newton", + "vimId": "windriver-hudson-dc_RegionOne", + 'cloud_owner': 'windriver-hudson-dc', + 'cloud_region_id': 'RegionOne', + 'insecure': 'True', + 'cloud_extra_info': '{ \ + "ovsDpdk": { \ + "version": "v1", \ + "arch": "Intel64", \ + "libname": "dataProcessingAccelerationLibrary", \ + "libversion": "v12.1" \ + } \ + }' + } + + # flavor extra specs + extra_specs = [ + # HPA UT1: CPU-Pinning + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:cpu_policy": "dedicated", + "hw:cpu_thread_policy": "prefer" + }, + # HPA UT2: CPU-Topology + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:cpu_sockets": "2", + "hw:cpu_cores": "4", + "hw:cpu_threads": "16" + }, + # HPA UT3: mem_page_size + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:mem_page_size": "large" + }, + # HPA UT4: numa_nodes + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:numa_nodes": "2", + "hw:numa_cpus.0": "0,1", + "hw:numa_cpus.1": "2,3,4,5", + "hw:numa_mem.0": "2048", + "hw:numa_mem.1": "2048" + }, + # HPA UT5: instruction set + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "hw:capabilities:cpu_info:features": "avx,acpi" + }, + # HPA UT6: pci passthrough + { + "aggregate_instance_extra_specs:storage": "local_image", + "capabilities:cpu_info:model": "Haswell", + "pci_passthrough:alias": "sriov-vf-intel-8086-15b3:4" + }, + # HPA UT7: sriov-nic + { + "aggregate_instance_extra_specs:sriov_nic": "sriov-nic-intel-8086-15b3-physnet-1:1", + "capabilities:cpu_info:model": "Haswell" + } + ] + + vimtype = "windriver" + hpa = hpa_discovery.HPA_Discovery() + for extra_spec in extra_specs: + data = {"flavor": flavor, "extra_specs": extra_spec, "viminfo": viminfo, "vimtype": vimtype} + results = hpa.get_hpa_capabilities(data) + +if __name__ == '__main__': + unittest.main() + diff --git a/hpa/tox.ini b/hpa/tox.ini new file mode 100644 index 00000000..8727707e --- /dev/null +++ b/hpa/tox.ini @@ -0,0 +1,8 @@ +[tox] +envlist = py35 + +[testenv] +deps = + +commands = + python3 -m unittest discover @@ -45,6 +45,7 @@ <module>pike</module> <module>starlingx</module> <!--module>lenovo</module--> + <module>hpa</module> </modules> <build> |