Fix an error when generating a host ID

When instance action events are created by periodic tasks,
the project IDs of them become null (None).
It causes an error when 'hostId' is generated
in the "Show Server Action Details"
(GET /servers/{server_id}/os-instance-actions/{request_id})
API.

Fix the issue by using the project ID of the server
if the project ID of the event is None.

Conflicts:
    nova/tests/unit/api/openstack/compute/test_instance_actions.py

    The conflicts are due to not having the following
    changes in Rocky.

    I7f5f08691ca3f73073c66c29dddb996fb2c2b266
    If91c179e3823c8b0da744a9363906b0f7b05c326
    I44546bc9798708a48a250cc3a21bdbcabe2649e1

Change-Id: Iac07fcddd4cc3321c6efe702066eb8af6a875418
Closes-Bug: #1817542
(cherry picked from commit 31fe7c7600)
This commit is contained in:
Takashi NATSUME 2019-02-28 13:49:41 +09:00
parent 549f899d9b
commit e2185168f8
2 changed files with 70 additions and 2 deletions

View File

@ -163,8 +163,15 @@ class InstanceActionsController(wsgi.Controller):
if show_events: if show_events:
events_raw = self.action_api.action_events_get(context, instance, events_raw = self.action_api.action_events_get(context, instance,
action_id) action_id)
# NOTE(takashin): The project IDs of instance action events
# become null (None) when instance action events are created
# by periodic tasks. If the project ID is null (None),
# it causes an error when 'hostId' is generated.
# If the project ID is null (None), pass the project ID of
# the server instead of that of instance action events.
action['events'] = [self._format_event( action['events'] = [self._format_event(
evt, action['project_id'], show_traceback=show_traceback, evt, action['project_id'] or instance.project_id,
show_traceback=show_traceback,
show_host=show_host, show_hostid=show_hostid show_host=show_host, show_hostid=show_hostid
) for evt in events_raw] ) for evt in events_raw]
return {'instanceAction': action} return {'instanceAction': action}

View File

@ -14,6 +14,7 @@
# under the License. # under the License.
import copy import copy
import datetime
import mock import mock
from oslo_policy import policy as oslo_policy from oslo_policy import policy as oslo_policy
@ -31,6 +32,8 @@ from nova import test
from nova.tests.unit.api.openstack import fakes from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import fake_server_actions from nova.tests.unit import fake_server_actions
from nova.tests import uuidsentinel as uuids from nova.tests import uuidsentinel as uuids
from nova import utils
FAKE_UUID = fake_server_actions.FAKE_UUID FAKE_UUID = fake_server_actions.FAKE_UUID
FAKE_REQUEST_ID = fake_server_actions.FAKE_REQUEST_ID1 FAKE_REQUEST_ID = fake_server_actions.FAKE_REQUEST_ID1
@ -314,7 +317,65 @@ class InstanceActionsTestV258(InstanceActionsTestV251):
six.text_type(ex)) six.text_type(ex))
class InstanceActionsTestV262(InstanceActionsTestV251): class InstanceActionsTestV262(InstanceActionsTestV258):
wsgi_api_version = "2.62" wsgi_api_version = "2.62"
expect_event_hostId = True expect_event_hostId = True
expect_event_host = True expect_event_host = True
instance_project_id = '26cde4489f6749a08834741678df3c4a'
def fake_get(self, context, instance_uuid, expected_attrs=None,
cell_down_support=False):
return objects.Instance(uuid=instance_uuid,
project_id=self.instance_project_id)
@mock.patch.object(compute_api.InstanceActionAPI, 'action_events_get')
@mock.patch.object(compute_api.InstanceActionAPI,
'action_get_by_request_id')
def test_get_action_with_events_project_id_none(self, mock_action_get,
mock_action_events):
fake_request_id = 'req-%s' % uuids.req1
mock_action_get.return_value = objects.InstanceAction(
id=789,
action='stop',
instance_uuid=uuids.instance,
request_id=fake_request_id,
user_id=None,
project_id=None,
start_time=datetime.datetime(2019, 2, 28, 14, 28, 0, 0),
finish_time=None,
message='',
created_at=None,
updated_at=None,
deleted_at=None,
deleted=False)
mock_action_events.return_value = [
objects.InstanceActionEvent(
id=5,
action_id=789,
event='compute_stop_instance',
start_time=datetime.datetime(2019, 2, 28, 14, 28, 0, 0),
finish_time=datetime.datetime(2019, 2, 28, 14, 30, 0, 0),
result='Success',
traceback='',
created_at=None,
updated_at=None,
deleted_at=None,
deleted=False,
host='host2')]
req = self._get_http_req('os-instance-actions/1',
use_admin_context=True)
res_dict = self.controller.show(req, uuids.instance, fake_request_id)
# Assert that 'project_id' is null (None) in the response
self.assertIsNone(res_dict['instanceAction']['project_id'])
self.assertEqual('host2',
res_dict['instanceAction']['events'][0]['host'])
# Assert that the 'hostId' is based on 'host' and the project ID
# of the server
self.assertEqual(utils.generate_hostid(
res_dict['instanceAction']['events'][0]['host'],
self.instance_project_id),
res_dict['instanceAction']['events'][0]['hostId'])