Activity log for bug #2129983

Date Who What changed Old value New value Message
2025-10-28 02:00:22 Hitomi Koba bug added bug
2025-12-08 06:23:50 Hitomi Koba description When there are two projects (for example, Project A and Project B), if both try to onboard a VNF Package that contains the same vnfdId, the onboarding of the second project fails. Currently, the vnfdId duplication check is performed globally across all projects, instead of being scoped per tenant/project. As a result, multi-tenancy is not properly supported in VNF Package onboarding. Project A: ``` $ openstack vnf p list +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | Id | Vnf Product Name | Onboarding State | Usage State | Operational State | Links | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08 | Sample | ONBOARDED | NOT_IN_USE | ENABLED | { | | | | | | | "self": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08" | | | | | | | }, | | | | | | | "packageContent": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08/package_content" | | | | | | | } | | | | | | | } | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ $ openstack vnf p show a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08 -c 'VNFD ID' +---------+--------------------------------------+ | Field | Value | +---------+--------------------------------------+ | VNFD ID | c922dbf4-ee96-4e4b-af0e-85d233504d48 | +---------+--------------------------------------+ ``` Project B: The status remains `CREATED` instead of changing to `ONBOARDED`. ``` $ openstack vnf p list +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | Id | Vnf Product Name | Onboarding State | Usage State | Operational State | Links | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | 390b0bc9-90a3-4f3c-b510-c99f652f3679 | | CREATED | NOT_IN_USE | DISABLED | { | | | | | | | "self": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/390b0bc9-90a3-4f3c-b510-c99f652f3679" | | | | | | | }, | | | | | | | "packageContent": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/390b0bc9-90a3-4f3c-b510-c99f652f3679/package_content" | | | | | | | } | | | | | | | } | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ ``` Tacker error log ``` Traceback (most recent call last): File "/usr/local/lib/python3.8/dist-packages/oslo_messaging/rpc/server.py", line 165, in _process_incoming res = self.dispatcher.dispatch(message) File "/usr/local/lib/python3.8/dist-packages/oslo_messaging/rpc/dispatcher.py", line 309, in dispatch return self._do_dispatch(endpoint, method, ctxt, args) File "/usr/local/lib/python3.8/dist-packages/oslo_messaging/rpc/dispatcher.py", line 229, in _do_dispatch result = func(ctxt, **new_args) File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 164, in decorated_function vnf_package.save() File "/usr/local/lib/python3.8/dist-packages/oslo_utils/excutils.py", line 227, in __exit__ self.force_reraise() File "/usr/local/lib/python3.8/dist-packages/oslo_utils/excutils.py", line 200, in force_reraise raise self.value File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 127, in decorated_function return function(self, context, *args, **kwargs) File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 507, in load_csar_data self._onboard_vnf_package( File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 456, in _onboard_vnf_package package_vnfd.create() File "/usr/local/lib/python3.8/dist-packages/oslo_versionedobjects/base.py", line 226, in wrapper return fn(self, *args, **kwargs) File "/opt/stack/tacker/tacker/objects/vnf_package_vnfd.py", line 204, in create db_vnf_package_vnfd = _vnf_package_vnfd_create( File "/usr/local/lib/python3.8/dist-packages/oslo_db/sqlalchemy/enginefacade.py", line 1022, in wrapper return fn(*args, **kwargs) File "/opt/stack/tacker/tacker/objects/vnf_package_vnfd.py", line 39, in _vnf_package_vnfd_create raise exceptions.VnfPackageVnfdIdDuplicate( tacker.common.exceptions.VnfPackageVnfdIdDuplicate: Vnf package with vnfd id c922dbf4-ee96-4e4b-af0e-85d233504d48 already exists. ``` ## Summary In the current Tacker implementation, a VNFD ID is treated as globally unique across all projects. As a result, it is not possible for multiple projects to onboard VNF packages that contain the same vnfdId, even if those projects are logically separated tenants. This behavior is inconsistent with the expected multi-tenant model, where each tenant should be able to onboard and use the same VNF package independently. ## Current behavior When there are two projects (for example, Project A and Project B), and both try to onboard a VNF package that contains the same vnfdId: - Project A can successfully onboard the VNF package. - Project B tries to onboard a different VNF package that contains the same vnfdId. - The onboarding for Project B fails with VnfPackageVnfdIdDuplicate, and the onboarding state remains in CREATED instead of changing to ONBOARDED. Project A: ``` $ openstack vnf p list +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | Id | Vnf Product Name | Onboarding State | Usage State | Operational State | Links | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08 | Sample | ONBOARDED | NOT_IN_USE | ENABLED | { | | | | | | | "self": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08" | | | | | | | }, | | | | | | | "packageContent": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08/package_content" | | | | | | | } | | | | | | | } | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ $ openstack vnf p show a1cf34b0-ab73-4d36-8b32-0aac4f0c0c08 -c 'VNFD ID' +---------+--------------------------------------+ | Field | Value | +---------+--------------------------------------+ | VNFD ID | c922dbf4-ee96-4e4b-af0e-85d233504d48 | +---------+--------------------------------------+ ``` Project B: The status remains `CREATED` instead of changing to `ONBOARDED`. ``` $ openstack vnf p list +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | Id | Vnf Product Name | Onboarding State | Usage State | Operational State | Links | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ | 390b0bc9-90a3-4f3c-b510-c99f652f3679 | | CREATED | NOT_IN_USE | DISABLED | { | | | | | | | "self": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/390b0bc9-90a3-4f3c-b510-c99f652f3679" | | | | | | | }, | | | | | | | "packageContent": { | | | | | | | "href": "/vnfpkgm/v1/vnf_packages/390b0bc9-90a3-4f3c-b510-c99f652f3679/package_content" | | | | | | | } | | | | | | | } | +--------------------------------------+------------------+------------------+-------------+-------------------+-------------------------------------------------------------------------------------------------+ ``` Tacker error log ``` Traceback (most recent call last):   File "/usr/local/lib/python3.8/dist-packages/oslo_messaging/rpc/server.py", line 165, in _process_incoming     res = self.dispatcher.dispatch(message)   File "/usr/local/lib/python3.8/dist-packages/oslo_messaging/rpc/dispatcher.py", line 309, in dispatch     return self._do_dispatch(endpoint, method, ctxt, args)   File "/usr/local/lib/python3.8/dist-packages/oslo_messaging/rpc/dispatcher.py", line 229, in _do_dispatch     result = func(ctxt, **new_args)   File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 164, in decorated_function     vnf_package.save()   File "/usr/local/lib/python3.8/dist-packages/oslo_utils/excutils.py", line 227, in __exit__     self.force_reraise()   File "/usr/local/lib/python3.8/dist-packages/oslo_utils/excutils.py", line 200, in force_reraise     raise self.value   File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 127, in decorated_function     return function(self, context, *args, **kwargs)   File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 507, in load_csar_data     self._onboard_vnf_package(   File "/opt/stack/tacker/tacker/conductor/conductor_server.py", line 456, in _onboard_vnf_package     package_vnfd.create()   File "/usr/local/lib/python3.8/dist-packages/oslo_versionedobjects/base.py", line 226, in wrapper     return fn(self, *args, **kwargs)   File "/opt/stack/tacker/tacker/objects/vnf_package_vnfd.py", line 204, in create     db_vnf_package_vnfd = _vnf_package_vnfd_create(   File "/usr/local/lib/python3.8/dist-packages/oslo_db/sqlalchemy/enginefacade.py", line 1022, in wrapper     return fn(*args, **kwargs)   File "/opt/stack/tacker/tacker/objects/vnf_package_vnfd.py", line 39, in _vnf_package_vnfd_create     raise exceptions.VnfPackageVnfdIdDuplicate( tacker.common.exceptions.VnfPackageVnfdIdDuplicate: Vnf package with vnfd id c922dbf4-ee96-4e4b-af0e-85d233504d48 already exists. ``` ## Expected behavior From a data-model perspective, tenant-scoped resources in Tacker should behave consistently. Resources such as: - VNF Package (e.g. `vnf_packages` table), - VNF Instance (e.g. `vnf_instances` table), - VIMs (e.g. `vims` table) ... all have a `tenant_id` column and are treated as **tenant-scoped**. Their ownership and uniqueness are evaluated within the scope of a single tenant/project. By contrast, the VNFD metadata table (e.g. `vnf_package_vnfd`) does not have a `tenant_id` column, and `vnfdId` is enforced as **globally unique** across the whole deployment. This effectively makes VNFD a **global** resource. In a real multi-tenant NFV deployment, however: - The same VNFD (the same VNF product and VNFD content) may need to be used by different projects/tenants. - The choice of “which project owns this VNF package?” is an operational and design decision, and should not be constrained by a globally unique `vnfdId`. Therefore, VNFD should be aligned with other resources and become **tenant-scoped** as well, by introducing `tenant_id` into the VNFD metadata and scoping uniqueness per tenant. VNFD metadata (vnf_package_vnfd) – expected - id (PK) - package_uuid (FK → vnf_packages.id) - tenant_id (same value as the owning VNF package) - vnfd_id - ... other fields ... - Uniqueness constraint: UNIQUE (tenant_id, vnfd_id)