Blob Blame History Raw
From b56bf42759b18ed7b98dc98d3897b3cdf7b3ce5a Mon Sep 17 00:00:00 2001
From: Ondrej Mular <omular@redhat.com>
Date: Thu, 11 Jun 2020 16:53:09 +0200
Subject: [PATCH 1/6] GUI: fix race-condition when removing resource

---
 pcs/lib/cib/tools.py      | 30 ++++++++++++++++++++----------
 pcs/test/test_acl.py      |  4 ++--
 pcs/test/test_resource.py | 33 +++++++++++++++++++++++++++++++++
 pcsd/public/js/pcsd.js    |  2 +-
 4 files changed, 56 insertions(+), 13 deletions(-)

diff --git a/pcs/lib/cib/tools.py b/pcs/lib/cib/tools.py
index ab2a9df5..e9599c43 100644
--- a/pcs/lib/cib/tools.py
+++ b/pcs/lib/cib/tools.py
@@ -56,11 +56,14 @@ class IdProvider(object):
         return report_list
 
 
-def does_id_exist(tree, check_id):
+def get_configuration_elements_by_id(tree, check_id):
     """
-    Checks to see if id exists in the xml dom passed
-    tree cib etree node
-    check_id id to check
+    Return any configuration elements (not in status section of cib) with value
+    of attribte id specified as 'check_id'
+
+    tree -- any element in xml tree, whole tree (not only its subtree) will be
+        searched
+    check_id -- id to find
     """
 
     # do not search in /cib/status, it may contain references to previously
@@ -70,7 +73,7 @@ def does_id_exist(tree, check_id):
     #which will be named the same as the value of the remote-node attribute of
     #the explicit resource. So the value of nvpair named "remote-node" is
     #considered to be id
-    existing = get_root(tree).xpath("""
+    return get_root(tree).xpath("""
         (
             /cib/*[name()!="status"]
             |
@@ -96,7 +99,15 @@ def does_id_exist(tree, check_id):
             )
         ]
     """.format(check_id))
-    return len(existing) > 0
+
+
+def does_id_exist(tree, check_id):
+    """
+    Checks to see if id exists in the xml dom passed
+    tree cib etree node
+    check_id id to check
+    """
+    return len(get_configuration_elements_by_id(tree, check_id)) > 0
 
 def validate_id_does_not_exist(tree, id):
     """
@@ -155,11 +166,10 @@ def find_element_by_tag_and_id(
     if element_list:
         return element_list[0]
 
-    element = get_root(context_element).find(
-        './/*[@id="{0}"]'.format(element_id)
-    )
+    elements = get_configuration_elements_by_id(context_element, element_id)
 
-    if element is not None:
+    if elements:
+        element = elements[0]
         raise LibraryError(
             reports.id_belongs_to_unexpected_type(
                 element_id,
diff --git a/pcs/test/test_acl.py b/pcs/test/test_acl.py
index a59beb0a..2a3b6d66 100644
--- a/pcs/test/test_acl.py
+++ b/pcs/test/test_acl.py
@@ -395,7 +395,7 @@ Group: group2
 
         o,r = pcs("acl group delete user1")
         assert r == 1
-        ac(o,"Error: 'user1' is not an ACL group\n")
+        ac(o,"Error: ACL group 'user1' does not exist\n")
 
         o,r = pcs("acl")
         ac(o, """\
@@ -861,7 +861,7 @@ Role: role4
         self.assert_pcs_success("acl user create user1")
         self.assert_pcs_fail(
             "acl role assign role1 to group user1",
-            "Error: 'user1' is not an ACL group\n"
+            "Error: ACL group 'user1' does not exist\n"
         )
 
     def test_assign_unassign_role_to_group_with_to(self):
diff --git a/pcs/test/test_resource.py b/pcs/test/test_resource.py
index 972323f9..fd1a0731 100644
--- a/pcs/test/test_resource.py
+++ b/pcs/test/test_resource.py
@@ -3542,6 +3542,39 @@ Error: Cannot remove more than one resource from cloned group
             )
         )
 
+    def testResourceDisableNonExistingWithFailedAction(self):
+        with open(temp_cib, "w") as f:
+            f.truncate()
+            f.write(
+                """
+                <cib epoch="557" num_updates="122" admin_epoch="0" crm_feature_set="3.0.14" validate-with="pacemaker-2.10" update-origin="rh7-3" update-client="crmd" cib-last-written="Thu Aug 23 16:49:17 2012" have-quorum="0" dc-uuid="2">
+                  <configuration>
+                    <crm_config/>
+                    <nodes>
+                    </nodes>
+                    <resources/>
+                    <constraints/>
+                  </configuration>
+                  <status>
+                    <node_state id="1" uname="rh7-1" in_ccm="true" crmd="online" crm-debug-origin="do_update_resource" join="member" expected="member">
+                      <lrm id="1">
+                        <lrm_resources>
+                          <lrm_resource id="A" type="apache" class="ocf" provider="heartbeat">
+                            <lrm_rsc_op id="A_last_0" operation_key="A_monitor_0" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.0.14" transition-key="1:1104:7:817ee250-d179-483a-819e-9be9cb0e06df" transition-magic="0:7;1:1104:7:817ee250-d179-483a-819e-9be9cb0e06df" exit-reason="" on_node="rh7-1" call-id="1079" rc-code="7" op-status="0" interval="0" last-run="1591791198" last-rc-change="1591791198" exec-time="275" queue-time="0" op-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+                          </lrm_resource>
+                        </lrm_resources>
+                      </lrm>
+                    </node_state>
+                  </status>
+                </cib>
+                """
+            )
+        self.assert_pcs_fail(
+            "resource disable A",
+            "Error: bundle/clone/group/master/resource 'A' does not exist\n"
+        )
+
+
     def testResourceEnable(self):
         # These tests were moved to
         # pcs/lib/commands/test/resource/test_resource_enable_disable.py .
diff --git a/pcsd/public/js/pcsd.js b/pcsd/public/js/pcsd.js
index 20c19434..60c3da59 100644
--- a/pcsd/public/js/pcsd.js
+++ b/pcsd/public/js/pcsd.js
@@ -1441,7 +1441,7 @@ function remove_resource(ids, force) {
         error == "timeout" ||
         xhr.responseText == '{"noresponse":true}'
       ) {
-        message = "Operation takes longer to complete than expected.";
+        message = "Operation takes longer to complete than expected but it will continue in the background.";
       } else {
         message = "Unable to remove resources (" + error + ")";
         if (
-- 
2.21.0