From e487cd90e97edb6b085e03de93b169756b41b882 Mon Sep 17 00:00:00 2001 From: Bin Yang Date: Mon, 9 Oct 2017 17:42:08 +0800 Subject: Fix bug in identity v2.0 proxy Change-Id: I9e25a1b6438f602e38c13cc1282daa9b10118388 Issue-Id: MULTICLOUD-109 Signed-off-by: Bin Yang --- newton/newton/proxy/urls.py | 6 +++-- newton/newton/proxy/views/identityV3.py | 43 +++++++++++++++++++++++++++++--- newton/newton/pub/msapi/extsys.py | 43 ++++++++++++++++---------------- newton/newton/pub/tests/test_extsys.py | 25 ++++++++++++------- newton/newton/pub/tests/test_restcall.py | 11 ++++---- newton/newton/pub/utils/restcall.py | 28 +++++++++++++++------ ocata/ocata/proxy/urls.py | 8 +++--- ocata/run.sh | 8 ++++++ windriver/run.sh | 8 ++++++ windriver/titanium_cloud/proxy/urls.py | 2 ++ 10 files changed, 131 insertions(+), 51 deletions(-) diff --git a/newton/newton/proxy/urls.py b/newton/newton/proxy/urls.py index ee2da591..556cc4e6 100644 --- a/newton/newton/proxy/urls.py +++ b/newton/newton/proxy/urls.py @@ -23,9 +23,11 @@ urlpatterns = [ # identityV2.Tokens.as_view()), url(r'^identity/v3/auth/tokens$', identityV3.Tokens.as_view()), - url(r'^identity/v2.0/tokens$', + url(r'^identity/v2.0/?$', identityV3.TokensV2.as_view()), - url(r'^identity/v2.0/tenants$', + url(r'^identity/v2.0/tokens/?$', + identityV3.TokensV2.as_view()), + url(r'^identity/v2.0/tenants/?$', services.GetTenants.as_view()), url(r'^(?P[0-9a-zA-Z_-]{,18})/(?P[0-9a-zA-Z./_-]*)$', services.Services.as_view()), diff --git a/newton/newton/proxy/views/identityV3.py b/newton/newton/proxy/views/identityV3.py index bf63ad6a..3fa124c9 100644 --- a/newton/newton/proxy/views/identityV3.py +++ b/newton/newton/proxy/views/identityV3.py @@ -50,14 +50,26 @@ class Tokens(APIView): resp_body = None try: tenant_name = request.data.get("tenant_name") + tenant_id = request.data.get("tenant_id") #backward support for keystone v2.0 API if not tenant_name and request.data.get("auth"): - tenant_name = request.data["auth"].get("tenant_name") + tenant_name = request.data["auth"].get("tenantName") + + #keystone v3 API + if not tenant_name and request.data.get("auth") \ + and request.data["auth"].get("scope")\ + and request["auth"]["scope"].get("project"): + if request["auth"]["scope"]["project"].get("name"): + tenant_name = request["auth"]["scope"]["project"].get("name") + else: + tenant_id = request["auth"]["scope"]["project"].get("id") + + # prepare request resource to vim instance vim = VimDriverUtils.get_vim_info(vimid) - sess = VimDriverUtils.get_session(vim, tenantname = tenant_name) + sess = VimDriverUtils.get_session(vim, tenantname = tenant_name, tenantid=tenant_id) tmp_auth_state = VimDriverUtils.get_auth_state(vim, sess) tmp_auth_info = json.loads(tmp_auth_state) @@ -85,6 +97,21 @@ class Tokens(APIView): return Response(data={'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) +version_detail = { + "version": { + "status": "stable", + "updated": "2014-04-17T00:00:00Z", + "media-types": [ + { + "base": "application/json", + "type": "application/vnd.openstack.identity-v2.0+json" + } + ], + "id": "v2.0", + "links": [ + ] + } +} class TokensV2(Tokens): ''' @@ -95,6 +122,11 @@ class TokensV2(Tokens): self.proxy_prefix = config.MULTICLOUD_PREFIX self._logger = logger + def get(self, request, vimid=""): + self._logger.debug("TokensV2--get::META> %s" % request.META) + + return Response(data=version_detail, status=status.HTTP_200_OK) + def post(self, request, vimid=""): self._logger.debug("TokensV2--post::META> %s" % request.META) self._logger.debug("TokensV2--post::data> %s" % request.data) @@ -142,11 +174,14 @@ class TokensV2(Tokens): "tenant" : v3_token["project"], }, "serviceCatalog": v2_catalog, - # "user": v3_token["user"], + "user": v3_token["user"], } } - return Response(data=v2_content, status=resp.status_code) + return Response(data=v2_content, + status=status.HTTP_200_OK \ + if resp.status_code==status.HTTP_201_CREATED \ + else resp.status_code) else: return resp diff --git a/newton/newton/pub/msapi/extsys.py b/newton/newton/pub/msapi/extsys.py index aa6a159c..0f08adb4 100644 --- a/newton/newton/pub/msapi/extsys.py +++ b/newton/newton/pub/msapi/extsys.py @@ -25,7 +25,7 @@ def get_vim_by_id(vim_id): if cloud_owner and cloud_region_id: retcode, content, status_code = \ - restcall.req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" + restcall.req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s?depth=1" % (cloud_owner,cloud_region_id),"GET") if retcode != 0: logger.error("Status code is %s, detail is %s.", status_code, content) @@ -35,16 +35,17 @@ def get_vim_by_id(vim_id): tmp_viminfo = json.JSONDecoder().decode(content) #assume esr-system-info-id is composed by {cloud-owner} _ {cloud-region-id} - retcode2,content2,status_code2 = \ - restcall.req_to_aai(("/cloud-infrastructure/cloud-regions/cloud-region/%(owner)s/%(region)s" - "/esr-system-info-list/esr-system-info/%(owner)s_%(region)s" % { - "owner": cloud_owner, "region": cloud_region_id}), "GET") - if retcode2 != 0: - logger.error("Status code is %s, detail is %s.", status_code, content) - raise VimDriverNewtonException( - "Failed to query ESR system with id (%s:%s,%s)." % (vim_id,cloud_owner,cloud_region_id), - status_code, content) - tmp_authinfo = json.JSONDecoder().decode(content2) +# retcode2,content2,status_code2 = \ +# restcall.req_to_aai(("/cloud-infrastructure/cloud-regions/cloud-region/%(owner)s/%(region)s" +# "/esr-system-info-list/esr-system-info/%(owner)s_%(region)s" % { +# "owner": cloud_owner, "region": cloud_region_id}), "GET") +# if retcode2 != 0: +# logger.error("Status code is %s, detail is %s.", status_code, content) +# raise VimDriverNewtonException( +# "Failed to query ESR system with id (%s:%s,%s)." % (vim_id,cloud_owner,cloud_region_id), +# status_code2, content2) +# tmp_authinfo = json.JSONDecoder().decode(content2) + tmp_authinfo = tmp_viminfo['esr-system-info-list']['esr-system-info'][0] if tmp_viminfo else None #convert vim information if tmp_viminfo and tmp_authinfo: @@ -52,19 +53,19 @@ def get_vim_by_id(vim_id): viminfo['vimId'] = vim_id viminfo['cloud_owner'] = cloud_owner viminfo['cloud_region_id'] = cloud_region_id - viminfo['type'] = tmp_viminfo['cloud-type'] - viminfo['name'] = tmp_viminfo['complex-name'] - viminfo['version'] = tmp_viminfo['cloud-region-version'] - viminfo['cloud_extra_info'] = tmp_viminfo['cloud-extra-info'] - viminfo['cloud_epa_caps'] = tmp_viminfo['cloud-epa-caps'] + viminfo['type'] = tmp_viminfo.get('cloud-type') + viminfo['name'] = tmp_viminfo.get('complex-name') + viminfo['version'] = tmp_viminfo.get('cloud-region-version') + viminfo['cloud_extra_info'] = tmp_viminfo.get('cloud-extra-info') + viminfo['cloud_epa_caps'] = tmp_viminfo.get('cloud-epa-caps') viminfo['userName'] = tmp_authinfo['user-name'] viminfo['password'] = tmp_authinfo['password'] - viminfo['domain'] = tmp_authinfo['cloud-domain'] - viminfo['url'] = tmp_authinfo['service-url'] - viminfo['tenant'] = tmp_authinfo['default-tenant'] - viminfo['cacert'] = tmp_authinfo['ssl-cacert'] - viminfo['insecure'] = tmp_authinfo['ssl-insecure'] + viminfo['domain'] = tmp_authinfo.get('cloud-domain') + viminfo['url'] = tmp_authinfo.get('service-url') + viminfo['tenant'] = tmp_authinfo.get('default-tenant') + viminfo['cacert'] = tmp_authinfo.get('ssl-cacert') + viminfo['insecure'] = tmp_authinfo.get('ssl-insecure') return viminfo return None diff --git a/newton/newton/pub/tests/test_extsys.py b/newton/newton/pub/tests/test_extsys.py index 239ebe00..533910f9 100644 --- a/newton/newton/pub/tests/test_extsys.py +++ b/newton/newton/pub/tests/test_extsys.py @@ -23,24 +23,31 @@ from newton.pub.exceptions import VimDriverNewtonException from newton.pub.msapi import extsys from newton.pub.utils import restcall -MOCK_VIM_INFO = { - "cloud-type": "openstack", - "complex-name": "complex", - "cloud-region-version": "Regionv1", - "cloud-extra-info": "type", - "cloud-epa-caps": "epa" -} MOCK_ESR_SYSTEM_INFO = { "user-name": "test", "password": "secret", - "cloud-domain": "default", + "cloud-domain": "Default", "service-url": "http://localhost", "default-tenant": "demo", "ssl-cacert": None, "ssl-insecure": None } +MOCK_VIM_INFO = { + "cloud-type": "openstack", + "complex-name": "complex", + "cloud-region-version": "Regionv1", + "cloud-extra-info": "type", + "cloud-epa-caps": "epa", + "esr-system-info-list" : + { + "esr-system-info": [ + MOCK_ESR_SYSTEM_INFO + ] + } +} + def returnList(items): def func(): @@ -82,7 +89,7 @@ class TestEpaCaps(unittest.TestCase): self.assertRaises(VimDriverNewtonException, extsys.get_vim_by_id, self.vim_id) restcall.req_to_aai.assert_called_once() - self.assertRaises(VimDriverNewtonException, extsys.get_vim_by_id, self.vim_id) + #self.assertRaises(VimDriverNewtonException, extsys.get_vim_by_id, self.vim_id) viminfo = extsys.get_vim_by_id(self.vim_id) self.assertIsNotNone(viminfo) diff --git a/newton/newton/pub/tests/test_restcall.py b/newton/newton/pub/tests/test_restcall.py index 28def73f..063beb35 100644 --- a/newton/newton/pub/tests/test_restcall.py +++ b/newton/newton/pub/tests/test_restcall.py @@ -19,6 +19,7 @@ import unittest from newton.pub.utils import restcall +rest_no_auth, rest_oneway_auth, rest_bothway_auth = 0, 1, 2 class TestRestCall(unittest.TestCase): base_url = "http://localhost" @@ -29,7 +30,7 @@ class TestRestCall(unittest.TestCase): mock_http.raiseError.side_effect = mock.Mock( side_effect=Exception('Test')) args = [ - self.base_url, "user", "password", "auth_type", + self.base_url, None, None, rest_no_auth, self.resource, "get", {"extra": "test"} ] @@ -41,7 +42,7 @@ class TestRestCall(unittest.TestCase): @mock.patch.object(Http, 'request') def test_invalid_output_call_req(self, mock_http): args = [ - self.base_url, "user", "password", "auth_type", + self.base_url, None, None, rest_no_auth, self.resource, "get", {"extra": "test"} ] @@ -56,7 +57,7 @@ class TestRestCall(unittest.TestCase): @mock.patch.object(Http, 'request') def test_req_by_msb(self, mock_http): resp_body = "test_body" - resp_status=status.HTTP_200_OK + resp_status='200' #status.HTTP_200_OK mock_http.return_value = ( {'status': resp_status}, str.encode(resp_body, 'utf-8')) @@ -70,7 +71,7 @@ class TestRestCall(unittest.TestCase): @mock.patch.object(Http, 'request') def test_req_to_vim(self, mock_http): resp_body = "test_body" - resp_status=status.HTTP_200_OK + resp_status='200' #status.HTTP_200_OK mock_http.return_value = ( {'status': resp_status}, str.encode(resp_body, 'utf-8')) @@ -83,7 +84,7 @@ class TestRestCall(unittest.TestCase): @mock.patch.object(Http, 'request') def test_req_to_aai(self, mock_http): resp_body = "test_body" - resp_status=status.HTTP_200_OK + resp_status='200' #status.HTTP_200_OK mock_http.return_value = ( {'status': resp_status}, str.encode(resp_body, 'utf-8')) diff --git a/newton/newton/pub/utils/restcall.py b/newton/newton/pub/utils/restcall.py index 6444014d..f0c19930 100644 --- a/newton/newton/pub/utils/restcall.py +++ b/newton/newton/pub/utils/restcall.py @@ -9,6 +9,9 @@ # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +import six +import base64 + import codecs import json import traceback @@ -23,9 +26,12 @@ from rest_framework import status from newton.pub.config import config rest_no_auth, rest_oneway_auth, rest_bothway_auth = 0, 1, 2 - -status_ok_list \ - = [status.HTTP_200_OK, status.HTTP_201_CREATED, status.HTTP_204_NO_CONTENT, status.HTTP_202_ACCEPTED] +HTTP_200_OK, HTTP_201_CREATED = '200', '201' +HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED = '204', '202' +status_ok_list = [HTTP_200_OK, HTTP_201_CREATED, + HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED] +HTTP_404_NOTFOUND, HTTP_403_FORBIDDEN = '404', '403' +HTTP_401_UNAUTHORIZED, HTTP_400_BADREQUEST = '401', '400' MAX_RETRY_TIME = 3 @@ -46,9 +52,16 @@ def _call_req(base_url, user, passwd, auth_type, if extra_headers: headers.update(extra_headers) +# if user: +# headers['Authorization'] = \ +# 'Basic ' + str(codecs.encode('%s:%s' % (user, passwd), "ascii")) + if user: - headers['Authorization'] = \ - 'Basic ' + str(codecs.encode('%s:%s' % (user, passwd), "ascii")) + tmpauthsource = '%s:%s' % (user, passwd) + if six.PY3: + tmpauthsource = tmpauthsource.encode('utf-8') + headers['Authorization'] = 'Basic ' + \ + base64.b64encode(tmpauthsource).decode('utf-8') ca_certs = None for retry_times in range(MAX_RETRY_TIME): @@ -102,7 +115,7 @@ def req_to_vim(base_url, resource, method, extra_headers='', content=''): def req_to_aai(resource, method, content='', appid=config.MULTICLOUD_APP_ID): - tmp_trasaction_id = str(uuid.uuid1()) + tmp_trasaction_id = '9003' #str(uuid.uuid1()) headers = { 'X-FromAppId': appid, 'X-TransactionId': tmp_trasaction_id, @@ -110,7 +123,8 @@ def req_to_aai(resource, method, content='', appid=config.MULTICLOUD_APP_ID): 'accept': 'application/json' } - logger.debug("req_to_aai--%s::> %s, %s" % (tmp_trasaction_id, method, resource)) + logger.debug("req_to_aai--%s::> %s, %s" % + (tmp_trasaction_id, method, _combine_url(config.AAI_BASE_URL,resource))) return _call_req(config.AAI_BASE_URL, config.AAI_USERNAME, config.AAI_PASSWORD, rest_no_auth, resource, method, content=json.dumps(content), extra_headers=headers) diff --git a/ocata/ocata/proxy/urls.py b/ocata/ocata/proxy/urls.py index 12777bf6..e59b2e06 100644 --- a/ocata/ocata/proxy/urls.py +++ b/ocata/ocata/proxy/urls.py @@ -21,11 +21,13 @@ from ocata.proxy.views import services urlpatterns = [ # url(r'^identity/v2)$', # identityV2.Tokens.as_view()), - url(r'^identity/v3/auth/tokens$', + url(r'^identity/v3/auth/tokens/?$', identityV3.Tokens.as_view()), - url(r'^identity/v2.0/tokens$', + url(r'^identity/v2.0/?', identityV3.TokensV2.as_view()), - url(r'^identity/v2.0/tenants$', + url(r'^identity/v2.0/tokens/?$', + identityV3.TokensV2.as_view()), + url(r'^identity/v2.0/tenants/?$', services.GetTenants.as_view()), url(r'^(?P[0-9a-zA-Z_-]{,18})/(?P[0-9a-zA-Z./_-]*)$', services.Services.as_view()), diff --git a/ocata/run.sh b/ocata/run.sh index 446172b4..cfb52b74 100644 --- a/ocata/run.sh +++ b/ocata/run.sh @@ -20,6 +20,14 @@ sed -i "s/AAI_SCHEMA_VERSION =.*/AAI_SCHEMA_VERSION = \"${AAI_SCHEMA_VERSION}\"/ sed -i "s/AAI_USERNAME =.*/AAI_USERNAME = \"${AAI_USERNAME}\"/g" ocata/pub/config/config.py sed -i "s/AAI_PASSWORD =.*/AAI_PASSWORD = \"${AAI_PASSWORD}\"/g" ocata/pub/config/config.py +sed -i "s/MSB_SERVICE_ADDR =.*/MSB_SERVICE_ADDR = \"${MSB_ADDR}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/MSB_SERVICE_PORT =.*/MSB_SERVICE_PORT = \"${MSB_PORT}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_ADDR =.*/AAI_ADDR = \"${AAI_ADDR}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_PORT =.*/AAI_PORT = \"${AAI_PORT}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_SCHEMA_VERSION =.*/AAI_SCHEMA_VERSION = \"${AAI_SCHEMA_VERSION}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_USERNAME =.*/AAI_USERNAME = \"${AAI_USERNAME}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_PASSWORD =.*/AAI_PASSWORD = \"${AAI_PASSWORD}\"/g" lib/newton/newton/pub/config/config.py + memcached -d -m 2048 -u root -c 1024 -p 11211 -P /tmp/memcached1.pid export PYTHONPATH=lib/newton nohup python manage.py runserver 0.0.0.0:9006 2>&1 & diff --git a/windriver/run.sh b/windriver/run.sh index 031719b4..ddf92da2 100644 --- a/windriver/run.sh +++ b/windriver/run.sh @@ -20,6 +20,14 @@ sed -i "s/AAI_SCHEMA_VERSION =.*/AAI_SCHEMA_VERSION = \"${AAI_SCHEMA_VERSION}\"/ sed -i "s/AAI_USERNAME =.*/AAI_USERNAME = \"${AAI_USERNAME}\"/g" titanium_cloud/pub/config/config.py sed -i "s/AAI_PASSWORD =.*/AAI_PASSWORD = \"${AAI_PASSWORD}\"/g" titanium_cloud/pub/config/config.py +sed -i "s/MSB_SERVICE_ADDR =.*/MSB_SERVICE_ADDR = \"${MSB_ADDR}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/MSB_SERVICE_PORT =.*/MSB_SERVICE_PORT = \"${MSB_PORT}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_ADDR =.*/AAI_ADDR = \"${AAI_ADDR}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_PORT =.*/AAI_PORT = \"${AAI_PORT}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_SCHEMA_VERSION =.*/AAI_SCHEMA_VERSION = \"${AAI_SCHEMA_VERSION}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_USERNAME =.*/AAI_USERNAME = \"${AAI_USERNAME}\"/g" lib/newton/newton/pub/config/config.py +sed -i "s/AAI_PASSWORD =.*/AAI_PASSWORD = \"${AAI_PASSWORD}\"/g" lib/newton/newton/pub/config/config.py + memcached -d -m 2048 -u root -c 1024 -p 11211 -P /tmp/memcached1.pid export PYTHONPATH=lib/newton nohup python manage.py runserver 0.0.0.0:9005 2>&1 & diff --git a/windriver/titanium_cloud/proxy/urls.py b/windriver/titanium_cloud/proxy/urls.py index 31a3c8f7..73cd428e 100644 --- a/windriver/titanium_cloud/proxy/urls.py +++ b/windriver/titanium_cloud/proxy/urls.py @@ -23,6 +23,8 @@ urlpatterns = [ # identityV2.Tokens.as_view()), url(r'^identity/v3/auth/tokens/?$', 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/?$', -- cgit 1.2.3-korg