From 8323156d2e7c951a5a70a7ab4796990fa1d6848f Mon Sep 17 00:00:00 2001 From: "ying.yunlong" Date: Fri, 1 Sep 2017 13:43:11 +0800 Subject: [PATCH] SVNFM driver align ESR rest interface As ESR move to AAI, its rest api is changed, SVNFM driver align ESR new rest interface. Change-Id: If6ea6e8f5eb58aea277decd740fb839c0390148c Issue-ID: VFC-223 Signed-off-by: ying.yunlong --- zte/vmanager/driver/interfaces/tests.py | 64 +++++++++++++++---------------- zte/vmanager/driver/interfaces/views.py | 7 +++- zte/vmanager/driver/pub/config/config.py | 10 +++++ zte/vmanager/driver/pub/utils/restcall.py | 53 ++++++++++++++++++++++++- zte/vmanager/driver/settings.py | 4 ++ 5 files changed, 102 insertions(+), 36 deletions(-) diff --git a/zte/vmanager/driver/interfaces/tests.py b/zte/vmanager/driver/interfaces/tests.py index cfdf6902..cebc8c51 100644 --- a/zte/vmanager/driver/interfaces/tests.py +++ b/zte/vmanager/driver/interfaces/tests.py @@ -27,8 +27,9 @@ class InterfacesTest(TestCase): def tearDown(self): pass + @mock.patch.object(restcall, 'call_req_aai') @mock.patch.object(restcall, 'call_req') - def test_instantiate_vnf_001(self, mock_call_req): + def test_instantiate_vnf_001(self, mock_call_req, mock_call_req_aai): """ Initate_VNF """ @@ -96,9 +97,11 @@ class InterfacesTest(TestCase): u'operationalState': u'Disabled', u'createTime': u'2016-10-31 16:21:11', u'size': u'12.1 MB'} - ret = [0, json.JSONEncoder().encode({"vnfInstanceId":"8", - "jobid":"NF-CREATE-8-b384535c-9f45-11e6-8749-fa163e91c2f9"}), - '200'] + inst_response = { + u'vnfInstanceId': u'8', + u'jobid': u'NF-CREATE-8-b384535c-9f45-11e6-8749-fa163e91c2f9' + } + ret = [0, json.JSONEncoder().encode(inst_response), '200'] r1 = [0, json.JSONEncoder().encode(vnfm_info), "200"] @@ -106,8 +109,8 @@ class InterfacesTest(TestCase): r3 = [0, json.JSONEncoder().encode(packageInfo), "200"] - - mock_call_req.side_effect = [r1, r2, r3, ret] + mock_call_req_aai.side_effect =[r1] + mock_call_req.side_effect = [r2, r3, ret] req_data = {'vnfInstanceName': 'VFW_f88c0cb7-512a-44c4-bd09-891663f19367', 'vnfPackageId': 'd852e1be-0aac-48f1-b1a4-cd825f6cdf9a', @@ -128,8 +131,9 @@ class InterfacesTest(TestCase): expect_resp_data = {"jobid": "NF-CREATE-8-b384535c-9f45-11e6-8749-fa163e91c2f9", "vnfInstanceId": "8"} self.assertEqual(expect_resp_data, response.data) + @mock.patch.object(restcall, 'call_req_aai') @mock.patch.object(restcall, 'call_req') - def test_terminate_vnf__002(self, mock_call_req): + def test_terminate_vnf__002(self, mock_call_req, mock_call_req_aai): """ Terminate_VNF """ @@ -148,7 +152,8 @@ class InterfacesTest(TestCase): "createTime": "2016-07-06 15:33:18"}), "200"] r2 = [0, json.JSONEncoder().encode({"vnfInstanceId": "1", "JobId": "1"}), "200"] - mock_call_req.side_effect = [r1, r2] + mock_call_req_aai.side_effect = [r1] + mock_call_req.side_effect = [r2] response = self.client.post("/api/ztevmanagerdriver/v1/ztevnfmid/vnfs/vbras_innstance_id/terminate") @@ -156,8 +161,9 @@ class InterfacesTest(TestCase): expect_resp_data = {"jobid": "1", "vnfInstanceId": "1"} self.assertEqual(expect_resp_data, response.data) + @mock.patch.object(restcall, 'call_req_aai') @mock.patch.object(restcall, 'call_req') - def test_query_vnf_003(self, mock_call_req): + def test_query_vnf_003(self, mock_call_req, mock_call_req_aai): """ Query_VNF """ @@ -176,7 +182,8 @@ class InterfacesTest(TestCase): "createTime": "2016-07-06 15:33:18"}), "200"] r2 = [0, json.JSONEncoder().encode({"vnfinstancestatus": "1"}), "200"] - mock_call_req.side_effect = [r1, r2] + mock_call_req_aai.side_effect = [r1] + mock_call_req.side_effect = [r2] response = self.client.get("/api/ztevmanagerdriver/v1/ztevnfmid/vnfs/vbras_innstance_id") @@ -185,8 +192,9 @@ class InterfacesTest(TestCase): expect_resp_data = {"vnfInfo": {"vnfStatus": "1"}} self.assertEqual(expect_resp_data, response.data) + @mock.patch.object(restcall, 'call_req_aai') @mock.patch.object(restcall, 'call_req') - def test_operation_status_004(self, mock_call_req): + def test_operation_status_004(self, mock_call_req, mock_call_req_aai): """ Operation_status """ @@ -216,7 +224,8 @@ class InterfacesTest(TestCase): "jobid": "NF-CREATE-11-ec6c2f2a-9f48-11e6-9405-fa163e91c2f9"} r1 = [0, json.JSONEncoder().encode(vnfm_info), '200'] r2 = [0, json.JSONEncoder().encode(resp_body), '200'] - mock_call_req.side_effect = [r1, r2] + mock_call_req_aai.side_effect = [r1] + mock_call_req.side_effect = [r2] response = self.client.get("/api/ztevmanagerdriver/v1/{vnfmid}/jobs/{jobid}?responseId={responseId}". format( vnfmid=vnfm_info["vnfmId"], @@ -271,21 +280,7 @@ class InterfacesTest(TestCase): """ Notification """ - r1 = [0, json.JSONEncoder().encode({ - "vnfmId": "19ecbb3a-3242-4fa3-9926-8dfb7ddc29ee", - "name": "g_vnfm", - "type": "vnfm", - "vimId": "", - "vendor": "ZTE", - "version": "v1.0", - "description": "vnfm", - "certificateUrl": "", - "url": "http://10.74.44.11", - "userName": "admin", - "password": "admin", - "createTime": "2016-07-06 15:33:18"}), "200"] - - r2 = [0, json.JSONEncoder().encode( + r1 = [0, json.JSONEncoder().encode( {"vim": { "vimInfoId": "111111", @@ -334,7 +329,7 @@ class InterfacesTest(TestCase): "vmflavor": "CMP", "vmnumber": "3", "vmidlist ": ["vmuuid"]}]} - mock_call_req.side_effect = [r1, r2] + mock_call_req.side_effect = [r1] response = self.client.post("/api/ztevmanagerdriver/v1/vnfs/lifecyclechangesnotification", data=json.dumps(req_data), content_type='application/json') @@ -343,9 +338,9 @@ class InterfacesTest(TestCase): expect_resp_data = None self.assertEqual(expect_resp_data, response.data) - + @mock.patch.object(restcall, 'call_req_aai') @mock.patch.object(restcall, 'call_req') - def test_scale(self,mock_call_req): + def test_scale(self, mock_call_req, mock_call_req_aai): job_info = {"jobid":"801","nfInstanceId":"101"} vnfm_info = {u'userName': u'admin', u'vendor': u'ZTE', @@ -362,7 +357,8 @@ class InterfacesTest(TestCase): ret = [0, json.JSONEncoder().encode(job_info), "202"] ret_vnfm = [0,json.JSONEncoder().encode(vnfm_info), "200"] - mock_call_req.side_effect = [ret_vnfm, ret] + mock_call_req_aai.side_effect = [ret_vnfm] + mock_call_req.side_effect = [ret] vnfd_info = { "vnf_flavours":[ @@ -420,8 +416,9 @@ class InterfacesTest(TestCase): self.assertEqual(str(status.HTTP_202_ACCEPTED), response.status_code) self.assertDictEqual(job_info, response.data) + @mock.patch.object(restcall, 'call_req_aai') @mock.patch.object(restcall, 'call_req') - def test_heal(self,mock_call_req): + def test_heal(self, mock_call_req, mock_call_req_aai): job_info = {"jobid": "12234455", "nfInstanceId": "10144445666"} vnfm_info = {u'userName': u'admin', u'vendor': u'ZTE', @@ -438,7 +435,8 @@ class InterfacesTest(TestCase): ret = [0, json.JSONEncoder().encode(job_info), "202"] ret_vnfm = [0, json.JSONEncoder().encode(vnfm_info), "200"] - mock_call_req.side_effect = [ret_vnfm, ret] + mock_call_req_aai.side_effect = [ret_vnfm] + mock_call_req.side_effect = [ret] heal_vnf_data = { 'action': 'vmReset', diff --git a/zte/vmanager/driver/interfaces/views.py b/zte/vmanager/driver/interfaces/views.py index 50e71a16..dc94f838 100644 --- a/zte/vmanager/driver/interfaces/views.py +++ b/zte/vmanager/driver/interfaces/views.py @@ -21,7 +21,7 @@ from rest_framework.decorators import api_view from rest_framework.response import Response from driver.pub.utils import restcall -from driver.pub.utils.restcall import req_by_msb +from driver.pub.utils.restcall import req_by_msb, call_aai logger = logging.getLogger(__name__) @@ -58,7 +58,7 @@ query_package_url = "api/nslcm/v1/vnfpackage/%s" # Query VNFM by VNFMID def vnfm_get(vnfmid): - ret = req_by_msb("api/extsys/v1/vnfms/%s" % vnfmid, "GET") + ret = call_aai("api/aai-esr-server/v1/vnfms/%s" % vnfmid, "GET") return ret @@ -117,6 +117,7 @@ def instantiate_vnf(request, *args, **kwargs): data["NFVOID"] = 1 data["VNFMID"] = vnfm_id vnfdId = ignorcase_get(packageInfo, "vnfdId") + # TODO convert sdc vnf package to vnf vender package from urlparse import urlparse vnfm_ip = urlparse(ignorcase_get(vnfm_info, "url")).netloc.split(':')[0] VNFS = ["SPGW", "MME"] @@ -141,6 +142,7 @@ def instantiate_vnf(request, *args, **kwargs): data["extension"]["vnfid"] = data["VNFD"] data["extension"]["multivim"] = 0 logger.debug("[%s] call_req data=%s", fun_name(), data) + ret = restcall.call_req( base_url=ignorcase_get(vnfm_info, "url"), user=ignorcase_get(vnfm_info, "userName"), @@ -149,6 +151,7 @@ def instantiate_vnf(request, *args, **kwargs): resource=create_vnf_url, method='post', content=json.JSONEncoder().encode(data)) + logger.debug("[%s] call_req ret=%s", fun_name(), ret) if ret[0] != 0: return Response(data={'error': ret[1]}, status=ret[2]) diff --git a/zte/vmanager/driver/pub/config/config.py b/zte/vmanager/driver/pub/config/config.py index 346aaaf3..f0d85d07 100644 --- a/zte/vmanager/driver/pub/config/config.py +++ b/zte/vmanager/driver/pub/config/config.py @@ -12,6 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +# [AAI] +AAI_SERVICE_IP = '127.0.0.1' +AAI_SERVICE_PORT = '8443' +AAI_BASE_URL = "https://%s:%s/aai/v8" % (AAI_SERVICE_IP, AAI_SERVICE_PORT) +AAI_USER = "AAI" +AAI_PASSWORD = "AAI" +CLOUD_OWNER = "11" +CLOUD_REGION_ID = "" +TENANT_ID = "" + # [MSB] MSB_SERVICE_IP = '127.0.0.1' MSB_SERVICE_PORT = '80' diff --git a/zte/vmanager/driver/pub/utils/restcall.py b/zte/vmanager/driver/pub/utils/restcall.py index 59c6013e..8efe0afb 100644 --- a/zte/vmanager/driver/pub/utils/restcall.py +++ b/zte/vmanager/driver/pub/utils/restcall.py @@ -19,7 +19,7 @@ import urllib2 import uuid import httplib2 -from driver.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT +from driver.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT, AAI_BASE_URL, AAI_USER, AAI_PASSWORD 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' @@ -93,3 +93,54 @@ def combine_url(base_url, resource): else: full_url = base_url + '/' + resource return full_url + +def call_req_aai(base_url, user, passwd, auth_type, resource, method, 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)) + ret = None + resp_status = '' + try: + full_url = combine_url(base_url, resource) + headers = {'content-type': 'application/json', 'accept': 'application/json', + 'X-FromAppId': 'VFC-SVNFM-ZTE-DRIVER', 'X-TransactionId': str(uuid.uuid1())} + if user: + 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)) + 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)) + if resp_status in status_ok_list: + ret = [0, resp_body, resp_status] + else: + ret = [1, resp_body, resp_status] + break + except Exception as ex: + if 'httplib.ResponseNotReady' in str(sys.exc_info()): + logger.debug("retry_times=%d", retry_times) + logger.error(traceback.format_exc()) + ret = [1, "Unable to connect to %s" % full_url, resp_status] + continue + raise ex + except urllib2.URLError as err: + ret = [2, str(err), resp_status] + except Exception as ex: + logger.error(traceback.format_exc()) + 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 + ret = [3, res_info, resp_status] + except: + logger.error(traceback.format_exc()) + ret = [4, str(sys.exc_info()), resp_status] + + logger.debug("[%s]ret=%s" % (callid, str(ret))) + return ret + +def call_aai(resource, method, data=''): + return call_req_aai(AAI_BASE_URL, AAI_USER, AAI_PASSWORD, rest_no_auth, resource, method, data) diff --git a/zte/vmanager/driver/settings.py b/zte/vmanager/driver/settings.py index dac23585..6af1f267 100644 --- a/zte/vmanager/driver/settings.py +++ b/zte/vmanager/driver/settings.py @@ -16,6 +16,8 @@ import os import sys # Build paths inside the project like this: os.path.join(BASE_DIR, ...) +from driver.pub.config import config + BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -115,6 +117,8 @@ LOGGING = { 'propagate': False}, }} if 'test' in sys.argv: + config.REG_TO_MSB_WHEN_START = False + REST_FRAMEWORK = {} import platform if platform.system() == 'Linux': TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' -- 2.16.6