Allow deleting unbound ports on active node
Change-Id: I2b8017d5b71bd289fd76274fa96aa6b64c03ce24 Story: 2006385
This commit is contained in:
parent
e038bb8ebd
commit
f759572688
@ -2335,13 +2335,16 @@ class ConductorManager(base_manager.BaseConductorManager):
|
|||||||
with task_manager.acquire(context, port.node_id,
|
with task_manager.acquire(context, port.node_id,
|
||||||
purpose='port deletion') as task:
|
purpose='port deletion') as task:
|
||||||
node = task.node
|
node = task.node
|
||||||
|
vif = task.driver.network.get_current_vif(task, port)
|
||||||
if ((node.provision_state == states.ACTIVE or node.instance_uuid)
|
if ((node.provision_state == states.ACTIVE or node.instance_uuid)
|
||||||
and not node.maintenance):
|
and not node.maintenance and vif):
|
||||||
msg = _("Cannot delete the port %(port)s as node "
|
msg = _("Cannot delete the port %(port)s as node "
|
||||||
"%(node)s is active or has "
|
"%(node)s is active or has "
|
||||||
"instance UUID assigned")
|
"instance UUID assigned or port is bound "
|
||||||
|
"to vif %(vif)s")
|
||||||
raise exception.InvalidState(msg % {'node': node.uuid,
|
raise exception.InvalidState(msg % {'node': node.uuid,
|
||||||
'port': port.uuid})
|
'port': port.uuid,
|
||||||
|
'vif': vif})
|
||||||
port.destroy()
|
port.destroy()
|
||||||
LOG.info('Successfully deleted port %(port)s. '
|
LOG.info('Successfully deleted port %(port)s. '
|
||||||
'The node associated with the port was %(node)s',
|
'The node associated with the port was %(node)s',
|
||||||
|
@ -8150,9 +8150,10 @@ class DestroyPortTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
|||||||
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
|
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
|
||||||
instance_uuid=instance_uuid,
|
instance_uuid=instance_uuid,
|
||||||
provision_state='active')
|
provision_state='active')
|
||||||
port = obj_utils.create_test_port(self.context,
|
port = obj_utils.create_test_port(
|
||||||
|
self.context,
|
||||||
node_id=node.id,
|
node_id=node.id,
|
||||||
extra={'vif_port_id': 'fake-id'})
|
internal_info={'tenant_vif_port_id': 'foo'})
|
||||||
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
||||||
self.service.destroy_port,
|
self.service.destroy_port,
|
||||||
self.context, port)
|
self.context, port)
|
||||||
@ -8172,18 +8173,44 @@ class DestroyPortTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
|||||||
self.dbapi.get_port_by_uuid,
|
self.dbapi.get_port_by_uuid,
|
||||||
port.uuid)
|
port.uuid)
|
||||||
|
|
||||||
def test_destroy_port_with_instance_not_in_active(self):
|
def test_destroy_port_with_instance_not_in_active_port_unbound(self):
|
||||||
instance_uuid = uuidutils.generate_uuid()
|
instance_uuid = uuidutils.generate_uuid()
|
||||||
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
|
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
|
||||||
instance_uuid=instance_uuid,
|
instance_uuid=instance_uuid,
|
||||||
provision_state='deploy failed')
|
provision_state='deploy failed')
|
||||||
port = obj_utils.create_test_port(self.context,
|
port = obj_utils.create_test_port(self.context,
|
||||||
node_id=node.id)
|
node_id=node.id)
|
||||||
|
self.service.destroy_port(self.context, port)
|
||||||
|
self.assertRaises(exception.PortNotFound,
|
||||||
|
self.dbapi.get_port_by_uuid,
|
||||||
|
port.uuid)
|
||||||
|
|
||||||
|
def test_destroy_port_with_instance_not_in_active_port_bound(self):
|
||||||
|
instance_uuid = uuidutils.generate_uuid()
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
|
||||||
|
instance_uuid=instance_uuid,
|
||||||
|
provision_state='deploy failed')
|
||||||
|
port = obj_utils.create_test_port(
|
||||||
|
self.context,
|
||||||
|
node_id=node.id,
|
||||||
|
internal_info={'tenant_vif_port_id': 'foo'})
|
||||||
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
exc = self.assertRaises(messaging.rpc.ExpectedException,
|
||||||
self.service.destroy_port,
|
self.service.destroy_port,
|
||||||
self.context, port)
|
self.context, port)
|
||||||
self.assertEqual(exception.InvalidState, exc.exc_info[0])
|
self.assertEqual(exception.InvalidState, exc.exc_info[0])
|
||||||
|
|
||||||
|
def test_destroy_port_node_active_port_unbound(self):
|
||||||
|
instance_uuid = uuidutils.generate_uuid()
|
||||||
|
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
|
||||||
|
instance_uuid=instance_uuid,
|
||||||
|
provision_state='active')
|
||||||
|
port = obj_utils.create_test_port(self.context,
|
||||||
|
node_id=node.id)
|
||||||
|
self.service.destroy_port(self.context, port)
|
||||||
|
self.assertRaises(exception.PortNotFound,
|
||||||
|
self.dbapi.get_port_by_uuid,
|
||||||
|
port.uuid)
|
||||||
|
|
||||||
|
|
||||||
@mgr_utils.mock_record_keepalive
|
@mgr_utils.mock_record_keepalive
|
||||||
class DestroyPortgroupTestCase(mgr_utils.ServiceSetUpMixin,
|
class DestroyPortgroupTestCase(mgr_utils.ServiceSetUpMixin,
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Allows deleting unbound ports on an active node. See
|
||||||
|
https://storyboard.openstack.org/#!/story/2006385 for details.
|
Loading…
Reference in New Issue
Block a user