Repository: ClusterLabs/ha_cluster_exporter
Pull request #99 (2019-11-19 16:27:32)

Refactor resource location constraints metric
This PR performs some changes to `ha_cluster_pacemaker_constraints` as some limitations have arisen during the implementation of its visual representation in the Grafana dashboard:

- **BC break:**  renames `ha_cluster_pacemaker_constraints` to `ha_cluster_pacemaker_location_constraints` to distinguish it from possible future new types of constraint metrics like order and colocation.
- **BC break:** the value is no longer always `1` but is now set to the _score_ of the constraint.
- **BC break:** the`type` label, which was not even documented before, has been removed.
- the `id` label has been renamed to `constraint`, to conform to the convention consolidated in #94.
- the new labels `node` and `role` have been added.
- all location constraints are scraped, not just the ones with their id starting with `cli-ban` or `cli-prefer`. That naming prefix was a convention of `crmsh`, but users may be adding constraints through other means (e.g. cibadmin, hawk, crm_resource, etc).
- the `cibadmin` command no longer uses an `--xpath` flag that would produce non-0 exit codes in case the XML query wouldn't return any result, causing the whole pacemaker collector to go into a warning condition.
- The whole CIB is now unmarshalled in a more generic data structure that can accommodate for further metrics.
- `fake_cibadmin.sh` now produces a complete CIB XML mock.
- metric documentation was outdated and has been updated.

MalloZup: @stefanotorresi  a part of that, squash the last commit `fmt fix`

Patch:
diff --git a/doc/metric_spec.md b/doc/metric_spec.md
index f70721b..2c734b0 100644
--- a/doc/metric_spec.md
+++ b/doc/metric_spec.md
@@ -25,8 +25,8 @@ The Pacemaker subsystem collects an atomic snapshot of the HA cluster directly f
 
 0. [Sample](../test/pacemaker.metrics)
 1. [`ha_cluster_pacemaker_config_last_change`](#ha_cluster_pacemaker_config_last_change)
-2. [`ha_cluster_pacemaker_constraints`](#ha_cluster_pacemaker_constraints)
 3. [`ha_cluster_pacemaker_fail_count`](#ha_cluster_pacemaker_fail_count)
+2. [`ha_cluster_pacemaker_location_constraints`](#ha_cluster_pacemaker_location_constraints)
 4. [`ha_cluster_pacemaker_migration_threshold`](#ha_cluster_pacemaker_migration_threshold)
 5. [`ha_cluster_pacemaker_nodes_total`](#ha_cluster_pacemaker_nodes_total)
 6. [`ha_cluster_pacemaker_nodes`](#ha_cluster_pacemaker_nodes)
@@ -34,16 +34,58 @@ The Pacemaker subsystem collects an atomic snapshot of the HA cluster directly f
 8. [`ha_cluster_pacemaker_resources`](#ha_cluster_pacemaker_resources)
 9. [`ha_cluster_pacemaker_stonith_enabled`](#ha_cluster_pacemaker_stonith_enabled)
 
+
+### `ha_cluster_pacemaker_config_last_change`
+
+#### Description
+
+The value of this metric is a Unix timestamp in seconds, converted to a float, corresponding to the last time Pacemaker configuration changed.
+The metric is in turn timestamped with the time it was last checked.
+
+
+### `ha_cluster_pacemaker_fail_count`
+
+#### Description
+
+The number of fail count per node and resource ID.  
+The value is an integer ranging from 0 to `+Inf`.    
+The actual maximum integer value depends on Pacemaker internals, so please refer to upstream documentation for further information.
+
+
+### `ha_cluster_pacemaker_location_constraints`
+
+#### Description
+
+Resource location constraints.  
+The value of the metric is the **score** of the constraint, represented by an integer ranging from `-Inf` to `+Inf`.  
+The actual minimum and maximum integer values depend on Pacemaker internals, so please refer to upstream documentation for further information.
+
+#### Labels
+
+- `constraint`: the unique string identifier of the constraint.
+- `node`: the node the constraint applies to.
+- `resource`: the resource the constraint applies to.
+- `role`: the resource role the constraint applies to, if any.
+
+
+### `ha_cluster_pacemaker_migration_threshold`
+
+#### Description
+
+The number of migration threshold pro node and resource ID set by a pacemaker cluster. 
+Possible values are positive numbers.
+
+
 ### `ha_cluster_pacemaker_nodes`
 
 #### Description
 
-The nodes in the cluster; one line per `name`, per `status`.  
+The nodes in the cluster; one line per `node`, per `status`.  
 Either the value is `1`, or the line is absent altogether.
 
 #### Labels
 
-- `name`: name of the node (usually the hostname).
+- `node`: name of the node (usually the hostname).
 - `status`: one of `online|standby|standby_onfail|maintanance|pending|unclean|shutdown|expected_up|dc`. 
 - `type`: one of `member|ping|remote`.
 
@@ -66,7 +108,7 @@ Either the value is `1`, or the line is absent altogether.
 
 #### Labels
 
-- `id`: the unique resource name.
+- `resource`: the unique resource name.
 - `node`: the name of the node hosting the resource.
 - `managed`: either `true` or `false`.
 - `role`:  one of `started|stopped|master|slave` or one of `starting|stopping|migrating|promoting|demoting`.
@@ -89,35 +131,6 @@ The total number of *configured* resources in the cluster. This value is mostly
 Whether or not stonith is enabled in the cluster.  
 Value is either `1` or `0`.
 
-### `ha_cluster_pacemaker_fail_count`
-
-#### Description
-
-The number of fail count per node and resource ID.
-The value can vary from 0, 1 , 5 etc to `+Inf`, that  correspond to the infinity fail count. For more information about fail count refer to pacemaker upstream documentation.
-
-### `ha_cluster_pacemaker_migration_threshold`
-
-#### Description
-
-The number of migration threshold pro node and resource ID set by a pacemaker cluster. 
-Possible values are positive numbers.
-
-### `ha_cluster_pacemaker_config_last_change`
-
-#### Description
-
-The value of this metric is a Unix timestamp in seconds, converted to a float, corresponding to the last time Pacemaker configuration changed.
-The metric is in turn timestamped with the time it was last checked.
-
-
-### `ha_cluster_pacemaker_constraints`
-
-### Description
-
-Indicate if a cluster constraints is present, peer ID and resource.
-There are 2 types of constraints currently: `prefer` and `ban` which correspond to pacemaker constraints.
-
 
 ## Corosync
 
@@ -163,6 +176,7 @@ The SBD subsystems collect devices stats by parsing its configuration the output
 1. [`ha_cluster_sbd_device_status`](#ha_cluster_sbd_device_status)
 2. [`ha_cluster_sbd_devices_total`](#ha_cluster_sbd_devices_total)
 
+
 ### `ha_cluster_sbd_device_status`
 
 #### Description
@@ -184,6 +198,7 @@ The total number of lines for this metric will be the cardinality of `device`.
 Total count of configured SBD devices.  
 Value is an integer greater than or equal to `0`.
 
+
 ## DRBD
 
 The DRBD subsystems collect devices stats by parsing its configuration the JSON output of `drbdsetup`.
@@ -193,6 +208,7 @@ The DRBD subsystems collect devices stats by parsing its configuration the JSON
 2. [`ha_cluster_drbd_connections`](#ha_cluster_drbd_connections)
 3. [`ha_cluster_drbd_connections_sync`](#ha_cluster_drbd_connections_sync`)
 
+
 ### `ha_cluster_drbd_connections`
 
 #### Description
@@ -210,12 +226,14 @@ Either the value is `1`, or the line is absent altogether.
 
 The total number of lines for this metric will be the cardinality of `resource` times the cardinality of `peer_node_id`.
 
+
 ### `ha_cluster_drbd_connections_sync`
 
 #### Descriptions
 
 The DRBD disk connections in sync percentage. Values are float from `0` to `100.00`.
 
+
 ### `ha_cluster_drbd_resources`
 
 #### Description
@@ -225,7 +243,7 @@ Either the value is `1`, or the line is absent altogether.
 
 #### Labels
 
-- `name`: the name of the resource.
+- `resource`: the name of the resource.
 - `role`: one of `primary|secondary|unknown`
 - `volume`: the volume number
 - `disk_state`: one of `attaching|failed|negotiating|inconsistent|outdated|dunknown|consistent|uptodate`
diff --git a/pacemaker_metrics.go b/pacemaker_metrics.go
index c421081..6754c1f 100644
--- a/pacemaker_metrics.go
+++ b/pacemaker_metrics.go
@@ -30,12 +30,6 @@ type pacemakerStatus struct {
 			} `xml:"resource_history"`
 		} `xml:"node"`
 	} `xml:"node_history"`
-	Bans struct {
-		Ban []struct {
-			ID  string `xml:"id,attr"`
-			RSC string `xml:"resource,attr"`
-		} `xml:"ban"`
-	} `xml:"bans"`
 }
 
 type summary struct {
@@ -85,19 +79,34 @@ type resource struct {
 	NodesRunningOn int    `xml:"nodes_running_on,attr"`
 }
 
+// Pacemaker CIB is queried from cibadmin and unmarshaled from XML
+type CIB struct {
+	Configuration struct {
+		Constraints struct {
+			RscLocations []struct {
+				Id       string `xml:"id,attr"`
+				Node     string `xml:"node,attr"`
+				Resource string `xml:"rsc,attr"`
+				Role     string `xml:"role,attr"`
+				Score    string `xml:"score,attr"`
+			} `xml:"rsc_location"`
+		} `xml:"constraints"`
+	} `xml:"configuration"`
+}
+
 var (
 	pacemakerMetrics = metricDescriptors{
 		// the map key will function as an identifier of the metric throughout the rest of the code;
 		// it is arbitrary, but by convention we use the actual metric name
-		"nodes":               NewMetricDesc("pacemaker", "nodes", "The nodes in the cluster; one line per name, per status", []string{"node", "type", "status"}),
-		"nodes_total":         NewMetricDesc("pacemaker", "nodes_total", "Total number of nodes in the cluster", nil),
-		"resources":           NewMetricDesc("pacemaker", "resources", "The resources in the cluster; one line per id, per status", []string{"node", "resource", "role", "managed", "status"}),
-		"resources_total":     NewMetricDesc("pacemaker", "resources_total", "Total number of resources in the cluster", nil),
-		"stonith_enabled":     NewMetricDesc("pacemaker", "stonith_enabled", "Whether or not stonith is enabled", nil),
-		"fail_count":          NewMetricDesc("pacemaker", "fail_count", "The Fail count number per node and resource id", []string{"node", "resource"}),
-		"migration_threshold": NewMetricDesc("pacemaker", "migration_threshold", "The migration_threshold number per node and resource id", []string{"node", "resource"}),
-		"config_last_change":  NewMetricDesc("pacemaker", "config_last_change", "The timestamp of the last change of the cluster configuration", nil),
-		"constraints":         NewMetricDesc("pacemaker", "constraints", "Indicate if a constraints of specific type is present per ID and per resource", []string{"type", "id", "resource"}),
+		"nodes":                NewMetricDesc("pacemaker", "nodes", "The nodes in the cluster; one line per name, per status", []string{"node", "type", "status"}),
+		"nodes_total":          NewMetricDesc("pacemaker", "nodes_total", "Total number of nodes in the cluster", nil),
+		"resources":            NewMetricDesc("pacemaker", "resources", "The resources in the cluster; one line per id, per status", []string{"node", "resource", "role", "managed", "status"}),
+		"resources_total":      NewMetricDesc("pacemaker", "resources_total", "Total number of resources in the cluster", nil),
+		"stonith_enabled":      NewMetricDesc("pacemaker", "stonith_enabled", "Whether or not stonith is enabled", nil),
+		"fail_count":           NewMetricDesc("pacemaker", "fail_count", "The Fail count number per node and resource id", []string{"node", "resource"}),
+		"migration_threshold":  NewMetricDesc("pacemaker", "migration_threshold", "The migration_threshold number per node and resource id", []string{"node", "resource"}),
+		"config_last_change":   NewMetricDesc("pacemaker", "config_last_change", "The timestamp of the last change of the cluster configuration", nil),
+		"location_constraints": NewMetricDesc("pacemaker", "location_constraints", "Resource location constraints. The value indicates the score.", []string{"constraint", "node", "resource", "role"}),
 	}
 )
 
@@ -134,6 +143,12 @@ func (c *pacemakerCollector) Collect(ch chan<- prometheus.Metric) {
 		return
 	}
 
+	cib, err := c.getCIB()
+	if err != nil {
+		log.Warnln(err)
+		return
+	}
+
 	var stonithEnabled float64
 	if pacemakerStatus.Summary.ClusterOptions.StonithEnabled {
 		stonithEnabled = 1
@@ -147,7 +162,7 @@ func (c *pacemakerCollector) Collect(ch chan<- prometheus.Metric) {
 	c.recordFailCountMetrics(pacemakerStatus, ch)
 	c.recordMigrationThresholdMetrics(pacemakerStatus, ch)
 	c.recordResourceAgentsChanges(pacemakerStatus, ch)
-	c.recordMigrationConstraintsMetrics(pacemakerStatus, ch)
+	c.recordConstraintsMetrics(cib, ch)
 }
 
 func (c *pacemakerCollector) getPacemakerStatus() (pacemakerStatus, error) {
@@ -264,44 +279,34 @@ func (c *pacemakerCollector) recordMigrationThresholdMetrics(pacemakerStatus pac
 	}
 }
 
-// cibAdminStatus used by only constraint metric and by cibadmin binary only
-type cibAdminStatus struct {
-	RscLocation []struct {
-		ID  string `xml:"id,attr"`
-		RSC string `xml:"rsc,attr"`
-	} `xml:"rsc_location"`
-}
-
-func (c *pacemakerCollector) getCibAdminPreferConstraint() (cibAdminStatus, error) {
-	var cibAdminStatus cibAdminStatus
-	cibAdminStatusXML, err := exec.Command(c.cibAdminPath, "--query", "--xpath", "//rsc_location[starts-with(@id,'cli-prefer-')]").Output()
+func (c *pacemakerCollector) getCIB() (CIB, error) {
+	var cib CIB
+	cibXML, err := exec.Command(c.cibAdminPath, "--query", "--local").Output()
 	if err != nil {
-		return cibAdminStatus, errors.Wrap(err, "error while executing cibadmin")
+		return cib, errors.Wrap(err, "error while executing cibadmin")
 	}
 
-	err = xml.Unmarshal(cibAdminStatusXML, &cibAdminStatus)
+	err = xml.Unmarshal(cibXML, &cib)
 	if err != nil {
-		return cibAdminStatus, errors.Wrap(err, "could not parse cibadmin status from XML")
+		return cib, errors.Wrap(err, "could not parse cibadmin status from XML")
 	}
 
-	return cibAdminStatus, nil
+	return cib, nil
 }
 
-func (c *pacemakerCollector) recordMigrationConstraintsMetrics(pacemakerStatus pacemakerStatus, ch chan<- prometheus.Metric) {
-	// set "ban" type of metric
-	for _, ban := range pacemakerStatus.Bans.Ban {
-		// the ban constraints live in xml of pacemaker, where others constraints not
-		ch <- c.makeGaugeMetric("constraints", float64(1), "ban", ban.ID, ban.RSC)
-	}
-
-	// set the 2nd type of metric "prefer"
-	cibAdminConstraint, err := c.getCibAdminPreferConstraint()
-	if err != nil {
-		log.Warnln(err)
-		return
-	}
+func (c *pacemakerCollector) recordConstraintsMetrics(cib CIB, ch chan<- prometheus.Metric) {
+	for _, constraint := range cib.Configuration.Constraints.RscLocations {
+		var constraintScore float64
+		switch constraint.Score {
+		case "INFINITY":
+			constraintScore = math.Inf(1)
+		case "-INFINITY":
+			constraintScore = math.Inf(-1)
+		default:
+			s, _ := strconv.Atoi(constraint.Score)
+			constraintScore = float64(s)
+		}
 
-	for _, rsc := range cibAdminConstraint.RscLocation {
-		ch <- c.makeGaugeMetric("constraints", float64(1), "prefer", rsc.ID, rsc.RSC)
+		ch <- c.makeGaugeMetric("location_constraints", constraintScore, constraint.Id, constraint.Node, constraint.Resource, strings.ToLower(constraint.Role))
 	}
 }


Test patch:
diff --git a/pacemaker_metrics_test.go b/pacemaker_metrics_test.go
index ed8b847..e2d3381 100644
--- a/pacemaker_metrics_test.go
+++ b/pacemaker_metrics_test.go
@@ -64,10 +64,6 @@ func TestParsePacemakerXML(t *testing.T) {
 		</fence_history>
 		<tickets>
 		</tickets>
-		<bans>
-     		<ban id="cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana01" resource="msl_SAPHana_PRD_HDB00" node="damadog-hana01" weight="-1000000" master_only="false" />
-			<ban id="cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana02" resource="msl_SAPHana_PRD_HDB002" node="damadog-hana01" weight="-1000000" master_only="false" />
-	    </bans>
 	</crm_mon>`
 
 	status, err := parsePacemakerStatus([]byte(pacemakerxml))
@@ -79,13 +75,6 @@ func TestParsePacemakerXML(t *testing.T) {
 		t.Errorf("Version was incorrect, got: %s, expected: %s ", status.Version, "2.0.0")
 	}
 
-	if status.Bans.Ban[0].ID != "cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana01" {
-		t.Errorf("ban constraint incorrect, got: %s, expected: cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana01", status.Bans.Ban[0].ID)
-	}
-
-	if status.Bans.Ban[1].ID != "cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana02" {
-		t.Errorf("ban constraint incorrect, got: %s, expected: cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana02", status.Bans.Ban[0].ID)
-	}
 	var expected int
 	expected = 3
 
diff --git a/test/fake_cibadmin.sh b/test/fake_cibadmin.sh
index 2c173de..6495db4 100755
--- a/test/fake_cibadmin.sh
+++ b/test/fake_cibadmin.sh
@@ -1,8 +1,193 @@
 #!/usr/bin/env bash
 
 cat <<EOF
-<xpath-query>
-  <rsc_location id="cli-prefer-msl_SAPHana_PRD_HDB00" rsc="msl_SAPHana_PRD_HDB00" role="Started" node="damadog-hana01" score="INFINITY"/>
-  <rsc_location id="cli-prefer-cln_SAPHanaTopology_PRD_HDB00" rsc="cln_SAPHanaTopology_PRD_HDB00" role="Started" node="damadog-hana01" score="INFINITY"/>
-</xpath-query>
+<cib crm_feature_set="3.1.0" validate-with="pacemaker-3.0" epoch="6881" num_updates="0" admin_epoch="0" cib-last-written="Mon Nov 18 17:48:21 2019" update-origin="hana01" update-client="crm_attribute" update-user="root" have-quorum="1" dc-uuid="1084783375">
+  <configuration>
+    <crm_config>
+      <cluster_property_set id="cib-bootstrap-options">
+        <nvpair id="cib-bootstrap-options-have-watchdog" name="have-watchdog" value="true"/>
+        <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.1.18+20180430.b12c320f5-3.15.1-b12c320f5"/>
+        <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"/>
+        <nvpair id="cib-bootstrap-options-cluster-name" name="cluster-name" value="hana_cluster"/>
+        <nvpair name="stonith-enabled" value="true" id="cib-bootstrap-options-stonith-enabled"/>
+        <nvpair name="placement-strategy" value="balanced" id="cib-bootstrap-options-placement-strategy"/>
+      </cluster_property_set>
+    </crm_config>
+    <nodes>
+      <node id="1084783375" uname="hana01">
+        <instance_attributes id="nodes-1084783375">
+          <nvpair id="nodes-1084783375-lpa_prd_lpt" name="lpa_prd_lpt" value="1574095701"/>
+          <nvpair id="nodes-1084783375-hana_prd_vhost" name="hana_prd_vhost" value="hana01"/>
+          <nvpair id="nodes-1084783375-hana_prd_site" name="hana_prd_site" value="PRIMARY_SITE_NAME"/>
+          <nvpair id="nodes-1084783375-hana_prd_op_mode" name="hana_prd_op_mode" value="logreplay"/>
+          <nvpair id="nodes-1084783375-hana_prd_srmode" name="hana_prd_srmode" value="sync"/>
+          <nvpair id="nodes-1084783375-hana_prd_remoteHost" name="hana_prd_remoteHost" value="hana02"/>
+        </instance_attributes>
+      </node>
+      <node id="1084783376" uname="hana02">
+        <instance_attributes id="nodes-1084783376">
+          <nvpair id="nodes-1084783376-lpa_prd_lpt" name="lpa_prd_lpt" value="30"/>
+          <nvpair id="nodes-1084783376-hana_prd_op_mode" name="hana_prd_op_mode" value="logreplay"/>
+          <nvpair id="nodes-1084783376-hana_prd_vhost" name="hana_prd_vhost" value="hana02"/>
+          <nvpair id="nodes-1084783376-hana_prd_remoteHost" name="hana_prd_remoteHost" value="hana01"/>
+          <nvpair id="nodes-1084783376-hana_prd_site" name="hana_prd_site" value="SECONDARY_SITE_NAME"/>
+          <nvpair id="nodes-1084783376-hana_prd_srmode" name="hana_prd_srmode" value="sync"/>
+        </instance_attributes>
+      </node>
+    </nodes>
+    <resources>
+      <primitive id="stonith-sbd" class="stonith" type="external/sbd">
+        <instance_attributes id="stonith-sbd-instance_attributes">
+          <nvpair name="pcmk_delay_max" value="30s" id="stonith-sbd-instance_attributes-pcmk_delay_max"/>
+        </instance_attributes>
+      </primitive>
+      <primitive id="rsc_ip_PRD_HDB00" class="ocf" provider="heartbeat" type="IPaddr2">
+        <!--#-->
+        <!--# production HANA-->
+        <!--#-->
+        <instance_attributes id="rsc_ip_PRD_HDB00-instance_attributes">
+          <nvpair name="ip" value="192.168.123.200" id="rsc_ip_PRD_HDB00-instance_attributes-ip"/>
+          <nvpair name="cidr_netmask" value="24" id="rsc_ip_PRD_HDB00-instance_attributes-cidr_netmask"/>
+          <nvpair name="nic" value="eth1" id="rsc_ip_PRD_HDB00-instance_attributes-nic"/>
+        </instance_attributes>
+        <operations>
+          <op name="start" timeout="20" interval="0" id="rsc_ip_PRD_HDB00-start-0"/>
+          <op name="stop" timeout="20" interval="0" id="rsc_ip_PRD_HDB00-stop-0"/>
+          <op name="monitor" interval="10" timeout="20" id="rsc_ip_PRD_HDB00-monitor-10"/>
+        </operations>
+      </primitive>
+      <master id="msl_SAPHana_PRD_HDB00">
+        <meta_attributes id="msl_SAPHana_PRD_HDB00-meta_attributes">
+          <nvpair name="clone-max" value="2" id="msl_SAPHana_PRD_HDB00-meta_attributes-clone-max"/>
+          <nvpair name="clone-node-max" value="1" id="msl_SAPHana_PRD_HDB00-meta_attributes-clone-node-max"/>
+          <nvpair name="interleave" value="true" id="msl_SAPHana_PRD_HDB00-meta_attributes-interleave"/>
+        </meta_attributes>
+        <primitive id="rsc_SAPHana_PRD_HDB00" class="ocf" provider="suse" type="SAPHana">
+          <instance_attributes id="rsc_SAPHana_PRD_HDB00-instance_attributes">
+            <nvpair name="SID" value="PRD" id="rsc_SAPHana_PRD_HDB00-instance_attributes-SID"/>
+            <nvpair name="InstanceNumber" value="00" id="rsc_SAPHana_PRD_HDB00-instance_attributes-InstanceNumber"/>
+            <nvpair name="PREFER_SITE_TAKEOVER" value="True" id="rsc_SAPHana_PRD_HDB00-instance_attributes-PREFER_SITE_TAKEOVER"/>
+            <nvpair name="AUTOMATED_REGISTER" value="False" id="rsc_SAPHana_PRD_HDB00-instance_attributes-AUTOMATED_REGISTER"/>
+            <nvpair name="DUPLICATE_PRIMARY_TIMEOUT" value="7200" id="rsc_SAPHana_PRD_HDB00-instance_attributes-DUPLICATE_PRIMARY_TIMEOUT"/>
+          </instance_attributes>
+          <operations>
+            <op name="start" interval="0" timeout="3600" id="rsc_SAPHana_PRD_HDB00-start-0"/>
+            <op name="stop" interval="0" timeout="3600" id="rsc_SAPHana_PRD_HDB00-stop-0"/>
+            <op name="promote" interval="0" timeout="3600" id="rsc_SAPHana_PRD_HDB00-promote-0"/>
+            <op name="monitor" interval="60" role="Master" timeout="700" id="rsc_SAPHana_PRD_HDB00-monitor-60"/>
+            <op name="monitor" interval="61" role="Slave" timeout="700" id="rsc_SAPHana_PRD_HDB00-monitor-61"/>
+          </operations>
+        </primitive>
+      </master>
+      <clone id="cln_SAPHanaTopology_PRD_HDB00">
+        <meta_attributes id="cln_SAPHanaTopology_PRD_HDB00-meta_attributes">
+          <nvpair name="is-managed" value="true" id="cln_SAPHanaTopology_PRD_HDB00-meta_attributes-is-managed"/>
+          <nvpair name="clone-node-max" value="1" id="cln_SAPHanaTopology_PRD_HDB00-meta_attributes-clone-node-max"/>
+          <nvpair name="interleave" value="true" id="cln_SAPHanaTopology_PRD_HDB00-meta_attributes-interleave"/>
+        </meta_attributes>
+        <primitive id="rsc_SAPHanaTopology_PRD_HDB00" class="ocf" provider="suse" type="SAPHanaTopology">
+          <instance_attributes id="rsc_SAPHanaTopology_PRD_HDB00-instance_attributes">
+            <nvpair name="SID" value="PRD" id="rsc_SAPHanaTopology_PRD_HDB00-instance_attributes-SID"/>
+            <nvpair name="InstanceNumber" value="00" id="rsc_SAPHanaTopology_PRD_HDB00-instance_attributes-InstanceNumber"/>
+          </instance_attributes>
+          <operations>
+            <op name="monitor" interval="10" timeout="600" id="rsc_SAPHanaTopology_PRD_HDB00-monitor-10"/>
+            <op name="start" interval="0" timeout="600" id="rsc_SAPHanaTopology_PRD_HDB00-start-0"/>
+            <op name="stop" interval="0" timeout="300" id="rsc_SAPHanaTopology_PRD_HDB00-stop-0"/>
+          </operations>
+        </primitive>
+      </clone>
+      <primitive id="test" class="ocf" provider="heartbeat" type="Dummy"/>
+    </resources>
+    <constraints>
+      <rsc_colocation id="col_saphana_ip_PRD_HDB00" score="2000" rsc="rsc_ip_PRD_HDB00" rsc-role="Started" with-rsc="msl_SAPHana_PRD_HDB00" with-rsc-role="Master"/>
+      <rsc_order id="ord_SAPHana_PRD_HDB00" kind="Optional" first="cln_SAPHanaTopology_PRD_HDB00" then="msl_SAPHana_PRD_HDB00"/>
+      <rsc_location id="cli-prefer-msl_SAPHana_PRD_HDB00" rsc="msl_SAPHana_PRD_HDB00" role="Started" node="hana01" score="INFINITY"/>
+      <rsc_location id="cli-prefer-cln_SAPHanaTopology_PRD_HDB00" rsc="cln_SAPHanaTopology_PRD_HDB00" role="Started" node="hana01" score="INFINITY"/>
+      <rsc_location id="cli-ban-msl_SAPHana_PRD_HDB00-on-hana01" rsc="msl_SAPHana_PRD_HDB00" role="Started" node="hana01" score="-INFINITY"/>
+      <rsc_location id="test" rsc="test" role="Started" node="hana02" score="666"/>
+    </constraints>
+    <rsc_defaults>
+      <meta_attributes id="rsc-options">
+        <nvpair name="resource-stickiness" value="1000" id="rsc-options-resource-stickiness"/>
+        <nvpair name="migration-threshold" value="5000" id="rsc-options-migration-threshold"/>
+      </meta_attributes>
+    </rsc_defaults>
+    <op_defaults>
+      <meta_attributes id="op-options">
+        <nvpair name="timeout" value="600" id="op-options-timeout"/>
+        <nvpair name="record-pending" value="true" id="op-options-record-pending"/>
+      </meta_attributes>
+    </op_defaults>
+  </configuration>
+  <status>
+    <node_state id="1084783375" uname="hana01" in_ccm="true" crmd="online" crm-debug-origin="do_update_resource" join="member" expected="member">
+      <transient_attributes id="1084783375">
+        <instance_attributes id="status-1084783375">
+          <nvpair id="status-1084783375-master-rsc_SAPHana_PRD_HDB00" name="master-rsc_SAPHana_PRD_HDB00" value="150"/>
+          <nvpair id="status-1084783375-hana_prd_version" name="hana_prd_version" value="2.00.040.00.1553674765"/>
+          <nvpair id="status-1084783375-hana_prd_clone_state" name="hana_prd_clone_state" value="PROMOTED"/>
+          <nvpair id="status-1084783375-hana_prd_sync_state" name="hana_prd_sync_state" value="PRIM"/>
+          <nvpair id="status-1084783375-hana_prd_roles" name="hana_prd_roles" value="4:P:master1:master:worker:master"/>
+        </instance_attributes>
+      </transient_attributes>
+      <lrm id="1084783375">
+        <lrm_resources>
+          <lrm_resource id="rsc_SAPHana_PRD_HDB00" type="SAPHana" class="ocf" provider="suse">
+            <lrm_rsc_op id="rsc_SAPHana_PRD_HDB00_last_failure_0" operation_key="rsc_SAPHana_PRD_HDB00_monitor_0" operation="monitor" crm-debug-origin="build_active_RAs" crm_feature_set="3.1.0" transition-key="3:3:7:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;3:3:7:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="15" rc-code="0" op-status="0" interval="0" last-run="1573663876" last-rc-change="1573663876" exec-time="3450" queue-time="0" op-digest="ff4ff123bc6f906497ef0ef5e44dffd1"/>
+            <lrm_rsc_op id="rsc_SAPHana_PRD_HDB00_last_0" operation_key="rsc_SAPHana_PRD_HDB00_promote_0" operation="promote" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="12:8:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;12:8:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="31" rc-code="0" op-status="0" interval="0" last-run="1573663898" last-rc-change="1573663898" exec-time="2257" queue-time="0" op-digest="ff4ff123bc6f906497ef0ef5e44dffd1" op-force-restart=" INSTANCE_PROFILE " op-restart-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+            <lrm_rsc_op id="rsc_SAPHana_PRD_HDB00_monitor_60000" operation_key="rsc_SAPHana_PRD_HDB00_monitor_60000" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="14:9:8:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:8;14:9:8:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="32" rc-code="8" op-status="0" interval="60000" last-rc-change="1573663906" exec-time="3586" queue-time="0" op-digest="05b857e482ebd46019d347fd55ebbcdb"/>
+          </lrm_resource>
+          <lrm_resource id="rsc_ip_PRD_HDB00" type="IPaddr2" class="ocf" provider="heartbeat">
+            <lrm_rsc_op id="rsc_ip_PRD_HDB00_last_0" operation_key="rsc_ip_PRD_HDB00_start_0" operation="start" crm-debug-origin="build_active_RAs" crm_feature_set="3.1.0" transition-key="7:3:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;7:3:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="21" rc-code="0" op-status="0" interval="0" last-run="1573663876" last-rc-change="1573663876" exec-time="136" queue-time="0" op-digest="a6da6959be1e15c2f9f5e88476e82ba4"/>
+            <lrm_rsc_op id="rsc_ip_PRD_HDB00_monitor_10000" operation_key="rsc_ip_PRD_HDB00_monitor_10000" operation="monitor" crm-debug-origin="build_active_RAs" crm_feature_set="3.1.0" transition-key="8:3:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;8:3:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="22" rc-code="0" op-status="0" interval="10000" last-rc-change="1573663876" exec-time="85" queue-time="0" op-digest="c7df6e2194c50ed86aa98b66e909fe11"/>
+          </lrm_resource>
+          <lrm_resource id="stonith-sbd" type="external/sbd" class="stonith">
+            <lrm_rsc_op id="stonith-sbd_last_0" operation_key="stonith-sbd_start_0" operation="start" crm-debug-origin="build_active_RAs" crm_feature_set="3.1.0" transition-key="3:2:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;3:2:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="6" rc-code="0" op-status="0" interval="0" last-run="1573663874" last-rc-change="1573663874" exec-time="2238" queue-time="0" op-digest="265be3215da5e5037d35e7fe1bcc5ae0"/>
+          </lrm_resource>
+          <lrm_resource id="rsc_SAPHanaTopology_PRD_HDB00" type="SAPHanaTopology" class="ocf" provider="suse">
+            <lrm_rsc_op id="rsc_SAPHanaTopology_PRD_HDB00_last_0" operation_key="rsc_SAPHanaTopology_PRD_HDB00_start_0" operation="start" crm-debug-origin="build_active_RAs" crm_feature_set="3.1.0" transition-key="19:4:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;19:4:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="24" rc-code="0" op-status="0" interval="0" last-run="1573663881" last-rc-change="1573663881" exec-time="4355" queue-time="0" op-digest="2d8d79c3726afb91c33d406d5af79b53" op-force-restart="" op-restart-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+            <lrm_rsc_op id="rsc_SAPHanaTopology_PRD_HDB00_monitor_10000" operation_key="rsc_SAPHanaTopology_PRD_HDB00_monitor_10000" operation="monitor" crm-debug-origin="build_active_RAs" crm_feature_set="3.1.0" transition-key="22:5:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;22:5:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="26" rc-code="0" op-status="0" interval="10000" last-rc-change="1573663885" exec-time="4949" queue-time="0" op-digest="64db68ca3e12e0d41eb98ce63b9610d2"/>
+          </lrm_resource>
+          <lrm_resource id="test" type="Dummy" class="ocf" provider="heartbeat">
+            <lrm_rsc_op id="test_last_0" operation_key="test_start_0" operation="start" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="8:6863:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;8:6863:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana01" call-id="37" rc-code="0" op-status="0" interval="0" last-run="1574095329" last-rc-change="1574095329" exec-time="10" queue-time="0" op-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8" op-force-restart=" state " op-restart-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+          </lrm_resource>
+        </lrm_resources>
+      </lrm>
+    </node_state>
+    <node_state id="1084783376" in_ccm="true" crmd="online" crm-debug-origin="do_update_resource" uname="hana02" join="member" expected="member">
+      <lrm id="1084783376">
+        <lrm_resources>
+          <lrm_resource id="stonith-sbd" type="external/sbd" class="stonith">
+            <lrm_rsc_op id="stonith-sbd_last_0" operation_key="stonith-sbd_monitor_0" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="5:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:7;5:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="5" rc-code="7" op-status="0" interval="0" last-run="1573663890" last-rc-change="1573663890" exec-time="1" queue-time="0" op-digest="265be3215da5e5037d35e7fe1bcc5ae0"/>
+          </lrm_resource>
+          <lrm_resource id="rsc_ip_PRD_HDB00" type="IPaddr2" class="ocf" provider="heartbeat">
+            <lrm_rsc_op id="rsc_ip_PRD_HDB00_last_0" operation_key="rsc_ip_PRD_HDB00_monitor_0" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="6:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:7;6:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="9" rc-code="7" op-status="0" interval="0" last-run="1573663890" last-rc-change="1573663890" exec-time="56" queue-time="0" op-digest="a6da6959be1e15c2f9f5e88476e82ba4"/>
+          </lrm_resource>
+          <lrm_resource id="rsc_SAPHana_PRD_HDB00" type="SAPHana" class="ocf" provider="suse">
+            <lrm_rsc_op id="rsc_SAPHana_PRD_HDB00_last_0" operation_key="rsc_SAPHana_PRD_HDB00_monitor_0" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="7:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;7:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="14" rc-code="0" op-status="0" interval="0" last-run="1573663890" last-rc-change="1573663890" exec-time="3515" queue-time="0" op-digest="ff4ff123bc6f906497ef0ef5e44dffd1" op-force-restart=" INSTANCE_PROFILE " op-restart-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+            <lrm_rsc_op id="rsc_SAPHana_PRD_HDB00_last_failure_0" operation_key="rsc_SAPHana_PRD_HDB00_monitor_0" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="7:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;7:6:7:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="14" rc-code="0" op-status="0" interval="0" last-run="1573663890" last-rc-change="1573663890" exec-time="3515" queue-time="0" op-digest="ff4ff123bc6f906497ef0ef5e44dffd1"/>
+            <lrm_rsc_op id="rsc_SAPHana_PRD_HDB00_monitor_61000" operation_key="rsc_SAPHana_PRD_HDB00_monitor_61000" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="13:7:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;13:7:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="20" rc-code="0" op-status="0" interval="61000" last-rc-change="1573663895" exec-time="3225" queue-time="0" op-digest="05b857e482ebd46019d347fd55ebbcdb"/>
+          </lrm_resource>
+          <lrm_resource id="rsc_SAPHanaTopology_PRD_HDB00" type="SAPHanaTopology" class="ocf" provider="suse">
+            <lrm_rsc_op id="rsc_SAPHanaTopology_PRD_HDB00_last_0" operation_key="rsc_SAPHanaTopology_PRD_HDB00_start_0" operation="start" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="24:7:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;24:7:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="21" rc-code="0" op-status="0" interval="0" last-run="1573663895" last-rc-change="1573663895" exec-time="3650" queue-time="0" op-digest="2d8d79c3726afb91c33d406d5af79b53" op-force-restart="" op-restart-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+            <lrm_rsc_op id="rsc_SAPHanaTopology_PRD_HDB00_monitor_10000" operation_key="rsc_SAPHanaTopology_PRD_HDB00_monitor_10000" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="28:8:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;28:8:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="22" rc-code="0" op-status="0" interval="10000" last-rc-change="1573663898" exec-time="3978" queue-time="0" op-digest="64db68ca3e12e0d41eb98ce63b9610d2"/>
+          </lrm_resource>
+          <lrm_resource id="test" type="Dummy" class="ocf" provider="heartbeat">
+            <lrm_rsc_op id="test_last_0" operation_key="test_stop_0" operation="stop" crm-debug-origin="do_update_resource" crm_feature_set="3.1.0" transition-key="7:6863:0:70ea6528-73ad-48be-9eb7-583ee933f216" transition-magic="0:0;7:6863:0:70ea6528-73ad-48be-9eb7-583ee933f216" exit-reason="" on_node="hana02" call-id="28" rc-code="0" op-status="0" interval="0" last-run="1574095329" last-rc-change="1574095329" exec-time="12" queue-time="0" op-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8" op-force-restart=" state " op-restart-digest="f2317cad3d54cec5d7d7aa7d0bf35cf8"/>
+          </lrm_resource>
+        </lrm_resources>
+      </lrm>
+      <transient_attributes id="1084783376">
+        <instance_attributes id="status-1084783376">
+          <nvpair id="status-1084783376-hana_prd_clone_state" name="hana_prd_clone_state" value="DEMOTED"/>
+          <nvpair id="status-1084783376-master-rsc_SAPHana_PRD_HDB00" name="master-rsc_SAPHana_PRD_HDB00" value="100"/>
+          <nvpair id="status-1084783376-hana_prd_version" name="hana_prd_version" value="2.00.040.00.1553674765"/>
+          <nvpair id="status-1084783376-hana_prd_roles" name="hana_prd_roles" value="4:S:master1:master:worker:master"/>
+          <nvpair id="status-1084783376-hana_prd_sync_state" name="hana_prd_sync_state" value="SOK"/>
+        </instance_attributes>
+      </transient_attributes>
+    </node_state>
+  </status>
+</cib>
 EOF
diff --git a/test/fake_crm_mon.sh b/test/fake_crm_mon.sh
index d0f8554..7318e98 100755
--- a/test/fake_crm_mon.sh
+++ b/test/fake_crm_mon.sh
@@ -85,7 +85,6 @@ cat <<EOF
     <tickets>
     </tickets>
     <bans>
-        <ban id="cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana01" resource="msl_SAPHana_PRD_HDB00" node="damadog-hana01" weight="-1000000" master_only="false" />
     </bans>
 </crm_mon>
 EOF
diff --git a/test/pacemaker.metrics b/test/pacemaker.metrics
index c5702a6..d0dbc77 100644
--- a/test/pacemaker.metrics
+++ b/test/pacemaker.metrics
@@ -1,11 +1,6 @@
 # HELP ha_cluster_pacemaker_config_last_change The timestamp of the last change of the cluster configuration
 # TYPE ha_cluster_pacemaker_config_last_change counter
 ha_cluster_pacemaker_config_last_change 1.571399302e+09 1234
-# HELP ha_cluster_pacemaker_constraints Indicate if a constraints of specific type is present per ID and per resource
-# TYPE ha_cluster_pacemaker_constraints gauge
-ha_cluster_pacemaker_constraints{id="cli-ban-msl_SAPHana_PRD_HDB00-on-damadog-hana01",resource="msl_SAPHana_PRD_HDB00",type="ban"} 1 1234
-ha_cluster_pacemaker_constraints{id="cli-prefer-cln_SAPHanaTopology_PRD_HDB00",resource="cln_SAPHanaTopology_PRD_HDB00",type="prefer"} 1 1234
-ha_cluster_pacemaker_constraints{id="cli-prefer-msl_SAPHana_PRD_HDB00",resource="msl_SAPHana_PRD_HDB00",type="prefer"} 1 1234
 # HELP ha_cluster_pacemaker_fail_count The Fail count number per node and resource id
 # TYPE ha_cluster_pacemaker_fail_count gauge
 ha_cluster_pacemaker_fail_count{node="hana01",resource="rsc_SAPHanaTopology_PRD_HDB00"} 0 1234
@@ -14,6 +9,12 @@ ha_cluster_pacemaker_fail_count{node="hana01",resource="rsc_ip_PRD_HDB00"} 2 123
 ha_cluster_pacemaker_fail_count{node="hana01",resource="stonith-sbd"} 0 1234
 ha_cluster_pacemaker_fail_count{node="hana02",resource="rsc_SAPHanaTopology_PRD_HDB00"} 0 1234
 ha_cluster_pacemaker_fail_count{node="hana02",resource="rsc_SAPHana_PRD_HDB00"} 300 1234
+# HELP ha_cluster_pacemaker_location_constraints Resource location constraints. The value indicates the score.
+# TYPE ha_cluster_pacemaker_location_constraints gauge
+ha_cluster_pacemaker_location_constraints{constraint="cli-ban-msl_SAPHana_PRD_HDB00-on-hana01",node="hana01",resource="msl_SAPHana_PRD_HDB00",role="started"} -Inf 1234
+ha_cluster_pacemaker_location_constraints{constraint="cli-prefer-cln_SAPHanaTopology_PRD_HDB00",node="hana01",resource="cln_SAPHanaTopology_PRD_HDB00",role="started"} +Inf 1234
+ha_cluster_pacemaker_location_constraints{constraint="cli-prefer-msl_SAPHana_PRD_HDB00",node="hana01",resource="msl_SAPHana_PRD_HDB00",role="started"} +Inf 1234
+ha_cluster_pacemaker_location_constraints{constraint="test",node="hana02",resource="test",role="started"} 666 1234
 # HELP ha_cluster_pacemaker_migration_threshold The migration_threshold number per node and resource id
 # TYPE ha_cluster_pacemaker_migration_threshold gauge
 ha_cluster_pacemaker_migration_threshold{node="hana01",resource="rsc_SAPHanaTopology_PRD_HDB00"} 1 1234