attach/detach interface should raise exception when instance is locked

when instance is locked, exception should be raised if attach and
detach an interface operation is performed. This patch add instance
lock check for the 2 APIs, catch and process the exception at API layer.

Change-Id: I6c0b05dafb9d480c8f0002bcc8306cb65a32aaf7
Closes-Bug: #1275741
This commit is contained in:
jichenjc 2014-01-26 21:37:25 +08:00
parent 4ed6043144
commit 9583b35b42
5 changed files with 90 additions and 0 deletions

View File

@ -112,6 +112,8 @@ class InterfaceAttachmentController(object):
except exception.NotFound as e:
LOG.exception(e)
raise exc.HTTPNotFound()
except exception.InstanceIsLocked as e:
raise exc.HTTPConflict(explanation=e.format_message())
except NotImplementedError:
msg = _("Network driver does not support this function.")
raise webob.exc.HTTPNotImplemented(explanation=msg)
@ -144,6 +146,8 @@ class InterfaceAttachmentController(object):
instance, port_id=port_id)
except exception.PortNotFound:
raise exc.HTTPNotFound()
except exception.InstanceIsLocked as e:
raise exc.HTTPConflict(explanation=e.format_message())
except NotImplementedError:
msg = _("Network driver does not support this function.")
raise webob.exc.HTTPNotImplemented(explanation=msg)

View File

@ -111,6 +111,8 @@ class InterfaceAttachmentController(object):
exception.NetworkAmbiguous,
exception.NetworkNotFound) as e:
raise exc.HTTPBadRequest(explanation=e.format_message())
except exception.InstanceIsLocked as e:
raise exc.HTTPConflict(explanation=e.format_message())
except NotImplementedError as e:
raise webob.exc.HTTPNotImplemented(explanation=e.format_message())
except exception.InterfaceAttachFailed as e:
@ -138,6 +140,8 @@ class InterfaceAttachmentController(object):
instance, port_id=port_id)
except exception.PortNotFound:
raise exc.HTTPNotFound()
except exception.InstanceIsLocked as e:
raise exc.HTTPConflict(explanation=e.format_message())
except NotImplementedError as e:
raise webob.exc.HTTPNotImplemented(explanation=e.format_message())

View File

@ -2805,6 +2805,7 @@ class API(base.Base):
self.volume_api.unreserve_volume(context, new_volume['id'])
@wrap_check_policy
@check_instance_lock
def attach_interface(self, context, instance, network_id, port_id,
requested_ip):
"""Use hotplug to add an network adapter to an instance."""
@ -2813,6 +2814,7 @@ class API(base.Base):
requested_ip=requested_ip)
@wrap_check_policy
@check_instance_lock
def detach_interface(self, context, instance, port_id):
"""Detach an network adapter from an instance."""
self.compute_rpcapi.detach_interface(context, instance=instance,

View File

@ -170,6 +170,27 @@ class InterfaceAttachTests(test.NoDBTestCase):
result = attachments.delete(req, FAKE_UUID1, FAKE_PORT_ID1)
self.assertEqual('202 Accepted', result.status)
def test_detach_interface_instance_locked(self):
def fake_detach_interface_from_locked_server(self, context,
instance, port_id):
raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1)
self.stubs.Set(compute_api.API,
'detach_interface',
fake_detach_interface_from_locked_server)
attachments = attach_interfaces.InterfaceAttachmentController()
req = webob.Request.blank('/v2/fake/os-interfaces/delete')
req.method = 'POST'
req.body = jsonutils.dumps({})
req.headers['content-type'] = 'application/json'
req.environ['nova.context'] = self.context
self.assertRaises(exc.HTTPConflict,
attachments.delete,
req,
FAKE_UUID1,
FAKE_PORT_ID1)
def test_delete_interface_not_found(self):
self.stubs.Set(compute_api.API, 'detach_interface',
fake_detach_interface)
@ -186,6 +207,24 @@ class InterfaceAttachTests(test.NoDBTestCase):
FAKE_UUID1,
'invaid-port-id')
def test_attach_interface_instance_locked(self):
def fake_attach_interface_to_locked_server(self, context,
instance, network_id, port_id, requested_ip):
raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1)
self.stubs.Set(compute_api.API,
'attach_interface',
fake_attach_interface_to_locked_server)
attachments = attach_interfaces.InterfaceAttachmentController()
req = webob.Request.blank('/v2/fake/os-interfaces/attach')
req.method = 'POST'
req.body = jsonutils.dumps({})
req.headers['content-type'] = 'application/json'
req.environ['nova.context'] = self.context
self.assertRaises(exc.HTTPConflict,
attachments.create, req, FAKE_UUID1,
jsonutils.loads(req.body))
def test_attach_interface_without_network_id(self):
self.stubs.Set(compute_api.API, 'attach_interface',
fake_attach_interface)

View File

@ -203,6 +203,28 @@ class InterfaceAttachTests(test.NoDBTestCase):
result = attachments.delete(req, FAKE_UUID1, FAKE_PORT_ID1)
self.assertEqual('202 Accepted', result.status)
def test_detach_interface_instance_locked(self):
def fake_detach_interface_from_locked_server(self, context,
instance, port_id):
raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1)
self.stubs.Set(compute_api.API,
'detach_interface',
fake_detach_interface_from_locked_server)
attachments = attach_interfaces.InterfaceAttachmentController()
req = webob.Request.blank(
'/v3/servers/fake/os-attach-interfaces/delete')
req.method = 'POST'
req.body = jsonutils.dumps({})
req.headers['content-type'] = 'application/json'
req.environ['nova.context'] = self.context
self.assertRaises(exc.HTTPConflict,
attachments.delete,
req,
FAKE_UUID1,
FAKE_PORT_ID1)
def test_delete_interface_not_found(self):
self.stubs.Set(compute_api.API, 'detach_interface',
fake_detach_interface)
@ -242,6 +264,25 @@ class InterfaceAttachTests(test.NoDBTestCase):
'fake',
'invaid-port-id')
def test_attach_interface_instance_locked(self):
def fake_attach_interface_to_locked_server(self, context,
instance, network_id, port_id, requested_ip):
raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1)
self.stubs.Set(compute_api.API,
'attach_interface',
fake_attach_interface_to_locked_server)
attachments = attach_interfaces.InterfaceAttachmentController()
req = webob.Request.blank(
'/v3/servers/fake/os-attach-interfaces/attach')
req.method = 'POST'
req.body = jsonutils.dumps({})
req.headers['content-type'] = 'application/json'
req.environ['nova.context'] = self.context
self.assertRaises(exc.HTTPConflict,
attachments.create, req, FAKE_UUID1,
jsonutils.loads(req.body))
def test_attach_interface_without_network_id(self):
self.stubs.Set(compute_api.API, 'attach_interface',
fake_attach_interface)