Add a REST API to trigger crash dump in an instance.

Change I9b649aafba011d537e3fe4eebef7a678ff6733e4 has added a
compute API to trigger crash dump in instance. This patch adds
the REST API to nova. It enables users to trigger crash dump in
an instance through REST API.

Change-Id: I6ed777ff637254b4b79417008f9055dd19fc7405
Implements: blueprint instance-crash-dump
Co-Authored-By: Hironori Shiina <shiina.hironori@jp.fujitsu.com>
Co-Authored-By: Tang Chen <tangchen@cn.fujitsu.com>
This commit is contained in:
Tang Chen 2016-01-19 17:30:25 +08:00
parent 49c05a2430
commit 30c6f49817
17 changed files with 170 additions and 7 deletions

View File

@ -0,0 +1,3 @@
{
"trigger_crash_dump": null
}

View File

@ -19,7 +19,7 @@
}
],
"status": "CURRENT",
"version": "2.16",
"version": "2.17",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@ -22,7 +22,7 @@
}
],
"status": "CURRENT",
"version": "2.16",
"version": "2.17",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@ -269,6 +269,7 @@
"os_compute_api:servers:create_image:allow_volume_backed": "",
"os_compute_api:servers:start": "rule:admin_or_owner",
"os_compute_api:servers:stop": "rule:admin_or_owner",
"os_compute_api:servers:trigger_crash_dump": "rule:admin_or_owner",
"os_compute_api:os-access-ips:discoverable": "",
"os_compute_api:os-access-ips": "",
"os_compute_api:os-admin-actions": "rule:admin_api",

View File

@ -58,6 +58,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
adminPass from the response body
* 2.15 - Add soft-affinity and soft-anti-affinity policies
* 2.16 - Exposes host_status for servers/detail and servers/{server_id}
* 2.17 - Add trigger_crash_dump to server actions
"""
# The minimum and maximum versions of the API supported
@ -66,7 +67,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
# Note(cyeoh): This only applies for the v2.1 API once microversions
# support is fully merged. It does not affect the V2 API.
_MIN_API_VERSION = "2.1"
_MAX_API_VERSION = "2.16"
_MAX_API_VERSION = "2.17"
DEFAULT_API_VERSION = _MIN_API_VERSION

View File

@ -161,3 +161,14 @@ reboot = {
'required': ['reboot'],
'additionalProperties': False
}
trigger_crash_dump = {
'type': 'object',
'properties': {
'trigger_crash_dump': {
'type': 'null'
}
},
'required': ['trigger_crash_dump'],
'additionalProperties': False
}

View File

@ -1162,6 +1162,26 @@ class ServersController(wsgi.Controller):
common.raise_http_conflict_for_instance_invalid_state(state_error,
'stop', id)
@wsgi.Controller.api_version("2.17")
@wsgi.response(202)
@extensions.expected_errors((400, 404, 409))
@wsgi.action('trigger_crash_dump')
@validation.schema(schema_servers.trigger_crash_dump)
def _action_trigger_crash_dump(self, req, id, body):
"""Trigger crash dump in an instance"""
context = req.environ['nova.context']
instance = self._get_instance(context, id)
authorize(context, instance, 'trigger_crash_dump')
try:
self.compute_api.trigger_crash_dump(context, instance)
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'trigger_crash_dump', id)
except (exception.InstanceNotReady, exception.InstanceIsLocked) as e:
raise webob.exc.HTTPConflict(explanation=e.format_message())
except exception.NMINotSupported as e:
raise webob.exc.HTTPBadRequest(explanation=e.format_message())
def remove_invalid_options(context, search_options, allowed_search_options):
"""Remove search options that are not valid for non-admin API/context."""

View File

@ -157,3 +157,9 @@ user documentation.
Exposes new host_status attribute for servers/detail and servers/{server_id}.
Ability to get nova-compute status when querying servers. By default, this is
only exposed to cloud administrators.
2.17
----
Add a new API for triggering crash dump in an instance. Different operation
systems in instance may need different configurations to trigger crash dump.

View File

@ -0,0 +1,3 @@
{
"trigger_crash_dump": null
}

View File

@ -19,7 +19,7 @@
}
],
"status": "CURRENT",
"version": "2.16",
"version": "2.17",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@ -22,7 +22,7 @@
}
],
"status": "CURRENT",
"version": "2.16",
"version": "2.17",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@ -267,3 +267,19 @@ class ServersSampleMultiStatusJsonTest(ServersSampleBase):
response = self._do_get('servers?status=active&status=error')
subs = {'id': uuid}
self._verify_response('servers-list-resp', subs, response, 200)
class ServerTriggerCrashDumpJsonTest(ServersSampleBase):
sample_dir = 'servers'
microversion = '2.17'
scenarios = [('v2_17', {'api_major_version': 'v2.1'})]
def test_trigger_crash_dump(self):
uuid = self._post_server()
response = self._do_post('servers/%s/action' % uuid,
'server-action-trigger-crash-dump',
{},
api_version=self.microversion)
self.assertEqual(response.status_code, 202)
self.assertEqual(response.content, "")

View File

@ -1937,6 +1937,91 @@ class ServersControllerUpdateTest(ControllerTest):
self.controller.update, req, FAKE_UUID, body=body)
class ServersControllerTriggerCrashDumpTest(ControllerTest):
def setUp(self):
super(ServersControllerTriggerCrashDumpTest, self).setUp()
self.instance = fakes.stub_instance_obj(None,
vm_state=vm_states.ACTIVE)
def fake_get(ctrl, ctxt, uuid):
if uuid != FAKE_UUID:
raise webob.exc.HTTPNotFound(explanation='fakeout')
return self.instance
self.useFixture(
fixtures.MonkeyPatch('nova.api.openstack.compute.servers.'
'ServersController._get_instance',
fake_get))
self.req = fakes.HTTPRequest.blank('/servers/%s/action' % FAKE_UUID)
self.req.api_version_request =\
api_version_request.APIVersionRequest('2.17')
self.body = dict(trigger_crash_dump=None)
@mock.patch.object(compute_api.API, 'trigger_crash_dump')
def test_trigger_crash_dump(self, mock_trigger_crash_dump):
ctxt = self.req.environ['nova.context']
self.controller._action_trigger_crash_dump(self.req, FAKE_UUID,
body=self.body)
mock_trigger_crash_dump.assert_called_with(ctxt, self.instance)
def test_trigger_crash_dump_policy_failed(self):
rule_name = "os_compute_api:servers:trigger_crash_dump"
self.policy.set_rules({rule_name: "project_id:non_fake"})
exc = self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body=self.body)
self.assertIn("os_compute_api:servers:trigger_crash_dump",
exc.format_message())
@mock.patch.object(compute_api.API, 'trigger_crash_dump',
fake_start_stop_not_ready)
def test_trigger_crash_dump_not_ready(self):
self.assertRaises(webob.exc.HTTPConflict,
self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body=self.body)
@mock.patch.object(compute_api.API, 'trigger_crash_dump',
fakes.fake_actions_to_locked_server)
def test_trigger_crash_dump_locked_server(self):
self.assertRaises(webob.exc.HTTPConflict,
self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body=self.body)
@mock.patch.object(compute_api.API, 'trigger_crash_dump',
fake_start_stop_invalid_state)
def test_trigger_crash_dump_invalid_state(self):
self.assertRaises(webob.exc.HTTPConflict,
self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body=self.body)
def test_trigger_crash_dump_with_bogus_id(self):
self.assertRaises(webob.exc.HTTPNotFound,
self.controller._action_trigger_crash_dump,
self.req, 'test_inst', body=self.body)
def test_trigger_crash_dump_schema_invalid_type(self):
self.body['trigger_crash_dump'] = 'not null'
self.assertRaises(exception.ValidationError,
self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body=self.body)
def test_trigger_crash_dump_schema_extra_property(self):
self.body['extra_property'] = 'extra'
self.assertRaises(exception.ValidationError,
self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body=self.body)
@mock.patch.object(compute_api.API, 'trigger_crash_dump',
side_effect=exception.NMINotSupported)
def test_trigger_crash_dump_not_supported(self, mock_trigger_crash_dump):
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body=self.body)
class ServerStatusTest(test.TestCase):
def setUp(self):
@ -3876,6 +3961,17 @@ class ServersPolicyEnforcementV21(test.NoDBTestCase):
rule, rule_name, self.controller._stop_server,
self.req, FAKE_UUID, body={})
@mock.patch.object(servers.ServersController, '_get_instance')
def test_trigger_crash_dump_policy_failed(self, _get_instance_mock):
_get_instance_mock.return_value = None
rule_name = "os_compute_api:servers:trigger_crash_dump"
rule = {rule_name: "project:non_fake"}
self.req.api_version_request =\
api_version_request.APIVersionRequest('2.17')
self._common_policy_check(
rule, rule_name, self.controller._action_trigger_crash_dump,
self.req, FAKE_UUID, body={'trigger_crash_dump': None})
def test_index_policy_failed(self):
rule_name = "os_compute_api:servers:index"
rule = {rule_name: "project:non_fake"}

View File

@ -66,7 +66,7 @@ EXP_VERSIONS = {
"v2.1": {
"id": "v2.1",
"status": "CURRENT",
"version": "2.16",
"version": "2.17",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z",
"links": [
@ -128,7 +128,7 @@ class VersionsTestV20(test.NoDBTestCase):
{
"id": "v2.1",
"status": "CURRENT",
"version": "2.16",
"version": "2.17",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z",
"links": [

View File

@ -124,6 +124,7 @@ policy_data = """
"os_compute_api:servers:update": "",
"os_compute_api:servers:start": "",
"os_compute_api:servers:stop": "",
"os_compute_api:servers:trigger_crash_dump": "",
"os_compute_api:os-access-ips": "",
"compute_extension:accounts": "",
"compute_extension:admin_actions:pause": "",

View File

@ -382,6 +382,7 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"compute_extension:simple_tenant_usage:show",
"os_compute_api:servers:start",
"os_compute_api:servers:stop",
"os_compute_api:servers:trigger_crash_dump",
"os_compute_api:os-create-backup",
"os_compute_api:ips:index",
"os_compute_api:ips:show",

View File

@ -0,0 +1,4 @@
---
features:
- A new server action trigger_crash_dump has been added to the REST API in
microversion 2.17.