Make resize api of compute manager to send flavor object

This code change implements the conversion of flavor to use object. Rpcapi of
compute manager sends objects for new version and sents primitivized data for
older versions.

Related to blueprint liberty-objects

Change-Id: I11a28cd3b2eb98b42d78f9327ed6b38dc2bc8f30
This commit is contained in:
Qin Zhao 2015-03-06 03:47:32 +08:00
parent e1613d1bbe
commit 5bd81ab5fb
5 changed files with 114 additions and 36 deletions

View File

@ -644,7 +644,7 @@ class ComputeVirtAPI(virtapi.VirtAPI):
class ComputeManager(manager.Manager):
"""Manages the running instances from creation to destruction."""
target = messaging.Target(version='4.0')
target = messaging.Target(version='4.1')
# How long to wait in seconds before re-issuing a shutdown
# signal to a instance during power off. The overall
@ -3473,7 +3473,7 @@ class ComputeManager(manager.Manager):
same_host = instance.host == self.host
# if the flavor IDs match, it's migrate; otherwise resize
if same_host and instance_type['id'] == instance['instance_type_id']:
if same_host and instance_type.id == instance['instance_type_id']:
# check driver whether support migrate to same host
if not self.driver.capabilities['supports_migrate_to_same_host']:
raise exception.UnableToMigrateToSelf(
@ -3547,8 +3547,8 @@ class ComputeManager(manager.Manager):
filter_properties)
finally:
extra_usage_info = dict(
new_instance_type=instance_type['name'],
new_instance_type_id=instance_type['id'])
new_instance_type=instance_type.name,
new_instance_type_id=instance_type.id)
self._notify_about_instance_usage(
context, instance, "resize.prep.end",
@ -3612,6 +3612,7 @@ class ComputeManager(manager.Manager):
instance=instance)
with self._error_out_instance_on_exception(context, instance,
quotas=quotas):
# TODO(chaochin) Remove this until v5 RPC API
# Code downstream may expect extra_specs to be populated since it
# is receiving an object, so lookup the flavor to ensure this.
if (not instance_type or

View File

@ -297,6 +297,7 @@ class ComputeAPI(object):
3.x for Juno compatibility. All new changes should go against 4.x.
* 4.0 - Remove 3.x compatibility
* 4.1 - Make prep_resize() and resize_instance() send Flavor object
'''
VERSION_ALIASES = {
@ -563,18 +564,20 @@ class ComputeAPI(object):
reservations=None, request_spec=None,
filter_properties=None, node=None,
clean_shutdown=True):
# TODO(danms): This needs to be fixed for objects!
instance_type_p = jsonutils.to_primitive(instance_type)
image_p = jsonutils.to_primitive(image)
msg_args = {'instance': instance,
'instance_type': instance_type_p,
'instance_type': instance_type,
'image': image_p,
'reservations': reservations,
'request_spec': request_spec,
'filter_properties': filter_properties,
'node': node,
'clean_shutdown': clean_shutdown}
version = '4.0'
version = '4.1'
if not self.client.can_send_version(version):
version = '4.0'
msg_args['instance_type'] = objects_base.obj_to_primitive(
instance_type)
cctxt = self.client.prepare(server=host, version=version)
cctxt.cast(ctxt, 'prep_resize', **msg_args)
@ -660,14 +663,16 @@ class ComputeAPI(object):
def resize_instance(self, ctxt, instance, migration, image, instance_type,
reservations=None, clean_shutdown=True):
# TODO(danms): This needs to be fixed for objects!
instance_type_p = jsonutils.to_primitive(instance_type)
msg_args = {'instance': instance, 'migration': migration,
'image': image, 'reservations': reservations,
'instance_type': instance_type_p,
'instance_type': instance_type,
'clean_shutdown': clean_shutdown,
}
version = '4.0'
version = '4.1'
if not self.client.can_send_version(version):
msg_args['instance_type'] = objects_base.obj_to_primitive(
instance_type)
version = '4.0'
cctxt = self.client.prepare(server=_compute_host(None, instance),
version=version)
cctxt.cast(ctxt, 'resize_instance', **msg_args)

View File

@ -4759,7 +4759,6 @@ class ComputeTestCase(BaseTestCase):
timeutils.set_time_override(old_time)
instance = self._create_fake_instance_obj()
new_type = flavors.get_flavor_by_name('m1.small')
new_type = jsonutils.to_primitive(new_type)
new_type_id = new_type['id']
flavor_id = new_type['flavorid']
self.compute.build_and_run_instance(self.context, instance, {}, {}, {},
@ -5093,12 +5092,10 @@ class ComputeTestCase(BaseTestCase):
instance.power_state = p_state
instance.save()
new_instance_type_ref = db.flavor_get_by_flavor_id(
self.context, 3)
new_instance_type_p = jsonutils.to_primitive(new_instance_type_ref)
new_instance_type_ref = flavors.get_flavor_by_flavor_id(3)
self.compute.prep_resize(self.context,
instance=instance,
instance_type=new_instance_type_p,
instance_type=new_instance_type_ref,
image={}, reservations=reservations, request_spec={},
filter_properties={}, node=None, clean_shutdown=True)
@ -5115,7 +5112,7 @@ class ComputeTestCase(BaseTestCase):
migration=migration,
image={},
reservations=[],
instance_type=new_instance_type_p,
instance_type=new_instance_type_ref,
clean_shutdown=True)
self.compute.finish_resize(self.context,
migration=migration, reservations=[],
@ -5198,12 +5195,10 @@ class ComputeTestCase(BaseTestCase):
instance.vm_state = old_vm_state
instance.save()
new_instance_type_ref = db.flavor_get_by_flavor_id(
self.context, 3)
new_instance_type_p = jsonutils.to_primitive(new_instance_type_ref)
new_instance_type_ref = flavors.get_flavor_by_flavor_id(3)
self.compute.prep_resize(self.context,
instance=instance,
instance_type=new_instance_type_p,
instance_type=new_instance_type_ref,
image={}, reservations=reservations, request_spec={},
filter_properties={}, node=None,
clean_shutdown=True)
@ -5221,15 +5216,14 @@ class ComputeTestCase(BaseTestCase):
migration=migration,
image={},
reservations=[],
instance_type=new_instance_type_p,
instance_type=new_instance_type_ref,
clean_shutdown=True)
self.compute.finish_resize(self.context,
migration=migration, reservations=[],
disk_info={}, image={}, instance=instance)
# Prove that the instance size is now the new size
instance_type_ref = db.flavor_get(self.context,
instance['instance_type_id'])
instance_type_ref = flavors.get_flavor_by_flavor_id(3)
self.assertEqual(instance_type_ref['flavorid'], '3')
instance.task_state = task_states.RESIZE_REVERTING

View File

@ -27,6 +27,7 @@ from nova import context
from nova.objects import block_device as objects_block_dev
from nova import test
from nova.tests.unit import fake_block_device
from nova.tests.unit import fake_flavor
from nova.tests.unit import fake_instance
CONF = cfg.CONF
@ -37,10 +38,14 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
def setUp(self):
super(ComputeRpcAPITestCase, self).setUp()
self.context = context.get_admin_context()
self.fake_flavor_obj = fake_flavor.fake_flavor_obj(self.context)
self.fake_flavor = jsonutils.to_primitive(self.fake_flavor_obj)
instance_attr = {'host': 'fake_host',
'instance_type_id': 1}
'instance_type_id': self.fake_flavor_obj['id'],
'instance_type': self.fake_flavor_obj}
self.fake_instance_obj = fake_instance.fake_instance_obj(self.context,
**instance_attr)
self.fake_instance = jsonutils.to_primitive(self.fake_instance_obj)
self.fake_volume_bdm = objects_block_dev.BlockDeviceMapping(
**fake_block_device.FakeDbBlockDeviceDict(
{'source_type': 'volume', 'destination_type': 'volume',
@ -48,7 +53,7 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
'volume_id': 'fake-volume-id'}))
def _test_compute_api(self, method, rpc_method,
assert_dict=False, **kwargs):
expected_args=None, **kwargs):
ctxt = context.RequestContext('fake_user', 'fake_project')
rpcapi = kwargs.pop('rpcapi_class', compute_rpcapi.ComputeAPI)()
@ -60,15 +65,13 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
expected_version = kwargs.pop('version', base_version)
expected_kwargs = kwargs.copy()
if expected_args:
expected_kwargs.update(expected_args)
if 'host_param' in expected_kwargs:
expected_kwargs['host'] = expected_kwargs.pop('host_param')
else:
expected_kwargs.pop('host', None)
if assert_dict:
expected_kwargs['instance'] = jsonutils.to_primitive(
expected_kwargs['instance'])
cast_and_call = ['confirm_resize', 'stop_instance']
if rpc_method == 'call' and method in cast_and_call:
if method == 'confirm_resize':
@ -187,8 +190,9 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
instance=self.fake_instance_obj, version='4.0')
def test_get_instance_diagnostics(self):
expected_args = {'instance': self.fake_instance}
self._test_compute_api('get_instance_diagnostics', 'call',
assert_dict=True, instance=self.fake_instance_obj,
expected_args, instance=self.fake_instance_obj,
version='4.0')
def test_get_vnc_console(self):
@ -265,7 +269,18 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
def test_prep_resize(self):
self._test_compute_api('prep_resize', 'cast',
instance=self.fake_instance_obj, instance_type='fake_type',
instance=self.fake_instance_obj,
instance_type=self.fake_flavor_obj,
image='fake_image', host='host',
reservations=list('fake_res'),
request_spec='fake_spec',
filter_properties={'fakeprop': 'fakeval'},
node='node', clean_shutdown=True, version='4.1')
self.flags(compute='4.0', group='upgrade_levels')
expected_args = {'instance_type': self.fake_flavor}
self._test_compute_api('prep_resize', 'cast', expected_args,
instance=self.fake_instance_obj,
instance_type=self.fake_flavor_obj,
image='fake_image', host='host',
reservations=list('fake_res'),
request_spec='fake_spec',
@ -306,9 +321,10 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
security_group_id='id', host='host', version='4.0')
def test_refresh_instance_security_rules(self):
expected_args = {'instance': self.fake_instance}
self._test_compute_api('refresh_instance_security_rules', 'cast',
host='fake_host', instance=self.fake_instance_obj,
version='4.0', assert_dict=True)
expected_args, host='fake_host',
instance=self.fake_instance_obj, version='4.0')
def test_remove_aggregate_host(self):
self._test_compute_api('remove_aggregate_host', 'cast',
@ -338,7 +354,14 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
def test_resize_instance(self):
self._test_compute_api('resize_instance', 'cast',
instance=self.fake_instance_obj, migration={'id': 'fake_id'},
image='image', instance_type={'id': 1},
image='image', instance_type=self.fake_flavor_obj,
reservations=list('fake_res'),
clean_shutdown=True, version='4.1')
self.flags(compute='4.0', group='upgrade_levels')
expected_args = {'instance_type': self.fake_flavor}
self._test_compute_api('resize_instance', 'cast', expected_args,
instance=self.fake_instance_obj, migration={'id': 'fake_id'},
image='image', instance_type=self.fake_flavor_obj,
reservations=list('fake_res'),
clean_shutdown=True, version='4.0')

View File

@ -0,0 +1,55 @@
# Copyright 2015 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
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from nova import objects
from nova.objects import fields
def fake_db_flavor(**updates):
db_flavor = {
'id': 1,
'name': 'fake_flavor',
'memory_mb': 1024,
'vcpus': 1,
'root_gb': 100,
'ephemeral_gb': 0,
'flavorid': 'abc',
'swap': 0,
'disabled': False,
'is_public': True,
'extra_specs': {},
'projects': []
}
for name, field in objects.Flavor.fields.items():
if name in db_flavor:
continue
if field.nullable:
db_flavor[name] = None
elif field.default != fields.UnspecifiedDefault:
db_flavor[name] = field.default
else:
raise Exception('fake_db_flavor needs help with %s' % name)
if updates:
db_flavor.update(updates)
return db_flavor
def fake_flavor_obj(context, **updates):
expected_attrs = updates.pop('expected_attrs', None)
return objects.Flavor._from_db_object(context,
objects.Flavor(), fake_db_flavor(**updates),
expected_attrs=expected_attrs)