summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--newton/newton/pub/exceptions.py6
-rw-r--r--newton/newton/pub/msapi/extsys.py21
-rw-r--r--newton/newton/pub/utils/restcall.py57
-rw-r--r--[-rwxr-xr-x]newton/newton/pub/utils/share_lock.py0
-rw-r--r--newton/newton/requests/__init__.py13
-rw-r--r--newton/newton/requests/tests/__init__.py13
-rw-r--r--newton/newton/requests/tests/test_reqeust.py26
-rw-r--r--newton/newton/requests/urls.py25
-rw-r--r--newton/newton/requests/views.py151
-rw-r--r--newton/newton/urls.py9
10 files changed, 295 insertions, 26 deletions
diff --git a/newton/newton/pub/exceptions.py b/newton/newton/pub/exceptions.py
index dff87e8a..b750d0a8 100644
--- a/newton/newton/pub/exceptions.py
+++ b/newton/newton/pub/exceptions.py
@@ -11,4 +11,8 @@
class VimDriverNewtonException(Exception):
- pass
+ def __init__(self, message, status_code="", content=""):
+ super(VimDriverNewtonException, self).__init__(message)
+ self.status_code = status_code
+ self.content = content
+ pass
diff --git a/newton/newton/pub/msapi/extsys.py b/newton/newton/pub/msapi/extsys.py
index 748d33a9..297d4716 100644
--- a/newton/newton/pub/msapi/extsys.py
+++ b/newton/newton/pub/msapi/extsys.py
@@ -19,16 +19,19 @@ logger = logging.getLogger(__name__)
def get_vims():
- ret = req_by_msb("/openoapi/extsys/v1/vims", "GET")
- if ret[0] != 0:
- logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ retcode, content, status_code = \
+ req_by_msb("/openoapi/extsys/v1/vims", "GET")
+ if retcode != 0:
+ logger.error("Status code is %s, detail is %s.", status_code, content)
raise VimDriverNewtonException("Failed to query VIMs from extsys.")
- return json.JSONDecoder().decode(ret[1])
+ return json.JSONDecoder().decode(content)
def get_vim_by_id(vim_id):
- ret = req_by_msb("/openoapi/extsys/v1/vims/%s" % vim_id, "GET")
- if ret[0] != 0:
- logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
- raise VimDriverNewtonException("Failed to query VIM with id (%s) from extsys." % vim_id)
- return json.JSONDecoder().decode(ret[1])
+ retcode, content, status_code = \
+ req_by_msb("/openoapi/extsys/v1/vims/%s" % vim_id, "GET")
+ if retcode != 0:
+ logger.error("Status code is %s, detail is %s.", status_code, content)
+ raise VimDriverNewtonException(
+ "Failed to query VIM with id (%s) from extsys." % vim_id)
+ return json.JSONDecoder().decode(content)
diff --git a/newton/newton/pub/utils/restcall.py b/newton/newton/pub/utils/restcall.py
index 6f9f9d8b..7f372982 100644
--- a/newton/newton/pub/utils/restcall.py
+++ b/newton/newton/pub/utils/restcall.py
@@ -19,14 +19,19 @@ import httplib2
from newton.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT
rest_no_auth, rest_oneway_auth, rest_bothway_auth = 0, 1, 2
-HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED = '200', '201', '204', '202'
-status_ok_list = [HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED]
-HTTP_404_NOTFOUND, HTTP_403_FORBIDDEN, HTTP_401_UNAUTHORIZED, HTTP_400_BADREQUEST = '404', '403', '401', '400'
+HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED \
+ = '200', '201', '204', '202'
+status_ok_list \
+ = [HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED]
+HTTP_404_NOTFOUND, HTTP_403_FORBIDDEN, \
+ HTTP_401_UNAUTHORIZED, HTTP_400_BADREQUEST = '404', '403', '401', '400'
+MAX_RETRY_TIME = 3
logger = logging.getLogger(__name__)
-def call_req(base_url, user, passwd, auth_type, resource, method, content=''):
+def call_req(base_url, user, passwd, auth_type,
+ resource, method, extra_headers='', content=''):
callid = str(uuid.uuid1())
logger.debug("[%s]call_req('%s','%s','%s',%s,'%s','%s','%s')" % (
callid, base_url, user, passwd, auth_type, resource, method, content))
@@ -34,17 +39,31 @@ def call_req(base_url, user, passwd, auth_type, resource, method, content=''):
resp_status = ''
try:
full_url = combine_url(base_url, resource)
- headers = {'content-type': 'application/json', 'accept': 'application/json'}
+ headers = {
+ 'content-type': 'application/json',
+ 'accept': 'application/json'
+ }
+
+ if extra_headers:
+ headers.update(extra_headers)
if user:
- headers['Authorization'] = 'Basic ' + ('%s:%s' % (user, passwd)).encode("base64")
+ headers['Authorization'] = \
+ 'Basic ' + ('%s:%s' % (user, passwd)).encode("base64")
ca_certs = None
- for retry_times in range(3):
- http = httplib2.Http(ca_certs=ca_certs, disable_ssl_certificate_validation=(auth_type == rest_no_auth))
+ for retry_times in range(MAX_RETRY_TIME):
+ http = httplib2.Http(
+ ca_certs=ca_certs,
+ disable_ssl_certificate_validation=(auth_type == rest_no_auth))
http.follow_all_redirects = True
try:
- resp, resp_content = http.request(full_url, method=method.upper(), body=content, headers=headers)
- resp_status, resp_body = resp['status'], resp_content.decode('UTF-8')
- logger.debug("[%s][%d]status=%s,resp_body=%s)" % (callid, retry_times, resp_status, resp_body))
+ resp, resp_content = http.request(full_url,
+ method=method.upper(),
+ body=content,
+ headers=headers)
+ resp_status, resp_body = \
+ resp['status'], resp_content.decode('UTF-8')
+ logger.debug("[%s][%d]status=%s,resp_body=%s)" %
+ (callid, retry_times, resp_status, resp_body))
if resp_status in status_ok_list:
ret = [0, resp_body, resp_status]
else:
@@ -64,7 +83,8 @@ def call_req(base_url, user, passwd, auth_type, resource, method, content=''):
logger.error("[%s]ret=%s" % (callid, str(sys.exc_info())))
res_info = str(sys.exc_info())
if 'httplib.ResponseNotReady' in res_info:
- res_info = "The URL[%s] request failed or is not responding." % full_url
+ res_info = ("The URL[%s] request failed or is not responding." %
+ full_url)
ret = [3, res_info, resp_status]
except:
logger.error(traceback.format_exc())
@@ -76,11 +96,22 @@ def call_req(base_url, user, passwd, auth_type, resource, method, content=''):
def req_by_msb(resource, method, content=''):
base_url = "http://%s:%s/" % (MSB_SERVICE_IP, MSB_SERVICE_PORT)
- return call_req(base_url, "", "", rest_no_auth, resource, method, content)
+ logger.debug("Networks--get::> %s" % "33")
+ return call_req(base_url, "", "", rest_no_auth,
+ resource, method, "", content)
+
+
+def req_to_vim(base_url, resource, method, extra_headers='', content=''):
+ return call_req(base_url, "", "", rest_no_auth,
+ resource, method, extra_headers, content)
def combine_url(base_url, resource):
full_url = None
+
+ if not resource:
+ return base_url
+
if base_url.endswith('/') and resource.startswith('/'):
full_url = base_url[:-1] + resource
elif base_url.endswith('/') and not resource.startswith('/'):
diff --git a/newton/newton/pub/utils/share_lock.py b/newton/newton/pub/utils/share_lock.py
index aba599a2..aba599a2 100755..100644
--- a/newton/newton/pub/utils/share_lock.py
+++ b/newton/newton/pub/utils/share_lock.py
diff --git a/newton/newton/requests/__init__.py b/newton/newton/requests/__init__.py
new file mode 100644
index 00000000..48b6e44b
--- /dev/null
+++ b/newton/newton/requests/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2017 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.
diff --git a/newton/newton/requests/tests/__init__.py b/newton/newton/requests/tests/__init__.py
new file mode 100644
index 00000000..48b6e44b
--- /dev/null
+++ b/newton/newton/requests/tests/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2017 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.
diff --git a/newton/newton/requests/tests/test_reqeust.py b/newton/newton/requests/tests/test_reqeust.py
new file mode 100644
index 00000000..bae2b84b
--- /dev/null
+++ b/newton/newton/requests/tests/test_reqeust.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2017 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.test import TestCase
+
+
+class TestNetworksRequest(TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def assert_true_result(self):
+ self.assertTrue(1)
diff --git a/newton/newton/requests/urls.py b/newton/newton/requests/urls.py
new file mode 100644
index 00000000..f832eec4
--- /dev/null
+++ b/newton/newton/requests/urls.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2017 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 . import views
+
+urlpatterns = [
+ url(r'^networks(/(?P<networkid>[0-9a-zA-Z_-]+))?', views.Networks.as_view()),
+ url(r'^subnets/(?P<subnetid>[0-9a-zA-Z_-]+)', views.Subnets.as_view()),
+]
+
+urlpatterns = format_suffix_patterns(urlpatterns)
diff --git a/newton/newton/requests/views.py b/newton/newton/requests/views.py
new file mode 100644
index 00000000..0333f86c
--- /dev/null
+++ b/newton/newton/requests/views.py
@@ -0,0 +1,151 @@
+# Copyright (c) 2017 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.
+import logging
+import json
+from json import JSONEncoder
+
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from newton.pub.utils.restcall import req_to_vim
+from newton.pub.exceptions import VimDriverNewtonException
+from newton.pub.msapi.extsys import get_vim_by_id
+
+logger = logging.getLogger(__name__)
+
+
+class VimDriverUtils(object):
+ @staticmethod
+ def get_vim_info(vimid):
+ # get vim info from local cache firstly
+ # if cache miss, get it from ESR service
+ vim = get_vim_by_id(vimid)
+ return vim
+
+ @staticmethod
+ def relay_request_to_vim_service(vimid, tenantid, request, service_type,
+ req_resouce, req_content=""):
+ """
+ if there is no token cache, do auth
+ if there is, use token directly
+ if response is 'need auth', do auth
+ get the use extractor to get token
+ and service rul and then do request
+ """
+ vim = VimDriverUtils.get_vim_info(vimid)
+ auth_resouce = "/tokens"
+ method = "POST"
+ headers = ""
+ r_content_dict = {
+ "auth": {
+ "tenantName": vim["tenant"],
+ "passwordCredentials": {
+ "username": vim["userName"],
+ "password": vim["password"]
+ }
+ }
+ }
+ r_content = JSONEncoder().encode(r_content_dict)
+ retcode, content, status_code = \
+ req_to_vim(vim["url"], auth_resouce, method, headers, r_content)
+ if retcode != 0:
+ logger.error("Status code is %s, detail is %s.",
+ status_code, content)
+ raise VimDriverNewtonException("Fail to authorize",
+ status_code, content)
+ else:
+ # extract token id and issue the get request
+ json_content = None
+ auth_resp = json.JSONDecoder().decode(content)
+ tokenid, svcurl = VimDriverUtils.extractor(auth_resp, service_type)
+ method = request.method
+ headers = {'X-Auth-Token': tokenid}
+ retcode, content, status_code = \
+ req_to_vim(svcurl, req_resouce, method, headers, req_content)
+ if retcode != 0:
+ logger.error("Status code is %s, detail is %s.",
+ status_code, content)
+ raise VimDriverNewtonException("Fail to complte request",
+ status_code, content)
+ else:
+ json_content = json.JSONDecoder().decode(content)
+ vim_dict = {
+ "vimName": vim["name"],
+ "vimId": vim["vimId"],
+ "tenantId": tenantid,
+ }
+ json_content.update(vim_dict)
+ return status_code, json_content
+
+ @staticmethod
+ def extractor(resp_data, service_type):
+ try:
+ tokenid = resp_data["access"]["token"]["id"]
+ sc = resp_data["access"]["serviceCatalog"]
+ service = [svc for svc in sc if svc["type"] == service_type]
+ return tokenid, service[0]["endpoints"][0]["publicURL"]
+ except Exception:
+ raise Exception(
+ "There is no valid %s token or service info" % service_type)
+
+
+class Networks(APIView):
+ SERVICE = "network"
+ keys_map_resp = [
+ ("provider:segmentation_id", "segmentationId"),
+ ("provider:physical_network", "physicalNetwork"),
+ ("router:external", "routerExternal"),
+ ("provider:network_type", "networkType"),
+ ("vlan_transparent", "vlanTransparent"),
+ ]
+
+ def get(self, request, vimid="", tenantid="", networkid=""):
+ logger.debug("Networks--get::> %s" % request.data)
+ try:
+ # prepare request resource to vim instance
+ req_resouce = "v2.0/networks"
+ full_path = request.get_full_path()
+ if '?' in full_path:
+ _, query = request.get_full_path().split('?')
+ req_resouce += "?%s" % query
+ status_code, content = VimDriverUtils.relay_request_to_vim_service(
+ vimid, tenantid, request, self.SERVICE, req_resouce)
+
+ logger.debug("response content after11: %s" % content)
+ # convert the key naming in networks
+ for network in content["networks"]:
+ for k in self.keys_map_resp:
+ v = network.pop(k[0], None)
+ if v:
+ network[k[1]] = v
+ logger.debug("response content after: %s" % content)
+ return Response(data=content, status=status_code)
+ except VimDriverNewtonException as e:
+ return Response(data=e.content, status=e.status_code)
+ except Exception as e:
+ return Response(data={'error': e},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def post(self, request, tenantid=""):
+ logger.debug("Networks--post::> %s" % request.data)
+ pass
+
+ def delete(self, request):
+ logger.debug("Networks--delete::> %s" % request.data)
+ pass
+
+
+class Subnets(APIView):
+ pass
diff --git a/newton/newton/urls.py b/newton/newton/urls.py
index 94ca0bc4..ad2979ff 100644
--- a/newton/newton/urls.py
+++ b/newton/newton/urls.py
@@ -10,16 +10,19 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
from django.conf.urls import include, url
-from newton.pub.config.config import REG_TO_MSB_WHEN_START, REG_TO_MSB_REG_URL, REG_TO_MSB_REG_PARAM
+from newton.pub.config.config \
+ import REG_TO_MSB_WHEN_START, REG_TO_MSB_REG_URL, REG_TO_MSB_REG_PARAM
urlpatterns = [
url(r'^', include('newton.swagger.urls')),
url(r'^', include('newton.samples.urls')),
+ url(r'^openoapi/multivim-newton/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ '(?P<tenantid>[0-9a-zA-Z_-]+)/', include('newton.requests.urls')),
]
-#url(r'^', include('newton.forward.urls')),
# regist to MSB when startup
if REG_TO_MSB_WHEN_START:
import json
from newton.pub.utils.restcall import req_by_msb
- req_by_msb(REG_TO_MSB_REG_URL, "POST", json.JSONEncoder().encode(REG_TO_MSB_REG_PARAM))
+ req_by_msb(REG_TO_MSB_REG_URL, "POST",
+ json.JSONEncoder().encode(REG_TO_MSB_REG_PARAM))