Make cells send Instance objects in build_instance()

This makes the cells rpcapi pass real objects through in the build_instances()
call.

Related to blueprint kilo-objects

Change-Id: I4a08274c34acedc58a2010a5f3093865bd1055d4
This commit is contained in:
Dan Smith 2014-12-03 12:26:15 -08:00
parent ebbb56e297
commit 1a1a8ca295
6 changed files with 49 additions and 23 deletions

View File

@ -33,6 +33,7 @@ from nova.i18n import _LW
from nova import manager from nova import manager
from nova import objects from nova import objects
from nova.objects import base as base_obj from nova.objects import base as base_obj
from nova.objects import instance as instance_obj
from nova.openstack.common import log as logging from nova.openstack.common import log as logging
from nova.openstack.common import periodic_task from nova.openstack.common import periodic_task
@ -73,7 +74,7 @@ class CellsManager(manager.Manager):
Scheduling requests get passed to the scheduler class. Scheduling requests get passed to the scheduler class.
""" """
target = oslo_messaging.Target(version='1.31') target = oslo_messaging.Target(version='1.32')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
LOG.warning(_LW('The cells feature of Nova is considered experimental ' LOG.warning(_LW('The cells feature of Nova is considered experimental '
@ -206,6 +207,13 @@ class CellsManager(manager.Manager):
flavor = objects.Flavor(**filter_properties['instance_type']) flavor = objects.Flavor(**filter_properties['instance_type'])
build_inst_kwargs['filter_properties'] = dict( build_inst_kwargs['filter_properties'] = dict(
filter_properties, instance_type=flavor) filter_properties, instance_type=flavor)
instances = build_inst_kwargs['instances']
if not isinstance(instances[0], objects.Instance):
# NOTE(danms): Handle pre-1.32 build_instances() call. Remove me
# when we bump the RPC API version to 2.0
build_inst_kwargs['instances'] = instance_obj._make_instance_list(
ctxt, objects.InstanceList(), instances, ['system_metadata',
'metadata'])
our_cell = self.state_manager.get_my_state() our_cell = self.state_manager.get_my_state()
self.msg_runner.build_instances(ctxt, our_cell, build_inst_kwargs) self.msg_runner.build_instances(ctxt, our_cell, build_inst_kwargs)

View File

@ -104,6 +104,7 @@ class CellsAPI(object):
* 1.30 - Make build_instances() use flavor object * 1.30 - Make build_instances() use flavor object
* 1.31 - Add clean_shutdown to stop, resize, rescue, and shelve * 1.31 - Add clean_shutdown to stop, resize, rescue, and shelve
* 1.32 - Send objects for instances in build_instances()
''' '''
VERSION_ALIASES = { VERSION_ALIASES = {
@ -149,18 +150,20 @@ class CellsAPI(object):
"""Build instances.""" """Build instances."""
build_inst_kwargs = kwargs build_inst_kwargs = kwargs
instances = build_inst_kwargs['instances'] instances = build_inst_kwargs['instances']
instances_p = [jsonutils.to_primitive(inst) for inst in instances]
build_inst_kwargs['instances'] = instances_p
build_inst_kwargs['image'] = jsonutils.to_primitive( build_inst_kwargs['image'] = jsonutils.to_primitive(
build_inst_kwargs['image']) build_inst_kwargs['image'])
version = '1.32'
if not self.client.can_send_version('1.32'):
instances_p = [jsonutils.to_primitive(inst) for inst in instances]
build_inst_kwargs['instances'] = instances_p
version = '1.30' version = '1.30'
if not self.client.can_send_version(version): if not self.client.can_send_version('1.30'):
version = '1.8'
if 'filter_properties' in build_inst_kwargs: if 'filter_properties' in build_inst_kwargs:
filter_properties = build_inst_kwargs['filter_properties'] filter_properties = build_inst_kwargs['filter_properties']
flavor = filter_properties['instance_type'] flavor = filter_properties['instance_type']
flavor_p = objects_base.obj_to_primitive(flavor) flavor_p = objects_base.obj_to_primitive(flavor)
filter_properties['instance_type'] = flavor_p filter_properties['instance_type'] = flavor_p
version = '1.8'
cctxt = self.client.prepare(version=version) cctxt = self.client.prepare(version=version)
cctxt.cast(ctxt, 'build_instances', cctxt.cast(ctxt, 'build_instances',
build_inst_kwargs=build_inst_kwargs) build_inst_kwargs=build_inst_kwargs)

View File

@ -167,7 +167,8 @@ class CellsScheduler(base.Base):
build_inst_kwargs): build_inst_kwargs):
"""Attempt to build instance(s) or send msg to child cell.""" """Attempt to build instance(s) or send msg to child cell."""
ctxt = message.ctxt ctxt = message.ctxt
instance_properties = build_inst_kwargs['instances'][0] instance_properties = obj_base.obj_to_primitive(
build_inst_kwargs['instances'][0])
filter_properties = build_inst_kwargs['filter_properties'] filter_properties = build_inst_kwargs['filter_properties']
instance_type = filter_properties['instance_type'] instance_type = filter_properties['instance_type']
image = build_inst_kwargs['image'] image = build_inst_kwargs['image']

View File

@ -28,6 +28,7 @@ from nova import context
from nova import objects from nova import objects
from nova import test from nova import test
from nova.tests.unit.cells import fakes from nova.tests.unit.cells import fakes
from nova.tests.unit import fake_instance
from nova.tests.unit import fake_server_actions from nova.tests.unit import fake_server_actions
from nova.tests.unit.objects import test_flavor from nova.tests.unit.objects import test_flavor
@ -116,7 +117,8 @@ class CellsManagerClassTestCase(test.NoDBTestCase):
self.cells_manager._update_our_parents(self.ctxt) self.cells_manager._update_our_parents(self.ctxt)
def test_build_instances(self): def test_build_instances(self):
build_inst_kwargs = {'instances': [1, 2]} build_inst_kwargs = {'instances': [objects.Instance(),
objects.Instance()]}
self.mox.StubOutWithMock(self.msg_runner, 'build_instances') self.mox.StubOutWithMock(self.msg_runner, 'build_instances')
our_cell = self.msg_runner.state_manager.get_my_state() our_cell = self.msg_runner.state_manager.get_my_state()
self.msg_runner.build_instances(self.ctxt, our_cell, build_inst_kwargs) self.msg_runner.build_instances(self.ctxt, our_cell, build_inst_kwargs)
@ -126,7 +128,8 @@ class CellsManagerClassTestCase(test.NoDBTestCase):
def test_build_instances_old_flavor(self): def test_build_instances_old_flavor(self):
flavor_dict = test_flavor.fake_flavor flavor_dict = test_flavor.fake_flavor
args = {'filter_properties': {'instance_type': flavor_dict}} args = {'filter_properties': {'instance_type': flavor_dict},
'instances': [objects.Instance()]}
with mock.patch.object(self.msg_runner, 'build_instances') as mock_bi: with mock.patch.object(self.msg_runner, 'build_instances') as mock_bi:
self.cells_manager.build_instances(self.ctxt, self.cells_manager.build_instances(self.ctxt,
build_inst_kwargs=args) build_inst_kwargs=args)
@ -134,6 +137,14 @@ class CellsManagerClassTestCase(test.NoDBTestCase):
self.assertIsInstance(filter_properties['instance_type'], self.assertIsInstance(filter_properties['instance_type'],
objects.Flavor) objects.Flavor)
def test_build_instances_old_instances(self):
args = {'instances': [fake_instance.fake_db_instance()]}
with mock.patch.object(self.msg_runner, 'build_instances') as mock_bi:
self.cells_manager.build_instances(self.ctxt,
build_inst_kwargs=args)
self.assertIsInstance(mock_bi.call_args[0][2]['instances'][0],
objects.Instance)
def test_run_compute_api_method(self): def test_run_compute_api_method(self):
# Args should just be silently passed through # Args should just be silently passed through
cell_name = 'fake-cell-name' cell_name = 'fake-cell-name'

View File

@ -21,6 +21,7 @@ import six
from nova.cells import rpcapi as cells_rpcapi from nova.cells import rpcapi as cells_rpcapi
from nova import exception from nova import exception
from nova import objects
from nova import test from nova import test
from nova.tests.unit import fake_instance from nova.tests.unit import fake_instance
@ -125,17 +126,20 @@ class CellsAPITestCase(test.NoDBTestCase):
def test_build_instances(self): def test_build_instances(self):
call_info = self._stub_rpc_method('cast', None) call_info = self._stub_rpc_method('cast', None)
instances = [objects.Instance(id=1),
objects.Instance(id=2)]
self.cells_rpcapi.build_instances( self.cells_rpcapi.build_instances(
self.fake_context, instances=['1', '2'], self.fake_context, instances=instances,
image={'fake': 'image'}, arg1=1, arg2=2, arg3=3) image={'fake': 'image'}, arg1=1, arg2=2, arg3=3)
expected_args = {'build_inst_kwargs': {'instances': ['1', '2'], expected_args = {'build_inst_kwargs': {'instances': instances,
'image': {'fake': 'image'}, 'image': {'fake': 'image'},
'arg1': 1, 'arg1': 1,
'arg2': 2, 'arg2': 2,
'arg3': 3}} 'arg3': 3}}
self._check_result(call_info, 'build_instances', self._check_result(call_info, 'build_instances',
expected_args, version='1.30') expected_args, version='1.32')
def test_get_capacities(self): def test_get_capacities(self):
capacity_info = {"capacity": "info"} capacity_info = {"capacity": "info"}

View File

@ -27,11 +27,11 @@ from nova.compute import vm_states
from nova import context from nova import context
from nova import db from nova import db
from nova import exception from nova import exception
from nova import objects
from nova.openstack.common import uuidutils from nova.openstack.common import uuidutils
from nova.scheduler import utils as scheduler_utils from nova.scheduler import utils as scheduler_utils
from nova import test from nova import test
from nova.tests.unit.cells import fakes from nova.tests.unit.cells import fakes
from nova.tests.unit import fake_instance
from nova import utils from nova import utils
CONF = cfg.CONF CONF = cfg.CONF
@ -80,7 +80,8 @@ class CellsSchedulerTestCase(test.TestCase):
for x in xrange(3): for x in xrange(3):
instance_uuids.append(uuidutils.generate_uuid()) instance_uuids.append(uuidutils.generate_uuid())
self.instance_uuids = instance_uuids self.instance_uuids = instance_uuids
self.instances = [{'uuid': uuid} for uuid in instance_uuids] self.instances = [objects.Instance(uuid=uuid, id=id)
for id, uuid in enumerate(instance_uuids)]
self.request_spec = { self.request_spec = {
'instance_uuids': instance_uuids, 'instance_uuids': instance_uuids,
'instance_properties': self.instances[0], 'instance_properties': self.instances[0],
@ -197,9 +198,7 @@ class CellsSchedulerTestCase(test.TestCase):
call_info['image'] = image call_info['image'] = image
call_info['security_groups'] = security_groups call_info['security_groups'] = security_groups
call_info['block_device_mapping'] = block_device_mapping call_info['block_device_mapping'] = block_device_mapping
instances = [fake_instance.fake_instance_obj(ctxt, **instance) return self.instances
for instance in self.instances]
return instances
def fake_rpc_build_instances(ctxt, **build_inst_kwargs): def fake_rpc_build_instances(ctxt, **build_inst_kwargs):
call_info['build_inst_kwargs'] = build_inst_kwargs call_info['build_inst_kwargs'] = build_inst_kwargs
@ -222,8 +221,8 @@ class CellsSchedulerTestCase(test.TestCase):
self.assertEqual(self.ctxt, call_info['ctxt']) self.assertEqual(self.ctxt, call_info['ctxt'])
self.assertEqual(self.instance_uuids, call_info['instance_uuids']) self.assertEqual(self.instance_uuids, call_info['instance_uuids'])
self.assertEqual(self.build_inst_kwargs['instances'][0], self.assertEqual(self.build_inst_kwargs['instances'][0]['id'],
call_info['instance_properties']) call_info['instance_properties']['id'])
self.assertEqual( self.assertEqual(
self.build_inst_kwargs['filter_properties']['instance_type'], self.build_inst_kwargs['filter_properties']['instance_type'],
call_info['instance_type']) call_info['instance_type'])
@ -398,8 +397,8 @@ class CellsSchedulerTestCase(test.TestCase):
# Our cell was selected. # Our cell was selected.
self.assertEqual(self.ctxt, call_info['ctxt']) self.assertEqual(self.ctxt, call_info['ctxt'])
self.assertEqual(self.instance_uuids, call_info['instance_uuids']) self.assertEqual(self.instance_uuids, call_info['instance_uuids'])
self.assertEqual(self.request_spec['instance_properties'], self.assertEqual(self.request_spec['instance_properties']['id'],
call_info['instance_properties']) call_info['instance_properties']['id'])
self.assertEqual(self.request_spec['instance_type'], self.assertEqual(self.request_spec['instance_type'],
call_info['instance_type']) call_info['instance_type'])
self.assertEqual(self.request_spec['image'], call_info['image']) self.assertEqual(self.request_spec['image'], call_info['image'])
@ -513,8 +512,8 @@ class CellsSchedulerTestCase(test.TestCase):
# Our cell was selected. # Our cell was selected.
self.assertEqual(self.ctxt, call_info['ctxt']) self.assertEqual(self.ctxt, call_info['ctxt'])
self.assertEqual(self.instance_uuids, call_info['instance_uuids']) self.assertEqual(self.instance_uuids, call_info['instance_uuids'])
self.assertEqual(self.request_spec['instance_properties'], self.assertEqual(self.request_spec['instance_properties']['id'],
call_info['instance_properties']) call_info['instance_properties']['id'])
self.assertEqual(self.request_spec['instance_type'], self.assertEqual(self.request_spec['instance_type'],
call_info['instance_type']) call_info['instance_type'])
self.assertEqual(self.request_spec['image'], call_info['image']) self.assertEqual(self.request_spec['image'], call_info['image'])