From 6e8a094c48dc77fdfe68c72c7a09b7819710d4b6 Mon Sep 17 00:00:00 2001 From: chenxiao Date: Mon, 4 Nov 2013 15:02:12 +0800 Subject: [PATCH] Add status mapping for shutoff instance when resize Current code always map instance's status into Shutoff when getting status of resizing instance with power_state shutoff. This isn't consistent with active instance, we should add status mapping for power-off resizing instance. Closes-Bug: #1247106 Co-Authored-By: chenxiao Change-Id: Id4bff71b2c46ec9dccea6d8ac36eba273e48ea5d --- nova/api/openstack/common.py | 19 ++++++++---- .../openstack/compute/plugins/v3/servers.py | 2 +- nova/api/openstack/compute/servers.py | 2 +- .../compute/plugins/v3/test_servers.py | 27 +++++++++++++++-- .../api/openstack/compute/test_servers.py | 27 +++++++++++++++-- nova/tests/api/openstack/test_common.py | 29 ++++++++++++++++--- 6 files changed, 90 insertions(+), 16 deletions(-) diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index 5c86215bdaf1..ba3cb075db60 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -76,6 +76,10 @@ _STATE_MAP = { }, vm_states.STOPPED: { 'default': 'SHUTOFF', + task_states.RESIZE_PREP: 'RESIZE', + task_states.RESIZE_MIGRATING: 'RESIZE', + task_states.RESIZE_MIGRATED: 'RESIZE', + task_states.RESIZE_FINISH: 'RESIZE', }, vm_states.RESIZED: { 'default': 'VERIFY_RESIZE', @@ -124,16 +128,19 @@ def status_from_state(vm_state, task_state='default'): def task_and_vm_state_from_status(status): - """Map the server status string to a vm state and list of task states.""" - vm_state = '' - task_states = [] + """Map the server status string to list of vm states and + list of task states. + """ + vm_states = set() + task_states = set() for state, task_map in _STATE_MAP.iteritems(): for task_state, mapped_state in task_map.iteritems(): status_string = mapped_state if status.lower() == status_string.lower(): - vm_state = state - task_states.append(task_state) - return vm_state, task_states + vm_states.add(state) + task_states.add(task_state) + # Add sort to avoid different order on set in Python 3 + return sorted(vm_states), sorted(task_states) def get_pagination_params(request): diff --git a/nova/api/openstack/compute/plugins/v3/servers.py b/nova/api/openstack/compute/plugins/v3/servers.py index 693ad60bcc49..3104a4d57517 100644 --- a/nova/api/openstack/compute/plugins/v3/servers.py +++ b/nova/api/openstack/compute/plugins/v3/servers.py @@ -532,7 +532,7 @@ class ServersController(wsgi.Controller): if 'changes_since' in search_opts: search_opts['changes-since'] = search_opts.pop('changes_since') - if search_opts.get("vm_state") == "deleted": + if search_opts.get("vm_state") == ['deleted']: if context.is_admin: search_opts['deleted'] = True else: diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index 1495ba68bef2..9ccdb1242e49 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -550,7 +550,7 @@ class Controller(wsgi.Controller): # No 'changes-since', so we only want non-deleted servers search_opts['deleted'] = False - if search_opts.get("vm_state") == "deleted": + if search_opts.get("vm_state") == ['deleted']: if context.is_admin: search_opts['deleted'] = True else: diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_servers.py b/nova/tests/api/openstack/compute/plugins/v3/test_servers.py index 95f446888e12..2459b127a009 100644 --- a/nova/tests/api/openstack/compute/plugins/v3/test_servers.py +++ b/nova/tests/api/openstack/compute/plugins/v3/test_servers.py @@ -912,7 +912,7 @@ class ServersControllerTest(ControllerTest): limit=None, marker=None, want_objects=False): self.assertIsNotNone(search_opts) self.assertIn('vm_state', search_opts) - self.assertEqual(search_opts['vm_state'], vm_states.ACTIVE) + self.assertEqual(search_opts['vm_state'], [vm_states.ACTIVE]) db_list = [fakes.stub_instance(100, uuid=server_uuid)] return instance_obj._make_instance_list( context, instance_obj.InstanceList(), db_list, FIELDS) @@ -948,6 +948,29 @@ class ServersControllerTest(ControllerTest): self.assertEqual(len(servers), 1) self.assertEqual(servers[0]['id'], server_uuid) + def test_get_servers_resize_status(self): + # Test when resize status, it maps list of vm states. + server_uuid = str(uuid.uuid4()) + + def fake_get_all(compute_self, context, search_opts=None, + sort_key=None, sort_dir='desc', + limit=None, marker=None, want_objects=False): + self.assertIn('vm_state', search_opts) + self.assertEqual(search_opts['vm_state'], + [vm_states.ACTIVE, vm_states.STOPPED]) + + db_list = [fakes.stub_instance(100, uuid=server_uuid)] + return instance_obj._make_instance_list( + context, instance_obj.InstanceList(), db_list, FIELDS) + + self.stubs.Set(compute_api.API, 'get_all', fake_get_all) + + req = fakes.HTTPRequestV3.blank('/servers?status=resize') + + servers = self.controller.detail(req)['servers'] + self.assertEqual(len(servers), 1) + self.assertEqual(servers[0]['id'], server_uuid) + def test_get_servers_invalid_status(self): # Test getting servers by invalid status. req = fakes.HTTPRequestV3.blank('/servers?status=baloney', @@ -968,7 +991,7 @@ class ServersControllerTest(ControllerTest): sort_key=None, sort_dir='desc', limit=None, marker=None, want_objects=False): self.assertIn('vm_state', search_opts) - self.assertEqual(search_opts['vm_state'], 'deleted') + self.assertEqual(search_opts['vm_state'], ['deleted']) db_list = [fakes.stub_instance(100, uuid=server_uuid)] return instance_obj._make_instance_list( diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py index 50b8f23be45a..24dbb263c168 100644 --- a/nova/tests/api/openstack/compute/test_servers.py +++ b/nova/tests/api/openstack/compute/test_servers.py @@ -854,7 +854,7 @@ class ServersControllerTest(ControllerTest): limit=None, marker=None, want_objects=False): self.assertIsNotNone(search_opts) self.assertIn('vm_state', search_opts) - self.assertEqual(search_opts['vm_state'], vm_states.ACTIVE) + self.assertEqual(search_opts['vm_state'], [vm_states.ACTIVE]) db_list = [fakes.stub_instance(100, uuid=server_uuid)] return instance_obj._make_instance_list( context, instance_obj.InstanceList(), db_list, FIELDS) @@ -890,6 +890,29 @@ class ServersControllerTest(ControllerTest): self.assertEqual(len(servers), 1) self.assertEqual(servers[0]['id'], server_uuid) + def test_get_servers_resize_status(self): + # Test when resize status, it maps list of vm states. + server_uuid = str(uuid.uuid4()) + + def fake_get_all(compute_self, context, search_opts=None, + sort_key=None, sort_dir='desc', + limit=None, marker=None, want_objects=False): + self.assertIn('vm_state', search_opts) + self.assertEqual(search_opts['vm_state'], + [vm_states.ACTIVE, vm_states.STOPPED]) + + db_list = [fakes.stub_instance(100, uuid=server_uuid)] + return instance_obj._make_instance_list( + context, instance_obj.InstanceList(), db_list, FIELDS) + + self.stubs.Set(compute_api.API, 'get_all', fake_get_all) + + req = fakes.HTTPRequest.blank('/fake/servers?status=resize') + + servers = self.controller.detail(req)['servers'] + self.assertEqual(len(servers), 1) + self.assertEqual(servers[0]['id'], server_uuid) + def test_get_servers_invalid_status(self): # Test getting servers by invalid status. req = fakes.HTTPRequest.blank('/fake/servers?status=baloney', @@ -910,7 +933,7 @@ class ServersControllerTest(ControllerTest): sort_key=None, sort_dir='desc', limit=None, marker=None, want_objects=False): self.assertIn('vm_state', search_opts) - self.assertEqual(search_opts['vm_state'], 'deleted') + self.assertEqual(search_opts['vm_state'], ['deleted']) db_list = [fakes.stub_instance(100, uuid=server_uuid)] return instance_obj._make_instance_list( diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 4c230ba8f756..5ae588bbbead 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -26,6 +26,8 @@ import xml.dom.minidom as minidom from nova.api.openstack import common from nova.api.openstack import xmlutil +from nova.compute import task_states +from nova.compute import vm_states from nova import exception from nova import test from nova.tests import utils @@ -349,11 +351,30 @@ class MiscFunctionsTest(test.TestCase): self.assertIsNone(common.check_img_metadata_properties_quota(ctxt, metadata5)) + def test_status_from_state(self): + for vm_state in (vm_states.ACTIVE, vm_states.STOPPED): + for task_state in (task_states.RESIZE_PREP, + task_states.RESIZE_MIGRATING, + task_states.RESIZE_MIGRATED, + task_states.RESIZE_FINISH): + actual = common.status_from_state(vm_state, task_state) + expected = 'RESIZE' + self.assertEqual(expected, actual) + def test_task_and_vm_state_from_status(self): - fixture = 'reboot' - actual = common.task_and_vm_state_from_status(fixture) - excepted = 'active', ['rebooting'] - self.assertEqual(actual, excepted) + fixture1 = 'reboot' + actual = common.task_and_vm_state_from_status(fixture1) + expected = [vm_states.ACTIVE], [task_states.REBOOTING] + self.assertEqual(expected, actual) + + fixture2 = 'resize' + actual = common.task_and_vm_state_from_status(fixture2) + expected = ([vm_states.ACTIVE, vm_states.STOPPED], + [task_states.RESIZE_FINISH, + task_states.RESIZE_MIGRATED, + task_states.RESIZE_MIGRATING, + task_states.RESIZE_PREP]) + self.assertEqual(expected, actual) class MetadataXMLDeserializationTest(test.TestCase):