modify vnfd, param & config attr. to dict objects

vnfd templates, parameter and config files are sent as yaml
strings in requests body to tacker server.

Change the attributes to dictionary objects. New behavior
is applicable to tosca templates only. Also, this change may mangle
the order of nodes in tosca templates. In order to address this
concern and preserve the network interfaces order in these nodes,
there will be follow on patch to address this.

Change-Id: I05a1d60dc643dca864aff559f37491914b1fcfc3
Partial-Bug: #1591361
This commit is contained in:
Sripriya 2016-08-25 15:11:01 -07:00
parent b439935ef2
commit e8418071bf
7 changed files with 98 additions and 41 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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'])

View File

@ -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'}}}

View File

@ -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']