From 7419e38021a3c959af3b6a4730a0f50baff2e15b Mon Sep 17 00:00:00 2001 From: Bin Yang Date: Thu, 16 Aug 2018 06:49:12 +0000 Subject: [PATCH] API upgrading for forwarder API Change-Id: Iabbab0fd3cd52f728fe69599110b0168c48fb17a Issue-ID: MULTICLOUD-310 Signed-off-by: Bin Yang --- multivimbroker/multivimbroker/forwarder/urls.py | 36 +++++++ multivimbroker/multivimbroker/forwarder/views.py | 114 ++++++++++++++++++++++ multivimbroker/multivimbroker/pub/msapi/extsys.py | 32 ++++++ 3 files changed, 182 insertions(+) diff --git a/multivimbroker/multivimbroker/forwarder/urls.py b/multivimbroker/multivimbroker/forwarder/urls.py index 3f11588..5e1320e 100644 --- a/multivimbroker/multivimbroker/forwarder/urls.py +++ b/multivimbroker/multivimbroker/forwarder/urls.py @@ -25,6 +25,15 @@ from multivimbroker.forwarder.views import UnRegistry from multivimbroker.forwarder.views import VIMTypes from multivimbroker.forwarder.views import MultiPartView +# API v1 +from multivimbroker.forwarder.views import APIv1CheckCapacity +from multivimbroker.forwarder.views import APIv1Extension +from multivimbroker.forwarder.views import APIv1Forward +from multivimbroker.forwarder.views import APIv1Identity +from multivimbroker.forwarder.views import APIv1Registry +from multivimbroker.forwarder.views import APIv1UnRegistry +from multivimbroker.forwarder.views import APIv1VIMTypes +from multivimbroker.forwarder.views import APIv1MultiPartView urlpatterns = [ url(r'^api/multicloud/v0/vim_types$', @@ -45,6 +54,33 @@ urlpatterns = [ MultiPartView.as_view()), url(r'^api/multicloud/v0/(?P[0-9a-zA-Z_-]+)', Forward.as_view()), + + # API v1 + url(r'^api/multicloud/v1/vim_types$', + APIv1VIMTypes.as_view()), + url(r'^api/multicloud/v1/check_vim_capacity$', + APIv1CheckCapacity.as_view()), + url(r'^api/multicloud/v1/(?P[0-9a-zA-Z_-]+)' + r'/(?P[0-9a-zA-Z_-]+)/identity/v3$', + APIv1Identity.as_view()), + url(r'^api/multicloud/v1/(?P[0-9a-zA-Z_-]+)' + r'/(?P[0-9a-zA-Z_-]+)/identity/v3' + r'/auth/tokens$', APIv1Identity.as_view()), + url(r'^api/multicloud/v1/(?P[0-9a-zA-Z_-]+)' + r'/(?P[0-9a-zA-Z_-]+)/registry$', + APIv1Registry.as_view()), + url(r'^api/multicloud/v1/(?P[0-9a-zA-Z_-]+)i' + r'/(?P[0-9a-zA-Z_-]+)$', + APIv1UnRegistry.as_view()), + url(r'^api/multicloud/v1/(?P[0-9a-zA-Z_-]+)' + r'/(?P[0-9a-zA-Z_-]+)/extensions$', + APIv1Extension.as_view()), + url(r'^api/multicloud/v1/(?P[0-9a-zA-Z_-]+)' + r'/(?P[0-9a-zA-Z_-]+)/multipart', + APIv1MultiPartView.as_view()), + url(r'^api/multicloud/v1/(?P[0-9a-zA-Z_-]+)' + r'/(?P[0-9a-zA-Z_-]+)', + APIv1Forward.as_view()), ] urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/multivimbroker/multivimbroker/forwarder/views.py b/multivimbroker/multivimbroker/forwarder/views.py index 1e57d0e..ef7ab95 100644 --- a/multivimbroker/multivimbroker/forwarder/views.py +++ b/multivimbroker/multivimbroker/forwarder/views.py @@ -27,6 +27,7 @@ from multivimbroker.forwarder.base import BaseHandler from multivimbroker.pub.utils.syscomm import originHeaders from multivimbroker.pub.utils import syscomm from rest_framework.parsers import MultiPartParser +from multivimbroker.pub.msapi import extsys class BaseServer(BaseHandler, APIView): @@ -193,3 +194,116 @@ class MultiPartView(BaseServer): fileRef.close() os.remove(fileRef.name) return resp + + +# API v1 +# proxy handler +class APIv1Identity(Identity): + + def get(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Identity, self).get(request, vimid) + + def post(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Identity, self).post(request, vimid) + + +class APIv1Registry(Registry): + + def post(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Registry, self).post(request, vimid) + + +class APIv1UnRegistry(UnRegistry): + + def delete(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1UnRegistry, self).delete(request, vimid) + + +class APIv1Extension(Extension): + + def get(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Extension, self).get(request, vimid) + + +class APIv1VIMTypes(VIMTypes): + + def get(self, request): + return super(APIv1VIMTypes, self).get(request) + + +class APIv1CheckCapacity(CheckCapacity): + + def post(self, request): + try: + body = json.loads(request.body) + except ValueError as e: + return Response( + data={'error': 'Invalidate request body %s.' % e}, + status=status.HTTP_400_BAD_REQUEST) + + ret = {"VIMs": []} + newbody = { + "vCPU": body.get("vCPU", 0), + "Memory": body.get("Memory", 0), + "Storage": body.get("Storage", 0) + } + for vim in body.get("VIMs", []): + cloud_owner = vim["cloud-owner"] + cloud_region_id = vim["cloud-region-id"] + url = request.get_full_path().replace( + "check_vim_capacity", "%s/%s/capacity_check" % + (cloud_owner, cloud_region_id)) + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + resp = self.send(vimid, url, json.dumps(newbody), "POST") + if int(resp.status_code) != status.HTTP_200_OK: + continue + try: + resp_body = json.loads(resp.content) + except ValueError: + continue + if not resp_body.get("result", False): + continue + ret['VIMs'].append(vim) + return Response(data=ret, status=status.HTTP_200_OK) + + +# forward handler +class APIv1Forward(Forward): + + def get(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Forward, self).get(request, vimid) + + def post(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Forward, self).post(request, vimid) + + def patch(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Forward, self).patch(request, vimid) + + def delete(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Forward, self).delete(request, vimid) + + def head(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Forward, self).head(request, vimid) + + def put(self, request, cloud_owner, cloud_region_id): + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1Forward, self).put(request, vimid) + + +# Multipart view +class APIv1MultiPartView(MultiPartView): + + def post(self, request, cloud_owner, cloud_region_id): + + vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id) + return super(APIv1MultiPartView, self).post(request, vimid) diff --git a/multivimbroker/multivimbroker/pub/msapi/extsys.py b/multivimbroker/multivimbroker/pub/msapi/extsys.py index 1208ac9..a76d56a 100644 --- a/multivimbroker/multivimbroker/pub/msapi/extsys.py +++ b/multivimbroker/multivimbroker/pub/msapi/extsys.py @@ -19,6 +19,38 @@ from multivimbroker.pub.utils import restcall logger = logging.getLogger(__name__) +def encode_vim_id(cloud_owner, cloud_region_id): + ''' + compose vim_id by cloud_owner and cloud_region, make sure the vimid can be + converted back when talking to AAI,etc. + This is a backward compatibility design to reuse the existing + implementation code + :param cloud_owner: + :param cloud_region: + :return: + ''' + + # since the {cloud_owner}/{cloud_region_id"} is globally unique, the + # concatenated one as below will be unique as well. + + vim_id = cloud_owner + "_" + cloud_region_id + + # other options: + # 1, store it into cache so the decode and just look up the cache for + # decoding + # 2, use other delimiter in case that '_' was used by + # cloud owner/cloud region id, + # e.g. '.', '#', hence the decode need to try more than one time + + return vim_id + + +def decode_vim_id(vim_id): + # m = re.search(r'^([0-9a-zA-Z-]+)_([0-9a-zA-Z_-]+)$', vim_id) + # cloud_owner, cloud_region_id = m.group(1), m.group(2) + return split_vim_to_owner_region(vim_id) + + def split_vim_to_owner_region(vim_id): split_vim = vim_id.split('_') cloud_owner = split_vim[0] -- 2.16.6