summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vio/vio/pub/exceptions.py57
-rw-r--r--vio/vio/pub/utils/syscomm.py33
-rw-r--r--vio/vio/swagger/urls.py47
-rw-r--r--vio/vio/swagger/views/proxyplugin/__init__.py11
-rw-r--r--vio/vio/swagger/views/proxyplugin/heat/__init__.py11
-rw-r--r--vio/vio/swagger/views/proxyplugin/heat/views.py54
-rw-r--r--vio/vio/swagger/views/proxyplugin/httpclient.py182
-rw-r--r--vio/vio/swagger/views/proxyplugin/identity/__init__.py11
-rw-r--r--vio/vio/swagger/views/proxyplugin/identity/views.py183
-rw-r--r--vio/vio/swagger/views/proxyplugin/image/__init__.py11
-rw-r--r--vio/vio/swagger/views/proxyplugin/image/views.py50
-rw-r--r--vio/vio/swagger/views/proxyplugin/neutron/__init__.py11
-rw-r--r--vio/vio/swagger/views/proxyplugin/neutron/views.py39
-rw-r--r--vio/vio/swagger/views/proxyplugin/nova/__init__.py11
-rw-r--r--vio/vio/swagger/views/proxyplugin/nova/views.py43
-rw-r--r--vio/vio/swagger/views/proxyplugin/volumn/__init__.py11
-rw-r--r--vio/vio/swagger/views/proxyplugin/volumn/views.py53
17 files changed, 813 insertions, 5 deletions
diff --git a/vio/vio/pub/exceptions.py b/vio/vio/pub/exceptions.py
index 077b72d..097d785 100644
--- a/vio/vio/pub/exceptions.py
+++ b/vio/vio/pub/exceptions.py
@@ -11,9 +11,58 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-class VimDriverVioException(Exception):
- def __init__(self, message, status_code="", content=""):
- super(VimDriverVioException, self).__init__(message)
+class ClientException(Exception):
+
+ message = "ClientException"
+
+ def __init__(self, message=None):
+ self.message = message or self.message
+ super(ClientException, self).__init__(self.message)
+
+class ServerException(Exception):
+
+ message = "ServerException"
+
+ def __init__(self, message=None, status_code="", content=""):
+ super(ServerException, self).__init__(message)
+ self.message = message or self.message
self.status_code = status_code
self.content = content
- pass
+
+class RetriableConnectionFailure(Exception):
+
+ pass
+
+
+class ConnectionError(ClientException):
+ message = "Cannot connect to API service."
+
+
+class ConnectTimeout(ConnectionError, RetriableConnectionFailure):
+ message = "Timed out connecting to service."
+
+
+class ConnectFailure(ConnectionError, RetriableConnectionFailure):
+ message = "Connection failure that may be retried."
+
+
+class SSLError(ConnectionError):
+ message = "An SSL error occurred."
+
+
+
+
+class UnknownConnectionError(ConnectionError):
+
+ def __init__(self, msg, original):
+ super(UnknownConnectionError, self).__init__(msg)
+ self.original = original
+
+
+
+class NotFoundError(ServerException):
+ message = "Cannot find value"
+
+class VimDriverVioException(ServerException):
+ message = "Cannot find vim driver"
+
diff --git a/vio/vio/pub/utils/syscomm.py b/vio/vio/pub/utils/syscomm.py
index 833a290..fd99ac6 100644
--- a/vio/vio/pub/utils/syscomm.py
+++ b/vio/vio/pub/utils/syscomm.py
@@ -11,7 +11,38 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import inspect
-
+import json
+from collections import defaultdict
def fun_name():
return inspect.stack()[1][3]
+
+
+def jsonResponse(data,encoding='utf-8'):
+
+ content_type = "application/json"
+ try:
+ res = json.loads(data,encoding=encoding)
+ except Exception as e:
+ res = data
+ content_type = "text/plain"
+ return (res,content_type)
+
+
+class Catalogs(object):
+
+ def __init__(self):
+ self.ct=defaultdict(dict)
+
+
+ def storeEndpoint(self,vimid,endpoints):
+ self.ct.setdefault(vimid,endpoints)
+
+ def getEndpointBy(self,vimid,serverType,interface='public'):
+
+ vim = self.ct.get(vimid)
+ return vim.get(serverType).get(interface,"") if vim else ""
+
+
+
+catalog = Catalogs()
diff --git a/vio/vio/swagger/urls.py b/vio/vio/swagger/urls.py
index 1740c03..26a739f 100644
--- a/vio/vio/swagger/urls.py
+++ b/vio/vio/swagger/urls.py
@@ -28,6 +28,14 @@ from vio.swagger.views.network.views import CreateNetworkView, DeleteNetworkView
from vio.swagger.views.subnet.views import CreateSubnetView, DeleteSubnetView
from vio.swagger.views.port.views import CreatePortView, DeletePortView
+#proxy
+from vio.swagger.views.proxyplugin.identity.views import TokenView,IdentityServer
+from vio.swagger.views.proxyplugin.nova.views import ComputeServer
+from vio.swagger.views.proxyplugin.image.views import ImageServer
+from vio.swagger.views.proxyplugin.neutron.views import NetWorkServer
+from vio.swagger.views.proxyplugin.volumn.views import VolumeServer
+from vio.swagger.views.proxyplugin.heat.views import HeatServer
+
urlpatterns = [
url(r'^openoapi/multivim-vio/v1/swagger.json$', SwaggerJsonView.as_view()),
url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
@@ -79,6 +87,45 @@ urlpatterns = [
url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z\-\_]+)/(?P<tenantid>[0-9a-zA-Z\-\_]+)/ports/'
r'(?P<portid>[0-9a-zA-Z\-\_]+)$',
DeletePortView.as_view()),
+
+ # proxy
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/identity/v3',
+ TokenView.as_view()),
+
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/identity$',
+ IdentityServer.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/identity/(?P<other>(.*))$',
+ IdentityServer.as_view()),
+
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/glance/(?P<other>(.*))$',
+ ImageServer.as_view()),
+
+ url(
+ r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/cinder/(?P<tenantid>[0-9a-z-A-Z\-\_]+)/(?P<other>(.*))$',
+ VolumeServer.as_view()),
+
+ url(
+ r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/cinderv2/(?P<tenantid>[0-9a-z-A-Z\-\_]+)/(?P<other>(.*))$',
+ VolumeServer.as_view()),
+
+ url(
+ r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/cinderv3/(?P<tenantid>[0-9a-z-A-Z\-\_]+)/(?P<other>(.*))$',
+ VolumeServer.as_view()),
+
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/neutron$',
+ NetWorkServer.as_view()),
+
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/neutron/(?P<other>(.*))$',
+ NetWorkServer.as_view()),
+
+ url(
+ r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/heat/(?P<tenantid>[0-9a-z-A-Z\-\_]+)/(?P<other>(.*))$',
+ HeatServer.as_view()),
+
+ url(
+ r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-z-A-Z\-\_]+)/nova/(?P<tenantid>[0-9a-z-A-Z\-\_]+)/(?P<other>(.*))$',
+ ComputeServer.as_view()),
+
]
urlpatterns = format_suffix_patterns(urlpatterns)
diff --git a/vio/vio/swagger/views/proxyplugin/__init__.py b/vio/vio/swagger/views/proxyplugin/__init__.py
new file mode 100644
index 0000000..9ac359f
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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. \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/heat/__init__.py b/vio/vio/swagger/views/proxyplugin/heat/__init__.py
new file mode 100644
index 0000000..9ac359f
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/heat/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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. \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/heat/views.py b/vio/vio/swagger/views/proxyplugin/heat/views.py
new file mode 100644
index 0000000..b60cb7b
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/heat/views.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2017 VMware, 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.
+
+from vio.swagger.views.proxyplugin.httpclient import BaseClient
+
+
+class HeatServer(BaseClient):
+
+ serverType = "heat"
+
+ def get(self,request,vimid,tenantid,other):
+
+ return self.send(request=request,method="GET",vimid=vimid,tenantid=tenantid,other=other)
+
+ def post(self,request,vimid,tenantid,other):
+
+ return self.send(request=request,method="POST",vimid=vimid,tenantid=tenantid,other=other)
+
+
+ def put(self,request,vimid,tenantid,other):
+
+ return self.send(request=request, method="PUT",vimid=vimid, tenantid=tenantid, other=other)
+
+
+ def delete(self,request,vimid,tenantid,other):
+
+ return self.send(request=request, method="DELETE",vimid=vimid, tenantid=tenantid, other=other)
+
+ def patch(self, request, vimid, tenantid,other):
+
+ return self.send(request=request, method="PATCH",vimid=vimid, tenantid=tenantid, other=other)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vio/vio/swagger/views/proxyplugin/httpclient.py b/vio/vio/swagger/views/proxyplugin/httpclient.py
new file mode 100644
index 0000000..b335d4a
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/httpclient.py
@@ -0,0 +1,182 @@
+# Copyright (c) 2017 VMware, 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.
+
+import logging
+import requests
+import json
+import socket
+import time
+
+from rest_framework import status
+from rest_framework.views import APIView
+from rest_framework.response import Response
+
+
+from vio.pub.utils.syscomm import catalog,jsonResponse
+import vio.pub.exceptions as exceptions
+
+
+logger = logging.getLogger(__name__)
+
+class TCPKeepAliveAdapter(requests.adapters.HTTPAdapter):
+ """The custom adapter used to set TCP Keep-Alive on all connections."""
+
+ def init_poolmanager(self, *args, **kwargs):
+ if 'socket_options' not in kwargs and tuple(int(v) for v in requests.__version__.split('.')) >= (2, 4, 1):
+ socket_options = [
+ # Keep Nagle's algorithm off
+ (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),
+ # Turn on TCP Keep-Alive
+ (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
+ ]
+
+ if hasattr(socket, 'TCP_KEEPIDLE'):
+ socket_options += [
+ # Wait 60 seconds before sending keep-alive probes
+ (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
+ ]
+
+ if hasattr(socket, 'TCP_KEEPINTVL'):
+ socket_options += [
+ # Send keep-alive probes every 15 seconds
+ (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15),
+ ]
+
+ kwargs['socket_options'] = socket_options
+ super(TCPKeepAliveAdapter, self).init_poolmanager(*args, **kwargs)
+
+
+class BaseClient(APIView):
+
+ def __init__(self):
+ super(BaseClient,self).__init__()
+
+ self.session = requests.Session()
+ for schema in list(self.session.adapters):
+ self.session.mount(schema,TCPKeepAliveAdapter())
+
+ def buildRequest(self,request,vimid,tenantid="",tail=None):
+
+ preUrl = catalog.getEndpointBy(vimid, serverType=self.serverType,interface="public")
+ token = request.META.get('HTTP_X_AUTH_TOKEN', "")
+ tail = "/" + tail if tail else ""
+ tenantid = "/" + tenantid if tenantid else ""
+ endPointURL = preUrl + tenantid + tail
+
+ headers = {"X-Auth-Token": token}
+ headers['Content-Type'] = request.META.get("CONTENT_TYPE","application/json")
+ try:
+ json_req = json.loads(request.body)
+ except Exception as e:
+ json_req = ""
+
+ return (endPointURL,headers,json_req)
+
+
+ def _request(self, url, method,redirect=20,
+ connect_retries=0, connect_retry_delay=0.5, **kwargs):
+
+ try:
+ try:
+ logger.info("%(method)s Request to %(url)s ",{'url':url,'method':method})
+ resp = self.session.request(method, url,verify=False,timeout=30,**kwargs)
+ except requests.exceptions.SSLError as e:
+ msg = 'SSL exception connecting to %(url)s: %(error)s' % {
+ 'url': url, 'error': e}
+ raise exceptions.SSLError(msg)
+ except requests.exceptions.Timeout:
+ msg = 'Request to %s timed out' % url
+ raise exceptions.ConnectTimeout(msg)
+ except requests.exceptions.ConnectionError as e:
+ msg = 'Unable to establish connection to %s: %s' % (url, e)
+ raise exceptions.ConnectionError(msg)
+ except requests.exceptions.RequestException as e:
+ msg = 'Unexpected exception for %(url)s: %(error)s' % {
+ 'url': url, 'error': e}
+ raise exceptions.UnknownConnectionError(msg, e)
+
+ except exceptions.RetriableConnectionFailure as e:
+ if connect_retries <= 0:
+ return Response(data={"error":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ logger.info('Failure: %(e)s. Retrying in %(delay).1fs.',
+ {'e': e, 'delay': connect_retry_delay})
+ time.sleep(connect_retry_delay)
+
+ return self._request(
+ url, method, redirect,
+ connect_retries=connect_retries - 1,
+ connect_retry_delay=connect_retry_delay * 2,
+ **kwargs)
+
+
+ if resp.status_code in [301, 302, 303, 305, 307, 308]:
+
+ if isinstance(redirect, bool):
+ redirect_allowed = redirect
+ else:
+ redirect -= 1
+ redirect_allowed = redirect >= 0
+
+ if not redirect_allowed:
+ return resp
+
+ try:
+ location = resp.headers['location']
+ except KeyError:
+ logger.warning("Failed to redirect request to %s as new "
+ "location was not provided.", resp.url)
+ pass
+
+ else:
+ new_resp = self._request(
+ location, method, redirect,
+ connect_retries=connect_retries,
+ **kwargs)
+
+ if not isinstance(new_resp.history, list):
+ new_resp.history = list(new_resp.history)
+ new_resp.history.insert(0, resp)
+ resp = new_resp
+
+ data,content_type = jsonResponse(resp.content)
+ return Response(data=data, status=resp.status_code,content_type=content_type)
+
+
+ def send(self,request,method,vimid,tenantid="",other="",**kwargs):
+
+ (url, headers, data) = self.buildRequest(request, vimid, tenantid=tenantid, tail=other)
+ kwargs.setdefault('headers', headers)
+
+ if method in ["POST","PUT","PATCH"]:
+ kwargs.setdefault('data', json.dumps(data, encoding='utf-8'))
+
+ return self._request(url,method,**kwargs)
+
+
+ def get(self,request,vimid):
+ raise NotImplementedError()
+
+ def post(self,request,vimid):
+ raise NotImplementedError()
+
+ def put(self,request,vimid):
+ raise NotImplementedError()
+
+ def patch(self,request,vimid):
+ raise NotImplementedError()
+
+ def delete(self,request,vimid):
+ raise NotImplementedError()
+
+ def head(self,request,vimid):
+ raise NotImplementedError()
diff --git a/vio/vio/swagger/views/proxyplugin/identity/__init__.py b/vio/vio/swagger/views/proxyplugin/identity/__init__.py
new file mode 100644
index 0000000..9ac359f
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/identity/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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. \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/identity/views.py b/vio/vio/swagger/views/proxyplugin/identity/views.py
new file mode 100644
index 0000000..c7addc9
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/identity/views.py
@@ -0,0 +1,183 @@
+# Copyright (c) 2017 VMware, 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.
+
+import logging
+from rest_framework import status
+from rest_framework.response import Response
+
+from vio.pub.msapi import extsys
+from vio.pub.exceptions import VimDriverVioException
+from vio.pub.utils.syscomm import catalog
+from vio.pub.config.config import MSB_SERVICE_PORT,MSB_SERVICE_IP
+import json
+import requests
+from collections import defaultdict
+from copy import deepcopy
+
+from vio.swagger.views.proxyplugin.httpclient import BaseClient
+
+logger = logging.getLogger(__name__)
+
+MSB_ADDRESS = MSB_SERVICE_IP+":"+MSB_SERVICE_PORT+"/api"
+
+
+class IdentityServer(BaseClient):
+
+ serverType = 'keystone'
+
+ def get(self,request,vimid,other=None):
+
+ (url,headers,_) = self.buildRequest(request,vimid,tail=other)
+
+ query = ""
+ for k,v in request.GET.items():
+ query+= (k+"="+v)
+ query+="&"
+
+ if query!="":
+ query = query[:-1]
+ url+="/?"+query
+ return self._request(url,method="GET",headers=headers)
+
+ def patch(self,request,vimid,other):
+
+ return self.send(request=request,method="PATCH",vimid=vimid,other=other)
+
+ def post(self,request,vimid,other):
+
+ return self.send(request=request,method="POST",vimid=vimid,other=other)
+
+ def delete(self,request,vimid,other):
+
+ return self.send(request=request,method="DELETE",vimid=vimid,other=other)
+
+ def head(self,request,vimid,other):
+
+ return self.send(request=request,method="HEAD",vimid=vimid,other=other)
+
+
+
+class TokenView(BaseClient):
+
+ serverType = 'identity'
+
+
+ def get(self,request,vimid):
+
+ url_path = request.get_full_path()
+ if url_path[url_path.rfind("identity"):]!="identity/v3":
+ return Response(data={"error":"method not allowed"},status=status.HTTP_405_METHOD_NOT_ALLOWED)
+
+ try:
+ vim_info = extsys.get_vim_by_id(vim_id=vimid)
+ except VimDriverVioException as e:
+ return Response(data={"error": str(e)}, status=e.status_code)
+ except Exception as e:
+ logging.exception("error %s" % e)
+ return Response(data={"error":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+ keystoneURL = vim_info['url']
+ logger.info("vimid(%(vimid)s) get keystone url %(url)s ", {"vimid": vimid, "url": keystoneURL})
+ try:
+ res = requests.get(url=keystoneURL).json()
+ res['version']['links'][0]['href']="http://"+MSB_ADDRESS+"/multivim-vio/v1/"+vimid +"/identity/v3"
+
+
+ except Exception as e:
+ logging.exception("error %s" % e)
+ return Response(data={"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ return Response(data=res, status=status.HTTP_200_OK)
+
+
+ def delete(self,request,vimid):
+
+ (url, headers, _) = self.buildRequest(request, vimid)
+
+ subject_token = request.META.get("HTTP_X_SUBJECT_TOKEN","")
+
+ url+="/auth/tokens"
+ headers["X-Subject-Token"] = subject_token
+ return self._request(url,method="DELETE",headers=headers)
+
+
+ def post(self,request,vimid):
+
+ url_path = request.get_full_path()
+ if url_path[url_path.rfind("identity"):] != "identity/v3/auth/tokens":
+ return Response(data={"error": "method not allowed"}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
+
+ try:
+ create_req = json.loads(request.body)
+ except Exception as e:
+ return Response(data={'error': 'Fail to decode request body %s.' %e},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+
+ try:
+ vim_info = extsys.get_vim_by_id(vimid)
+ except VimDriverVioException as e:
+ return Response(data={'error': str(e)}, status=e.status_code)
+ except Exception as e:
+ logging.exception("error %s" % e)
+ return Response(data={"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ url = vim_info['url']+"/auth/tokens"
+ headers = {"Content-Type": "application/json"}
+ logger.info("vimid(%(vimid)s) request token url %(url)s ", {"vimid": vimid, "url": url})
+
+ try:
+ res = requests.post(url=url, data=json.dumps(create_req), headers=headers)
+ tokenInfo = res.json()
+ resHeader = dict(res.headers)
+ except Exception as e:
+ logging.exception("error %s" % e)
+ return Response(data={'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+
+ try:
+
+ tenantid = tokenInfo['token']['project']['id']
+ vimEndpoints = defaultdict(dict)
+
+ for i in tokenInfo['token']['catalog']:
+ for j in i['endpoints']:
+ tmp = j['url']
+ ends = deepcopy(j['url'])
+ ends = ends.split("/")
+ version = "/"+ends[3] if len(ends) > 3 else ""
+ ends = ends[0]+"//"+ends[2]+version
+ vimEndpoints[i['name']][j['interface']]=ends
+ res=tmp.split("/")
+ if i['type'] in ['image','network','cloudformation','identity']:
+ if i['type'] != 'identity':
+ res[2] = MSB_ADDRESS+"/multivim-vio/v1/" + vimid + "/" + i['name']
+ else:
+ # use identity instead of keystone
+ res[2] = MSB_ADDRESS + "/multivim-vio/v1/" + vimid + "/" + i['type']
+ else:
+ res[2]= MSB_ADDRESS+"/multivim-vio/v1/"+vimid+"/"+i['name']+"/"+tenantid
+ j['url']="http:"+"//"+res[2]
+ except Exception as e:
+ logging.exception("error %s" % e)
+ return Response(data={'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ logger.info("vimid(%(vimid)s) service enpoints %(endpoint)s ",{"vimid":vimid,"endpoint":vimEndpoints})
+ tokenInfo['token']['value'] = resHeader['X-Subject-Token']
+ catalog.storeEndpoint(vimid=vimid, endpoints=vimEndpoints)
+ Res = Response(data=tokenInfo,status=status.HTTP_200_OK)
+ Res['X-Subject-Token']=resHeader['X-Subject-Token']
+ return Res
+
diff --git a/vio/vio/swagger/views/proxyplugin/image/__init__.py b/vio/vio/swagger/views/proxyplugin/image/__init__.py
new file mode 100644
index 0000000..9ac359f
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/image/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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. \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/image/views.py b/vio/vio/swagger/views/proxyplugin/image/views.py
new file mode 100644
index 0000000..ff14eaf
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/image/views.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2017 VMware, 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.
+
+from vio.swagger.views.proxyplugin.httpclient import BaseClient
+
+
+class ImageServer(BaseClient):
+
+ serverType = "glance"
+
+ def get(self,request,vimid,other):
+
+ (url, headers, _) = self.buildRequest(request, vimid, tail=other)
+
+ query = ""
+ for k, v in request.GET.items():
+ query += (k + "=" + v)
+ query += "&"
+
+ if query != "":
+ query = query[:-1]
+ url += "?" + query
+ return self._request(url, method="GET", headers=headers)
+
+
+ def post(self, request, vimid, other):
+
+ return self.send(request=request,method="POST",vimid=vimid,other=other)
+
+
+ def patch(self, request, vimid, other):
+
+ return self.send(request=request,method="PATCH",vimid=vimid,other=other)
+
+ def put(self,request,vimid,other):
+
+ return self.send(request=request,method="PUT",vimid=vimid,other=other)
+
+ def delete(self, request, vimid, other):
+
+ return self.send(request=request,method="DELETE",vimid=vimid,other=other) \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/neutron/__init__.py b/vio/vio/swagger/views/proxyplugin/neutron/__init__.py
new file mode 100644
index 0000000..9ac359f
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/neutron/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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. \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/neutron/views.py b/vio/vio/swagger/views/proxyplugin/neutron/views.py
new file mode 100644
index 0000000..23d01ad
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/neutron/views.py
@@ -0,0 +1,39 @@
+# Copyright (c) 2017 VMware, 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.
+
+from vio.swagger.views.proxyplugin.httpclient import BaseClient
+
+
+
+class NetWorkServer(BaseClient):
+
+ serverType = "neutron"
+
+ def get(self,request,vimid,other=None):
+
+ return self.send(request=request,method="GET",vimid=vimid,other=other)
+
+ def post(self,request,vimid,other):
+
+ return self.send(request=request,method="POST",vimid=vimid,other=other)
+
+ def patch(self, request, vimid, other):
+
+ return self.send(request=request,method="PATCH",vimid=vimid,other=other)
+
+ def put(self, request, vimid, other):
+
+ return self.send(request=request,method="PUT",vimid=vimid,other=other)
+
+ def delete(self, request, vimid, other):
+
+ return self.send(request=request,method="DELETE",vimid=vimid,other=other) \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/nova/__init__.py b/vio/vio/swagger/views/proxyplugin/nova/__init__.py
new file mode 100644
index 0000000..9ac359f
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/nova/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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. \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/nova/views.py b/vio/vio/swagger/views/proxyplugin/nova/views.py
new file mode 100644
index 0000000..6a0a93d
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/nova/views.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2017 VMware, 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.
+
+from vio.swagger.views.proxyplugin.httpclient import BaseClient
+
+
+class ComputeServer(BaseClient):
+
+ serverType = "nova"
+
+ def get(self,request,vimid,tenantid,other):
+
+ (url, headers, _) = self.buildRequest(request, vimid, tenantid=tenantid,tail=other)
+ query = ""
+ for k, v in request.GET.items():
+ query += (k + "=" + v)
+ query += "&"
+
+ if query != "":
+ query = query[:-1]
+ url += "?" + query
+ return self._request(url, method="GET", headers=headers)
+
+ def post(self,request,vimid,tenantid,other):
+
+ return self.send(request=request,method="POST",vimid=vimid,tenantid=tenantid,other=other)
+
+ def put(self,request,vimid,tenantid,other):
+
+ return self.send(request=request,method="PUT",vimid=vimid,tenantid=tenantid,other=other)
+
+ def delete(self,request,vimid,tenantid,other):
+
+ return self.send(request=request,method="DELETE",vimid=vimid,tenantid=tenantid,other=other)
diff --git a/vio/vio/swagger/views/proxyplugin/volumn/__init__.py b/vio/vio/swagger/views/proxyplugin/volumn/__init__.py
new file mode 100644
index 0000000..9ac359f
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/volumn/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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. \ No newline at end of file
diff --git a/vio/vio/swagger/views/proxyplugin/volumn/views.py b/vio/vio/swagger/views/proxyplugin/volumn/views.py
new file mode 100644
index 0000000..8eccce9
--- /dev/null
+++ b/vio/vio/swagger/views/proxyplugin/volumn/views.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2017 VMware, 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.
+
+from vio.swagger.views.proxyplugin.httpclient import BaseClient
+
+
+class VolumeServer(BaseClient):
+
+ serverType = "cinder"
+
+ def get(self,request,vimid,tenantid,other):
+
+ return self.send(request=request,method="GET",vimid=vimid,tenantid=tenantid,other=other)
+
+ def post(self,request,vimid,tenantid,other):
+
+ return self.send(request=request,method="POST",vimid=vimid,tenantid=tenantid,other=other)
+
+ def put(self, request, vimid, tenantid, other):
+
+ return self.send(request=request,method="PUT",vimid=vimid,tenantid=tenantid,other=other)
+
+ def delete(self, request, vimid, tenantid, other):
+
+ return self.send(request=request,method="DELETE",vimid=vimid,tenantid=tenantid,other=other)
+
+ def patch(self, request, vimid, tenantid, other):
+
+ return self.send(request=request,method="PATCH",vimid=vimid,tenantid=tenantid,other=other)
+
+
+class VolumeServer2(VolumeServer):
+ serverType = "cinderv2"
+
+class VolumeServer3(VolumeServer):
+ serverType = "volumev3"
+
+
+
+
+
+
+
+