diff options
-rw-r--r-- | ocata/ocata/extensions/urlsV1.py | 24 | ||||
-rw-r--r-- | ocata/ocata/extensions/views/extensions.py | 12 | ||||
-rw-r--r-- | ocata/ocata/proxy/views/identityV3.py | 48 | ||||
-rw-r--r-- | ocata/ocata/registration/views/registration.py | 19 | ||||
-rw-r--r-- | ocata/ocata/settings.py | 3 | ||||
-rw-r--r-- | ocata/ocata/urls.py | 8 | ||||
-rw-r--r-- | pike/pike/proxy/__init__.py | 14 | ||||
-rw-r--r-- | pike/pike/proxy/tests/__init__.py | 14 | ||||
-rw-r--r-- | pike/pike/proxy/tests/test_identity_proxy.py | 740 | ||||
-rw-r--r-- | pike/pike/proxy/tests/test_service_proxy.py | 852 | ||||
-rw-r--r-- | pike/pike/proxy/urls.py | 39 | ||||
-rw-r--r-- | pike/pike/proxy/views/__init__.py | 14 | ||||
-rw-r--r-- | pike/pike/proxy/views/identityV3.py | 34 | ||||
-rw-r--r-- | pike/pike/proxy/views/services.py | 46 | ||||
-rw-r--r-- | pike/pike/registration/__init__.py | 14 | ||||
-rw-r--r-- | pike/pike/registration/tests/__init__.py | 14 | ||||
-rw-r--r-- | pike/pike/registration/tests/test_registration.py | 476 | ||||
-rw-r--r-- | pike/pike/registration/views/__init__.py | 14 | ||||
-rw-r--r-- | pike/pike/registration/views/registration.py | 376 | ||||
-rw-r--r-- | pike/pike/urls.py | 6 |
20 files changed, 2767 insertions, 0 deletions
diff --git a/ocata/ocata/extensions/urlsV1.py b/ocata/ocata/extensions/urlsV1.py new file mode 100644 index 00000000..0d6e3ada --- /dev/null +++ b/ocata/ocata/extensions/urlsV1.py @@ -0,0 +1,24 @@ +# 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. + +from django.conf.urls import url +from rest_framework.urlpatterns import format_suffix_patterns + +from ocata.extensions.views import extensions + +urlpatterns = [ + url(r'^sions/?$', extensions.APIv1Extensions.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/ocata/ocata/extensions/views/extensions.py b/ocata/ocata/extensions/views/extensions.py index 2c499f36..bd90a119 100644 --- a/ocata/ocata/extensions/views/extensions.py +++ b/ocata/ocata/extensions/views/extensions.py @@ -27,3 +27,15 @@ class Extensions(newton_extensions.Extensions): self._logger = logger self.proxy_prefix = settings.MULTICLOUD_PREFIX +class APIv1Extensions(Extensions): + + def __init__(self): + self._logger = logger + self.proxy_prefix = settings.MULTICLOUD_API_V1_PREFIX + + + def get(self, request, cloud_owner="", cloud_region_id=""): + self._logger.info("cloud_owner,cloud_region_id: %s,%s" % (cloud_owner,cloud_region_id)) + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Extensions,self).get(request, vimid) diff --git a/ocata/ocata/proxy/views/identityV3.py b/ocata/ocata/proxy/views/identityV3.py index eaeeca47..ed0443dc 100644 --- a/ocata/ocata/proxy/views/identityV3.py +++ b/ocata/ocata/proxy/views/identityV3.py @@ -32,3 +32,51 @@ class TokensV2(newton_identityV3.TokensV2): def __init__(self): self.proxy_prefix = settings.MULTICLOUD_PREFIX self._logger = logger + +class APIv1Tokens(Tokens): + def __init__(self): + super(APIv1Tokens, self).__init__() + self.proxy_prefix = settings.MULTICLOUD_API_V1_PREFIX + + + def get(self, request, cloud_owner="", cloud_region_id=""): + self._logger.info("cloud_owner,cloud_region_id: %s,%s" % (cloud_owner,cloud_region_id)) + #self._logger.debug("META> %s" % request.META) + #self._logger.debug("data> %s" % request.data) + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Tokens, self).get(request, vimid) + + + def post(self, request, cloud_owner="", cloud_region_id=""): + self._logger.info("cloud_owner,cloud_region_id: %s,%s" % (cloud_owner,cloud_region_id)) + #self._logger.debug("META> %s" % request.META) + #self._logger.debug("data> %s" % request.data) + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Tokens,self).post(request, vimid) + + +class APIv1TokensV2(TokensV2): + def __init__(self): + super(APIv1TokensV2, self).__init__() + self.proxy_prefix = settings.MULTICLOUD_API_V1_PREFIX + + + def get(self, request, cloud_owner="", cloud_region_id=""): + self._logger.info("cloud_owner,cloud_region_id: %s,%s" % (cloud_owner,cloud_region_id)) + #self._logger.debug("META> %s" % request.META) + #self._logger.debug("data> %s" % request.data) + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1TokensV2, self).get(request, vimid) + + + def post(self, request, cloud_owner="", cloud_region_id=""): + self._logger.info("cloud_owner,cloud_region_id: %s,%s" % (cloud_owner,cloud_region_id)) + #self._logger.debug("META> %s" % request.META) + #self._logger.debug("data> %s" % request.data) + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1TokensV2,self).post(request, vimid) + diff --git a/ocata/ocata/registration/views/registration.py b/ocata/ocata/registration/views/registration.py index ccaea45a..4f8180b4 100644 --- a/ocata/ocata/registration/views/registration.py +++ b/ocata/ocata/registration/views/registration.py @@ -374,3 +374,22 @@ class Registry(newton_registration.Registry): 'hpa-attribute-value': '{{\"value\":\"{0}\"}}'.format(cloud_dpdk_info.get("libversion")) }) return ovsdpdk_capability + +class RegistryV1(Registry): + def __init__(self): + self.proxy_prefix = settings.MULTICLOUD_API_V1_PREFIX + self.aai_base_url = settings.AAI_BASE_URL + self._logger = logger + + def post(self, request, cloud_owner="", cloud_region_id=""): + self._logger.info("registration with : %s, %s" % (cloud_owner, cloud_region_id)) + self._logger.debug("with data: %s" % request.data) + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(RegistryV1, self).post(request, vimid) + + def delete(self, request, cloud_owner="", cloud_region_id=""): + self._logger.debug("unregister cloud region: %s, %s" % (cloud_owner, cloud_region_id)) + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(RegistryV1, self).delete(request, vimid) diff --git a/ocata/ocata/settings.py b/ocata/ocata/settings.py index f9f040ba..1e86178e 100644 --- a/ocata/ocata/settings.py +++ b/ocata/ocata/settings.py @@ -97,6 +97,9 @@ MSB_SERVICE_PORT = os.environ.get('MSB_PORT', "80") MULTICLOUD_PREFIX = "http://%s:%s/api/multicloud-ocata/v0" % ( MSB_SERVICE_ADDR, MSB_SERVICE_PORT) +MULTICLOUD_API_V1_PREFIX = "http://%s:%s/api/multicloud-ocata/v1" % ( + MSB_SERVICE_ADDR, MSB_SERVICE_PORT) + # [A&AI] AAI_ADDR = os.environ.get('AAI_ADDR', "aai.api.simpledemo.openecomp.org") AAI_PORT = os.environ.get('AAI_PORT', "8443") diff --git a/ocata/ocata/urls.py b/ocata/ocata/urls.py index bcac8669..525650df 100644 --- a/ocata/ocata/urls.py +++ b/ocata/ocata/urls.py @@ -44,6 +44,14 @@ urlpatterns = [ url(r'^api/multicloud-ocata/v0/(?P<vimid>[0-9a-zA-Z_-]+)/vesagent/?$', vesagent_ctrl.VesAgentCtrl.as_view()), + # API upgrading + url(r'^api/multicloud-ocata/v1/(?P<vimid>[0-9a-zA-Z_-]+)/registry$', + registration.RegistryV1.as_view()), + url(r'^api/multicloud-ocata/v1/(?P<vimid>[0-9a-zA-Z_-]+)$', + registration.RegistryV1.as_view()), + url(r'^api/multicloud-ocata/v1/(?P<vimid>[0-9a-zA-Z_-]+)/exten', + include('ocata.extensions.urlsV1')), + ] diff --git a/pike/pike/proxy/__init__.py b/pike/pike/proxy/__init__.py new file mode 100644 index 00000000..741e0afb --- /dev/null +++ b/pike/pike/proxy/__init__.py @@ -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/proxy/tests/__init__.py b/pike/pike/proxy/tests/__init__.py new file mode 100644 index 00000000..741e0afb --- /dev/null +++ b/pike/pike/proxy/tests/__init__.py @@ -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/proxy/tests/test_identity_proxy.py b/pike/pike/proxy/tests/test_identity_proxy.py new file mode 100644 index 00000000..0eeb96ae --- /dev/null +++ b/pike/pike/proxy/tests/test_identity_proxy.py @@ -0,0 +1,740 @@ +# 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 json + +import mock +import unittest + +from django.test import Client +from rest_framework import status + +from keystoneauth1 import session +from keystoneauth1.exceptions import HttpError + +from newton_base.util import VimDriverUtils +from pike.proxy.views.identityV3 import Tokens +from newton_base.tests import mock_info + +mock_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": "pike", + "vimId": "windriver-hudson-dc_RegionOne", + 'cloud_owner':'windriver-hudson-dc', + 'cloud_region_id':'RegionOne', + 'cloud_extra_info':'', + 'insecure':'True', +} + +mock_token_id="1a62b3971d774404a504c5d9a3e506e3" + +mock_catalog_response = { + "catalog" : [ + { + "id" : "99aefcc82a9246f98f8c281e61ffc754", + "endpoints" : [ + { + "region" : "RegionOne", + "url" : "http://128.224.180.14:9696", + "id" : "39583c1508ad4b71b380570a745ee10a", + "interface" : "public", + "region_id" : "RegionOne" + }, + { + "url" : "http://192.168.204.2:9696", + "region" : "RegionOne", + "id" : "37e8d07ba24e4b8f93490c9daaba06e2", + "interface" : "internal", + "region_id" : "RegionOne" + }, + { + "interface" : "admin", + "id" : "7eee4ca98d444b1abb00a50d4b89373f", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://192.168.204.2:9696" + } + ], + "name" : "neutron", + "type" : "network" + }, + { + "endpoints" : [ + { + "interface" : "public", + "id" : "10496738fa374295a4a88a63b81a1589", + "region_id" : "RegionOne", + "url" : "http://128.224.180.14:8777", + "region" : "RegionOne" + }, + { + "id" : "02dcb8c0bd464c4489fa0a0c9f28571f", + "region_id" : "RegionOne", + "interface" : "internal", + "url" : "http://192.168.204.2:8777", + "region" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "8a73b0d3743b4e78b87614690f6e97fe", + "interface" : "admin", + "url" : "http://192.168.204.2:8777", + "region" : "RegionOne" + } + ], + "id" : "d131054da83f4c93833799747a0f4709", + "name" : "ceilometer", + "type" : "metering" + }, + { + "type" : "volumev2", + "name" : "cinderv2", + "endpoints" : [ + { + "id" : "35a67ad36f0447d19c9662babf7cf609", + "interface" : "public", + "region_id" : "RegionOne", + "url" : "http://128.224.180.14:8776/v2/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v2/fcca3cc49d5e42caae15459e27103efc", + "id" : "c6ea42052268420fa2c8d351ee68c922", + "interface" : "internal", + "region_id" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "91cb24853dc3450d847b0c286a2e44ea", + "interface" : "admin", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v2/fcca3cc49d5e42caae15459e27103efc" + } + ], + "id" : "40440057102440739c30be10a66bc5d1" + }, + { + "name" : "heat", + "type" : "orchestration", + "id" : "35300cce88db4bd4bb5a72ffe3b88b00", + "endpoints" : [ + { + "id" : "58999d7b4a94439089ecfb2aca2d7f6c", + "region_id" : "RegionOne", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:8004/v1/fcca3cc49d5e42caae15459e27103efc" + }, + { + "url" : "http://192.168.204.2:8004/v1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "interface" : "internal", + "id" : "1e0ee1a2aef84802b921d422372a567e", + "region_id" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8004/v1/fcca3cc49d5e42caae15459e27103efc", + "id" : "17661bf4859741b8a43a461dedad1871", + "region_id" : "RegionOne", + "interface" : "admin" + } + ] + }, + { + "id" : "08dc6912aea64c01925012c8a6df250a", + "endpoints" : [ + { + "id" : "02792c4eed77486083f9b2e52d7b94b0", + "region_id" : "RegionOne", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:5000/v3" + }, + { + "id" : "b6d5cad394b94309ae40d8de88059c5f", + "region_id" : "RegionOne", + "interface" : "internal", + "url" : "http://192.168.204.2:5000/v3", + "region" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:35357/v3", + "region_id" : "RegionOne", + "id" : "1f18e2b7c6a34493b86853b65917888e", + "interface" : "admin" + } + ], + "type" : "identity", + "name" : "keystone" + }, + { + "name" : "vim", + "type" : "nfv", + "endpoints" : [ + { + "url" : "http://128.224.180.14:4545", + "region" : "RegionOne", + "id" : "b33e317345e4480ab0786e4960995ec9", + "interface" : "public", + "region_id" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:4545", + "interface" : "internal", + "id" : "03c85828d5bf432ab04831aa65ac9c52", + "region_id" : "RegionOne" + }, + { + "id" : "067983abb061476cb53a9e23a740d98f", + "region_id" : "RegionOne", + "interface" : "admin", + "url" : "http://192.168.204.2:4545", + "region" : "RegionOne" + } + ], + "id" : "01636c856fc84988b38b9117eb4a8021" + }, + { + "name" : "aodh", + "type" : "alarming", + "id" : "eb269151d0e44744a5b5449657bdc61c", + "endpoints" : [ + { + "id" : "5bfc6c056e0244c493642eb82f6aaa11", + "region_id" : "RegionOne", + "interface" : "public", + "url" : "http://128.224.180.14:8042", + "region" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8042", + "region_id" : "RegionOne", + "id" : "ad69c7f76dce4089a195b9221ddbfb44", + "interface" : "internal" + }, + { + "interface" : "admin", + "id" : "3e8fcdfa7bcb40b0ae33c282adfcc9ff", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8042" + } + ] + }, + { + "name" : "sysinv", + "type" : "platform", + "endpoints" : [ + { + "region" : "RegionOne", + "url" : "http://128.224.180.14:6385/v1", + "interface" : "public", + "id" : "ba4ba8104590421b84672306c7e0e1f1", + "region_id" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:6385/v1", + "interface" : "internal", + "id" : "a1cba34b163f496ab1acd6e9b51e39a2", + "region_id" : "RegionOne" + }, + { + "url" : "http://192.168.204.2:6385/v1", + "region" : "RegionOne", + "id" : "7c171210a2c841a6a52a5713e316d6fc", + "interface" : "admin", + "region_id" : "RegionOne" + } + ], + "id" : "256bbad671f946fea543e6bd71f98875" + }, + { + "id" : "e84665dcce814c05b4c5084964547534", + "endpoints" : [ + { + "url" : "http://128.224.180.14:8000/v1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "region_id" : "RegionOne", + "id" : "b2ed1a23dc6944bea129c20861e0286a", + "interface" : "public" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8000/v1/fcca3cc49d5e42caae15459e27103efc", + "interface" : "internal", + "id" : "c4df7c6bc15646848eff35caf6ffea8e", + "region_id" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "61b3dabb761443a89ab549f437c05ab0", + "interface" : "admin", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8000/v1/fcca3cc49d5e42caae15459e27103efc" + } + ], + "name" : "heat-cfn", + "type" : "cloudformation" + }, + { + "id" : "823024424a014981a3721229491c0b1a", + "endpoints" : [ + { + "region" : "RegionOne", + "url" : "http://128.224.180.14:8776/v1/fcca3cc49d5e42caae15459e27103efc", + "region_id" : "RegionOne", + "id" : "4a52e4e54ff440789f9a797919c4a0f2", + "interface" : "public" + }, + { + "url" : "http://192.168.204.2:8776/v1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "id" : "d4f9a84476524a39844f0fce63f1022e", + "region_id" : "RegionOne", + "interface" : "internal" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v1/fcca3cc49d5e42caae15459e27103efc", + "interface" : "admin", + "id" : "81bf3810a8cc4697b68c6e93b5b8fe1f", + "region_id" : "RegionOne" + } + ], + "type" : "volume", + "name" : "cinder" + }, + { + "name" : "glance", + "type" : "image", + "endpoints" : [ + { + "id" : "bd930aba961946cfb1401bada56d55e3", + "region_id" : "RegionOne", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:9292" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:9292", + "id" : "c11da585f0b141b99d1e18bb9a607beb", + "region_id" : "RegionOne", + "interface" : "internal" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:9292", + "id" : "31b26c625a6a4fc7910dc5935155996e", + "interface" : "admin", + "region_id" : "RegionOne" + } + ], + "id" : "3b78cf039bc54d1bbb99ab3a4be15ef1" + }, + { + "id" : "b8701374bf254de1beee8a2c9ecc6b33", + "endpoints" : [ + { + "region_id" : "RegionOne", + "id" : "f7407f330c8b4577b1d377d3fab9c2f8", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:15491" + }, + { + "url" : "http://192.168.204.2:5491", + "region" : "RegionOne", + "interface" : "internal", + "id" : "0b37ce31a32f4b6fa5e1aa0d6c20680f", + "region_id" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "7b87ea72adf245e1991e9e0df29b7ea9", + "interface" : "admin", + "region" : "RegionOne", + "url" : "http://192.168.204.2:5491" + } + ], + "type" : "patching", + "name" : "patching" + }, + { + "id" : "0ec0923a58f04ffeb6fced3bbc5c0947", + "endpoints" : [ + { + "url" : "http://128.224.180.14:8774/v2.1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "id" : "13168b12da17451fb39630de67db168f", + "region_id" : "RegionOne", + "interface" : "public" + }, + { + "id" : "22dd6a44209f42d986b82e3aa6535f82", + "interface" : "internal", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8774/v2.1/fcca3cc49d5e42caae15459e27103efc" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8774/v2.1/fcca3cc49d5e42caae15459e27103efc", + "id" : "552a991ae501492f841c1b6e2ff38fc5", + "region_id" : "RegionOne", + "interface" : "admin" + } + ], + "type" : "compute", + "name" : "nova" + }, + { + "id" : "50b219650f1049b097b3f14e8c70cdf8", + "endpoints" : [ + { + "interface" : "public", + "id" : "5a4276cd6e4d43e883cf8640d4e13f7d", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://128.224.180.14:8776/v3/fcca3cc49d5e42caae15459e27103efc" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v3/fcca3cc49d5e42caae15459e27103efc", + "region_id" : "RegionOne", + "id" : "c796df3ca5a84fc18db5b43a55283953", + "interface" : "internal" + }, + { + "region_id" : "RegionOne", + "id" : "cf55c2b34d0049ba835a2e48b9ad0e2e", + "interface" : "admin", + "url" : "http://192.168.204.2:8776/v3/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne" + } + ], + "type" : "volumev3", + "name" : "cinderv3" + } + ], +} + +mock_auth_state = { + "body" : { + "token" : { + "is_domain" : "false", + "expires_at" : "2017-08-27T14:19:15.000000Z", + "issued_at" : "2017-08-27T13:19:15.000000Z", + "roles" : [ + { + "id" : "9fe2ff9ee4384b1894a90878d3e92bab", + "name" : "_member_" + }, + { + "id" : "b86a7e02935844b899d3d326f83c1b1f", + "name" : "admin" + }, + { + "name" : "heat_stack_owner", + "id" : "7de502236e954c8282de32e773fc052e" + } + ], + "methods" : [ + "password" + ], + "catalog" : mock_catalog_response['catalog'], + "project" : { + "name" : "admin", + "id" : "fcca3cc49d5e42caae15459e27103efc", + "domain" : { + "id" : "default", + "name" : "Default" + } + }, + "user" : { + "name" : "admin", + "id" : "9efb043c7629497a8028d7325ca1afb0", + "domain" : { + "id" : "default", + "name" : "Default" + } + }, + "audit_ids" : [ + "_ZWT10DtSZKRXIvIcxun7w" + ] + } + }, + "auth_token" : mock_token_id +} + + +class TestIdentityService(unittest.TestCase): + def setUp(self): + self.client = Client() + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + @mock.patch.object(VimDriverUtils, 'get_session') + @mock.patch.object(VimDriverUtils, 'get_auth_state') + @mock.patch.object(VimDriverUtils, 'update_token_cache') + def test_token(self, mock_update_token_cache, mock_get_auth_state, mock_get_session, mock_get_vim_info): + ''' + test API: get token + :param mock_update_token_cache: + :param mock_get_auth_state: + :param mock_get_session: + :param mock_get_vim_info: + :return: + ''' + + #mock VimDriverUtils APIs + mock_session_specs = ["get"] + mock_session_get_response = {'status':200} + mock_session = mock.Mock(name='mock_session', spec=mock_session_specs) + mock_session.get.return_value = mock_session_get_response + + mock_get_vim_info.return_value = mock_viminfo + mock_get_session.return_value = mock_session + mock_get_auth_state.return_value = json.dumps(mock_auth_state) + mock_update_token_cache.return_value = mock_token_id + + #simulate client to make the request + data ={} + response = self.client.post("/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/identity/v3/auth/tokens", data=data, format='json') + self.failUnlessEqual(status.HTTP_201_CREATED, response.status_code) + context = response.json() + + self.assertTrue(response['X-Subject-Token'] == mock_token_id) + self.assertTrue(context['token']['catalog'] != None) + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + @mock.patch.object(VimDriverUtils, 'get_session') + @mock.patch.object(VimDriverUtils, 'get_auth_state') + @mock.patch.object(VimDriverUtils, 'update_token_cache') + def test_tokensV2(self, mock_update_token_cache, mock_get_auth_state, + mock_get_session, mock_get_vim_info): + ''' + test API: get token + :param mock_update_token_cache: + :param mock_get_auth_state: + :param mock_get_session: + :param mock_get_vim_info: + :return: + ''' + + # mock VimDriverUtils APIs + mock_session_specs = ["get"] + mock_session_get_response = {'status': 200} + mock_session = mock.Mock(name='mock_session', + spec=mock_session_specs) + mock_session.get.return_value = mock_session_get_response + + mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO + mock_get_session.return_value = mock_session + mock_get_auth_state.return_value = json.dumps(mock_auth_state) + mock_update_token_cache.return_value = mock_info.MOCK_TOKEN_ID + + # simulate client to make the request + data = {} + response = self.client.post( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/identity/v2.0/tokens", + data=data, format='json') + self.failUnlessEqual(status.HTTP_200_OK, + response.status_code) + context = response.json() + + self.assertIsNotNone(context['access']['token']) + self.assertEqual(mock_info.MOCK_TOKEN_ID, + context['access']['token']["id"]) + self.assertIsNotNone(context['access']['serviceCatalog']) + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + @mock.patch.object(VimDriverUtils, 'get_session') + @mock.patch.object(VimDriverUtils, 'get_auth_state') + @mock.patch.object(VimDriverUtils, 'update_token_cache') + def test_token_with_tenantname(self, mock_update_token_cache, mock_get_auth_state, + mock_get_session, mock_get_vim_info): + ''' + test API: get token + :param mock_update_token_cache: + :param mock_get_auth_state: + :param mock_get_session: + :param mock_get_vim_info: + :return: + ''' + + # mock VimDriverUtils APIs + mock_session_specs = ["get"] + mock_session_get_response = {'status': 200} + mock_session = mock.Mock(name='mock_session', + spec=mock_session_specs) + mock_session.get.return_value = mock_session_get_response + + mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO + mock_get_session.return_value = mock_session + mock_get_auth_state.return_value = json.dumps(mock_auth_state) + mock_update_token_cache.return_value = mock_info.MOCK_TOKEN_ID + + # simulate client to make the request + token_data = { + "auth": { + "identity": { + "methods": ["password"], + "password": { + "user": { + "name": "demo", + "domain": {"name": "Default"}, + "password": "demo" + } + } + }, + "scope": { + "project": { + "domain": {"name":"Default"}, + "name": "Integration" + } + } + } + } + + response = self.client.post( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/identity/v3/auth/tokens", + data=json.dumps(token_data), content_type='application/json') + self.failUnlessEqual(status.HTTP_201_CREATED, + response.status_code) + context = response.json() + + self.assertEqual(mock_info.MOCK_TOKEN_ID, + response['X-Subject-Token']) + self.assertIsNotNone(context['token']['catalog']) + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + @mock.patch.object(VimDriverUtils, 'get_session') + @mock.patch.object(VimDriverUtils, 'get_auth_state') + @mock.patch.object(VimDriverUtils, 'update_token_cache') + def test_tokensV2_with_tenantname(self, mock_update_token_cache, mock_get_auth_state, + mock_get_session, mock_get_vim_info): + ''' + test API: get token + :param mock_update_token_cache: + :param mock_get_auth_state: + :param mock_get_session: + :param mock_get_vim_info: + :return: + ''' + + # mock VimDriverUtils APIs + mock_session_specs = ["get"] + mock_session_get_response = {'status': 200} + mock_session = mock.Mock(name='mock_session', + spec=mock_session_specs) + mock_session.get.return_value = mock_session_get_response + + mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO + mock_get_session.return_value = mock_session + mock_get_auth_state.return_value = json.dumps(mock_auth_state) + mock_update_token_cache.return_value = mock_info.MOCK_TOKEN_ID + + # simulate client to make the request + token_data = { + "auth": { + "tenantName": "Integration", + "passwordCredentials": { + "username": "demo", + "password": "demo" + } + } + } + + response = self.client.post( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/identity/v2.0/tokens", + data=json.dumps(token_data), content_type='application/json') + self.failUnlessEqual(status.HTTP_200_OK, + response.status_code) + context = response.json() + + self.assertIsNotNone(context['access']['token']) + self.assertEqual(mock_info.MOCK_TOKEN_ID, + context['access']['token']["id"]) + self.assertIsNotNone(context['access']['serviceCatalog']) + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + @mock.patch.object(VimDriverUtils, 'get_session') + @mock.patch.object(VimDriverUtils, 'get_auth_state') + @mock.patch.object(VimDriverUtils, 'update_token_cache') + def test_token_with_projectid(self, mock_update_token_cache, mock_get_auth_state, + mock_get_session, mock_get_vim_info): + ''' + test API: get token + :param mock_update_token_cache: + :param mock_get_auth_state: + :param mock_get_session: + :param mock_get_vim_info: + :return: + ''' + + # mock VimDriverUtils APIs + mock_session_specs = ["get"] + mock_session_get_response = {'status': 200} + mock_session = mock.Mock(name='mock_session', + spec=mock_session_specs) + mock_session.get.return_value = mock_session_get_response + + mock_get_vim_info.return_value = mock_info.MOCK_VIM_INFO + mock_get_session.return_value = mock_session + mock_get_auth_state.return_value = json.dumps(mock_auth_state) + mock_update_token_cache.return_value = mock_info.MOCK_TOKEN_ID + + # simulate client to make the request + token_data = { + "auth": { + "identity": { + "methods": ["password"], + "password": { + "user": { + "name": "demo", + "password": "demo" + } + } + }, + "scope": { + "project": {"id": "dd327af0542e47d7853e0470fe9ad625"} + } + } + } + + response = self.client.post( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/identity/v3/auth/tokens", + data=json.dumps(token_data), content_type='application/json') + self.failUnlessEqual(status.HTTP_201_CREATED, + response.status_code) + context = response.json() + + self.assertEqual(mock_info.MOCK_TOKEN_ID, + response['X-Subject-Token']) + self.assertIsNotNone(context['token']['catalog']) + diff --git a/pike/pike/proxy/tests/test_service_proxy.py b/pike/pike/proxy/tests/test_service_proxy.py new file mode 100644 index 00000000..0449afd5 --- /dev/null +++ b/pike/pike/proxy/tests/test_service_proxy.py @@ -0,0 +1,852 @@ +# 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 copy +import json + +from django.test import Client +import mock +from rest_framework import status +import unittest + + +from newton_base.util import VimDriverUtils + +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": "pike", + "vimId": "windriver-hudson-dc_RegionOne", + 'cloud_owner':'windriver-hudson-dc', + 'cloud_region_id':'RegionOne', + 'cloud_extra_info':'', + 'insecure':'True', +} + +MOCK_TOKEN_ID="1a62b3971d774404a504c5d9a3e506e3" + +MOCK_CATALOG_RESPONSE = { + "catalog" : [ + { + "id" : "99aefcc82a9246f98f8c281e61ffc754", + "endpoints" : [ + { + "region" : "RegionOne", + "url" : "http://128.224.180.14:9696", + "id" : "39583c1508ad4b71b380570a745ee10a", + "interface" : "public", + "region_id" : "RegionOne" + }, + { + "url" : "http://192.168.204.2:9696", + "region" : "RegionOne", + "id" : "37e8d07ba24e4b8f93490c9daaba06e2", + "interface" : "internal", + "region_id" : "RegionOne" + }, + { + "interface" : "admin", + "id" : "7eee4ca98d444b1abb00a50d4b89373f", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://192.168.204.2:9696" + } + ], + "name" : "neutron", + "type" : "network" + }, + { + "endpoints" : [ + { + "interface" : "public", + "id" : "10496738fa374295a4a88a63b81a1589", + "region_id" : "RegionOne", + "url" : "http://128.224.180.14:8777", + "region" : "RegionOne" + }, + { + "id" : "02dcb8c0bd464c4489fa0a0c9f28571f", + "region_id" : "RegionOne", + "interface" : "internal", + "url" : "http://192.168.204.2:8777", + "region" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "8a73b0d3743b4e78b87614690f6e97fe", + "interface" : "admin", + "url" : "http://192.168.204.2:8777", + "region" : "RegionOne" + } + ], + "id" : "d131054da83f4c93833799747a0f4709", + "name" : "ceilometer", + "type" : "metering" + }, + { + "type" : "volumev2", + "name" : "cinderv2", + "endpoints" : [ + { + "id" : "35a67ad36f0447d19c9662babf7cf609", + "interface" : "public", + "region_id" : "RegionOne", + "url" : "http://128.224.180.14:8776/v2/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v2/fcca3cc49d5e42caae15459e27103efc", + "id" : "c6ea42052268420fa2c8d351ee68c922", + "interface" : "internal", + "region_id" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "91cb24853dc3450d847b0c286a2e44ea", + "interface" : "admin", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v2/fcca3cc49d5e42caae15459e27103efc" + } + ], + "id" : "40440057102440739c30be10a66bc5d1" + }, + { + "name" : "heat", + "type" : "orchestration", + "id" : "35300cce88db4bd4bb5a72ffe3b88b00", + "endpoints" : [ + { + "id" : "58999d7b4a94439089ecfb2aca2d7f6c", + "region_id" : "RegionOne", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:8004/v1/fcca3cc49d5e42caae15459e27103efc" + }, + { + "url" : "http://192.168.204.2:8004/v1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "interface" : "internal", + "id" : "1e0ee1a2aef84802b921d422372a567e", + "region_id" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8004/v1/fcca3cc49d5e42caae15459e27103efc", + "id" : "17661bf4859741b8a43a461dedad1871", + "region_id" : "RegionOne", + "interface" : "admin" + } + ] + }, + { + "id" : "08dc6912aea64c01925012c8a6df250a", + "endpoints" : [ + { + "id" : "02792c4eed77486083f9b2e52d7b94b0", + "region_id" : "RegionOne", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:5000/v3" + }, + { + "id" : "b6d5cad394b94309ae40d8de88059c5f", + "region_id" : "RegionOne", + "interface" : "internal", + "url" : "http://192.168.204.2:5000/v3", + "region" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:35357/v3", + "region_id" : "RegionOne", + "id" : "1f18e2b7c6a34493b86853b65917888e", + "interface" : "admin" + } + ], + "type" : "identity", + "name" : "keystone" + }, + { + "name" : "vim", + "type" : "nfv", + "endpoints" : [ + { + "url" : "http://128.224.180.14:4545", + "region" : "RegionOne", + "id" : "b33e317345e4480ab0786e4960995ec9", + "interface" : "public", + "region_id" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:4545", + "interface" : "internal", + "id" : "03c85828d5bf432ab04831aa65ac9c52", + "region_id" : "RegionOne" + }, + { + "id" : "067983abb061476cb53a9e23a740d98f", + "region_id" : "RegionOne", + "interface" : "admin", + "url" : "http://192.168.204.2:4545", + "region" : "RegionOne" + } + ], + "id" : "01636c856fc84988b38b9117eb4a8021" + }, + { + "name" : "aodh", + "type" : "alarming", + "id" : "eb269151d0e44744a5b5449657bdc61c", + "endpoints" : [ + { + "id" : "5bfc6c056e0244c493642eb82f6aaa11", + "region_id" : "RegionOne", + "interface" : "public", + "url" : "http://128.224.180.14:8042", + "region" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8042", + "region_id" : "RegionOne", + "id" : "ad69c7f76dce4089a195b9221ddbfb44", + "interface" : "internal" + }, + { + "interface" : "admin", + "id" : "3e8fcdfa7bcb40b0ae33c282adfcc9ff", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8042" + } + ] + }, + { + "name" : "sysinv", + "type" : "platform", + "endpoints" : [ + { + "region" : "RegionOne", + "url" : "http://128.224.180.14:6385/v1", + "interface" : "public", + "id" : "ba4ba8104590421b84672306c7e0e1f1", + "region_id" : "RegionOne" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:6385/v1", + "interface" : "internal", + "id" : "a1cba34b163f496ab1acd6e9b51e39a2", + "region_id" : "RegionOne" + }, + { + "url" : "http://192.168.204.2:6385/v1", + "region" : "RegionOne", + "id" : "7c171210a2c841a6a52a5713e316d6fc", + "interface" : "admin", + "region_id" : "RegionOne" + } + ], + "id" : "256bbad671f946fea543e6bd71f98875" + }, + { + "id" : "e84665dcce814c05b4c5084964547534", + "endpoints" : [ + { + "url" : "http://128.224.180.14:8000/v1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "region_id" : "RegionOne", + "id" : "b2ed1a23dc6944bea129c20861e0286a", + "interface" : "public" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8000/v1/fcca3cc49d5e42caae15459e27103efc", + "interface" : "internal", + "id" : "c4df7c6bc15646848eff35caf6ffea8e", + "region_id" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "61b3dabb761443a89ab549f437c05ab0", + "interface" : "admin", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8000/v1/fcca3cc49d5e42caae15459e27103efc" + } + ], + "name" : "heat-cfn", + "type" : "cloudformation" + }, + { + "id" : "823024424a014981a3721229491c0b1a", + "endpoints" : [ + { + "region" : "RegionOne", + "url" : "http://128.224.180.14:8776/v1/fcca3cc49d5e42caae15459e27103efc", + "region_id" : "RegionOne", + "id" : "4a52e4e54ff440789f9a797919c4a0f2", + "interface" : "public" + }, + { + "url" : "http://192.168.204.2:8776/v1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "id" : "d4f9a84476524a39844f0fce63f1022e", + "region_id" : "RegionOne", + "interface" : "internal" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v1/fcca3cc49d5e42caae15459e27103efc", + "interface" : "admin", + "id" : "81bf3810a8cc4697b68c6e93b5b8fe1f", + "region_id" : "RegionOne" + } + ], + "type" : "volume", + "name" : "cinder" + }, + { + "name" : "glance", + "type" : "image", + "endpoints" : [ + { + "id" : "bd930aba961946cfb1401bada56d55e3", + "region_id" : "RegionOne", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:9292" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:9292", + "id" : "c11da585f0b141b99d1e18bb9a607beb", + "region_id" : "RegionOne", + "interface" : "internal" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:9292", + "id" : "31b26c625a6a4fc7910dc5935155996e", + "interface" : "admin", + "region_id" : "RegionOne" + } + ], + "id" : "3b78cf039bc54d1bbb99ab3a4be15ef1" + }, + { + "id" : "b8701374bf254de1beee8a2c9ecc6b33", + "endpoints" : [ + { + "region_id" : "RegionOne", + "id" : "f7407f330c8b4577b1d377d3fab9c2f8", + "interface" : "public", + "region" : "RegionOne", + "url" : "http://128.224.180.14:15491" + }, + { + "url" : "http://192.168.204.2:5491", + "region" : "RegionOne", + "interface" : "internal", + "id" : "0b37ce31a32f4b6fa5e1aa0d6c20680f", + "region_id" : "RegionOne" + }, + { + "region_id" : "RegionOne", + "id" : "7b87ea72adf245e1991e9e0df29b7ea9", + "interface" : "admin", + "region" : "RegionOne", + "url" : "http://192.168.204.2:5491" + } + ], + "type" : "patching", + "name" : "patching" + }, + { + "id" : "0ec0923a58f04ffeb6fced3bbc5c0947", + "endpoints" : [ + { + "url" : "http://128.224.180.14:8774/v2.1/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne", + "id" : "13168b12da17451fb39630de67db168f", + "region_id" : "RegionOne", + "interface" : "public" + }, + { + "id" : "22dd6a44209f42d986b82e3aa6535f82", + "interface" : "internal", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://192.168.204.2:8774/v2.1/fcca3cc49d5e42caae15459e27103efc" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8774/v2.1/fcca3cc49d5e42caae15459e27103efc", + "id" : "552a991ae501492f841c1b6e2ff38fc5", + "region_id" : "RegionOne", + "interface" : "admin" + } + ], + "type" : "compute", + "name" : "nova" + }, + { + "id" : "50b219650f1049b097b3f14e8c70cdf8", + "endpoints" : [ + { + "interface" : "public", + "id" : "5a4276cd6e4d43e883cf8640d4e13f7d", + "region_id" : "RegionOne", + "region" : "RegionOne", + "url" : "http://128.224.180.14:8776/v3/fcca3cc49d5e42caae15459e27103efc" + }, + { + "region" : "RegionOne", + "url" : "http://192.168.204.2:8776/v3/fcca3cc49d5e42caae15459e27103efc", + "region_id" : "RegionOne", + "id" : "c796df3ca5a84fc18db5b43a55283953", + "interface" : "internal" + }, + { + "region_id" : "RegionOne", + "id" : "cf55c2b34d0049ba835a2e48b9ad0e2e", + "interface" : "admin", + "url" : "http://192.168.204.2:8776/v3/fcca3cc49d5e42caae15459e27103efc", + "region" : "RegionOne" + } + ], + "type" : "volumev3", + "name" : "cinderv3" + } + ] +} + +MOCK_AUTH_STATE = { + "body" : { + "token" : { + "is_domain" : "false", + "expires_at" : "2017-08-27T14:19:15.000000Z", + "issued_at" : "2017-08-27T13:19:15.000000Z", + "roles" : [ + { + "id" : "9fe2ff9ee4384b1894a90878d3e92bab", + "name" : "_member_" + }, + { + "id" : "b86a7e02935844b899d3d326f83c1b1f", + "name" : "admin" + }, + { + "name" : "heat_stack_owner", + "id" : "7de502236e954c8282de32e773fc052e" + } + ], + "methods" : [ + "password" + ], + "catalog" : MOCK_CATALOG_RESPONSE['catalog'], + "project" : { + "name" : "admin", + "id" : "fcca3cc49d5e42caae15459e27103efc", + "domain" : { + "id" : "default", + "name" : "Default" + } + }, + "user" : { + "name" : "admin", + "id" : "9efb043c7629497a8028d7325ca1afb0", + "domain" : { + "id" : "default", + "name" : "Default" + } + }, + "audit_ids" : [ + "_ZWT10DtSZKRXIvIcxun7w" + ] + } + }, + "auth_token" : MOCK_TOKEN_ID +} + +MOCK_INTERNAL_METADATA_CATALOG = { + "identity" : { + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/identity", + "prefix" : "http://128.224.180.14:5000", + "suffix" : "v3" + }, + "patching" : { + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/patching", + "suffix" : "", + "prefix" : "http://128.224.180.14:15491" + }, + "orchestration" : { + "suffix" : "v1/fcca3cc49d5e42caae15459e27103efc", + "prefix" : "http://128.224.180.14:8004", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/orchestration" + }, + "volume" : { + "prefix" : "http://128.224.180.14:8776", + "suffix" : "v1/fcca3cc49d5e42caae15459e27103efc", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/volume" + }, + "metering" : { + "suffix" : "", + "prefix" : "http://128.224.180.14:8777", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/metering" + }, + "volumev3" : { + "prefix" : "http://128.224.180.14:8776", + "suffix" : "v3/fcca3cc49d5e42caae15459e27103efc", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/volumev3" + }, + "compute" : { + "suffix" : "v2.1/fcca3cc49d5e42caae15459e27103efc", + "prefix" : "http://128.224.180.14:8774", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute" + }, + "platform" : { + "prefix" : "http://128.224.180.14:6385", + "suffix" : "v1", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/platform" + }, + "nfv" : { + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/nfv", + "prefix" : "http://128.224.180.14:4545", + "suffix" : "" + }, + "volumev2" : { + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/volumev2", + "suffix" : "v2/fcca3cc49d5e42caae15459e27103efc", + "prefix" : "http://128.224.180.14:8776" + }, + "image" : { + "suffix" : "", + "prefix" : "http://128.224.180.14:9292", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/image" + }, + "network" : { + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/network", + "prefix" : "http://128.224.180.14:9696", + "suffix" : "" + }, + "alarming" : { + "suffix" : "", + "prefix" : "http://128.224.180.14:8042", + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/alarming" + }, + "cloudformation" : { + "proxy_prefix" : "http://172.16.77.20:9003/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/cloudformation", + "prefix" : "http://128.224.180.14:8000", + "suffix" : "v1/fcca3cc49d5e42caae15459e27103efc" + } +} + + +MOCK_GET_SERVERS_RESPONSE = { + "servers" : [ + { + "links" : [ + { + "href" : "http://128.224.180.14:8774/v2.1/fcca3cc49d5e42caae15459e27103efc/servers/b2581b5c-7c56-4564-819d-fe7a2ce9c261", + "rel" : "self" + }, + { + "href" : "http://128.224.180.14:8774/fcca3cc49d5e42caae15459e27103efc/servers/b2581b5c-7c56-4564-819d-fe7a2ce9c261", + "rel" : "bookmark" + } + ], + "id" : "b2581b5c-7c56-4564-819d-fe7a2ce9c261", + "name" : "t1" + }, + { + "id" : "ff7b51ca-a272-45f4-b54c-e40b8099e67d", + "name" : "t2", + "links" : [ + { + "rel" : "self", + "href" : "http://128.224.180.14:8774/v2.1/fcca3cc49d5e42caae15459e27103efc/servers/ff7b51ca-a272-45f4-b54c-e40b8099e67d" + }, + { + "rel" : "bookmark", + "href" : "http://128.224.180.14:8774/fcca3cc49d5e42caae15459e27103efc/servers/ff7b51ca-a272-45f4-b54c-e40b8099e67d" + } + ] + } + ] +} + +MOCK_POST_SERVER_REQUEST = { + "server" : { + "accessIPv4": "1.2.3.4", + "accessIPv6": "80fe::", + "name" : "new-server-test", + "imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b", + "flavorRef" : "1", + "availability_zone": "nova", + "OS-DCF:diskConfig": "AUTO", + "metadata" : { + "My Server Name" : "Apache1" + }, + "personality": [ + { + "path": "/etc/banner.txt", + "contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 b25zLiINCg0KLVJpY2hhcmQgQmFjaA==" + } + ], + "security_groups": [ + { + "name": "default" + } + ], + "user_data" : "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==" + }, + "OS-SCH-HNT:scheduler_hints": { + "same_host": "48e6a9f6-30af-47e0-bc04-acaed113bb4e" + } +} + +MOCK_POST_SERVER_RESPONSE = { + "server": { + "OS-DCF:diskConfig": "AUTO", + "adminPass": "6NpUwoz2QDRN", + "id": "f5dc173b-6804-445a-a6d8-c705dad5b5eb", + "links": [ + { + "href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/servers/f5dc173b-6804-445a-a6d8-c705dad5b5eb", + "rel": "self" + }, + { + "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/f5dc173b-6804-445a-a6d8-c705dad5b5eb", + "rel": "bookmark" + } + ], + "security_groups": [ + { + "name": "default" + } + ] + } +} + + +MOCK_PATCH_IMAGE_REQUEST = [ + { + "op": "replace", + "path": "/name", + "value": "Fedora 17" + }, + { + "op": "replace", + "path": "/tags", + "value": [ + "fedora", + "beefy" + ] + } +] + +MOCK_PATCH_IMAGE_RESPONSE = { + "checksum": "710544e7f0c828b42f51207342622d33", + "container_format": "ovf", + "created_at": "2016-06-29T16:13:07Z", + "disk_format": "vhd", + "file": "/v2/images/2b61ed2b-f800-4da0-99ff-396b742b8646/file", + "id": "2b61ed2b-f800-4da0-99ff-396b742b8646", + "min_disk": 20, + "min_ram": 512, + "name": "Fedora 17", + "owner": "02a7fb2dd4ef434c8a628c511dcbbeb6", + "protected": "false", + "schema": "/v2/schemas/image", + "self": "/v2/images/2b61ed2b-f800-4da0-99ff-396b742b8646", + "size": 21909, + "status": "active", + "tags": [ + "beefy", + "fedora" + ], + "updated_at": "2016-07-25T14:48:18Z", + "virtual_size": "", + "visibility": "private" +} + + +class MockResponse(object): + status_code = 200 + content = '' + + def json(self): + pass + + +class TestServiceProxy(unittest.TestCase): + def setUp(self): + self.client = Client() + + @mock.patch.object(VimDriverUtils, 'get_session') + @mock.patch.object(VimDriverUtils, 'get_token_cache') + @mock.patch.object(VimDriverUtils, 'get_vim_info') + def test_get_token(self, mock_get_vim_info, mock_get_token_cache, mock_get_session): + mock_session_specs = ["head"] + mock_session = mock.Mock(name='mock_session', spec=mock_session_specs) + mock_get_servers_response_obj = mock.Mock(spec=MockResponse) + mock_get_servers_response_obj.status_code=200 + mock_get_servers_response_obj.content = MOCK_GET_SERVERS_RESPONSE + mock_get_servers_response_obj.json.return_value=MOCK_GET_SERVERS_RESPONSE + mock_session.head.return_value = mock_get_servers_response_obj + + mock_get_vim_info.return_value = MOCK_VIM_INFO + mock_get_session.return_value = mock_session + mock_get_token_cache.return_value = (json.dumps(MOCK_AUTH_STATE),json.dumps(MOCK_INTERNAL_METADATA_CATALOG)) + response = self.client.head( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute/v2.1/fcca3cc49d5e42caae15459e27103efc/servers", + {}, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + self.assertEquals(status.HTTP_200_OK, response.status_code) + + def test_unauthorized_access(self): + response = self.client.get( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute/v2.1/fcca3cc49d5e42caae15459e27103efc/servers") + self.assertEquals(status.HTTP_403_FORBIDDEN, response.status_code) + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + def test_expired_auth_token(self, mock_get_vim_info): + mock_get_vim_info.return_value = MOCK_VIM_INFO + + response = self.client.get( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute/v2.1/fcca3cc49d5e42caae15459e27103efc/servers", + {}, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + self.assertEquals(status.HTTP_403_FORBIDDEN, response.status_code) + + @mock.patch.object(VimDriverUtils, 'get_token_cache') + @mock.patch.object(VimDriverUtils, 'get_vim_info') + def test_request_without_servicetype(self, mock_get_vim_info, mock_get_token_cache): + mock_get_vim_info.return_value = MOCK_VIM_INFO + mock_get_token_cache.return_value = (json.dumps(MOCK_AUTH_STATE), {}) + servicetype = "compute" + url = ("/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/" + servicetype + + "/v2.1/fcca3cc49d5e42caae15459e27103efc/servers") + response = self.client.get(url, {}, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + self.assertEquals(status.HTTP_500_INTERNAL_SERVER_ERROR, response.status_code) + + metadata_catalog = copy.deepcopy(MOCK_INTERNAL_METADATA_CATALOG) + metadata_catalog[servicetype] = None + mock_get_token_cache.return_value = (json.dumps(MOCK_AUTH_STATE), json.dumps(metadata_catalog)) + + response = self.client.get(url, {}, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + self.assertEquals(status.HTTP_500_INTERNAL_SERVER_ERROR, response.status_code) + + metadata_catalog = copy.deepcopy(MOCK_INTERNAL_METADATA_CATALOG) + metadata_catalog[servicetype]['prefix'] = None + metadata_catalog[servicetype]['proxy_prefix'] = None + mock_get_token_cache.return_value = (json.dumps(MOCK_AUTH_STATE), json.dumps(metadata_catalog)) + + response = self.client.get(url, {}, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + self.assertEquals(status.HTTP_500_INTERNAL_SERVER_ERROR, response.status_code) + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + @mock.patch.object(VimDriverUtils, 'get_session') + @mock.patch.object(VimDriverUtils, 'get_auth_state') + @mock.patch.object(VimDriverUtils, 'update_token_cache') + @mock.patch.object(VimDriverUtils, 'get_token_cache') + def test_crud_resources(self, mock_get_token_cache, mock_update_token_cache, mock_get_auth_state, mock_get_session, mock_get_vim_info): + ''' + Test service proxy API: GET + + :param mock_get_token_cache: + :param mock_update_token_cache: + :param mock_get_auth_state: + :param mock_get_session: + :param mock_get_vim_info: + :return: + ''' + + #mock VimDriverUtils APIs + mock_session_specs = ["get", "post", "put", "patch", "delete"] + + mock_get_servers_response_obj = mock.Mock(spec=MockResponse) + mock_get_servers_response_obj.status_code=200 + mock_get_servers_response_obj.content = MOCK_GET_SERVERS_RESPONSE + mock_get_servers_response_obj.json.return_value=MOCK_GET_SERVERS_RESPONSE + + mock_post_server_response_obj = mock.Mock(spec=MockResponse) + mock_post_server_response_obj.status_code=202 + mock_post_server_response_obj.content = MOCK_POST_SERVER_RESPONSE + mock_post_server_response_obj.json.return_value=MOCK_POST_SERVER_RESPONSE + + mock_patch_server_response_obj = mock.Mock(spec=MockResponse) + mock_patch_server_response_obj.status_code=202 + mock_patch_server_response_obj.content = MOCK_PATCH_IMAGE_REQUEST + mock_patch_server_response_obj.json.return_value=MOCK_PATCH_IMAGE_REQUEST + + mock_delete_server_response_obj = mock.Mock(spec=MockResponse) + mock_delete_server_response_obj.status_code=204 + + mock_session = mock.Mock(name='mock_session', spec=mock_session_specs) + mock_session.get.return_value = mock_get_servers_response_obj + mock_session.post.return_value = mock_post_server_response_obj + mock_session.patch.return_value = mock_patch_server_response_obj + mock_session.delete.return_value = mock_delete_server_response_obj + + mock_get_vim_info.return_value = MOCK_VIM_INFO + mock_get_session.return_value = mock_session + mock_get_auth_state.return_value = json.dumps(MOCK_AUTH_STATE) + mock_update_token_cache.return_value = MOCK_TOKEN_ID + mock_get_token_cache.return_value = (json.dumps(MOCK_AUTH_STATE),json.dumps(MOCK_INTERNAL_METADATA_CATALOG)) + + # Create resource + response = self.client.post( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute/v2.1/fcca3cc49d5e42caae15459e27103efc/servers", + MOCK_POST_SERVER_REQUEST, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + + self.assertEquals(status.HTTP_202_ACCEPTED, response.status_code) + context = response.json() + self.assertEquals(MOCK_TOKEN_ID, response['X-Subject-Token']) + self.assertIsNotNone(context['server']) + + # Retrieve resource + response = self.client.get( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute/v2.1/fcca3cc49d5e42caae15459e27103efc/servers", + {}, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + self.assertEquals(status.HTTP_200_OK, response.status_code) + context = response.json() + + self.assertEquals(MOCK_TOKEN_ID, response['X-Subject-Token']) + self.assertIsNotNone(context['servers']) + + # Update resource + response = self.client.get( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute/v2.1/fcca3cc49d5e42caae15459e27103efc/servers", + {}, HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + self.assertEquals(status.HTTP_200_OK, response.status_code) + context = response.json() + + self.assertEquals(MOCK_TOKEN_ID, response['X-Subject-Token']) + self.assertIsNotNone(context['servers']) + + #simulate client to make the request + response = self.client.delete( + "/api/multicloud-pike/v0/windriver-hudson-dc_RegionOne/compute/v2.1/fcca3cc49d5e42caae15459e27103efc/servers/324dfb7d-f4a9-419a-9a19-237df04b443b", + HTTP_X_AUTH_TOKEN=MOCK_TOKEN_ID) + + self.assertEquals(status.HTTP_204_NO_CONTENT, response.status_code) + self.assertEquals(MOCK_TOKEN_ID, response['X-Subject-Token']) diff --git a/pike/pike/proxy/urls.py b/pike/pike/proxy/urls.py new file mode 100644 index 00000000..3dafd528 --- /dev/null +++ b/pike/pike/proxy/urls.py @@ -0,0 +1,39 @@ +# 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. + +from django.conf.urls import url +from rest_framework.urlpatterns import format_suffix_patterns + +from pike.proxy.views import identityV3 +from pike.proxy.views import services +from newton_base.proxy import dnsaasdelegate + +urlpatterns = [ + url(r'^identity/v3/auth/tokens/?$', + identityV3.Tokens.as_view()), + url(r'^identity/v3/?$', + identityV3.Tokens.as_view()), + url(r'^identity/v2.0/?', + identityV3.TokensV2.as_view()), + url(r'^identity/v2.0/tokens/?$', + identityV3.TokensV2.as_view()), + url(r'^identity/v2.0/tenants/?$', + services.GetTenants.as_view()), + url(r'dns-delegate/(?P<requri>[0-9a-zA-Z./_-]*)$', + dnsaasdelegate.DnsaasDelegate.as_view()), + url(r'^(?P<servicetype>[0-9a-zA-Z_-]{,18})/(?P<requri>[0-9a-zA-Z./_-]*)$', + services.Services.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/pike/pike/proxy/views/__init__.py b/pike/pike/proxy/views/__init__.py new file mode 100644 index 00000000..741e0afb --- /dev/null +++ b/pike/pike/proxy/views/__init__.py @@ -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/proxy/views/identityV3.py b/pike/pike/proxy/views/identityV3.py new file mode 100644 index 00000000..e87ea86e --- /dev/null +++ b/pike/pike/proxy/views/identityV3.py @@ -0,0 +1,34 @@ +# 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 + +from django.conf import settings +from newton_base.proxy import identityV3 as newton_identityV3 + +logger = logging.getLogger(__name__) + +# DEBUG=True + +class Tokens(newton_identityV3.Tokens): + + def __init__(self): + self.proxy_prefix = settings.MULTICLOUD_PREFIX + self._logger = logger + +class TokensV2(newton_identityV3.TokensV2): + + def __init__(self): + self.proxy_prefix = settings.MULTICLOUD_PREFIX + self._logger = logger diff --git a/pike/pike/proxy/views/services.py b/pike/pike/proxy/views/services.py new file mode 100644 index 00000000..358ac3d6 --- /dev/null +++ b/pike/pike/proxy/views/services.py @@ -0,0 +1,46 @@ +# 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 + +from rest_framework import status + +from django.conf import settings +from newton_base.proxy import services as newton_services + +logger = logging.getLogger(__name__) + +# DEBUG=True + +class Services(newton_services.Services): + + def __init__(self): + self._logger = logger + + +class GetTenants(newton_services.GetTenants): + ''' + Backward compatible API for /v2.0/tenants + ''' + + def __init__(self): + self._logger = logger + + def get(self, request, vimid="", servicetype="identity", requri='v3/projects'): + self._logger.debug("GetTenants--get::META> %s" % request.META) + self._logger.debug("GetTenants--get::data> %s" % request.data) + self._logger.debug("GetTenants--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + + return super(GetTenants,self).get(request, vimid, servicetype, requri) diff --git a/pike/pike/registration/__init__.py b/pike/pike/registration/__init__.py new file mode 100644 index 00000000..741e0afb --- /dev/null +++ b/pike/pike/registration/__init__.py @@ -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 index 00000000..741e0afb --- /dev/null +++ b/pike/pike/registration/tests/__init__.py @@ -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 index 00000000..3893fcaf --- /dev/null +++ b/pike/pike/registration/tests/test_registration.py @@ -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 + +PIKE_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 = PIKE_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 index 00000000..741e0afb --- /dev/null +++ b/pike/pike/registration/views/__init__.py @@ -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 index 00000000..fdb2b0fe --- /dev/null +++ b/pike/pike/registration/views/registration.py @@ -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 diff --git a/pike/pike/urls.py b/pike/pike/urls.py index 6ff32d91..2796208d 100644 --- a/pike/pike/urls.py +++ b/pike/pike/urls.py @@ -14,13 +14,19 @@ 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')), + url(r'^api/multicloud-pike/v0/(?P<vimid>[0-9a-zA-Z_-]+)/', + include('pike.proxy.urls')), + ] |