Handle instance objects in conductor compute_stop

The compute manager is sending instance objects to
compute_stop in conductor but conductor's compute_stop
RPC proxy wasn't handling objects. This patch fixes that
and also handles compatibility with older installations
using the dict-style format in the conductor compute_stop
RPC proxy.

Fixes bug 1195849

Change-Id: Ib678df424a58a0d7023ce3b2bdd5001998daf398
This commit is contained in:
Matt Riedemann
2013-07-18 14:23:15 -07:00
parent 3b517c3d5a
commit 190d8ca452
3 changed files with 44 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
# Copyright 2012 IBM Corp.
# Copyright 2013 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -32,6 +32,7 @@ from nova import network
from nova.network.security_group import openstack_driver
from nova import notifications
from nova.objects import base as nova_object
from nova.objects import instance as instance_obj
from nova.openstack.common import excutils
from nova.openstack.common import jsonutils
from nova.openstack.common import log as logging
@@ -73,7 +74,7 @@ class ConductorManager(manager.Manager):
namespace. See the ComputeTaskManager class for details.
"""
RPC_API_VERSION = '1.54'
RPC_API_VERSION = '1.55'
def __init__(self, *args, **kwargs):
super(ConductorManager, self).__init__(service_name='conductor',
@@ -513,6 +514,12 @@ class ConductorManager(manager.Manager):
return ec2_ids
def compute_stop(self, context, instance, do_cast=True):
# NOTE(mriedem): Clients using an interface before 1.43 will be sending
# dicts so we need to handle that here since compute/api::stop()
# requires an object.
if isinstance(instance, dict):
instance = instance_obj.Instance._from_db_object(
context, instance_obj.Instance(), instance)
self.compute_api.stop(context, instance, do_cast)
def compute_confirm_resize(self, context, instance, migration_ref):

View File

@@ -1,4 +1,4 @@
# Copyright 2012 IBM Corp.
# Copyright 2013 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -106,6 +106,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
1.52 - Pass instance objects for compute_confirm_resize
1.53 - Added compute_reboot
1.54 - Added 'update_cells' argument to bw_usage_update
1.55 - Pass instance objects for compute_stop
"""
BASE_RPC_API_VERSION = '1.0'
@@ -477,10 +478,14 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
return self.call(context, msg, version='1.42')
def compute_stop(self, context, instance, do_cast=True):
instance_p = jsonutils.to_primitive(instance)
msg = self.make_msg('compute_stop', instance=instance_p,
do_cast=do_cast)
return self.call(context, msg, version='1.43')
if not self.can_send_version('1.55'):
instance = jsonutils.to_primitive(
objects_base.obj_to_primitive(instance))
version = '1.43'
else:
version = '1.55'
msg = self.make_msg('compute_stop', instance=instance, do_cast=do_cast)
return self.call(context, msg, version=version)
def compute_confirm_resize(self, context, instance, migration_ref):
migration_p = jsonutils.to_primitive(migration_ref)

View File

@@ -812,6 +812,31 @@ class ConductorTestCase(_BaseTestCase, test.TestCase):
self.conductor.security_groups_trigger_handler(self.context,
'event', ['args'])
def test_compute_stop_with_objects(self):
# use an instance object rather than a dict
instance = self._create_fake_instance()
inst_obj = instance_obj.Instance._from_db_object(
self.context, instance_obj.Instance(), instance)
self.mox.StubOutWithMock(self.conductor_manager.compute_api, 'stop')
self.conductor_manager.compute_api.stop(self.context, inst_obj, True)
self.mox.ReplayAll()
self.conductor.compute_stop(self.context, inst_obj)
def test_compute_confirm_resize_with_objects(self):
# use an instance object rather than a dict
instance = self._create_fake_instance()
inst_obj = instance_obj.Instance._from_db_object(
self.context, instance_obj.Instance(), instance)
self.mox.StubOutWithMock(self.conductor_manager.compute_api,
'confirm_resize')
# make sure the instance object is serialized
primitive_instance = dict(inst_obj.items())
self.conductor_manager.compute_api.confirm_resize(
self.context, primitive_instance, 'migration')
self.mox.ReplayAll()
self.conductor.compute_confirm_resize(self.context, inst_obj,
'migration')
class ConductorRPCAPITestCase(_BaseTestCase, test.TestCase):
"""Conductor RPC API Tests."""