diff options
author | Huang Haibin <haibin.huang@intel.com> | 2018-01-17 06:06:27 +0800 |
---|---|---|
committer | Huang Haibin <haibin.huang@intel.com> | 2018-01-18 01:01:15 +0800 |
commit | 9e7c5a6bfd338dd5352d9d6afdae0cea23856acf (patch) | |
tree | bffbbdc32f615bb2e8c44441572a942c75ce66b1 /share/newton_base/proxy/services.py | |
parent | 79c711a95de34531e62927ea19fe16753513063b (diff) |
Add newton base directory
newton base directory is mainly placed openstack public files, we
will move mainly from the original newton folder.this patch create
newton base framework and move one file to here.
Issue-ID: MULTICLOUD-138
Change-Id: Ie901795a5cf3383217c3585eb6602a4baba6dcd8
Signed-off-by: Huang Haibin <haibin.huang@intel.com>
Diffstat (limited to 'share/newton_base/proxy/services.py')
-rw-r--r-- | share/newton_base/proxy/services.py | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/share/newton_base/proxy/services.py b/share/newton_base/proxy/services.py new file mode 100644 index 00000000..3c543bf9 --- /dev/null +++ b/share/newton_base/proxy/services.py @@ -0,0 +1,273 @@ +# Copyright (c) 2017-2018 Wind River System Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import logging +import json +import traceback + +from keystoneauth1.exceptions import HttpError +import re +from rest_framework.permissions import BasePermission +from rest_framework.response import Response +from rest_framework import status +from rest_framework.views import APIView + +from newton.proxy.views.proxy_utils import ProxyUtils +from newton.pub.exceptions import VimDriverNewtonException +from newton.pub.msapi import extsys +from newton.requests.views.util import VimDriverUtils + +logger = logging.getLogger(__name__) + +DEBUG=True + + +class HasValidToken(BasePermission): + + def has_permission(self, request, view): + logger.debug("HasValidToken--has_permission::META> %s" % request.META) + token = request.META.get('HTTP_X_AUTH_TOKEN', None) + if token: + state, metadata = VimDriverUtils.get_token_cache(token) + if state: + return True + return False + + +class Services(APIView): + permission_classes = (HasValidToken,) + + def __init__(self): + self._logger = logger + + def _get_token(self, request): + return request.META.get('HTTP_X_AUTH_TOKEN', None) + + def _get_resource_and_metadata(self, servicetype, metadata_catalog, requri): + real_prefix = None + proxy_prefix = None + suffix = None + if servicetype and metadata_catalog: + metadata_catalog = json.loads(metadata_catalog) + service_metadata = metadata_catalog.get(servicetype, None) + if service_metadata: + real_prefix = service_metadata['prefix'] + proxy_prefix = service_metadata['proxy_prefix'] + suffix = service_metadata['suffix'] + + if not real_prefix or not proxy_prefix: + raise VimDriverNewtonException(message="internal state error", + content="invalid cached metadata", + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) + + if requri == suffix: + requri = None + + if suffix and requri: + # remove the suffix from the requri to avoid duplicated suffix in real request uri later + tmp_pattern = re.compile(suffix) + requri = tmp_pattern.sub('', requri) + + req_resource = '' + if requri and requri != '': + req_resource = "/" if re.match(r'//', requri) else '' + requri + return req_resource, metadata_catalog + + def _do_action(self, action, request, vim_id, servicetype, requri): + tmp_auth_token = self._get_token(request) + try: + #special handling of compute/v2 request from APPC, temp solution for A release + if servicetype == 'compute': + tmp_pattern = re.compile(r'^v2/(.+)') + requri = tmp_pattern.sub(r'v2.1/' + r'\1', requri) + + + vim = VimDriverUtils.get_vim_info(vim_id) + # fetch the auth_state out of cache + auth_state, metadata_catalog = VimDriverUtils.get_token_cache(tmp_auth_token) + req_resource, metadata_catalog = self._get_resource_and_metadata(servicetype, metadata_catalog, requri) + sess = VimDriverUtils.get_session(vim, auth_state=auth_state) + + cloud_owner, regionid = extsys.decode_vim_id(vim_id) + interface = 'public' + service = { + 'service_type': servicetype, + 'interface': interface, + 'region_id': regionid + } + + querystr = VimDriverUtils.get_query_part(request) + if querystr: + req_resource += "?" + querystr + + self._logger.debug("hhb service " + action + " request uri %s" % (req_resource)) + if(action == "get"): + resp = sess.get(req_resource, endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif(action == "post"): + resp = sess.post(req_resource, data=json.JSONEncoder().encode(request.data), + endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif(action == "put"): + resp = sess.put(req_resource, data=json.JSONEncoder().encode(request.data), + endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif(action == "patch"): + resp = sess.patch(req_resource, data=json.JSONEncoder().encode(request.data), + endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif (action == "delete"): + resp = sess.delete(req_resource, endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + content = resp.json() if resp.content else None + self._logger.debug("service " + action + " response: %s, %s" % (resp.status_code, content)) + + if (action == "delete"): + return Response(headers={'X-Subject-Token': tmp_auth_token}, status=resp.status_code) + else: + content = ProxyUtils.update_prefix(metadata_catalog, content) + if (action == "get"): + if requri == '/v3/auth/catalog' and content and content.get("catalog"): + content['catalog'] = ProxyUtils.update_catalog_dnsaas( + vim_id, content['catalog'], self.proxy_prefix, vim) + return Response(headers={'X-Subject-Token': tmp_auth_token}, data=content, status=resp.status_code) + + except VimDriverNewtonException as e: + return Response(data={'error': e.content}, status=e.status_code) + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return Response(data=e.response.json(), status=e.http_status) + except Exception as e: + self._logger.error(traceback.format_exc()) + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + def head(self, request, vimid="", servicetype="", requri=""): + #self._logger.debug("Services--head::META> %s" % request.META) + self._logger.debug("Services--head::data> %s" % request.data) + self._logger.debug("Services--head::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + + token = self._get_token(request) + try: + vim = VimDriverUtils.get_vim_info(vimid) + auth_state, metadata_catalog = VimDriverUtils.get_token_cache(token) + sess = VimDriverUtils.get_session(vim, auth_state=auth_state) + + req_resource = '' + if requri and requri != '': + req_resource = "/" if re.match(r'//', requri) else ''+ requri + + cloud_owner, regionid = extsys.decode_vim_id(vimid) + interface = 'public' + service = {'service_type': servicetype, + 'interface': interface, + 'region_id': regionid} + + self._logger.debug("service head request uri %s" % (req_resource)) + + resp = sess.head(req_resource, endpoint_filter=service) + content = resp.json() if resp.content else None + self._logger.debug("service head response: %s, %s" % (resp.status_code, content)) + + return Response(headers={'X-Subject-Token': token}, data=content, status=resp.status_code) + except VimDriverNewtonException as e: + return Response(data={'error': e.content}, status=e.status_code) + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return Response(data=e.response.json(), status=e.http_status) + except Exception as e: + self._logger.error(traceback.format_exc()) + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + def get(self, request, vimid="", servicetype="", requri=""): + #self._logger.debug("Services--get::META> %s" % request.META) + self._logger.debug("Services--get::data> %s" % request.data) + self._logger.debug("Services--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("get", request, vimid, servicetype, requri) + + def post(self, request, vimid="", servicetype="", requri=""): + #self._logger.debug("Services--post::META> %s" % request.META) + self._logger.debug("Services--post::data> %s" % request.data) + self._logger.debug("Services--post::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + + return self._do_action("post", request, vimid, servicetype, requri) + + def put(self, request, vimid="", servicetype="", requri=""): + #self._logger.debug("Services--put::META> %s" % request.META) + self._logger.debug("Services--put::data> %s" % request.data) + self._logger.debug("Services--put::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("put", request, vimid, servicetype, requri) + + def patch(self, request, vimid="", servicetype="", requri=""): + #self._logger.debug("Services--patch::META> %s" % request.META) + self._logger.debug("Services--patch::data> %s" % request.data) + self._logger.debug("Services--patch::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("patch", request, vimid, servicetype, requri) + + def delete(self, request, vimid="", servicetype="", requri=""): + #self._logger.debug("Services--delete::META> %s" % request.META) + self._logger.debug("Services--delete::data> %s" % request.data) + self._logger.debug("Services--delete::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("delete", request, vimid, servicetype, requri) + + +class GetTenants(Services): + ''' + Backward compatible API for /v2.0/tenants + ''' + + def __init__(self): + self._logger = logger + + def get(self, request, vimid="", servicetype="identity", requri='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)) + + tmp_auth_token = request.META.get('HTTP_X_AUTH_TOKEN', None) + + resp = super(GetTenants,self).get(request, vimid, servicetype, requri) + if resp.status_code == status.HTTP_200_OK: + content = resp.data + return Response(headers={'X-Subject-Token': tmp_auth_token}, data={'tenants': content['projects'],'tenants_links':[]}, + status=resp.status_code) + else: + return resp + + def head(self, request, vimid="", servicetype="", requri=""): + return Response(data={'error': 'unsupported operation'}, status=status.HTTP_400_BAD_REQUEST) + + def post(self, request, vimid="", servicetype="", requri=""): + return Response(data={'error': 'unsupported operation'}, status=status.HTTP_400_BAD_REQUEST) + + def put(self, request, vimid="", servicetype="", requri=""): + return Response(data={'error': 'unsupported operation'}, status=status.HTTP_400_BAD_REQUEST) + + def patch(self, request, vimid="", servicetype="", requri=""): + return Response(data={'error': 'unsupported operation'}, status=status.HTTP_400_BAD_REQUEST) + + def delete(self, request, vimid="", servicetype="", requri=""): + return Response(data={'error': 'unsupported operation'}, status=status.HTTP_400_BAD_REQUEST) |