Skip to content

Commit

Permalink
Make compute_api.reboot() use objects
Browse files Browse the repository at this point in the history
This makes the compute api's reboot() method use objects and pass
them to compute/manager.

The one place we call back from compute/manager to compute/api's
reboot() is also converted to use objects in this patch. That
almost makes bug 1196301 go away, but will require instance
actions work as well.

This also adds a new cells method for passing the object to reboot in
the child cell.

Related to blueprint compute-api-objects

Change-Id: I7845daa266687b5dc24fc2b1a98f2e5a2841e4bf
  • Loading branch information
kk7ds committed Jul 18, 2013
1 parent c11c0d8 commit 7f0051d
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 101 deletions.
3 changes: 2 additions & 1 deletion nova/api/ec2/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,8 @@ def terminate_instances(self, context, instance_id, **kwargs):

def reboot_instances(self, context, instance_id, **kwargs):
"""instance_id is a list of instance ids."""
instances = self._ec2_ids_to_instances(context, instance_id)
instances = self._ec2_ids_to_instances(context, instance_id,
objects=True)
LOG.audit(_("Reboot instance %r"), instance_id, context=context)
for instance in instances:
self.compute_api.reboot(context, instance, 'HARD')
Expand Down
6 changes: 5 additions & 1 deletion nova/cells/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class CellsManager(manager.Manager):
Scheduling requests get passed to the scheduler class.
"""
RPC_API_VERSION = '1.13'
RPC_API_VERSION = '1.14'

def __init__(self, *args, **kwargs):
# Mostly for tests.
Expand Down Expand Up @@ -440,3 +440,7 @@ def cell_delete(self, ctxt, cell_name):

def cell_get(self, ctxt, cell_name):
return self.state_manager.cell_get(ctxt, cell_name)

def reboot_instance(self, ctxt, instance, reboot_type):
"""Reboot an instance in its cell."""
self.msg_runner.reboot_instance(ctxt, instance, reboot_type)
11 changes: 11 additions & 0 deletions nova/cells/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,11 @@ def stop_instance(self, message, instance):
return self._call_compute_api_with_obj(message.ctxt, instance,
'stop', do_cast=do_cast)

def reboot_instance(self, message, instance, reboot_type):
"""Reboot an instance via compute_api.reboot()."""
self._call_compute_api_with_obj(message.ctxt, instance, 'reboot',
reboot_type=reboot_type)


class _BroadcastMessageMethods(_BaseMessageMethods):
"""These are the methods that can be called as a part of a broadcast
Expand Down Expand Up @@ -1527,6 +1532,12 @@ def stop_instance(self, ctxt, instance, do_cast=True):
return self._instance_action(ctxt, instance, 'stop_instance',
need_response=True)

def reboot_instance(self, ctxt, instance, reboot_type):
"""Reboot an instance in its cell."""
extra_kwargs = dict(reboot_type=reboot_type)
self._instance_action(ctxt, instance, 'reboot_instance',
extra_kwargs=extra_kwargs)

@staticmethod
def get_message_types():
return _CELL_MESSAGE_TYPE_TO_MESSAGE_CLS.keys()
Expand Down
14 changes: 14 additions & 0 deletions nova/cells/rpcapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class CellsAPI(rpc_proxy.RpcProxy):
1.12 - Adds instance_start() and instance_stop()
1.13 - Adds cell_create(), cell_update(), cell_delete(), and
cell_get()
1.14 - Adds reboot_instance()
'''
BASE_RPC_API_VERSION = '1.0'

Expand Down Expand Up @@ -406,3 +407,16 @@ def cell_get(self, ctxt, cell_name):
return self.call(ctxt,
self.make_msg('cell_get', cell_name=cell_name),
version='1.13')

def reboot_instance(self, ctxt, instance, block_device_info,
reboot_type):
"""Reboot an instance in its cell.
This method takes a new-world instance object.
"""
if not CONF.cells.enable:
return
self.cast(ctxt,
self.make_msg('reboot_instance', instance=instance,
reboot_type=reboot_type),
version='1.14')
6 changes: 2 additions & 4 deletions nova/compute/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1898,10 +1898,8 @@ def reboot(self, context, instance, reboot_type):
method='reboot')
state = {'SOFT': task_states.REBOOTING,
'HARD': task_states.REBOOTING_HARD}[reboot_type]
instance = self.update(context, instance,
task_state=state,
expected_task_state=[None,
task_states.REBOOTING])
instance.task_state = state
instance.save(expected_task_state=[None, task_states.REBOOTING])
elevated = context.elevated()
block_info = self._get_block_device_info(elevated,
instance['uuid'])
Expand Down
10 changes: 2 additions & 8 deletions nova/compute/cells_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class ComputeRPCAPIRedirect(object):
# and the compute_rpcapi methods have the same signatures. This
# is for transitioning to a common interface where we can just
# swap out the compute_rpcapi class with the cells_rpcapi class.
cells_compatible = ['start_instance', 'stop_instance']
cells_compatible = ['start_instance', 'stop_instance',
'reboot_instance']

def __init__(self, cells_rpcapi):
self.cells_rpcapi = cells_rpcapi
Expand Down Expand Up @@ -269,13 +270,6 @@ def force_delete(self, context, instance):
super(ComputeCellsAPI, self).force_delete(context, instance)
self._cast_to_cells(context, instance, 'force_delete')

def reboot(self, context, instance, *args, **kwargs):
"""Reboot the given instance."""
super(ComputeCellsAPI, self).reboot(context, instance,
*args, **kwargs)
self._cast_to_cells(context, instance, 'reboot', *args,
**kwargs)

@check_instance_cell
def rebuild(self, context, instance, *args, **kwargs):
"""Rebuild the given instance with the provided attributes."""
Expand Down
21 changes: 11 additions & 10 deletions nova/compute/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def instance_type_get(self, context, instance_type_id):
class ComputeManager(manager.SchedulerDependentManager):
"""Manages the running instances from creation to destruction."""

RPC_API_VERSION = '2.31'
RPC_API_VERSION = '2.32'

def __init__(self, compute_driver=None, *args, **kwargs):
"""Load configuration options and connect to the hypervisor."""
Expand Down Expand Up @@ -1931,6 +1931,7 @@ def _handle_bad_volumes_detached(self, context, instance, bad_devices,
# Manager-detach
self.detach_volume(context, volume_id, instance)

@object_compat
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@reverts_task_state
@wrap_instance_event
Expand All @@ -1954,8 +1955,8 @@ def reboot_instance(self, context, instance,

current_power_state = self._get_power_state(context, instance)

instance = self._instance_update(context, instance['uuid'],
power_state=current_power_state)
instance.power_state = current_power_state
instance.save()

if instance['power_state'] != power_state.RUNNING:
state = instance['power_state']
Expand Down Expand Up @@ -2001,16 +2002,16 @@ def bad_volumes_callback(bad_devices):
else:
LOG.error(_('Cannot reboot instance: %s'), error,
context=context, instance=instance)
self._set_instance_error_state(context, instance['uuid'])
self._set_instance_obj_error_state(context, instance)
raise type_, value, tb

if not new_power_state:
new_power_state = self._get_power_state(context, instance)
try:
instance = self._instance_update(context, instance['uuid'],
power_state=new_power_state,
vm_state=new_vm_state,
task_state=None)
instance.power_state = new_power_state
instance.vm_state = new_vm_state
instance.task_state = None
instance.save()
except exception.InstanceNotFound:
LOG.warn(_("Instance disappeared during reboot"),
context=context, instance=instance)
Expand Down Expand Up @@ -4005,8 +4006,8 @@ def _poll_rebooting_instances(self, context):
if CONF.reboot_timeout > 0:
filters = {'task_state': task_states.REBOOTING,
'host': self.host}
rebooting = self.conductor_api.instance_get_all_by_filters(
context, filters, columns_to_join=[])
rebooting = instance_obj.InstanceList.get_by_filters(
context, filters, expected_attrs=[])

to_poll = []
for instance in rebooting:
Expand Down
12 changes: 9 additions & 3 deletions nova/compute/rpcapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy):
2.30 - Adds live_snapshot_instance()
2.31 - Adds shelve_instance(), shelve_offload_instance, and
unshelve_instance()
2.32 - Make reboot_instance take a new world instance object
'''

#
Expand Down Expand Up @@ -459,13 +460,18 @@ def prep_resize(self, ctxt, image, instance, instance_type, host,

def reboot_instance(self, ctxt, instance, block_device_info,
reboot_type):
instance_p = jsonutils.to_primitive(instance)
if not self.can_send_version('2.32'):
version = '2.23'
instance = jsonutils.to_primitive(
objects_base.obj_to_primitive(instance))
else:
version = '2.32'
self.cast(ctxt, self.make_msg('reboot_instance',
instance=instance_p,
instance=instance,
block_device_info=block_device_info,
reboot_type=reboot_type),
topic=_compute_topic(self.topic, ctxt, None, instance),
version='2.23')
version=version)

def rebuild_instance(self, ctxt, instance, new_pass, injected_files,
image_ref, orig_image_ref, orig_sys_metadata, bdms,
Expand Down
9 changes: 9 additions & 0 deletions nova/tests/cells/test_cells_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,3 +663,12 @@ def test_cell_get(self):
self.mox.ReplayAll()
self.assertEqual(response,
self.cells_manager.cell_get(self.ctxt, cell_name))

def test_reboot_instance(self):
self.mox.StubOutWithMock(self.msg_runner, 'reboot_instance')
self.msg_runner.reboot_instance(self.ctxt, 'fake-instance',
'HARD')
self.mox.ReplayAll()
self.cells_manager.reboot_instance(self.ctxt,
instance='fake-instance',
reboot_type='HARD')
5 changes: 5 additions & 0 deletions nova/tests/cells/test_cells_messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,11 @@ def test_stop_instance_call(self):
self._test_instance_action_method('stop', (), {}, (),
{'do_cast': False}, True)

def test_reboot_instance(self):
kwargs = dict(reboot_type='HARD')
self._test_instance_action_method('reboot', (), kwargs, (),
kwargs, False)


class CellsBroadcastMethodsTestCase(test.TestCase):
"""Test case for _BroadcastMessageMethods class. Most of these
Expand Down
12 changes: 12 additions & 0 deletions nova/tests/cells/test_cells_rpcapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,15 @@ def test_cell_get(self):
self._check_result(call_info, 'cell_get',
expected_args, version='1.13')
self.assertEqual(result, 'fake_response')

def test_reboot_instance(self):
call_info = self._stub_rpc_method('cast', None)

self.cells_rpcapi.reboot_instance(
self.fake_context, 'fake-instance',
block_device_info='ignored', reboot_type='HARD')

expected_args = {'instance': 'fake-instance',
'reboot_type': 'HARD'}
self._check_result(call_info, 'reboot_instance',
expected_args, version='1.14')

0 comments on commit 7f0051d

Please sign in to comment.