Skip to content

Commit 87d05fb

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "api: Log os-resetState as an instance action"
2 parents 2a160f6 + 534b4f3 commit 87d05fb

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

nova/api/openstack/compute/admin_actions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
from nova.api.openstack import wsgi
2020
from nova.api import validation
2121
from nova.compute import api as compute
22+
from nova.compute import instance_actions
2223
from nova.compute import vm_states
2324
from nova import exception
25+
from nova import objects
2426
from nova.policies import admin_actions as aa_policies
2527

2628
# States usable in resetState action
@@ -65,9 +67,14 @@ def _reset_state(self, req, id, body):
6567
context.can(aa_policies.POLICY_ROOT % 'reset_state',
6668
target={'project_id': instance.project_id})
6769

70+
# Log os-resetState as an instance action
71+
instance_action = objects.InstanceAction.action_start(
72+
context, instance.uuid, instance_actions.RESET_STATE)
73+
6874
# Identify the desired state from the body
6975
state = state_map[body["os-resetState"]["state"]]
7076

7177
instance.vm_state = state
7278
instance.task_state = None
7379
instance.save(admin_state_reset=True)
80+
instance_action.finish()

nova/compute/instance_actions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,4 @@
7070
UNLOCK = 'unlock'
7171
BACKUP = 'createBackup'
7272
CREATE_IMAGE = 'createImage'
73+
RESET_STATE = 'resetState'

nova/tests/unit/api/openstack/compute/test_server_reset_state.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from nova.api.openstack.compute import admin_actions \
2020
as admin_actions_v21
21+
from nova.compute import instance_actions
2122
from nova.compute import vm_states
2223
from nova import exception
2324
from nova import objects
@@ -59,18 +60,27 @@ def _check_instance_state(self, expected):
5960
def _get_request(self):
6061
return fakes.HTTPRequest.blank('')
6162

63+
@mock.patch(
64+
'nova.objects.instance_action.InstanceAction.action_start',
65+
new=mock.Mock(spec=objects.InstanceAction))
6266
def test_no_state(self):
6367
self.assertRaises(self.bad_request,
6468
self.admin_api._reset_state,
6569
self.request, self.uuid,
6670
body={"os-resetState": None})
6771

72+
@mock.patch(
73+
'nova.objects.instance_action.InstanceAction.action_start',
74+
new=mock.Mock(spec=objects.InstanceAction))
6875
def test_bad_state(self):
6976
self.assertRaises(self.bad_request,
7077
self.admin_api._reset_state,
7178
self.request, self.uuid,
7279
body={"os-resetState": {"state": "spam"}})
7380

81+
@mock.patch(
82+
'nova.objects.instance_action.InstanceAction.action_start',
83+
new=mock.Mock(spec=objects.InstanceAction))
7484
def test_no_instance(self):
7585
self.compute_api.get = mock.MagicMock(
7686
side_effect=exception.InstanceNotFound(instance_id='inst_ud'))
@@ -84,11 +94,14 @@ def test_no_instance(self):
8494
self.context, self.uuid, expected_attrs=None,
8595
cell_down_support=False)
8696

87-
def test_reset_active(self):
97+
@mock.patch('nova.objects.instance_action.InstanceAction.action_start')
98+
def test_reset_active(self, mock_instance_action_start):
8899
expected = dict(vm_state=vm_states.ACTIVE, task_state=None)
89100
self.instance.save = mock.MagicMock(
90101
side_effect=lambda **kw: self._check_instance_state(expected))
91102
self.compute_api.get = mock.MagicMock(return_value=self.instance)
103+
mock_instance_action = mock.Mock(spec=objects.InstanceAction)
104+
mock_instance_action_start.return_value = mock_instance_action
92105

93106
body = {"os-resetState": {"state": "active"}}
94107
result = self.admin_api._reset_state(self.request, self.uuid,
@@ -107,11 +120,18 @@ def test_reset_active(self):
107120
cell_down_support=False)
108121
self.instance.save.assert_called_once_with(admin_state_reset=True)
109122

110-
def test_reset_error(self):
123+
mock_instance_action_start.assert_called_once_with(
124+
self.context, self.instance.uuid, instance_actions.RESET_STATE)
125+
mock_instance_action.finish.assert_called_once()
126+
127+
@mock.patch('nova.objects.instance_action.InstanceAction.action_start')
128+
def test_reset_error(self, mock_instance_action_start):
111129
expected = dict(vm_state=vm_states.ERROR, task_state=None)
112130
self.instance.save = mock.MagicMock(
113131
side_effect=lambda **kw: self._check_instance_state(expected))
114132
self.compute_api.get = mock.MagicMock(return_value=self.instance)
133+
mock_instance_action = mock.Mock(spec=objects.InstanceAction)
134+
mock_instance_action_start.return_value = mock_instance_action
115135

116136
body = {"os-resetState": {"state": "error"}}
117137
result = self.admin_api._reset_state(self.request, self.uuid,
@@ -129,3 +149,7 @@ def test_reset_error(self):
129149
self.context, self.instance.uuid, expected_attrs=None,
130150
cell_down_support=False)
131151
self.instance.save.assert_called_once_with(admin_state_reset=True)
152+
153+
mock_instance_action_start.assert_called_once_with(
154+
self.context, self.instance.uuid, instance_actions.RESET_STATE)
155+
mock_instance_action.finish.assert_called_once()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
fixes:
3+
- |
4+
The `os-resetState`_ API will now log an instance action when called. The
5+
resulting instance action being visable via the `os-instance-actions`_ API
6+
to users and admins, resolving `bug 1911924`_.
7+
8+
.. _bug 1911924: https://launchpad.net/bugs/1911924
9+
.. _os-instance-actions: https://docs.openstack.org/api-ref/compute/?expanded=reset-server-state-os-resetstate-action-detail,list-actions-for-server-detail
10+
.. _os-resetState: https://docs.openstack.org/api-ref/compute/?expanded=reset-server-state-os-resetstate-action-detail

0 commit comments

Comments
 (0)