Delete vnf package if operationalState is DISABLED

Presently, vnf package can be deleted when it's operationalState is
'ENABLED'.

As per pre-condition rule, vnf package can be deleted only when
it's operationalState is 'DISABLED' and it's usageState is 'NOT_IN_USE.

This patch fixes this issue and now vnf package will be deleted only
when it's operationalState is 'DISABLED' and it's usageState is 'NOT_IN_USE.

Note: I have fixed windows style line ending issue in vnf_packages.inc.
Also, updated 'Delete VNF Package' API doc to include 409 error.

Change-Id: Id4d50264d1052a09e6ce527b6aab1bb941fdc6af
Closes-Bug: #1862864
This commit is contained in:
tpatil 2020-02-12 02:45:20 +00:00
parent e82d982d7b
commit 33f92086f4
3 changed files with 286 additions and 248 deletions

View File

@ -1,243 +1,249 @@
.. -*- rst -*- .. -*- rst -*-
==================================================== ====================================================
Virtualized Network Function Packages (VNF packages) Virtualized Network Function Packages (VNF packages)
==================================================== ====================================================
Manages Virtualized Network Function Packages (VNF Packages) and their resources. Manages Virtualized Network Function Packages (VNF Packages) and their resources.
A VNF Package is a tar-archive containing all the information required for managing A VNF Package is a tar-archive containing all the information required for managing
the lifecycle of a VNF. the lifecycle of a VNF.
Create VNF Package Create VNF Package
================== ==================
.. rest_method:: POST /vnfpkgm/v1/vnf_packages .. rest_method:: POST /vnfpkgm/v1/vnf_packages
Creates a VNF Package. Creates a VNF Package.
Response Codes Response Codes
-------------- --------------
.. rest_status_code:: success status.yaml .. rest_status_code:: success status.yaml
- 201 - 201
.. rest_status_code:: error status.yaml .. rest_status_code:: error status.yaml
- 400 - 400
- 401 - 401
- 403 - 403
Request Parameters Request Parameters
------------------ ------------------
.. rest_parameters:: parameters.yaml .. rest_parameters:: parameters.yaml
- userDefinedData: userDefinedData - userDefinedData: userDefinedData
Request Example Request Example
--------------- ---------------
.. literalinclude:: samples/vnf_packages/vnf-packages-create-request.json .. literalinclude:: samples/vnf_packages/vnf-packages-create-request.json
:language: javascript :language: javascript
Response Parameters Response Parameters
------------------- -------------------
.. rest_parameters:: parameters.yaml .. rest_parameters:: parameters.yaml
- id: vnf_package_id - id: vnf_package_id
- _links: vnf_pkg_links - _links: vnf_pkg_links
- onboardingState: onboardingState - onboardingState: onboardingState
- operationalState: operationalState - operationalState: operationalState
- usageState: usageState - usageState: usageState
- userDefinedData: userDefinedData - userDefinedData: userDefinedData
Response Example Response Example
---------------- ----------------
.. literalinclude:: samples/vnf_packages/vnf-packages-create-response.json .. literalinclude:: samples/vnf_packages/vnf-packages-create-response.json
:language: javascript :language: javascript
List VNF Packages List VNF Packages
================= =================
.. rest_method:: GET /vnfpkgm/v1/vnf_packages .. rest_method:: GET /vnfpkgm/v1/vnf_packages
Lists VNF Packages. Lists VNF Packages.
Response Codes Response Codes
-------------- --------------
.. rest_status_code:: success status.yaml .. rest_status_code:: success status.yaml
- 200 - 200
.. rest_status_code:: error status.yaml .. rest_status_code:: error status.yaml
- 401 - 401
- 403 - 403
Response Parameters Response Parameters
------------------- -------------------
.. rest_parameters:: parameters.yaml .. rest_parameters:: parameters.yaml
- id: vnf_package_id - id: vnf_package_id
- vnfdId: vnf_pkg_vnfd_id - vnfdId: vnf_pkg_vnfd_id
- vnfProvider: vnf_provider - vnfProvider: vnf_provider
- vnfProductName: vnf_product_name - vnfProductName: vnf_product_name
- vnfSoftwareVersion: vnf_software_version - vnfSoftwareVersion: vnf_software_version
- vnfdVersion: vnfd_version - vnfdVersion: vnfd_version
- softwareImages: software_images - softwareImages: software_images
- onboardingState: onboardingState - onboardingState: onboardingState
- operationalState: operationalState - operationalState: operationalState
- usageState: usageState - usageState: usageState
- userDefinedData: userDefinedData - userDefinedData: userDefinedData
- _links: vnf_pkg_links - _links: vnf_pkg_links
Response Example Response Example
---------------- ----------------
.. literalinclude:: samples/vnf_packages/vnf-packages-list-response.json .. literalinclude:: samples/vnf_packages/vnf-packages-list-response.json
:language: javascript :language: javascript
Show VNF Package Show VNF Package
================= =================
.. rest_method:: GET /vnfpkgm/v1/vnf_packages/{vnf_package_id} .. rest_method:: GET /vnfpkgm/v1/vnf_packages/{vnf_package_id}
Shows information of a given VNF Package. Shows information of a given VNF Package.
Response Codes Response Codes
-------------- --------------
.. rest_status_code:: success status.yaml .. rest_status_code:: success status.yaml
- 200 - 200
.. rest_status_code:: error status.yaml .. rest_status_code:: error status.yaml
- 401 - 401
- 403 - 403
- 404 - 404
Request Parameters Request Parameters
------------------ ------------------
.. rest_parameters:: parameters.yaml .. rest_parameters:: parameters.yaml
- vnf_package_id: vnf_package_id_path - vnf_package_id: vnf_package_id_path
Response Parameters Response Parameters
------------------- -------------------
.. rest_parameters:: parameters.yaml .. rest_parameters:: parameters.yaml
- id: vnf_package_id - id: vnf_package_id
- vnfdId: vnf_pkg_vnfd_id - vnfdId: vnf_pkg_vnfd_id
- vnfProvider: vnf_provider - vnfProvider: vnf_provider
- vnfProductName: vnf_product_name - vnfProductName: vnf_product_name
- vnfSoftwareVersion: vnf_software_version - vnfSoftwareVersion: vnf_software_version
- vnfdVersion: vnfd_version - vnfdVersion: vnfd_version
- softwareImages: software_images - softwareImages: software_images
- onboardingState: onboardingState - onboardingState: onboardingState
- operationalState: operationalState - operationalState: operationalState
- usageState: usageState - usageState: usageState
- userDefinedData: userDefinedData - userDefinedData: userDefinedData
- _links: vnf_pkg_links - _links: vnf_pkg_links
Response Example Response Example
---------------- ----------------
.. literalinclude:: samples/vnf_packages/vnf-packages-show-response.json .. literalinclude:: samples/vnf_packages/vnf-packages-show-response.json
:language: javascript :language: javascript
Delete VNF Package Delete VNF Package
================== ==================
.. rest_method:: DELETE /vnfpkgm/v1/vnf_packages/{vnf_package_id} .. rest_method:: DELETE /vnfpkgm/v1/vnf_packages/{vnf_package_id}
Deletes a given VNF Package. Deletes a given VNF Package.
Response Codes **Preconditions**
--------------
The vnf package ``operationalState`` value must be ``DISABLED`` and it's
.. rest_status_code:: success status.yaml ``usageState`` value must be ``NOT_IN_USE``.
- 204 Response Codes
--------------
.. rest_status_code:: error status.yaml
.. rest_status_code:: success status.yaml
- 401
- 403 - 204
- 404
.. rest_status_code:: error status.yaml
Request Parameters
------------------ - 401
- 403
.. rest_parameters:: parameters.yaml - 404
- 409
- vnf_package_id: vnf_package_id_path
Request Parameters
Upload VNF Package from content ------------------
===============================
.. rest_parameters:: parameters.yaml
.. rest_method:: PUT /vnfpkgm/v1/vnf_packages/{vnf_package_id}/package_content
- vnf_package_id: vnf_package_id_path
Upload a given VNF Package from content.
Upload VNF Package from content
Response Codes ===============================
--------------
.. rest_method:: PUT /vnfpkgm/v1/vnf_packages/{vnf_package_id}/package_content
.. rest_status_code:: success status.yaml
Upload a given VNF Package from content.
- 202
Response Codes
.. rest_status_code:: error status.yaml --------------
- 401 .. rest_status_code:: success status.yaml
- 403
- 404 - 202
- 409
.. rest_status_code:: error status.yaml
Request Parameters
------------------ - 401
- 403
.. rest_parameters:: parameters.yaml - 404
- 409
- vnf_package_id: vnf_package_id_path
- vnf_package_content: vnf_pkg_content Request Parameters
------------------
Upload VNF Package from uri
=========================== .. rest_parameters:: parameters.yaml
.. rest_method:: POST /vnf_packages/{vnf_package_id}/package_content/upload_from_uri - vnf_package_id: vnf_package_id_path
- vnf_package_content: vnf_pkg_content
Upload a given VNF Package from content.
Upload VNF Package from uri
Response Codes ===========================
--------------
.. rest_method:: POST /vnf_packages/{vnf_package_id}/package_content/upload_from_uri
.. rest_status_code:: success status.yaml
Upload a given VNF Package from content.
- 202
Response Codes
.. rest_status_code:: error status.yaml --------------
- 401 .. rest_status_code:: success status.yaml
- 400
- 403 - 202
- 404
- 409 .. rest_status_code:: error status.yaml
Request Parameters - 401
------------------ - 400
- 403
.. rest_parameters:: parameters.yaml - 404
- 409
- vnf_package_id: vnf_package_id_path
- addressInformation: addressInformation Request Parameters
- userName: userName ------------------
- password: password
.. rest_parameters:: parameters.yaml
- vnf_package_id: vnf_package_id_path
- addressInformation: addressInformation
- userName: userName
- password: password

View File

@ -102,7 +102,8 @@ class VnfPkgmController(wsgi.Controller):
return self._view_builder.index(request, vnf_packages) return self._view_builder.index(request, vnf_packages)
@wsgi.response(http_client.NO_CONTENT) @wsgi.response(http_client.NO_CONTENT)
@wsgi.expected_errors((http_client.FORBIDDEN, http_client.NOT_FOUND)) @wsgi.expected_errors((http_client.FORBIDDEN, http_client.NOT_FOUND,
http_client.CONFLICT))
def delete(self, request, id): def delete(self, request, id):
context = request.environ['tacker.context'] context = request.environ['tacker.context']
context.can(vnf_package_policies.VNFPKGM % 'delete') context.can(vnf_package_policies.VNFPKGM % 'delete')
@ -119,13 +120,18 @@ class VnfPkgmController(wsgi.Controller):
msg = _("Can not find requested vnf package: %s") % id msg = _("Can not find requested vnf package: %s") % id
raise webob.exc.HTTPNotFound(explanation=msg) raise webob.exc.HTTPNotFound(explanation=msg)
if vnf_package.operational_state == \ if (vnf_package.operational_state ==
fields.PackageUsageStateType.IN_USE: fields.PackageOperationalStateType.ENABLED or
msg = _("VNF Package %(id)s usage state is %(state)s") vnf_package.usage_state ==
fields.PackageUsageStateType.IN_USE):
msg = _("VNF Package %(id)s cannot be deleted as it's "
"operational state is %(operational_state)s and usage "
"state is %(usage_state)s.")
raise webob.exc.HTTPConflict( raise webob.exc.HTTPConflict(
explanation=msg % { explanation=msg % {
"id": id, "id": id,
"state": fields.PackageOperationalStateType.ENABLED}) "operational_state": vnf_package.operational_state,
"usage_state": vnf_package.usage_state})
# Delete vnf_package # Delete vnf_package
self.rpc_api.delete_vnf_package(context, vnf_package) self.rpc_api.delete_vnf_package(context, vnf_package)

View File

@ -22,6 +22,8 @@ from webob import exc
from tacker.api.vnfpkgm.v1 import controller from tacker.api.vnfpkgm.v1 import controller
from tacker.conductor.conductorrpc.vnf_pkgm_rpc import VNFPackageRPCAPI from tacker.conductor.conductorrpc.vnf_pkgm_rpc import VNFPackageRPCAPI
from tacker.glance_store import store as glance_store from tacker.glance_store import store as glance_store
from tacker import objects
from tacker.objects import fields
from tacker.objects import vnf_package from tacker.objects import vnf_package
from tacker.objects.vnf_package import VnfPackagesList from tacker.objects.vnf_package import VnfPackagesList
from tacker.tests import constants from tacker.tests import constants
@ -121,6 +123,30 @@ class TestController(base.TestCase):
self.assertRaises(exc.HTTPNotFound, self.controller.delete, self.assertRaises(exc.HTTPNotFound, self.controller.delete,
req, constants.INVALID_UUID) req, constants.INVALID_UUID)
@mock.patch.object(objects.VnfPackage, "get_by_id")
def test_delete_with_operational_state_enabled(self, mock_vnf_by_id):
req = fake_request.HTTPRequest.blank(
'/vnfpkgm/v1/vnf_packages/%s' % constants.UUID)
vnf_package_dict = fakes.fake_vnf_package()
vnf_package_dict['operational_state'] = \
fields.PackageOperationalStateType.ENABLED
vnf_package = objects.VnfPackage(**vnf_package_dict)
mock_vnf_by_id.return_value = vnf_package
self.assertRaises(exc.HTTPConflict, self.controller.delete,
req, constants.UUID)
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
def test_delete_with_usage_state_in_use(self, mock_vnf_by_id):
req = fake_request.HTTPRequest.blank(
'/vnfpkgm/v1/vnf_packages/%s' % constants.UUID)
vnf_package_dict = fakes.fake_vnf_package()
vnf_package_dict['usage_state'] = \
fields.PackageUsageStateType.IN_USE
vnf_package = objects.VnfPackage(**vnf_package_dict)
mock_vnf_by_id.return_value = vnf_package
self.assertRaises(exc.HTTPConflict, self.controller.delete,
req, constants.UUID)
@mock.patch.object(glance_store, 'store_csar') @mock.patch.object(glance_store, 'store_csar')
@mock.patch.object(VNFPackageRPCAPI, "upload_vnf_package_content") @mock.patch.object(VNFPackageRPCAPI, "upload_vnf_package_content")
@mock.patch.object(vnf_package.VnfPackage, "get_by_id") @mock.patch.object(vnf_package.VnfPackage, "get_by_id")