From 5cbf4c74e680aeabf7d20903b8d6875a2bdda479 Mon Sep 17 00:00:00 2001 From: Dongfeng Huang Date: Wed, 12 Apr 2017 15:28:08 +0800 Subject: [PATCH] Synchronized patch: Nova API-Gateway Server Action Support(part2) 1. What is the problem Originally this patch was committed to the Tricircle and provided server action support, but after Tricircle narrowed its scope to networking automation across Neutron, these API-Gateway features implemented in this patch were no longer used. However Trio2o needs these functions, so we plan to synchronize this patch from Gerrit to Trio2o. You can find the old patch on Gerrit here[1]. The current Nova API-Gateway does not support following server actions: reboot: Reboot a server resize: Resize a server confirmResize: Confirm a pending resize action for a server revertResize: Cancel and revert a pending resize action for a server os-resetState: Reset the state of a server 2. What is the solution to the problem Implement the above server actions. 3. What the features need to be implemented to the Trio2o to realize the solution Add the above server actions. [1] https://review.openstack.org/#/c/369958 Change-Id: If0feb3d31fc7877ead84424c7329051857f23628 --- trio2o/common/constants.py | 3 + trio2o/nova_apigw/controllers/action.py | 96 +++----- trio2o/tempestplugin/tempest_compute.sh | 29 ++- .../nova_apigw/controllers/test_action.py | 214 ++++++++++++++---- 4 files changed, 218 insertions(+), 124 deletions(-) diff --git a/trio2o/common/constants.py b/trio2o/common/constants.py index f66d00b..b9b38b5 100644 --- a/trio2o/common/constants.py +++ b/trio2o/common/constants.py @@ -97,3 +97,6 @@ NOVA_MICRO_VERSION_PREFIX = 'compute' # support nova version range NOVA_APIGW_MIN_VERSION = '2.1' NOVA_APIGW_MAX_VERSION = '2.36' + +# server action url(part url) +SERVER_ACTION_URL = '/servers/%s/action' diff --git a/trio2o/nova_apigw/controllers/action.py b/trio2o/nova_apigw/controllers/action.py index 6daf56b..65838a7 100644 --- a/trio2o/nova_apigw/controllers/action.py +++ b/trio2o/nova_apigw/controllers/action.py @@ -36,20 +36,25 @@ class ActionController(rest.RestController): self.server_id = server_id self.clients = {constants.TOP: t_client.Client()} self.handle_map = { - 'os-start': self._handle_start, - 'os-stop': self._handle_stop, - 'forceDelete': self._handle_force_delete, - 'lock': self._handle_lock, - 'unlock': self._handle_unlock, - 'pause': self._handle_pause, - 'unpause': self._handle_unpause, - 'resume': self._handle_resume, - 'suspend': self._handle_suspend, - 'shelve': self._handle_shelve, - 'unshelve': self._handle_unshelve, - 'shelveOffload': self._handle_shelve_offload, - 'migrate': self._handle_migrate, - 'trigger_crash_dump': self._handle_trigger_crash_dump + 'os-start': self._handle_action, + 'os-stop': self._handle_action, + 'forceDelete': self._handle_action, + 'lock': self._handle_action, + 'unlock': self._handle_action, + 'pause': self._handle_action, + 'unpause': self._handle_action, + 'resume': self._handle_action, + 'suspend': self._handle_action, + 'shelve': self._handle_action, + 'unshelve': self._handle_action, + 'shelveOffload': self._handle_action, + 'migrate': self._handle_action, + 'trigger_crash_dump': self._handle_action, + 'reboot': self._handle_action, + 'resize': self._handle_action, + 'confirmResize': self._handle_action, + 'revertResize': self._handle_action, + 'os-resetState': self._handle_action } def _get_client(self, pod_name=constants.TOP): @@ -57,62 +62,17 @@ class ActionController(rest.RestController): self.clients[pod_name] = t_client.Client(pod_name) return self.clients[pod_name] - def _handle_start(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'start', self.server_id) + def _handle_action(self, context, pod_name, body): + """Perform a server action - def _handle_stop(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'stop', self.server_id) + :param pod_name: the bottom pod name. - def _handle_force_delete(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'force_delete', self.server_id) - - def _handle_pause(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'pause', self.server_id) - - def _handle_unpause(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'unpause', self.server_id) - - def _handle_lock(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'lock', self.server_id) - - def _handle_unlock(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'unlock', self.server_id) - - def _handle_suspend(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'suspend', self.server_id) - - def _handle_resume(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'resume', self.server_id) - - def _handle_shelve(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'shelve', self.server_id) - - def _handle_shelve_offload(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'shelve_offload', self.server_id) - - def _handle_unshelve(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'unshelve', self.server_id) - - def _handle_trigger_crash_dump(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'trigger_crash_dump', - self.server_id) - - def _handle_migrate(self, context, pod_name, body): - client = self._get_client(pod_name) - return client.action_servers(context, 'migrate', self.server_id) + :param body: action parameters body. + """ + url = constants.SERVER_ACTION_URL % self.server_id + api = self._get_client(pod_name).get_native_client(constants.RT_SERVER, + context) + return api.client.post(url, body=body) @expose(generic=True, template='json') def post(self, **kw): diff --git a/trio2o/tempestplugin/tempest_compute.sh b/trio2o/tempestplugin/tempest_compute.sh index 3bc7777..b3dab54 100755 --- a/trio2o/tempestplugin/tempest_compute.sh +++ b/trio2o/tempestplugin/tempest_compute.sh @@ -37,8 +37,15 @@ TESTCASES="$TESTCASES|tempest.api.compute.servers.test_servers_negative.ServersN TESTCASES="$TESTCASES|tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_suspend_server_invalid_state" TESTCASES="$TESTCASES|tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_migrate_non_existent_server" TESTCASES="$TESTCASES|tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_migrate_server_invalid_state" -# add new test cases like following line for volume_type test -# TESTCASES="$TESTCASES|tempest.api.volume.admin.test_volumes_type" +TESTCASES="$TESTCASES|tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard" +TESTCASES="$TESTCASES|tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_soft" +TESTCASES="$TESTCASES|tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_revert" +TESTCASES="$TESTCASES|tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_confirm" +TESTCASES="$TESTCASES|tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_confirm_from_stopped" +TESTCASES="$TESTCASES|tempest.api.compute.admin.test_servers.ServersAdminTestJSON.test_reset_state_server" +TESTCASES="$TESTCASES|tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_invalid_state" +TESTCASES="$TESTCASES|tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_invalid_type" +TESTCASES="$TESTCASES|tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_nonexistent_server" TESTCASES="$TESTCASES)" ostestr --regex $TESTCASES @@ -213,13 +220,13 @@ ostestr --regex $TESTCASES # tempest.api.compute.admin.test_servers.ServersAdminTestJSON.test_list_servers_filter_by_exist_host[id-86c7a8f7-50cf-43a9-9bac-5b985317134f] # tempest.api.compute.admin.test_servers.ServersAdminTestJSON.test_rebuild_server_in_error_state[id-682cb127-e5bb-4f53-87ce-cb9003604442] # tempest.api.compute.admin.test_servers.ServersAdminTestJSON.test_reset_network_inject_network_info[id-7a1323b4-a6a2-497a-96cb-76c07b945c71] -# tempest.api.compute.admin.test_servers.ServersAdminTestJSON.test_reset_state_server[id-ee8ae470-db70-474d-b752-690b7892cab1] +# **DONE** tempest.api.compute.admin.test_servers.ServersAdminTestJSON.test_reset_state_server[id-ee8ae470-db70-474d-b752-690b7892cab1] # tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_get_server_diagnostics_by_non_admin[id-e84e2234-60d2-42fa-8b30-e2d3049724ac,negative] # **DONE** tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_migrate_non_existent_server[id-46a4e1ca-87ae-4d28-987a-1b6b136a0221,negative] # **DONE** tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_migrate_server_invalid_state[id-b0b17f83-d14e-4fc4-8f31-bcc9f3cfa629,negative] -# tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_invalid_state[id-b0b4d8af-1256-41ef-9ee7-25f1c19dde80,negative] -# tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_invalid_type[id-4cdcc984-fab0-4577-9a9d-6d558527ee9d,negative] -# tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_nonexistent_server[id-e741298b-8df2-46f0-81cb-8f814ff2504c,negative] +# **DONE** tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_invalid_state[id-b0b4d8af-1256-41ef-9ee7-25f1c19dde80,negative] +# **DONE** tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_invalid_type[id-4cdcc984-fab0-4577-9a9d-6d558527ee9d,negative] +# **DONE** tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_reset_state_server_nonexistent_server[id-e741298b-8df2-46f0-81cb-8f814ff2504c,negative] # tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_resize_server_using_overlimit_ram[id-28dcec23-f807-49da-822c-56a92ea3c687,negative] # tempest.api.compute.admin.test_servers_negative.ServersAdminNegativeTestJSON.test_resize_server_using_overlimit_vcpus[id-7368a427-2f26-4ad9-9ba9-911a0ec2b0db,negative] # tempest.api.compute.admin.test_servers_on_multinodes.ServersOnMultiNodesTest.test_create_servers_on_different_hosts[id-cc7ca884-6e3e-42a3-a92f-c522fcf25e8e] @@ -449,13 +456,13 @@ ostestr --regex $TESTCASES # tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_get_vnc_console[id-c6bc11bf-592e-4015-9319-1c98dc64daf5] # **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_lock_unlock_server[id-80a8094c-211e-440a-ab88-9e59d556c7ee] # **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_pause_unpause_server[id-bd61a9fd-062f-4670-972b-2d6c3e3b9e73] -# tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard[id-2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32,smoke] -# tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_soft[id-4640e3ef-a5df-482e-95a1-ceeeb0faa84d] +# **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard[id-2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32,smoke] +# **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_soft[id-4640e3ef-a5df-482e-95a1-ceeeb0faa84d] # tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_rebuild_server[id-aaa6cdf3-55a7-461a-add9-1c8596b9a07c] # tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_rebuild_server_in_stop_state[id-30449a88-5aff-4f9b-9866-6ee9b17f906d] -# tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_confirm[id-1499262a-9328-4eda-9068-db1ac57498d2] -# tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_confirm_from_stopped[id-138b131d-66df-48c9-a171-64f45eb92962] -# tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_revert[id-c03aab19-adb1-44f5-917d-c419577e9e68] +# **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_confirm[id-1499262a-9328-4eda-9068-db1ac57498d2] +# **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_confirm_from_stopped[id-138b131d-66df-48c9-a171-64f45eb92962] +# **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_resize_server_revert[id-c03aab19-adb1-44f5-917d-c419577e9e68] # **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_shelve_unshelve_server[id-77eba8e0-036e-4635-944b-f7a8f3b78dc9] # **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_stop_start_server[id-af8eafd4-38a7-4a4b-bdbc-75145a580560] # **DONE** tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_suspend_resume_server[id-0d8ee21e-b749-462d-83da-b85b41c86c7f] diff --git a/trio2o/tests/unit/nova_apigw/controllers/test_action.py b/trio2o/tests/unit/nova_apigw/controllers/test_action.py index be5c863..f315960 100644 --- a/trio2o/tests/unit/nova_apigw/controllers/test_action.py +++ b/trio2o/tests/unit/nova_apigw/controllers/test_action.py @@ -14,12 +14,12 @@ # under the License. from mock import patch +from novaclient.client import SessionClient import pecan import unittest from oslo_utils import uuidutils -from trio2o.common import client from trio2o.common import constants from trio2o.common import context from trio2o.common import exceptions @@ -40,8 +40,9 @@ class ActionTest(unittest.TestCase): def setUp(self): core.initialize() core.ModelBase.metadata.create_all(core.get_engine()) - self.context = context.get_admin_context() + self.context = context.Context() self.project_id = 'test_project' + self.context.tenant = self.project_id self.controller = action.ActionController(self.project_id, '') def _prepare_pod(self, bottom_pod_num=1): @@ -63,6 +64,13 @@ class ActionTest(unittest.TestCase): b_pods.append(b_pod) return t_pod, b_pods + def _prepare_pod_service(self, pod_id, service): + config_dict = {'service_id': uuidutils.generate_uuid(), + 'pod_id': pod_id, + 'service_type': service, + 'service_url': 'fake_pod_service'} + api.create_pod_service_configuration(self.context, config_dict) + def _prepare_server(self, pod): t_server_id = uuidutils.generate_uuid() b_server_id = t_server_id @@ -96,12 +104,13 @@ class ActionTest(unittest.TestCase): self._validate_error_code(res, 404) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_action_exception(self, mock_context, mock_action): mock_context.return_value = self.context t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id @@ -122,241 +131,356 @@ class ActionTest(unittest.TestCase): self._validate_error_code(res, 500) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_start_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'os-start': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'start', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_stop_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'os-stop': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'stop', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_force_delete_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'forceDelete': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'force_delete', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_lock_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'lock': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'lock', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_unlock_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'unlock': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'unlock', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_pause_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'pause': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'pause', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_unpause_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'unpause': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'unpause', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_suspend_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'suspend': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'suspend', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_resume_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'resume': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'resume', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_shelveOffload_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'shelveOffload': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'shelve_offload', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_shelve_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'shelve': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'shelve', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_unshelve_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'unshelve': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'unshelve', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_trigger_crash_dump_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'trigger_crash_dump': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'trigger_crash_dump', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) @patch.object(pecan, 'response', new=FakeResponse) - @patch.object(client.Client, 'action_resources') + @patch.object(SessionClient, 'post') @patch.object(context, 'extract_context_from_environ') def test_migrate_action(self, mock_context, mock_action): mock_context.return_value = self.context mock_action.return_value = (FakeResponse(202), None) t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) t_server_id = self._prepare_server(b_pods[0]) self.controller.server_id = t_server_id body = {'migrate': ''} res = self.controller.post(**body) - mock_action.assert_called_once_with( - 'server', self.context, 'migrate', t_server_id) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) + self.assertEqual(202, res.status) + + @patch.object(pecan, 'response', new=FakeResponse) + @patch.object(SessionClient, 'post') + @patch.object(context, 'extract_context_from_environ') + def test_confirm_resize_action(self, mock_context, mock_action): + mock_context.return_value = self.context + mock_action.return_value = (FakeResponse(202), None) + + t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) + t_server_id = self._prepare_server(b_pods[0]) + self.controller.server_id = t_server_id + body = {"confirmResize": ''} + res = self.controller.post(**body) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) + self.assertEqual(202, res.status) + + @patch.object(pecan, 'response', new=FakeResponse) + @patch.object(SessionClient, 'post') + @patch.object(context, 'extract_context_from_environ') + def test_revert_resize_action(self, mock_context, mock_action): + mock_context.return_value = self.context + mock_action.return_value = (FakeResponse(202), None) + + t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) + t_server_id = self._prepare_server(b_pods[0]) + self.controller.server_id = t_server_id + body = {"revertResize": ''} + res = self.controller.post(**body) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) + self.assertEqual(202, res.status) + + @patch.object(pecan, 'response', new=FakeResponse) + @patch.object(SessionClient, 'post') + @patch.object(context, 'extract_context_from_environ') + def test_resize_action(self, mock_context, mock_action): + mock_context.return_value = self.context + mock_action.return_value = (FakeResponse(202), None) + + t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) + t_server_id = self._prepare_server(b_pods[0]) + self.controller.server_id = t_server_id + body = {"resize": {"flavorRef": "2"}} + res = self.controller.post(**body) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) + self.assertEqual(202, res.status) + + @patch.object(pecan, 'response', new=FakeResponse) + @patch.object(SessionClient, 'post') + @patch.object(context, 'extract_context_from_environ') + def test_reset_state_action(self, mock_context, mock_action): + mock_context.return_value = self.context + mock_action.return_value = (FakeResponse(202), None) + + t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) + t_server_id = self._prepare_server(b_pods[0]) + self.controller.server_id = t_server_id + body = {"os-resetState": {"state": "active"}} + res = self.controller.post(**body) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) + self.assertEqual(202, res.status) + + @patch.object(pecan, 'response', new=FakeResponse) + @patch.object(SessionClient, 'post') + @patch.object(context, 'extract_context_from_environ') + def test_soft_reboot_action(self, mock_context, mock_action): + mock_context.return_value = self.context + mock_action.return_value = (FakeResponse(202), None) + + t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) + t_server_id = self._prepare_server(b_pods[0]) + self.controller.server_id = t_server_id + body = {"reboot": {"type": "SOFT"}} + res = self.controller.post(**body) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) + self.assertEqual(202, res.status) + + @patch.object(pecan, 'response', new=FakeResponse) + @patch.object(SessionClient, 'post') + @patch.object(context, 'extract_context_from_environ') + def test_hard_reboot_action(self, mock_context, mock_action): + mock_context.return_value = self.context + mock_action.return_value = (FakeResponse(202), None) + t_pod, b_pods = self._prepare_pod() + self._prepare_pod_service(b_pods[0]['pod_id'], constants.ST_NOVA) + t_server_id = self._prepare_server(b_pods[0]) + self.controller.server_id = t_server_id + body = {"reboot": {"type": "HARD"}} + res = self.controller.post(**body) + url = '/servers/%s/action' % t_server_id + mock_action.assert_called_once_with(url, body=body) self.assertEqual(202, res.status) def tearDown(self):