Add pike registration 07/61607/2
authorHuang Haibin <haibin.huang@intel.com>
Tue, 21 Aug 2018 14:14:49 +0000 (22:14 +0800)
committerHuang Haibin <haibin.huang@intel.com>
Wed, 22 Aug 2018 01:33:39 +0000 (09:33 +0800)
Change-Id: Ie3dfa2292e59e4cd7cd9a0bae980d6f3aad9cbde
Issue-ID: MULTICLOUD-276
Signed-off-by: Huang Haibin <haibin.huang@intel.com>
pike/pike/registration/__init__.py [new file with mode: 0644]
pike/pike/registration/tests/__init__.py [new file with mode: 0644]
pike/pike/registration/tests/test_registration.py [new file with mode: 0644]
pike/pike/registration/views/__init__.py [new file with mode: 0644]
pike/pike/registration/views/registration.py [new file with mode: 0644]
pike/pike/urls.py

diff --git a/pike/pike/registration/__init__.py b/pike/pike/registration/__init__.py
new file mode 100644 (file)
index 0000000..741e0af
--- /dev/null
@@ -0,0 +1,14 @@
+# Copyright (c) 2018 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/pike/pike/registration/tests/__init__.py b/pike/pike/registration/tests/__init__.py
new file mode 100644 (file)
index 0000000..741e0af
--- /dev/null
@@ -0,0 +1,14 @@
+# Copyright (c) 2018 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/pike/pike/registration/tests/test_registration.py b/pike/pike/registration/tests/test_registration.py
new file mode 100644 (file)
index 0000000..193d8ba
--- /dev/null
@@ -0,0 +1,476 @@
+# Copyright (c) 2018 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.
+
+import mock
+
+from rest_framework import status
+
+from common.utils import restcall
+from newton_base.tests import mock_info
+from newton_base.tests import test_base
+from newton_base.util import VimDriverUtils
+
+OCATA_MOCK_VIM_INFO = {
+    "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',
+    'cloud_extra_info':
+        {
+        "ovsDpdk":{
+          "version": "v1",
+          "arch": "Intel64",
+          "libname":"dataProcessingAccelerationLibrary",
+          "libversion":"v12.1",
+          }
+        },
+    'insecure': 'True'
+}
+
+MOCK_GET_TENANT_RESPONSE = {
+    "projects":[
+        {"id": "1", "name": "project"},
+        {"id": "2", "name": "project2"},
+    ]
+}
+
+MOCK_GET_FLAVOR_RESPONSE = {
+    "flavors": [
+        {
+            "id": "1", "name": "micro", "vcpus": 1, "ram": "1MB",
+            "disk": "1G", "OS-FLV-EXT-DATA:ephemeral": False,
+            "swap": True, "os-flavor-access:is_public": True,
+            "OS-FLV-DISABLED:disabled": True, "link": [{"href":1}]
+         },
+        {
+            "id": "2", "name": "mini", "vcpus": 2, "ram": "2",
+            "disk": "2G", "OS-FLV-EXT-DATA:ephemeral": True,
+            "swap": False, "os-flavor-access:is_public": True,
+            "OS-FLV-DISABLED:disabled": True
+        },
+    ]
+}
+
+MOCK_GET_IMAGE_RESPONSE = {
+    "images": [
+        {
+            "id": "1", "name": "cirros", "self": "test",
+            "os_distro": "CirrOS", "os_version": "0.3",
+            "application": "test", "application_vendor": "ONAP",
+            "application_version": 1, "architecture": "x86",
+            "schema": None
+        },
+        {
+            "id": "2", "name": "cirros", "self": "test",
+            "os_distro": "CirrOS", "os_version": "0.3",
+            "application": "test", "application_vendor": "ONAP",
+            "application_version": 1, "architecture": "x86",
+            "schema": "req_resource"
+        },
+    ]
+}
+
+MOCK_GET_AZ_RESPONSE = {
+    "availabilityZoneInfo": [
+        {
+            "zoneName": "production",
+            "zoneState": {"available": True},
+            "hosts": { "hypervisor": "kvm" }
+        },
+        {
+            "zoneName": "testing",
+        },
+    ]
+}
+
+MOCK_HYPERVISOR_RESPONSE = {
+    "hypervisors": [
+        {"hypervisor_type": "kvm"}
+    ]
+}
+
+MOCK_GET_SNAPSHOT_RESPONSE = {
+    "snapshots": [
+        {
+            "id": 1, "name": "test", "metadata":
+            {
+            "architecture": "x86", "os-distro": "clearlinux",
+            "os-version": "276", "vendor": "intel", "version": 3,
+            "selflink": "test", "prev-snapshot-id": "test-id"
+            }
+        },
+        {"id": 2, "name": "test2"}
+    ]
+}
+
+MOCK_GET_HYPERVISOR_RESPONSE = {
+    "hypervisors": [
+        {
+            "hypervisor_hostname": "testing", "state": "ACTIVE",
+            "id": 1, "local_gb": 256, "memory_mb": 1024,
+            "hypervisor_links": "link", "host_ip": "127.0.0.1",
+            "cpu_info": u'{"topology": {"cores": 8, "threads": 16, "sockets": 4}}'
+        },
+        {
+            "hypervisor_hostname": "testing2", "state": "XXX",
+            "id": 1, "local_gb": 256, "memory_mb": 1024,
+            "hypervisor_links": "link", "host_ip": "127.0.0.1",
+        }
+    ]
+}
+
+TEST_REGISTER_ENDPOINT_REQUEST = {
+    "defaultTenant": "project1"
+}
+
+
+# HPA UT1: CPU-PINNING
+MOCK_GET_HPA_FLAVOR_LIST1_RESPONSE= {
+    "flavors": [
+        {
+            "id": "1", "name": "micro", "vcpus": 1, "ram": "1024",
+            "disk": "1G", "OS-FLV-EXT-DATA:ephemeral": False,
+            "swap": True, "os-flavor-access:is_public": True,
+            "OS-FLV-DISABLED:disabled": True, "link": [{"href": 1}]
+        },
+        {
+            "id": "2", "name": "onap.mini", "vcpus": 2, "ram": "2048",
+            "disk": "2G", "OS-FLV-EXT-DATA:ephemeral": True,
+            "swap": False, "os-flavor-access:is_public": True,
+            "OS-FLV-DISABLED:disabled": True
+        },
+    ]
+}
+
+# HPA UT2: CPU-Topology
+MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS2_RESPONSE = {
+    "extra_specs": {
+        "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
+MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS3_RESPONSE = {
+    "extra_specs": {
+        "aggregate_instance_extra_specs:storage": "local_image",
+        "capabilities:cpu_info:model": "Haswell",
+        "hw:mem_page_size": "large"
+    }
+}
+
+# HPA UT4: numa_nodes
+MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS4_RESPONSE = {
+    "extra_specs": {
+        "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
+MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS5_RESPONSE = {
+    "extra_specs": {
+        "aggregate_instance_extra_specs:storage": "local_image",
+        "capabilities:cpu_info:model": "Haswell",
+            "hw:capabilities:cpu_info:features": "avx,acpi"
+    }
+}
+
+# HPA UT6: pci passthrough
+MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS6_RESPONSE = {
+    "extra_specs": {
+        "aggregate_instance_extra_specs:storage": "local_image",
+        "capabilities:cpu_info:model": "Haswell",
+            "pci_passthrough:alias": "sriov-vf-intel-8086-15b3:4"
+    }
+}
+
+MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS_RESPONSE = {
+    "extra_specs": {
+        "aggregate_instance_extra_specs:storage": "local_image",
+        "capabilities:cpu_info:model": "Haswell",
+        "hw:cpu_policy": "dedicated",
+        "hw:cpu_thread_policy": "prefer"
+    }
+}
+
+
+class TestRegistration(test_base.TestRequest):
+
+    def setUp(self):
+        super(TestRegistration, self).setUp()
+        self.req_to_aai_backup = restcall.req_to_aai
+
+    def tearDown(self):
+        super(TestRegistration, self).tearDown()
+        restcall.req_to_aai = self.req_to_aai_backup
+
+    def _get_mock_response(self, return_value=None):
+        mock_response = mock.Mock(spec=test_base.MockResponse)
+        mock_response.status_code = status.HTTP_200_OK
+        mock_response.json.return_value = return_value
+        return mock_response
+
+    @mock.patch.object(VimDriverUtils, 'get_session')
+    @mock.patch.object(VimDriverUtils, 'get_vim_info')
+    def test_register_endpoint_successfully(
+            self, mock_get_vim_info, mock_get_session):
+        restcall.req_to_aai = mock.Mock()
+        restcall.req_to_aai.return_value = (0, {}, status.HTTP_200_OK)
+        mock_get_vim_info.return_value = OCATA_MOCK_VIM_INFO
+        mock_get_session.return_value = test_base.get_mock_session(
+            ["get"], {
+                "side_effect": [
+                    self._get_mock_response(MOCK_GET_TENANT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_FLAVOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_IMAGE_RESPONSE),
+                    self._get_mock_response(),
+                    self._get_mock_response(MOCK_GET_AZ_RESPONSE),
+                    self._get_mock_response(MOCK_HYPERVISOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_SNAPSHOT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HYPERVISOR_RESPONSE)
+                ]
+            })
+
+        response = self.client.post((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), TEST_REGISTER_ENDPOINT_REQUEST,
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                          response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'delete_vim_info')
+    def test_unregister_endpoint_successfully(
+            self, mock_delete_vim_info):
+        mock_delete_vim_info.return_value = 0
+
+        response = self.client.delete((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), "{}", content_type="application/json",
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                          response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'delete_vim_info')
+    def test_fail_unregister_endpoint(
+            self, mock_delete_vim_info):
+        mock_delete_vim_info.return_value = 1
+
+        response = self.client.delete((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), "{}", content_type="application/json",
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_500_INTERNAL_SERVER_ERROR,
+                          response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'get_session')
+    @mock.patch.object(VimDriverUtils, 'get_vim_info')
+    def test_register_hpa_cpupinning_successfully(
+            self, mock_get_vim_info, mock_get_session):
+        restcall.req_to_aai = mock.Mock()
+        restcall.req_to_aai.return_value = (0, {}, status.HTTP_200_OK)
+        mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO
+        mock_get_session.return_value = test_base.get_mock_session(
+            ["get"], {
+                "side_effect": [
+                    self._get_mock_response(MOCK_GET_TENANT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_LIST1_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS_RESPONSE),
+                    self._get_mock_response(MOCK_GET_IMAGE_RESPONSE),
+                    self._get_mock_response(),
+                    self._get_mock_response(MOCK_GET_AZ_RESPONSE),
+                    self._get_mock_response(MOCK_HYPERVISOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_SNAPSHOT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HYPERVISOR_RESPONSE)
+                ]
+            })
+
+        response = self.client.post((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), TEST_REGISTER_ENDPOINT_REQUEST,
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                      response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'get_session')
+    @mock.patch.object(VimDriverUtils, 'get_vim_info')
+    def test_register_hpa_cputopology_successfully(
+            self, mock_get_vim_info, mock_get_session):
+        restcall.req_to_aai = mock.Mock()
+        restcall.req_to_aai.return_value = (0, {}, status.HTTP_200_OK)
+        mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO
+        mock_get_session.return_value = test_base.get_mock_session(
+            ["get"], {
+                "side_effect": [
+                    self._get_mock_response(MOCK_GET_TENANT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_LIST1_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS2_RESPONSE),
+                    self._get_mock_response(MOCK_GET_IMAGE_RESPONSE),
+                    self._get_mock_response(),
+                    self._get_mock_response(MOCK_GET_AZ_RESPONSE),
+                    self._get_mock_response(MOCK_HYPERVISOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_SNAPSHOT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HYPERVISOR_RESPONSE)
+                ]
+            })
+
+        response = self.client.post((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), TEST_REGISTER_ENDPOINT_REQUEST,
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                      response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'get_session')
+    @mock.patch.object(VimDriverUtils, 'get_vim_info')
+    def test_register_hpa_hugepage_successfully(
+            self, mock_get_vim_info, mock_get_session):
+        restcall.req_to_aai = mock.Mock()
+        restcall.req_to_aai.return_value = (0, {}, status.HTTP_200_OK)
+        mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO
+        mock_get_session.return_value = test_base.get_mock_session(
+            ["get"], {
+                "side_effect": [
+                    self._get_mock_response(MOCK_GET_TENANT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_LIST1_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS3_RESPONSE),
+                    self._get_mock_response(MOCK_GET_IMAGE_RESPONSE),
+                    self._get_mock_response(),
+                    self._get_mock_response(MOCK_GET_AZ_RESPONSE),
+                    self._get_mock_response(MOCK_HYPERVISOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_SNAPSHOT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HYPERVISOR_RESPONSE)
+                ]
+            })
+
+        response = self.client.post((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), TEST_REGISTER_ENDPOINT_REQUEST,
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                      response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'get_session')
+    @mock.patch.object(VimDriverUtils, 'get_vim_info')
+    def test_register_hpa_numa_successfully(
+            self, mock_get_vim_info, mock_get_session):
+        restcall.req_to_aai = mock.Mock()
+        restcall.req_to_aai.return_value = (0, {}, status.HTTP_200_OK)
+        mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO
+        mock_get_session.return_value = test_base.get_mock_session(
+            ["get"], {
+                "side_effect": [
+                    self._get_mock_response(MOCK_GET_TENANT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_LIST1_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS4_RESPONSE),
+                    self._get_mock_response(MOCK_GET_IMAGE_RESPONSE),
+                    self._get_mock_response(),
+                    self._get_mock_response(MOCK_GET_AZ_RESPONSE),
+                    self._get_mock_response(MOCK_HYPERVISOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_SNAPSHOT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HYPERVISOR_RESPONSE)
+                ]
+            })
+
+        response = self.client.post((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), TEST_REGISTER_ENDPOINT_REQUEST,
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                      response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'get_session')
+    @mock.patch.object(VimDriverUtils, 'get_vim_info')
+    def test_register_hpa_instructionset_successfully(
+            self, mock_get_vim_info, mock_get_session):
+        restcall.req_to_aai = mock.Mock()
+        restcall.req_to_aai.return_value = (0, {}, status.HTTP_200_OK)
+        mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO
+        mock_get_session.return_value = test_base.get_mock_session(
+            ["get"], {
+                "side_effect": [
+                    self._get_mock_response(MOCK_GET_TENANT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_LIST1_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS5_RESPONSE),
+                    self._get_mock_response(MOCK_GET_IMAGE_RESPONSE),
+                    self._get_mock_response(),
+                    self._get_mock_response(MOCK_GET_AZ_RESPONSE),
+                    self._get_mock_response(MOCK_HYPERVISOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_SNAPSHOT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HYPERVISOR_RESPONSE)
+                ]
+            })
+
+        response = self.client.post((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), TEST_REGISTER_ENDPOINT_REQUEST,
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                      response.status_code)
+
+    @mock.patch.object(VimDriverUtils, 'get_session')
+    @mock.patch.object(VimDriverUtils, 'get_vim_info')
+    def test_register_hpa_pcipassthrough_successfully(
+            self, mock_get_vim_info, mock_get_session):
+        restcall.req_to_aai = mock.Mock()
+        restcall.req_to_aai.return_value = (0, {}, status.HTTP_200_OK)
+        mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO
+        mock_get_session.return_value = test_base.get_mock_session(
+            ["get"], {
+                "side_effect": [
+                    self._get_mock_response(MOCK_GET_TENANT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_LIST1_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HPA_FLAVOR_onap_mini_EXTRA_SPECS6_RESPONSE),
+                    self._get_mock_response(MOCK_GET_IMAGE_RESPONSE),
+                    self._get_mock_response(),
+                    self._get_mock_response(MOCK_GET_AZ_RESPONSE),
+                    self._get_mock_response(MOCK_HYPERVISOR_RESPONSE),
+                    self._get_mock_response(MOCK_GET_SNAPSHOT_RESPONSE),
+                    self._get_mock_response(MOCK_GET_HYPERVISOR_RESPONSE)
+                ]
+            })
+
+        response = self.client.post((
+            "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/"
+            "registry"), TEST_REGISTER_ENDPOINT_REQUEST,
+            HTTP_X_AUTH_TOKEN=mock_info.MOCK_TOKEN_ID)
+
+        self.assertEquals(status.HTTP_202_ACCEPTED,
+                      response.status_code)
+
diff --git a/pike/pike/registration/views/__init__.py b/pike/pike/registration/views/__init__.py
new file mode 100644 (file)
index 0000000..741e0af
--- /dev/null
@@ -0,0 +1,14 @@
+# Copyright (c) 2018 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/pike/pike/registration/views/registration.py b/pike/pike/registration/views/registration.py
new file mode 100644 (file)
index 0000000..fdb2b0f
--- /dev/null
@@ -0,0 +1,376 @@
+# Copyright (c) 2018 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.
+
+import logging
+import json
+import uuid
+import traceback
+
+from django.conf import settings
+
+from newton_base.registration import registration as newton_registration
+from common.exceptions import VimDriverNewtonException
+from common.msapi import extsys
+from keystoneauth1.exceptions import HttpError
+
+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)
+
+            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('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'
+
+                # 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")
+
+                    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'],
+                    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, 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\":\"{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")
+                                                           })
+
+        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\":\"{0}\"}}'.format(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\":\"{0}\"}}'.format(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\":\"{0}\"}}'.format(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\":\"{0}\"}}'.format(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\":\"{0}\"}}'.format(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\":\"{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")
+                                                                       })
+
+        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\":\"{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 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\":\"{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")
+                                                                      })
+
+        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\":\"{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")
+                                                             })
+        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\":\"{0}\"}}'.format(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\":\"{0}\"}}'.format(value1[1])
+                                                                     })
+            instruction_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'pciVendorId',
+                                                       'hpa-attribute-value':
+                                                      '{{\"value\":\"{0}\"}}'.format(value2[3])
+                                                                     })
+            instruction_capability['hpa-feature-attributes'].append({'hpa-attribute-key': 'pciDeviceId',
+                                                       'hpa-attribute-value':
+                                                      '{{\"value\":\"{0}\"}}'.format(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 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 :
+                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\":\"{0}\"}}'.format(cloud_dpdk_info.get("libversion"))                                                                                                                 })
+        return ovsdpdk_capability
index 6ff32d9..11d670c 100644 (file)
 
 from django.conf.urls import include, url
 
+from pike.registration.views import registration
 from newton_base.openoapi import tenants
 
 urlpatterns = [
     url(r'^', include('pike.swagger.urls')),
     url(r'^', include('pike.samples.urls')),
+    url(r'^api/multicloud-pike/v0/(?P<vimid>[0-9a-zA-Z_-]+)/registry$',
+        registration.Registry.as_view()),
     url(r'^api/multicloud-pike/v0/(?P<vimid>[0-9a-zA-Z_-]+)/exten',
         include('pike.extensions.urls')),
 ]