From 6e3cec799f8bca5e281c74d05eaf98bc61ed23fd Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 27 Mar 2019 18:25:44 +0000 Subject: [PATCH] Use XML to get node list The current list_nodes command tries to parse the output of "crm node list" to get a list of nodes. But the output is messy if remote nodes are present so use "crm node status" to get properly formatted XML which can be reliably parsed. Change-Id: Iea7ef3dca194e7440dc2cde2624d07e990006685 --- hooks/pcmk.py | 12 +++++------- unit_tests/test_pcmk.py | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/hooks/pcmk.py b/hooks/pcmk.py index ad965a0..5643d96 100644 --- a/hooks/pcmk.py +++ b/hooks/pcmk.py @@ -103,14 +103,12 @@ def crm_res_running(opt_name): def list_nodes(): - cmd = ['crm', 'node', 'list'] + """List member nodes.""" + cmd = ['crm', 'node', 'status'] out = subprocess.check_output(cmd).decode('utf-8') - nodes = [] - for line in str(out).split('\n'): - if line != '': - nodes.append(line.split(':')[0]) - - return nodes + tree = etree.fromstring(out) + nodes = [n.attrib['uname'] for n in tree.iter('node')] + return sorted(nodes) def _maas_ipmi_stonith_resource(node, power_params): diff --git a/unit_tests/test_pcmk.py b/unit_tests/test_pcmk.py index 633db07..1eb7215 100644 --- a/unit_tests/test_pcmk.py +++ b/unit_tests/test_pcmk.py @@ -74,6 +74,14 @@ CRM_CONFIGURE_SHOW_XML_MAINT_MODE_TRUE = ''' ''' # noqa +CRM_NODE_STATUS_XML = b''' + + + + + +''' + class TestPcmk(unittest.TestCase): def setUp(self): @@ -226,3 +234,13 @@ class TestPcmk(unittest.TestCase): r = pcmk.resource_checksum('res_test', 'IPaddr2', 'params ip=1.2.3.4 cidr_netmask=255.0.0.0') self.assertEqual(r, 'ef395293b1b7c29c5bf1c99774f75cf4') + + @mock.patch('subprocess.check_output', return_value=CRM_NODE_STATUS_XML) + def test_list_nodes(self, mock_check_output): + self.assertSequenceEqual( + pcmk.list_nodes(), + [ + 'juju-982848-zaza-ce47c58f6c88-10', + 'juju-982848-zaza-ce47c58f6c88-11', + 'juju-982848-zaza-ce47c58f6c88-9']) + mock_check_output.assert_called_once_with(['crm', 'node', 'status'])