Blob Blame History Raw
commit 5efd173dac6b22eee48f1f9372b2e86cb6d27282
Author: Andrew Beekhof <andrew@beekhof.net>
Date:   Thu Apr 3 16:02:23 2014 +1100

    Feature: PE: Automatically re-unfence a node if the fencing device definition changes
    
    Ensures all resources that require unfencing are stopped first
    If unfencing is enabled, this is the new default for resource.requires
    
    (cherry picked from commit 26fe2e39b9e060597cddeeb69d8b846784dfac55)
    
    Conflicts:
    	include/crm/pengine/internal.h
    	include/crm/pengine/status.h
    	lib/pengine/complex.c

diff --git a/fencing/main.c b/fencing/main.c
index c40610e..e002125 100644
--- a/fencing/main.c
+++ b/fencing/main.c
@@ -573,7 +573,6 @@ fencing_topology_init(xmlNode * msg)
 }
 
 #define rsc_name(x) x->clone_name?x->clone_name:x->id
-static bool have_fence_scsi = FALSE;
 
 static void cib_device_update(resource_t *rsc, pe_working_set_t *data_set)
 {
@@ -662,34 +661,6 @@ static void cib_device_update(resource_t *rsc, pe_working_set_t *data_set)
         data = create_device_registration_xml(rsc_name(rsc), provider, agent, params);
         stonith_device_register(data, NULL, TRUE);
 
-        /* If required, unfence ourselves on cluster startup
-         *
-         * Make this generic/smarter if/when more than a single agent needs this
-         */
-        if(have_fence_scsi == FALSE && safe_str_eq(agent, "fence_scsi")) {
-            stonith_device_t *device = g_hash_table_lookup(device_list, rsc->id);
-
-            if(stonith_our_uname == NULL) {
-                crm_trace("Cannot unfence ourselves: no local host name");
-
-            } else if(device == NULL) {
-                crm_err("Cannot unfence ourselves: no such device '%s'", rsc->id);
-
-            } else {
-                const char *alias = g_hash_table_lookup(device->aliases, stonith_our_uname);
-
-                if (!alias) {
-                    alias = stonith_our_uname;
-                }
-
-                if (device->targets && string_in_list(device->targets, alias)) {
-                    have_fence_scsi = TRUE;
-                    crm_notice("Unfencing ourselves with %s (%s)", agent, device->id);
-                    schedule_internal_command(__FUNCTION__, device, "on", stonith_our_uname, 0, NULL, unfence_cb);
-                }
-            }
-        }
-
         stonith_key_value_freeall(params, 1, 1);
         free_xml(data);
     }
diff --git a/include/crm/msg_xml.h b/include/crm/msg_xml.h
index 8575163..055f476 100644
--- a/include/crm/msg_xml.h
+++ b/include/crm/msg_xml.h
@@ -200,6 +200,7 @@
 #  define XML_RSC_ATTR_MULTIPLE		"multiple-active"
 #  define XML_RSC_ATTR_PRIORITY		"priority"
 #  define XML_RSC_ATTR_REQUIRES		"requires"
+#  define XML_RSC_ATTR_PROVIDES		"provides"
 #  define XML_RSC_ATTR_CONTAINER	"container"
 #  define XML_RSC_ATTR_INTERNAL_RSC	"internal_rsc"
 #  define XML_OP_ATTR_ON_FAIL		"on-fail"
diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h
index dd52e7f..657c647 100644
--- a/include/crm/pengine/internal.h
+++ b/include/crm/pengine/internal.h
@@ -261,6 +261,7 @@ op_digest_cache_t *rsc_action_digest_cmp(resource_t * rsc, xmlNode * xml_op, nod
                                          pe_working_set_t * data_set);
 
 gboolean is_remote_node(xmlNode *xml);
+void clear_bit_recursive(resource_t * rsc, unsigned long long flag);
 
 resource_t * rsc_contains_remote_node(pe_working_set_t * data_set, resource_t *rsc);
 #endif
diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h
index b74bf83..ddf9dd7 100644
--- a/include/crm/pengine/status.h
+++ b/include/crm/pengine/status.h
@@ -60,6 +60,7 @@ enum pe_find {
 
 #  define pe_flag_stonith_enabled	0x00000010ULL
 #  define pe_flag_have_stonith_resource	0x00000020ULL
+#  define pe_flag_enable_unfencing	0x00000040ULL
 
 #  define pe_flag_stop_rsc_orphans	0x00000100ULL
 #  define pe_flag_stop_action_orphans	0x00000200ULL
@@ -165,6 +166,7 @@ struct node_s {
 
 #  define pe_rsc_notify		0x00000010ULL
 #  define pe_rsc_unique		0x00000020ULL
+#  define pe_rsc_fence_device   0x00000040ULL
 
 #  define pe_rsc_provisional	0x00000100ULL
 #  define pe_rsc_allocating	0x00000200ULL
@@ -329,6 +331,12 @@ enum pe_ordering {
 
     pe_order_runnable_left         = 0x100,     /* 'then' requires 'first' to be runnable */
 
+    pe_order_pseudo_left           = 0x200,     /* 'then' can only be pseudo if 'first' is runnable */
+    pe_order_implies_then_on_node  = 0x400,     /* If 'first' is required on 'nodeX',
+                                                 * ensure instances of 'then' on 'nodeX' are too.
+                                                 * Only really useful if 'then' is a clone and 'first' is not
+                                                 */
+
     pe_order_restart               = 0x1000,    /* 'then' is runnable if 'first' is optional or runnable */
     pe_order_stonith_stop          = 0x2000,    /* only applies if the action is non-pseudo */
     pe_order_serialize_only        = 0x4000,    /* serialize */
diff --git a/lib/pengine/clone.c b/lib/pengine/clone.c
index c6c69e6..b13cceb 100644
--- a/lib/pengine/clone.c
+++ b/lib/pengine/clone.c
@@ -46,7 +46,7 @@ mark_as_orphan(resource_t * rsc)
     }
 }
 
-static void
+void
 clear_bit_recursive(resource_t * rsc, unsigned long long flag)
 {
     GListPtr gIter = rsc->children;
diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c
index 8a6049d..8b774c0 100644
--- a/lib/pengine/complex.c
+++ b/lib/pengine/complex.c
@@ -340,12 +340,13 @@ gboolean
 common_unpack(xmlNode * xml_obj, resource_t ** rsc,
               resource_t * parent, pe_working_set_t * data_set)
 {
+    bool isdefault = FALSE;
     xmlNode *expanded_xml = NULL;
     xmlNode *ops = NULL;
     resource_t *top = NULL;
     const char *value = NULL;
+    const char *rclass = NULL; /* Look for this after any templates have been expanded */
     const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
-    const char *class = crm_element_value(xml_obj, XML_AGENT_ATTR_CLASS);
 
     crm_log_xml_trace(xml_obj, "Processing resource input...");
 
@@ -375,6 +376,8 @@ common_unpack(xmlNode * xml_obj, resource_t ** rsc,
         (*rsc)->orig_xml = NULL;
     }
 
+    /* Do not use xml_obj from here on, use (*rsc)->xml in case templates are involved */
+    rclass = crm_element_value((*rsc)->xml, XML_AGENT_ATTR_CLASS);
     (*rsc)->parent = parent;
 
     ops = find_xml_node((*rsc)->xml, "operations", FALSE);
@@ -538,47 +541,67 @@ common_unpack(xmlNode * xml_obj, resource_t ** rsc,
         }
     }
 
+    if (safe_str_eq(rclass, "stonith")) {
+        set_bit(data_set->flags, pe_flag_have_stonith_resource);
+        set_bit((*rsc)->flags, pe_rsc_fence_device);
+    }
+
     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_REQUIRES);
+
+  handle_requires_pref:
     if (safe_str_eq(value, "nothing")) {
 
     } else if (safe_str_eq(value, "quorum")) {
         set_bit((*rsc)->flags, pe_rsc_needs_quorum);
 
     } else if (safe_str_eq(value, "unfencing")) {
-        set_bit((*rsc)->flags, pe_rsc_needs_fencing);
-        set_bit((*rsc)->flags, pe_rsc_needs_unfencing);
-        if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
-            crm_notice("%s requires (un)fencing but fencing is disabled", (*rsc)->id);
+        if (is_set((*rsc)->flags, pe_rsc_fence_device)) {
+            crm_config_warn("%s is a fencing device but requires (un)fencing", (*rsc)->id);
+            value = "quorum";
+            isdefault = TRUE;
+            goto handle_requires_pref;
+
+        } else if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
+            crm_config_warn("%s requires (un)fencing but fencing is disabled", (*rsc)->id);
+            value = "quorum";
+            isdefault = TRUE;
+            goto handle_requires_pref;
+
+        } else {
+            set_bit((*rsc)->flags, pe_rsc_needs_fencing);
+            set_bit((*rsc)->flags, pe_rsc_needs_unfencing);
         }
 
     } else if (safe_str_eq(value, "fencing")) {
         set_bit((*rsc)->flags, pe_rsc_needs_fencing);
         if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
-            crm_notice("%s requires fencing but fencing is disabled", (*rsc)->id);
+            crm_config_warn("%s requires (un)fencing but fencing is disabled", (*rsc)->id);
         }
 
     } else {
         if (value) {
             crm_config_err("Invalid value for %s->requires: %s%s",
                            (*rsc)->id, value,
-                           is_set(data_set->flags,
-                                  pe_flag_stonith_enabled) ? "" : " (stonith-enabled=false)");
+                           is_set(data_set->flags, pe_flag_stonith_enabled) ? "" : " (stonith-enabled=false)");
         }
 
-        if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
-            set_bit((*rsc)->flags, pe_rsc_needs_fencing);
-            value = "fencing (default)";
+        isdefault = TRUE;
+        if (is_set(data_set->flags, pe_flag_enable_unfencing)) {
+            value = "unfencing";
+
+        } else if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
+            value = "fencing";
 
         } else if (data_set->no_quorum_policy == no_quorum_ignore) {
-            value = "nothing (default)";
+            value = "nothing";
 
         } else {
-            set_bit((*rsc)->flags, pe_rsc_needs_quorum);
-            value = "quorum (default)";
+            value = "quorum";
         }
+        goto handle_requires_pref;
     }
 
-    pe_rsc_trace((*rsc), "\tRequired to start: %s", value);
+    pe_rsc_trace((*rsc), "\tRequired to start: %s%s", value, isdefault?" (default)":"");
 
     value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_FAIL_TIMEOUT);
     if (value != NULL) {
@@ -606,10 +629,6 @@ common_unpack(xmlNode * xml_obj, resource_t ** rsc,
     pe_rsc_trace((*rsc), "\tAction notification: %s",
                  is_set((*rsc)->flags, pe_rsc_notify) ? "required" : "not required");
 
-    if (safe_str_eq(class, "stonith")) {
-        set_bit(data_set->flags, pe_flag_have_stonith_resource);
-    }
-
     (*rsc)->utilization =
         g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
 
diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c
index 56ed291..39ded96 100644
--- a/lib/pengine/unpack.c
+++ b/lib/pengine/unpack.c
@@ -77,6 +77,35 @@ unpack_config(xmlNode * config, pe_working_set_t * data_set)
     GHashTable *config_hash =
         g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
 
+    xmlXPathObjectPtr xpathObj = NULL;
+
+    if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
+        xpathObj = xpath_search(data_set->input, "//nvpair[@name='provides' and @value='unfencing']");
+        if(xpathObj && numXpathResults(xpathObj) > 0) {
+            set_bit(data_set->flags, pe_flag_enable_unfencing);
+        }
+        freeXpathObject(xpathObj);
+    }
+
+    if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
+        xpathObj = xpath_search(data_set->input, "//nvpair[@name='requires' and @value='unfencing']");
+        if(xpathObj && numXpathResults(xpathObj) > 0) {
+            set_bit(data_set->flags, pe_flag_enable_unfencing);
+        }
+        freeXpathObject(xpathObj);
+    }
+
+
+#ifdef REDHAT_COMPAT_6
+    if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
+        xpathObj = xpath_search(data_set->input, "//primitive[@type='fence_scsi']");
+        if(xpathObj && numXpathResults(xpathObj) > 0) {
+            set_bit(data_set->flags, pe_flag_enable_unfencing);
+        }
+        freeXpathObject(xpathObj);
+    }
+#endif
+
     data_set->config_hash = config_hash;
 
     unpack_instance_attributes(data_set->input, config, XML_CIB_TAG_PROPSET, NULL, config_hash,
diff --git a/pengine/allocate.c b/pengine/allocate.c
index b9ce069..88258f4 100644
--- a/pengine/allocate.c
+++ b/pengine/allocate.c
@@ -123,6 +123,7 @@ check_rsc_parameters(resource_t * rsc, node_t * node, xmlNode * rsc_entry,
         }
 
         changed = TRUE;
+        trigger_unfencing(rsc, node, "Device definition changed", NULL, data_set);
         if (active_here) {
             force_restart = TRUE;
             crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s",
@@ -169,6 +170,7 @@ CancelXmlOp(resource_t * rsc, xmlNode * xml_op, node_t * active_node,
     crm_info("Action %s on %s will be stopped: %s",
              key, active_node->details->uname, reason ? reason : "unknown");
 
+    /* TODO: This looks highly dangerous if we ever try to schedule 'key' too */
     cancel = custom_action(rsc, strdup(key), RSC_CANCEL, active_node, FALSE, TRUE, data_set);
 
     free(cancel->task);
@@ -227,6 +229,7 @@ check_action_definition(resource_t * rsc, node_t * active_node, xmlNode * xml_op
         key = NULL;
     }
 
+    crm_trace("Testing %s_%s_%d on %s", rsc->id, task, interval, active_node?active_node->details->uname:"N/A");
     if (interval == 0 && safe_str_eq(task, RSC_STATUS)) {
         /* Reload based on the start action not a probe */
         task = RSC_START;
@@ -252,6 +255,7 @@ check_action_definition(resource_t * rsc, node_t * active_node, xmlNode * xml_op
                  op_version, crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
 
         custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
+        trigger_unfencing(rsc, NULL, "Device parameters changed", NULL, data_set);
 
     } else if ((digest_data->rc == RSC_DIGEST_ALL) || (digest_data->rc == RSC_DIGEST_UNKNOWN)) {
         /* Changes that can potentially be handled by a reload */
@@ -259,6 +263,7 @@ check_action_definition(resource_t * rsc, node_t * active_node, xmlNode * xml_op
         const char *digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST);
 
         did_change = TRUE;
+        trigger_unfencing(rsc, NULL, "Device parameters changed (reload)", NULL, data_set);
         crm_log_xml_info(digest_data->params_all, "params:reload");
         key = generate_op_key(rsc->id, task, interval);
         pe_rsc_info(rsc, "Parameters to %s on %s changed: was %s vs. now %s (reload:%s) %s",
@@ -1262,8 +1267,40 @@ any_managed_resources(pe_working_set_t * data_set)
     return FALSE;
 }
 
+void
+trigger_unfencing(
+    resource_t * rsc, node_t *node, const char *reason, action_t *dependancy, pe_working_set_t * data_set) 
+{
+    if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
+        /* No resources require it */
+        return;
+
+    } else if (rsc != NULL && is_not_set(rsc->flags, pe_rsc_fence_device)) {
+        /* Wasnt a stonith device */
+        return;
+
+    } else if(node) {
+        action_t *unfence = pe_fence_op(node, "on", FALSE, data_set);
+
+        crm_notice("Unfencing %s: %s", node->details->uname, reason);
+        if(FALSE && dependancy) {
+            order_actions(dependancy, unfence, pe_order_optional);
+        }
+
+    } else if(rsc) {
+        GHashTableIter iter;
+
+        g_hash_table_iter_init(&iter, rsc->allowed_nodes);
+        while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
+            if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
+                trigger_unfencing(rsc, node, reason, dependancy, data_set);
+            }
+        }
+    }
+}
+
 action_t *
-pe_fence_op(node_t * node, const char *op, pe_working_set_t * data_set)
+pe_fence_op(node_t * node, const char *op, bool optional, pe_working_set_t * data_set)
 {
     char *key = NULL;
     action_t *stonith_op = NULL;
@@ -1279,13 +1316,18 @@ pe_fence_op(node_t * node, const char *op, pe_working_set_t * data_set)
     }
 
     if(stonith_op == NULL) {
-        stonith_op = custom_action(NULL, key, CRM_OP_FENCE, node, FALSE, TRUE, data_set);
+        stonith_op = custom_action(NULL, key, CRM_OP_FENCE, node, optional, TRUE, data_set);
 
         add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET, node->details->uname);
         add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET_UUID, node->details->id);
         add_hash_param(stonith_op->meta, "stonith_action", op);
     }
 
+    if(optional == FALSE) {
+        crm_trace("%s is no longer optional", stonith_op->uuid);
+        pe_clear_action_bit(stonith_op, pe_action_optional);
+    }
+
     return stonith_op;
 }
 
@@ -1323,7 +1365,7 @@ stage6(pe_working_set_t * data_set)
         if (need_stonith && node->details->unclean && pe_can_fence(data_set, node)) {
             pe_warn("Scheduling Node %s for STONITH", node->details->uname);
 
-            stonith_op = pe_fence_op(node, NULL, data_set);
+            stonith_op = pe_fence_op(node, NULL, FALSE, data_set);
 
             stonith_constraints(node, stonith_op, data_set);
 
diff --git a/pengine/allocate.h b/pengine/allocate.h
index 042d3aa..712de60 100644
--- a/pengine/allocate.h
+++ b/pengine/allocate.h
@@ -51,7 +51,7 @@ struct resource_alloc_functions_s {
     void (*append_meta) (resource_t * rsc, xmlNode * xml);
 };
 
-action_t *pe_fence_op(node_t * node, const char *op, pe_working_set_t * data_set);
+action_t *pe_fence_op(node_t * node, const char *op, bool optional, pe_working_set_t * data_set);
 
 extern GHashTable *rsc_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes,
                                      const char *attr, float factor, enum pe_weights flags);
@@ -161,6 +161,8 @@ extern void rsc_migrate_reload(resource_t * rsc, pe_working_set_t * data_set);
 extern void rsc_stonith_ordering(resource_t * rsc, action_t * stonith_op,
                                  pe_working_set_t * data_set);
 
+void trigger_unfencing(resource_t * rsc, node_t *node, const char *reason, action_t *dependancy, pe_working_set_t * data_set);
+
 extern enum pe_graph_flags native_update_actions(action_t * first, action_t * then, node_t * node,
                                                  enum pe_action_flags flags,
                                                  enum pe_action_flags filter,
diff --git a/pengine/graph.c b/pengine/graph.c
index 779f0e0..9c82d23 100644
--- a/pengine/graph.c
+++ b/pengine/graph.c
@@ -430,11 +430,49 @@ update_action(action_t * then)
                   uname : "", other->type);
 
         if (first == other->action) {
+            /*
+             * 'first' was not expanded (ie. from 'start' to 'running'), which could mean it:
+             * - has no associated resource,
+             * - was a primitive,
+             * - was pre-expanded (ie. 'running' instead of 'start')
+             *
+             * The third argument here to graph_update_action() is a node which is used under two conditions:
+             * - Interleaving, in which case first->node and
+             *   then->node are equal (and NULL)
+             * - If 'then' is a clone, to limit the scope of the
+             *   constraint to instances on the supplied node
+             *
+             */
+            int otype = other->type;
+            node_t *node = then->node;
+
+            if(is_set(otype, pe_order_implies_then_on_node)) {
+                /* Normally we want the _whole_ 'then' clone to
+                 * restart if 'first' is restarted, so then->node is
+                 * needed.
+                 *
+                 * However for unfencing, we want to limit this to
+                 * instances on the same node as 'first' (the
+                 * unfencing operation), so first->node is supplied.
+                 *
+                 * Swap the node, from then on we can can treat it
+                 * like any other 'pe_order_implies_then'
+                 */
+
+                clear_bit(otype, pe_order_implies_then_on_node);
+                set_bit(otype, pe_order_implies_then);
+                node = first->node;
+            }
             clear_bit(first_flags, pe_action_pseudo);
-            changed |= graph_update_action(first, then, then->node, first_flags, other->type);
+            changed |= graph_update_action(first, then, node, first_flags, otype);
 
+            /* 'first' was for a complex resource (clone, group, etc),
+             * create a new dependancy if necessary
+             */
         } else if (order_actions(first, then, other->type)) {
-            /* Start again to get the new actions_before list */
+            /* This was the first time 'first' and 'then' were associated,
+             * start again to get the new actions_before list
+             */
             changed |= (pe_graph_updated_then | pe_graph_disable);
         }
 
diff --git a/pengine/native.c b/pengine/native.c
index 4016a3c..d0eb950 100644
--- a/pengine/native.c
+++ b/pengine/native.c
@@ -1236,9 +1236,7 @@ native_internal_constraints(resource_t * rsc, pe_working_set_t * data_set)
 
     resource_t *top = uber_parent(rsc);
     int type = pe_order_optional | pe_order_implies_then | pe_order_restart;
-    gboolean is_stonith =
-        (rsc->xml && safe_str_eq(crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS), "stonith")) ?
-        TRUE : FALSE;
+    gboolean is_stonith = is_set(rsc->flags, pe_rsc_fence_device);
 
     custom_action_order(rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
                         rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, type, data_set);
@@ -1253,6 +1251,34 @@ native_internal_constraints(resource_t * rsc, pe_working_set_t * data_set)
                             pe_order_runnable_left, data_set);
     }
 
+    if (is_stonith == FALSE
+        && is_set(data_set->flags, pe_flag_enable_unfencing)
+        && is_set(rsc->flags, pe_rsc_needs_unfencing)) {
+        /* Check if the node needs to be unfenced first */
+        node_t *node = NULL;
+        GHashTableIter iter;
+
+        if(rsc != top) {
+            /* Only create these constraints once, rsc is almost certainly cloned */
+            clear_bit_recursive(top, pe_rsc_needs_unfencing);
+        }
+
+        g_hash_table_iter_init(&iter, rsc->allowed_nodes);
+        while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
+            action_t *unfence = pe_fence_op(node, "on", TRUE, data_set);
+
+            custom_action_order(top, generate_op_key(top->id, top == rsc?RSC_STOP:RSC_STOPPED, 0), NULL,
+                                NULL, strdup(unfence->uuid), unfence,
+                                pe_order_optional, data_set);
+
+            crm_debug("Stopping %s prior to unfencing %s", top->id, unfence->uuid);
+
+            custom_action_order(NULL, strdup(unfence->uuid), unfence,
+                                top, generate_op_key(top->id, RSC_START, 0), NULL,
+                                pe_order_implies_then_on_node, data_set);
+        }
+    }
+
     if (is_not_set(rsc->flags, pe_rsc_managed)) {
         pe_rsc_trace(rsc, "Skipping fencing constraints for unmanaged resource: %s", rsc->id);
         return;
@@ -2456,20 +2482,9 @@ native_create_probe(resource_t * rsc, node_t * node, action_t * complete,
     probe = custom_action(rsc, key, RSC_STATUS, node, FALSE, TRUE, data_set);
     update_action_flags(probe, pe_action_optional | pe_action_clear);
 
-    /* Check if the node needs to be unfenced first */
-    if (is_set(rsc->flags, pe_rsc_needs_unfencing)) {
-        action_t *unfence = pe_fence_op(node, "on", data_set);
-
-        crm_notice("Unfencing %s for %s", node->details->uname, rsc->id);
-        order_actions(unfence, probe, pe_order_implies_then);
-
-        /* The lack of ordering constraints on STONITH_UP would
-         * traditionally mean unfencing is initiated /before/ the
-         * devices are started.
-         *
-         * However this is a non-issue as stonithd is now smart
-         * enough to be able to use devices directly from the cib
-         */
+    if(is_set(rsc->flags, pe_rsc_fence_device)) {
+        crm_crit("TODO: %s: Trigger when probing the device or the resource that needs unfencing?", rsc->id);
+        trigger_unfencing(NULL, node, "node discovery", probe, data_set);
     }
 
     /*
diff --git a/pengine/regression.sh b/pengine/regression.sh
index aa50854..9cb6c18 100755
--- a/pengine/regression.sh
+++ b/pengine/regression.sh
@@ -317,6 +317,11 @@ do_test bug-cl-5170 "Prevent clone from starting with on-fail=block"
 do_test clone-fail-block-colocation "Move colocated group when failed clone has on-fail=block"
 
 echo ""
+do_test unfence-startup "Clean unfencing"
+do_test unfence-definition "Unfencing when the agent changes"
+do_test unfence-parameters "Unfencing when the agent parameters changes"
+
+echo ""
 do_test master-0 "Stopped -> Slave"
 do_test master-1 "Stopped -> Promote"
 do_test master-2 "Stopped -> Promote : notify"