File bsc#1155290-0001-Bug-tools-Fix-moving-a-resource-with-a-lifetime-cons-1.1.patch of Package pacemaker.16959
From e063d082d3aa0780b27ec5eff9c60783dcd23235 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 11 Jan 2019 12:14:58 -0500
Subject: [PATCH 1/4] Bug: tools: Fix moving a resource with a lifetime
constraint
A node can be specified two different ways - with attribute="#uname"
and value= on an expression XML node, or with node= on a rsc_location
XML node. Both possibilities need to be considered when attempting to
clear an existing constraint.
cli_resource_clear was previously only considering the second case.
This patch rearranges the code to allow for trying both, and then adds
the code to try the first case by constructing a different blob of XML
to match.
See rhbz#1648620
---
tools/crm_resource_ban.c | 104 +++++++++++++++++++++++++++++++++++------------
1 file changed, 79 insertions(+), 25 deletions(-)
Index: pacemaker-1.1.19+20181105.ccd6b5b10/tools/crm_resource_ban.c
===================================================================
--- pacemaker-1.1.19+20181105.ccd6b5b10.orig/tools/crm_resource_ban.c
+++ pacemaker-1.1.19+20181105.ccd6b5b10/tools/crm_resource_ban.c
@@ -188,37 +188,56 @@ cli_resource_prefer(const char *rsc_id,
return rc;
}
-int
-cli_resource_clear(const char *rsc_id, const char *host, GListPtr allnodes, cib_t * cib_conn)
+/* Nodes can be specified two different ways in the CIB, so we have two different
+ * functions to try clearing out any constraints on them:
+ *
+ * (1) The node could be given by attribute=/value= in an expression XML node.
+ * That's what resource_clear_node_in_expr handles. That XML looks like this:
+ *
+ * <rsc_location id="cli-prefer-dummy" rsc="dummy" role="Started">
+ * <rule id="cli-prefer-rule-dummy" score="INFINITY" boolean-op="and">
+ * <expression id="cli-prefer-expr-dummy" attribute="#uname" operation="eq" value="test02" type="string"/>
+ * <date_expression id="cli-prefer-lifetime-end-dummy" operation="lt" end="2018-12-12 14:05:37 -05:00"/>
+ * </rule>
+ * </rsc_location>
+ *
+ * (2) The mode could be given by node= in an rsc_location XML node. That's
+ * what resource_clear_node_in_location handles. That XML looks like this:
+ *
+ * <rsc_location id="cli-prefer-dummy" rsc="dummy" role="Started" node="node1" score="INFINITY"/>
+ */
+static int
+resource_clear_node_in_expr(const char *rsc_id, const char *host, cib_t * cib_conn)
{
int rc = pcmk_ok;
- xmlNode *fragment = NULL;
- xmlNode *location = NULL;
+ char *xpath_string = NULL;
- if(cib_conn == NULL) {
- return -ENOTCONN;
- }
+ xpath_string = crm_strdup_printf("//rsc_location[@id='cli-prefer-%s'][rule[@id='cli-prefer-rule-%s']/expression[@attribute='#uname' and @value='%s']]",
+ rsc_id, rsc_id, host);
- fragment = create_xml_node(NULL, XML_CIB_TAG_CONSTRAINTS);
+ rc = cib_conn->cmds->delete(cib_conn, xpath_string, NULL, cib_xpath | cib_options);
+ if (rc == -ENXIO) {
+ rc = pcmk_ok;
+ }
- if(host) {
- location = create_xml_node(fragment, XML_CONS_TAG_RSC_LOCATION);
- crm_xml_set_id(location, "cli-ban-%s-on-%s", rsc_id, host);
+ free(xpath_string);
+ return rc;
+}
- } else {
- GListPtr n = allnodes;
- for(; n; n = n->next) {
- node_t *target = n->data;
+static int
+resource_clear_node_in_location(const char *rsc_id, const char *host, cib_t * cib_conn)
+{
+ int rc = pcmk_ok;
+ xmlNode *fragment = NULL;
+ xmlNode *location = NULL;
- location = create_xml_node(fragment, XML_CONS_TAG_RSC_LOCATION);
- crm_xml_set_id(location, "cli-ban-%s-on-%s",
- rsc_id, target->details->uname);
- }
- }
+ fragment = create_xml_node(NULL, XML_CIB_TAG_CONSTRAINTS);
+ location = create_xml_node(fragment, XML_CONS_TAG_RSC_LOCATION);
+ crm_xml_set_id(location, "cli-ban-%s-on-%s", rsc_id, host);
location = create_xml_node(fragment, XML_CONS_TAG_RSC_LOCATION);
crm_xml_set_id(location, "cli-prefer-%s", rsc_id);
- if(host && do_force == FALSE) {
+ if (do_force == FALSE) {
crm_xml_add(location, XML_CIB_TAG_NODE, host);
}
@@ -226,12 +245,47 @@ cli_resource_clear(const char *rsc_id, c
rc = cib_conn->cmds->delete(cib_conn, XML_CIB_TAG_CONSTRAINTS, fragment, cib_options);
if (rc == -ENXIO) {
rc = pcmk_ok;
+ }
+
+ free(fragment);
+ return rc;
+}
+
+int
+cli_resource_clear(const char *rsc_id, const char *host, GListPtr allnodes, cib_t * cib_conn)
+{
+ int rc = pcmk_ok;
+
+ if(cib_conn == NULL) {
+ return -ENOTCONN;
+ }
+
+ if (host) {
+ rc = resource_clear_node_in_expr(rsc_id, host, cib_conn);
+
+ /* rc does not tell us whether the previous operation did anything, only
+ * whether it failed or not. Thus, as long as it did not fail, we need
+ * to try the second clear method.
+ */
+ if (rc == pcmk_ok) {
+ rc = resource_clear_node_in_location(rsc_id, host, cib_conn);
+ }
+
+ } else {
+ GListPtr n = allnodes;
+
+ /* Iterate over all nodes, attempting to clear the constraint from each.
+ * On the first error, abort.
+ */
+ for(; n; n = n->next) {
+ node_t *target = n->data;
- } else if (rc != pcmk_ok) {
- goto bail;
+ rc = cli_resource_clear(rsc_id, target->details->uname, NULL, cib_conn);
+ if (rc != pcmk_ok) {
+ break;
+ }
+ }
}
- bail:
- free_xml(fragment);
return rc;
}