403 lines
14 KiB
Diff
403 lines
14 KiB
Diff
From 4a986e8ee0610b1c85a04e38042e4073d41207a4 Mon Sep 17 00:00:00 2001
|
|
From: Miroslav Lisik <mlisik@redhat.com>
|
|
Date: Mon, 13 Jul 2020 12:59:09 +0200
|
|
Subject: [PATCH 2/3] Fix tag removal in resource 'unclone/ungroup' commands
|
|
and extend test coverage
|
|
|
|
---
|
|
pcs/resource.py | 2 +-
|
|
.../tier1/cib_resource/test_clone_unclone.py | 73 +++++++--
|
|
.../tier1/cib_resource/test_group_ungroup.py | 143 +++++++++++++++---
|
|
pcs_test/tools/cib.py | 10 +-
|
|
4 files changed, 187 insertions(+), 41 deletions(-)
|
|
|
|
diff --git a/pcs/resource.py b/pcs/resource.py
|
|
index 9a3bd0ee..49d28ef0 100644
|
|
--- a/pcs/resource.py
|
|
+++ b/pcs/resource.py
|
|
@@ -2027,7 +2027,7 @@ def remove_resource_references(
|
|
if obj_ref.getAttribute("id") == resource_id:
|
|
tag = obj_ref.parentNode
|
|
tag.removeChild(obj_ref)
|
|
- if tag.getElementsByTagName(obj_ref).length == 0:
|
|
+ if tag.getElementsByTagName("obj_ref").length == 0:
|
|
remove_resource_references(
|
|
dom, tag.getAttribute("id"), output=output,
|
|
)
|
|
diff --git a/pcs_test/tier1/cib_resource/test_clone_unclone.py b/pcs_test/tier1/cib_resource/test_clone_unclone.py
|
|
index c9c6a29e..2633801a 100644
|
|
--- a/pcs_test/tier1/cib_resource/test_clone_unclone.py
|
|
+++ b/pcs_test/tier1/cib_resource/test_clone_unclone.py
|
|
@@ -55,6 +55,38 @@ FIXTURE_RESOURCES = """
|
|
)
|
|
|
|
|
|
+FIXTURE_CONSTRAINTS_CONFIG_XML = """
|
|
+ <constraints>
|
|
+ <rsc_location id="location-C-clone-rh7-1-INFINITY" node="rh7-1"
|
|
+ rsc="C-clone" score="INFINITY"/>
|
|
+ <rsc_location id="location-TagCloneOnly-rh7-1-INFINITY"
|
|
+ node="rh7-1" rsc="TagCloneOnly" score="INFINITY"/>
|
|
+ </constraints>
|
|
+"""
|
|
+
|
|
+
|
|
+FIXTURE_TAGS_CONFIG_XML = """
|
|
+ <tags>
|
|
+ <tag id="TagCloneOnly">
|
|
+ <obj_ref id="C-clone"/>
|
|
+ </tag>
|
|
+ <tag id="TagNotCloneOnly">
|
|
+ <obj_ref id="C-clone"/>
|
|
+ <obj_ref id="Dummy"/>
|
|
+ </tag>
|
|
+ </tags>
|
|
+"""
|
|
+
|
|
+
|
|
+FIXTURE_TAGS_RESULT_XML = """
|
|
+ <tags>
|
|
+ <tag id="TagNotCloneOnly">
|
|
+ <obj_ref id="Dummy"/>
|
|
+ </tag>
|
|
+ </tags>
|
|
+"""
|
|
+
|
|
+
|
|
class Unclone(
|
|
TestCase,
|
|
get_assert_pcs_effect_mixin(
|
|
@@ -66,6 +98,22 @@ class Unclone(
|
|
):
|
|
empty_cib = rc("cib-empty.xml")
|
|
|
|
+ def assert_tags_xml(self, expected_xml):
|
|
+ self.assert_resources_xml_in_cib(
|
|
+ expected_xml,
|
|
+ get_cib_part_func=lambda cib: etree.tostring(
|
|
+ etree.parse(cib).findall(".//tags")[0],
|
|
+ ),
|
|
+ )
|
|
+
|
|
+ def assert_constraint_xml(self, expected_xml):
|
|
+ self.assert_resources_xml_in_cib(
|
|
+ expected_xml,
|
|
+ get_cib_part_func=lambda cib: etree.tostring(
|
|
+ etree.parse(cib).findall(".//constraints")[0],
|
|
+ ),
|
|
+ )
|
|
+
|
|
def setUp(self):
|
|
# pylint: disable=invalid-name
|
|
self.temp_cib = get_tmp_file("tier1_cib_resource_group_ungroup")
|
|
@@ -75,18 +123,7 @@ class Unclone(
|
|
"resources", FIXTURE_CLONE, FIXTURE_DUMMY,
|
|
)
|
|
xml_manip.append_to_first_tag_name(
|
|
- "configuration",
|
|
- """
|
|
- <tags>
|
|
- <tag id="T1">
|
|
- <obj_ref id="C-clone"/>
|
|
- <obj_ref id="Dummy"/>
|
|
- </tag>
|
|
- <tag id="T2">
|
|
- <obj_ref id="C-clone"/>
|
|
- </tag>
|
|
- </tags>
|
|
- """,
|
|
+ "configuration", FIXTURE_TAGS_CONFIG_XML,
|
|
)
|
|
xml_manip.append_to_first_tag_name(
|
|
"constraints",
|
|
@@ -95,8 +132,8 @@ class Unclone(
|
|
rsc="C-clone" score="INFINITY"/>
|
|
""",
|
|
"""
|
|
- <rsc_location id="location-T1-rh7-1-INFINITY" node="rh7-1" rsc="T1"
|
|
- score="INFINITY"/>
|
|
+ <rsc_location id="location-TagCloneOnly-rh7-1-INFINITY"
|
|
+ node="rh7-1" rsc="TagCloneOnly" score="INFINITY"/>
|
|
""",
|
|
)
|
|
write_data_to_tmpfile(str(xml_manip), self.temp_cib)
|
|
@@ -111,6 +148,8 @@ class Unclone(
|
|
"Error: could not find resource: NonExistentClone\n",
|
|
)
|
|
self.assert_resources_xml_in_cib(FIXTURE_CLONE_AND_RESOURCE)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_CONFIG_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CONSTRAINTS_CONFIG_XML)
|
|
|
|
def test_not_clone_resource(self):
|
|
self.assert_pcs_fail(
|
|
@@ -118,9 +157,15 @@ class Unclone(
|
|
"Error: 'Dummy' is not a clone resource\n",
|
|
)
|
|
self.assert_resources_xml_in_cib(FIXTURE_CLONE_AND_RESOURCE)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_CONFIG_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CONSTRAINTS_CONFIG_XML)
|
|
|
|
def test_unclone_clone_id(self):
|
|
self.assert_effect("resource unclone C-clone", FIXTURE_RESOURCES)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_RESULT_XML)
|
|
+ self.assert_constraint_xml("<constraints/>")
|
|
|
|
def test_unclone_resoruce_id(self):
|
|
self.assert_effect("resource unclone C", FIXTURE_RESOURCES)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_RESULT_XML)
|
|
+ self.assert_constraint_xml("<constraints/>")
|
|
diff --git a/pcs_test/tier1/cib_resource/test_group_ungroup.py b/pcs_test/tier1/cib_resource/test_group_ungroup.py
|
|
index f86e9890..88cc315d 100644
|
|
--- a/pcs_test/tier1/cib_resource/test_group_ungroup.py
|
|
+++ b/pcs_test/tier1/cib_resource/test_group_ungroup.py
|
|
@@ -64,14 +64,63 @@ FIXTURE_AGROUP_XML = fixture_group_xml(
|
|
)
|
|
|
|
|
|
-class TestGroupMixin(
|
|
- get_assert_pcs_effect_mixin(
|
|
- lambda cib: etree.tostring(
|
|
- # pylint:disable=undefined-variable
|
|
- etree.parse(cib).findall(".//resources")[0]
|
|
- )
|
|
- ),
|
|
-):
|
|
+FIXTURE_CONSTRAINTS_CONFIG_XML = """
|
|
+ <constraints>
|
|
+ <rsc_location id="location-AGroup-rh7-1-INFINITY" node="rh7-1"
|
|
+ rsc="AGroup" score="INFINITY"/>
|
|
+ <rsc_location id="location-TagGroupOnly-rh7-1-INFINITY"
|
|
+ node="rh7-1" rsc="TagGroupOnly" score="INFINITY"/>
|
|
+ </constraints>
|
|
+"""
|
|
+
|
|
+FIXTURE_CLONE_TAG_CONSTRAINTS = """
|
|
+ <constraints>
|
|
+ <rsc_location id="location-AGroup-rh7-1-INFINITY" node="rh7-1"
|
|
+ rsc="AGroup-clone" score="INFINITY"
|
|
+ />
|
|
+ <rsc_location id="location-TagGroupOnly-rh7-1-INFINITY"
|
|
+ node="rh7-1" rsc="TagGroupOnly" score="INFINITY"
|
|
+ />
|
|
+ </constraints>
|
|
+"""
|
|
+
|
|
+
|
|
+FIXTURE_CLONE_CONSTRAINT = """
|
|
+ <constraints>
|
|
+ <rsc_location id="location-AGroup-rh7-1-INFINITY" node="rh7-1"
|
|
+ rsc="AGroup-clone" score="INFINITY"
|
|
+ />
|
|
+ </constraints>
|
|
+"""
|
|
+
|
|
+
|
|
+FIXTURE_TAGS_CONFIG_XML = """
|
|
+ <tags>
|
|
+ <tag id="TagGroupOnly">
|
|
+ <obj_ref id="AGroup"/>
|
|
+ </tag>
|
|
+ <tag id="TagNotGroupOnly">
|
|
+ <obj_ref id="AGroup"/>
|
|
+ <obj_ref id="A1"/>
|
|
+ <obj_ref id="A2"/>
|
|
+ <obj_ref id="A3"/>
|
|
+ </tag>
|
|
+ </tags>
|
|
+"""
|
|
+
|
|
+
|
|
+FIXTURE_TAGS_RESULT_XML = """
|
|
+ <tags>
|
|
+ <tag id="TagNotGroupOnly">
|
|
+ <obj_ref id="A1"/>
|
|
+ <obj_ref id="A2"/>
|
|
+ <obj_ref id="A3"/>
|
|
+ </tag>
|
|
+ </tags>
|
|
+"""
|
|
+
|
|
+
|
|
+class TestGroupMixin:
|
|
empty_cib = rc("cib-empty.xml")
|
|
|
|
def setUp(self):
|
|
@@ -81,17 +130,7 @@ class TestGroupMixin(
|
|
xml_manip = XmlManipulation.from_file(self.empty_cib)
|
|
xml_manip.append_to_first_tag_name("resources", FIXTURE_AGROUP_XML)
|
|
xml_manip.append_to_first_tag_name(
|
|
- "configuration",
|
|
- """
|
|
- <tags>
|
|
- <tag id="T1">
|
|
- <obj_ref id="AGroup"/>
|
|
- </tag>
|
|
- <tag id="T2">
|
|
- <obj_ref id="AGroup"/>
|
|
- </tag>
|
|
- </tags>
|
|
- """,
|
|
+ "configuration", FIXTURE_TAGS_CONFIG_XML,
|
|
)
|
|
xml_manip.append_to_first_tag_name(
|
|
"constraints",
|
|
@@ -100,8 +139,8 @@ class TestGroupMixin(
|
|
rsc="AGroup" score="INFINITY"/>
|
|
""",
|
|
"""
|
|
- <rsc_location id="location-T1-rh7-1-INFINITY" node="rh7-1" rsc="T1"
|
|
- score="INFINITY"/>
|
|
+ <rsc_location id="location-TagGroupOnly-rh7-1-INFINITY"
|
|
+ node="rh7-1" rsc="TagGroupOnly" score="INFINITY"/>
|
|
""",
|
|
)
|
|
write_data_to_tmpfile(str(xml_manip), self.temp_cib)
|
|
@@ -111,9 +150,33 @@ class TestGroupMixin(
|
|
self.temp_cib.close()
|
|
|
|
|
|
-class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
+class GroupDeleteRemoveUngroupBase(
|
|
+ get_assert_pcs_effect_mixin(
|
|
+ lambda cib: etree.tostring(
|
|
+ # pylint:disable=undefined-variable
|
|
+ etree.parse(cib).findall(".//resources")[0]
|
|
+ )
|
|
+ ),
|
|
+ TestGroupMixin,
|
|
+):
|
|
command = None
|
|
|
|
+ def assert_tags_xml(self, expected_xml):
|
|
+ self.assert_resources_xml_in_cib(
|
|
+ expected_xml,
|
|
+ get_cib_part_func=lambda cib: etree.tostring(
|
|
+ etree.parse(cib).findall(".//tags")[0],
|
|
+ ),
|
|
+ )
|
|
+
|
|
+ def assert_constraint_xml(self, expected_xml):
|
|
+ self.assert_resources_xml_in_cib(
|
|
+ expected_xml,
|
|
+ get_cib_part_func=lambda cib: etree.tostring(
|
|
+ etree.parse(cib).findall(".//constraints")[0],
|
|
+ ),
|
|
+ )
|
|
+
|
|
def test_nonexistent_group(self):
|
|
self.assert_pcs_fail(
|
|
f"resource {self.command} NonExistentGroup",
|
|
@@ -122,6 +185,8 @@ class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
self.assert_resources_xml_in_cib(
|
|
fixture_resources_xml([FIXTURE_AGROUP_XML]),
|
|
)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_CONFIG_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CONSTRAINTS_CONFIG_XML)
|
|
|
|
def test_not_a_group_id(self):
|
|
self.assert_pcs_fail(
|
|
@@ -130,6 +195,8 @@ class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
self.assert_resources_xml_in_cib(
|
|
fixture_resources_xml([FIXTURE_AGROUP_XML]),
|
|
)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_CONFIG_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CONSTRAINTS_CONFIG_XML)
|
|
|
|
def test_whole_group(self):
|
|
self.assert_effect(
|
|
@@ -142,10 +209,12 @@ class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
],
|
|
),
|
|
output=(
|
|
- "Removing Constraint - location-T1-rh7-1-INFINITY\n"
|
|
+ "Removing Constraint - location-TagGroupOnly-rh7-1-INFINITY\n"
|
|
"Removing Constraint - location-AGroup-rh7-1-INFINITY\n"
|
|
),
|
|
)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_RESULT_XML)
|
|
+ self.assert_constraint_xml("<constraints/>")
|
|
|
|
def test_specified_resources(self):
|
|
self.assert_effect(
|
|
@@ -160,6 +229,26 @@ class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
],
|
|
),
|
|
)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_CONFIG_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CONSTRAINTS_CONFIG_XML)
|
|
+
|
|
+ def test_all_resources(self):
|
|
+ self.assert_effect(
|
|
+ f"resource {self.command} AGroup A1 A2 A3",
|
|
+ fixture_resources_xml(
|
|
+ [
|
|
+ fixture_primitive_xml("A1"),
|
|
+ fixture_primitive_xml("A2"),
|
|
+ fixture_primitive_xml("A3"),
|
|
+ ],
|
|
+ ),
|
|
+ output=(
|
|
+ "Removing Constraint - location-TagGroupOnly-rh7-1-INFINITY\n"
|
|
+ "Removing Constraint - location-AGroup-rh7-1-INFINITY\n"
|
|
+ ),
|
|
+ )
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_RESULT_XML)
|
|
+ self.assert_constraint_xml("<constraints/>")
|
|
|
|
def test_cloned_group(self):
|
|
self.assert_pcs_success("resource clone AGroup")
|
|
@@ -172,6 +261,8 @@ class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
[fixture_clone_xml("AGroup-clone", FIXTURE_AGROUP_XML)],
|
|
)
|
|
)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_CONFIG_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CLONE_TAG_CONSTRAINTS)
|
|
|
|
def test_cloned_group_all_resorces_specified(self):
|
|
self.assert_pcs_success("resource clone AGroup")
|
|
@@ -184,6 +275,8 @@ class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
[fixture_clone_xml("AGroup-clone", FIXTURE_AGROUP_XML)],
|
|
)
|
|
)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_CONFIG_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CLONE_TAG_CONSTRAINTS)
|
|
|
|
def test_cloned_group_with_one_resource(self):
|
|
self.assert_pcs_success("resource clone AGroup")
|
|
@@ -199,8 +292,10 @@ class GroupDeleteRemoveUngroupBase(TestGroupMixin):
|
|
fixture_primitive_xml("A2"),
|
|
],
|
|
),
|
|
- output="Removing Constraint - location-T1-rh7-1-INFINITY\n",
|
|
+ output="Removing Constraint - location-TagGroupOnly-rh7-1-INFINITY\n",
|
|
)
|
|
+ self.assert_tags_xml(FIXTURE_TAGS_RESULT_XML)
|
|
+ self.assert_constraint_xml(FIXTURE_CLONE_CONSTRAINT)
|
|
|
|
|
|
class ResourceUngroup(GroupDeleteRemoveUngroupBase, TestCase):
|
|
diff --git a/pcs_test/tools/cib.py b/pcs_test/tools/cib.py
|
|
index d52176cf..5eaaa92e 100644
|
|
--- a/pcs_test/tools/cib.py
|
|
+++ b/pcs_test/tools/cib.py
|
|
@@ -30,8 +30,14 @@ def xml_format(xml_string):
|
|
|
|
def get_assert_pcs_effect_mixin(get_cib_part):
|
|
class AssertPcsEffectMixin(AssertPcsMixin):
|
|
- def assert_resources_xml_in_cib(self, expected_xml_resources):
|
|
- xml = get_cib_part(self.temp_cib)
|
|
+ def assert_resources_xml_in_cib(
|
|
+ self, expected_xml_resources, get_cib_part_func=None,
|
|
+ ):
|
|
+ self.temp_cib.seek(0)
|
|
+ if get_cib_part_func is not None:
|
|
+ xml = get_cib_part_func(self.temp_cib)
|
|
+ else:
|
|
+ xml = get_cib_part(self.temp_cib)
|
|
try:
|
|
assert_xml_equal(expected_xml_resources, xml.decode())
|
|
except AssertionError as e:
|
|
--
|
|
2.25.4
|
|
|