diff --git a/tacker/common/utils.py b/tacker/common/utils.py index 97f2c7edf..bff05f592 100644 --- a/tacker/common/utils.py +++ b/tacker/common/utils.py @@ -35,6 +35,7 @@ import netaddr from oslo_concurrency import lockutils from oslo_config import cfg from oslo_log import log as logging +from oslo_log import versionutils from oslo_utils import importutils from six import iteritems from stevedore import driver @@ -391,3 +392,9 @@ def deep_update(orig_dict, new_dict): continue orig_dict[key] = value + + +def deprecate_warning(what, as_of, in_favor_of=None, remove_in=1): + versionutils.deprecation_warning(as_of=as_of, what=what, + in_favor_of=in_favor_of, + remove_in=remove_in) diff --git a/tacker/tests/functional/vnfm/test_tosca_vnf.py b/tacker/tests/functional/vnfm/test_tosca_vnf.py index b58b1a995..eae87dbcf 100644 --- a/tacker/tests/functional/vnfm/test_tosca_vnf.py +++ b/tacker/tests/functional/vnfm/test_tosca_vnf.py @@ -14,6 +14,7 @@ from novaclient import exceptions from oslo_config import cfg +import yaml from tacker.tests import constants from tacker.tests.functional import base @@ -26,12 +27,11 @@ VNF_CIRROS_CREATE_TIMEOUT = 120 class VnfTestToscaCreate(base.BaseTackerTest): def test_create_delete_vnf_tosca_no_monitoring(self): - data = dict() - data['tosca'] = read_file('sample-tosca-vnfd.yaml') + input_yaml = read_file('sample-tosca-vnfd.yaml') vnfd_name = 'test_tosca_vnf_with_cirros_no_monitoring' - toscal = data['tosca'] + tosca_dict = yaml.safe_load(input_yaml) tosca_arg = {'vnfd': {'name': vnfd_name, - 'attributes': {'vnfd': toscal}}} + 'attributes': {'vnfd': tosca_dict}}} # Create vnfd with tosca template vnfd_instance = self.client.create_vnfd(body=tosca_arg) @@ -67,12 +67,11 @@ class VnfTestToscaCreate(base.BaseTackerTest): class VnfTestToscaCreateFlavorCreation(base.BaseTackerTest): def test_create_delete_vnf_tosca_no_monitoring(self): - data = dict() vnfd_name = 'tosca_vnfd_with_auto_flavor' - data['tosca'] = read_file('sample-tosca-vnfd-flavor.yaml') - toscal = data['tosca'] + input_yaml = read_file('sample-tosca-vnfd-flavor.yaml') + tosca_dict = yaml.safe_load(input_yaml) tosca_arg = {'vnfd': {'name': vnfd_name, 'attributes': {'vnfd': - toscal}}} + tosca_dict}}} # Create vnfd with tosca template vnfd_instance = self.client.create_vnfd(body=tosca_arg) @@ -122,12 +121,11 @@ class VnfTestToscaCreateFlavorCreation(base.BaseTackerTest): class VnfTestToscaCreateImageCreation(base.BaseTackerTest): def test_create_delete_vnf_tosca_no_monitoring(self): - data = dict() vnfd_name = 'tosca_vnfd_with_auto_image' - data['tosca'] = read_file('sample-tosca-vnfd-image.yaml') - toscal = data['tosca'] + input_yaml = read_file('sample-tosca-vnfd-image.yaml') + tosca_dict = yaml.safe_load(input_yaml) tosca_arg = {'vnfd': {'name': vnfd_name, 'attributes': {'vnfd': - toscal}}} + tosca_dict}}} # Create vnfd with tosca template vnfd_instance = self.client.create_vnfd(body=tosca_arg) diff --git a/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py b/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py index a278a9b08..dcfea3750 100644 --- a/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py +++ b/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py @@ -26,13 +26,11 @@ CONF = cfg.CONF class VnfTestToscaMultipleVDU(base.BaseTackerTest): def test_create_delete_tosca_vnf_with_multiple_vdus(self): - data = dict() input_yaml = read_file('sample-tosca-vnfd-multi-vdu.yaml') - data['tosca'] = input_yaml - toscal = data['tosca'] + tosca_dict = yaml.safe_load(input_yaml) vnfd_name = 'sample-tosca-vnfd-multi-vdu' tosca_arg = {'vnfd': {'name': vnfd_name, - 'attributes': {'vnfd': toscal}}} + 'attributes': {'vnfd': tosca_dict}}} # Create vnfd with tosca template vnfd_instance = self.client.create_vnfd(body=tosca_arg) diff --git a/tacker/tests/functional/vnfm/test_tosca_vnfd.py b/tacker/tests/functional/vnfm/test_tosca_vnfd.py index 3f61eb523..edad78e1b 100644 --- a/tacker/tests/functional/vnfm/test_tosca_vnfd.py +++ b/tacker/tests/functional/vnfm/test_tosca_vnfd.py @@ -13,6 +13,7 @@ # under the License. from oslo_config import cfg +import yaml from tacker.tests.functional import base from tacker.tests.utils import read_file @@ -22,12 +23,11 @@ CONF = cfg.CONF class VnfdTestCreate(base.BaseTackerTest): def _test_create_list_delete_tosca_vnfd(self, tosca_vnfd_file): - data = dict() - data['tosca'] = read_file(tosca_vnfd_file) - toscal = data['tosca'] + input_yaml = read_file(tosca_vnfd_file) + tosca_dict = yaml.safe_load(input_yaml) vnfd_name = 'sample-tosca-vnfd' tosca_arg = {'vnfd': {'name': vnfd_name, - 'attributes': {'vnfd': toscal}}} + 'attributes': {'vnfd': tosca_dict}}} vnfd_instance = self.client.create_vnfd(body=tosca_arg) self.assertIsNotNone(vnfd_instance) diff --git a/tacker/tests/functional/vnfm/test_vnfm_param.py b/tacker/tests/functional/vnfm/test_vnfm_param.py index 3d51d7ee1..8874664ba 100644 --- a/tacker/tests/functional/vnfm/test_vnfm_param.py +++ b/tacker/tests/functional/vnfm/test_vnfm_param.py @@ -21,12 +21,14 @@ from tacker.tests.utils import read_file class VnfmTestParam(base.BaseTackerTest): def _test_vnfd_create(self, vnfd_file): - yaml_input = dict() - yaml_input['tosca'] = read_file(vnfd_file) + yaml_input = read_file(vnfd_file) vnfd_name = 'sample_cirros_vnf' - toscal = yaml_input['tosca'] + # TODO(anyone) remove this condition check once old templates + # are deprecated + if "tosca_definitions_version" in yaml_input: + yaml_input = yaml.safe_load(yaml_input) req_dict = {'vnfd': {'name': vnfd_name, - 'attributes': {'vnfd': toscal}}} + 'attributes': {'vnfd': yaml_input}}} # Create vnfd vnfd_instance = self.client.create_vnfd(body=req_dict) @@ -48,15 +50,13 @@ class VnfmTestParam(base.BaseTackerTest): except Exception: assert True, "Vnfd Delete success" + str(vfnd_d) + str(Exception) - def _test_vnf_create(self, vnfd_instance, vnf_name, vnf_value_file): + def _test_vnf_create(self, vnfd_instance, vnf_name, param_values): # Create the vnf with values vnfd_id = vnfd_instance['vnfd']['id'] - values_str = read_file(vnf_value_file) - # Create vnf with values file vnf_dict = dict() vnf_dict = {'vnf': {'vnfd_id': vnfd_id, 'name': vnf_name, - 'attributes': {'param_values': values_str}}} + 'attributes': {'param_values': param_values}}} vnf_instance = self.client.create_vnf(body=vnf_dict) self.validate_vnf_instance(vnfd_instance, vnf_instance) @@ -70,11 +70,11 @@ class VnfmTestParam(base.BaseTackerTest): vnf_instance = self.client.show_vnf(vnf_id) # Verify values dictionary is same as param values from vnf_show - input_dict = yaml.load(values_str) + param_values = vnf_instance['vnf']['attributes']['param_values'] - param_values_dict = yaml.load(param_values) - self.assertEqual(input_dict, param_values_dict) - return vnf_instance + param_values_dict = yaml.safe_load(param_values) + + return vnf_instance, param_values_dict def _test_vnf_delete(self, vnf_instance): # Delete Vnf @@ -90,10 +90,15 @@ class VnfmTestParam(base.BaseTackerTest): assert True, "Vnf Delete success" + str(vfn_d) + str(Exception) def test_vnf_param(self): - vnfd_instance = self._test_vnfd_create('sample_cirros_vnf_param.yaml') - vnf_instance = self._test_vnf_create(vnfd_instance, + vnfd_instance = self._test_vnfd_create( + 'sample_cirros_vnf_param.yaml') + values_str = read_file('sample_cirros_vnf_values.yaml') + vnf_instance, param_values_dict = self._test_vnf_create(vnfd_instance, 'test_vnf_with_parameters', - 'sample_cirros_vnf_values.yaml') + values_str) + # Verify values dictionary is same as param values from vnf_show + input_dict = yaml.safe_load(values_str) + self.assertEqual(input_dict, param_values_dict) self._test_vnf_delete(vnf_instance) vnf_id = vnf_instance['vnf']['id'] self.addCleanup(self.client.delete_vnfd, vnfd_instance['vnfd']['id']) @@ -101,14 +106,19 @@ class VnfmTestParam(base.BaseTackerTest): constants.VNF_CIRROS_DELETE_TIMEOUT) def test_vnfd_param_tosca_template(self): - vnfd_instance = self._test_vnfd_create('sample-tosca-vnfd-param.yaml') + vnfd_instance = self._test_vnfd_create( + 'sample-tosca-vnfd-param.yaml') self._test_vnfd_delete(vnfd_instance) def test_vnf_param_tosca_template(self): - vnfd_instance = self._test_vnfd_create('sample-tosca-vnfd-param.yaml') - vnf_instance = self._test_vnf_create(vnfd_instance, + vnfd_instance = self._test_vnfd_create( + 'sample-tosca-vnfd-param.yaml') + values_str = read_file('sample-tosca-vnf-values.yaml') + values_dict = yaml.safe_load(values_str) + vnf_instance, param_values_dict = self._test_vnf_create(vnfd_instance, 'test_vnf_with_parameters_tosca_template', - 'sample-tosca-vnf-values.yaml') + values_dict) + self.assertEqual(values_dict, param_values_dict) self._test_vnf_delete(vnf_instance) vnf_id = vnf_instance['vnf']['id'] self.addCleanup(self.client.delete_vnfd, vnfd_instance['vnfd']['id']) diff --git a/tacker/tests/unit/db/utils.py b/tacker/tests/unit/db/utils.py index 0b7b5a06b..0e2ee8519 100644 --- a/tacker/tests/unit/db/utils.py +++ b/tacker/tests/unit/db/utils.py @@ -15,6 +15,7 @@ import codecs import os +import yaml def _get_template(name): @@ -38,7 +39,7 @@ def get_dummy_vnfd_obj(): 'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437', u'mgmt_driver': u'noop', u'infra_driver': u'fake_driver', - u'attributes': {u'vnfd': vnfd_openwrt}, + u'attributes': {u'vnfd': yaml.safe_load(vnfd_openwrt)}, 'description': 'dummy_vnfd_description'}, u'auth': {u'tenantName': u'admin', u'passwordCredentials': { u'username': u'admin', u'password': u'devstack'}}} diff --git a/tacker/vm/plugin.py b/tacker/vm/plugin.py index 670aba227..d537b46ae 100644 --- a/tacker/vm/plugin.py +++ b/tacker/vm/plugin.py @@ -28,6 +28,7 @@ from tacker._i18n import _LE from tacker.api.v1 import attributes from tacker.common import driver_manager from tacker.common import exceptions +from tacker.common import utils from tacker.db.vm import vm_db from tacker.extensions import vnfm from tacker.plugins.common import constants @@ -132,7 +133,16 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin): def create_vnfd(self, context, vnfd): vnfd_data = vnfd['vnfd'] - if "tosca_definitions_version" not in vnfd_data['attributes']['vnfd']: + template = vnfd_data['attributes'].get('vnfd') + if isinstance(template, dict): + # TODO(sripriya) remove this yaml dump once db supports storing + # json format of yaml files in a separate column instead of + # key value string pairs in vnf attributes table + vnfd_data['attributes']['vnfd'] = yaml.safe_dump( + template) + elif isinstance(template, str): + self._report_deprecated_yaml_str() + if "tosca_definitions_version" not in template: versionutils.report_deprecated_feature(LOG, 'VNFD legacy vnfds' ' are deprecated since Mitaka release and will be removed in' ' Ocata release. Please use NFV TOSCA vnfds.') @@ -279,6 +289,25 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin): def create_vnf(self, context, vnf): vnf_info = vnf['vnf'] + vnf_attributes = vnf_info['attributes'] + if vnf_attributes.get('param_values'): + param = vnf_attributes['param_values'] + if isinstance(param, dict): + # TODO(sripriya) remove this yaml dump once db supports storing + # json format of yaml files in a separate column instead of + # key value string pairs in vnf attributes table + vnf_attributes['param_values'] = yaml.safe_dump(param) + else: + self._report_deprecated_yaml_str() + if vnf_attributes.get('config'): + config = vnf_attributes['config'] + if isinstance(config, dict): + # TODO(sripriya) remove this yaml dump once db supports storing + # json format of yaml files in a separate column instead of + # key value string pairs in vnf attributes table + vnf_attributes['config'] = yaml.safe_dump(config) + else: + self._report_deprecated_yaml_str() vim_auth = self.get_vim(context, vnf_info) vnf_dict = self._create_vnf(context, vnf_info, vim_auth) @@ -326,6 +355,16 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin): new_status, vnf_dict) def update_vnf(self, context, vnf_id, vnf): + vnf_attributes = vnf['vnf']['attributes'] + if vnf_attributes.get('config'): + config = vnf_attributes['config'] + if isinstance(config, dict): + # TODO(sripriya) remove this yaml dump once db supports storing + # json format of yaml files in a separate column instead of + # key value string pairs in vnf attributes table + vnf_attributes['config'] = yaml.safe_dump(config) + else: + self._report_deprecated_yaml_str() vnf_dict = self._update_vnf_pre(context, vnf_id) vim_auth = self.get_vim(context, vnf_dict) driver_name = self._infra_driver_name(vnf_dict) @@ -531,6 +570,10 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin): return policy + def _report_deprecated_yaml_str(self): + utils.deprecate_warning(what='yaml as string', + as_of='N', in_favor_of='yaml as dictionary') + def _make_policy_dict(self, vnf, name, policy): p = {} p['type'] = policy['type']