Blob Blame History Raw
From a3f2fe109fd8d6a30ac8834ad513be6dba34a4b0 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 10 Dec 2020 15:57:44 -0500
Subject: [PATCH 01/18] Test: cts: Add regression tests for crm_resource
 output.

This adds a bunch of tests for various configurations of location
constraints and colocation constraints on resources.  This also updates
the regex that removes the absolute path from the cmdline request, now
that crm_resource is also using formatted output.
---
 cts/cli/constraints.xml      |  58 ++++
 cts/cli/regression.tools.exp | 782 +++++++++++++++++++++++++++++++++++++++++++
 cts/cts-cli.in               |  25 +-
 3 files changed, 864 insertions(+), 1 deletion(-)
 create mode 100644 cts/cli/constraints.xml

diff --git a/cts/cli/constraints.xml b/cts/cli/constraints.xml
new file mode 100644
index 0000000..1a27aa7
--- /dev/null
+++ b/cts/cli/constraints.xml
@@ -0,0 +1,58 @@
+<cib crm_feature_set="3.3.0" validate-with="pacemaker-3.3" epoch="1" num_updates="1" admin_epoch="1" cib-last-written="Tue May  5 12:04:36 2020" update-origin="cluster01" update-client="crmd" update-user="hacluster" have-quorum="1" dc-uuid="2">
+  <configuration>
+    <crm_config>
+      <cluster_property_set id="cib-bootstrap-options">
+        <nvpair id="cib-bootstrap-options-have-watchdog" name="have-watchdog" value="false"/>
+        <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="2.0.4-1.e97f9675f.git.el7-e97f9675f"/>
+        <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"/>
+        <nvpair id="cib-bootstrap-options-cluster-name" name="cluster-name" value="test-cluster"/>
+        <nvpair id="cib-bootstrap-options-stonith-enabled" name="stonith-enabled" value="true"/>
+        <nvpair id="cib-bootstrap-options-maintenance-mode" name="maintenance-mode" value="false"/>
+      </cluster_property_set>
+    </crm_config>
+    <nodes>
+      <node id="1" uname="cluster01"/>
+      <node id="2" uname="cluster02"/>
+    </nodes>
+    <resources>
+      <primitive class="ocf" id="prim1" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim2" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim3" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim4" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim5" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim6" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim7" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim8" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim9" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim10" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim11" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim12" provider="pacemaker" type="Dummy"/>
+      <primitive class="ocf" id="prim13" provider="pacemaker" type="Dummy"/>
+      <group id="group">
+        <primitive class="ocf" id="gr1" provider="pacemaker" type="Dummy"/>
+        <primitive class="ocf" id="gr2" provider="pacemaker" type="Dummy"/>
+        <primitive class="ocf" id="gr3" provider="pacemaker" type="Dummy"/>
+      </group>
+      <clone id="clone">
+        <primitive class="ocf" id="cl1" provider="pacemaker" type="Dummy"/>
+      </clone>
+    </resources>
+    <constraints>
+      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" score="INFINITY" with-rsc="prim3"/>
+      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" score="INFINITY" with-rsc="prim4"/>
+      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" score="INFINITY" with-rsc="prim5"/>
+      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" score="INFINITY" with-rsc="prim4"/>
+      <rsc_location id="prim2-on-cluster1" rsc="prim2" node="cluster01" score="INFINITY"/>
+      <rsc_location id="prim4-on-cluster2" rsc="prim4" node="cluster02" score="INFINITY"/>
+      <rsc_location id="prim6-not-on-cluster2" rsc="prim6" node="cluster02" score="-INFINITY"/>
+      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" score="INFINITY" with-rsc="group"/>
+      <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" score="INFINITY" with-rsc="gr2"/>
+      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" score="INFINITY" with-rsc="clone"/>
+      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" score="INFINITY" with-rsc="prim12"/>
+      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" score="INFINITY" with-rsc="prim13"/>
+      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" score="INFINITY" with-rsc="prim11"/>
+    </constraints>
+    <op_defaults/>
+  </configuration>
+  <status/>
+</cib>
diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
index 221730d..565cacc 100644
--- a/cts/cli/regression.tools.exp
+++ b/cts/cli/regression.tools.exp
@@ -3470,3 +3470,785 @@ Removing constraint: cli-prefer-dummy
 
 =#=#=#= End test: Create an XML patchset - Error occurred (1) =#=#=#=
 * Passed: crm_diff       - Create an XML patchset
+=#=#=#= Begin test: Check locations and constraints for prim1 =#=#=#=
+prim1:
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim1 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim1
+=#=#=#= Begin test: Recursively check locations and constraints for prim1 =#=#=#=
+prim1:
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim1 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim1
+=#=#=#= Begin test: Check locations and constraints for prim1 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim1 --output-as=xml">
+  <constraints>
+    <resource id="prim1">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim1 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim1 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim1 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim1 --output-as=xml">
+  <constraints>
+    <resource id="prim1">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim1 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim1 in XML
+=#=#=#= Begin test: Check locations and constraints for prim2 =#=#=#=
+prim2:
+  * Locations:
+    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
+Colocations:
+  * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim2 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim2
+=#=#=#= Begin test: Recursively check locations and constraints for prim2 =#=#=#=
+prim2:
+  * Locations:
+    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
+Colocations:
+  * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim2 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim2
+=#=#=#= Begin test: Check locations and constraints for prim2 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim2 --output-as=xml">
+  <constraints>
+    <resource id="prim2">
+      <locations>
+        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
+      </locations>
+    </resource>
+    <colocations>
+      <colocation peer="prim3" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim2 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim2 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim2 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim2 --output-as=xml">
+  <constraints>
+    <resource id="prim2">
+      <locations>
+        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
+      </locations>
+    </resource>
+    <colocations>
+      <colocation peer="prim3" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim2 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim2 in XML
+=#=#=#= Begin test: Check locations and constraints for prim3 =#=#=#=
+Colocations:
+  * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * Locations:
+    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
+prim3:
+  * Locations:
+Colocations:
+  * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+=#=#=#= End test: Check locations and constraints for prim3 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim3
+=#=#=#= Begin test: Recursively check locations and constraints for prim3 =#=#=#=
+Colocations:
+  * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * Locations:
+    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
+prim3:
+  * Locations:
+Colocations:
+  * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+=#=#=#= End test: Recursively check locations and constraints for prim3 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim3
+=#=#=#= Begin test: Check locations and constraints for prim3 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim3 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim2" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
+      </locations>
+    </colocations>
+    <resource id="prim3">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim4" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim3 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim3 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim3 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim3 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim2" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
+      </locations>
+    </colocations>
+    <resource id="prim3">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim4" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim3 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim3 in XML
+=#=#=#= Begin test: Check locations and constraints for prim4 =#=#=#=
+Colocations:
+  * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * Locations:
+  * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * Locations:
+prim4:
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+Colocations:
+  * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim4 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim4
+=#=#=#= Begin test: Recursively check locations and constraints for prim4 =#=#=#=
+Colocations:
+  * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * Locations:
+  * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * Locations:
+prim4:
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+Colocations:
+  * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim4 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim4
+=#=#=#= Begin test: Check locations and constraints for prim4 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim4 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim10" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <locations/>
+      <colocation peer="prim3" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim4">
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </resource>
+    <colocations>
+      <colocation peer="prim5" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim4 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim4 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim4 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim4 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim10" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <locations/>
+      <colocation peer="prim3" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim4">
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </resource>
+    <colocations>
+      <colocation peer="prim5" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim4 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim4 in XML
+=#=#=#= Begin test: Check locations and constraints for prim5 =#=#=#=
+Colocations:
+  * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+prim5:
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim5 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim5
+=#=#=#= Begin test: Recursively check locations and constraints for prim5 =#=#=#=
+Colocations:
+  * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+prim5:
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim5 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim5
+=#=#=#= Begin test: Check locations and constraints for prim5 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim5 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim4" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </colocations>
+    <resource id="prim5">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim5 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim5 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim5 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim5 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim4" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </colocations>
+    <resource id="prim5">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim5 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim5 in XML
+=#=#=#= Begin test: Check locations and constraints for prim6 =#=#=#=
+prim6:
+  * Locations:
+    * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2)
+=#=#=#= End test: Check locations and constraints for prim6 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim6
+=#=#=#= Begin test: Recursively check locations and constraints for prim6 =#=#=#=
+prim6:
+  * Locations:
+    * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2)
+=#=#=#= End test: Recursively check locations and constraints for prim6 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim6
+=#=#=#= Begin test: Check locations and constraints for prim6 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim6 --output-as=xml">
+  <constraints>
+    <resource id="prim6">
+      <locations>
+        <location host="cluster02" id="prim6-not-on-cluster2" score="-INFINITY"/>
+      </locations>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim6 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim6 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim6 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim6 --output-as=xml">
+  <constraints>
+    <resource id="prim6">
+      <locations>
+        <location host="cluster02" id="prim6-not-on-cluster2" score="-INFINITY"/>
+      </locations>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim6 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim6 in XML
+=#=#=#= Begin test: Check locations and constraints for prim7 =#=#=#=
+prim7:
+  * Locations:
+Colocations:
+  * group (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim7 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim7
+=#=#=#= Begin test: Recursively check locations and constraints for prim7 =#=#=#=
+prim7:
+  * Locations:
+Colocations:
+  * group (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim7 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim7
+=#=#=#= Begin test: Check locations and constraints for prim7 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim7 --output-as=xml">
+  <constraints>
+    <resource id="prim7">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="group" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim7 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim7 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim7 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim7 --output-as=xml">
+  <constraints>
+    <resource id="prim7">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="group" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim7 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim7 in XML
+=#=#=#= Begin test: Check locations and constraints for prim8 =#=#=#=
+prim8:
+  * Locations:
+Colocations:
+  * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim8 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim8
+=#=#=#= Begin test: Recursively check locations and constraints for prim8 =#=#=#=
+prim8:
+  * Locations:
+Colocations:
+  * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim8 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim8
+=#=#=#= Begin test: Check locations and constraints for prim8 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim8 --output-as=xml">
+  <constraints>
+    <resource id="prim8">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="gr2" id="colocation-prim8-gr2-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim8 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim8 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim8 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim8 --output-as=xml">
+  <constraints>
+    <resource id="prim8">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="gr2" id="colocation-prim8-gr2-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim8 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim8 in XML
+=#=#=#= Begin test: Check locations and constraints for prim9 =#=#=#=
+prim9:
+  * Locations:
+Colocations:
+  * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim9 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim9
+=#=#=#= Begin test: Recursively check locations and constraints for prim9 =#=#=#=
+prim9:
+  * Locations:
+Colocations:
+  * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim9 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim9
+=#=#=#= Begin test: Check locations and constraints for prim9 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim9 --output-as=xml">
+  <constraints>
+    <resource id="prim9">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="clone" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim9 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim9 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim9 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim9 --output-as=xml">
+  <constraints>
+    <resource id="prim9">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="clone" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim9 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim9 in XML
+=#=#=#= Begin test: Check locations and constraints for prim10 =#=#=#=
+prim10:
+  * Locations:
+Colocations:
+  * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+=#=#=#= End test: Check locations and constraints for prim10 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim10
+=#=#=#= Begin test: Recursively check locations and constraints for prim10 =#=#=#=
+prim10:
+  * Locations:
+Colocations:
+  * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * Locations:
+    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+=#=#=#= End test: Recursively check locations and constraints for prim10 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim10
+=#=#=#= Begin test: Check locations and constraints for prim10 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim10 --output-as=xml">
+  <constraints>
+    <resource id="prim10">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim4" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim10 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim10 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim10 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim10 --output-as=xml">
+  <constraints>
+    <resource id="prim10">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim4" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <locations>
+        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
+      </locations>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim10 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim10 in XML
+=#=#=#= Begin test: Check locations and constraints for prim11 =#=#=#=
+Colocations:
+  * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * Locations:
+prim11:
+  * Locations:
+Colocations:
+  * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim11 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim11
+=#=#=#= Begin test: Recursively check locations and constraints for prim11 =#=#=#=
+Colocations:
+  * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * Locations:
+prim11:
+  * Locations:
+Colocations:
+  * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim11 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim11
+=#=#=#= Begin test: Check locations and constraints for prim11 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim11 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim13" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim11">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim12" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim11 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim11 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim11 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim11 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim13" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim11">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim12" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim11 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim11 in XML
+=#=#=#= Begin test: Check locations and constraints for prim12 =#=#=#=
+Colocations:
+  * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * Locations:
+prim12:
+  * Locations:
+Colocations:
+  * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim12 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim12
+=#=#=#= Begin test: Recursively check locations and constraints for prim12 =#=#=#=
+Colocations:
+  * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * Locations:
+prim12:
+  * Locations:
+Colocations:
+  * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim12 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim12
+=#=#=#= Begin test: Check locations and constraints for prim12 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim12 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim11" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim12">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim13" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim12 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim12 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim12 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim12 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim11" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim12">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim13" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim12 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim12 in XML
+=#=#=#= Begin test: Check locations and constraints for prim13 =#=#=#=
+Colocations:
+  * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * Locations:
+prim13:
+  * Locations:
+Colocations:
+  * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * Locations:
+=#=#=#= End test: Check locations and constraints for prim13 - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim13
+=#=#=#= Begin test: Recursively check locations and constraints for prim13 =#=#=#=
+Colocations:
+  * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * Locations:
+prim13:
+  * Locations:
+Colocations:
+  * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for prim13 - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim13
+=#=#=#= Begin test: Check locations and constraints for prim13 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r prim13 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim12" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim13">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim11" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for prim13 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for prim13 in XML
+=#=#=#= Begin test: Recursively check locations and constraints for prim13 in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r prim13 --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim12" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="prim13">
+      <locations/>
+    </resource>
+    <colocations>
+      <colocation peer="prim11" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for prim13 in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for prim13 in XML
+=#=#=#= Begin test: Check locations and constraints for group =#=#=#=
+Colocations:
+  * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * Locations:
+group:
+  * Locations:
+=#=#=#= End test: Check locations and constraints for group - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for group
+=#=#=#= Begin test: Recursively check locations and constraints for group =#=#=#=
+Colocations:
+  * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * Locations:
+group:
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for group - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for group
+=#=#=#= Begin test: Check locations and constraints for group in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r group --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim7" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="group">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for group in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for group in XML
+=#=#=#= Begin test: Recursively check locations and constraints for group in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r group --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim7" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="group">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for group in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for group in XML
+=#=#=#= Begin test: Check locations and constraints for clone =#=#=#=
+Colocations:
+  * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * Locations:
+clone:
+  * Locations:
+=#=#=#= End test: Check locations and constraints for clone - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for clone
+=#=#=#= Begin test: Recursively check locations and constraints for clone =#=#=#=
+Colocations:
+  * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * Locations:
+clone:
+  * Locations:
+=#=#=#= End test: Recursively check locations and constraints for clone - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for clone
+=#=#=#= Begin test: Check locations and constraints for clone in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -a -r clone --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim9" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="clone">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Check locations and constraints for clone in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Check locations and constraints for clone in XML
+=#=#=#= Begin test: Recursively check locations and constraints for clone in XML =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -A -r clone --output-as=xml">
+  <constraints>
+    <colocations>
+      <colocation peer="prim9" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <locations/>
+    </colocations>
+    <resource id="clone">
+      <locations/>
+    </resource>
+  </constraints>
+  <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Recursively check locations and constraints for clone in XML - OK (0) =#=#=#=
+* Passed: crm_resource   - Recursively check locations and constraints for clone in XML
diff --git a/cts/cts-cli.in b/cts/cts-cli.in
index 14b4ce9..dfdd3de 100755
--- a/cts/cts-cli.in
+++ b/cts/cts-cli.in
@@ -768,6 +768,29 @@ function test_tools() {
     desc="Create an XML patchset"
     cmd="crm_diff -o $test_home/cli/crm_diff_old.xml -n $test_home/cli/crm_diff_new.xml"
     test_assert $CRM_EX_ERROR 0
+
+    export CIB_file="$test_home/cli/constraints.xml"
+
+    for rsc in prim1 prim2 prim3 prim4 prim5 prim6 prim7 prim8 prim9 \
+               prim10 prim11 prim12 prim13 group clone; do
+        desc="Check locations and constraints for $rsc"
+        cmd="crm_resource -a -r $rsc"
+        test_assert $CRM_EX_OK 0
+
+        desc="Recursively check locations and constraints for $rsc"
+        cmd="crm_resource -A -r $rsc"
+        test_assert $CRM_EX_OK 0
+
+        desc="Check locations and constraints for $rsc in XML"
+        cmd="crm_resource -a -r $rsc --output-as=xml"
+        test_assert $CRM_EX_OK 0
+
+        desc="Recursively check locations and constraints for $rsc in XML"
+        cmd="crm_resource -A -r $rsc --output-as=xml"
+        test_assert $CRM_EX_OK 0
+    done
+
+    unset CIB_file
 }
 
 INVALID_PERIODS=(
@@ -1604,7 +1627,7 @@ for t in $tests; do
         -e 's/last_change time=\".*\"/last_change time=\"\"/' \
         -e 's/ api-version=\".*\" / api-version=\"X\" /' \
         -e 's/ version=\".*\" / version=\"\" /' \
-        -e 's/request=\".*crm_mon/request=\"crm_mon/' \
+        -e 's/request=\".*\(crm_[a-zA-Z0-9]*\)/request=\"\1/' \
         -e 's/crm_feature_set="[^"]*" //'\
         -e 's/validate-with="[^"]*" //'\
         -e 's/Created new pacemaker-.* configuration/Created new pacemaker configuration/'\
-- 
1.8.3.1


From c3acf54d012bd113ddc69bd6412f272879408e5d Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 7 Dec 2020 15:43:27 -0500
Subject: [PATCH 02/18] Refactor: scheduler: Add
 pe__clear_resource_flags_on_all.

This function clears a given flag on all resources in the data set.
---
 include/crm/pengine/internal.h |  1 +
 lib/pacemaker/pcmk_output.c    | 26 ++++----------------------
 lib/pengine/utils.c            |  9 +++++++++
 tools/crm_resource_runtime.c   |  6 +-----
 4 files changed, 15 insertions(+), 27 deletions(-)

diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h
index 89e17b8..a4f8086 100644
--- a/include/crm/pengine/internal.h
+++ b/include/crm/pengine/internal.h
@@ -529,6 +529,7 @@ void pe_action_set_flag_reason(const char *function, long line, pe_action_t *act
 
 void pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags);
 void pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags);
+void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag);
 
 gboolean add_tag_ref(GHashTable * tags, const char * tag_name,  const char * obj_ref);
 
diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 1f5a25b..d3e93ca 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -283,7 +283,6 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
     pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
     gboolean recursive = va_arg(args, gboolean);
 
-    GList *lpc = NULL;
     xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
                                                  data_set->input);
 
@@ -292,11 +291,7 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
     // Constraints apply to group/clone, not member/instance
     rsc = uber_parent(rsc);
 
-    for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
-        pe_resource_t *r = (pe_resource_t *) lpc->data;
-
-        pe__clear_resource_flags(r, pe_rsc_allocating);
-    }
+    pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 
     out->message(out, "colocations-list", rsc, TRUE, recursive);
 
@@ -304,11 +299,7 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
     out->message(out, "locations-list", rsc);
     out->end_list(out);
 
-    for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
-        pe_resource_t *r = (pe_resource_t *) lpc->data;
-
-        pe__clear_resource_flags(r, pe_rsc_allocating);
-    }
+    pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 
     out->message(out, "colocations-list", rsc, FALSE, recursive);
     return pcmk_rc_ok;
@@ -321,7 +312,6 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
     pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
     gboolean recursive = va_arg(args, gboolean);
 
-    GList *lpc = NULL;
     xmlNodePtr cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS,
                                                  data_set->input);
 
@@ -330,11 +320,7 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
     // Constraints apply to group/clone, not member/instance
     rsc = uber_parent(rsc);
 
-    for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
-        pe_resource_t *r = (pe_resource_t *) lpc->data;
-
-        pe__clear_resource_flags(r, pe_rsc_allocating);
-    }
+    pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 
     pcmk__output_xml_create_parent(out, "constraints", NULL);
 
@@ -346,11 +332,7 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
     out->message(out, "locations-list", rsc);
     pcmk__output_xml_pop_parent(out);
 
-    for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
-        pe_resource_t *r = (pe_resource_t *) lpc->data;
-
-        pe__clear_resource_flags(r, pe_rsc_allocating);
-    }
+    pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 
     out->message(out, "colocations-list", rsc, FALSE, recursive);
     return pcmk_rc_ok;
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
index b0922fa..b07afbe 100644
--- a/lib/pengine/utils.c
+++ b/lib/pengine/utils.c
@@ -2010,6 +2010,15 @@ pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
 }
 
 void
+pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
+{
+    for (GList *lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
+        pe_resource_t *r = (pe_resource_t *) lpc->data;
+        pe__clear_resource_flags_recursive(r, flag);
+    }
+}
+
+void
 pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
 {
     pe__set_resource_flags(rsc, flags);
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index 3a9feac..f4500db 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -386,11 +386,7 @@ cli_resource_update_attribute(pcmk__output_t *out, pe_resource_t *rsc,
                 need_init = FALSE;
                 unpack_constraints(cib_constraints, data_set);
 
-                for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
-                    pe_resource_t *r = (pe_resource_t *) lpc->data;
-
-                    pe__clear_resource_flags(r, pe_rsc_allocating);
-                }
+                pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
             }
 
             crm_debug("Looking for dependencies %p", rsc->rsc_cons_lhs);
-- 
1.8.3.1


From d7e95983ef14bdc25fdc42f51d7d7d9fb2240ec8 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 7 Dec 2020 15:54:40 -0500
Subject: [PATCH 03/18] Refactor: libpacemaker: Add colocations_header.

This moves code that is going to be useful in multiple places into its
own function.

This also fixes a missing paren at the end of the header that was being
printed out, which means the test output has changed.  So also update
the test output.
---
 cts/cli/regression.tools.exp | 76 ++++++++++++++++++++++----------------------
 lib/pacemaker/pcmk_output.c  | 36 ++++++++++++++-------
 2 files changed, 62 insertions(+), 50 deletions(-)

diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
index 565cacc..0e69d0d 100644
--- a/cts/cli/regression.tools.exp
+++ b/cts/cli/regression.tools.exp
@@ -3507,7 +3507,7 @@ prim2:
   * Locations:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 Colocations:
-  * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim2 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim2
@@ -3516,7 +3516,7 @@ prim2:
   * Locations:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 Colocations:
-  * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim2 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim2
@@ -3556,26 +3556,26 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim2 in XML
 =#=#=#= Begin test: Check locations and constraints for prim3 =#=#=#=
 Colocations:
-  * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
   * Locations:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 prim3:
   * Locations:
 Colocations:
-  * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 =#=#=#= End test: Check locations and constraints for prim3 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim3
 =#=#=#= Begin test: Recursively check locations and constraints for prim3 =#=#=#=
 Colocations:
-  * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY
+  * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
   * Locations:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 prim3:
   * Locations:
 Colocations:
-  * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 =#=#=#= End test: Recursively check locations and constraints for prim3 - OK (0) =#=#=#=
@@ -3628,29 +3628,29 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim3 in XML
 =#=#=#= Begin test: Check locations and constraints for prim4 =#=#=#=
 Colocations:
-  * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * Locations:
-  * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
   * Locations:
 prim4:
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 Colocations:
-  * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim4 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim4
 =#=#=#= Begin test: Recursively check locations and constraints for prim4 =#=#=#=
 Colocations:
-  * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * Locations:
-  * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY
+  * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
   * Locations:
 prim4:
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 Colocations:
-  * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim4 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim4
@@ -3702,7 +3702,7 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim4 in XML
 =#=#=#= Begin test: Check locations and constraints for prim5 =#=#=#=
 Colocations:
-  * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 prim5:
@@ -3711,7 +3711,7 @@ prim5:
 * Passed: crm_resource   - Check locations and constraints for prim5
 =#=#=#= Begin test: Recursively check locations and constraints for prim5 =#=#=#=
 Colocations:
-  * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY
+  * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 prim5:
@@ -3794,7 +3794,7 @@ prim6:
 prim7:
   * Locations:
 Colocations:
-  * group (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * group (score=INFINITY, id=colocation-prim7-group-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim7 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim7
@@ -3802,7 +3802,7 @@ Colocations:
 prim7:
   * Locations:
 Colocations:
-  * group (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * group (score=INFINITY, id=colocation-prim7-group-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim7 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim7
@@ -3840,7 +3840,7 @@ Colocations:
 prim8:
   * Locations:
 Colocations:
-  * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY
+  * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim8 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim8
@@ -3848,7 +3848,7 @@ Colocations:
 prim8:
   * Locations:
 Colocations:
-  * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY
+  * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim8 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim8
@@ -3886,7 +3886,7 @@ Colocations:
 prim9:
   * Locations:
 Colocations:
-  * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim9 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim9
@@ -3894,7 +3894,7 @@ Colocations:
 prim9:
   * Locations:
 Colocations:
-  * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim9 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim9
@@ -3932,7 +3932,7 @@ Colocations:
 prim10:
   * Locations:
 Colocations:
-  * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 =#=#=#= End test: Check locations and constraints for prim10 - OK (0) =#=#=#=
@@ -3941,7 +3941,7 @@ Colocations:
 prim10:
   * Locations:
 Colocations:
-  * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY
+  * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 =#=#=#= End test: Recursively check locations and constraints for prim10 - OK (0) =#=#=#=
@@ -3982,23 +3982,23 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim10 in XML
 =#=#=#= Begin test: Check locations and constraints for prim11 =#=#=#=
 Colocations:
-  * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
   * Locations:
 prim11:
   * Locations:
 Colocations:
-  * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim11 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim11
 =#=#=#= Begin test: Recursively check locations and constraints for prim11 =#=#=#=
 Colocations:
-  * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
   * Locations:
 prim11:
   * Locations:
 Colocations:
-  * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim11 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim11
@@ -4042,23 +4042,23 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim11 in XML
 =#=#=#= Begin test: Check locations and constraints for prim12 =#=#=#=
 Colocations:
-  * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
   * Locations:
 prim12:
   * Locations:
 Colocations:
-  * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim12 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim12
 =#=#=#= Begin test: Recursively check locations and constraints for prim12 =#=#=#=
 Colocations:
-  * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY
+  * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
   * Locations:
 prim12:
   * Locations:
 Colocations:
-  * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim12 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim12
@@ -4102,23 +4102,23 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim12 in XML
 =#=#=#= Begin test: Check locations and constraints for prim13 =#=#=#=
 Colocations:
-  * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
   * Locations:
 prim13:
   * Locations:
 Colocations:
-  * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
   * Locations:
 =#=#=#= End test: Check locations and constraints for prim13 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim13
 =#=#=#= Begin test: Recursively check locations and constraints for prim13 =#=#=#=
 Colocations:
-  * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY
+  * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
   * Locations:
 prim13:
   * Locations:
 Colocations:
-  * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY
+  * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
   * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim13 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim13
@@ -4162,7 +4162,7 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim13 in XML
 =#=#=#= Begin test: Check locations and constraints for group =#=#=#=
 Colocations:
-  * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY)
   * Locations:
 group:
   * Locations:
@@ -4170,7 +4170,7 @@ group:
 * Passed: crm_resource   - Check locations and constraints for group
 =#=#=#= Begin test: Recursively check locations and constraints for group =#=#=#=
 Colocations:
-  * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY
+  * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY)
   * Locations:
 group:
   * Locations:
@@ -4208,7 +4208,7 @@ group:
 * Passed: crm_resource   - Recursively check locations and constraints for group in XML
 =#=#=#= Begin test: Check locations and constraints for clone =#=#=#=
 Colocations:
-  * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY)
   * Locations:
 clone:
   * Locations:
@@ -4216,7 +4216,7 @@ clone:
 * Passed: crm_resource   - Check locations and constraints for clone
 =#=#=#= Begin test: Recursively check locations and constraints for clone =#=#=#=
 Colocations:
-  * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY
+  * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY)
   * Locations:
 clone:
   * Locations:
diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index d3e93ca..8ff3e9d 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -46,6 +46,26 @@ pcmk__out_epilogue(pcmk__output_t *out, xmlNodePtr *xml, int retval) {
     pcmk__output_free(out);
 }
 
+static char *
+colocations_header(pe_resource_t *rsc, rsc_colocation_t *cons,
+                   gboolean dependents) {
+    char *score = NULL;
+    char *retval = NULL;
+
+    score = score2char(cons->score);
+    if (cons->role_rh > RSC_ROLE_STARTED) {
+            retval = crm_strdup_printf("%s (score=%s, %s role=%s, id=%s)",
+                                       rsc->id, score, dependents ? "needs" : "with",
+                                       role2text(cons->role_rh), cons->id);
+    } else {
+        retval = crm_strdup_printf("%s (score=%s, id=%s)",
+                                   rsc->id, score, cons->id);
+    }
+
+    free(score);
+    return retval;
+}
+
 PCMK__OUTPUT_ARGS("colocations-list", "pe_resource_t *", "gboolean", "gboolean")
 static int colocations_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
@@ -67,9 +87,8 @@ static int colocations_list(pcmk__output_t *out, va_list args) {
     pe__set_resource_flags(rsc, pe_rsc_allocating);
     for (lpc = list; lpc != NULL; lpc = lpc->next) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
-
-        char *score = NULL;
         pe_resource_t *peer = cons->rsc_rh;
+        char *hdr = NULL;
 
         if (dependents) {
             peer = cons->rsc_lh;
@@ -101,17 +120,10 @@ static int colocations_list(pcmk__output_t *out, va_list args) {
             printed_header = true;
         }
 
-        score = score2char(cons->score);
-        if (cons->role_rh > RSC_ROLE_STARTED) {
-            out->list_item(out, NULL, "%s (score=%s, %s role=%s, id=%s",
-                           peer->id, score, dependents ? "needs" : "with",
-                           role2text(cons->role_rh), cons->id);
-        } else {
-            out->list_item(out, NULL, "%s (score=%s, id=%s",
-                           peer->id, score, cons->id);
-        }
+        hdr = colocations_header(peer, cons, dependents);
+        out->list_item(out, NULL, "%s", hdr);
+        free(hdr);
 
-        free(score);
         out->message(out, "locations-list", peer);
 
         if (!dependents && recursive) {
-- 
1.8.3.1


From 393342ea9a113e5453a4fd490c5f45557636902e Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 10 Dec 2020 11:31:14 -0500
Subject: [PATCH 04/18] Refactor: libpacemaker: Add colocations_xml_node.

This is like colocations_header, but for the XML side of things.  Also,
use XML_CONS_TAG_RSC_DEPEND for the XML tag name to bring us closer in
line with the CIB.  Finally, update the test output for the new code.
---
 cts/cli/regression.tools.exp | 76 ++++++++++++++++++++++----------------------
 lib/pacemaker/pcmk_output.c  | 49 +++++++++++++++++-----------
 2 files changed, 68 insertions(+), 57 deletions(-)

diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
index 0e69d0d..98c8f23 100644
--- a/cts/cli/regression.tools.exp
+++ b/cts/cli/regression.tools.exp
@@ -3529,7 +3529,7 @@ Colocations:
       </locations>
     </resource>
     <colocations>
-      <colocation peer="prim3" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3546,7 +3546,7 @@ Colocations:
       </locations>
     </resource>
     <colocations>
-      <colocation peer="prim3" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3584,7 +3584,7 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -a -r prim3 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim2" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
       <locations>
         <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
       </locations>
@@ -3593,7 +3593,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim4" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
       <locations>
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
       </locations>
@@ -3607,7 +3607,7 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim3 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim2" id="colocation-prim2-prim3-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
       <locations>
         <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
       </locations>
@@ -3616,7 +3616,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim4" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
       <locations>
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
       </locations>
@@ -3658,9 +3658,9 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -a -r prim4 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim10" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
       <locations/>
-      <colocation peer="prim3" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim4">
@@ -3669,7 +3669,7 @@ Colocations:
       </locations>
     </resource>
     <colocations>
-      <colocation peer="prim5" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3681,9 +3681,9 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim4 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim10" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
       <locations/>
-      <colocation peer="prim3" id="colocation-prim3-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim4">
@@ -3692,7 +3692,7 @@ Colocations:
       </locations>
     </resource>
     <colocations>
-      <colocation peer="prim5" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3722,7 +3722,7 @@ prim5:
 <pacemaker-result api-version="X" request="crm_resource -a -r prim5 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim4" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
       <locations>
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
       </locations>
@@ -3739,7 +3739,7 @@ prim5:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim5 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim4" id="colocation-prim4-prim5-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
       <locations>
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
       </locations>
@@ -3813,7 +3813,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="group" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3828,7 +3828,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="group" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3859,7 +3859,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="gr2" id="colocation-prim8-gr2-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3874,7 +3874,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="gr2" id="colocation-prim8-gr2-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3905,7 +3905,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="clone" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3920,7 +3920,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="clone" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -3953,7 +3953,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim4" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
       <locations>
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
       </locations>
@@ -3970,7 +3970,7 @@ Colocations:
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim4" id="colocation-prim10-prim4-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
       <locations>
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
       </locations>
@@ -4006,14 +4006,14 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -a -r prim11 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim13" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim11">
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim12" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -4025,14 +4025,14 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim11 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim13" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim11">
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim12" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -4066,14 +4066,14 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -a -r prim12 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim11" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim12">
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim13" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -4085,14 +4085,14 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim12 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim11" id="colocation-prim11-prim12-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim12">
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim13" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -4126,14 +4126,14 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -a -r prim13 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim12" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim13">
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim11" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -4145,14 +4145,14 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim13 --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim12" id="colocation-prim12-prim13-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="prim13">
       <locations/>
     </resource>
     <colocations>
-      <colocation peer="prim11" id="colocation-prim13-prim11-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
       <locations/>
     </colocations>
   </constraints>
@@ -4180,7 +4180,7 @@ group:
 <pacemaker-result api-version="X" request="crm_resource -a -r group --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim7" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="group">
@@ -4195,7 +4195,7 @@ group:
 <pacemaker-result api-version="X" request="crm_resource -A -r group --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim7" id="colocation-prim7-group-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="group">
@@ -4226,7 +4226,7 @@ clone:
 <pacemaker-result api-version="X" request="crm_resource -a -r clone --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim9" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="clone">
@@ -4241,7 +4241,7 @@ clone:
 <pacemaker-result api-version="X" request="crm_resource -A -r clone --output-as=xml">
   <constraints>
     <colocations>
-      <colocation peer="prim9" id="colocation-prim9-clone-INFINITY" score="INFINITY"/>
+      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
       <locations/>
     </colocations>
     <resource id="clone">
diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 8ff3e9d..78171d7 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -66,6 +66,35 @@ colocations_header(pe_resource_t *rsc, rsc_colocation_t *cons,
     return retval;
 }
 
+static void
+colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
+                     rsc_colocation_t *cons) {
+    char *score = NULL;
+    xmlNodePtr node = NULL;
+
+    score = score2char(cons->score);
+    node = pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_DEPEND,
+                                        "id", cons->id,
+                                        "rsc", cons->rsc_lh->id,
+                                        "with-rsc", cons->rsc_rh->id,
+                                        "score", score,
+                                        NULL);
+
+    if (cons->node_attribute) {
+        xmlSetProp(node, (pcmkXmlStr) "node-attribute", (pcmkXmlStr) cons->node_attribute);
+    }
+
+    if (cons->role_lh != RSC_ROLE_UNKNOWN) {
+        xmlSetProp(node, (pcmkXmlStr) "rsc-role", (pcmkXmlStr) role2text(cons->role_lh));
+    }
+
+    if (cons->role_rh != RSC_ROLE_UNKNOWN) {
+        xmlSetProp(node, (pcmkXmlStr) "with-rsc-role", (pcmkXmlStr) role2text(cons->role_rh));
+    }
+
+    free(score);
+}
+
 PCMK__OUTPUT_ARGS("colocations-list", "pe_resource_t *", "gboolean", "gboolean")
 static int colocations_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
@@ -160,7 +189,6 @@ static int colocations_list_xml(pcmk__output_t *out, va_list args) {
     for (lpc = list; lpc != NULL; lpc = lpc->next) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
         pe_resource_t *peer = cons->rsc_rh;
-        char *score = NULL;
 
         if (dependents) {
             peer = cons->rsc_lh;
@@ -195,24 +223,7 @@ static int colocations_list_xml(pcmk__output_t *out, va_list args) {
             printed_header = true;
         }
 
-        score = score2char(cons->score);
-        if (cons->role_rh > RSC_ROLE_STARTED) {
-            pcmk__output_create_xml_node(out, "colocation",
-                                         "peer", peer->id,
-                                         "id", cons->id,
-                                         "score", score,
-                                         "dependents", dependents ? "needs" : "with",
-                                         "role", role2text(cons->role_rh),
-                                         NULL);
-        } else {
-            pcmk__output_create_xml_node(out, "colocation",
-                                         "peer", peer->id,
-                                         "id", cons->id,
-                                         "score", score,
-                                         NULL);
-        }
-
-        free(score);
+        colocations_xml_node(out, peer, cons);
         out->message(out, "locations-list", peer);
 
         if (!dependents && recursive) {
-- 
1.8.3.1


From 1952bdb888fce9a686c60f99340ad904012ac807 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 18:43:31 -0500
Subject: [PATCH 05/18] Fix: libpacemaker: Don't show an empty locations list.

---
 cts/cli/regression.tools.exp | 236 ++++++++++---------------------------------
 lib/pacemaker/pcmk_output.c  |  19 ++--
 2 files changed, 61 insertions(+), 194 deletions(-)

diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
index 98c8f23..f5de14d 100644
--- a/cts/cli/regression.tools.exp
+++ b/cts/cli/regression.tools.exp
@@ -3472,20 +3472,16 @@ Removing constraint: cli-prefer-dummy
 * Passed: crm_diff       - Create an XML patchset
 =#=#=#= Begin test: Check locations and constraints for prim1 =#=#=#=
 prim1:
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim1 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim1
 =#=#=#= Begin test: Recursively check locations and constraints for prim1 =#=#=#=
 prim1:
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim1 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim1
 =#=#=#= Begin test: Check locations and constraints for prim1 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim1 --output-as=xml">
   <constraints>
-    <resource id="prim1">
-      <locations/>
-    </resource>
+    <resource id="prim1"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3494,9 +3490,7 @@ prim1:
 =#=#=#= Begin test: Recursively check locations and constraints for prim1 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim1 --output-as=xml">
   <constraints>
-    <resource id="prim1">
-      <locations/>
-    </resource>
+    <resource id="prim1"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3508,7 +3502,6 @@ prim2:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 Colocations:
   * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim2 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim2
 =#=#=#= Begin test: Recursively check locations and constraints for prim2 =#=#=#=
@@ -3517,20 +3510,18 @@ prim2:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 Colocations:
   * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim2 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim2
 =#=#=#= Begin test: Check locations and constraints for prim2 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim2 --output-as=xml">
   <constraints>
     <resource id="prim2">
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </locations>
+      </list>
     </resource>
     <colocations>
       <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3541,13 +3532,12 @@ Colocations:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim2 --output-as=xml">
   <constraints>
     <resource id="prim2">
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </locations>
+      </list>
     </resource>
     <colocations>
       <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3560,7 +3550,6 @@ Colocations:
   * Locations:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 prim3:
-  * Locations:
 Colocations:
   * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
   * Locations:
@@ -3573,7 +3562,6 @@ Colocations:
   * Locations:
     * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
 prim3:
-  * Locations:
 Colocations:
   * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
   * Locations:
@@ -3585,18 +3573,16 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
-    <resource id="prim3">
-      <locations/>
-    </resource>
+    <resource id="prim3"/>
     <colocations>
       <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3608,18 +3594,16 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
-    <resource id="prim3">
-      <locations/>
-    </resource>
+    <resource id="prim3"/>
     <colocations>
       <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3629,29 +3613,23 @@ Colocations:
 =#=#=#= Begin test: Check locations and constraints for prim4 =#=#=#=
 Colocations:
   * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
-  * Locations:
   * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
-  * Locations:
 prim4:
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 Colocations:
   * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim4 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim4
 =#=#=#= Begin test: Recursively check locations and constraints for prim4 =#=#=#=
 Colocations:
   * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
-  * Locations:
   * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
-  * Locations:
 prim4:
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 Colocations:
   * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim4 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim4
 =#=#=#= Begin test: Check locations and constraints for prim4 in XML =#=#=#=
@@ -3659,18 +3637,15 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <locations/>
       <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-      <locations/>
     </colocations>
     <resource id="prim4">
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </resource>
     <colocations>
       <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3682,18 +3657,15 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <locations/>
       <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-      <locations/>
     </colocations>
     <resource id="prim4">
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </resource>
     <colocations>
       <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3706,7 +3678,6 @@ Colocations:
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 prim5:
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim5 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim5
 =#=#=#= Begin test: Recursively check locations and constraints for prim5 =#=#=#=
@@ -3715,7 +3686,6 @@ Colocations:
   * Locations:
     * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
 prim5:
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim5 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim5
 =#=#=#= Begin test: Check locations and constraints for prim5 in XML =#=#=#=
@@ -3723,13 +3693,11 @@ prim5:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
-    <resource id="prim5">
-      <locations/>
-    </resource>
+    <resource id="prim5"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3740,13 +3708,11 @@ prim5:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
-    <resource id="prim5">
-      <locations/>
-    </resource>
+    <resource id="prim5"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3768,9 +3734,9 @@ prim6:
 <pacemaker-result api-version="X" request="crm_resource -a -r prim6 --output-as=xml">
   <constraints>
     <resource id="prim6">
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim6-not-on-cluster2" score="-INFINITY"/>
-      </locations>
+      </list>
     </resource>
   </constraints>
   <status code="0" message="OK"/>
@@ -3781,9 +3747,9 @@ prim6:
 <pacemaker-result api-version="X" request="crm_resource -A -r prim6 --output-as=xml">
   <constraints>
     <resource id="prim6">
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim6-not-on-cluster2" score="-INFINITY"/>
-      </locations>
+      </list>
     </resource>
   </constraints>
   <status code="0" message="OK"/>
@@ -3792,29 +3758,22 @@ prim6:
 * Passed: crm_resource   - Recursively check locations and constraints for prim6 in XML
 =#=#=#= Begin test: Check locations and constraints for prim7 =#=#=#=
 prim7:
-  * Locations:
 Colocations:
   * group (score=INFINITY, id=colocation-prim7-group-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim7 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim7
 =#=#=#= Begin test: Recursively check locations and constraints for prim7 =#=#=#=
 prim7:
-  * Locations:
 Colocations:
   * group (score=INFINITY, id=colocation-prim7-group-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim7 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim7
 =#=#=#= Begin test: Check locations and constraints for prim7 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim7 --output-as=xml">
   <constraints>
-    <resource id="prim7">
-      <locations/>
-    </resource>
+    <resource id="prim7"/>
     <colocations>
       <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3824,12 +3783,9 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim7 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim7 --output-as=xml">
   <constraints>
-    <resource id="prim7">
-      <locations/>
-    </resource>
+    <resource id="prim7"/>
     <colocations>
       <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3838,29 +3794,22 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim7 in XML
 =#=#=#= Begin test: Check locations and constraints for prim8 =#=#=#=
 prim8:
-  * Locations:
 Colocations:
   * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim8 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim8
 =#=#=#= Begin test: Recursively check locations and constraints for prim8 =#=#=#=
 prim8:
-  * Locations:
 Colocations:
   * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim8 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim8
 =#=#=#= Begin test: Check locations and constraints for prim8 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim8 --output-as=xml">
   <constraints>
-    <resource id="prim8">
-      <locations/>
-    </resource>
+    <resource id="prim8"/>
     <colocations>
       <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3870,12 +3819,9 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim8 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim8 --output-as=xml">
   <constraints>
-    <resource id="prim8">
-      <locations/>
-    </resource>
+    <resource id="prim8"/>
     <colocations>
       <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3884,29 +3830,22 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim8 in XML
 =#=#=#= Begin test: Check locations and constraints for prim9 =#=#=#=
 prim9:
-  * Locations:
 Colocations:
   * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim9 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim9
 =#=#=#= Begin test: Recursively check locations and constraints for prim9 =#=#=#=
 prim9:
-  * Locations:
 Colocations:
   * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim9 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim9
 =#=#=#= Begin test: Check locations and constraints for prim9 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim9 --output-as=xml">
   <constraints>
-    <resource id="prim9">
-      <locations/>
-    </resource>
+    <resource id="prim9"/>
     <colocations>
       <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3916,12 +3855,9 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim9 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim9 --output-as=xml">
   <constraints>
-    <resource id="prim9">
-      <locations/>
-    </resource>
+    <resource id="prim9"/>
     <colocations>
       <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3930,7 +3866,6 @@ Colocations:
 * Passed: crm_resource   - Recursively check locations and constraints for prim9 in XML
 =#=#=#= Begin test: Check locations and constraints for prim10 =#=#=#=
 prim10:
-  * Locations:
 Colocations:
   * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * Locations:
@@ -3939,7 +3874,6 @@ Colocations:
 * Passed: crm_resource   - Check locations and constraints for prim10
 =#=#=#= Begin test: Recursively check locations and constraints for prim10 =#=#=#=
 prim10:
-  * Locations:
 Colocations:
   * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * Locations:
@@ -3949,14 +3883,12 @@ Colocations:
 =#=#=#= Begin test: Check locations and constraints for prim10 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim10 --output-as=xml">
   <constraints>
-    <resource id="prim10">
-      <locations/>
-    </resource>
+    <resource id="prim10"/>
     <colocations>
       <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3966,14 +3898,12 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim10 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim10 --output-as=xml">
   <constraints>
-    <resource id="prim10">
-      <locations/>
-    </resource>
+    <resource id="prim10"/>
     <colocations>
       <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <locations>
+      <list name="locations" count="1">
         <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </locations>
+      </list>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -3983,23 +3913,17 @@ Colocations:
 =#=#=#= Begin test: Check locations and constraints for prim11 =#=#=#=
 Colocations:
   * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
-  * Locations:
 prim11:
-  * Locations:
 Colocations:
   * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim11 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim11
 =#=#=#= Begin test: Recursively check locations and constraints for prim11 =#=#=#=
 Colocations:
   * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
-  * Locations:
 prim11:
-  * Locations:
 Colocations:
   * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim11 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim11
 =#=#=#= Begin test: Check locations and constraints for prim11 in XML =#=#=#=
@@ -4007,14 +3931,10 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="prim11">
-      <locations/>
-    </resource>
+    <resource id="prim11"/>
     <colocations>
       <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -4026,14 +3946,10 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="prim11">
-      <locations/>
-    </resource>
+    <resource id="prim11"/>
     <colocations>
       <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -4043,23 +3959,17 @@ Colocations:
 =#=#=#= Begin test: Check locations and constraints for prim12 =#=#=#=
 Colocations:
   * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
-  * Locations:
 prim12:
-  * Locations:
 Colocations:
   * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim12 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim12
 =#=#=#= Begin test: Recursively check locations and constraints for prim12 =#=#=#=
 Colocations:
   * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
-  * Locations:
 prim12:
-  * Locations:
 Colocations:
   * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim12 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim12
 =#=#=#= Begin test: Check locations and constraints for prim12 in XML =#=#=#=
@@ -4067,14 +3977,10 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="prim12">
-      <locations/>
-    </resource>
+    <resource id="prim12"/>
     <colocations>
       <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -4086,14 +3992,10 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="prim12">
-      <locations/>
-    </resource>
+    <resource id="prim12"/>
     <colocations>
       <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -4103,23 +4005,17 @@ Colocations:
 =#=#=#= Begin test: Check locations and constraints for prim13 =#=#=#=
 Colocations:
   * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
-  * Locations:
 prim13:
-  * Locations:
 Colocations:
   * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
-  * Locations:
 =#=#=#= End test: Check locations and constraints for prim13 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim13
 =#=#=#= Begin test: Recursively check locations and constraints for prim13 =#=#=#=
 Colocations:
   * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
-  * Locations:
 prim13:
-  * Locations:
 Colocations:
   * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for prim13 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim13
 =#=#=#= Begin test: Check locations and constraints for prim13 in XML =#=#=#=
@@ -4127,14 +4023,10 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="prim13">
-      <locations/>
-    </resource>
+    <resource id="prim13"/>
     <colocations>
       <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -4146,14 +4038,10 @@ Colocations:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="prim13">
-      <locations/>
-    </resource>
+    <resource id="prim13"/>
     <colocations>
       <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-      <locations/>
     </colocations>
   </constraints>
   <status code="0" message="OK"/>
@@ -4163,17 +4051,13 @@ Colocations:
 =#=#=#= Begin test: Check locations and constraints for group =#=#=#=
 Colocations:
   * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY)
-  * Locations:
 group:
-  * Locations:
 =#=#=#= End test: Check locations and constraints for group - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for group
 =#=#=#= Begin test: Recursively check locations and constraints for group =#=#=#=
 Colocations:
   * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY)
-  * Locations:
 group:
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for group - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for group
 =#=#=#= Begin test: Check locations and constraints for group in XML =#=#=#=
@@ -4181,11 +4065,8 @@ group:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="group">
-      <locations/>
-    </resource>
+    <resource id="group"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -4196,11 +4077,8 @@ group:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="group">
-      <locations/>
-    </resource>
+    <resource id="group"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -4209,17 +4087,13 @@ group:
 =#=#=#= Begin test: Check locations and constraints for clone =#=#=#=
 Colocations:
   * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY)
-  * Locations:
 clone:
-  * Locations:
 =#=#=#= End test: Check locations and constraints for clone - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for clone
 =#=#=#= Begin test: Recursively check locations and constraints for clone =#=#=#=
 Colocations:
   * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY)
-  * Locations:
 clone:
-  * Locations:
 =#=#=#= End test: Recursively check locations and constraints for clone - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for clone
 =#=#=#= Begin test: Check locations and constraints for clone in XML =#=#=#=
@@ -4227,11 +4101,8 @@ clone:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="clone">
-      <locations/>
-    </resource>
+    <resource id="clone"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -4242,11 +4113,8 @@ clone:
   <constraints>
     <colocations>
       <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-      <locations/>
     </colocations>
-    <resource id="clone">
-      <locations/>
-    </resource>
+    <resource id="clone"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 78171d7..aab6876 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -244,8 +244,7 @@ static int locations_list(pcmk__output_t *out, va_list args) {
 
     GList *lpc = NULL;
     GList *list = rsc->rsc_location;
-
-    out->begin_list(out, NULL, NULL, "Locations");
+    int rc = pcmk_rc_no_output;
 
     for (lpc = list; lpc != NULL; lpc = lpc->next) {
         pe__location_t *cons = lpc->data;
@@ -256,15 +255,15 @@ static int locations_list(pcmk__output_t *out, va_list args) {
             pe_node_t *node = (pe_node_t *) lpc2->data;
             char *score = score2char(node->weight);
 
+            PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Locations");
             out->list_item(out, NULL, "Node %s (score=%s, id=%s)",
                            node->details->uname, score, cons->id);
             free(score);
         }
     }
 
-    out->end_list(out);
-
-    return pcmk_rc_ok;
+    PCMK__OUTPUT_LIST_FOOTER(out, rc);
+    return rc;
 }
 
 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
@@ -273,8 +272,7 @@ static int locations_list_xml(pcmk__output_t *out, va_list args) {
 
     GList *lpc = NULL;
     GList *list = rsc->rsc_location;
-
-    pcmk__output_xml_create_parent(out, "locations", NULL);
+    int rc = pcmk_rc_no_output;
 
     for (lpc = list; lpc != NULL; lpc = lpc->next) {
         pe__location_t *cons = lpc->data;
@@ -285,6 +283,8 @@ static int locations_list_xml(pcmk__output_t *out, va_list args) {
             pe_node_t *node = (pe_node_t *) lpc2->data;
             char *score = score2char(node->weight);
 
+            PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
+
             pcmk__output_create_xml_node(out, "location",
                                          "host", node->details->uname,
                                          "id", cons->id,
@@ -294,9 +294,8 @@ static int locations_list_xml(pcmk__output_t *out, va_list args) {
         }
     }
 
-    pcmk__output_xml_pop_parent(out);
-
-    return pcmk_rc_ok;
+    PCMK__OUTPUT_LIST_FOOTER(out, rc);
+    return rc;
 }
 
 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
-- 
1.8.3.1


From e67b94edb679a62cec5ebc5a3f398c7aec3949f9 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 14:48:22 -0500
Subject: [PATCH 06/18] Refactor: libpacemaker: Split colocations_list into two
 functions.

The point of this is to make it easier to follow along with what these
functions do by eliminating some of the conditionals.  However, the
names are confusing and probably can't be made much less confusing.

* rscs_colocated_with_list outputs a list of all the resources that are
  colocated with the given resource argument.
* rsc_is_colocated_with_list outputs a list of all the resources that
  the given resource argument is colocated with.
---
 lib/pacemaker/pcmk_output.c | 190 ++++++++++++++++++++++++++++----------------
 1 file changed, 121 insertions(+), 69 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index aab6876..dcb024c 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -95,53 +95,133 @@ colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
     free(score);
 }
 
-PCMK__OUTPUT_ARGS("colocations-list", "pe_resource_t *", "gboolean", "gboolean")
-static int colocations_list(pcmk__output_t *out, va_list args) {
+PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
+static int
+rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
-    gboolean dependents = va_arg(args, gboolean);
     gboolean recursive = va_arg(args, gboolean);
 
-    GList *lpc = NULL;
-    GList *list = rsc->rsc_cons;
     bool printed_header = false;
 
-    if (dependents) {
-        list = rsc->rsc_cons_lhs;
-    }
-
     if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
         return pcmk_rc_no_output;
     }
 
     pe__set_resource_flags(rsc, pe_rsc_allocating);
-    for (lpc = list; lpc != NULL; lpc = lpc->next) {
+    for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
-        pe_resource_t *peer = cons->rsc_rh;
         char *hdr = NULL;
 
-        if (dependents) {
-            peer = cons->rsc_lh;
+        if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
+            if (!printed_header) {
+                out->begin_list(out, NULL, NULL, "Colocations");
+                printed_header = true;
+            }
+
+            out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_rh->id, cons->id);
+            continue;
+        }
+
+        if (!printed_header) {
+            out->begin_list(out, NULL, NULL, "Colocations");
+            printed_header = true;
         }
 
-        if (pcmk_is_set(peer->flags, pe_rsc_allocating)) {
-            if (dependents == FALSE) {
-                if (!printed_header) {
-                    out->begin_list(out, NULL, NULL, "Colocations");
-                    printed_header = true;
-                }
+        hdr = colocations_header(cons->rsc_rh, cons, FALSE);
+        out->list_item(out, NULL, "%s", hdr);
+        free(hdr);
+
+        out->message(out, "locations-list", cons->rsc_rh);
+
+        if (recursive) {
+            out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
+        }
+    }
 
-                out->list_item(out, NULL, "%s (id=%s - loop)", peer->id, cons->id);
+    if (printed_header) {
+        out->end_list(out);
+    }
+
+    return pcmk_rc_no_output;
+}
+
+PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
+static int
+rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
+    pe_resource_t *rsc = va_arg(args, pe_resource_t *);
+    gboolean recursive = va_arg(args, gboolean);
+
+    bool printed_header = false;
+
+    if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
+        return pcmk_rc_ok;
+    }
+
+    pe__set_resource_flags(rsc, pe_rsc_allocating);
+    for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
+        rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
+
+        if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
+            if (!printed_header) {
+                pcmk__output_xml_create_parent(out, "colocations", NULL);
+                printed_header = true;
             }
+
+            pcmk__output_create_xml_node(out, "colocation",
+                                         "peer", cons->rsc_rh->id,
+                                         "id", cons->id,
+                                         NULL);
+            continue;
+        }
+
+        if (!printed_header) {
+            pcmk__output_xml_create_parent(out, "colocations", NULL);
+            printed_header = true;
+        }
+
+        colocations_xml_node(out, cons->rsc_rh, cons);
+        out->message(out, "locations-list", cons->rsc_rh);
+
+        if (recursive) {
+            out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
+        }
+    }
+
+    if (printed_header) {
+        pcmk__output_xml_pop_parent(out);
+    }
+
+    return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
+static int
+rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
+    pe_resource_t *rsc = va_arg(args, pe_resource_t *);
+    gboolean recursive = va_arg(args, gboolean);
+
+    bool printed_header = false;
+
+    if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
+        return pcmk_rc_no_output;
+    }
+
+    pe__set_resource_flags(rsc, pe_rsc_allocating);
+    for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
+        rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
+        char *hdr = NULL;
+
+        if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
             continue;
         }
 
-        if (dependents && recursive) {
+        if (recursive) {
             if (!printed_header) {
                 out->begin_list(out, NULL, NULL, "Colocations");
                 printed_header = true;
             }
 
-            out->message(out, "colocations-list", rsc, dependents, recursive);
+            out->message(out, "rscs-colocated-with-list", rsc, recursive);
         }
 
         if (!printed_header) {
@@ -149,15 +229,11 @@ static int colocations_list(pcmk__output_t *out, va_list args) {
             printed_header = true;
         }
 
-        hdr = colocations_header(peer, cons, dependents);
+        hdr = colocations_header(cons->rsc_lh, cons, TRUE);
         out->list_item(out, NULL, "%s", hdr);
         free(hdr);
 
-        out->message(out, "locations-list", peer);
-
-        if (!dependents && recursive) {
-            out->message(out, "colocations-list", rsc, dependents, recursive);
-        }
+        out->message(out, "locations-list", cons->rsc_lh);
     }
 
     if (printed_header) {
@@ -167,55 +243,33 @@ static int colocations_list(pcmk__output_t *out, va_list args) {
     return pcmk_rc_no_output;
 }
 
-PCMK__OUTPUT_ARGS("colocations-list", "pe_resource_t *", "gboolean", "gboolean")
-static int colocations_list_xml(pcmk__output_t *out, va_list args) {
+PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
+static int
+rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
-    gboolean dependents = va_arg(args, gboolean);
     gboolean recursive = va_arg(args, gboolean);
 
-    GList *lpc = NULL;
-    GList *list = rsc->rsc_cons;
     bool printed_header = false;
 
-    if (dependents) {
-        list = rsc->rsc_cons_lhs;
-    }
-
     if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
         return pcmk_rc_ok;
     }
 
     pe__set_resource_flags(rsc, pe_rsc_allocating);
-    for (lpc = list; lpc != NULL; lpc = lpc->next) {
+    for (GList *lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
-        pe_resource_t *peer = cons->rsc_rh;
 
-        if (dependents) {
-            peer = cons->rsc_lh;
-        }
-
-        if (pcmk_is_set(peer->flags, pe_rsc_allocating)) {
-            if (dependents == FALSE) {
-                if (!printed_header) {
-                    pcmk__output_xml_create_parent(out, "colocations", NULL);
-                    printed_header = true;
-                }
-
-                pcmk__output_create_xml_node(out, "colocation",
-                                             "peer", peer->id,
-                                             "id", cons->id,
-                                             NULL);
-            }
+        if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
             continue;
         }
 
-        if (dependents && recursive) {
+        if (recursive) {
             if (!printed_header) {
                 pcmk__output_xml_create_parent(out, "colocations", NULL);
                 printed_header = true;
             }
 
-            out->message(out, "colocations-list", rsc, dependents, recursive);
+            out->message(out, "rscs-colocated-with-list", rsc, recursive);
         }
 
         if (!printed_header) {
@@ -223,12 +277,8 @@ static int colocations_list_xml(pcmk__output_t *out, va_list args) {
             printed_header = true;
         }
 
-        colocations_xml_node(out, peer, cons);
-        out->message(out, "locations-list", peer);
-
-        if (!dependents && recursive) {
-            out->message(out, "colocations-list", rsc, dependents, recursive);
-        }
+        colocations_xml_node(out, cons->rsc_lh, cons);
+        out->message(out, "locations-list", cons->rsc_lh);
     }
 
     if (printed_header) {
@@ -315,7 +365,7 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 
-    out->message(out, "colocations-list", rsc, TRUE, recursive);
+    out->message(out, "rscs-colocated-with-list", rsc, recursive);
 
     out->begin_list(out, NULL, NULL, "%s", rsc->id);
     out->message(out, "locations-list", rsc);
@@ -323,7 +373,7 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 
-    out->message(out, "colocations-list", rsc, FALSE, recursive);
+    out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
     return pcmk_rc_ok;
 }
 
@@ -346,7 +396,7 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
 
     pcmk__output_xml_create_parent(out, "constraints", NULL);
 
-    out->message(out, "colocations-list", rsc, TRUE, recursive);
+    out->message(out, "rscs-colocated-with-list", rsc, recursive);
 
     pcmk__output_xml_create_parent(out, "resource",
                                    "id", rsc->id,
@@ -356,7 +406,7 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
 
-    out->message(out, "colocations-list", rsc, FALSE, recursive);
+    out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
     return pcmk_rc_ok;
 }
 
@@ -529,8 +579,10 @@ crmadmin_node_xml(pcmk__output_t *out, va_list args)
 }
 
 static pcmk__message_entry_t fmt_functions[] = {
-    { "colocations-list", "default", colocations_list },
-    { "colocations-list", "xml", colocations_list_xml },
+    { "rsc-is-colocated-with-list", "default", rsc_is_colocated_with_list },
+    { "rsc-is-colocated-with-list", "xml", rsc_is_colocated_with_list_xml },
+    { "rscs-colocated-with-list", "default", rscs_colocated_with_list },
+    { "rscs-colocated-with-list", "xml", rscs_colocated_with_list_xml },
     { "locations-list", "default", locations_list },
     { "locations-list", "xml", locations_list_xml },
     { "stacks-constraints", "default", stacks_and_constraints },
-- 
1.8.3.1


From 75c45fef1f292d3d6428a10a1a25a4a151d3633a Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 14:55:35 -0500
Subject: [PATCH 07/18] Refactor: libpacemaker: Use list macros in constraint
 formatted output.

This just gets rid of all the uses of printed_header in favor of
PCMK__OUTPUT_LIST_HEADER and PCMK__OUTPUT_LIST_FOOTER.
---
 lib/pacemaker/pcmk_output.c | 99 ++++++++++++---------------------------------
 1 file changed, 25 insertions(+), 74 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index dcb024c..2eb3ced 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -101,10 +101,10 @@ rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
     gboolean recursive = va_arg(args, gboolean);
 
-    bool printed_header = false;
+    int rc = pcmk_rc_no_output;
 
     if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
-        return pcmk_rc_no_output;
+        return rc;
     }
 
     pe__set_resource_flags(rsc, pe_rsc_allocating);
@@ -112,21 +112,13 @@ rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
         char *hdr = NULL;
 
-        if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
-            if (!printed_header) {
-                out->begin_list(out, NULL, NULL, "Colocations");
-                printed_header = true;
-            }
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations")
 
+        if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
             out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_rh->id, cons->id);
             continue;
         }
 
-        if (!printed_header) {
-            out->begin_list(out, NULL, NULL, "Colocations");
-            printed_header = true;
-        }
-
         hdr = colocations_header(cons->rsc_rh, cons, FALSE);
         out->list_item(out, NULL, "%s", hdr);
         free(hdr);
@@ -138,11 +130,8 @@ rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
         }
     }
 
-    if (printed_header) {
-        out->end_list(out);
-    }
-
-    return pcmk_rc_no_output;
+    PCMK__OUTPUT_LIST_FOOTER(out, rc);
+    return rc;
 }
 
 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
@@ -151,22 +140,19 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
     gboolean recursive = va_arg(args, gboolean);
 
-    bool printed_header = false;
+    int rc = pcmk_rc_no_output;
 
     if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
-        return pcmk_rc_ok;
+        return rc;
     }
 
     pe__set_resource_flags(rsc, pe_rsc_allocating);
     for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
 
-        if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
-            if (!printed_header) {
-                pcmk__output_xml_create_parent(out, "colocations", NULL);
-                printed_header = true;
-            }
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations");
 
+        if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
             pcmk__output_create_xml_node(out, "colocation",
                                          "peer", cons->rsc_rh->id,
                                          "id", cons->id,
@@ -174,11 +160,6 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
             continue;
         }
 
-        if (!printed_header) {
-            pcmk__output_xml_create_parent(out, "colocations", NULL);
-            printed_header = true;
-        }
-
         colocations_xml_node(out, cons->rsc_rh, cons);
         out->message(out, "locations-list", cons->rsc_rh);
 
@@ -187,11 +168,8 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
         }
     }
 
-    if (printed_header) {
-        pcmk__output_xml_pop_parent(out);
-    }
-
-    return pcmk_rc_ok;
+    PCMK__OUTPUT_LIST_FOOTER(out, rc);
+    return rc;
 }
 
 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
@@ -200,10 +178,10 @@ rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
     gboolean recursive = va_arg(args, gboolean);
 
-    bool printed_header = false;
+    int rc = pcmk_rc_no_output;
 
     if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
-        return pcmk_rc_no_output;
+        return rc;
     }
 
     pe__set_resource_flags(rsc, pe_rsc_allocating);
@@ -215,20 +193,12 @@ rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
             continue;
         }
 
-        if (recursive) {
-            if (!printed_header) {
-                out->begin_list(out, NULL, NULL, "Colocations");
-                printed_header = true;
-            }
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations");
 
+        if (recursive) {
             out->message(out, "rscs-colocated-with-list", rsc, recursive);
         }
 
-        if (!printed_header) {
-            out->begin_list(out, NULL, NULL, "Colocations");
-            printed_header = true;
-        }
-
         hdr = colocations_header(cons->rsc_lh, cons, TRUE);
         out->list_item(out, NULL, "%s", hdr);
         free(hdr);
@@ -236,11 +206,8 @@ rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
         out->message(out, "locations-list", cons->rsc_lh);
     }
 
-    if (printed_header) {
-        out->end_list(out);
-    }
-
-    return pcmk_rc_no_output;
+    PCMK__OUTPUT_LIST_FOOTER(out, rc);
+    return rc;
 }
 
 PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
@@ -249,10 +216,10 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
     gboolean recursive = va_arg(args, gboolean);
 
-    bool printed_header = false;
+    int rc = pcmk_rc_no_output;
 
     if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
-        return pcmk_rc_ok;
+        return rc;
     }
 
     pe__set_resource_flags(rsc, pe_rsc_allocating);
@@ -263,29 +230,18 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
             continue;
         }
 
-        if (recursive) {
-            if (!printed_header) {
-                pcmk__output_xml_create_parent(out, "colocations", NULL);
-                printed_header = true;
-            }
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations");
 
+        if (recursive) {
             out->message(out, "rscs-colocated-with-list", rsc, recursive);
         }
 
-        if (!printed_header) {
-            pcmk__output_xml_create_parent(out, "colocations", NULL);
-            printed_header = true;
-        }
-
         colocations_xml_node(out, cons->rsc_lh, cons);
         out->message(out, "locations-list", cons->rsc_lh);
     }
 
-    if (printed_header) {
-        pcmk__output_xml_pop_parent(out);
-    }
-
-    return pcmk_rc_ok;
+    PCMK__OUTPUT_LIST_FOOTER(out, rc);
+    return rc;
 }
 
 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
@@ -364,7 +320,6 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
     rsc = uber_parent(rsc);
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
-
     out->message(out, "rscs-colocated-with-list", rsc, recursive);
 
     out->begin_list(out, NULL, NULL, "%s", rsc->id);
@@ -372,7 +327,6 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
     out->end_list(out);
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
-
     out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
     return pcmk_rc_ok;
 }
@@ -393,19 +347,16 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
     rsc = uber_parent(rsc);
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
-
     pcmk__output_xml_create_parent(out, "constraints", NULL);
-
     out->message(out, "rscs-colocated-with-list", rsc, recursive);
 
     pcmk__output_xml_create_parent(out, "resource",
                                    "id", rsc->id,
                                    NULL);
     out->message(out, "locations-list", rsc);
-    pcmk__output_xml_pop_parent(out);
 
+    pcmk__output_xml_pop_parent(out);
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
-
     out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
     return pcmk_rc_ok;
 }
-- 
1.8.3.1


From c84ffba9b9d5dd22167215d6e93d8f51ec232d78 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 16 Dec 2020 14:26:27 -0500
Subject: [PATCH 08/18] Fix: libpacemaker: Change the colocation list headings.

This should make it a lot more clear what these lists are trying to tell
you.
---
 lib/pacemaker/pcmk_output.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 2eb3ced..b054848 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -112,7 +112,7 @@ rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
         char *hdr = NULL;
 
-        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations")
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources %s is colocated with", rsc->id);
 
         if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
             out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_rh->id, cons->id);
@@ -150,7 +150,7 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
     for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
 
-        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations");
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "rsc-is-colocated-with");
 
         if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
             pcmk__output_create_xml_node(out, "colocation",
@@ -193,7 +193,7 @@ rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
             continue;
         }
 
-        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations");
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
 
         if (recursive) {
             out->message(out, "rscs-colocated-with-list", rsc, recursive);
@@ -230,7 +230,7 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
             continue;
         }
 
-        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Colocations");
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "rscs-colocated-with");
 
         if (recursive) {
             out->message(out, "rscs-colocated-with-list", rsc, recursive);
-- 
1.8.3.1


From 9570877703f98fd6e3de56df6e2648689650d81e Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 14 Dec 2020 14:01:18 -0500
Subject: [PATCH 09/18] Fix: tools: Don't display generic lists for colocations
 and constraints.

---
 tools/crm_resource.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 2afb0d6..b028c40 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1589,12 +1589,20 @@ main(int argc, char **argv)
         /* Kind of a hack to display XML lists using a real tag instead of <list>.  This just
          * saves from having to write custom messages to build the lists around all these things
          */
-        if (options.rsc_cmd == cmd_list_resources || options.rsc_cmd == cmd_query_xml ||
-            options.rsc_cmd == cmd_query_raw_xml || options.rsc_cmd == cmd_list_active_ops ||
-            options.rsc_cmd == cmd_list_all_ops) {
-            pcmk__force_args(context, &error, "%s --xml-simple-list --xml-substitute", g_get_prgname());
-        } else {
-            pcmk__force_args(context, &error, "%s --xml-substitute", g_get_prgname());
+        switch (options.rsc_cmd) {
+            case cmd_list_resources:
+            case cmd_query_xml:
+            case cmd_query_raw_xml:
+            case cmd_list_active_ops:
+            case cmd_list_all_ops:
+            case cmd_colocations:
+            case cmd_colocations_deep:
+                pcmk__force_args(context, &error, "%s --xml-simple-list --xml-substitute", g_get_prgname());
+                break;
+
+            default:
+                pcmk__force_args(context, &error, "%s --xml-substitute", g_get_prgname());
+                break;
         }
     } else if (pcmk__str_eq(args->output_ty, "text", pcmk__str_null_matches)) {
         if (options.rsc_cmd == cmd_colocations || options.rsc_cmd == cmd_colocations_deep ||
-- 
1.8.3.1


From 0d845340d5c91e177ba4321b62e6b79bb0e00b81 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 14:56:55 -0500
Subject: [PATCH 10/18] Fix: libpacemaker: Pass the correct resource to
 recursive calls.

Previously, we were just passing the same resource into the recursive
call, which would immediately return due to pe_rscs_allocating being set
on it.  This gets us the recursive output we're expecting.
---
 lib/pacemaker/pcmk_output.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index b054848..4003b4d 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -126,7 +126,7 @@ rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
         out->message(out, "locations-list", cons->rsc_rh);
 
         if (recursive) {
-            out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
+            out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
         }
     }
 
@@ -164,7 +164,7 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
         out->message(out, "locations-list", cons->rsc_rh);
 
         if (recursive) {
-            out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
+            out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
         }
     }
 
@@ -196,7 +196,7 @@ rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
         PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
 
         if (recursive) {
-            out->message(out, "rscs-colocated-with-list", rsc, recursive);
+            out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
         }
 
         hdr = colocations_header(cons->rsc_lh, cons, TRUE);
@@ -233,7 +233,7 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
         PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "rscs-colocated-with");
 
         if (recursive) {
-            out->message(out, "rscs-colocated-with-list", rsc, recursive);
+            out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
         }
 
         colocations_xml_node(out, cons->rsc_lh, cons);
-- 
1.8.3.1


From bb11c15d8ed9a2fac743d095f1caaf070cf4d148 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 16 Dec 2020 15:02:57 -0500
Subject: [PATCH 11/18] Fix: libpacemaker: Flatten XML output for colocations.

The XML nodes contain enough information to determine the structure, so
there's no need to build up a recursive tree of tags.
---
 lib/pacemaker/pcmk_output.c | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 4003b4d..e2a4dbb 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -150,13 +150,8 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
     for (GList *lpc = rsc->rsc_cons; lpc != NULL; lpc = lpc->next) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
 
-        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "rsc-is-colocated-with");
-
         if (pcmk_is_set(cons->rsc_rh->flags, pe_rsc_allocating)) {
-            pcmk__output_create_xml_node(out, "colocation",
-                                         "peer", cons->rsc_rh->id,
-                                         "id", cons->id,
-                                         NULL);
+            colocations_xml_node(out, cons->rsc_rh, cons);
             continue;
         }
 
@@ -168,7 +163,6 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
         }
     }
 
-    PCMK__OUTPUT_LIST_FOOTER(out, rc);
     return rc;
 }
 
@@ -227,11 +221,10 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
 
         if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
+            colocations_xml_node(out, cons->rsc_lh, cons);
             continue;
         }
 
-        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "rscs-colocated-with");
-
         if (recursive) {
             out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
         }
@@ -240,7 +233,6 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
         out->message(out, "locations-list", cons->rsc_lh);
     }
 
-    PCMK__OUTPUT_LIST_FOOTER(out, rc);
     return rc;
 }
 
@@ -355,9 +347,10 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
                                    NULL);
     out->message(out, "locations-list", rsc);
 
-    pcmk__output_xml_pop_parent(out);
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
     out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
+
+    pcmk__output_xml_pop_parent(out);
     return pcmk_rc_ok;
 }
 
-- 
1.8.3.1


From 78563138db4214db7ccd49da0ba11d880de36267 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 16 Dec 2020 15:04:36 -0500
Subject: [PATCH 12/18] Fix: libpacemaker: Correct loop detection in
 rscs_colocated_with_list.

If we hit a loop, print something out and continue instead of just
continuing silently.
---
 lib/pacemaker/pcmk_output.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index e2a4dbb..9930a5f 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -170,7 +170,7 @@ PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
 static int
 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
-    gboolean recursive = va_arg(args, gboolean);
+    gboolean recursive G_GNUC_UNUSED = va_arg(args, gboolean);
 
     int rc = pcmk_rc_no_output;
 
@@ -183,12 +183,13 @@ rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
         char *hdr = NULL;
 
+        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
+
         if (pcmk_is_set(cons->rsc_lh->flags, pe_rsc_allocating)) {
+            out->list_item(out, NULL, "%s (id=%s - loop)", cons->rsc_lh->id, cons->id);
             continue;
         }
 
-        PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources colocated with %s", rsc->id);
-
         if (recursive) {
             out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
         }
-- 
1.8.3.1


From 12f26406247950cd857e498785be860225027629 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 15 Dec 2020 16:23:19 -0500
Subject: [PATCH 13/18] Fix: libpacemaker: Fix printing out location
 constraints.

In the text output, put the location constraints inside empty lists.
This will indent it under the previous line of text, making it more
apparent what the location information applies to.

In both text and XML output, remove the print out of the initial
resource.  There's plenty of context for what is happening already.  We
don't need an extra level.
---
 lib/pacemaker/pcmk_output.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 9930a5f..07f7475 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -123,11 +123,15 @@ rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
         out->list_item(out, NULL, "%s", hdr);
         free(hdr);
 
-        out->message(out, "locations-list", cons->rsc_rh);
+        /* Empty list header just for indentation of information about this resource. */
+        out->begin_list(out, NULL, NULL, NULL);
 
+        out->message(out, "locations-list", cons->rsc_rh);
         if (recursive) {
             out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
         }
+
+        out->end_list(out);
     }
 
     PCMK__OUTPUT_LIST_FOOTER(out, rc);
@@ -170,7 +174,7 @@ PCMK__OUTPUT_ARGS("rscs-colocated-with-list", "pe_resource_t *", "gboolean")
 static int
 rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
-    gboolean recursive G_GNUC_UNUSED = va_arg(args, gboolean);
+    gboolean recursive = va_arg(args, gboolean);
 
     int rc = pcmk_rc_no_output;
 
@@ -190,15 +194,19 @@ rscs_colocated_with_list(pcmk__output_t *out, va_list args) {
             continue;
         }
 
-        if (recursive) {
-            out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
-        }
-
         hdr = colocations_header(cons->rsc_lh, cons, TRUE);
         out->list_item(out, NULL, "%s", hdr);
         free(hdr);
 
+        /* Empty list header just for indentation of information about this resource. */
+        out->begin_list(out, NULL, NULL, NULL);
+
         out->message(out, "locations-list", cons->rsc_lh);
+        if (recursive) {
+            out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
+        }
+
+        out->end_list(out);
     }
 
     PCMK__OUTPUT_LIST_FOOTER(out, rc);
@@ -312,13 +320,11 @@ stacks_and_constraints(pcmk__output_t *out, va_list args) {
     // Constraints apply to group/clone, not member/instance
     rsc = uber_parent(rsc);
 
+    out->message(out, "locations-list", rsc);
+
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
     out->message(out, "rscs-colocated-with-list", rsc, recursive);
 
-    out->begin_list(out, NULL, NULL, "%s", rsc->id);
-    out->message(out, "locations-list", rsc);
-    out->end_list(out);
-
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
     out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
     return pcmk_rc_ok;
@@ -339,16 +345,13 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
     // Constraints apply to group/clone, not member/instance
     rsc = uber_parent(rsc);
 
-    pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
     pcmk__output_xml_create_parent(out, "constraints", NULL);
-    out->message(out, "rscs-colocated-with-list", rsc, recursive);
-
-    pcmk__output_xml_create_parent(out, "resource",
-                                   "id", rsc->id,
-                                   NULL);
     out->message(out, "locations-list", rsc);
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
+    out->message(out, "rscs-colocated-with-list", rsc, recursive);
+
+    pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
     out->message(out, "rsc-is-colocated-with-list", rsc, recursive);
 
     pcmk__output_xml_pop_parent(out);
-- 
1.8.3.1


From 8b49f68aa4c881021a50fddb25e4d657294d8142 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Wed, 16 Dec 2020 15:21:42 -0500
Subject: [PATCH 14/18] Fix: libpacemaker: Various small fixes to
 location-list.

* Output a "node" attribute instead of a "host" attribute, bringing
  crm_resource closer in line to what's used in the CIB.

* Correct indentation on the function prototypes.

* Add a "rsc" attribute.  This was previously absent (and unnecessary)
  because the location and colocation constraint output was structured
  in such a way that you could figure out the resource based on the
  context.  Now that we are just flattening the XML output, this is no
  longer the case.  We need the attribute to make sense of it.

* Also add "rsc" to the text output.  It's not strictly necessary, but
  it does make things look a little clearer.
---
 lib/pacemaker/pcmk_output.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 07f7475..63a6f25 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -246,7 +246,8 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
 }
 
 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
-static int locations_list(pcmk__output_t *out, va_list args) {
+static int
+locations_list(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
 
     GList *lpc = NULL;
@@ -263,8 +264,8 @@ static int locations_list(pcmk__output_t *out, va_list args) {
             char *score = score2char(node->weight);
 
             PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Locations");
-            out->list_item(out, NULL, "Node %s (score=%s, id=%s)",
-                           node->details->uname, score, cons->id);
+            out->list_item(out, NULL, "Node %s (score=%s, id=%s, rsc=%s)",
+                           node->details->uname, score, cons->id, rsc->id);
             free(score);
         }
     }
@@ -274,7 +275,8 @@ static int locations_list(pcmk__output_t *out, va_list args) {
 }
 
 PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
-static int locations_list_xml(pcmk__output_t *out, va_list args) {
+static int
+locations_list_xml(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
 
     GList *lpc = NULL;
@@ -292,8 +294,9 @@ static int locations_list_xml(pcmk__output_t *out, va_list args) {
 
             PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
 
-            pcmk__output_create_xml_node(out, "location",
-                                         "host", node->details->uname,
+            pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_LOCATION,
+                                         "node", node->details->uname,
+                                         "rsc", rsc->id,
                                          "id", cons->id,
                                          "score", score,
                                          NULL);
-- 
1.8.3.1


From 0b2a8b80ec614e7c8c7e31dd49af1b0dcdc7fbcb Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 15:02:42 -0500
Subject: [PATCH 15/18] Fix: libpacemaker: Also flatten XML location constraint
 output.

There's enough information in the constraint output to put these into
the same single flat list as all the colocation constraints.
---
 lib/pacemaker/pcmk_output.c | 76 +++++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 33 deletions(-)

diff --git a/lib/pacemaker/pcmk_output.c b/lib/pacemaker/pcmk_output.c
index 63a6f25..0d20a54 100644
--- a/lib/pacemaker/pcmk_output.c
+++ b/lib/pacemaker/pcmk_output.c
@@ -95,6 +95,43 @@ colocations_xml_node(pcmk__output_t *out, pe_resource_t *rsc,
     free(score);
 }
 
+static int
+do_locations_list_xml(pcmk__output_t *out, pe_resource_t *rsc, bool add_header)
+{
+    GList *lpc = NULL;
+    GList *list = rsc->rsc_location;
+    int rc = pcmk_rc_no_output;
+
+    for (lpc = list; lpc != NULL; lpc = lpc->next) {
+        pe__location_t *cons = lpc->data;
+
+        GList *lpc2 = NULL;
+
+        for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
+            pe_node_t *node = (pe_node_t *) lpc2->data;
+            char *score = score2char(node->weight);
+
+            if (add_header) {
+                PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
+            }
+
+            pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_LOCATION,
+                                         "node", node->details->uname,
+                                         "rsc", rsc->id,
+                                         "id", cons->id,
+                                         "score", score,
+                                         NULL);
+            free(score);
+        }
+    }
+
+    if (add_header) {
+        PCMK__OUTPUT_LIST_FOOTER(out, rc);
+    }
+
+    return rc;
+}
+
 PCMK__OUTPUT_ARGS("rsc-is-colocated-with-list", "pe_resource_t *", "gboolean")
 static int
 rsc_is_colocated_with_list(pcmk__output_t *out, va_list args) {
@@ -160,7 +197,7 @@ rsc_is_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
         }
 
         colocations_xml_node(out, cons->rsc_rh, cons);
-        out->message(out, "locations-list", cons->rsc_rh);
+        do_locations_list_xml(out, cons->rsc_rh, false);
 
         if (recursive) {
             out->message(out, "rsc-is-colocated-with-list", cons->rsc_rh, recursive);
@@ -234,12 +271,12 @@ rscs_colocated_with_list_xml(pcmk__output_t *out, va_list args) {
             continue;
         }
 
+        colocations_xml_node(out, cons->rsc_lh, cons);
+        do_locations_list_xml(out, cons->rsc_lh, false);
+
         if (recursive) {
             out->message(out, "rscs-colocated-with-list", cons->rsc_lh, recursive);
         }
-
-        colocations_xml_node(out, cons->rsc_lh, cons);
-        out->message(out, "locations-list", cons->rsc_lh);
     }
 
     return rc;
@@ -278,34 +315,7 @@ PCMK__OUTPUT_ARGS("locations-list", "pe_resource_t *")
 static int
 locations_list_xml(pcmk__output_t *out, va_list args) {
     pe_resource_t *rsc = va_arg(args, pe_resource_t *);
-
-    GList *lpc = NULL;
-    GList *list = rsc->rsc_location;
-    int rc = pcmk_rc_no_output;
-
-    for (lpc = list; lpc != NULL; lpc = lpc->next) {
-        pe__location_t *cons = lpc->data;
-
-        GList *lpc2 = NULL;
-
-        for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
-            pe_node_t *node = (pe_node_t *) lpc2->data;
-            char *score = score2char(node->weight);
-
-            PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "locations");
-
-            pcmk__output_create_xml_node(out, XML_CONS_TAG_RSC_LOCATION,
-                                         "node", node->details->uname,
-                                         "rsc", rsc->id,
-                                         "id", cons->id,
-                                         "score", score,
-                                         NULL);
-            free(score);
-        }
-    }
-
-    PCMK__OUTPUT_LIST_FOOTER(out, rc);
-    return rc;
+    return do_locations_list_xml(out, rsc, true);
 }
 
 PCMK__OUTPUT_ARGS("stacks-constraints", "pe_resource_t *", "pe_working_set_t *", "gboolean")
@@ -349,7 +359,7 @@ stacks_and_constraints_xml(pcmk__output_t *out, va_list args) {
     rsc = uber_parent(rsc);
 
     pcmk__output_xml_create_parent(out, "constraints", NULL);
-    out->message(out, "locations-list", rsc);
+    do_locations_list_xml(out, rsc, false);
 
     pe__clear_resource_flags_on_all(data_set, pe_rsc_allocating);
     out->message(out, "rscs-colocated-with-list", rsc, recursive);
-- 
1.8.3.1


From e5c98e481273d1bd365b8094df1a00d70e776504 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 18:51:10 -0500
Subject: [PATCH 16/18] Test: cts: Update expected crm_resource test output.

---
 cts/cli/regression.tools.exp | 477 +++++++++++++++++--------------------------
 1 file changed, 188 insertions(+), 289 deletions(-)

diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
index f5de14d..a85b7d6 100644
--- a/cts/cli/regression.tools.exp
+++ b/cts/cli/regression.tools.exp
@@ -2005,9 +2005,8 @@ resource dummy is running on: node1
 =#=#=#= End test: Show where a resource is running - OK (0) =#=#=#=
 * Passed: crm_resource   - Show where a resource is running
 =#=#=#= Begin test: Show constraints on a resource =#=#=#=
-dummy:
-  * Locations:
-    * Node node1 (score=-INFINITY, id=cli-ban-dummy-on-node1)
+Locations:
+  * Node node1 (score=-INFINITY, id=cli-ban-dummy-on-node1, rsc=dummy)
 =#=#=#= End test: Show constraints on a resource - OK (0) =#=#=#=
 * Passed: crm_resource   - Show constraints on a resource
 =#=#=#= Begin test: Ban dummy from node2 =#=#=#=
@@ -3471,58 +3470,50 @@ Removing constraint: cli-prefer-dummy
 =#=#=#= End test: Create an XML patchset - Error occurred (1) =#=#=#=
 * Passed: crm_diff       - Create an XML patchset
 =#=#=#= Begin test: Check locations and constraints for prim1 =#=#=#=
-prim1:
 =#=#=#= End test: Check locations and constraints for prim1 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim1
 =#=#=#= Begin test: Recursively check locations and constraints for prim1 =#=#=#=
-prim1:
 =#=#=#= End test: Recursively check locations and constraints for prim1 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim1
 =#=#=#= Begin test: Check locations and constraints for prim1 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim1 --output-as=xml">
-  <constraints>
-    <resource id="prim1"/>
-  </constraints>
+  <constraints/>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Check locations and constraints for prim1 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim1 in XML
 =#=#=#= Begin test: Recursively check locations and constraints for prim1 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim1 --output-as=xml">
-  <constraints>
-    <resource id="prim1"/>
-  </constraints>
+  <constraints/>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim1 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim1 in XML
 =#=#=#= Begin test: Check locations and constraints for prim2 =#=#=#=
-prim2:
-  * Locations:
-    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
-Colocations:
+Locations:
+  * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2)
+Resources prim2 is colocated with:
   * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim2 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim2
 =#=#=#= Begin test: Recursively check locations and constraints for prim2 =#=#=#=
-prim2:
-  * Locations:
-    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
-Colocations:
+Locations:
+  * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2)
+Resources prim2 is colocated with:
   * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
+    * Resources prim3 is colocated with:
+      * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
+        * Locations:
+          * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
+        * Resources prim4 is colocated with:
+          * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
 =#=#=#= End test: Recursively check locations and constraints for prim2 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim2
 =#=#=#= Begin test: Check locations and constraints for prim2 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim2 --output-as=xml">
   <constraints>
-    <resource id="prim2">
-      <list name="locations" count="1">
-        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </list>
-    </resource>
-    <colocations>
-      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-    </colocations>
+    <rsc_location node="cluster01" rsc="prim2" id="prim2-on-cluster1" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3531,59 +3522,47 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim2 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim2 --output-as=xml">
   <constraints>
-    <resource id="prim2">
-      <list name="locations" count="1">
-        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </list>
-    </resource>
-    <colocations>
-      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-    </colocations>
+    <rsc_location node="cluster01" rsc="prim2" id="prim2-on-cluster1" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim2 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim2 in XML
 =#=#=#= Begin test: Check locations and constraints for prim3 =#=#=#=
-Colocations:
+Resources colocated with prim3:
   * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
-  * Locations:
-    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
-prim3:
-Colocations:
+    * Locations:
+      * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2)
+Resources prim3 is colocated with:
   * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+    * Locations:
+      * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
 =#=#=#= End test: Check locations and constraints for prim3 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim3
 =#=#=#= Begin test: Recursively check locations and constraints for prim3 =#=#=#=
-Colocations:
+Resources colocated with prim3:
   * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
-  * Locations:
-    * Node cluster01 (score=INFINITY, id=prim2-on-cluster1)
-prim3:
-Colocations:
+    * Locations:
+      * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2)
+Resources prim3 is colocated with:
   * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+    * Locations:
+      * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
+    * Resources prim4 is colocated with:
+      * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
 =#=#=#= End test: Recursively check locations and constraints for prim3 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim3
 =#=#=#= Begin test: Check locations and constraints for prim3 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim3 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </list>
-    </colocations>
-    <resource id="prim3"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </colocations>
+    <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
+    <rsc_location node="cluster01" rsc="prim2" id="prim2-on-cluster1" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3592,61 +3571,47 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim3 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim3 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster01" id="prim2-on-cluster1" score="INFINITY"/>
-      </list>
-    </colocations>
-    <resource id="prim3"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </colocations>
+    <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
+    <rsc_location node="cluster01" rsc="prim2" id="prim2-on-cluster1" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim3 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim3 in XML
 =#=#=#= Begin test: Check locations and constraints for prim4 =#=#=#=
-Colocations:
+Locations:
+  * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
+Resources colocated with prim4:
   * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
-prim4:
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
-Colocations:
+Resources prim4 is colocated with:
   * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim4 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim4
 =#=#=#= Begin test: Recursively check locations and constraints for prim4 =#=#=#=
-Colocations:
+Locations:
+  * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
+Resources colocated with prim4:
   * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
   * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
-prim4:
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
-Colocations:
+    * Resources colocated with prim3:
+      * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
+        * Locations:
+          * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2)
+Resources prim4 is colocated with:
   * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
 =#=#=#= End test: Recursively check locations and constraints for prim4 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim4
 =#=#=#= Begin test: Check locations and constraints for prim4 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim4 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-    </colocations>
-    <resource id="prim4">
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </resource>
-    <colocations>
-      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-    </colocations>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3655,49 +3620,43 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim4 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim4 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
-    </colocations>
-    <resource id="prim4">
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </resource>
-    <colocations>
-      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-    </colocations>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
+    <rsc_location node="cluster01" rsc="prim2" id="prim2-on-cluster1" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim4 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim4 in XML
 =#=#=#= Begin test: Check locations and constraints for prim5 =#=#=#=
-Colocations:
+Resources colocated with prim5:
   * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
-prim5:
+    * Locations:
+      * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
 =#=#=#= End test: Check locations and constraints for prim5 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim5
 =#=#=#= Begin test: Recursively check locations and constraints for prim5 =#=#=#=
-Colocations:
+Resources colocated with prim5:
   * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
-prim5:
+    * Locations:
+      * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
+    * Resources colocated with prim4:
+      * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
+      * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY)
+        * Resources colocated with prim3:
+          * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY)
+            * Locations:
+              * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2)
 =#=#=#= End test: Recursively check locations and constraints for prim5 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim5
 =#=#=#= Begin test: Check locations and constraints for prim5 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim5 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </colocations>
-    <resource id="prim5"/>
+    <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3706,38 +3665,31 @@ prim5:
 =#=#=#= Begin test: Recursively check locations and constraints for prim5 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim5 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </colocations>
-    <resource id="prim5"/>
+    <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim3-prim4-INFINITY" rsc="prim3" with-rsc="prim4" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim2-prim3-INFINITY" rsc="prim2" with-rsc="prim3" score="INFINITY"/>
+    <rsc_location node="cluster01" rsc="prim2" id="prim2-on-cluster1" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim5 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim5 in XML
 =#=#=#= Begin test: Check locations and constraints for prim6 =#=#=#=
-prim6:
-  * Locations:
-    * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2)
+Locations:
+  * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2, rsc=prim6)
 =#=#=#= End test: Check locations and constraints for prim6 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim6
 =#=#=#= Begin test: Recursively check locations and constraints for prim6 =#=#=#=
-prim6:
-  * Locations:
-    * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2)
+Locations:
+  * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2, rsc=prim6)
 =#=#=#= End test: Recursively check locations and constraints for prim6 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim6
 =#=#=#= Begin test: Check locations and constraints for prim6 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim6 --output-as=xml">
   <constraints>
-    <resource id="prim6">
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim6-not-on-cluster2" score="-INFINITY"/>
-      </list>
-    </resource>
+    <rsc_location node="cluster02" rsc="prim6" id="prim6-not-on-cluster2" score="-INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3746,35 +3698,26 @@ prim6:
 =#=#=#= Begin test: Recursively check locations and constraints for prim6 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim6 --output-as=xml">
   <constraints>
-    <resource id="prim6">
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim6-not-on-cluster2" score="-INFINITY"/>
-      </list>
-    </resource>
+    <rsc_location node="cluster02" rsc="prim6" id="prim6-not-on-cluster2" score="-INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim6 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim6 in XML
 =#=#=#= Begin test: Check locations and constraints for prim7 =#=#=#=
-prim7:
-Colocations:
+Resources prim7 is colocated with:
   * group (score=INFINITY, id=colocation-prim7-group-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim7 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim7
 =#=#=#= Begin test: Recursively check locations and constraints for prim7 =#=#=#=
-prim7:
-Colocations:
+Resources prim7 is colocated with:
   * group (score=INFINITY, id=colocation-prim7-group-INFINITY)
 =#=#=#= End test: Recursively check locations and constraints for prim7 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim7
 =#=#=#= Begin test: Check locations and constraints for prim7 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim7 --output-as=xml">
   <constraints>
-    <resource id="prim7"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3783,34 +3726,26 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim7 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim7 --output-as=xml">
   <constraints>
-    <resource id="prim7"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim7 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim7 in XML
 =#=#=#= Begin test: Check locations and constraints for prim8 =#=#=#=
-prim8:
-Colocations:
+Resources prim8 is colocated with:
   * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim8 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim8
 =#=#=#= Begin test: Recursively check locations and constraints for prim8 =#=#=#=
-prim8:
-Colocations:
+Resources prim8 is colocated with:
   * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY)
 =#=#=#= End test: Recursively check locations and constraints for prim8 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim8
 =#=#=#= Begin test: Check locations and constraints for prim8 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim8 --output-as=xml">
   <constraints>
-    <resource id="prim8"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3819,34 +3754,26 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim8 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim8 --output-as=xml">
   <constraints>
-    <resource id="prim8"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim8-gr2-INFINITY" rsc="prim8" with-rsc="gr2" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim8 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim8 in XML
 =#=#=#= Begin test: Check locations and constraints for prim9 =#=#=#=
-prim9:
-Colocations:
+Resources prim9 is colocated with:
   * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim9 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim9
 =#=#=#= Begin test: Recursively check locations and constraints for prim9 =#=#=#=
-prim9:
-Colocations:
+Resources prim9 is colocated with:
   * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY)
 =#=#=#= End test: Recursively check locations and constraints for prim9 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim9
 =#=#=#= Begin test: Check locations and constraints for prim9 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim9 --output-as=xml">
   <constraints>
-    <resource id="prim9"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3855,41 +3782,33 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim9 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim9 --output-as=xml">
   <constraints>
-    <resource id="prim9"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim9 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim9 in XML
 =#=#=#= Begin test: Check locations and constraints for prim10 =#=#=#=
-prim10:
-Colocations:
+Resources prim10 is colocated with:
   * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+    * Locations:
+      * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
 =#=#=#= End test: Check locations and constraints for prim10 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim10
 =#=#=#= Begin test: Recursively check locations and constraints for prim10 =#=#=#=
-prim10:
-Colocations:
+Resources prim10 is colocated with:
   * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY)
-  * Locations:
-    * Node cluster02 (score=INFINITY, id=prim4-on-cluster2)
+    * Locations:
+      * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4)
+    * Resources prim4 is colocated with:
+      * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY)
 =#=#=#= End test: Recursively check locations and constraints for prim10 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim10
 =#=#=#= Begin test: Check locations and constraints for prim10 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim10 --output-as=xml">
   <constraints>
-    <resource id="prim10"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </colocations>
+    <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3898,44 +3817,41 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim10 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim10 --output-as=xml">
   <constraints>
-    <resource id="prim10"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
-      <list name="locations" count="1">
-        <location host="cluster02" id="prim4-on-cluster2" score="INFINITY"/>
-      </list>
-    </colocations>
+    <rsc_colocation id="colocation-prim10-prim4-INFINITY" rsc="prim10" with-rsc="prim4" score="INFINITY"/>
+    <rsc_location node="cluster02" rsc="prim4" id="prim4-on-cluster2" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim4-prim5-INFINITY" rsc="prim4" with-rsc="prim5" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim10 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim10 in XML
 =#=#=#= Begin test: Check locations and constraints for prim11 =#=#=#=
-Colocations:
+Resources colocated with prim11:
   * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
-prim11:
-Colocations:
+Resources prim11 is colocated with:
   * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim11 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim11
 =#=#=#= Begin test: Recursively check locations and constraints for prim11 =#=#=#=
-Colocations:
+Resources colocated with prim11:
   * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
-prim11:
-Colocations:
+    * Resources colocated with prim13:
+      * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
+        * Resources colocated with prim12:
+          * prim11 (id=colocation-prim11-prim12-INFINITY - loop)
+Resources prim11 is colocated with:
   * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
+    * Resources prim12 is colocated with:
+      * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
+        * Resources prim13 is colocated with:
+          * prim11 (id=colocation-prim13-prim11-INFINITY - loop)
 =#=#=#= End test: Recursively check locations and constraints for prim11 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim11
 =#=#=#= Begin test: Check locations and constraints for prim11 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim11 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-    </colocations>
-    <resource id="prim11"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3944,44 +3860,44 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim11 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim11 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-    </colocations>
-    <resource id="prim11"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim11 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim11 in XML
 =#=#=#= Begin test: Check locations and constraints for prim12 =#=#=#=
-Colocations:
+Resources colocated with prim12:
   * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
-prim12:
-Colocations:
+Resources prim12 is colocated with:
   * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim12 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim12
 =#=#=#= Begin test: Recursively check locations and constraints for prim12 =#=#=#=
-Colocations:
+Resources colocated with prim12:
   * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
-prim12:
-Colocations:
+    * Resources colocated with prim11:
+      * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
+        * Resources colocated with prim13:
+          * prim12 (id=colocation-prim12-prim13-INFINITY - loop)
+Resources prim12 is colocated with:
   * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
+    * Resources prim13 is colocated with:
+      * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
+        * Resources prim11 is colocated with:
+          * prim12 (id=colocation-prim11-prim12-INFINITY - loop)
 =#=#=#= End test: Recursively check locations and constraints for prim12 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim12
 =#=#=#= Begin test: Check locations and constraints for prim12 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim12 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-    </colocations>
-    <resource id="prim12"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -3990,44 +3906,44 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim12 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim12 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
-    </colocations>
-    <resource id="prim12"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim12 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim12 in XML
 =#=#=#= Begin test: Check locations and constraints for prim13 =#=#=#=
-Colocations:
+Resources colocated with prim13:
   * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
-prim13:
-Colocations:
+Resources prim13 is colocated with:
   * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
 =#=#=#= End test: Check locations and constraints for prim13 - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for prim13
 =#=#=#= Begin test: Recursively check locations and constraints for prim13 =#=#=#=
-Colocations:
+Resources colocated with prim13:
   * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY)
-prim13:
-Colocations:
+    * Resources colocated with prim12:
+      * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
+        * Resources colocated with prim11:
+          * prim13 (id=colocation-prim13-prim11-INFINITY - loop)
+Resources prim13 is colocated with:
   * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY)
+    * Resources prim11 is colocated with:
+      * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY)
+        * Resources prim12 is colocated with:
+          * prim13 (id=colocation-prim12-prim13-INFINITY - loop)
 =#=#=#= End test: Recursively check locations and constraints for prim13 - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim13
 =#=#=#= Begin test: Check locations and constraints for prim13 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r prim13 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-    </colocations>
-    <resource id="prim13"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -4036,37 +3952,31 @@ Colocations:
 =#=#=#= Begin test: Recursively check locations and constraints for prim13 in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r prim13 --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
-    </colocations>
-    <resource id="prim13"/>
-    <colocations>
-      <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
-    </colocations>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim13-prim11-INFINITY" rsc="prim13" with-rsc="prim11" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim11-prim12-INFINITY" rsc="prim11" with-rsc="prim12" score="INFINITY"/>
+    <rsc_colocation id="colocation-prim12-prim13-INFINITY" rsc="prim12" with-rsc="prim13" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for prim13 in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for prim13 in XML
 =#=#=#= Begin test: Check locations and constraints for group =#=#=#=
-Colocations:
+Resources colocated with group:
   * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY)
-group:
 =#=#=#= End test: Check locations and constraints for group - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for group
 =#=#=#= Begin test: Recursively check locations and constraints for group =#=#=#=
-Colocations:
+Resources colocated with group:
   * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY)
-group:
 =#=#=#= End test: Recursively check locations and constraints for group - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for group
 =#=#=#= Begin test: Check locations and constraints for group in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r group --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-    </colocations>
-    <resource id="group"/>
+    <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -4075,34 +3985,26 @@ group:
 =#=#=#= Begin test: Recursively check locations and constraints for group in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r group --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
-    </colocations>
-    <resource id="group"/>
+    <rsc_colocation id="colocation-prim7-group-INFINITY" rsc="prim7" with-rsc="group" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
 =#=#=#= End test: Recursively check locations and constraints for group in XML - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for group in XML
 =#=#=#= Begin test: Check locations and constraints for clone =#=#=#=
-Colocations:
+Resources colocated with clone:
   * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY)
-clone:
 =#=#=#= End test: Check locations and constraints for clone - OK (0) =#=#=#=
 * Passed: crm_resource   - Check locations and constraints for clone
 =#=#=#= Begin test: Recursively check locations and constraints for clone =#=#=#=
-Colocations:
+Resources colocated with clone:
   * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY)
-clone:
 =#=#=#= End test: Recursively check locations and constraints for clone - OK (0) =#=#=#=
 * Passed: crm_resource   - Recursively check locations and constraints for clone
 =#=#=#= Begin test: Check locations and constraints for clone in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -a -r clone --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-    </colocations>
-    <resource id="clone"/>
+    <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
@@ -4111,10 +4013,7 @@ clone:
 =#=#=#= Begin test: Recursively check locations and constraints for clone in XML =#=#=#=
 <pacemaker-result api-version="X" request="crm_resource -A -r clone --output-as=xml">
   <constraints>
-    <colocations>
-      <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
-    </colocations>
-    <resource id="clone"/>
+    <rsc_colocation id="colocation-prim9-clone-INFINITY" rsc="prim9" with-rsc="clone" score="INFINITY"/>
   </constraints>
   <status code="0" message="OK"/>
 </pacemaker-result>
-- 
1.8.3.1


From 99078013039810d828ff629af6431765979db89b Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 17:38:22 -0500
Subject: [PATCH 17/18] Fix: xml: Clone crm_resource schema in preparation for
 changes..

---
 xml/api/crm_resource-2.5.rng | 255 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 255 insertions(+)
 create mode 100644 xml/api/crm_resource-2.5.rng

diff --git a/xml/api/crm_resource-2.5.rng b/xml/api/crm_resource-2.5.rng
new file mode 100644
index 0000000..1bcb969
--- /dev/null
+++ b/xml/api/crm_resource-2.5.rng
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+         datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+    <start>
+        <ref name="element-crm-resource"/>
+    </start>
+
+    <define name="element-crm-resource">
+        <choice>
+            <ref name="agents-list" />
+            <ref name="alternatives-list" />
+            <ref name="constraints-list" />
+            <externalRef href="generic-list-2.4.rng"/>
+            <element name="metadata"> <text/> </element>
+            <ref name="locate-list" />
+            <ref name="operations-list" />
+            <ref name="providers-list" />
+            <ref name="reasons-list" />
+            <ref name="resource-check" />
+            <ref name="resource-config" />
+            <ref name="resources-list" />
+        </choice>
+    </define>
+
+    <define name="agents-list">
+        <element name="agents">
+            <attribute name="standard"> <text/> </attribute>
+            <optional>
+                <attribute name="provider"> <text/> </attribute>
+            </optional>
+            <zeroOrMore>
+                <element name="agent"> <text/> </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="alternatives-list">
+        <element name="providers">
+            <attribute name="for"> <text/> </attribute>
+            <zeroOrMore>
+                <element name="provider"> <text/> </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="colocations-list">
+        <element name="colocations">
+            <oneOrMore>
+                <ref name="element-colocation-list"/>
+            </oneOrMore>
+        </element>
+    </define>
+
+    <define name="constraints-list">
+        <element name="constraints">
+            <optional>
+                <ref name="colocations-list"/>
+            </optional>
+            <element name="resource">
+                <attribute name="id"> <text/> </attribute>
+                <ref name="locations-list"/>
+            </element>
+            <optional>
+                <ref name="colocations-list"/>
+            </optional>
+        </element>
+    </define>
+
+    <define name="locate-list">
+        <element name="nodes">
+            <attribute name="resource"> <text/> </attribute>
+            <zeroOrMore>
+                <element name="node">
+                    <optional>
+                        <attribute name="state"><value>promoted</value></attribute>
+                    </optional>
+                    <text/>
+                </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="locations-list">
+        <element name="locations">
+            <zeroOrMore>
+                <element name="location">
+                    <attribute name="host"> <text/> </attribute>
+                    <attribute name="id"> <text/> </attribute>
+                    <attribute name="score"> <text/> </attribute>
+                </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="operations-list">
+        <element name="operations">
+            <oneOrMore>
+                <ref name="element-operation-list" />
+            </oneOrMore>
+        </element>
+    </define>
+
+    <define name="providers-list">
+        <element name="providers">
+            <attribute name="standard"> <value>ocf</value> </attribute>
+            <optional>
+                <attribute name="agent"> <text/> </attribute>
+            </optional>
+            <zeroOrMore>
+                <element name="provider"> <text/> </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="reasons-list">
+        <choice>
+            <ref name="no-resource-or-uname"/>
+            <ref name="resource-and-uname"/>
+            <ref name="no-resource-but-uname"/>
+            <ref name="resource-but-no-uname"/>
+        </choice>
+    </define>
+
+    <define name="no-resource-or-uname">
+        <element name="reason">
+            <element name="resources">
+                <zeroOrMore>
+                    <element name="resource">
+                        <attribute name="id"> <text/> </attribute>
+                        <attribute name="running"> <data type="boolean"/> </attribute>
+                        <ref name="resource-check"/>
+                    </element>
+                </zeroOrMore>
+            </element>
+        </element>
+    </define>
+
+    <define name="resource-and-uname">
+        <element name="reason">
+            <attribute name="running_on"> <text/> </attribute>
+            <ref name="resource-check"/>
+        </element>
+    </define>
+
+    <define name="no-resource-but-uname">
+        <element name="reason">
+            <element name="resources">
+                <zeroOrMore>
+                    <element name="resource">
+                        <attribute name="id"> <text/> </attribute>
+                        <attribute name="running"> <data type="boolean"/> </attribute>
+                        <attribute name="host"> <text/> </attribute>
+                        <ref name="resource-check"/>
+                    </element>
+                </zeroOrMore>
+            </element>
+        </element>
+    </define>
+
+    <define name="resource-but-no-uname">
+        <element name="reason">
+            <attribute name="running"> <data type="boolean"/> </attribute>
+            <ref name="resource-check"/>
+        </element>
+    </define>
+
+    <define name="resource-config">
+        <element name="resource_config">
+            <externalRef href="resources-2.4.rng" />
+            <element name="xml"> <text/> </element>
+        </element>
+    </define>
+
+    <define name="resource-check">
+        <element name="check">
+            <attribute name="id"> <text/> </attribute>
+            <optional>
+                <choice>
+                    <attribute name="remain_stopped"><value>true</value></attribute>
+                    <attribute name="promotable"><value>false</value></attribute>
+                </choice>
+            </optional>
+            <optional>
+                <attribute name="unmanaged"><value>true</value></attribute>
+            </optional>
+            <optional>
+                <attribute name="locked-to"> <text/> </attribute>
+            </optional>
+        </element>
+    </define>
+
+    <define name="resources-list">
+        <element name="resources">
+            <zeroOrMore>
+                <externalRef href="resources-2.4.rng" />
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="element-colocation-list">
+        <optional>
+            <element name="colocation">
+                <attribute name="peer"> <text/> </attribute>
+                <attribute name="id"> <text/> </attribute>
+            </element>
+        </optional>
+        <optional>
+            <ref name="colocations-list" />
+        </optional>
+        <choice>
+            <element name="colocation">
+                <attribute name="peer"> <text/> </attribute>
+                <attribute name="id"> <text/> </attribute>
+                <attribute name="score"> <text/> </attribute>
+                <attribute name="dependends">
+                    <choice>
+                        <value>needs</value>
+                        <value>with</value>
+                    </choice>
+                </attribute>
+                <attribute name="role"> <text/> </attribute>
+            </element>
+            <element name="colocation">
+                <attribute name="peer"> <text/> </attribute>
+                <attribute name="id"> <text/> </attribute>
+                <attribute name="score"> <text/> </attribute>
+            </element>
+        </choice>
+        <ref name="locations-list" />
+        <optional>
+            <ref name="colocations-list" />
+        </optional>
+    </define>
+
+    <define name="element-operation-list">
+        <element name="operation">
+            <optional>
+                <group>
+                    <attribute name="rsc"> <text/> </attribute>
+                    <attribute name="agent"> <text/> </attribute>
+                </group>
+            </optional>
+            <attribute name="op"> <text/> </attribute>
+            <attribute name="node"> <text/> </attribute>
+            <attribute name="call"> <data type="nonNegativeInteger" /> </attribute>
+            <attribute name="rc"> <data type="nonNegativeInteger" /> </attribute>
+            <optional>
+                <attribute name="last-rc-change"> <text/> </attribute>
+                <attribute name="exec-time"> <data type="nonNegativeInteger" /> </attribute>
+            </optional>
+            <attribute name="status"> <text/> </attribute>
+        </element>
+    </define>
+</grammar>
-- 
1.8.3.1


From 5aadeaf78dbbb5a3c43f96891baa5acf234f7cef Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 17 Dec 2020 18:07:46 -0500
Subject: [PATCH 18/18] Fix: xml: Update XML schema for crm_resource changes.

The previous colocations-list and locations-list elements and everything
under them has been removed.  The elements that would go into these
lists are now in a flat constraints-list element.  Those elements have
further been modified to be brought in line with what crm_resource now
outputs.
---
 xml/api/crm_resource-2.5.rng | 101 ++++++++++++++++++-------------------------
 1 file changed, 42 insertions(+), 59 deletions(-)

diff --git a/xml/api/crm_resource-2.5.rng b/xml/api/crm_resource-2.5.rng
index 1bcb969..b49e24c 100644
--- a/xml/api/crm_resource-2.5.rng
+++ b/xml/api/crm_resource-2.5.rng
@@ -44,26 +44,16 @@
         </element>
     </define>
 
-    <define name="colocations-list">
-        <element name="colocations">
-            <oneOrMore>
-                <ref name="element-colocation-list"/>
-            </oneOrMore>
-        </element>
-    </define>
-
     <define name="constraints-list">
         <element name="constraints">
-            <optional>
-                <ref name="colocations-list"/>
-            </optional>
-            <element name="resource">
-                <attribute name="id"> <text/> </attribute>
-                <ref name="locations-list"/>
-            </element>
-            <optional>
-                <ref name="colocations-list"/>
-            </optional>
+            <interleave>
+                <zeroOrMore>
+                    <ref name="rsc-location" />
+                </zeroOrMore>
+                <zeroOrMore>
+                    <ref name="rsc-colocation" />
+                </zeroOrMore>
+            </interleave>
         </element>
     </define>
 
@@ -81,15 +71,12 @@
         </element>
     </define>
 
-    <define name="locations-list">
-        <element name="locations">
-            <zeroOrMore>
-                <element name="location">
-                    <attribute name="host"> <text/> </attribute>
-                    <attribute name="id"> <text/> </attribute>
-                    <attribute name="score"> <text/> </attribute>
-                </element>
-            </zeroOrMore>
+    <define name="rsc-location">
+        <element name="rsc_location">
+            <attribute name="node"> <text/> </attribute>
+            <attribute name="rsc"> <text/> </attribute>
+            <attribute name="id"> <text/> </attribute>
+            <externalRef href="../score.rng"/>
         </element>
     </define>
 
@@ -198,39 +185,26 @@
         </element>
     </define>
 
-    <define name="element-colocation-list">
-        <optional>
-            <element name="colocation">
-                <attribute name="peer"> <text/> </attribute>
-                <attribute name="id"> <text/> </attribute>
-            </element>
-        </optional>
-        <optional>
-            <ref name="colocations-list" />
-        </optional>
-        <choice>
-            <element name="colocation">
-                <attribute name="peer"> <text/> </attribute>
-                <attribute name="id"> <text/> </attribute>
-                <attribute name="score"> <text/> </attribute>
-                <attribute name="dependends">
-                    <choice>
-                        <value>needs</value>
-                        <value>with</value>
-                    </choice>
+    <define name="rsc-colocation">
+        <element name="rsc_colocation">
+            <attribute name="id"> <text/> </attribute>
+            <attribute name="rsc"> <text/> </attribute>
+            <attribute name="with-rsc"> <text/> </attribute>
+            <externalRef href="../score.rng"/>
+            <optional>
+                <attribute name="node-attribute"> <text/> </attribute>
+            </optional>
+            <optional>
+                <attribute name="rsc-role">
+                    <ref name="attribute-roles"/>
                 </attribute>
-                <attribute name="role"> <text/> </attribute>
-            </element>
-            <element name="colocation">
-                <attribute name="peer"> <text/> </attribute>
-                <attribute name="id"> <text/> </attribute>
-                <attribute name="score"> <text/> </attribute>
-            </element>
-        </choice>
-        <ref name="locations-list" />
-        <optional>
-            <ref name="colocations-list" />
-        </optional>
+            </optional>
+            <optional>
+                <attribute name="with-rsc-role">
+                    <ref name="attribute-roles"/>
+                </attribute>
+            </optional>
+        </element>
     </define>
 
     <define name="element-operation-list">
@@ -252,4 +226,13 @@
             <attribute name="status"> <text/> </attribute>
         </element>
     </define>
+
+    <define name="attribute-roles">
+        <choice>
+            <value>Stopped</value>
+            <value>Started</value>
+            <value>Master</value>
+            <value>Slave</value>
+        </choice>
+    </define>
 </grammar>
-- 
1.8.3.1