Fix listing nodes with conductor could raise

In the case of conductor service goes offline, some hardware types
may be not available as well, get_conductor_for is not protected for
such case when querying node with conductor.

This patch adds exception handling and bypasses orphaned nodes.

Change-Id: I381585240057a989ab269ea35ea9b2124527bf8e
Story: 2004834
Task: 29028
This commit is contained in:
Kaifeng Wang 2019-01-23 11:30:34 +08:00
parent ab4778717b
commit 9555ad281c
3 changed files with 39 additions and 3 deletions

View File

@ -1587,9 +1587,15 @@ class NodesController(rest.RestController):
def _filter_by_conductor(self, nodes, conductor):
filtered_nodes = []
for n in nodes:
host = pecan.request.rpcapi.get_conductor_for(n)
if host == conductor:
filtered_nodes.append(n)
try:
host = pecan.request.rpcapi.get_conductor_for(n)
if host == conductor:
filtered_nodes.append(n)
except (exception.NoValidHost, exception.TemporaryFailure):
# NOTE(kaifeng) Node gets orphaned in case some conductor
# offline or all conductors are offline.
pass
return filtered_nodes
def _get_nodes_collection(self, chassis_uuid, instance_uuid, associated,

View File

@ -1636,6 +1636,30 @@ class TestListNodes(test_api_base.BaseApiTest):
self.assertNotIn(node1.uuid, uuids)
self.assertIn(node2.uuid, uuids)
def test_get_nodes_by_conductor_no_valid_host(self):
obj_utils.create_test_node(self.context,
uuid=uuidutils.generate_uuid())
self.mock_get_conductor_for.side_effect = exception.NoValidHost(
reason='hey a conductor just goes vacation')
response = self.get_json('/nodes?conductor=like.shadows',
headers={api_base.Version.string: "1.49"})
self.assertEqual([], response['nodes'])
self.mock_get_conductor_for.side_effect = exception.TemporaryFailure(
reason='this must be conductor strike')
response = self.get_json('/nodes?conductor=like.shadows',
headers={api_base.Version.string: "1.49"})
self.assertEqual([], response['nodes'])
self.mock_get_conductor_for.side_effect = exception.IronicException(
'Some unexpected thing happened')
response = self.get_json('/nodes?conductor=fake.conductor',
headers={api_base.Version.string: "1.49"},
expect_errors=True)
self.assertIn('Some unexpected thing happened',
response.json['error_message'])
def test_get_nodes_by_owner(self):
node1 = obj_utils.create_test_node(self.context,
uuid=uuidutils.generate_uuid(),

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Fixes an issue that node list with conductor fails if any of the nodes
has an invalid hardware type, which may happen when some conductor is
out of service.