Merge "Add instance action record for attach/detach interface"

This commit is contained in:
Zuul 2017-11-24 18:10:56 +00:00 committed by Gerrit Code Review
commit 0f523c8a52
7 changed files with 51 additions and 21 deletions

View File

@ -3734,6 +3734,8 @@ class API(base.Base):
def attach_interface(self, context, instance, network_id, port_id,
requested_ip, tag=None):
"""Use hotplug to add an network adapter to an instance."""
self._record_action_start(
context, instance, instance_actions.ATTACH_INTERFACE)
return self.compute_rpcapi.attach_interface(context,
instance=instance, network_id=network_id, port_id=port_id,
requested_ip=requested_ip, tag=tag)
@ -3744,6 +3746,8 @@ class API(base.Base):
task_state=[None])
def detach_interface(self, context, instance, port_id):
"""Detach an network adapter from an instance."""
self._record_action_start(
context, instance, instance_actions.DETACH_INTERFACE)
self.compute_rpcapi.detach_interface(context, instance=instance,
port_id=port_id)

View File

@ -60,3 +60,5 @@ TRIGGER_CRASH_DUMP = 'trigger_crash_dump'
# is used for tracking this asynchronous operation so the user/admin can know
# when it is done in case they need/want to reboot the guest operating system.
EXTEND_VOLUME = 'extend_volume'
ATTACH_INTERFACE = 'attach_interface'
DETACH_INTERFACE = 'detach_interface'

View File

@ -5498,6 +5498,7 @@ class ComputeManager(manager.Manager):
pass
@wrap_exception()
@wrap_instance_event(prefix='compute')
@wrap_instance_fault
def attach_interface(self, context, instance, network_id, port_id,
requested_ip, tag=None):
@ -5561,6 +5562,7 @@ class ComputeManager(manager.Manager):
return network_info[0]
@wrap_exception()
@wrap_instance_event(prefix='compute')
@wrap_instance_fault
def detach_interface(self, context, instance, port_id):
"""Detach a network adapter from an instance."""

View File

@ -9835,11 +9835,7 @@ class ComputeAPITestCase(BaseTestCase):
@mock.patch.object(compute_utils, 'notify_about_instance_action')
def test_attach_interface(self, mock_notify):
new_type = flavors.get_flavor_by_flavor_id('4')
instance = objects.Instance(image_ref=uuids.image_instance,
system_metadata={},
flavor=new_type,
host='fake-host')
instance = self._create_fake_instance_obj()
nwinfo = [fake_network_cache_model.new_vif()]
network_id = nwinfo[0]['network']['id']
port_id = nwinfo[0]['id']
@ -9857,7 +9853,7 @@ class ComputeAPITestCase(BaseTestCase):
self.assertEqual(vif['id'], network_id)
mock_allocate.assert_called_once_with(
self.context, instance, port_id, network_id, req_ip,
bind_host_id='fake-host', tag=None)
bind_host_id='fake-mini', tag=None)
mock_notify.assert_has_calls([
mock.call(self.context, instance, self.compute.host,
action='interface_attach', phase='start'),
@ -9867,11 +9863,7 @@ class ComputeAPITestCase(BaseTestCase):
@mock.patch.object(compute_utils, 'notify_about_instance_action')
def test_interface_tagged_attach(self, mock_notify):
new_type = flavors.get_flavor_by_flavor_id('4')
instance = objects.Instance(image_ref=uuids.image_instance,
system_metadata={},
flavor=new_type,
host='fake-host')
instance = self._create_fake_instance_obj()
nwinfo = [fake_network_cache_model.new_vif()]
network_id = nwinfo[0]['network']['id']
port_id = nwinfo[0]['id']
@ -9890,7 +9882,7 @@ class ComputeAPITestCase(BaseTestCase):
self.assertEqual(vif['id'], network_id)
mock_allocate.assert_called_once_with(
self.context, instance, port_id, network_id, req_ip,
bind_host_id='fake-host', tag='foo')
bind_host_id='fake-mini', tag='foo')
mock_notify.assert_has_calls([
mock.call(self.context, instance, self.compute.host,
action='interface_attach', phase='start'),
@ -9959,7 +9951,7 @@ class ComputeAPITestCase(BaseTestCase):
self.stub_out('nova.network.api.API.'
'deallocate_port_for_instance',
lambda a, b, c, d: [])
instance = objects.Instance()
instance = self._create_fake_instance_obj()
instance.info_cache = objects.InstanceInfoCache.new(
self.context, uuids.info_cache_instance)
instance.info_cache.network_info = network_model.NetworkInfo.hydrate(
@ -9974,7 +9966,7 @@ class ComputeAPITestCase(BaseTestCase):
def test_detach_interface_failed(self):
nwinfo, port_id = self.test_attach_interface()
instance = objects.Instance(id=42)
instance = self._create_fake_instance_obj()
instance['uuid'] = uuids.info_cache_instance
instance.info_cache = objects.InstanceInfoCache.new(
self.context, uuids.info_cache_instance)
@ -10002,7 +9994,7 @@ class ComputeAPITestCase(BaseTestCase):
# Tests that when deallocate_port_for_instance fails we log the failure
# before exiting compute.detach_interface.
nwinfo, port_id = self.test_attach_interface()
instance = objects.Instance(id=42, uuid=uuids.fake)
instance = self._create_fake_instance_obj()
instance.info_cache = objects.InstanceInfoCache.new(
self.context, uuids.info_cache_instance)
instance.info_cache.network_info = network_model.NetworkInfo.hydrate(

View File

@ -5072,14 +5072,27 @@ class ComputeAPIUnitTestCase(_ComputeAPIUnitTestMixIn, test.NoDBTestCase):
self.assertItemsEqual(['default', uuids.secgroup_uuid],
security_groups)
@mock.patch('nova.compute.api.API._record_action_start')
@mock.patch.object(compute_rpcapi.ComputeAPI, 'attach_interface')
def test_tagged_interface_attach(self, mock_attach):
def test_tagged_interface_attach(self, mock_attach, mock_record):
instance = self._create_instance_obj()
self.compute_api.attach_interface(self.context, instance, None, None,
None, tag='foo')
mock_attach.assert_called_with(self.context, instance=instance,
network_id=None, port_id=None,
requested_ip=None, tag='foo')
mock_record.assert_called_once_with(
self.context, instance, instance_actions.ATTACH_INTERFACE)
@mock.patch('nova.compute.api.API._record_action_start')
@mock.patch.object(compute_rpcapi.ComputeAPI, 'detach_interface')
def test_detach_interface(self, mock_detach, mock_record):
instance = self._create_instance_obj()
self.compute_api.detach_interface(self.context, instance, None)
mock_detach.assert_called_with(self.context, instance=instance,
port_id=None)
mock_record.assert_called_once_with(
self.context, instance, instance_actions.DETACH_INTERFACE)
class Cellsv1DeprecatedTestMixIn(object):

View File

@ -1783,6 +1783,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
db_instance)
e = exception.InterfaceAttachFailed(instance_uuid=f_instance.uuid)
@mock.patch.object(compute_utils, 'EventReporter')
@mock.patch.object(compute_utils, 'notify_about_instance_action')
@mock.patch.object(compute_utils, 'add_instance_fault_from_exc')
@mock.patch.object(self.compute.network_api,
@ -1790,7 +1791,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
side_effect=e)
@mock.patch.object(self.compute, '_instance_update',
side_effect=lambda *a, **k: {})
def do_test(update, meth, add_fault, notify):
def do_test(update, meth, add_fault, notify, event):
self.assertRaises(exception.InterfaceAttachFailed,
self.compute.attach_interface,
self.context, f_instance, 'net_id', 'port_id',
@ -1798,6 +1799,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
add_fault.assert_has_calls([
mock.call(self.context, f_instance, e,
mock.ANY)])
event.assert_called_once_with(
self.context, 'compute_attach_interface',
f_instance.uuid)
with mock.patch.dict(self.compute.driver.capabilities,
supports_attach_interface=True):
@ -1807,18 +1811,24 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
# Test that the fault methods are invoked when a detach fails
# Build test data that will cause a PortNotFound exception
f_instance = mock.MagicMock()
f_instance.info_cache = mock.MagicMock()
f_instance.info_cache.network_info = []
nw_info = network_model.NetworkInfo([])
info_cache = objects.InstanceInfoCache(network_info=nw_info,
instance_uuid=uuids.instance)
f_instance = objects.Instance(id=3, uuid=uuids.instance,
info_cache=info_cache)
@mock.patch.object(compute_utils, 'EventReporter')
@mock.patch.object(compute_utils, 'add_instance_fault_from_exc')
@mock.patch.object(self.compute, '_set_instance_obj_error_state')
def do_test(meth, add_fault):
def do_test(meth, add_fault, event):
self.assertRaises(exception.PortNotFound,
self.compute.detach_interface,
self.context, f_instance, 'port_id')
add_fault.assert_has_calls(
[mock.call(self.context, f_instance, mock.ANY, mock.ANY)])
event.assert_called_once_with(
self.context, 'compute_detach_interface',
f_instance.uuid)
do_test()

View File

@ -0,0 +1,7 @@
---
features:
- |
The following instance action records have been added:
* attach_interface
* detach_interface