summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Smith <danms@us.ibm.com>2012-09-27 11:41:02 -0700
committerRussell Bryant <rbryant@redhat.com>2012-10-16 05:35:07 -0700
commite7780b5f3f9d9ccb6ed18a353fdfe6ade904aba0 (patch)
tree7f75edef8d9b2f3f220b21b69f2b9eeb5d62ad89
parent70275a6502d47d70fc006b84af1035138bc16d66 (diff)
downloadnova-e7780b5f3f9d9ccb6ed18a353fdfe6ade904aba0.tar.gz
nova-e7780b5f3f9d9ccb6ed18a353fdfe6ade904aba0.tar.xz
nova-e7780b5f3f9d9ccb6ed18a353fdfe6ade904aba0.zip
Remove db access for block devices and network info on reboot
This makes compute/api pass the block device and network info to compute_manager::reboot_instance() so that it doesn't have to hit the database itself. This also extends the reboot tests for the compute manager and api to validate that these two bits of data are making it all the way through the stack. bp no-db-compute Change-Id: I92346d6c821241885b5f4b08fec05f38e6261edf
-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',