Blame SOURCES/011-shutdown-lock.patch

ed4e54
From f5d88938955f63935058b7cc2d706a12e6ea1121 Mon Sep 17 00:00:00 2001
ed4e54
From: Ken Gaillot <kgaillot@redhat.com>
ed4e54
Date: Fri, 6 Dec 2019 11:57:59 -0600
ed4e54
Subject: [PATCH 07/18] Low: scheduler: respect shutdown locks when placing
ed4e54
 active resources
ed4e54
ed4e54
Use new pe_resource_t members to indicate that a resource is locked to a
ed4e54
particular node.
ed4e54
ed4e54
For active resources (i.e. in the transition where the node is scheduled for
ed4e54
shutdown), these are connected by checking each lockable resource for whether
ed4e54
it is running on a single clean node that is shutting down.
ed4e54
ed4e54
When applying constraints, place -INFINITY location constraints for locked
ed4e54
resources on all nodes other than the lock node.
ed4e54
ed4e54
(Inactive resources -- i.e. in later transitions after the node is shut down --
ed4e54
are not yet locked.)
ed4e54
---
ed4e54
 include/crm/pengine/pe_types.h      |  2 +
ed4e54
 lib/pacemaker/pcmk_sched_allocate.c | 87 +++++++++++++++++++++++++++++++++++++
ed4e54
 2 files changed, 89 insertions(+)
ed4e54
ed4e54
diff --git a/include/crm/pengine/pe_types.h b/include/crm/pengine/pe_types.h
ed4e54
index 8a735a3..123d8ef 100644
ed4e54
--- a/include/crm/pengine/pe_types.h
ed4e54
+++ b/include/crm/pengine/pe_types.h
ed4e54
@@ -354,6 +354,8 @@ struct pe_resource_s {
ed4e54
     GListPtr fillers;
ed4e54
 
ed4e54
     pe_node_t *pending_node;    // Node on which pending_task is happening
ed4e54
+    pe_node_t *lock_node;       // Resource is shutdown-locked to this node
ed4e54
+    time_t lock_time;           // When shutdown lock started
ed4e54
 
ed4e54
 #if ENABLE_VERSIONED_ATTRS
ed4e54
     xmlNode *versioned_parameters;
ed4e54
diff --git a/lib/pacemaker/pcmk_sched_allocate.c b/lib/pacemaker/pcmk_sched_allocate.c
ed4e54
index fc2f4cf..0314f1b 100644
ed4e54
--- a/lib/pacemaker/pcmk_sched_allocate.c
ed4e54
+++ b/lib/pacemaker/pcmk_sched_allocate.c
ed4e54
@@ -977,6 +977,87 @@ rsc_discover_filter(resource_t *rsc, node_t *node)
ed4e54
     }
ed4e54
 }
ed4e54
 
ed4e54
+static time_t
ed4e54
+shutdown_time(pe_node_t *node, pe_working_set_t *data_set)
ed4e54
+{
ed4e54
+    const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
ed4e54
+    time_t result = 0;
ed4e54
+
ed4e54
+    if (shutdown) {
ed4e54
+        errno = 0;
ed4e54
+        result = (time_t) crm_int_helper(shutdown, NULL);
ed4e54
+        if (errno != 0) {
ed4e54
+            result = 0;
ed4e54
+        }
ed4e54
+    }
ed4e54
+    return result? result : get_effective_time(data_set);
ed4e54
+}
ed4e54
+
ed4e54
+static void
ed4e54
+apply_shutdown_lock(pe_resource_t *rsc, pe_working_set_t *data_set)
ed4e54
+{
ed4e54
+    const char *class;
ed4e54
+
ed4e54
+    // Only primitives and (uncloned) groups may be locked
ed4e54
+    if (rsc->variant == pe_group) {
ed4e54
+        for (GList *item = rsc->children; item != NULL;
ed4e54
+             item = item->next) {
ed4e54
+            apply_shutdown_lock((pe_resource_t *) item->data, data_set);
ed4e54
+        }
ed4e54
+    } else if (rsc->variant != pe_native) {
ed4e54
+        return;
ed4e54
+    }
ed4e54
+
ed4e54
+    // Fence devices and remote connections can't be locked
ed4e54
+    class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
ed4e54
+    if ((class == NULL) || !strcmp(class, PCMK_RESOURCE_CLASS_STONITH)
ed4e54
+        || pe__resource_is_remote_conn(rsc, data_set)) {
ed4e54
+        return;
ed4e54
+    }
ed4e54
+
ed4e54
+    // Only a resource active on exactly one node can be locked
ed4e54
+    if (pcmk__list_of_1(rsc->running_on)) {
ed4e54
+        pe_node_t *node = rsc->running_on->data;
ed4e54
+
ed4e54
+        if (node->details->shutdown) {
ed4e54
+            if (node->details->unclean) {
ed4e54
+                pe_rsc_debug(rsc, "Not locking %s to unclean %s for shutdown",
ed4e54
+                             rsc->id, node->details->uname);
ed4e54
+            } else {
ed4e54
+                rsc->lock_node = node;
ed4e54
+                rsc->lock_time = shutdown_time(node, data_set);
ed4e54
+            }
ed4e54
+        }
ed4e54
+    }
ed4e54
+
ed4e54
+    if (rsc->lock_node == NULL) {
ed4e54
+        // No lock needed
ed4e54
+        return;
ed4e54
+    }
ed4e54
+
ed4e54
+    if (data_set->shutdown_lock > 0) {
ed4e54
+        time_t lock_expiration = rsc->lock_time + data_set->shutdown_lock;
ed4e54
+
ed4e54
+        pe_rsc_info(rsc, "Locking %s to %s due to shutdown (expires @%lld)",
ed4e54
+                    rsc->id, rsc->lock_node->details->uname,
ed4e54
+                    (long long) lock_expiration);
ed4e54
+        pe__update_recheck_time(++lock_expiration, data_set);
ed4e54
+    } else {
ed4e54
+        pe_rsc_info(rsc, "Locking %s to %s due to shutdown",
ed4e54
+                    rsc->id, rsc->lock_node->details->uname);
ed4e54
+    }
ed4e54
+
ed4e54
+    // If resource is locked to one node, ban it from all other nodes
ed4e54
+    for (GList *item = data_set->nodes; item != NULL; item = item->next) {
ed4e54
+        pe_node_t *node = item->data;
ed4e54
+
ed4e54
+        if (strcmp(node->details->uname, rsc->lock_node->details->uname)) {
ed4e54
+            resource_location(rsc, node, -CRM_SCORE_INFINITY,
ed4e54
+                              XML_CONFIG_ATTR_SHUTDOWN_LOCK, data_set);
ed4e54
+        }
ed4e54
+    }
ed4e54
+}
ed4e54
+
ed4e54
 /*
ed4e54
  * Count how many valid nodes we have (so we know the maximum number of
ed4e54
  *  colors we can resolve).
ed4e54
@@ -988,6 +1069,12 @@ stage2(pe_working_set_t * data_set)
ed4e54
 {
ed4e54
     GListPtr gIter = NULL;
ed4e54
 
ed4e54
+    if (is_set(data_set->flags, pe_flag_shutdown_lock)) {
ed4e54
+        for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
ed4e54
+            apply_shutdown_lock((pe_resource_t *) gIter->data, data_set);
ed4e54
+        }
ed4e54
+    }
ed4e54
+
ed4e54
     for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
ed4e54
         node_t *node = (node_t *) gIter->data;
ed4e54
 
ed4e54
-- 
ed4e54
1.8.3.1
ed4e54