Correct forwarding graph 'id' to match 'chain_id' in port chain
This patch lets forwarding graph 'id' to match 'chain_id' in port chain. When users don't provide forwarding graph 'id', that 'id' will be updated automatically by port chain creation in networking-sfc. Change-Id: I4e1dba75078593ba35f3995a26336ed538669579
This commit is contained in:
parent
0da9469017
commit
4e1e284764
@ -449,15 +449,23 @@ as VNFFG ID and can not see any VNFFG is created.
|
||||
| | 522bf | | | | |
|
||||
+---------------------+---------------------+---------------------+--------+---------------------+-----------------------+
|
||||
|
||||
$ openstack vnf network forwarding path list
|
||||
+--------------------------------------+------------------+--------+--------------------------------------+---------+
|
||||
| ID | Name | Status | VNFFG ID | Path ID |
|
||||
+--------------------------------------+------------------+--------+--------------------------------------+---------+
|
||||
| 3d24b870-fe0d-4af9-a03f-9e0811859256 | Forwarding_path2 | ACTIVE | a601e938-a37b-493c-a48c-2c90aba73a77 | 52 |
|
||||
| a2ca3a24-f02e-4629-b12c-54256886c050 | Forwarding_path1 | ACTIVE | 1f48603b-6740-4b94-a981-15de8c5c0fb3 | 51 |
|
||||
+--------------------------------------+------------------+--------+--------------------------------------+---------+
|
||||
|
||||
$ openstack sfc port chain list --fit-width
|
||||
+---------------------+---------------------+---------------------+---------------------+---------------------+----------+
|
||||
| ID | Name | Port Pair Groups | Flow Classifiers | Chain Parameters | Chain ID |
|
||||
+---------------------+---------------------+---------------------+---------------------+---------------------+----------+
|
||||
| 2950fa88-d98f-4812 | NS2_VNFFG2_a7f77e11 | [u'e92feb43-4906-45 | [u'3eff5973-c612-43 | {u'symmetric': | 1 |
|
||||
| 2950fa88-d98f-4812 | NS2_VNFFG2_a7f77e11 | [u'e92feb43-4906-45 | [u'3eff5973-c612-43 | {u'symmetric': | 51 |
|
||||
| -830a-ae15452a8c08 | -d847-4090-aa79 | 21-852f- | 83-aee2-d1eb05c832e | False, | |
|
||||
| | -496610c522bf-port- | 1940c2f344a6'] | e'] | u'correlation': | |
|
||||
| | chain | | | u'mpls'} | |
|
||||
| 61c938f9-15a1-4ec8 | NS2_VNFFG1_a7f77e11 | [u'e92feb43-4906-45 | [u'b4cb5575-cb3c-41 | {u'symmetric': | 2 |
|
||||
| 61c938f9-15a1-4ec8 | NS2_VNFFG1_a7f77e11 | [u'e92feb43-4906-45 | [u'b4cb5575-cb3c-41 | {u'symmetric': | 52 |
|
||||
| -8dec-44e5f8af70ff | -d847-4090-aa79 | 21-852f- | a3-8649-c69e0cd48db | False, | |
|
||||
| | -496610c522bf-port- | 1940c2f344a6', u'82 | e'] | u'correlation': | |
|
||||
| | chain | dab526-540e-4047 | | u'mpls'} | |
|
||||
|
@ -0,0 +1,38 @@
|
||||
# Copyright 2018 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Change nullable value of path_id
|
||||
|
||||
Revision ID: 13ecc2dd6f7f
|
||||
Revises: 4747cc26b9c6
|
||||
Create Date: 2018-07-24 16:47:01.378226
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '13ecc2dd6f7f'
|
||||
down_revision = '4747cc26b9c6'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
op.alter_column('vnffgchains', 'path_id',
|
||||
existing_type=sa.String(length=255),
|
||||
nullable=True)
|
||||
op.alter_column('vnffgnfps', 'path_id',
|
||||
existing_type=sa.String(length=255),
|
||||
nullable=True)
|
@ -1 +1 @@
|
||||
4747cc26b9c6
|
||||
13ecc2dd6f7f
|
@ -115,7 +115,7 @@ class VnffgNfp(model_base.BASE, models_v1.HasTenant, models_v1.HasId):
|
||||
uselist=False)
|
||||
|
||||
status = sa.Column(sa.String(255), nullable=False)
|
||||
path_id = sa.Column(sa.String(255), nullable=False)
|
||||
path_id = sa.Column(sa.String(255), nullable=True)
|
||||
|
||||
# symmetry of forwarding path
|
||||
symmetrical = sa.Column(sa.Boolean(), default=False)
|
||||
@ -134,7 +134,7 @@ class VnffgChain(model_base.BASE, models_v1.HasTenant, models_v1.HasId):
|
||||
# chain
|
||||
chain = sa.Column(types.Json)
|
||||
|
||||
path_id = sa.Column(sa.String(255), nullable=False)
|
||||
path_id = sa.Column(sa.String(255), nullable=True)
|
||||
nfp_id = sa.Column(types.Uuid, sa.ForeignKey('vnffgnfps.id'))
|
||||
|
||||
|
||||
@ -376,6 +376,17 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
# create NFP dict
|
||||
nfp_dict = self._create_nfp_pre(template_db)
|
||||
LOG.debug('NFP: %s', nfp_dict)
|
||||
path_id = nfp_dict['path_id']
|
||||
try:
|
||||
if path_id:
|
||||
vnffgNfp_db = (self._model_query(context, VnffgNfp).
|
||||
filter(VnffgNfp.path_id == path_id).one())
|
||||
raise nfvo.NfpDuplicatePathID(path_id=path_id,
|
||||
nfp_name=vnffgNfp_db.name,
|
||||
vnffg_name=name)
|
||||
except orm_exc.NoResultFound:
|
||||
pass
|
||||
|
||||
vnffg_db = Vnffg(id=vnffg_id,
|
||||
tenant_id=tenant_id,
|
||||
name=name,
|
||||
@ -401,7 +412,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
tenant_id=tenant_id,
|
||||
name=nfp_dict['name'],
|
||||
status=constants.PENDING_CREATE,
|
||||
path_id=nfp_dict['path_id'],
|
||||
path_id=path_id,
|
||||
symmetrical=symmetrical)
|
||||
context.session.add(nfp_db)
|
||||
|
||||
@ -414,7 +425,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
symmetrical=symmetrical,
|
||||
chain=chain,
|
||||
nfp_id=nfp_id,
|
||||
path_id=nfp_dict['path_id'])
|
||||
path_id=path_id)
|
||||
|
||||
context.session.add(sfc_db)
|
||||
|
||||
@ -446,13 +457,8 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
# we assume only one NFP for initial implementation
|
||||
nfp_dict['name'] = template['groups'][vnffg_name]['members'][0]
|
||||
nfp_dict['path_id'] = template['node_templates'][nfp_dict['name']][
|
||||
'properties']['id']
|
||||
|
||||
if not nfp_dict['path_id']:
|
||||
# TODO(trozet): do we need to check if this path ID is already
|
||||
# taken by another VNFFG
|
||||
nfp_dict['path_id'] = random.randint(1, 16777216)
|
||||
|
||||
'properties'].get('id', None)
|
||||
# 'path_id' will be updated when creating port chain is done
|
||||
return nfp_dict
|
||||
|
||||
def _create_port_chain(self, context, vnf_mapping, template_db, nfp_name):
|
||||
@ -760,7 +766,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
|
||||
# called internally, not by REST API
|
||||
# instance_id = None means error on creation
|
||||
def _create_vnffg_post(self, context, sfc_instance_id,
|
||||
def _create_vnffg_post(self, context, sfc_instance_id, path_id,
|
||||
classifiers_map, vnffg_dict):
|
||||
LOG.debug('SFC created instance is %s', sfc_instance_id)
|
||||
LOG.debug('Flow Classifiers created instances are %s',
|
||||
@ -768,11 +774,16 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
nfp_dict = self.get_nfp(context, vnffg_dict['forwarding_paths'])
|
||||
sfc_id = nfp_dict['chain_id']
|
||||
with context.session.begin(subtransactions=True):
|
||||
nfp_query = (self._model_query(context, VnffgNfp).
|
||||
filter(VnffgNfp.id == nfp_dict['id']).
|
||||
filter(VnffgNfp.status == constants.PENDING_CREATE).
|
||||
one())
|
||||
nfp_query.update({'path_id': path_id})
|
||||
query = (self._model_query(context, VnffgChain).
|
||||
filter(VnffgChain.id == sfc_id).
|
||||
filter(VnffgChain.status == constants.PENDING_CREATE).
|
||||
one())
|
||||
query.update({'instance_id': sfc_instance_id})
|
||||
query.update({'instance_id': sfc_instance_id, 'path_id': path_id})
|
||||
if sfc_instance_id is None:
|
||||
query.update({'status': constants.ERROR})
|
||||
else:
|
||||
|
@ -208,6 +208,11 @@ class NfpDuplicatePolicyCriteria(exceptions.TackerException):
|
||||
message = _('The %(first_dict)s and %(sec_dict)s are overlapped')
|
||||
|
||||
|
||||
class NfpDuplicatePathID(exceptions.TackerException):
|
||||
message = _('The path_id %(path_id)s is overlapped with '
|
||||
'NFP %(nfp_name)s in %(vnffg_name)s')
|
||||
|
||||
|
||||
class NfpPolicyTypeError(exceptions.PolicyCheckError):
|
||||
message = _('Unsupported Policy Type: %(type)s')
|
||||
|
||||
|
@ -387,7 +387,7 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
|
||||
|
||||
raise ValueError('empty match field for input flow classifier')
|
||||
|
||||
def create_chain(self, name, fc_ids, vnfs, symmetrical=False,
|
||||
def create_chain(self, name, path_id, fc_ids, vnfs, symmetrical=False,
|
||||
auth_attr=None):
|
||||
if not auth_attr:
|
||||
LOG.warning("auth information required for n-sfc driver")
|
||||
@ -485,6 +485,8 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
|
||||
# TODO(s3wong): should the chain name be given as a parameter?
|
||||
port_chain = {}
|
||||
port_chain['name'] = name + '-port-chain'
|
||||
if path_id:
|
||||
port_chain['chain_id'] = path_id
|
||||
port_chain['description'] = 'port-chain for Tacker VNFFG'
|
||||
port_chain['port_pair_groups'] = port_pair_group_list
|
||||
port_chain['flow_classifiers'] = fc_ids
|
||||
@ -915,7 +917,7 @@ class NeutronClient(object):
|
||||
raise ValueError(str(e))
|
||||
|
||||
if pc and len(pc):
|
||||
return pc['port_chain']['id']
|
||||
return pc['port_chain']['id'], pc['port_chain']['chain_id']
|
||||
else:
|
||||
return None
|
||||
|
||||
|
@ -351,9 +351,10 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||
name=item['name'],
|
||||
fc=item['match'],
|
||||
auth_attr=vim_obj['auth_cred']))
|
||||
sfc_id = self._vim_drivers.invoke(driver_type,
|
||||
sfc_id, path_id = self._vim_drivers.invoke(driver_type,
|
||||
'create_chain',
|
||||
name=vnffg_dict['name'],
|
||||
path_id=sfc['path_id'],
|
||||
vnfs=sfc['chain'],
|
||||
fc_ids=fc_ids,
|
||||
symmetrical=sfc['symmetrical'],
|
||||
@ -364,7 +365,7 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||
classifiers_map = super(NfvoPlugin, self). \
|
||||
create_classifiers_map(nfp['classifier_ids'], fc_ids)
|
||||
super(NfvoPlugin, self)._create_vnffg_post(context, sfc_id,
|
||||
classifiers_map,
|
||||
path_id, classifiers_map,
|
||||
vnffg_dict)
|
||||
super(NfvoPlugin, self)._create_vnffg_status(context, vnffg_dict)
|
||||
return vnffg_dict
|
||||
|
@ -183,6 +183,7 @@ class TestChainSFC(base.TestCase):
|
||||
vnfs = [vnf_1, vnf_2, vnf_3]
|
||||
|
||||
chain_id = self.sfc_driver.create_chain(name='fake_ffg',
|
||||
path_id=None,
|
||||
fc_ids=fc_id,
|
||||
vnfs=vnfs,
|
||||
auth_attr=auth_attr)
|
||||
@ -238,6 +239,7 @@ class TestChainSFC(base.TestCase):
|
||||
vnfs = [vnf_1, vnf_2, vnf_3]
|
||||
|
||||
result = self.sfc_driver.create_chain(name='fake_ffg',
|
||||
path_id=None,
|
||||
fc_ids=fc_id,
|
||||
vnfs=vnfs,
|
||||
auth_attr=auth_attr)
|
||||
@ -269,6 +271,7 @@ class TestChainSFC(base.TestCase):
|
||||
vnfs = [vnf_1, vnf_2, vnf_3]
|
||||
|
||||
chain_id = self.sfc_driver.create_chain(name='fake_ffg',
|
||||
path_id=None,
|
||||
fc_ids=fc_id,
|
||||
vnfs=vnfs,
|
||||
auth_attr=auth_attr)
|
||||
|
@ -54,9 +54,11 @@ def _get_template(name):
|
||||
|
||||
class FakeDriverManager(mock.Mock):
|
||||
def invoke(self, *args, **kwargs):
|
||||
if any(x in ['create', 'create_chain', 'create_flow_classifier'] for
|
||||
if any(x in ['create', 'create_flow_classifier'] for
|
||||
x in args):
|
||||
return uuidutils.generate_uuid()
|
||||
elif 'create_chain' in args:
|
||||
return uuidutils.generate_uuid(), uuidutils.generate_uuid()
|
||||
elif 'execute_workflow' in args:
|
||||
mock_execution = mock.Mock()
|
||||
mock_execution.id.return_value = \
|
||||
@ -656,6 +658,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertEqual('PENDING_CREATE', result['status'])
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
path_id=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_ids=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
@ -677,6 +680,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertEqual('PENDING_CREATE', result['status'])
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
path_id=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_ids=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
@ -703,6 +707,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
mock_create_vnffgd.assert_called_once_with(mock.ANY, mock.ANY)
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
path_id=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_ids=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
@ -724,6 +729,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertEqual('PENDING_CREATE', result['status'])
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
path_id=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_ids=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
@ -745,6 +751,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertEqual('PENDING_CREATE', result['status'])
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
path_id=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_ids=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
@ -787,6 +794,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertEqual('PENDING_CREATE', result['status'])
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
path_id=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_ids=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
|
Loading…
Reference in New Issue
Block a user