NSHealService(self.ns_inst_id, data, self.job_id).run()
self.assertEqual(NSInstModel.objects.get(id=self.ns_inst_id).status, NS_INST_STATUS.HEALING)
- def test_swagger_ok(self):
- resp = self.client.get("/api/nslcm/v1/swagger.json", format='json')
- self.assertEqual(resp.status_code, status.HTTP_200_OK)
-
@mock.patch.object(NSHealService, "start")
def test_ns_heal_non_existing_ns(self, mock_start):
mock_start.side_effect = NSLCMException("NS Not Found")
self.assertEqual(resp.status_code, status.HTTP_200_OK)
"""
- def test_swagger_ok(self):
- resp = self.client.get("/api/nslcm/v1/swagger.json", format='json')
- self.assertEqual(resp.status_code, status.HTTP_200_OK)
+ # def test_swagger_ok(self):
+ # resp = self.client.get("/api/nslcm/v1/swagger.json", format='json')
+ # self.assertEqual(resp.status_code, status.HTTP_200_OK)
NSInstModel.objects.all().delete()
NfInstModel.objects.all().delete()
- @mock.patch.object(TerminateNsService, 'do_biz')
+ @mock.patch.object(TerminateNsService, 'run')
def test_terminate_vnf_url(self, mock_run):
+ mock_run.re.return_value = None
req_data = {
"terminationType": "forceful",
"gracefulTerminationTimeout": "600"}
response = self.client.delete("/api/nslcm/v1/ns/%s" % self.ns_inst_id)
self.failUnlessEqual(status.HTTP_204_NO_CONTENT, response.status_code)
- @mock.patch.object(restcall, "call_req")
+ @mock.patch.object(restcall, 'call_req')
def test_terminate_vnf(self, mock_call_req):
job_id = JobUtil.create_job("VNF", JOB_TYPE.TERMINATE_VNF, self.nf_inst_id)
mock_call_req.side_effect = side_effect
- TerminateNsService(self.nf_inst_id, "forceful", "600", job_id).start()
+ TerminateNsService(self.nf_inst_id, "forceful", "600", job_id).run()
nsinst = NSInstModel.objects.get(id=self.ns_inst_id)
if nsinst:
self.assertTrue(1, 0)
import json
import logging
+import uuid
from lcm.pub.exceptions import NSLCMException
from lcm.pub.utils import restcall
def call_aai(resource, method, content=''):
+ additional_headers = {
+ 'X-FromAppId': 'VFC-NFVO-LCM',
+ 'X-TransactionId': str(uuid.uuid1())
+ }
return restcall.call_req(base_url=AAI_BASE_URL,
user=AAI_USER,
passwd=AAI_PASSWD,
auth_type=restcall.rest_no_auth,
resource=resource,
method=method,
- content=content)
+ content=content,
+ additional_headers=additional_headers)
+def create_ns_aai(global_customer_id, service_type, service_instance_id, data):
+ resource = "/business/customers/customer/%s/service-subscriptions/service-subscription/" \
+ "%s/service-instances/service-instance/%s" % \
+ (global_customer_id, service_type, service_instance_id)
+ ret = call_aai(resource, "PUT", data)
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise NSLCMException("Ns instance creation exception in AAI")
+ return json.JSONDecoder().decode(ret[1])
+
+def delete_ns_aai(global_customer_id, service_type, service_instance_id, data):
+ resource = "/business/customers/customer/%s/service-subscriptions/service-subscription/" \
+ "%s/service-instances/service-instance/%s" % \
+ (global_customer_id, service_type, service_instance_id)
+ ret = call_aai(resource, "DELETE", data)
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise NSLCMException("Ns instance delete exception in AAI")
+ return json.JSONDecoder().decode(ret[1])
+
+def query_ns_aai(global_customer_id, service_type, service_instance_id, data):
+ resource = "/business/customers/customer/%s/service-subscriptions/service-subscription/" \
+ "%s/service-instances/service-instance/%s" % \
+ (global_customer_id, service_type, service_instance_id)
+ ret = call_aai(resource, "GET", data)
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise NSLCMException("Ns instance query exception in AAI")
+ return json.JSONDecoder().decode(ret[1])
+
+def create_vnf_aai(vnf_id, data):
+ resource = "/network/generic-vnfs/generic-vnf/%s" % vnf_id
+ ret = call_aai(resource, "PUT", data)
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise NSLCMException("Vnf instance creation exception in AAI")
+ return json.JSONDecoder().decode(ret[1])
+
+def delete_vnf_aai(vnf_id, data=''):
+ resource = "/network/generic-vnfs/generic-vnf/%s" % vnf_id
+ ret = call_aai(resource, "DELETE", data)
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise NSLCMException("Vnf instance delete exception in AAI")
+ return json.JSONDecoder().decode(ret[1])
+
+def query_vnf_aai(vnf_id, data):
+ resource = "/network/generic-vnfs/generic-vnf/%s" % vnf_id
+ ret = call_aai(resource, "GET", data)
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise NSLCMException("Vnf instance query exception in AAI")
+ return json.JSONDecoder().decode(ret[1])
ASSETTYPE_SERVICES = "services"
def call_sdc(resource, method, content=''):
+ additional_headers = {
+ 'X-ECOMP-InstanceID': 'VFC-NFVO-LCM'
+ }
return restcall.call_req(base_url=SDC_BASE_URL,
user=SDC_USER,
passwd=SDC_PASSWD,
auth_type=restcall.rest_no_auth,
resource=resource,
method=method,
- content=content)
+ content=content,
+ additional_headers=additional_headers)
def get_artifacts(asset_type):
resource = "/sdc/v1/catalog/{assetType}"
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,
+ content='', additional_headers={}):
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))
if user:
headers['Authorization'] = 'Basic ' + ('%s:%s' % (user, passwd)).encode("base64")
ca_certs = None
+ if additional_headers:
+ headers.update(additional_headers)
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
# 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 json
from lcm.pub.utils.toscaparser.nsdmodel import EtsiNsdInfoModel
+# Copyright 2017 ZTE Corporation.
+#
+# 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 copy
+import ftplib
import json
import os
import re
import shutil
import urllib
+import paramiko
from toscaparser.functions import GetInput
from toscaparser.tosca_template import ToscaTemplate
self.ftp_get(userName, userPwd, hostIp, hostPort, remoteFileName, localFileName)
return localFileName
+ def sftp_get(self, userName, userPwd, hostIp, hostPort, remoteFileName, localFileName):
+ # return
+ t = None
+ try:
+ t = paramiko.Transport(hostIp, int(hostPort))
+ t.connect(username=userName, password=userPwd)
+ sftp = paramiko.SFTPClient.from_transport(t)
+ sftp.get(remoteFileName, localFileName)
+ finally:
+ if t != None:
+ t.close()
+
+
+ def ftp_get(self, userName, userPwd, hostIp, hostPort, remoteFileName, localFileName):
+ f = None
+ try:
+ ftp = ftplib.FTP()
+ ftp.connect(hostIp, hostPort)
+ ftp.login(userName, userPwd)
+ f = open(localFileName, 'wb')
+ ftp.retrbinary('RETR ' + remoteFileName, f.write, 1024)
+ f.close()
+ finally:
+ if f != None:
+ f.close()
+
def buidMetadata(self, tosca):
if 'metadata' in tosca.tpl:
self.metadata = copy.deepcopy(tosca.tpl['metadata'])
for node in node_templates:
if node['name'] == name:
return node
- return None
\ No newline at end of file
+ return None
+
+ def get_all_nested_ns(self, nodes):
+ nss = []
+ for node in nodes:
+ if self.is_nested_ns(node):
+ ns = {}
+ ns['ns_id'] = node['name']
+ ns['description'] = node['description']
+ ns['properties'] = node['properties']
+ ns['networks'] = self.get_networks(node)
+
+ nss.append(ns)
+ return nss
+
+ def is_nested_ns(self, node):
+ return node['nodeType'].upper().find('.NS.') >= 0 or node['nodeType'].upper().endswith('.NS')
+++ /dev/null
-# Copyright 2017 ZTE Corporation.\r
-#\r
-# Licensed under the Apache License, Version 2.0 (the "License");\r
-# you may not use this file except in compliance with the License.\r
-# You may obtain a copy of the License at\r
-#\r
-# http://www.apache.org/licenses/LICENSE-2.0\r
-#\r
-# Unless required by applicable law or agreed to in writing, software\r
-# distributed under the License is distributed on an "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-# See the License for the specific language governing permissions and\r
-# limitations under the License.\r
-\r
-\r
-def convert_nsd(nsd_object):\r
- pass\r
-\r
-def convert_vnfd(vnfd_object):\r
- pass
\ No newline at end of file
-# 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
+# Copyright 2017 ZTE Corporation.
+#
+# 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.
-
+# 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 toscaparser.dataentity import DataEntity
from toscaparser.elements.constraints import Schema
from toscaparser.common.exception import ExceptionCollector
class DataEntityExt(object):
+
'''A complex data value entity ext.'''
-
@staticmethod
def validate_datatype(type, value, entry_schema=None, custom_def=None):
if value:
return DataEntity.validate_datatype(type, value, entry_schema, custom_def)
return value
-
+# Copyright 2017 ZTE Corporation.
+#
+# 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 functools
from lcm.pub.utils.toscaparser.basemodel import BaseInfoModel
self.ns_exposed = self.get_all_endpoint_exposed(tosca.topology_template)
self.policies = self._get_policies_scaling(tosca.topology_template.policies)
self.ns_flavours = self.get_all_flavour(tosca.topology_template.groups)
+ self.nested_ns = self.get_all_nested_ns(nodeTemplates)
def buildInputs(self, top_inputs):
return rets
def _isFlavour(self, group):
- return group.type.upper().find('FLAVOUR') >= 0
\ No newline at end of file
+ return group.type.upper().find('FLAVOUR') >= 0
+++ /dev/null
-# Copyright 2017 ZTE Corporation.\r
-#\r
-# Licensed under the Apache License, Version 2.0 (the "License");\r
-# you may not use this file except in compliance with the License.\r
-# You may obtain a copy of the License at\r
-#\r
-# http://www.apache.org/licenses/LICENSE-2.0\r
-#\r
-# Unless required by applicable law or agreed to in writing, software\r
-# distributed under the License is distributed on an "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-# See the License for the specific language governing permissions and\r
-# limitations under the License.\r
-from os import R_OK, access\r
-\r
-from lcm.pub.exceptions import NSLCMException\r
-from toscaparser.tosca_template import ToscaTemplate\r
-\r
-def parse_nsd_model(path, input_parameters):\r
- isexist = check_file_exist(path)\r
- if isexist:\r
- nsd_tpl = parse_nsd_csar(path, input_parameters)\r
- else:\r
- raise NSLCMException('%s is not exist.' % path)\r
- return nsd_tpl\r
-\r
-\r
-def parse_vnfd_model(path, input_parameters):\r
- isexist = check_file_exist(path)\r
- if isexist:\r
- vnfd_tpl = parse_vnfd_csar(path, input_parameters)\r
- else:\r
- raise NSLCMException('%s is not exist.' % path)\r
- return vnfd_tpl\r
-\r
-def check_file_exist(path):\r
- if path.exists(path) and path.isfile(path) and access(path, R_OK):\r
- return True\r
- else:\r
- return False\r
-\r
-def parse_nsd_csar(path, input_parameters=[], a_file=True):\r
- nsd_object = None\r
- nsd_object = ToscaTemplate(path, input_parameters)\r
- return nsd_object\r
-\r
-\r
-def parse_vnfd_csar(path, input_parameters=[], a_file=True):\r
- vnfd_object = None\r
- vnfd_object = ToscaTemplate(path, input_parameters)\r
- return vnfd_object
\ No newline at end of file
+# Copyright 2017 ZTE Corporation.
+#
+# 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 functools
from lcm.pub.utils.toscaparser import EtsiNsdInfoModel
self.vcloud = self._get_all_vcloud(nodeTemplates)
self.vcenter = self._get_all_vcenter(nodeTemplates)
self.image_files = self._get_all_image_file(nodeTemplates)
+ self.local_storages = self._get_all_local_storage(nodeTemplates)
+ self.volume_storages = self._get_all_volume_storage(nodeTemplates)
def _get_all_services(self, nodeTemplates):
return rets
def _isImageFile(self, node):
- return node['nodeType'].upper().find('.IMAGEFILE.') >= 0 or node['nodeType'].upper().endswith('.IMAGEFILE')
\ No newline at end of file
+ return node['nodeType'].upper().find('.IMAGEFILE.') >= 0 or node['nodeType'].upper().endswith('.IMAGEFILE')
+
+ def _get_all_local_storage(self, nodeTemplates):
+ rets = []
+ for node in nodeTemplates:
+ if self._isLocalStorage(node):
+ ret = {}
+ ret['local_storage_id'] = node['name']
+ if 'description' in node:
+ ret['description'] = node['description']
+ ret['properties'] = node['properties']
+
+ rets.append(ret)
+ return rets
+
+ def _isLocalStorage(self, node):
+ return node['nodeType'].upper().find('.LOCALSTORAGE.') >= 0 or node['nodeType'].upper().endswith(
+ '.LOCALSTORAGE')
+
+ def _get_all_volume_storage(self, nodeTemplates):
+ rets = []
+ for node in nodeTemplates:
+ if self._isVolumeStorage(node):
+ ret = {}
+ ret['volume_storage_id'] = node['name']
+ if 'description' in node:
+ ret['description'] = node['description']
+ ret['properties'] = node['properties']
+ ret['image_file'] = map(lambda x: self.get_requirement_node_name(x),
+ self.getRequirementByName(node, 'image_file'))
+
+ rets.append(ret)
+ return rets
+
+ def _isVolumeStorage(self, node):
+ return node['nodeType'].upper().find('.VOLUMESTORAGE.') >= 0 or node['nodeType'].upper().endswith(
+ '.VOLUMESTORAGE')
unittest_xml_reporting==1.12.0
# for parser
+paramiko==2.0.2
nfv-toscaparser==0.5.0.dev95