Support parameter input for vnffg template
Change-Id: Ied3dfaa3f9b2a4bc3be43cd349d6d47f760cdd3b Depends-On: I93819ff19ae91ca5e24778e220d3d09b63532ddf Implements: blueprint vnffgd-param-support
This commit is contained in:
parent
d311cfb77a
commit
c4eacd0d44
@ -51,22 +51,28 @@ deploy a sample VNFFGD template such as the one `here <https://github.com/
|
||||
openstack/tacker/tree/master/samples/tosca-templates/vnffgd/
|
||||
tosca-vnffgd-sample.yaml>`_.
|
||||
|
||||
*Note: A current constraint of the Forwarding Path policy match criteria is
|
||||
to include the network_src_port_id, such as:*
|
||||
.. note::
|
||||
|
||||
::
|
||||
A current constraint of the Forwarding Path policy match criteria is
|
||||
to include the network_src_port_id, such as:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
policy:
|
||||
type: ACL
|
||||
criteria:
|
||||
- network_src_port_id: 640dfd77-c92b-45a3-b8fc-22712de480e1
|
||||
|
||||
policy:
|
||||
type: ACL
|
||||
criteria:
|
||||
- network_src_port_id: 640dfd77-c92b-45a3-b8fc-22712de480e1
|
||||
|
||||
This is required due to a limitation of Neutron networking-sfc and only
|
||||
applies to an OpenStack VIM.
|
||||
|
||||
Tacker provides the following CLI to create a VNFFGD:
|
||||
|
||||
**tacker vnffgd-create --vnffgd-file <vnffgd file> <vnffgd name>**
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffgd-create --vnffgd-file <vnffgd file> <vnffgd name>
|
||||
|
||||
|
||||
Creating the VNFFG
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
@ -82,14 +88,23 @@ http://docs.openstack.org/developer/tacker/install/getting_started.html
|
||||
|
||||
Tacker provides the following CLI to create VNFFG:
|
||||
|
||||
**tacker vnffg-create --vnffgd-id <vnffg-id>**
|
||||
**--vnffgd-name <vnffgd name>**
|
||||
**--vnf-mapping <vnf mapping>**
|
||||
**--symmetrical <boolean>**
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-name <vnffgd name> \
|
||||
--vnf-mapping <vnf mapping> --symmetrical <boolean>
|
||||
|
||||
If you use a parameterized vnffg template:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-name <vnffgd name> \
|
||||
--param-file <param file> --vnf-mapping <vnf mapping> \
|
||||
--symmetrical <boolean>
|
||||
|
||||
Here,
|
||||
|
||||
* vnffgd-id/name - VNFFGD to use to instantiate this VNFFG
|
||||
* vnffgd-name - VNFFGD to use to instantiate this VNFFG
|
||||
* param-file - Parameter file in Yaml.
|
||||
* vnf-mapping - Allows a list of logical VNFD to VNF instance mapping
|
||||
* symmetrical - True/False
|
||||
|
||||
@ -101,9 +116,11 @@ each VNF in the Forwarding Path. For example, imagine a Forwarding Path
|
||||
map each VNFD defined in the VNFFGD Forwarding Path to the desired VNF
|
||||
instance:
|
||||
|
||||
**tacker vnffg-create --vnffgd-name myvnffgd**
|
||||
**--vnf-mapping VNF1:'91e32c20-6d1f-47a4-9ba7-08f5e5effe07',**
|
||||
**VNF2:'7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'**
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-name myvnffgd \
|
||||
--vnf-mapping VNF1:'91e32c20-6d1f-47a4-9ba7-08f5e5effe07', \
|
||||
VNF2:'7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'
|
||||
|
||||
Alternatively, if no vnf-mapping is provided then Tacker VNFFG will attempt
|
||||
to search for VNF instances derived from the given VNFDs in the VNFFGD. If
|
||||
@ -115,8 +132,10 @@ flow through the path. This creates an extra classifier to ensure return
|
||||
traffic flows through the chain in a reverse path, otherwise this traffic
|
||||
routed normally and does not enter the VNFFG.
|
||||
|
||||
*Note: Enabling symmetrical is not currently supported by the OpenStack VIM
|
||||
driver*
|
||||
.. note::
|
||||
|
||||
Enabling symmetrical is not currently supported by the OpenStack VIM
|
||||
driver
|
||||
|
||||
Viewing a VNFFG
|
||||
~~~~~~~~~~~~~~~
|
||||
@ -128,12 +147,14 @@ a Classifier. The main command to view a VNFFG is 'tacker vnffg-show,
|
||||
however there are several commands available in order to view the
|
||||
sub-components for a rendered VNFFG:
|
||||
|
||||
- **tacker nfp-list**
|
||||
- **tacker nfp-show <nfp id>**
|
||||
- **tacker chain-list**
|
||||
- **tacker chain-show <chain id>**
|
||||
- **tacker classifier-list**
|
||||
- **tacker classifier-show <classifier id>**
|
||||
.. code-block:: console
|
||||
|
||||
tacker nfp-list
|
||||
tacker nfp-show <nfp id>
|
||||
tacker chain-list
|
||||
tacker chain-show <chain id>
|
||||
tacker classifier-list
|
||||
tacker classifier-show <classifier id>
|
||||
|
||||
Known Issues and Limitations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- Added parameter support for deploying VNF Forwarding Graph
|
||||
Descriptor templates. With this addition the user can deploy
|
||||
a VNFFG using an Onboarded parameterized template with
|
||||
different parameter values using parameter yaml
|
||||
file at each time without onboarding new template.
|
||||
|
@ -0,0 +1,52 @@
|
||||
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||
|
||||
description: Sample VNFFG parameterized template
|
||||
|
||||
topology_template:
|
||||
description: Sample VNFFG parameterized template
|
||||
|
||||
inputs:
|
||||
net_src_port_id:
|
||||
type: string
|
||||
description: Port UUID of source VM.
|
||||
|
||||
dst_port_range:
|
||||
type: string
|
||||
description: Destination port range
|
||||
|
||||
ip_dst_pre:
|
||||
type: string
|
||||
description: Cidr format of destination ip.
|
||||
|
||||
node_templates:
|
||||
|
||||
Forwarding_path1:
|
||||
type: tosca.nodes.nfv.FP.Tacker
|
||||
description: creates path (CP12->CP22)
|
||||
properties:
|
||||
id: 51
|
||||
policy:
|
||||
type: ACL
|
||||
criteria:
|
||||
- network_src_port_id: { get_input: net_src_port_id }
|
||||
- destination_port_range: { get_input: dst_port_range }
|
||||
- ip_proto: 6
|
||||
- ip_dst_prefix: { get_input: ip_dst_pre }
|
||||
path:
|
||||
- forwarder: VNFD1
|
||||
capability: CP12
|
||||
- forwarder: VNFD2
|
||||
capability: CP22
|
||||
|
||||
groups:
|
||||
VNFFG1:
|
||||
type: tosca.groups.nfv.VNFFG
|
||||
description: HTTP to Corporate Net
|
||||
properties:
|
||||
vendor: tacker
|
||||
version: 1.0
|
||||
number_of_endpoints: 5
|
||||
dependent_virtual_link: [VL12,VL22]
|
||||
connection_point: [CP12,CP22]
|
||||
constituent_vnfs: [VNFD1,VNFD2]
|
||||
members: [Forwarding_path1]
|
6
samples/tosca-templates/vnffgd/vnffg-param-file.yaml
Normal file
6
samples/tosca-templates/vnffgd/vnffg-param-file.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
net_src_port_id: 640dfd77-c92b-45a3-b8fc-22712de480e1
|
||||
dst_port_range: 80-1024
|
||||
ip_dst_pre:
|
||||
- 192.168.1.2/24
|
||||
}
|
@ -269,3 +269,7 @@ class VnfPolicyTypeInvalid(BadRequest):
|
||||
|
||||
class DuplicateResourceName(TackerException):
|
||||
message = _("%(resource)s with name %(name)s already exists")
|
||||
|
||||
|
||||
class InvalidParam(TackerException):
|
||||
message = _("Param values must be a dict type")
|
||||
|
@ -91,6 +91,8 @@ class Vnffg(model_base.BASE, models_v1.HasTenant, models_v1.HasId):
|
||||
# Mapping of VNFD to VNF instance names
|
||||
vnf_mapping = sa.Column(types.Json)
|
||||
|
||||
attributes = sa.Column(types.Json)
|
||||
|
||||
|
||||
class VnffgNfp(model_base.BASE, models_v1.HasTenant, models_v1.HasId):
|
||||
"""Network Forwarding Path Data Model"""
|
||||
@ -310,6 +312,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
description=template_db.description,
|
||||
vnf_mapping=vnf_mapping,
|
||||
vnffgd_id=template_id,
|
||||
attributes=template_db.get('template'),
|
||||
status=constants.PENDING_CREATE)
|
||||
context.session.add(vnffg_db)
|
||||
|
||||
@ -677,7 +680,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
'forwarding_paths': vnffg_db.forwarding_paths[0]['id']
|
||||
}
|
||||
key_list = ('id', 'tenant_id', 'name', 'description',
|
||||
'vnf_mapping', 'status', 'vnffgd_id')
|
||||
'vnf_mapping', 'status', 'vnffgd_id', 'attributes')
|
||||
res.update((key, vnffg_db[key]) for key in key_list)
|
||||
return self._fields(res, fields)
|
||||
|
||||
|
@ -218,6 +218,13 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||
|
||||
@log.log
|
||||
def create_vnffg(self, context, vnffg):
|
||||
vnffg_attributes = vnffg['vnffg']['attributes']
|
||||
if vnffg_attributes.get('param_values'):
|
||||
param = vnffg_attributes['param_values']
|
||||
if isinstance(param, dict):
|
||||
vnffg_attributes['param_values'] = yaml.safe_dump(param)
|
||||
else:
|
||||
raise exceptions.InvalidParam()
|
||||
vnffg_dict = super(NfvoPlugin, self)._create_vnffg_pre(context, vnffg)
|
||||
nfp = super(NfvoPlugin, self).get_nfp(context,
|
||||
vnffg_dict['forwarding_paths'])
|
||||
|
@ -32,8 +32,11 @@ ipparams = _get_template('vnf_cirros_param_values_ipaddr.yaml')
|
||||
userdata_params = _get_template('vnf_cirros_param_values_user_data.yaml')
|
||||
config_data = _get_template('config_data.yaml')
|
||||
update_config_data = _get_template('update_config_data.yaml')
|
||||
vnffg_params = _get_template('vnffg_params.yaml')
|
||||
vnffgd_template = yaml.load(_get_template('vnffgd_template.yaml'))
|
||||
vnffgd_tosca_template = yaml.load(_get_template('tosca_vnffgd_template.yaml'))
|
||||
vnffgd_tosca_param_template = yaml.load(_get_template(
|
||||
'tosca_vnffgd_param_template.yaml'))
|
||||
vnffgd_invalid_tosca_template = yaml.load(_get_template(
|
||||
'tosca_invalid_vnffgd_template.yaml'))
|
||||
vnfd_scale_tosca_template = _get_template('tosca_scale.yaml')
|
||||
@ -164,15 +167,30 @@ def get_dummy_vnffg_obj():
|
||||
'vnffgd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'name': 'dummy_vnffg',
|
||||
u'attributes': {u'template': vnffgd_tosca_template},
|
||||
'vnf_mapping': {},
|
||||
'symmetrical': False}}
|
||||
|
||||
|
||||
def get_dummy_vnffg_param_obj():
|
||||
return {'vnffg': {'description': 'dummy_vnf_description',
|
||||
'vnffgd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'name': 'dummy_vnffg',
|
||||
u'attributes': {
|
||||
u'template': vnffgd_tosca_param_template},
|
||||
'vnf_mapping': {},
|
||||
u'attributes': {u'param_values':
|
||||
yaml.safe_load(vnffg_params)},
|
||||
'symmetrical': False}}
|
||||
|
||||
|
||||
def get_dummy_vnffg_obj_vnf_mapping():
|
||||
return {'vnffg': {'description': 'dummy_vnf_description',
|
||||
'vnffgd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'name': 'dummy_vnffg',
|
||||
u'attributes': {u'template': vnffgd_tosca_template},
|
||||
'vnf_mapping': {
|
||||
'VNF1': '91e32c20-6d1f-47a4-9ba7-08f5e5effe07',
|
||||
'VNF3': '7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'
|
||||
|
@ -0,0 +1,46 @@
|
||||
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||
|
||||
description: example template
|
||||
|
||||
topology_template:
|
||||
description: Example VNFFG template
|
||||
|
||||
inputs:
|
||||
net_name:
|
||||
type: string
|
||||
description: Name of the network
|
||||
|
||||
node_templates:
|
||||
|
||||
Forwarding_path1:
|
||||
type: tosca.nodes.nfv.FP.Tacker
|
||||
description: creates path (CP11->CP12->CP32)
|
||||
properties:
|
||||
id: 51
|
||||
policy:
|
||||
type: ACL
|
||||
criteria:
|
||||
- network_name: { get_input: net_name }
|
||||
- destination_port_range: 80-1024
|
||||
- ip_proto: 6
|
||||
- ip_dst_prefix: 192.168.1.2/24
|
||||
path:
|
||||
- forwarder: VNF1
|
||||
capability: CP11
|
||||
- forwarder: VNF1
|
||||
capability: CP12
|
||||
- forwarder: VNF3
|
||||
capability: CP32
|
||||
|
||||
groups:
|
||||
VNFFG1:
|
||||
type: tosca.groups.nfv.VNFFG
|
||||
description: HTTP to Corporate Net
|
||||
properties:
|
||||
vendor: tacker
|
||||
version: 1.0
|
||||
number_of_endpoints: 5
|
||||
dependent_virtual_link: [VL1,VL2,VL3]
|
||||
connection_point: [CP11,CP12,CP32]
|
||||
constituent_vnfs: [VNF1,VNF3]
|
||||
members: [Forwarding_path1]
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
'net_name': tenant1_net
|
||||
}
|
@ -257,6 +257,18 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
session.flush()
|
||||
return vnffg_template
|
||||
|
||||
def _insert_dummy_vnffg_param_template(self):
|
||||
session = self.context.session
|
||||
vnffg_template = vnffg_db.VnffgTemplate(
|
||||
id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
name='fake_template',
|
||||
description='fake_template_description',
|
||||
template={u'vnffgd': utils.vnffgd_tosca_param_template})
|
||||
session.add(vnffg_template)
|
||||
session.flush()
|
||||
return vnffg_template
|
||||
|
||||
def _insert_dummy_vnffg(self):
|
||||
session = self.context.session
|
||||
vnffg = vnffg_db.Vnffg(
|
||||
@ -363,6 +375,27 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
symmetrical=mock.ANY
|
||||
)
|
||||
|
||||
def test_create_vnffg_param_values(self):
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock.patch('tacker.common.driver_manager.DriverManager',
|
||||
side_effect=FakeDriverManager()).start()
|
||||
self._insert_dummy_vnffg_param_template()
|
||||
vnffg_obj = utils.get_dummy_vnffg_param_obj()
|
||||
result = self.nfvo_plugin.create_vnffg(self.context, vnffg_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertIn('status', result)
|
||||
self.assertEqual('PENDING_CREATE', result['status'])
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_id=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
symmetrical=mock.ANY
|
||||
)
|
||||
|
||||
def test_create_vnffg_vnf_mapping(self):
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
|
Loading…
Reference in New Issue
Block a user