1589a3e7c3
- Resolve coverity RESOURCE_LEAK, REVERSE_INULL and UNREACHABLE defects - Tools: crm_simulate - Support to grant/revoke/standby/activate tickets from the new ticket state section (bnc#752241) - Tools: Add crm_ticket to be profiled by valgrind - Tools: crm_ticket - Display the tickets that are referenced in rsc_ticket constraints but have never been granted yet (bnc#752241) - Tools: crm_mon - Support to display tickets (bnc#752242) - PE: Move the ticket state section to "/cib/status/tickets/ticket_state" (bnc#752241) - PE: Support to make tickets standby for relinquishing tickets gracefully (bnc#752241) - Tools: Implement a new crm_ticket (bnc#752241) - Tools: Update CLI regression tests for the new crm_ticket - Tools: Add CLI regression tests for ticket standby state - PE: Update regression tests for the new ticket state section - PE: Support to make tickets standby for relinquishing tickets gracefully (regression tests) - Tools: crm_ticket - Granting/revoking tickets need user to confirm unless "--force" option is used (bnc#752269) - Tools: Implement the support of granting/revoking tickets for crm_simulate (bnc#752241) OBS-URL: https://build.opensuse.org/package/show/network:ha-clustering:Factory/pacemaker?expand=0&rev=34
365 lines
12 KiB
Diff
365 lines
12 KiB
Diff
commit f3dea7908cfcc61e83b765b8bda68f6ce1ba31d3
|
|
Author: Gao,Yan <ygao@suse.com>
|
|
Date: Fri Mar 23 11:40:56 2012 +0800
|
|
|
|
High: PE: Move the ticket state section to "/cib/status/tickets/ticket_state"
|
|
|
|
Move the ticket state section:
|
|
--- "/cib/status/tickets/instance_attributes"
|
|
+++ "/cib/status/tickets/ticket_state"
|
|
|
|
Pengine still recognizes the deprecated section. If there's any
|
|
attribute appears in the new tickets_state section, it'll take over
|
|
precedence over the one in the deprecated section. Actually, even
|
|
more, once crm_ticket is invoked to set an attribute, it'll clear the
|
|
one in the deprecated section.
|
|
|
|
Index: pacemaker/include/crm/msg_xml.h
|
|
===================================================================
|
|
--- pacemaker.orig/include/crm/msg_xml.h
|
|
+++ pacemaker/include/crm/msg_xml.h
|
|
@@ -297,7 +297,8 @@
|
|
# define XML_ACL_ATTR_XPATH "xpath"
|
|
# define XML_ACL_ATTR_ATTRIBUTE "attribute"
|
|
|
|
-# define XML_CIB_TAG_TICKETS "tickets"
|
|
+# define XML_CIB_TAG_TICKETS "tickets"
|
|
+# define XML_CIB_TAG_TICKET_STATE "ticket_state"
|
|
|
|
# include <crm/common/xml.h>
|
|
|
|
Index: pacemaker/include/crm/pengine/status.h
|
|
===================================================================
|
|
--- pacemaker.orig/include/crm/pengine/status.h
|
|
+++ pacemaker/include/crm/pengine/status.h
|
|
@@ -294,6 +294,8 @@ struct ticket_s {
|
|
char *id;
|
|
gboolean granted;
|
|
time_t last_granted;
|
|
+ gboolean standby;
|
|
+ GHashTable *state;
|
|
};
|
|
|
|
gboolean cluster_status(pe_working_set_t * data_set);
|
|
Index: pacemaker/lib/pengine/unpack.c
|
|
===================================================================
|
|
--- pacemaker.orig/lib/pengine/unpack.c
|
|
+++ pacemaker/lib/pengine/unpack.c
|
|
@@ -412,10 +412,95 @@ unpack_resources(xmlNode * xml_resources
|
|
return TRUE;
|
|
}
|
|
|
|
+/* The ticket state section:
|
|
+ * "/cib/status/tickets/ticket_state" */
|
|
+static gboolean
|
|
+unpack_ticket_state(xmlNode * xml_ticket, pe_working_set_t * data_set)
|
|
+{
|
|
+ const char *ticket_id = NULL;
|
|
+ const char *granted = NULL;
|
|
+ const char *last_granted = NULL;
|
|
+ const char *standby = NULL;
|
|
+ xmlAttrPtr xIter = NULL;
|
|
+
|
|
+ ticket_t *ticket = NULL;
|
|
+
|
|
+ ticket_id = ID(xml_ticket);
|
|
+ if (ticket_id == NULL || strlen(ticket_id) == 0) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ crm_trace("Processing ticket state for %s", ticket_id);
|
|
+
|
|
+ ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
|
|
+ if (ticket == NULL) {
|
|
+ ticket = ticket_new(ticket_id, data_set);
|
|
+ if (ticket == NULL) {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (xIter = xml_ticket->properties; xIter; xIter = xIter->next) {
|
|
+ const char *prop_name = (const char *)xIter->name;
|
|
+ const char *prop_value = crm_element_value(xml_ticket, prop_name);
|
|
+
|
|
+ if(crm_str_eq(prop_name, XML_ATTR_ID, TRUE)) {
|
|
+ continue;
|
|
+ }
|
|
+ g_hash_table_replace(ticket->state, crm_strdup(prop_name), crm_strdup(prop_value));
|
|
+ }
|
|
+
|
|
+ granted = g_hash_table_lookup(ticket->state, "granted");
|
|
+ if (granted && crm_is_true(granted)) {
|
|
+ ticket->granted = TRUE;
|
|
+ crm_info("We have ticket '%s'", ticket->id);
|
|
+ } else {
|
|
+ ticket->granted = FALSE;
|
|
+ crm_info("We do not have ticket '%s'", ticket->id);
|
|
+ }
|
|
+
|
|
+ last_granted = g_hash_table_lookup(ticket->state, "last-granted");
|
|
+ if (last_granted) {
|
|
+ ticket->last_granted = crm_parse_int(last_granted, 0);
|
|
+ }
|
|
+
|
|
+ standby = g_hash_table_lookup(ticket->state, "standby");
|
|
+ if (standby && crm_is_true(standby)) {
|
|
+ ticket->standby = TRUE;
|
|
+ if (ticket->granted) {
|
|
+ crm_info("Granted ticket '%s' is in standby-mode", ticket->id);
|
|
+ }
|
|
+ } else {
|
|
+ ticket->standby = FALSE;
|
|
+ }
|
|
+
|
|
+ crm_trace("Done with ticket state for %s", ticket_id);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+unpack_tickets_state(xmlNode * xml_tickets, pe_working_set_t * data_set)
|
|
+{
|
|
+ xmlNode *xml_obj = NULL;
|
|
+
|
|
+ for (xml_obj = __xml_first_child(xml_tickets); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) {
|
|
+ if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_TICKET_STATE, TRUE) == FALSE) {
|
|
+ continue;
|
|
+ }
|
|
+ unpack_ticket_state(xml_obj, data_set);
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+/* Compatibility with the deprecated ticket state section:
|
|
+ * "/cib/status/tickets/instance_attributes" */
|
|
static void
|
|
-get_ticket_state(gpointer key, gpointer value, gpointer user_data)
|
|
+get_ticket_state_legacy(gpointer key, gpointer value, gpointer user_data)
|
|
{
|
|
- const char *attr_key = key;
|
|
+ const char *long_key = key;
|
|
+ char *state_key = NULL;
|
|
|
|
const char *granted_prefix = "granted-ticket-";
|
|
const char *last_granted_prefix = "last-granted-";
|
|
@@ -425,9 +510,10 @@ get_ticket_state(gpointer key, gpointer
|
|
const char *ticket_id = NULL;
|
|
const char *is_granted = NULL;
|
|
const char *last_granted = NULL;
|
|
+ const char *sep = NULL;
|
|
|
|
ticket_t *ticket = NULL;
|
|
- GHashTable *tickets = user_data;
|
|
+ pe_working_set_t *data_set = user_data;
|
|
|
|
if (granted_prefix_strlen == 0) {
|
|
granted_prefix_strlen = strlen(granted_prefix);
|
|
@@ -437,37 +523,41 @@ get_ticket_state(gpointer key, gpointer
|
|
last_granted_prefix_strlen = strlen(last_granted_prefix);
|
|
}
|
|
|
|
- if (strstr(attr_key, granted_prefix) == attr_key) {
|
|
- ticket_id = attr_key + granted_prefix_strlen;
|
|
+ if (strstr(long_key, granted_prefix) == long_key) {
|
|
+ ticket_id = long_key + granted_prefix_strlen;
|
|
if (strlen(ticket_id)) {
|
|
+ state_key = crm_strdup("granted");
|
|
is_granted = value;
|
|
}
|
|
- } else if (strstr(attr_key, last_granted_prefix) == attr_key) {
|
|
- ticket_id = attr_key + last_granted_prefix_strlen;
|
|
+ } else if (strstr(long_key, last_granted_prefix) == long_key) {
|
|
+ ticket_id = long_key + last_granted_prefix_strlen;
|
|
if (strlen(ticket_id)) {
|
|
+ state_key = crm_strdup("last-granted");
|
|
last_granted = value;
|
|
}
|
|
+ } else if ((sep = strrchr(long_key, '-'))) {
|
|
+ ticket_id = sep + 1;
|
|
+ state_key = strndup(long_key, strlen(long_key) - strlen(sep));
|
|
}
|
|
|
|
if (ticket_id == NULL || strlen(ticket_id) == 0) {
|
|
return;
|
|
}
|
|
|
|
- ticket = g_hash_table_lookup(tickets, ticket_id);
|
|
+ if (state_key == NULL || strlen(state_key) == 0) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
|
|
if (ticket == NULL) {
|
|
- crm_malloc0(ticket, sizeof(ticket_t));
|
|
+ ticket = ticket_new(ticket_id, data_set);
|
|
if (ticket == NULL) {
|
|
- crm_config_err("Cannot allocate ticket '%s'", ticket_id);
|
|
return;
|
|
}
|
|
-
|
|
- ticket->id = crm_strdup(ticket_id);
|
|
- ticket->granted = FALSE;
|
|
- ticket->last_granted = -1;
|
|
-
|
|
- g_hash_table_insert(tickets, crm_strdup(ticket->id), ticket);
|
|
}
|
|
|
|
+ g_hash_table_replace(ticket->state, state_key, crm_strdup(value));
|
|
+
|
|
if (is_granted) {
|
|
if (crm_is_true(is_granted)) {
|
|
ticket->granted = TRUE;
|
|
@@ -482,15 +572,6 @@ get_ticket_state(gpointer key, gpointer
|
|
}
|
|
}
|
|
|
|
-static void
|
|
-destroy_ticket(gpointer data)
|
|
-{
|
|
- ticket_t *ticket = data;
|
|
-
|
|
- crm_free(ticket->id);
|
|
- crm_free(ticket);
|
|
-}
|
|
-
|
|
/* remove nodes that are down, stopping */
|
|
/* create +ve rsc_to_node constraints between resources and the nodes they are running on */
|
|
/* anything else? */
|
|
@@ -508,24 +589,32 @@ unpack_status(xmlNode * status, pe_worki
|
|
|
|
crm_debug_3("Beginning unpack");
|
|
|
|
- data_set->tickets =
|
|
- g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket);
|
|
+ if (data_set->tickets == NULL) {
|
|
+ data_set->tickets =
|
|
+ g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket);
|
|
+ }
|
|
|
|
for (state = __xml_first_child(status); state != NULL; state = __xml_next(state)) {
|
|
if (crm_str_eq((const char *)state->name, XML_CIB_TAG_TICKETS, TRUE)) {
|
|
- xmlNode *tickets = state;
|
|
- GHashTable *attrs_hash =
|
|
- g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str,
|
|
+ xmlNode *xml_tickets = state;
|
|
+ GHashTable *state_hash = NULL;
|
|
+
|
|
+ /* Compatibility with the deprecated ticket state section:
|
|
+ * Unpack the attributes in the deprecated "/cib/status/tickets/instance_attributes" if it exists. */
|
|
+ state_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str,
|
|
g_hash_destroy_str);
|
|
|
|
- unpack_instance_attributes(data_set->input, tickets, XML_TAG_ATTR_SETS, NULL,
|
|
- attrs_hash, NULL, TRUE, data_set->now);
|
|
+ unpack_instance_attributes(data_set->input, xml_tickets, XML_TAG_ATTR_SETS, NULL,
|
|
+ state_hash, NULL, TRUE, data_set->now);
|
|
|
|
- g_hash_table_foreach(attrs_hash, get_ticket_state, data_set->tickets);
|
|
+ g_hash_table_foreach(state_hash, get_ticket_state_legacy, data_set);
|
|
|
|
- if (attrs_hash) {
|
|
- g_hash_table_destroy(attrs_hash);
|
|
+ if (state_hash) {
|
|
+ g_hash_table_destroy(state_hash);
|
|
}
|
|
+
|
|
+ /* Unpack the new "/cib/status/tickets/ticket_state"s */
|
|
+ unpack_tickets_state(xml_tickets, data_set);
|
|
}
|
|
|
|
if (crm_str_eq((const char *)state->name, XML_CIB_TAG_STATE, TRUE)) {
|
|
Index: pacemaker/lib/pengine/utils.c
|
|
===================================================================
|
|
--- pacemaker.orig/lib/pengine/utils.c
|
|
+++ pacemaker/lib/pengine/utils.c
|
|
@@ -1373,3 +1373,53 @@ get_target_role(resource_t * rsc, enum r
|
|
*role = local_role;
|
|
return TRUE;
|
|
}
|
|
+
|
|
+void
|
|
+destroy_ticket(gpointer data)
|
|
+{
|
|
+ ticket_t *ticket = data;
|
|
+
|
|
+ if (ticket->state) {
|
|
+ g_hash_table_destroy(ticket->state);
|
|
+ }
|
|
+ crm_free(ticket->id);
|
|
+ crm_free(ticket);
|
|
+}
|
|
+
|
|
+ticket_t *
|
|
+ticket_new(const char *ticket_id, pe_working_set_t * data_set)
|
|
+{
|
|
+ ticket_t *ticket = NULL;
|
|
+
|
|
+ if (ticket_id == NULL || strlen(ticket_id) == 0) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (data_set->tickets == NULL) {
|
|
+ data_set->tickets =
|
|
+ g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket);
|
|
+ }
|
|
+
|
|
+ ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
|
|
+ if (ticket == NULL) {
|
|
+
|
|
+ crm_malloc0(ticket, sizeof(ticket_t));
|
|
+ if (ticket == NULL) {
|
|
+ crm_err("Cannot allocate ticket '%s'", ticket_id);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ crm_trace("Creaing ticket entry for %s", ticket_id);
|
|
+
|
|
+ ticket->id = crm_strdup(ticket_id);
|
|
+ ticket->granted = FALSE;
|
|
+ ticket->last_granted = -1;
|
|
+ ticket->standby = FALSE;
|
|
+ ticket->state = g_hash_table_new_full(crm_str_hash, g_str_equal,
|
|
+ g_hash_destroy_str, g_hash_destroy_str);
|
|
+
|
|
+ g_hash_table_insert(data_set->tickets, crm_strdup(ticket->id), ticket);
|
|
+ }
|
|
+
|
|
+ return ticket;
|
|
+}
|
|
Index: pacemaker/lib/pengine/utils.h
|
|
===================================================================
|
|
--- pacemaker.orig/lib/pengine/utils.h
|
|
+++ pacemaker/lib/pengine/utils.h
|
|
@@ -162,4 +162,7 @@ extern gboolean get_target_role(resource
|
|
extern resource_t *find_clone_instance(resource_t * rsc, const char *sub_id,
|
|
pe_working_set_t * data_set);
|
|
|
|
+extern void destroy_ticket(gpointer data);
|
|
+extern ticket_t *ticket_new(const char * ticket_id, pe_working_set_t * data_set);
|
|
+
|
|
#endif
|
|
Index: pacemaker/pengine/constraints.c
|
|
===================================================================
|
|
--- pacemaker.orig/pengine/constraints.c
|
|
+++ pacemaker/pengine/constraints.c
|
|
@@ -2000,17 +2000,10 @@ unpack_rsc_ticket(xmlNode * xml_obj, pe_
|
|
}
|
|
|
|
if (ticket == NULL) {
|
|
- crm_malloc0(ticket, sizeof(ticket_t));
|
|
+ ticket = ticket_new(ticket_str, data_set);
|
|
if (ticket == NULL) {
|
|
- crm_config_err("Cannot allocate ticket '%s'", ticket_str);
|
|
return FALSE;
|
|
}
|
|
-
|
|
- ticket->id = crm_strdup(ticket_str);
|
|
- ticket->granted = FALSE;
|
|
- ticket->last_granted = -1;
|
|
-
|
|
- g_hash_table_insert(data_set->tickets, crm_strdup(ticket->id), ticket);
|
|
}
|
|
|
|
unpack_rsc_ticket_template(xml_obj, &expanded_xml, data_set);
|