Merge "object-ify flavors manager side of the RPC"

This commit is contained in:
Jenkins 2014-12-05 13:40:42 +00:00 committed by Gerrit Code Review
commit 16d38947ae
12 changed files with 88 additions and 44 deletions

View File

@ -73,7 +73,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.29') target = oslo_messaging.Target(version='1.30')
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 '

View File

@ -101,6 +101,8 @@ class CellsAPI(object):
... Juno supports message version 1.29. So, any changes to ... Juno supports message version 1.29. So, any changes to
existing methods in 1.x after that point should be done such that they existing methods in 1.x after that point should be done such that they
can handle the version_cap being set to 1.29. can handle the version_cap being set to 1.29.
* 1.30 - Make build_instances() use flavor object
''' '''
VERSION_ALIASES = { VERSION_ALIASES = {
@ -150,11 +152,15 @@ class CellsAPI(object):
build_inst_kwargs['instances'] = instances_p 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'])
if 'filter_properties' in build_inst_kwargs: version = '1.30'
flavor = build_inst_kwargs['filter_properties']['instance_type'] if not self.client.can_send_version(version):
flavor_p = objects_base.obj_to_primitive(flavor) version = '1.8'
build_inst_kwargs['filter_properties']['instance_type'] = flavor_p if 'filter_properties' in build_inst_kwargs:
cctxt = self.client.prepare(version='1.8') filter_properties = build_inst_kwargs['filter_properties']
flavor = filter_properties['instance_type']
flavor_p = objects_base.obj_to_primitive(flavor)
filter_properties['instance_type'] = flavor_p
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

@ -587,7 +587,7 @@ class ComputeVirtAPI(virtapi.VirtAPI):
class ComputeManager(manager.Manager): class ComputeManager(manager.Manager):
"""Manages the running instances from creation to destruction.""" """Manages the running instances from creation to destruction."""
target = messaging.Target(version='3.35') target = messaging.Target(version='3.36')
# How long to wait in seconds before re-issuing a shutdown # How long to wait in seconds before re-issuing a shutdown
# signal to a instance during power off. The overall # signal to a instance during power off. The overall
@ -1994,6 +1994,13 @@ class ComputeManager(manager.Manager):
requested_networks = objects.NetworkRequestList( requested_networks = objects.NetworkRequestList(
objects=[objects.NetworkRequest.from_tuple(t) objects=[objects.NetworkRequest.from_tuple(t)
for t in requested_networks]) for t in requested_networks])
# NOTE(melwitt): Remove this in v4.0 of the RPC API
flavor = filter_properties.get('instance_type')
if flavor and not isinstance(flavor, objects.Flavor):
# Code downstream may expect extra_specs to be populated since it
# is receiving an object, so lookup the flavor to ensure this.
flavor = objects.Flavor.get_by_id(context, flavor['id'])
filter_properties = dict(filter_properties, instance_type=flavor)
@utils.synchronized(instance.uuid) @utils.synchronized(instance.uuid)
def _locked_do_build_and_run_instance(*args, **kwargs): def _locked_do_build_and_run_instance(*args, **kwargs):

View File

@ -274,6 +274,8 @@ class ComputeAPI(object):
... Juno supports message version 3.35. So, any changes to ... Juno supports message version 3.35. So, any changes to
existing methods in 3.x after that point should be done such that they existing methods in 3.x after that point should be done such that they
can handle the version_cap being set to 3.35. can handle the version_cap being set to 3.35.
* 3.36 - Make build_and_run_instance() send a Flavor object
''' '''
VERSION_ALIASES = { VERSION_ALIASES = {
@ -880,17 +882,20 @@ class ComputeAPI(object):
filter_properties, admin_password=None, injected_files=None, filter_properties, admin_password=None, injected_files=None,
requested_networks=None, security_groups=None, requested_networks=None, security_groups=None,
block_device_mapping=None, node=None, limits=None): block_device_mapping=None, node=None, limits=None):
version = '3.33' version = '3.36'
if not self.client.can_send_version(version):
version = '3.33'
if 'instance_type' in filter_properties:
flavor = filter_properties['instance_type']
flavor_p = objects_base.obj_to_primitive(flavor)
filter_properties = dict(filter_properties,
instance_type=flavor_p)
if not self.client.can_send_version(version): if not self.client.can_send_version(version):
version = '3.23' version = '3.23'
if requested_networks is not None: if requested_networks is not None:
requested_networks = [(network_id, address, port_id) requested_networks = [(network_id, address, port_id)
for (network_id, address, port_id, _) in for (network_id, address, port_id, _) in
requested_networks.as_tuples()] requested_networks.as_tuples()]
if 'instance_type' in filter_properties:
flavor = filter_properties['instance_type']
flavor_p = objects_base.obj_to_primitive(flavor)
filter_properties = dict(filter_properties, instance_type=flavor_p)
cctxt = self.client.prepare(server=host, version=version) cctxt = self.client.prepare(server=host, version=version)
cctxt.cast(ctxt, 'build_and_run_instance', instance=instance, cctxt.cast(ctxt, 'build_and_run_instance', instance=instance,

View File

@ -461,7 +461,7 @@ class ComputeTaskManager(base.Base):
may involve coordinating activities on multiple compute nodes. may involve coordinating activities on multiple compute nodes.
""" """
target = messaging.Target(namespace='compute_task', version='1.9') target = messaging.Target(namespace='compute_task', version='1.10')
def __init__(self): def __init__(self):
super(ComputeTaskManager, self).__init__() super(ComputeTaskManager, self).__init__()
@ -491,6 +491,11 @@ class ComputeTaskManager(base.Base):
instance = objects.Instance._from_db_object( instance = objects.Instance._from_db_object(
context, objects.Instance(), instance, context, objects.Instance(), instance,
expected_attrs=attrs) expected_attrs=attrs)
# NOTE(melwitt): Remove this in version 2.0 of the RPC API
if flavor and not isinstance(flavor, objects.Flavor):
# Code downstream may expect extra_specs to be populated since it
# is receiving an object, so lookup the flavor to ensure this.
flavor = objects.Flavor.get_by_id(context, flavor['id'])
if live and not rebuild and not flavor: if live and not rebuild and not flavor:
self._live_migrate(context, instance, scheduler_hint, self._live_migrate(context, instance, scheduler_hint,
block_migration, disk_over_commit) block_migration, disk_over_commit)
@ -545,11 +550,6 @@ class ComputeTaskManager(base.Base):
# context is not serializable # context is not serializable
filter_properties.pop('context', None) filter_properties.pop('context', None)
# TODO(timello): originally, instance_type in request_spec
# on compute.api.resize does not have 'extra_specs', so we
# remove it for now to keep tests backward compatibility.
request_spec['instance_type'].pop('extra_specs', None)
(host, node) = (host_state['host'], host_state['nodename']) (host, node) = (host_state['host'], host_state['nodename'])
self.compute_rpcapi.prep_resize( self.compute_rpcapi.prep_resize(
context, image, instance, context, image, instance,
@ -622,6 +622,13 @@ class ComputeTaskManager(base.Base):
requested_networks = objects.NetworkRequestList( requested_networks = objects.NetworkRequestList(
objects=[objects.NetworkRequest.from_tuple(t) objects=[objects.NetworkRequest.from_tuple(t)
for t in requested_networks]) for t in requested_networks])
# TODO(melwitt): Remove this in version 2.0 of the RPC API
flavor = filter_properties.get('instance_type')
if flavor and not isinstance(flavor, objects.Flavor):
# Code downstream may expect extra_specs to be populated since it
# is receiving an object, so lookup the flavor to ensure this.
flavor = objects.Flavor.get_by_id(context, flavor['id'])
filter_properties = dict(filter_properties, instance_type=flavor)
try: try:
# check retry policy. Rather ugly use of instances[0]... # check retry policy. Rather ugly use of instances[0]...

View File

@ -390,6 +390,7 @@ class ComputeTaskAPI(object):
1.7 - Do not send block_device_mapping and legacy_bdm to build_instances 1.7 - Do not send block_device_mapping and legacy_bdm to build_instances
1.8 - Add rebuild_instance 1.8 - Add rebuild_instance
1.9 - Converted requested_networks to NetworkRequestList object 1.9 - Converted requested_networks to NetworkRequestList object
1.10 - Made migrate_server() and build_instances() send flavor objects
""" """
@ -404,17 +405,18 @@ class ComputeTaskAPI(object):
def migrate_server(self, context, instance, scheduler_hint, live, rebuild, def migrate_server(self, context, instance, scheduler_hint, live, rebuild,
flavor, block_migration, disk_over_commit, flavor, block_migration, disk_over_commit,
reservations=None): reservations=None):
if self.client.can_send_version('1.6'): version = '1.10'
if not self.client.can_send_version(version):
flavor = objects_base.obj_to_primitive(flavor)
version = '1.6' version = '1.6'
else: if not self.client.can_send_version(version):
instance = jsonutils.to_primitive( instance = jsonutils.to_primitive(
objects_base.obj_to_primitive(instance)) objects_base.obj_to_primitive(instance))
version = '1.4' version = '1.4'
flavor_p = jsonutils.to_primitive(flavor)
cctxt = self.client.prepare(version=version) cctxt = self.client.prepare(version=version)
return cctxt.call(context, 'migrate_server', return cctxt.call(context, 'migrate_server',
instance=instance, scheduler_hint=scheduler_hint, instance=instance, scheduler_hint=scheduler_hint,
live=live, rebuild=rebuild, flavor=flavor_p, live=live, rebuild=rebuild, flavor=flavor,
block_migration=block_migration, block_migration=block_migration,
disk_over_commit=disk_over_commit, disk_over_commit=disk_over_commit,
reservations=reservations) reservations=reservations)
@ -423,19 +425,21 @@ class ComputeTaskAPI(object):
admin_password, injected_files, requested_networks, admin_password, injected_files, requested_networks,
security_groups, block_device_mapping, legacy_bdm=True): security_groups, block_device_mapping, legacy_bdm=True):
image_p = jsonutils.to_primitive(image) image_p = jsonutils.to_primitive(image)
if 'instance_type' in filter_properties: version = '1.10'
flavor = filter_properties['instance_type'] if not self.client.can_send_version(version):
flavor_p = objects_base.obj_to_primitive(flavor) version = '1.9'
filter_properties = dict(filter_properties, instance_type=flavor_p) if 'instance_type' in filter_properties:
flavor = filter_properties['instance_type']
flavor_p = objects_base.obj_to_primitive(flavor)
filter_properties = dict(filter_properties,
instance_type=flavor_p)
kw = {'instances': instances, 'image': image_p, kw = {'instances': instances, 'image': image_p,
'filter_properties': filter_properties, 'filter_properties': filter_properties,
'admin_password': admin_password, 'admin_password': admin_password,
'injected_files': injected_files, 'injected_files': injected_files,
'requested_networks': requested_networks, 'requested_networks': requested_networks,
'security_groups': security_groups} 'security_groups': security_groups}
if not self.client.can_send_version(version):
version = '1.9'
if not self.client.can_send_version('1.9'):
version = '1.8' version = '1.8'
kw['requested_networks'] = kw['requested_networks'].as_tuples() kw['requested_networks'] = kw['requested_networks'].as_tuples()
if not self.client.can_send_version('1.7'): if not self.client.can_send_version('1.7'):

View File

@ -60,7 +60,7 @@ QUOTAS = quota.QUOTAS
class SchedulerManager(manager.Manager): class SchedulerManager(manager.Manager):
"""Chooses a host to run instances on.""" """Chooses a host to run instances on."""
target = messaging.Target(version='3.0') target = messaging.Target(version='3.1')
def __init__(self, scheduler_driver=None, *args, **kwargs): def __init__(self, scheduler_driver=None, *args, **kwargs):
if not scheduler_driver: if not scheduler_driver:
@ -171,6 +171,13 @@ class SchedulerManager(manager.Manager):
The result should be a list of dicts with 'host', 'nodename' and The result should be a list of dicts with 'host', 'nodename' and
'limits' as keys. 'limits' as keys.
""" """
# TODO(melwitt): Remove this in version 4.0 of the RPC API
flavor = filter_properties.get('instance_type')
if flavor and not isinstance(flavor, objects.Flavor):
# Code downstream may expect extra_specs to be populated since it
# is receiving an object, so lookup the flavor to ensure this.
flavor = objects.Flavor.get_by_id(context, flavor['id'])
filter_properties = dict(filter_properties, instance_type=flavor)
dests = self.driver.select_destinations(context, request_spec, dests = self.driver.select_destinations(context, request_spec,
filter_properties) filter_properties)
return jsonutils.to_primitive(dests) return jsonutils.to_primitive(dests)

View File

@ -84,6 +84,8 @@ class SchedulerAPI(object):
existing methods in 3.x after that point should be done such that they existing methods in 3.x after that point should be done such that they
can handle the version_cap being set to 3.0. can handle the version_cap being set to 3.0.
* 3.1 - Made select_destinations() send flavor object
''' '''
VERSION_ALIASES = { VERSION_ALIASES = {
@ -103,10 +105,14 @@ class SchedulerAPI(object):
serializer=serializer) serializer=serializer)
def select_destinations(self, ctxt, request_spec, filter_properties): def select_destinations(self, ctxt, request_spec, filter_properties):
if 'instance_type' in filter_properties: version = '3.1'
flavor = filter_properties['instance_type'] if not self.client.can_send_version(version):
flavor_p = objects_base.obj_to_primitive(flavor) version = '3.0'
filter_properties = dict(filter_properties, instance_type=flavor_p) if 'instance_type' in filter_properties:
cctxt = self.client.prepare() flavor = filter_properties['instance_type']
flavor_p = objects_base.obj_to_primitive(flavor)
filter_properties = dict(filter_properties,
instance_type=flavor_p)
cctxt = self.client.prepare(version=version)
return cctxt.call(ctxt, 'select_destinations', return cctxt.call(ctxt, 'select_destinations',
request_spec=request_spec, filter_properties=filter_properties) request_spec=request_spec, filter_properties=filter_properties)

View File

@ -135,7 +135,7 @@ class CellsAPITestCase(test.NoDBTestCase):
'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.8') expected_args, version='1.30')
def test_get_capacities(self): def test_get_capacities(self):
capacity_info = {"capacity": "info"} capacity_info = {"capacity": "info"}

View File

@ -468,7 +468,7 @@ class ComputeRpcAPITestCase(test.TestCase):
admin_password='passwd', injected_files=None, admin_password='passwd', injected_files=None,
requested_networks=['network1'], security_groups=None, requested_networks=['network1'], security_groups=None,
block_device_mapping=None, node='node', limits=[], block_device_mapping=None, node='node', limits=[],
version='3.33') version='3.36')
@mock.patch('nova.utils.is_neutron', return_value=True) @mock.patch('nova.utils.is_neutron', return_value=True)
def test_build_and_run_instance_icehouse_compat(self, is_neutron): def test_build_and_run_instance_icehouse_compat(self, is_neutron):

View File

@ -1196,9 +1196,9 @@ class _BaseTaskTestCase(object):
inst = fake_instance.fake_db_instance(image_ref='image_ref') inst = fake_instance.fake_db_instance(image_ref='image_ref')
inst_obj = objects.Instance._from_db_object( inst_obj = objects.Instance._from_db_object(
self.context, objects.Instance(), inst, []) self.context, objects.Instance(), inst, [])
flavor = obj_base.obj_to_primitive(flavors.get_default_flavor()) flavor = flavors.get_default_flavor()
flavor['extra_specs'] = 'extra_specs' flavor.extra_specs = {'extra_specs': 'fake'}
request_spec = {'instance_type': flavor, request_spec = {'instance_type': obj_base.obj_to_primitive(flavor),
'instance_properties': {}} 'instance_properties': {}}
compute_utils.get_image_metadata( compute_utils.get_image_metadata(
self.context, self.conductor_manager.image_api, self.context, self.conductor_manager.image_api,
@ -1207,7 +1207,7 @@ class _BaseTaskTestCase(object):
scheduler_utils.build_request_spec( scheduler_utils.build_request_spec(
self.context, 'image', self.context, 'image',
[mox.IsA(objects.Instance)], [mox.IsA(objects.Instance)],
instance_type=flavor).AndReturn(request_spec) instance_type=mox.IsA(objects.Flavor)).AndReturn(request_spec)
scheduler_utils.setup_instance_group(self.context, request_spec, {}) scheduler_utils.setup_instance_group(self.context, request_spec, {})
@ -1222,7 +1222,7 @@ class _BaseTaskTestCase(object):
self.conductor_manager.compute_rpcapi.prep_resize( self.conductor_manager.compute_rpcapi.prep_resize(
self.context, 'image', mox.IsA(objects.Instance), self.context, 'image', mox.IsA(objects.Instance),
mox.IsA(dict), 'host1', [], request_spec=request_spec, mox.IsA(objects.Flavor), 'host1', [], request_spec=request_spec,
filter_properties=filter_properties, node=None) filter_properties=filter_properties, node=None)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -1630,8 +1630,9 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
self.context, None, None, True, True, None, None, None) self.context, None, None, True, True, None, None, None)
def test_migrate_server_fails_with_flavor(self): def test_migrate_server_fails_with_flavor(self):
flavor = flavors.get_flavor_by_name('m1.tiny')
self.assertRaises(NotImplementedError, self.conductor.migrate_server, self.assertRaises(NotImplementedError, self.conductor.migrate_server,
self.context, None, None, True, False, "dummy", None, None) self.context, None, None, True, False, flavor, None, None)
def _build_request_spec(self, instance): def _build_request_spec(self, instance):
return { return {

View File

@ -66,4 +66,5 @@ class SchedulerRpcAPITestCase(test.NoDBTestCase):
def test_select_destinations(self): def test_select_destinations(self):
self._test_scheduler_api('select_destinations', rpc_method='call', self._test_scheduler_api('select_destinations', rpc_method='call',
request_spec='fake_request_spec', request_spec='fake_request_spec',
filter_properties='fake_prop') filter_properties='fake_prop',
version='3.1')