Restrict VNF deletion, if part of Active NS

VNF should not be allowed to delete separately,
if part of an active NS.

Change-Id: I3421a311c7a8dcc6c9c4eec2265c6384370c0972
Closes-Bug: #1691363
This commit is contained in:
dharmendra kushwaha 2018-01-09 07:51:55 +00:00 committed by gongysh
parent 06f8504eee
commit 6333914336
5 changed files with 75 additions and 2 deletions

View File

@ -0,0 +1,4 @@
---
fixes:
- |
VNF not be allowed to delete separately, if part of an active NS.

View File

@ -325,7 +325,7 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
return ns_dict
# reference implementation. needs to be overrided by subclass
def delete_ns(self, context, ns_id):
def delete_ns_pre(self, context, ns_id):
with context.session.begin(subtransactions=True):
ns_db = self._get_ns_db(
context, ns_id, _ACTIVE_UPDATE_ERROR_DEAD,

View File

@ -33,6 +33,7 @@ from tacker.db.common_services import common_services_db_plugin
from tacker.db import db_base
from tacker.db import model_base
from tacker.db import models_v1
from tacker.db.nfvo import ns_db
from tacker.db import types
from tacker.extensions import vnfm
from tacker import manager
@ -547,6 +548,13 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
def _delete_vnf_pre(self, context, vnf_id):
with context.session.begin(subtransactions=True):
nss_db = context.session.query(ns_db.NS).filter(
ns_db.NS.vnf_ids.like("%" + vnf_id + "%")).first()
if (nss_db is not None and nss_db.status not in
[constants.PENDING_DELETE, constants.ERROR]):
raise vnfm.VNFInUse(vnf_id=vnf_id)
vnf_db = self._get_vnf_db(
context, vnf_id, _ACTIVE_UPDATE_ERROR_DEAD,
constants.PENDING_DELETE)

View File

@ -805,6 +805,7 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
def delete_ns(self, context, ns_id):
ns = super(NfvoPlugin, self).get_ns(context, ns_id)
vim_res = self.vim_client.get_vim(context, ns['vim_id'])
super(NfvoPlugin, self).delete_ns_pre(context, ns_id)
driver_type = vim_res['vim_type']
workflow = None
try:
@ -835,7 +836,6 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
auth_dict=self.get_auth_dict(context))
raise ex
super(NfvoPlugin, self).delete_ns(context, ns_id)
def _delete_ns_wait(ns_id, execution_id):
exec_state = "RUNNING"

View File

@ -23,6 +23,7 @@ import yaml
from tacker import context
from tacker.db.common_services import common_services_db_plugin
from tacker.db.nfvo import nfvo_db
from tacker.db.nfvo import ns_db
from tacker.db.vnfm import vnfm_db
from tacker.extensions import vnfm
from tacker.plugins.common import constants
@ -344,6 +345,66 @@ class TestVNFMPlugin(db_base.SqlTestCase):
res_state=mock.ANY, res_type=constants.RES_TYPE_VNF,
tstamp=mock.ANY, details=mock.ANY)
def _insert_dummy_ns_template(self):
session = self.context.session
attributes = {
u'nsd': 'imports: [VNF1, VNF2]\ntopology_template:\n inputs:\n '
' vl1_name: {default: net_mgmt, description: name of VL1'
' virtuallink, type: string}\n vl2_name: {default: '
'net0, description: name of VL2 virtuallink, type: string'
'}\n node_templates:\n VL1:\n properties:\n '
' network_name: {get_input: vl1_name}\n vendor: '
'tacker\n type: tosca.nodes.nfv.VL\n VL2:\n '
'properties:\n network_name: {get_input: vl2_name}'
'\n vendor: tacker\n type: tosca.nodes.nfv.VL'
'\n VNF1:\n requirements:\n - {virtualLink1: '
'VL1}\n - {virtualLink2: VL2}\n type: tosca.node'
's.nfv.VNF1\n VNF2: {type: tosca.nodes.nfv.VNF2}\ntosca'
'_definitions_version: tosca_simple_profile_for_nfv_1_0_0'
'\n'}
nsd_template = ns_db.NSD(
id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
name='fake_template',
vnfds={'tosca.nodes.nfv.VNF1': 'vnf1',
'tosca.nodes.nfv.VNF2': 'vnf2'},
description='fake_nsd_template_description',
deleted_at=datetime.min,
template_source='onboarded')
session.add(nsd_template)
for (key, value) in attributes.items():
attribute_db = ns_db.NSDAttribute(
id=uuidutils.generate_uuid(),
nsd_id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
key=key,
value=value)
session.add(attribute_db)
session.flush()
return nsd_template
def _insert_dummy_ns(self):
session = self.context.session
ns = ns_db.NS(
id='ba6bf017-f6f7-45f1-a280-57b073bf78ea',
name='dummy_ns',
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
status='ACTIVE',
nsd_id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
vim_id='6261579e-d6f3-49ad-8bc3-a9cb974778ff',
description='dummy_ns_description',
vnf_ids='[5761579e-d6f3-49ad-8bc3-a9cb73477846,'
'6261579e-d6f3-49ad-8bc3-a9cb974778fe]',
deleted_at=datetime.min)
session.add(ns)
session.flush()
return ns
def test_delete_vnf_of_active_ns(self):
self._insert_dummy_ns_template()
self._insert_dummy_ns()
self.assertRaises(vnfm.VNFInUse, self.vnfm_plugin.delete_vnf,
self.context, '6261579e-d6f3-49ad-8bc3-a9cb974778fe')
def test_update_vnf(self):
self._insert_dummy_device_template()
dummy_device_obj = self._insert_dummy_device()