From 0130bb3d14e9e2db800ea0b15a48570085989521 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Fri, 8 Jul 2011 10:59:17 -0500 Subject: First take at migrations. --- nova/api/openstack/servers.py | 10 +++++++++- nova/compute/api.py | 17 ++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index fc1ab8d46..eacc2109f 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -176,7 +176,7 @@ class Controller(object): 'confirmResize': self._action_confirm_resize, 'revertResize': self._action_revert_resize, 'rebuild': self._action_rebuild, - } + 'migrate': self._action_migrate} for key in actions.keys(): if key in body: @@ -220,6 +220,14 @@ class Controller(object): return faults.Fault(exc.HTTPUnprocessableEntity()) return exc.HTTPAccepted() + def _action_migrate(self, input_dict, req, id): + try: + self.compute_api.resize(req.environ['nova.context'], id) + except Exception, e: + LOG.exception(_("Error in migrate %s"), e) + return faults.Fault(exc.HTTPBadRequest()) + return exc.HTTPAccepted() + @scheduler_api.redirect_handler def lock(self, req, id): """ diff --git a/nova/compute/api.py b/nova/compute/api.py index 28459dc75..b497a6550 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -855,13 +855,19 @@ class API(base.Base): self.db.instance_update(context, instance_id, {'host': migration_ref['dest_compute'], }) - def resize(self, context, instance_id, flavor_id): + def resize(self, context, instance_id, flavor_id=None): """Resize a running instance.""" instance = self.db.instance_get(context, instance_id) current_instance_type = instance['instance_type'] - new_instance_type = self.db.instance_type_get_by_flavor_id( - context, flavor_id) + # If flavor_id is not provided, only migrate the instance. + if not flavor_id: + LOG.debug(_("flavor_id is None. Assuming migration.")) + new_instance_type = current_instance_type + else: + new_instance_type = self.db.instance_type_get_by_flavor_id( + context, flavor_id) + current_instance_type_name = current_instance_type['name'] new_instance_type_name = new_instance_type['name'] LOG.debug(_("Old instance type %(current_instance_type_name)s, " @@ -875,7 +881,8 @@ class API(base.Base): if current_memory_mb > new_memory_mb: raise exception.ApiError(_("Invalid flavor: cannot downsize" "instances")) - if current_memory_mb == new_memory_mb: + + if (current_memory_mb == new_memory_mb) and flavor_id: raise exception.ApiError(_("Invalid flavor: cannot use" "the same flavor. ")) @@ -883,7 +890,7 @@ class API(base.Base): {"method": "prep_resize", "args": {"topic": FLAGS.compute_topic, "instance_id": instance_id, - "flavor_id": flavor_id}}) + "flavor_id": new_instance_type['id']}}) @scheduler_api.reroute_compute("add_fixed_ip") def add_fixed_ip(self, context, instance_id, network_id): -- cgit From ce0bdf7de31dcee53ee5ccdc0cca57333c6b6bc1 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Fri, 8 Jul 2011 11:47:34 -0500 Subject: Added unit tests. --- nova/tests/api/openstack/test_servers.py | 17 +++++++++++++++++ nova/tests/test_compute.py | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 0cb16b4c0..1f369c4c8 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -1557,6 +1557,23 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) + def test_migrate_server(self): + """This is basically the same as resize, only we provide the `migrate` + attribute in the body's dict. + """ + req = self.webreq('/1/action', 'POST', dict(migrate=None)) + + self.resize_called = False + + def resize_mock(*args): + self.resize_called = True + + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + def test_shutdown_status(self): new_server = return_server_with_power_state(power_state.SHUTDOWN) self.stubs.Set(nova.db.api, 'instance_get', new_server) diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 45cd2f764..04bb194d5 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -532,6 +532,14 @@ class ComputeTestCase(test.TestCase): self.context, instance_id, 1) self.compute.terminate_instance(self.context, instance_id) + def test_migrate(self): + context = self.context.elevated() + instance_id = self._create_instance() + self.compute.run_instance(self.context, instance_id) + # Migrate simply calls resize() without a flavor_id. + self.compute_api.resize(context, instance_id, None) + self.compute.terminate_instance(context, instance_id) + def _setup_other_managers(self): self.volume_manager = utils.import_object(FLAGS.volume_manager) self.network_manager = utils.import_object(FLAGS.network_manager) -- cgit From 93fe8b7844561f3872aa5afa5e85e7baf25f3ff4 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Fri, 8 Jul 2011 14:50:52 -0500 Subject: Updated resize docstring. --- nova/compute/api.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index 5e024f0ac..edd1a4d64 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -856,7 +856,12 @@ class API(base.Base): {'host': migration_ref['dest_compute'], }) def resize(self, context, instance_id, flavor_id=None): - """Resize a running instance.""" + """Resize (ie, migrate) a running instance. + + If flavor_id is None, the process is considered a migration, keeping + the original flavor_id. If flavor_id is not None, the instance should + be migrated to a new host and resized to the new flavor_id. + """ instance = self.db.instance_get(context, instance_id) current_instance_type = instance['instance_type'] -- cgit