Merge "Support creating VNFFG with no flow-classifier"
This commit is contained in:
commit
9ad393b0bc
|
@ -0,0 +1,32 @@
|
||||||
|
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||||
|
|
||||||
|
description: Sample VNFFG template with no flow classifier
|
||||||
|
|
||||||
|
topology_template:
|
||||||
|
description: Sample VNFFG template
|
||||||
|
|
||||||
|
node_templates:
|
||||||
|
|
||||||
|
Forwarding_path1:
|
||||||
|
type: tosca.nodes.nfv.FP.TackerV2
|
||||||
|
description: creates path (CP12->CP22)
|
||||||
|
properties:
|
||||||
|
id: 51
|
||||||
|
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: 2
|
||||||
|
dependent_virtual_link: [VL12,VL22]
|
||||||
|
connection_point: [CP12,CP22]
|
||||||
|
constituent_vnfs: [VNFD1,VNFD2]
|
||||||
|
members: [Forwarding_path1]
|
|
@ -662,49 +662,48 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||||
vnf_mapping):
|
vnf_mapping):
|
||||||
template = template_db.template['vnffgd']['topology_template']
|
template = template_db.template['vnffgd']['topology_template']
|
||||||
nfp = template['node_templates'][nfp_name]
|
nfp = template['node_templates'][nfp_name]
|
||||||
try:
|
|
||||||
|
if 'policy' in nfp['properties']:
|
||||||
policy = nfp['properties']['policy']
|
policy = nfp['properties']['policy']
|
||||||
except KeyError:
|
if 'type' in policy:
|
||||||
raise nfvo.NfpPolicyNotFoundException(policy=nfp)
|
if policy['type'] != 'ACL':
|
||||||
|
raise nfvo.NfpPolicyTypeError(type=policy['type'])
|
||||||
|
|
||||||
if 'type' in policy:
|
if 'criteria' not in policy:
|
||||||
if policy['type'] != 'ACL':
|
raise nfvo.NfpPolicyCriteriaError(
|
||||||
raise nfvo.NfpPolicyTypeError(type=policy['type'])
|
error="Missing criteria in policy")
|
||||||
|
validation_list = []
|
||||||
if 'criteria' not in policy:
|
for item in policy['criteria']:
|
||||||
raise nfvo.NfpPolicyCriteriaError(
|
if item.get('name') is None:
|
||||||
error="Missing criteria in policy")
|
LOG.warning('The unnamed classifier approach'
|
||||||
validation_list = []
|
' will be deprecated in subsequent'
|
||||||
for item in policy['criteria']:
|
' releases')
|
||||||
if item.get('name') is None:
|
validation_list.append(item)
|
||||||
LOG.warning('The unnamed classifier approach'
|
|
||||||
' will be deprecated in subsequent'
|
|
||||||
' releases')
|
|
||||||
validation_list.append(item)
|
|
||||||
else:
|
|
||||||
validation_list.append(item['classifier'])
|
|
||||||
|
|
||||||
self._validate_criteria(validation_list)
|
|
||||||
|
|
||||||
classifiers = []
|
|
||||||
for criteria in policy['criteria']:
|
|
||||||
match = dict()
|
|
||||||
if criteria.get('name') is None:
|
|
||||||
criteria_dict = criteria.copy()
|
|
||||||
else:
|
|
||||||
criteria_dict = criteria['classifier'].copy()
|
|
||||||
for key, val in criteria_dict.items():
|
|
||||||
if key in MATCH_CRITERIA:
|
|
||||||
match.update(self._convert_criteria(context, key, val,
|
|
||||||
vnf_mapping))
|
|
||||||
else:
|
else:
|
||||||
raise nfvo.NfpPolicyCriteriaError(error="Unsupported "
|
validation_list.append(item['classifier'])
|
||||||
"criteria: "
|
|
||||||
"{}".format(key))
|
|
||||||
classifiers.append({'name': criteria.get('name'),
|
|
||||||
'match': match})
|
|
||||||
|
|
||||||
return classifiers
|
self._validate_criteria(validation_list)
|
||||||
|
|
||||||
|
classifiers = []
|
||||||
|
for criteria in policy['criteria']:
|
||||||
|
match = dict()
|
||||||
|
if criteria.get('name') is None:
|
||||||
|
criteria_dict = criteria.copy()
|
||||||
|
else:
|
||||||
|
criteria_dict = criteria['classifier'].copy()
|
||||||
|
for key, val in criteria_dict.items():
|
||||||
|
if key in MATCH_CRITERIA:
|
||||||
|
match.update(self._convert_criteria(context, key, val,
|
||||||
|
vnf_mapping))
|
||||||
|
else:
|
||||||
|
raise nfvo.NfpPolicyCriteriaError(error="Unsupported "
|
||||||
|
"criteria: "
|
||||||
|
"{}".format(key))
|
||||||
|
classifiers.append({'name': criteria.get('name'),
|
||||||
|
'match': match})
|
||||||
|
return classifiers
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
def _convert_criteria(self, context, criteria, value, vnf_mapping):
|
def _convert_criteria(self, context, criteria, value, vnf_mapping):
|
||||||
"""Method is used to convert criteria to proper db value from template
|
"""Method is used to convert criteria to proper db value from template
|
||||||
|
|
|
@ -207,10 +207,6 @@ class NfpDuplicatePolicyCriteria(exceptions.TackerException):
|
||||||
message = _('The %(first_dict)s and %(sec_dict)s are overlapped')
|
message = _('The %(first_dict)s and %(sec_dict)s are overlapped')
|
||||||
|
|
||||||
|
|
||||||
class NfpPolicyNotFoundException(exceptions.NotFound):
|
|
||||||
message = _('Policy not found in NFP %(nfp)s')
|
|
||||||
|
|
||||||
|
|
||||||
class NfpPolicyTypeError(exceptions.PolicyCheckError):
|
class NfpPolicyTypeError(exceptions.PolicyCheckError):
|
||||||
message = _('Unsupported Policy Type: %(type)s')
|
message = _('Unsupported Policy Type: %(type)s')
|
||||||
|
|
||||||
|
|
|
@ -323,7 +323,6 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||||
nfp = super(NfvoPlugin, self).get_nfp(context,
|
nfp = super(NfvoPlugin, self).get_nfp(context,
|
||||||
vnffg_dict['forwarding_paths'])
|
vnffg_dict['forwarding_paths'])
|
||||||
sfc = super(NfvoPlugin, self).get_sfc(context, nfp['chain_id'])
|
sfc = super(NfvoPlugin, self).get_sfc(context, nfp['chain_id'])
|
||||||
classifier_dict = dict()
|
|
||||||
name_match_list = []
|
name_match_list = []
|
||||||
for classifier_id in nfp['classifier_ids']:
|
for classifier_id in nfp['classifier_ids']:
|
||||||
classifier_dict = super(NfvoPlugin, self).get_classifier(
|
classifier_dict = super(NfvoPlugin, self).get_classifier(
|
||||||
|
|
|
@ -37,6 +37,8 @@ vnffg_multi_params = _get_template('vnffg_multi_params.yaml')
|
||||||
vnffgd_template = yaml.safe_load(_get_template('vnffgd_template.yaml'))
|
vnffgd_template = yaml.safe_load(_get_template('vnffgd_template.yaml'))
|
||||||
vnffgd_tosca_template = yaml.safe_load(_get_template(
|
vnffgd_tosca_template = yaml.safe_load(_get_template(
|
||||||
'tosca_vnffgd_template.yaml'))
|
'tosca_vnffgd_template.yaml'))
|
||||||
|
vnffgd_tosca_no_classifier_template = yaml.safe_load(_get_template(
|
||||||
|
'tosca_vnffgd_no_classifier_template.yaml'))
|
||||||
vnffgd_tosca_template_for_update = yaml.safe_load(_get_template(
|
vnffgd_tosca_template_for_update = yaml.safe_load(_get_template(
|
||||||
'tosca_vnffgd_template_for_update.yaml'))
|
'tosca_vnffgd_template_for_update.yaml'))
|
||||||
vnffgd_legacy_template = yaml.safe_load(_get_template(
|
vnffgd_legacy_template = yaml.safe_load(_get_template(
|
||||||
|
@ -199,6 +201,17 @@ def get_dummy_vnffg_obj():
|
||||||
'symmetrical': False}}
|
'symmetrical': False}}
|
||||||
|
|
||||||
|
|
||||||
|
def get_dummy_vnffg_no_classifier_obj():
|
||||||
|
return {'vnffg': {'description': 'dummy_vnffg_no_classifier_description',
|
||||||
|
'vnffgd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||||
|
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||||
|
'name': 'dummy_vnffg',
|
||||||
|
u'attributes': {
|
||||||
|
u'template': vnffgd_tosca_no_classifier_template},
|
||||||
|
'vnf_mapping': {},
|
||||||
|
'symmetrical': False}}
|
||||||
|
|
||||||
|
|
||||||
def get_dummy_vnffg_obj_inline():
|
def get_dummy_vnffg_obj_inline():
|
||||||
return {'vnffg': {'description': 'dummy_vnffg_description_inline',
|
return {'vnffg': {'description': 'dummy_vnffg_description_inline',
|
||||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||||
|
|
|
@ -439,6 +439,18 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||||
session.flush()
|
session.flush()
|
||||||
return vnffg_template
|
return vnffg_template
|
||||||
|
|
||||||
|
def _insert_dummy_vnffg_no_classifier_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_no_classifier_template})
|
||||||
|
session.add(vnffg_template)
|
||||||
|
session.flush()
|
||||||
|
return vnffg_template
|
||||||
|
|
||||||
def _insert_dummy_vnffg_duplicate_criteria_template(self):
|
def _insert_dummy_vnffg_duplicate_criteria_template(self):
|
||||||
session = self.context.session
|
session = self.context.session
|
||||||
vnffg_template = vnffg_db.VnffgTemplate(
|
vnffg_template = vnffg_db.VnffgTemplate(
|
||||||
|
@ -692,6 +704,27 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||||
symmetrical=mock.ANY
|
symmetrical=mock.ANY
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_create_vnffg_no_classifier(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_no_classifier_template()
|
||||||
|
vnffg_obj = utils.get_dummy_vnffg_no_classifier_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_ids=mock.ANY,
|
||||||
|
auth_attr=mock.ANY,
|
||||||
|
symmetrical=mock.ANY
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, '_get_by_id')
|
@mock.patch.object(nfvo_plugin.NfvoPlugin, '_get_by_id')
|
||||||
def test_create_vnffg_param_value_format_error(self, mock_get_by_id):
|
def test_create_vnffg_param_value_format_error(self, mock_get_by_id):
|
||||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||||
|
description: example template
|
||||||
|
|
||||||
|
topology_template:
|
||||||
|
description: Example VNFFG template without any flow classifiers
|
||||||
|
node_templates:
|
||||||
|
Forwarding_path1:
|
||||||
|
type: tosca.nodes.nfv.FP.TackerV2
|
||||||
|
description: creates path (CP11->CP12->CP32)
|
||||||
|
properties:
|
||||||
|
id: 51
|
||||||
|
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: 3
|
||||||
|
dependent_virtual_link: [VL1,VL2,VL3]
|
||||||
|
connection_point: [CP11,CP12,CP32]
|
||||||
|
constituent_vnfs: [VNF1,VNF3]
|
||||||
|
members: [Forwarding_path1]
|
|
@ -307,7 +307,7 @@ node_types:
|
||||||
required: false
|
required: false
|
||||||
policy:
|
policy:
|
||||||
type: tosca.nfv.datatypes.policyTypeV2
|
type: tosca.nfv.datatypes.policyTypeV2
|
||||||
required: true
|
required: false
|
||||||
description: policy to use to match traffic for this FP
|
description: policy to use to match traffic for this FP
|
||||||
path:
|
path:
|
||||||
type: list
|
type: list
|
||||||
|
|
Loading…
Reference in New Issue