From 5921099626e3afde044027ed493bdee905db4415 Mon Sep 17 00:00:00 2001 From: Tomas Jelinek Date: Thu, 21 Jul 2016 13:58:41 +0200 Subject: [PATCH] fix filter by property name in "pcs property show" --- pcs/prop.py | 14 +-- pcs/test/test_properties.py | 263 ++++++++++++++++++++++++++++++++++---------- pcs/utils.py | 13 ++- 3 files changed, 223 insertions(+), 67 deletions(-) diff --git a/pcs/prop.py b/pcs/prop.py index 36eba60..92a953c 100644 --- a/pcs/prop.py +++ b/pcs/prop.py @@ -100,9 +100,7 @@ def unset_property(argv): utils.replace_cib_configuration(cib_dom) def list_property(argv): - print_all = False - if len(argv) == 0: - print_all = True + print_all = len(argv) == 0 if "--all" in utils.pcs_options and "--defaults" in utils.pcs_options: utils.err("you cannot specify both --all and --defaults") @@ -124,13 +122,15 @@ def list_property(argv): for prop,val in sorted(properties.items()): print(" " + prop + ": " + val) - node_attributes = utils.get_node_attributes() + node_attributes = utils.get_node_attributes( + filter_attr=(None if print_all else argv[0]) + ) if node_attributes: print("Node Attributes:") - for node in sorted(node_attributes): + for node in sorted(node_attributes.keys()): line_parts = [" " + node + ":"] - for attr in node_attributes[node]: - line_parts.append(attr) + for name, value in sorted(node_attributes[node].items()): + line_parts.append("{0}={1}".format(name, value)) print(" ".join(line_parts)) def get_default_properties(): diff --git a/pcs/test/test_properties.py b/pcs/test/test_properties.py index 6cdd2e5..fbaf880 100644 --- a/pcs/test/test_properties.py +++ b/pcs/test/test_properties.py @@ -8,11 +8,15 @@ from __future__ import ( import shutil import unittest +from pcs.test.tools.assertions import AssertPcsMixin from pcs.test.tools.misc import ( ac, get_test_resource as rc, ) -from pcs.test.tools.pcs_runner import pcs +from pcs.test.tools.pcs_runner import ( + pcs, + PcsRunner, +) from pcs import utils @@ -66,61 +70,6 @@ class PropertyTest(unittest.TestCase): assert "stonith-enabled: false" in output assert output.startswith('Cluster Properties:\n batch-limit') - def testNodeProperties(self): - utils.usefile = True - utils.filename = temp_cib - o,r = utils.run(["cibadmin","-M", '--xml-text', '']) - ac(o,"") - assert r == 0 - - o,r = pcs("property set --node=rh7-1 IP=192.168.1.1") - ac(o,"") - assert r==0 - - o,r = pcs("property set --node=rh7-2 IP=192.168.2.2") - ac(o,"") - assert r==0 - - o,r = pcs("property") - ac(o,"Cluster Properties:\nNode Attributes:\n rh7-1: IP=192.168.1.1\n rh7-2: IP=192.168.2.2\n") - assert r==0 - - o,r = pcs("property set --node=rh7-2 IP=") - ac(o,"") - assert r==0 - - o,r = pcs("property") - ac(o,"Cluster Properties:\nNode Attributes:\n rh7-1: IP=192.168.1.1\n") - assert r==0 - - o,r = pcs("property set --node=rh7-1 IP=192.168.1.1") - ac(o,"") - assert r==0 - - o,r = pcs("property set --node=rh7-2 IP=192.168.2.2") - ac(o,"") - assert r==0 - - o,r = pcs("property") - ac(o,"Cluster Properties:\nNode Attributes:\n rh7-1: IP=192.168.1.1\n rh7-2: IP=192.168.2.2\n") - assert r==0 - - o,r = pcs("property unset --node=rh7-1 IP") - ac(o,"") - assert r==0 - - o,r = pcs("property") - ac(o,"Cluster Properties:\nNode Attributes:\n rh7-2: IP=192.168.2.2\n") - assert r==0 - - o,r = pcs("property unset --node=rh7-1 IP") - ac(o,"Error: attribute: 'IP' doesn't exist for node: 'rh7-1'\n") - assert r==2 - - o,r = pcs("property unset --node=rh7-1 IP --force") - ac(o,"") - assert r==0 - def testBadProperties(self): o,r = pcs(temp_cib, "property set xxxx=zzzz") self.assertEqual(r, 1) @@ -329,3 +278,205 @@ class PropertyTest(unittest.TestCase): default-resource-stickiness: 0.1 """ ) + + +class NodePropertyTestBase(unittest.TestCase, AssertPcsMixin): + def setUp(self): + shutil.copy(empty_cib, temp_cib) + self.pcs_runner = PcsRunner(temp_cib) + + def fixture_nodes(self, nodes, attrs=None): + attrs = dict() if attrs is None else attrs + xml_lines = [''] + for node_id, node_name in enumerate(nodes, 1): + xml_lines.extend([ + ''.format(node_id, node_name), + ''.format(node_id), + ]) + nv = '' + for name, value in attrs.get(node_name, dict()).items(): + xml_lines.append(nv.format(id=node_id, name=name, val=value)) + xml_lines.extend([ + '', + '' + ]) + xml_lines.append('') + + utils.usefile = True + utils.filename = temp_cib + output, retval = utils.run([ + "cibadmin", "--modify", '--xml-text', "\n".join(xml_lines) + ]) + assert output == "" + assert retval == 0 + +class NodePropertyShowTest(NodePropertyTestBase): + def test_empty(self): + self.fixture_nodes(["rh7-1", "rh7-2"]) + self.assert_pcs_success( + "property", + "Cluster Properties:\n" + ) + + def test_nonempty(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", }, + "rh7-2": {"IP": "192.168.1.2", }, + } + ) + self.assert_pcs_success( + "property", + """\ +Cluster Properties: +Node Attributes: + rh7-1: IP=192.168.1.1 + rh7-2: IP=192.168.1.2 +""" + ) + + def test_multiple_per_node(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", "alias": "node1", }, + "rh7-2": {"IP": "192.168.1.2", "alias": "node2", }, + } + ) + self.assert_pcs_success( + "property", + """\ +Cluster Properties: +Node Attributes: + rh7-1: IP=192.168.1.1 alias=node1 + rh7-2: IP=192.168.1.2 alias=node2 +""" + ) + + def test_name_filter_not_exists(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", }, + "rh7-2": {"IP": "192.168.1.2", }, + } + ) + self.assert_pcs_success( + "property show alias", + """\ +Cluster Properties: +""" + ) + + def test_name_filter_exists(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", "alias": "node1", }, + "rh7-2": {"IP": "192.168.1.2", }, + } + ) + self.assert_pcs_success( + "property show alias", + """\ +Cluster Properties: +Node Attributes: + rh7-1: alias=node1 +""" + ) + +class NodePropertySetTest(NodePropertyTestBase): + def test_set_new(self): + self.fixture_nodes(["rh7-1", "rh7-2"]) + self.assert_pcs_success( + "property set --node=rh7-1 IP=192.168.1.1" + ) + self.assert_pcs_success( + "property", + """\ +Cluster Properties: +Node Attributes: + rh7-1: IP=192.168.1.1 +""" + ) + self.assert_pcs_success( + "property set --node=rh7-2 IP=192.168.1.2" + ) + self.assert_pcs_success( + "property", + """\ +Cluster Properties: +Node Attributes: + rh7-1: IP=192.168.1.1 + rh7-2: IP=192.168.1.2 +""" + ) + + def test_set_existing(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", }, + "rh7-2": {"IP": "192.168.1.2", }, + } + ) + self.assert_pcs_success( + "property set --node=rh7-2 IP=192.168.2.2" + ) + self.assert_pcs_success( + "property", + """\ +Cluster Properties: +Node Attributes: + rh7-1: IP=192.168.1.1 + rh7-2: IP=192.168.2.2 +""" + ) + + def test_unset(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", }, + "rh7-2": {"IP": "192.168.1.2", }, + } + ) + self.assert_pcs_success( + "property set --node=rh7-2 IP=" + ) + self.assert_pcs_success( + "property", + """\ +Cluster Properties: +Node Attributes: + rh7-1: IP=192.168.1.1 +""" + ) + + def test_unset_nonexisting(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", }, + "rh7-2": {"IP": "192.168.1.2", }, + } + ) + self.assert_pcs_result( + "property unset --node=rh7-1 missing", + "Error: attribute: 'missing' doesn't exist for node: 'rh7-1'\n", + returncode=2 + ) + + def test_unset_nonexisting_forced(self): + self.fixture_nodes( + ["rh7-1", "rh7-2"], + { + "rh7-1": {"IP": "192.168.1.1", }, + "rh7-2": {"IP": "192.168.1.2", }, + } + ) + self.assert_pcs_success( + "property unset --node=rh7-1 missing --force", + "" + ) diff --git a/pcs/utils.py b/pcs/utils.py index 981a186..c7d1759 100644 --- a/pcs/utils.py +++ b/pcs/utils.py @@ -1659,19 +1659,24 @@ def set_unmanaged(resource): "is-managed", "--meta", "--parameter-value", "false"] return run(args) -def get_node_attributes(): +def get_node_attributes(filter_node=None, filter_attr=None): node_config = get_cib_xpath("//nodes") - nas = {} if (node_config == ""): err("unable to get crm_config, is pacemaker running?") dom = parseString(node_config).documentElement + nas = dict() for node in dom.getElementsByTagName("node"): nodename = node.getAttribute("uname") + if filter_node is not None and nodename != filter_node: + continue for attributes in node.getElementsByTagName("instance_attributes"): for nvp in attributes.getElementsByTagName("nvpair"): + attr_name = nvp.getAttribute("name") + if filter_attr is not None and attr_name != filter_attr: + continue if nodename not in nas: - nas[nodename] = [] - nas[nodename].append(nvp.getAttribute("name") + "=" + nvp.getAttribute("value")) + nas[nodename] = dict() + nas[nodename][attr_name] = nvp.getAttribute("value") break return nas -- 1.8.3.1