From 41d7f5ce01116780bbfca3c99c45c7ffdcc11c31 Mon Sep 17 00:00:00 2001 From: Wataru Juso Date: Thu, 1 Jul 2021 18:09:12 +0900 Subject: [PATCH] Add specifying tenant in notification This patch fixes separate resources related to ETSI NFV-SOL based VNF management by using tenant. Co-Author: Manpreet Kaur Implement: blueprint multi-tenant-policy Change-Id: I4de84c85ab77429fb5b2c07f500c453632960a84 --- tacker/api/vnflcm/v1/controller.py | 10 ++- tacker/conductor/conductor_server.py | 24 ++++++ tacker/db/db_sqlalchemy/models.py | 2 + .../alembic_migrations/versions/HEAD | 2 +- ...add_tenant_id_to_lcm_subscriptions_and_.py | 39 ++++++++++ tacker/objects/vnf_instance.py | 11 ++- tacker/objects/vnf_lcm_op_occs.py | 8 +- tacker/objects/vnf_lcm_subscriptions.py | 18 +++-- .../unit/conductor/test_conductor_server.py | 77 ++++++++++++++----- tacker/tests/unit/db/test_vnf_instance.py | 3 +- tacker/tests/unit/objects/fakes.py | 6 +- .../unit/objects/test_vnf_lcm_op_occs.py | 1 + .../objects/test_vnf_lcm_subscriptions.py | 75 +++++++++++++++++- 13 files changed, 234 insertions(+), 42 deletions(-) create mode 100644 tacker/db/migration/alembic_migrations/versions/d6ae359ab0d6_add_tenant_id_to_lcm_subscriptions_and_.py diff --git a/tacker/api/vnflcm/v1/controller.py b/tacker/api/vnflcm/v1/controller.py index 105b63a5c..8c261b36c 100644 --- a/tacker/api/vnflcm/v1/controller.py +++ b/tacker/api/vnflcm/v1/controller.py @@ -349,7 +349,8 @@ class VnfLcmController(wsgi.Controller): operation=lcm_operation, is_automatic_invocation=is_auto, operation_params=operation_params, - error_point=error_point) + error_point=error_point, + tenant_id=context.tenant_id) vnf_lcm_op_occs.create() except Exception: msg = _("Failed to create LCM occurrence") @@ -914,7 +915,8 @@ class VnfLcmController(wsgi.Controller): 'vnf_instance_id': id, 'id': op_occs_uuid, 'state_entered_time': timeutils.utcnow(), - 'operationParams': str(body)} + 'operationParams': str(body), + 'tenant_id': request.context.project_id} self.rpc_api.update( context, @@ -947,6 +949,7 @@ class VnfLcmController(wsgi.Controller): 'callbackUri') vnf_lcm_subscription.subscription_authentication = \ subscription_request_data.get('subscriptionAuthentication') + vnf_lcm_subscription.tenant_id = request.context.tenant_id LOG.debug("filter %s " % subscription_request_data.get('filter')) LOG.debug( "filter type %s " % @@ -1225,7 +1228,8 @@ class VnfLcmController(wsgi.Controller): is_automatic_invocation=scale_vnf_request.additional_params.get('\ is_auto'), operation_params=json.dumps(operation_params), - error_point=1) + error_point=1, + tenant_id=vnf_instance.tenant_id) vnf_lcm_op_occ.create() else: try: diff --git a/tacker/conductor/conductor_server.py b/tacker/conductor/conductor_server.py index 537b042f4..e8e1bbf6a 100644 --- a/tacker/conductor/conductor_server.py +++ b/tacker/conductor/conductor_server.py @@ -1790,6 +1790,11 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook): context, notification_type=notification.get('notificationType') ) + + vnf_lcm_subscriptions = \ + self._extract_subscriptions(context, vnf_lcm_subscriptions, + notification.get('vnfInstanceId')) + if not vnf_lcm_subscriptions: LOG.warning( "vnf_lcm_subscription not found id[%s]" % @@ -1861,6 +1866,24 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook): return -2 return 0 + def _extract_subscriptions(self, context, vnf_lcm_subscriptions, + vnf_instance_id): + + extract_vnf_lcm_subscriptions = [] + + try: + vnf_instance = objects.VnfInstance.get_by_id( + context, vnf_instance_id, read_deleted='yes') + except exceptions.VnfInstanceNotFound: + LOG.warning("Can not find vnf instance for notification: %s" % id) + return [] + + for subscription in vnf_lcm_subscriptions: + if subscription.tenant_id == vnf_instance.get("tenant_id"): + extract_vnf_lcm_subscriptions.append(subscription) + + return extract_vnf_lcm_subscriptions + def _retry_check(self, retry_count): time.sleep(CONF.vnf_lcm.retry_wait) if retry_count == CONF.vnf_lcm.retry_num: @@ -2272,6 +2295,7 @@ class Conductor(manager.Manager, v2_hook.ConductorV2Hook): lcm_op_obj.is_automatic_invocation = 0 lcm_op_obj.is_cancel_pending = 0 lcm_op_obj.operation_params = vnf_lcm_opoccs.get('operationParams') + lcm_op_obj.tenant_id = vnf_lcm_opoccs.get('tenant_id') try: lcm_op_obj.create() diff --git a/tacker/db/db_sqlalchemy/models.py b/tacker/db/db_sqlalchemy/models.py index 024edff1a..f1585f767 100644 --- a/tacker/db/db_sqlalchemy/models.py +++ b/tacker/db/db_sqlalchemy/models.py @@ -311,6 +311,7 @@ class VnfLcmSubscriptions(model_base.BASE, models.SoftDeleteMixin, id = sa.Column(sa.String(36), nullable=False, primary_key=True) callback_uri = sa.Column(sa.String(255), nullable=False) subscription_authentication = sa.Column(sa.JSON, nullable=True) + tenant_id = sa.Column('tenant_id', sa.String(length=64), nullable=False) subscription_filter = orm.relationship( VnfLcmFilters, @@ -340,6 +341,7 @@ class VnfLcmOpOccs(model_base.BASE, models.SoftDeleteMixin, changed_info = sa.Column(sa.JSON(), nullable=True) changed_ext_connectivity = sa.Column(sa.JSON(), nullable=True) error_point = sa.Column(sa.Integer, nullable=False) + tenant_id = sa.Column('tenant_id', sa.String(length=64), nullable=False) class PlacementConstraint(model_base.BASE, models.SoftDeleteMixin, diff --git a/tacker/db/migration/alembic_migrations/versions/HEAD b/tacker/db/migration/alembic_migrations/versions/HEAD index b819caf90..93b7b1718 100644 --- a/tacker/db/migration/alembic_migrations/versions/HEAD +++ b/tacker/db/migration/alembic_migrations/versions/HEAD @@ -1 +1 @@ -3ff50553e9d3 +d6ae359ab0d6 diff --git a/tacker/db/migration/alembic_migrations/versions/d6ae359ab0d6_add_tenant_id_to_lcm_subscriptions_and_.py b/tacker/db/migration/alembic_migrations/versions/d6ae359ab0d6_add_tenant_id_to_lcm_subscriptions_and_.py new file mode 100644 index 000000000..4f36f497b --- /dev/null +++ b/tacker/db/migration/alembic_migrations/versions/d6ae359ab0d6_add_tenant_id_to_lcm_subscriptions_and_.py @@ -0,0 +1,39 @@ +# Copyright 2022 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. +# + +"""add tenant_id to lcm_subscriptions and lcm_op_occs + +Revision ID: d6ae359ab0d6 +Revises: 3ff50553e9d3 +Create Date: 2022-01-06 13:35:53.868106 + +""" + +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision = 'd6ae359ab0d6' +down_revision = '3ff50553e9d3' + + +def upgrade(active_plugins=None, options=None): + op.add_column('vnf_lcm_subscriptions', + sa.Column('tenant_id', sa.String(length=64), + nullable=False)) + + op.add_column('vnf_lcm_op_occs', + sa.Column('tenant_id', sa.String(length=64), + nullable=False)) diff --git a/tacker/objects/vnf_instance.py b/tacker/objects/vnf_instance.py index 2ba04843c..314faca12 100644 --- a/tacker/objects/vnf_instance.py +++ b/tacker/objects/vnf_instance.py @@ -41,10 +41,12 @@ LOG = logging.getLogger(__name__) @db_api.context_manager.reader -def _vnf_instance_get_by_id(context, vnf_instance_id, columns_to_join=None): +def _vnf_instance_get_by_id(context, vnf_instance_id, columns_to_join=None, + read_deleted="no"): query = api.model_query(context, models.VnfInstance, - read_deleted="no", project_only=True). \ + read_deleted=read_deleted, + project_only=True). \ filter_by(id=vnf_instance_id) if columns_to_join: @@ -517,10 +519,11 @@ class VnfInstance(base.TackerObject, base.TackerPersistentObject, vnfd_id) @base.remotable_classmethod - def get_by_id(cls, context, id): + def get_by_id(cls, context, id, read_deleted="no"): expected_attrs = ["instantiated_vnf_info"] db_vnf_instance = _vnf_instance_get_by_id( - context, id, columns_to_join=expected_attrs) + context, id, columns_to_join=expected_attrs, + read_deleted=read_deleted) return cls._from_db_object(context, cls(), db_vnf_instance, expected_attrs=expected_attrs) diff --git a/tacker/objects/vnf_lcm_op_occs.py b/tacker/objects/vnf_lcm_op_occs.py index d8c8fc197..329bebc2a 100644 --- a/tacker/objects/vnf_lcm_op_occs.py +++ b/tacker/objects/vnf_lcm_op_occs.py @@ -49,6 +49,7 @@ def _vnf_lcm_op_occ_create(context, values): 'changed_info': values.changed_info, 'changed_ext_connectivity': values.changed_ext_connectivity, 'error_point': values.error_point, + 'tenant_id': values.tenant_id, } if 'grant_id' in values: fields['grant_id'] = values.grant_id @@ -242,7 +243,8 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat, 'VnfInfoModifications', nullable=True, default=None), 'changed_ext_connectivity': fields.ListOfObjectsField( 'ExtVirtualLinkInfo', nullable=True, default=[]), - 'error_point': fields.IntegerField(nullable=True, default=0) + 'error_point': fields.IntegerField(nullable=True, default=0), + 'tenant_id': fields.StringField(nullable=False) } ALL_ATTRIBUTES = { @@ -367,6 +369,7 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat, changed_info = data_dict.get('changed_info') changed_ext_connectivity = data_dict.get('changed_ext_connectivity') error_point = data_dict.get('error_point') + tenant_id = data_dict.get('tenant_id') obj = cls(operation_state=operation_state, state_entered_time=state_entered_time, @@ -381,7 +384,8 @@ class VnfLcmOpOcc(base.TackerObject, base.TackerObjectDictCompat, resource_changes=resource_changes, changed_info=changed_info, changed_ext_connectivity=changed_ext_connectivity, - error_point=error_point + error_point=error_point, + tenant_id=tenant_id ) return obj diff --git a/tacker/objects/vnf_lcm_subscriptions.py b/tacker/objects/vnf_lcm_subscriptions.py index b292cd303..97a78f701 100644 --- a/tacker/objects/vnf_lcm_subscriptions.py +++ b/tacker/objects/vnf_lcm_subscriptions.py @@ -109,7 +109,8 @@ def _vnf_lcm_subscriptions_get(context, if notification_type == 'VnfLcmOperationOccurrenceNotification': sql = ( "select" - " t1.id,t1.callback_uri,t1.subscription_authentication,t2.filter " + " t1.id,t1.callback_uri,t1.subscription_authentication," + " t1.tenant_id, t2.filter " " from " " vnf_lcm_subscriptions t1, " " (select distinct subscription_uuid,filter from vnf_lcm_filters " @@ -132,7 +133,8 @@ def _vnf_lcm_subscriptions_get(context, else: sql = ( "select" - " t1.id,t1.callback_uri,t1.subscription_authentication,t2.filter " + " t1.id,t1.callback_uri,t1.subscription_authentication," + " t1.tenant_id, t2.filter " " from " " vnf_lcm_subscriptions t1, " " (select distinct subscription_uuid,filter from vnf_lcm_filters " @@ -375,10 +377,12 @@ def _vnf_lcm_subscriptions_create(context, values, filter): new_entries.append({"id": values.id, "callback_uri": values.callback_uri, "subscription_authentication": - values.subscription_authentication}) + values.subscription_authentication, + "tenant_id": values.tenant_id}) else: new_entries.append({"id": values.id, - "callback_uri": values.callback_uri}) + "callback_uri": values.callback_uri, + "tenant_id": values.tenant_id}) context.session.execute( models.VnfLcmSubscriptions.__table__.insert(None), @@ -480,7 +484,8 @@ class LccnSubscriptionRequest(base.TackerObject, base.TackerPersistentObject): 'callback_uri': fields.StringField(nullable=False), 'subscription_authentication': fields.DictOfStringsField(nullable=True), - 'filter': fields.StringField(nullable=True) + 'filter': fields.StringField(nullable=True), + 'tenant_id': fields.StringField(nullable=False) } @base.remotable @@ -578,6 +583,7 @@ class ChangeNotificationsFilter( 'operation_states': fields.StringField(nullable=True), 'operation_states_len': fields.IntegerField( nullable=True, default=0), + 'tenant_id': fields.StringField(nullable=False), } @@ -631,6 +637,8 @@ class LccnSubscription(base.TackerObject, base.TackerPersistentObject): 'VnfLcmFilters'), 'callbackUri': ('callback_uri', 'string', 'VnfLcmSubscriptions'), + 'tenantId': ('tenant_id', 'string', + 'VnfLcmSubscriptions'), } FLATTEN_ATTRIBUTES = utils.flatten_dict(ALL_ATTRIBUTES.copy()) diff --git a/tacker/tests/unit/conductor/test_conductor_server.py b/tacker/tests/unit/conductor/test_conductor_server.py index 6bb59a4ab..d0c3226e3 100644 --- a/tacker/tests/unit/conductor/test_conductor_server.py +++ b/tacker/tests/unit/conductor/test_conductor_server.py @@ -131,6 +131,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): auth_params).encode() self.id = uuidsentinel.lcm_subscription_id + self.tenant_id = uuidsentinel.tenant_id self.callback_uri = 'https://localhost/callback'.encode() def __getattr__(self, name): @@ -158,7 +159,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): 'state_entered_time': datetime.datetime( 1900, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC), - 'operationParams': 'operationParams' + 'operationParams': 'operationParams', + 'tenant_id': uuidsentinel.tenant_id } return vnf_lcm_opoccs @@ -2477,6 +2479,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): is_cancel_pending=False, error_point=0, id='00e1314d-2a82-40bd-b318-cc881243842d', + tenant_id='01db9967-ba45-4f1d-962d-7cbb825448f1', created_at=datetime.datetime(2000, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)) vnf_lcm_op_occ.create() @@ -2625,6 +2628,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): operation_params='{"type": "SCALE_OUT", "aspect_id": "SP1"}', is_cancel_pending=False, error_point=0, + tenant_id='7cd42301-a3a5-47ad-a7bd-87b02540503b', id='00e1314d-2a82-40bd-b318-cc881243843d', created_at=datetime.datetime(2000, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)) @@ -2728,6 +2732,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): operation_params='{"type": "SCALE_OUT", "aspect_id": "SP1"}', error_point=0, id='00e1314d-2a82-40bd-b318-cc881243843d', + tenant_id='00e1314d-2a82-40bd-b318-cc881243843r', created_at=datetime.datetime(2000, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)) vnf_lcm_op_occ.create() @@ -2790,7 +2795,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): mock_subscriptions_get): mock_subscriptions_get.return_value = None notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfLcmOperationOccurrenceNotification'} result = self.conductor.send_notification(self.context, notification) @@ -2798,19 +2803,23 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): self.assertEqual(result, -1) mock_subscriptions_get.assert_called() + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_send_notification_vnf_lcm_operation_occurrence(self, - mock_subscriptions_get): + mock_subscriptions_get, + mock_vnf_by_id): self.requests_mock.register_uri('POST', "https://localhost/callback", headers={ 'Content-Type': 'application/json'}, status_code=204) + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) mock_subscriptions_get.return_value = self._create_subscriptions() notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfLcmOperationOccurrenceNotification', 'operationTypes': 'SCALE', 'operationStates': 'RESULT', @@ -2826,10 +2835,12 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): history, "https://localhost") self.assertEqual(1, req_count) + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_send_notification_vnf_identifier_creation(self, - mock_subscriptions_get): + mock_subscriptions_get, + mock_vnf_by_id): self.requests_mock.register_uri( 'POST', "https://localhost/callback", @@ -2837,9 +2848,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): 'Content-Type': 'application/json'}, status_code=204) + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) mock_subscriptions_get.return_value = self._create_subscriptions() notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} @@ -2853,9 +2866,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): history, "https://localhost") self.assertEqual(1, req_count) + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') - def test_send_notification_with_auth_basic(self, mock_subscriptions_get): + def test_send_notification_with_auth_basic(self, mock_subscriptions_get, + mock_vnf_by_id): self.requests_mock.register_uri('POST', "https://localhost/callback", headers={ @@ -2868,9 +2883,10 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): {'authType': 'BASIC', 'paramsBasic': {'userName': auth_user_name, 'password': auth_password}}) - + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} @@ -2888,10 +2904,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): auth_user_name, auth_password) + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_send_notification_with_auth_client_credentials( - self, mock_subscriptions_get): + self, mock_subscriptions_get, mock_vnf_by_id): auth.auth_manager = auth._AuthManager() self.requests_mock.register_uri( 'POST', @@ -2916,8 +2933,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): 'clientPassword': auth_password, 'tokenEndpoint': token_endpoint}}) + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) + notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} @@ -2933,19 +2953,23 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): self.assert_auth_basic(history[0], auth_user_name, auth_password) self.assert_auth_client_credentials(history[1], "test_token") + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_send_notification_retry_notification(self, - mock_subscriptions_get): + mock_subscriptions_get, + mock_vnf_by_id): self.requests_mock.register_uri('POST', "https://localhost/callback", headers={ 'Content-Type': 'application/json'}, status_code=400) + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) mock_subscriptions_get.return_value = self._create_subscriptions() notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} @@ -2959,10 +2983,12 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): history, "https://localhost") self.assertEqual(3, req_count) + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_send_notification_send_error(self, - mock_subscriptions_get): + mock_subscriptions_get, + mock_vnf_by_id): self.requests_mock.register_uri( 'POST', "https://localhost/callback", @@ -2970,10 +2996,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): mock_subscriptions_get.return_value = self._create_subscriptions() notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} - + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, 0) @@ -2984,32 +3011,40 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase): history, "https://localhost") self.assertEqual(1, req_count) + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') def test_send_notification_internal_server_error( - self, mock_subscriptions_get): + self, mock_subscriptions_get, + mock_vnf_by_id): mock_subscriptions_get.side_effect = Exception("MockException") notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationTypes': 'VnfIdentifierCreationNotification', 'links': {}} - + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) result = self.conductor.send_notification(self.context, notification) self.assertEqual(result, -2) mock_subscriptions_get.assert_called() + @mock.patch.object(objects.VnfInstance, 'get_by_id') @mock.patch.object(objects.LccnSubscriptionRequest, 'vnf_lcm_subscriptions_get') - def test_send_notification_timeout(self, mock_subscriptions_get): + def test_send_notification_timeout(self, mock_subscriptions_get, + mock_vnf_by_id): self.requests_mock.register_uri( 'POST', "https://localhost/callback", exc=requests.Timeout) + mock_vnf_by_id.return_value = fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) + mock_subscriptions_get.return_value = self._create_subscriptions() notification = { - 'vnfInstanceId': 'Test', + 'vnfInstanceId': uuidsentinel.vnf_instance_id, 'notificationType': 'VnfIdentifierCreationNotification', 'links': {}} diff --git a/tacker/tests/unit/db/test_vnf_instance.py b/tacker/tests/unit/db/test_vnf_instance.py index 4a37795d0..091a25f1d 100644 --- a/tacker/tests/unit/db/test_vnf_instance.py +++ b/tacker/tests/unit/db/test_vnf_instance.py @@ -59,7 +59,8 @@ class TestVnfLcm(SqlTestCase): def test_vnf_instance_get_by_id(self): result = vnf_instance._vnf_instance_get_by_id( - self.context, self.vnf_instance.id, columns_to_join=None) + self.context, self.vnf_instance.id, + columns_to_join=None, read_deleted="no") self.assertEqual(self.vnf_instance.id, result.id) def test_vnf_instance_create(self): diff --git a/tacker/tests/unit/objects/fakes.py b/tacker/tests/unit/objects/fakes.py index 7f23de934..6248e3d6d 100644 --- a/tacker/tests/unit/objects/fakes.py +++ b/tacker/tests/unit/objects/fakes.py @@ -94,13 +94,15 @@ filter = { } ], "notificationTypes": ["VnfLcmOperationOccurrenceNotification"], - "operationalState": ["ENABLED"] + "operationalState": ["ENABLED"], + "tenant_id": uuidsentinel.tenant_id } subscription_data = { 'id': "c3e5ea85-8e3d-42df-a636-3b7857cbd7f9", 'callback_uri': "fake_url", - 'created_at': "2020-06-11 09:39:58" + 'created_at': "2020-06-11 09:39:58", + 'tenant_id': uuidsentinel.tenant_id } vnfd_data = { diff --git a/tacker/tests/unit/objects/test_vnf_lcm_op_occs.py b/tacker/tests/unit/objects/test_vnf_lcm_op_occs.py index 9d4c7825e..94074ff25 100644 --- a/tacker/tests/unit/objects/test_vnf_lcm_op_occs.py +++ b/tacker/tests/unit/objects/test_vnf_lcm_op_occs.py @@ -76,6 +76,7 @@ class TestVnfLcmOpOcc(SqlTestCase): context=self.context, **vnf_lcm_op_occs_data) vnf_lcm_op_occs.create() self.assertTrue(vnf_lcm_op_occs.vnf_instance_id) + self.assertTrue(vnf_lcm_op_occs.tenant_id) def test_save(self): id = uuidutils.generate_uuid() diff --git a/tacker/tests/unit/objects/test_vnf_lcm_subscriptions.py b/tacker/tests/unit/objects/test_vnf_lcm_subscriptions.py index ef68f1ed5..b98949cbb 100644 --- a/tacker/tests/unit/objects/test_vnf_lcm_subscriptions.py +++ b/tacker/tests/unit/objects/test_vnf_lcm_subscriptions.py @@ -104,7 +104,8 @@ class TestVnfLcmSubScriptions(SqlTestCase): /530a3c43-043a-4b84-9d65-aa0df49f7ced"\ }\ },\ - "id": "530a3c43-043a-4b84-9d65-aa0df49f7ced"\ + "id": "530a3c43-043a-4b84-9d65-aa0df49f7ced",\ + "tenant_id": "8cd59fef-397e-4bec-8621-0e69225434f0"\ }' subscription_obj = \ @@ -195,7 +196,8 @@ class TestVnfLcmSubScriptions(SqlTestCase): /530a3c43-043a-4b84-9d65-aa0df49f7ced"\ }\ },\ - "id": "530a3c43-043a-4b84-9d65-aa0df49f7ced"\ + "id": "530a3c43-043a-4b84-9d65-aa0df49f7ced",\ + "tenant_id": "8cd59fef-397e-4bec-8621-0e69225434f0"\ }' result = subscription_obj.vnf_lcm_subscriptions_show( @@ -258,7 +260,8 @@ class TestVnfLcmSubScriptions(SqlTestCase): /530a3c43-043a-4b84-9d65-aa0df49f7ced"\ }\ },\ - "id": "530a3c43-043a-4b84-9d65-aa0df49f7ced"\ + "id": "530a3c43-043a-4b84-9d65-aa0df49f7ced",\ + "tenant_id": "8cd59fef-397e-4bec-8621-0e69225434f0"\ }' result = subscription_obj.vnf_lcm_subscriptions_list(self.context) @@ -273,3 +276,69 @@ class TestVnfLcmSubScriptions(SqlTestCase): self.subscription.destroy(self.context, self.subscription.id) mock_vnf_lcm_subscriptions_destroy.assert_called_with( self.context, self.subscription.id) + + @mock.patch.object(objects.vnf_lcm_subscriptions, + '_vnf_lcm_subscriptions_get') + def test_get(self, mock_vnf_lcm_subscriptions_get): + subscription_obj = \ + objects.vnf_lcm_subscriptions.LccnSubscriptionRequest( + context=self.context) + mock_vnf_lcm_subscriptions_get.return_value = \ + '{\ + "filter": "{"operationStates": ["COMPLETED"],\ + "vnfInstanceNames": ["xxxxxxxxxxxxxxxxxx"],\ + "operationTypes": ["INSTANTIATE"],\ + "vnfdIds": ["405d73c7-e964-4c8b-a914-41478ccd7c42"],\ + "vnfProductsFromProviders": [{\ + "vnfProvider": "x2x", \ + "vnfProducts": [{\ + "vnfProductName": "x2xx", \ + "versions": [{\ + "vnfSoftwareVersion": "xx2XX", \ + "vnfdVersions": ["ss2"]\ + }]\ + }]\ + }, \ + {\ + "vnfProvider": "z2z",\ + "vnfProducts": [{\ + "vnfProductName": "z2zx", \ + "versions": [{\ + "vnfSoftwareVersion": "xx3XX",\ + "vnfdVersions": \ + ["s3sx", "s3sa"]\ + }\ + ]},\ + {\ + "vnfProductName": "zz3ex",\ + "versions": [{\ + "vnfSoftwareVersion": "xxe3eXz",\ + "vnfdVersions": ["ss3xz", "s3esaz"]\ + },\ + {\ + "vnfSoftwareVersion": "xxeeeXw", \ + "vnfdVersions": ["ss3xw", "ss3w"]\ + }]\ + }]\ + }],\ + "notificationTypes": [\ + "VnfLcmOperationOccurrenceNotification"],\ + "vnfInstanceIds": ["fb0b9a12-4b55-47ac-9ca8-5fdd52c4c07f"]}",\ + "callbackUri": "http://localhost/xxx",\ + "_links": {\ + "self": {\ + "href":\ + "http://localhost:9890//vnflcm/v1/subscriptions\ + /530a3c43-043a-4b84-9d65-aa0df49f7ced"\ + }\ + },\ + "id": "530a3c43-043a-4b84-9d65-aa0df49f7ced",\ + "tenant_id": "8cd59fef-397e-4bec-8621-0e69225434f0"\ + }' + + result = subscription_obj.vnf_lcm_subscriptions_get(self.context, + 'VnfLcmOperationOccurrenceNotification') + self.assertIn("tenant_id", result) + result = subscription_obj.vnf_lcm_subscriptions_get(self.context, + None) + self.assertIn("tenant_id", result)