Nova_APIGW Server Action Support(part2)
1. What is the problem The current Nova_APIGW does not support following server actions: reboot: Reboots a server. resize: Resizes a server. confirmResize: Confirms a pending resize action for a server. revertResize: Cancels and reverts a pending resize action for a server. os-resetState: Resets the state of a server. 2. What is the solution to the problem Implement the above server action 3. What the features need to be implemented to the Tricircle to realize the solution Add the above server action Change-Id: Ia3d0de1a42320cb1ee55b25210b227cb34a829a9
This commit is contained in:
parent
85df9c9c5f
commit
65f416745f
|
@ -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'
|
||||
|
|
|
@ -49,7 +49,12 @@ class ActionController(rest.RestController):
|
|||
'unshelve': self._handle_unshelve,
|
||||
'shelveOffload': self._handle_shelve_offload,
|
||||
'migrate': self._handle_migrate,
|
||||
'trigger_crash_dump': self._handle_trigger_crash_dump
|
||||
'trigger_crash_dump': self._handle_trigger_crash_dump,
|
||||
'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):
|
||||
|
@ -114,6 +119,18 @@ class ActionController(rest.RestController):
|
|||
client = self._get_client(pod_name)
|
||||
return client.action_servers(context, 'migrate', self.server_id)
|
||||
|
||||
def _handle_action(self, context, pod_name, body):
|
||||
"""Perform a server action
|
||||
|
||||
:param pod_name: the bottom pod name.
|
||||
|
||||
: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):
|
||||
context = t_context.extract_context_from_environ()
|
||||
|
|
|
@ -36,10 +36,16 @@ 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
|
||||
|
||||
# --------------------- IMPORTANT begin -------------------- #
|
||||
|
@ -212,13 +218,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]
|
||||
|
@ -448,13 +454,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]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
from mock import patch
|
||||
from novaclient.client import HTTPClient
|
||||
import pecan
|
||||
import unittest
|
||||
|
||||
|
@ -40,8 +41,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 +65,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
|
||||
|
@ -359,5 +368,106 @@ class ActionTest(unittest.TestCase):
|
|||
'server', self.context, 'migrate', t_server_id)
|
||||
self.assertEqual(202, res.status)
|
||||
|
||||
@patch.object(pecan, 'response', new=FakeResponse)
|
||||
@patch.object(HTTPClient, '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(HTTPClient, '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(HTTPClient, '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(HTTPClient, '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(HTTPClient, '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(HTTPClient, '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):
|
||||
core.ModelBase.metadata.drop_all(core.get_engine())
|
||||
|
|
Loading…
Reference in New Issue