NSX|V prevent deleting md proxy neutron objects
It is not allowed to delete metadata network / subnet / port or router. Change-Id: I7d99c9c1f51ffa076bda63ec3e59aea2a977f2d6
This commit is contained in:
parent
a48f364cff
commit
75bf6bdef0
@ -412,6 +412,12 @@ def get_nsxv_internal_networks(session, network_purpose):
|
||||
filter_by(network_purpose=network_purpose).all())
|
||||
|
||||
|
||||
def get_nsxv_internal_network_by_id(session, network_id):
|
||||
with session.begin(subtransactions=True):
|
||||
return (session.query(nsxv_models.NsxvInternalNetworks).
|
||||
filter_by(network_id=network_id).first())
|
||||
|
||||
|
||||
def delete_nsxv_internal_network(session, network_purpose, network_id):
|
||||
with session.begin(subtransactions=True):
|
||||
return (session.query(nsxv_models.NsxvInternalNetworks).
|
||||
@ -453,6 +459,12 @@ def get_nsxv_internal_edges_by_purpose(session, purpose):
|
||||
filter_by(purpose=purpose).all())
|
||||
|
||||
|
||||
def get_nsxv_internal_edge_by_router(session, router_id):
|
||||
with session.begin(subtransactions=True):
|
||||
return (session.query(nsxv_models.NsxvInternalEdges).
|
||||
filter_by(router_id=router_id).first())
|
||||
|
||||
|
||||
def delete_nsxv_internal_edge(session, ext_ip_address):
|
||||
with session.begin(subtransactions=True):
|
||||
return (session.query(nsxv_models.NsxvInternalEdges).
|
||||
|
@ -524,7 +524,8 @@ class NsxVMetadataProxyHandler(object):
|
||||
for port in ports:
|
||||
self.nsxv_plugin.delete_port(context, port['id'],
|
||||
l3_port_check=True,
|
||||
nw_gw_port_check=True)
|
||||
nw_gw_port_check=True,
|
||||
allow_delete_internal=True)
|
||||
|
||||
nsxv_db.delete_nsxv_internal_edge(
|
||||
context.session,
|
||||
|
@ -1394,6 +1394,13 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
return True
|
||||
return False
|
||||
|
||||
def _validate_internal_network(self, context, network_id):
|
||||
if nsxv_db.get_nsxv_internal_network_by_id(
|
||||
context.elevated().session, network_id):
|
||||
msg = (_("Cannot delete internal network %s or its subnets and "
|
||||
"ports") % network_id)
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
|
||||
def delete_network(self, context, id):
|
||||
mappings = nsx_db.get_nsx_network_mappings(context.session, id)
|
||||
bindings = nsxv_db.get_network_bindings(context.session, id)
|
||||
@ -1401,6 +1408,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
sg_policy_id = nsxv_db.get_spoofguard_policy_id(
|
||||
context.session, id)
|
||||
|
||||
self._validate_internal_network(context, id)
|
||||
|
||||
# Update the DHCP edge for metadata and clean the vnic in DHCP edge
|
||||
# if there is only no other existing port besides DHCP port
|
||||
filters = {'network_id': [id]}
|
||||
@ -2336,10 +2345,15 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
return db_utils.resource_fields(port, fields)
|
||||
|
||||
def delete_port(self, context, id, l3_port_check=True,
|
||||
nw_gw_port_check=True, force_delete_dhcp=False):
|
||||
nw_gw_port_check=True, force_delete_dhcp=False,
|
||||
allow_delete_internal=False):
|
||||
neutron_db_port = self.get_port(context, id)
|
||||
device_id = neutron_db_port['device_id']
|
||||
is_compute_port = self._is_compute_port(neutron_db_port)
|
||||
if not allow_delete_internal:
|
||||
self._validate_internal_network(
|
||||
context, neutron_db_port['network_id'])
|
||||
|
||||
if is_compute_port and device_id:
|
||||
# Lock on the device ID to make sure we do not change/delete
|
||||
# ports of the same device at the same time
|
||||
@ -2374,6 +2388,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
neutron_db_port['device_owner'] in [constants.DEVICE_OWNER_DHCP]):
|
||||
msg = (_('Can not delete DHCP port %s') % neutron_db_port['id'])
|
||||
raise n_exc.BadRequest(resource='port', msg=msg)
|
||||
|
||||
# If this port is attached to a device, remove the corresponding vnic
|
||||
# from all NSXv Security-Groups and the spoofguard policy
|
||||
port_index = neutron_db_port.get(ext_vnic_idx.VNIC_INDEX)
|
||||
@ -2431,6 +2446,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
# deleting subnet's corresponding dhcp interface rest call and lead to
|
||||
# overlap response from backend.
|
||||
network_id = subnet['network_id']
|
||||
self._validate_internal_network(context, network_id)
|
||||
|
||||
with locking.LockManager.get_lock(network_id):
|
||||
with db_api.context_manager.writer.using(context):
|
||||
self.base_delete_subnet(context, id)
|
||||
@ -3204,6 +3221,11 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
if ports:
|
||||
raise l3_exc.RouterInUse(router_id=router_id)
|
||||
|
||||
if nsxv_db.get_nsxv_internal_edge_by_router(
|
||||
context.elevated().session, router_id):
|
||||
msg = _("Cannot delete internal router %s") % router_id
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
|
||||
def delete_router(self, context, id):
|
||||
self._check_router_in_use(context, id)
|
||||
router_driver = self._find_router_driver(context, id)
|
||||
|
@ -17,8 +17,12 @@ import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron_lib import context
|
||||
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.db import nsxv_models
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import (
|
||||
constants as vcns_const)
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
|
||||
@ -53,6 +57,12 @@ class NsxVPluginWithMdV2TestCase(test_plugin.NsxVPluginV2TestCase):
|
||||
plugin=plugin, ext_mgr=ext_mgr,
|
||||
service_plugins=service_plugins)
|
||||
|
||||
self.context = context.get_admin_context()
|
||||
self.internal_net_id = nsxv_db.get_nsxv_internal_network_for_az(
|
||||
self.context.session,
|
||||
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE,
|
||||
'default')['network_id']
|
||||
|
||||
|
||||
class TestNetworksWithMdV2(test_plugin.TestNetworksV2,
|
||||
NsxVPluginWithMdV2TestCase):
|
||||
@ -107,6 +117,11 @@ class TestNetworksWithMdV2(test_plugin.TestNetworksV2,
|
||||
def test_create_networks_bulk_emulated_plugin_failure(self):
|
||||
self.skipTest("The test is not suitable for the metadata test case")
|
||||
|
||||
def test_cannot_delete_md_net(self):
|
||||
req = self.new_delete_request('networks', self.internal_net_id)
|
||||
net_del_res = req.get_response(self.api)
|
||||
self.assertEqual(net_del_res.status_int, 400)
|
||||
|
||||
|
||||
class TestSubnetsWithMdV2(test_plugin.TestSubnetsV2,
|
||||
NsxVPluginWithMdV2TestCase):
|
||||
@ -145,6 +160,16 @@ class TestSubnetsWithMdV2(test_plugin.TestSubnetsV2,
|
||||
def test_create_subnets_bulk_emulated_plugin_failure(self):
|
||||
self.skipTest("The test is not suitable for the metadata test case")
|
||||
|
||||
def test_cannot_delete_md_subnet(self):
|
||||
query_params = "network_id=%s" % self.internal_net_id
|
||||
res = self._list('subnets',
|
||||
neutron_context=self.context,
|
||||
query_params=query_params)
|
||||
internal_sub = res['subnets'][0]['id']
|
||||
req = self.new_delete_request('subnets', internal_sub)
|
||||
net_del_res = req.get_response(self.api)
|
||||
self.assertEqual(net_del_res.status_int, 400)
|
||||
|
||||
|
||||
class TestExclusiveRouterWithMdTestCase(
|
||||
test_plugin.TestExclusiveRouterTestCase,
|
||||
|
Loading…
Reference in New Issue
Block a user