From 74698ac6cb9cfd8ce69623562f8b4fe0a94a46b0 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Tue, 20 Nov 2012 17:13:29 -0500 Subject: Add migration_update to conductor. This patch adds a migration_update method to the conductor API. This is used by the compute manager to push off db access to nova-conductor. The only field that compute was updating was the status, so that is the only field allowed by the API. Instead of just sending the miration_id to the conductor, we are sending all of the migration data. This is done in the spirit of 'no-db-messaging'. While no other data is needed right now, it's easier to send it all now than have to change the API later. Change-Id: Ic3150fbc6d5e7b0c9e41681950a7424129cbc968 --- nova/compute/manager.py | 30 ++++++++++++++---------------- nova/conductor/api.py | 7 +++++++ nova/conductor/manager.py | 8 +++++++- nova/conductor/rpcapi.py | 8 ++++++++ nova/tests/compute/test_compute.py | 8 ++++---- nova/tests/conductor/test_conductor.py | 10 ++++++++++ 6 files changed, 50 insertions(+), 21 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 9a17e808c..a0835d107 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1873,9 +1873,8 @@ class ComputeManager(manager.SchedulerDependentManager): reservations=None, migration=None, migration_id=None, instance_type=None): """Starts the migration of a running instance to another host.""" - elevated = context.elevated() if not migration: - migration = self.db.migration_get(elevated, migration_id) + migration = self.db.migration_get(context.elevated(), migration_id) with self._error_out_instance_on_exception(context, instance['uuid'], reservations): if not instance_type: @@ -1884,9 +1883,8 @@ class ComputeManager(manager.SchedulerDependentManager): network_info = self._get_instance_nw_info(context, instance) - self.db.migration_update(elevated, - migration['id'], - {'status': 'migrating'}) + migration = self.conductor_api.migration_update(context, + migration, 'migrating') instance = self._instance_update(context, instance['uuid'], task_state=task_states.RESIZE_MIGRATING, @@ -1908,9 +1906,8 @@ class ComputeManager(manager.SchedulerDependentManager): self.network_api.migrate_instance_start(context, instance, migration) - migration = self.db.migration_update(elevated, - migration['id'], - {'status': 'post-migrating'}) + migration = self.conductor_api.migration_update(context, + migration, 'post-migrating') instance = self._instance_update(context, instance['uuid'], host=migration['dest_compute'], @@ -1994,8 +1991,8 @@ class ComputeManager(manager.SchedulerDependentManager): expected_task_state=task_states. RESIZE_FINISH) - self.db.migration_update(context.elevated(), migration['id'], - {'status': 'finished'}) + migration = self.conductor_api.migration_update(context, + migration, 'finished') self._notify_about_instance_usage( context, instance, "finish_resize.end", @@ -2801,12 +2798,13 @@ class ComputeManager(manager.SchedulerDependentManager): "older than %(confirm_window)d seconds"), migrations_info) - def _set_migration_to_error(migration_id, reason, **kwargs): + def _set_migration_to_error(migration, reason, **kwargs): + migration_id = migration['id'] msg = _("Setting migration %(migration_id)s to error: " "%(reason)s") % locals() LOG.warn(msg, **kwargs) - self.db.migration_update(context, migration_id, - {'status': 'error'}) + self.conductor_api.migration_update(context, migration, + 'error') for migration in migrations: migration_id = migration['id'] @@ -2819,11 +2817,11 @@ class ComputeManager(manager.SchedulerDependentManager): instance_uuid) except exception.InstanceNotFound: reason = _("Instance %(instance_uuid)s not found") - _set_migration_to_error(migration_id, reason % locals()) + _set_migration_to_error(migration, reason % locals()) continue if instance['vm_state'] == vm_states.ERROR: reason = _("In ERROR state") - _set_migration_to_error(migration_id, reason % locals(), + _set_migration_to_error(migration, reason % locals(), instance=instance) continue vm_state = instance['vm_state'] @@ -2831,7 +2829,7 @@ class ComputeManager(manager.SchedulerDependentManager): if vm_state != vm_states.RESIZED or task_state is not None: reason = _("In states %(vm_state)s/%(task_state)s, not" "RESIZED/None") - _set_migration_to_error(migration_id, reason % locals(), + _set_migration_to_error(migration, reason % locals(), instance=instance) continue try: diff --git a/nova/conductor/api.py b/nova/conductor/api.py index cef5d3501..43d8fd0bc 100644 --- a/nova/conductor/api.py +++ b/nova/conductor/api.py @@ -47,6 +47,9 @@ class LocalAPI(object): """Perform an instance update in the database""" return self._manager.instance_update(context, instance_uuid, updates) + def migration_update(self, context, migration, status): + return self._manager.migration_update(context, migration, status) + class API(object): """Conductor API that does updates via RPC to the ConductorManager""" @@ -58,3 +61,7 @@ class API(object): """Perform an instance update in the database""" return self.conductor_rpcapi.instance_update(context, instance_uuid, updates) + + def migration_update(self, context, migration, status): + return self.conductor_rpcapi.migration_update(context, migration, + status) diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 18fc1149b..6270fb241 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -35,7 +35,7 @@ allowed_updates = ['task_state', 'vm_state', 'expected_task_state', class ConductorManager(manager.SchedulerDependentManager): """Mission: TBD""" - RPC_API_VERSION = '1.0' + RPC_API_VERSION = '1.1' def __init__(self, *args, **kwargs): super(ConductorManager, self).__init__(service_name='conductor', @@ -51,3 +51,9 @@ class ConductorManager(manager.SchedulerDependentManager): context, instance_uuid, updates) notifications.send_update(context, old_ref, instance_ref) return jsonutils.to_primitive(instance_ref) + + def migration_update(self, context, migration, status): + migration_ref = self.db.migration_update(context.elevated(), + migration['id'], + {'status': status}) + return jsonutils.to_primitive(migration_ref) diff --git a/nova/conductor/rpcapi.py b/nova/conductor/rpcapi.py index 29055f76b..ae9ee47e2 100644 --- a/nova/conductor/rpcapi.py +++ b/nova/conductor/rpcapi.py @@ -15,6 +15,7 @@ """Client side of the conductor RPC API""" from nova.openstack.common import cfg +from nova.openstack.common import jsonutils import nova.openstack.common.rpc.proxy CONF = cfg.CONF @@ -26,6 +27,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): API version history: 1.0 - Initial version. + 1.1 - Added migration_update """ BASE_RPC_API_VERSION = '1.0' @@ -40,3 +42,9 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): self.make_msg('instance_update', instance_uuid=instance_uuid, updates=updates)) + + def migration_update(self, context, migration, status): + migration_p = jsonutils.to_primitive(migration) + msg = self.make_msg('migration_update', migration=migration_p, + status=status) + return self.call(context, msg) diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 32cd3ca3e..96d1f4250 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -2754,10 +2754,10 @@ class ComputeTestCase(BaseTestCase): self.assertEqual(dest_compute, CONF.host) return migrations - def fake_migration_update(context, migration_id, values): + def fake_migration_update(context, m, status): for migration in migrations: - if migration['id'] == migration_id and 'status' in values: - migration['status'] = values['status'] + if migration['id'] == m['id']: + migration['status'] = status def fake_confirm_resize(context, instance): # raise exception for 'fake_uuid4' to check migration status @@ -2772,7 +2772,7 @@ class ComputeTestCase(BaseTestCase): fake_instance_get_by_uuid) self.stubs.Set(db, 'migration_get_unconfirmed_by_dest_compute', fake_migration_get_unconfirmed_by_dest_compute) - self.stubs.Set(db, 'migration_update', + self.stubs.Set(self.compute.conductor_api, 'migration_update', fake_migration_update) self.stubs.Set(self.compute.compute_api, 'confirm_resize', fake_confirm_resize) diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py index e3138fd34..d3c555822 100644 --- a/nova/tests/conductor/test_conductor.py +++ b/nova/tests/conductor/test_conductor.py @@ -24,6 +24,7 @@ from nova import context from nova import db from nova.db.sqlalchemy import models from nova import notifications +from nova.openstack.common import jsonutils from nova import test @@ -88,6 +89,15 @@ class ConductorTestCase(BaseTestCase): self.assertRaises(KeyError, self._do_update, 'any-uuid', foobar=1) + def test_migration_update(self): + migration = db.migration_create(self.context.elevated(), + {'instance_uuid': 'fake-uuid', + 'status': 'migrating'}) + migration_p = jsonutils.to_primitive(migration) + migration = self.conductor.migration_update(self.context, migration_p, + 'finished') + self.assertEqual(migration['status'], 'finished') + class ConductorRPCAPITestCase(ConductorTestCase): """Conductor RPC API Tests""" -- cgit