pacemaker/pacemaker-ticket-state.diff
Tim Serong 1589a3e7c3 - Add provides to identify support level for tickets (bnc#752241)
- 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
2012-04-23 11:15:16 +00:00

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);