summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/compute/api.py31
-rw-r--r--nova/compute/manager.py20
-rw-r--r--nova/compute/rpcapi.py12
-rw-r--r--nova/tests/compute/test_compute.py57
-rw-r--r--nova/tests/compute/test_rpcapi.py7
5 files changed, 113 insertions, 14 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index e98f8a654..29f52c4e5 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -1358,6 +1358,27 @@ class API(base.Base):
return min_ram, min_disk
+ def _get_block_device_info(self, context, instance_uuid):
+ bdms = self.db.block_device_mapping_get_all_by_instance(context,
+ instance_uuid)
+ block_device_mapping = []
+ for bdm in bdms:
+ if not bdm['volume_id']:
+ continue
+ try:
+ cinfo = jsonutils.loads(bdm['connection_info'])
+ if cinfo and 'serial' not in cinfo:
+ cinfo['serial'] = bdm['volume_id']
+ bdmap = {'connection_info': cinfo,
+ 'mount_device': bdm['volume_id'],
+ 'delete_on_termination': bdm['delete_on_termination']}
+ block_device_mapping.append(bdmap)
+ except TypeError:
+ # if the block_device_mapping has no value in connection_info
+ # (returned as None), don't include in the mapping
+ pass
+ return {'block_device_mapping': block_device_mapping}
+
@wrap_check_policy
@check_instance_lock
@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED,
@@ -1377,8 +1398,16 @@ class API(base.Base):
task_state=state,
expected_task_state=[None,
task_states.REBOOTING])
+ elevated = context.elevated()
+ block_info = self._get_block_device_info(elevated,
+ instance['uuid'])
+ network_info = self.network_api.get_instance_nw_info(elevated,
+ instance)
+
self.compute_rpcapi.reboot_instance(context, instance=instance,
- reboot_type=reboot_type)
+ block_device_info=block_info,
+ network_info=network_info,
+ reboot_type=reboot_type)
def _get_image(self, context, image_href):
"""Throws an ImageNotFound exception if image_href does not exist."""
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 46760e772..8057ae4e1 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -210,7 +210,7 @@ def _get_image_meta(context, image_ref):
class ComputeManager(manager.SchedulerDependentManager):
"""Manages the running instances from creation to destruction."""
- RPC_API_VERSION = '2.4'
+ RPC_API_VERSION = '2.5'
def __init__(self, compute_driver=None, *args, **kwargs):
"""Load configuration options and connect to the hypervisor."""
@@ -1093,11 +1093,22 @@ class ComputeManager(manager.SchedulerDependentManager):
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@reverts_task_state
@wrap_instance_fault
- def reboot_instance(self, context, instance, reboot_type="SOFT"):
+ def reboot_instance(self, context, instance,
+ block_device_info=None,
+ network_info=None,
+ reboot_type="SOFT"):
"""Reboot an instance on this host."""
context = context.elevated()
LOG.audit(_("Rebooting instance"), context=context, instance=instance)
+ # NOTE(danms): remove these when RPC API < 2.5 compatibility
+ # is no longer needed
+ if block_device_info is None:
+ block_device_info = self._get_instance_volume_block_device_info(
+ context, instance['uuid'])
+ if network_info is None:
+ network_info = self._get_instance_nw_info(context, instance)
+
self._notify_about_instance_usage(context, instance, "reboot.start")
current_power_state = self._get_power_state(context, instance)
@@ -1113,11 +1124,6 @@ class ComputeManager(manager.SchedulerDependentManager):
'expected: %(running)s)') % locals(),
context=context, instance=instance)
- network_info = self._get_instance_nw_info(context, instance)
-
- block_device_info = self._get_instance_volume_block_device_info(
- context, instance['uuid'])
-
try:
self.driver.reboot(instance, self._legacy_nw_info(network_info),
reboot_type, block_device_info)
diff --git a/nova/compute/rpcapi.py b/nova/compute/rpcapi.py
index e0c4bae3b..6a47bb096 100644
--- a/nova/compute/rpcapi.py
+++ b/nova/compute/rpcapi.py
@@ -132,6 +132,7 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy):
remove_aggregate_host()
2.3 - Adds volume_id to reserve_block_device_name()
2.4 - Add bdms to terminate_instance
+ 2.5 - Add block device and network info to reboot_instance
'''
#
@@ -342,11 +343,16 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy):
image=image, reservations=reservations),
_compute_topic(self.topic, ctxt, host, None))
- def reboot_instance(self, ctxt, instance, reboot_type):
+ def reboot_instance(self, ctxt, instance,
+ block_device_info, network_info, reboot_type):
instance_p = jsonutils.to_primitive(instance)
self.cast(ctxt, self.make_msg('reboot_instance',
- instance=instance_p, reboot_type=reboot_type),
- topic=_compute_topic(self.topic, ctxt, None, instance))
+ instance=instance_p,
+ block_device_info=block_device_info,
+ network_info=network_info,
+ reboot_type=reboot_type),
+ topic=_compute_topic(self.topic, ctxt, None, instance),
+ version='2.5')
def rebuild_instance(self, ctxt, instance, new_pass, injected_files,
image_ref, orig_image_ref, orig_sys_metadata):
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 979dc9a5d..2479bc946 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -870,6 +870,15 @@ class ComputeTestCase(BaseTestCase):
self.compute.terminate_instance(self.context,
instance=jsonutils.to_primitive(instance))
+ def _stub_out_reboot(self, fake_net_info, fake_block_dev_info):
+ def fake_reboot(driver, inst, net_info, reboot_type, block_dev_info):
+ self.assertEqual(block_dev_info, fake_block_dev_info)
+ self.assertEqual(net_info, fake_net_info)
+
+ self.stubs.Set(nova.virt.fake.FakeDriver, 'legacy_nwinfo',
+ lambda x: False)
+ self.stubs.Set(nova.virt.fake.FakeDriver, 'reboot', fake_reboot)
+
def test_reboot_soft(self):
"""Ensure instance can be soft rebooted"""
instance = jsonutils.to_primitive(self._create_fake_instance())
@@ -878,8 +887,12 @@ class ComputeTestCase(BaseTestCase):
{'task_state': task_states.REBOOTING})
reboot_type = "SOFT"
- self.compute.reboot_instance(self.context,
- instance=instance,
+ fake_net_info = {'bar': 'baz'}
+ fake_block_dev_info = {'foo': 'bar'}
+ self._stub_out_reboot(fake_net_info, fake_block_dev_info)
+ self.compute.reboot_instance(self.context, instance=instance,
+ network_info=fake_net_info,
+ block_device_info=fake_block_dev_info,
reboot_type=reboot_type)
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
@@ -897,7 +910,12 @@ class ComputeTestCase(BaseTestCase):
{'task_state': task_states.REBOOTING_HARD})
reboot_type = "HARD"
+ fake_net_info = {'bar': 'baz'}
+ fake_block_dev_info = {'foo': 'bar'}
+ self._stub_out_reboot(fake_net_info, fake_block_dev_info)
self.compute.reboot_instance(self.context, instance=instance,
+ network_info=fake_net_info,
+ block_device_info=fake_block_dev_info,
reboot_type=reboot_type)
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
@@ -3268,15 +3286,40 @@ class ComputeAPITestCase(BaseTestCase):
'preserved': 'preserve this!'})
db.instance_destroy(self.context, instance['uuid'])
+ def _stub_out_reboot(self, volume_id):
+ def fake_reboot_instance(rpcapi, context, instance,
+ block_device_info,
+ network_info,
+ reboot_type):
+ self.assertEqual(
+ block_device_info['block_device_mapping'][0]['mount_device'],
+ volume_id)
+ self.assertEqual(network_info[0]['network']['bridge'], 'fake_br1')
+ self.stubs.Set(nova.compute.rpcapi.ComputeAPI, 'reboot_instance',
+ fake_reboot_instance)
+
+ self.stubs.Set(nova.virt.fake.FakeDriver, 'legacy_nwinfo',
+ lambda x: False)
+
def test_reboot_soft(self):
"""Ensure instance can be soft rebooted"""
instance = jsonutils.to_primitive(self._create_fake_instance())
self.compute.run_instance(self.context, instance=instance)
+ volume_id = db.volume_create(context.get_admin_context(),
+ {'size': 1})['id']
+ volume = {'instance_uuid': instance['uuid'],
+ 'device_name': '/dev/vdc',
+ 'delete_on_termination': False,
+ 'connection_info': '{"foo": "bar"}',
+ 'volume_id': volume_id}
+ db.block_device_mapping_create(self.context, volume)
+
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
self.assertEqual(inst_ref['task_state'], None)
reboot_type = "SOFT"
+ self._stub_out_reboot(volume_id)
self.compute_api.reboot(self.context, inst_ref, reboot_type)
inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
@@ -3289,10 +3332,20 @@ class ComputeAPITestCase(BaseTestCase):
instance = jsonutils.to_primitive(self._create_fake_instance())
self.compute.run_instance(self.context, instance=instance)
+ volume_id = db.volume_create(context.get_admin_context(),
+ {'size': 1})['id']
+ volume = {'instance_uuid': instance['uuid'],
+ 'device_name': '/dev/vdc',
+ 'delete_on_termination': False,
+ 'connection_info': '{"foo": "bar"}',
+ 'volume_id': volume_id}
+ db.block_device_mapping_create(self.context, volume)
+
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
self.assertEqual(inst_ref['task_state'], None)
reboot_type = "HARD"
+ self._stub_out_reboot(volume_id)
self.compute_api.reboot(self.context, inst_ref, reboot_type)
inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
diff --git a/nova/tests/compute/test_rpcapi.py b/nova/tests/compute/test_rpcapi.py
index 304f9adb3..2fa6bf9ee 100644
--- a/nova/tests/compute/test_rpcapi.py
+++ b/nova/tests/compute/test_rpcapi.py
@@ -216,8 +216,13 @@ class ComputeRpcAPITestCase(test.TestCase):
reservations=list('fake_res'))
def test_reboot_instance(self):
+ self.maxDiff = None
self._test_compute_api('reboot_instance', 'cast',
- instance=self.fake_instance, reboot_type='type')
+ instance=self.fake_instance,
+ block_device_info={},
+ network_info={},
+ reboot_type='type',
+ version='2.5')
def test_rebuild_instance(self):
self._test_compute_api('rebuild_instance', 'cast',