summaryrefslogtreecommitdiffstats
path: root/tools/crm_ticket.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/crm_ticket.c')
-rw-r--r--tools/crm_ticket.c614
1 files changed, 134 insertions, 480 deletions
diff --git a/tools/crm_ticket.c b/tools/crm_ticket.c
index d95b581..2faa74e 100644
--- a/tools/crm_ticket.c
+++ b/tools/crm_ticket.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2023 the Pacemaker project contributors
+ * Copyright 2012-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -22,7 +22,6 @@
#include <fcntl.h>
#include <libgen.h>
-#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/ipc.h>
#include <crm/common/cmdline_internal.h>
@@ -60,9 +59,17 @@ GList *attr_delete;
GHashTable *attr_set;
bool modified = false;
int cib_options = cib_sync_call;
+static pcmk__output_t *out = NULL;
#define INDENT " "
+static pcmk__supported_format_t formats[] = {
+ PCMK__SUPPORTED_FORMAT_NONE,
+ PCMK__SUPPORTED_FORMAT_TEXT,
+ PCMK__SUPPORTED_FORMAT_XML,
+ { NULL, NULL, NULL }
+};
+
static gboolean
attr_value_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **err) {
pcmk__str_update(&options.attr_value, optarg);
@@ -71,7 +78,7 @@ attr_value_cb(const gchar *option_name, const gchar *optarg, gpointer data, GErr
return TRUE;
}
- g_hash_table_insert(attr_set, strdup(options.attr_name), strdup(options.attr_value));
+ pcmk__insert_dup(attr_set, options.attr_name, options.attr_value);
pcmk__str_update(&options.attr_name, NULL);
pcmk__str_update(&options.attr_value, NULL);
@@ -116,16 +123,16 @@ get_attr_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError
static gboolean
grant_standby_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **err) {
if (pcmk__str_any_of(option_name, "--grant", "-g", NULL)) {
- g_hash_table_insert(attr_set, strdup("granted"), strdup("true"));
+ pcmk__insert_dup(attr_set, PCMK__XA_GRANTED, PCMK_VALUE_TRUE);
modified = true;
} else if (pcmk__str_any_of(option_name, "--revoke", "-r", NULL)) {
- g_hash_table_insert(attr_set, strdup("granted"), strdup("false"));
+ pcmk__insert_dup(attr_set, PCMK__XA_GRANTED, PCMK_VALUE_FALSE);
modified = true;
} else if (pcmk__str_any_of(option_name, "--standby", "-s", NULL)) {
- g_hash_table_insert(attr_set, strdup("standby"), strdup("true"));
+ pcmk__insert_dup(attr_set, PCMK_XA_STANDBY, PCMK_VALUE_TRUE);
modified = true;
} else if (pcmk__str_any_of(option_name, "--activate", "-a", NULL)) {
- g_hash_table_insert(attr_set, strdup("standby"), strdup("false"));
+ pcmk__insert_dup(attr_set, PCMK_XA_STANDBY, PCMK_VALUE_FALSE);
modified = true;
}
@@ -140,7 +147,7 @@ set_attr_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError
return TRUE;
}
- g_hash_table_insert(attr_set, strdup(options.attr_name), strdup(options.attr_value));
+ pcmk__insert_dup(attr_set, options.attr_name, options.attr_value);
pcmk__str_update(&options.attr_name, NULL);
pcmk__str_update(&options.attr_value, NULL);
@@ -167,7 +174,7 @@ static GOptionEntry query_entries[] = {
NULL },
{ "constraints", 'c', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
- "Display the rsc_ticket constraints that apply to ticket(s)",
+ "Display the " PCMK_XE_RSC_TICKET " constraints that apply to ticket(s)",
NULL },
{ NULL }
@@ -240,7 +247,7 @@ static GOptionEntry addl_entries[] = {
static GOptionEntry deprecated_entries[] = {
{ "set-name", 'n', 0, G_OPTION_ARG_STRING, &options.set_name,
- "(Advanced) ID of the instance_attributes object to change",
+ "(Advanced) ID of the " PCMK_XE_INSTANCE_ATTRIBUTES " object to change",
"ID" },
{ "nvpair", 'i', 0, G_OPTION_ARG_STRING, &options.attr_id,
@@ -254,420 +261,37 @@ static GOptionEntry deprecated_entries[] = {
{ NULL }
};
-static pcmk_ticket_t *
-find_ticket(gchar *ticket_id, pcmk_scheduler_t *scheduler)
-{
- return g_hash_table_lookup(scheduler->tickets, ticket_id);
-}
-
static void
-print_date(time_t time)
+ticket_grant_warning(gchar *ticket_id)
{
- int lpc = 0;
- char date_str[26];
-
- asctime_r(localtime(&time), date_str);
- for (; lpc < 26; lpc++) {
- if (date_str[lpc] == '\n') {
- date_str[lpc] = 0;
- }
- }
- fprintf(stdout, "'%s'", date_str);
+ out->err(out, "This command cannot help you verify whether '%s' has "
+ "been already granted elsewhere.\n"
+ "If you really want to grant '%s' to this site now, and "
+ "you know what you are doing,\n"
+ "please specify --force.",
+ ticket_id, ticket_id);
}
static void
-print_ticket(pcmk_ticket_t *ticket, bool raw, bool details)
-{
- if (raw) {
- fprintf(stdout, "%s\n", ticket->id);
- return;
- }
-
- fprintf(stdout, "%s\t%s %s",
- ticket->id, ticket->granted ? "granted" : "revoked",
- ticket->standby ? "[standby]" : " ");
-
- if (details && g_hash_table_size(ticket->state) > 0) {
- GHashTableIter iter;
- const char *name = NULL;
- const char *value = NULL;
- int lpc = 0;
-
- fprintf(stdout, " (");
-
- g_hash_table_iter_init(&iter, ticket->state);
- while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
- if (lpc > 0) {
- fprintf(stdout, ", ");
- }
- fprintf(stdout, "%s=", name);
- if (pcmk__str_any_of(name, "last-granted", "expires", NULL)) {
- long long time_ll;
-
- pcmk__scan_ll(value, &time_ll, 0);
- print_date((time_t) time_ll);
- } else {
- fprintf(stdout, "%s", value);
- }
- lpc++;
- }
-
- fprintf(stdout, ")\n");
-
- } else {
- if (ticket->last_granted > -1) {
- fprintf(stdout, " last-granted=");
- print_date(ticket->last_granted);
- }
- fprintf(stdout, "\n");
- }
-
- return;
-}
-
-static void
-print_ticket_list(pcmk_scheduler_t *scheduler, bool raw, bool details)
-{
- GHashTableIter iter;
- pcmk_ticket_t *ticket = NULL;
-
- g_hash_table_iter_init(&iter, scheduler->tickets);
-
- while (g_hash_table_iter_next(&iter, NULL, (void **)&ticket)) {
- print_ticket(ticket, raw, details);
- }
-}
-
-static int
-find_ticket_state(cib_t * the_cib, gchar *ticket_id, xmlNode ** ticket_state_xml)
-{
- int rc = pcmk_rc_ok;
- xmlNode *xml_search = NULL;
-
- GString *xpath = NULL;
-
- CRM_ASSERT(ticket_state_xml != NULL);
- *ticket_state_xml = NULL;
-
- xpath = g_string_sized_new(1024);
- g_string_append(xpath,
- "/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS
- "/" XML_CIB_TAG_TICKETS);
-
- if (ticket_id != NULL) {
- pcmk__g_strcat(xpath,
- "/" XML_CIB_TAG_TICKET_STATE
- "[@" XML_ATTR_ID "=\"", ticket_id, "\"]", NULL);
- }
-
- rc = the_cib->cmds->query(the_cib, (const char *) xpath->str, &xml_search,
- cib_sync_call | cib_scope_local | cib_xpath);
- rc = pcmk_legacy2rc(rc);
- g_string_free(xpath, TRUE);
-
- if (rc != pcmk_rc_ok) {
- return rc;
- }
-
- crm_log_xml_debug(xml_search, "Match");
- if (xml_search->children != NULL) {
- if (ticket_id) {
- fprintf(stdout, "Multiple ticket_states match ticket_id=%s\n", ticket_id);
- }
- *ticket_state_xml = xml_search;
- } else {
- *ticket_state_xml = xml_search;
- }
- return rc;
-}
-
-static int
-find_ticket_constraints(cib_t * the_cib, gchar *ticket_id, xmlNode ** ticket_cons_xml)
-{
- int rc = pcmk_rc_ok;
- xmlNode *xml_search = NULL;
-
- GString *xpath = NULL;
- const char *xpath_base = NULL;
-
- CRM_ASSERT(ticket_cons_xml != NULL);
- *ticket_cons_xml = NULL;
-
- xpath_base = pcmk_cib_xpath_for(XML_CIB_TAG_CONSTRAINTS);
- if (xpath_base == NULL) {
- crm_err(XML_CIB_TAG_CONSTRAINTS " CIB element not known (bug?)");
- return -ENOMSG;
- }
-
- xpath = g_string_sized_new(1024);
- pcmk__g_strcat(xpath, xpath_base, "/" XML_CONS_TAG_RSC_TICKET, NULL);
-
- if (ticket_id != NULL) {
- pcmk__g_strcat(xpath,
- "[@" XML_TICKET_ATTR_TICKET "=\"", ticket_id, "\"]",
- NULL);
- }
-
- rc = the_cib->cmds->query(the_cib, (const char *) xpath->str, &xml_search,
- cib_sync_call | cib_scope_local | cib_xpath);
- rc = pcmk_legacy2rc(rc);
- g_string_free(xpath, TRUE);
-
- if (rc != pcmk_rc_ok) {
- return rc;
- }
-
- crm_log_xml_debug(xml_search, "Match");
- *ticket_cons_xml = xml_search;
-
- return rc;
-}
-
-static int
-dump_ticket_xml(cib_t * the_cib, gchar *ticket_id)
-{
- int rc = pcmk_rc_ok;
- xmlNode *state_xml = NULL;
-
- rc = find_ticket_state(the_cib, ticket_id, &state_xml);
-
- if (state_xml == NULL) {
- return rc;
- }
-
- fprintf(stdout, "State XML:\n");
- if (state_xml) {
- char *state_xml_str = NULL;
-
- state_xml_str = dump_xml_formatted(state_xml);
- fprintf(stdout, "\n%s", state_xml_str);
- free_xml(state_xml);
- free(state_xml_str);
- }
-
- return rc;
-}
-
-static int
-dump_constraints(cib_t * the_cib, gchar *ticket_id)
-{
- int rc = pcmk_rc_ok;
- xmlNode *cons_xml = NULL;
- char *cons_xml_str = NULL;
-
- rc = find_ticket_constraints(the_cib, ticket_id, &cons_xml);
-
- if (cons_xml == NULL) {
- return rc;
- }
-
- cons_xml_str = dump_xml_formatted(cons_xml);
- fprintf(stdout, "Constraints XML:\n\n%s", cons_xml_str);
- free_xml(cons_xml);
- free(cons_xml_str);
-
- return rc;
-}
-
-static int
-get_ticket_state_attr(gchar *ticket_id, const char *attr_name, const char **attr_value,
- pcmk_scheduler_t *scheduler)
-{
- pcmk_ticket_t *ticket = NULL;
-
- CRM_ASSERT(attr_value != NULL);
- *attr_value = NULL;
-
- ticket = g_hash_table_lookup(scheduler->tickets, ticket_id);
- if (ticket == NULL) {
- return ENXIO;
- }
-
- *attr_value = g_hash_table_lookup(ticket->state, attr_name);
- if (*attr_value == NULL) {
- return ENXIO;
- }
-
- return pcmk_rc_ok;
-}
-
-static void
-ticket_warning(gchar *ticket_id, const char *action)
-{
- GString *warning = g_string_sized_new(1024);
- const char *word = NULL;
-
- CRM_ASSERT(action != NULL);
-
- if (strcmp(action, "grant") == 0) {
- pcmk__g_strcat(warning,
- "This command cannot help you verify whether '",
- ticket_id,
- "' has been already granted elsewhere.\n", NULL);
- word = "to";
-
- } else {
- pcmk__g_strcat(warning,
- "Revoking '", ticket_id, "' can trigger the specified "
- "'loss-policy'(s) relating to '", ticket_id, "'.\n\n"
- "You can check that with:\n"
- "crm_ticket --ticket ", ticket_id, " --constraints\n\n"
- "Otherwise before revoking '", ticket_id, "', "
- "you may want to make '", ticket_id, "' "
- "standby with:\n"
- "crm_ticket --ticket ", ticket_id, " --standby\n\n",
- NULL);
- word = "from";
- }
-
- pcmk__g_strcat(warning,
- "If you really want to ", action, " '", ticket_id, "' ",
- word, " this site now, and you know what you are doing,\n"
- "please specify --force.", NULL);
-
- fprintf(stdout, "%s\n", (const char *) warning->str);
-
- g_string_free(warning, TRUE);
-}
-
-static bool
-allow_modification(gchar *ticket_id)
+ticket_revoke_warning(gchar *ticket_id)
{
- const char *value = NULL;
- GList *list_iter = NULL;
-
- if (options.force) {
- return true;
- }
-
- if (g_hash_table_lookup_extended(attr_set, "granted", NULL, (gpointer *) & value)) {
- if (crm_is_true(value)) {
- ticket_warning(ticket_id, "grant");
- return false;
-
- } else {
- ticket_warning(ticket_id, "revoke");
- return false;
- }
- }
-
- for(list_iter = attr_delete; list_iter; list_iter = list_iter->next) {
- const char *key = (const char *)list_iter->data;
-
- if (pcmk__str_eq(key, "granted", pcmk__str_casei)) {
- ticket_warning(ticket_id, "revoke");
- return false;
- }
- }
-
- return true;
-}
-
-static int
-modify_ticket_state(gchar *ticket_id, cib_t *cib, pcmk_scheduler_t *scheduler)
-{
- int rc = pcmk_rc_ok;
- xmlNode *xml_top = NULL;
- xmlNode *ticket_state_xml = NULL;
- bool found = false;
-
- GList *list_iter = NULL;
- GHashTableIter hash_iter;
-
- char *key = NULL;
- char *value = NULL;
-
- pcmk_ticket_t *ticket = NULL;
-
- rc = find_ticket_state(cib, ticket_id, &ticket_state_xml);
- if (rc == pcmk_rc_ok) {
- crm_debug("Found a match state for ticket: id=%s", ticket_id);
- xml_top = ticket_state_xml;
- found = true;
-
- } else if (rc != ENXIO) {
- return rc;
-
- } else if (g_hash_table_size(attr_set) == 0){
- return pcmk_rc_ok;
-
- } else {
- xmlNode *xml_obj = NULL;
-
- xml_top = create_xml_node(NULL, XML_CIB_TAG_STATUS);
- xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
- ticket_state_xml = create_xml_node(xml_obj, XML_CIB_TAG_TICKET_STATE);
- crm_xml_add(ticket_state_xml, XML_ATTR_ID, ticket_id);
- }
-
- for(list_iter = attr_delete; list_iter; list_iter = list_iter->next) {
- const char *key = (const char *)list_iter->data;
- xml_remove_prop(ticket_state_xml, key);
- }
-
- ticket = find_ticket(ticket_id, scheduler);
-
- g_hash_table_iter_init(&hash_iter, attr_set);
- while (g_hash_table_iter_next(&hash_iter, (gpointer *) & key, (gpointer *) & value)) {
- crm_xml_add(ticket_state_xml, key, value);
-
- if (pcmk__str_eq(key, "granted", pcmk__str_casei)
- && (ticket == NULL || ticket->granted == FALSE)
- && crm_is_true(value)) {
-
- char *now = pcmk__ttoa(time(NULL));
-
- crm_xml_add(ticket_state_xml, "last-granted", now);
- free(now);
- }
- }
-
- if (found && (attr_delete != NULL)) {
- crm_log_xml_debug(xml_top, "Replace");
- rc = cib->cmds->replace(cib, XML_CIB_TAG_STATUS, ticket_state_xml, cib_options);
- rc = pcmk_legacy2rc(rc);
-
- } else {
- crm_log_xml_debug(xml_top, "Update");
- rc = cib->cmds->modify(cib, XML_CIB_TAG_STATUS, xml_top, cib_options);
- rc = pcmk_legacy2rc(rc);
- }
-
- free_xml(xml_top);
- return rc;
-}
-
-static int
-delete_ticket_state(gchar *ticket_id, cib_t * cib)
-{
- xmlNode *ticket_state_xml = NULL;
-
- int rc = pcmk_rc_ok;
-
- rc = find_ticket_state(cib, ticket_id, &ticket_state_xml);
-
- if (rc == ENXIO) {
- return pcmk_rc_ok;
-
- } else if (rc != pcmk_rc_ok) {
- return rc;
- }
-
- crm_log_xml_debug(ticket_state_xml, "Delete");
-
- rc = cib->cmds->remove(cib, XML_CIB_TAG_STATUS, ticket_state_xml, cib_options);
- rc = pcmk_legacy2rc(rc);
-
- if (rc == pcmk_rc_ok) {
- fprintf(stdout, "Cleaned up %s\n", ticket_id);
- }
-
- free_xml(ticket_state_xml);
- return rc;
+ out->err(out, "Revoking '%s' can trigger the specified '" PCMK_XA_LOSS_POLICY
+ "'(s) relating to '%s'.\n\n"
+ "You can check that with:\n"
+ "crm_ticket --ticket %s --constraints\n\n"
+ "Otherwise before revoking '%s', you may want to make '%s'"
+ "standby with:\n"
+ "crm_ticket --ticket %s --standby\n\n"
+ "If you really want to revoke '%s' from this site now, and "
+ "you know what you are doing,\n"
+ "please specify --force.",
+ ticket_id, ticket_id, ticket_id, ticket_id, ticket_id,
+ ticket_id, ticket_id);
}
static GOptionContext *
-build_arg_context(pcmk__common_args_t *args) {
+build_arg_context(pcmk__common_args_t *args, GOptionGroup **group)
+{
GOptionContext *context = NULL;
const char *description = "Examples:\n\n"
@@ -677,7 +301,7 @@ build_arg_context(pcmk__common_args_t *args) {
"\tcrm_ticket --details\n\n"
"Display the XML of 'ticketA':\n\n"
"\tcrm_ticket --ticket ticketA --query-xml\n\n"
- "Display the rsc_ticket constraints that apply to 'ticketA':\n\n"
+ "Display the " PCMK_XE_RSC_TICKET " constraints that apply to 'ticketA':\n\n"
"\tcrm_ticket --ticket ticketA --constraints\n\n"
"Grant 'ticketA' to this cluster site:\n\n"
"\tcrm_ticket --ticket ticketA --grant\n\n"
@@ -699,7 +323,7 @@ build_arg_context(pcmk__common_args_t *args) {
"causing the cluster site to 'forget' the existing ticket state:\n\n"
"\tcrm_ticket --ticket ticketA --cleanup\n\n";
- context = pcmk__build_arg_context(args, NULL, NULL, NULL);
+ context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
g_option_context_set_description(context, description);
pcmk__add_arg_group(context, "queries", "Queries:",
@@ -726,6 +350,7 @@ main(int argc, char **argv)
crm_exit_t exit_code = CRM_EX_OK;
int rc = pcmk_rc_ok;
+ GOptionGroup *output_group = NULL;
pcmk__common_args_t *args = NULL;
GOptionContext *context = NULL;
gchar **processed_args = NULL;
@@ -734,9 +359,10 @@ main(int argc, char **argv)
attr_delete = NULL;
args = pcmk__new_common_args(SUMMARY);
- context = build_arg_context(args);
+ context = build_arg_context(args, &output_group);
processed_args = pcmk__cmdline_preproc(argv, "dintvxCDGS");
+ pcmk__register_formats(output_group, formats);
if (!g_option_context_parse_strv(context, &processed_args, &error)) {
exit_code = CRM_EX_USAGE;
goto done;
@@ -744,11 +370,21 @@ main(int argc, char **argv)
pcmk__cli_init_logging("crm_ticket", args->verbosity);
+ rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
+ if (rc != pcmk_rc_ok) {
+ exit_code = pcmk_rc2exitc(rc);
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "Error creating output format %s: %s", args->output_ty,
+ pcmk_rc_str(rc));
+ goto done;
+ }
+
+ pe__register_messages(out);
+ pcmk__register_lib_messages(out);
+
if (args->version) {
- g_strfreev(processed_args);
- pcmk__free_arg_context(context);
- /* FIXME: When crm_ticket is converted to use formatted output, this can go. */
- pcmk__cli_help('v');
+ out->version(out, false);
+ goto done;
}
scheduler = pe_new_working_set();
@@ -759,7 +395,7 @@ main(int argc, char **argv)
"Could not allocate scheduler data: %s", pcmk_rc_str(rc));
goto done;
}
- pe__set_working_set_flags(scheduler,
+ pcmk__set_scheduler_flags(scheduler,
pcmk_sched_no_counts|pcmk_sched_no_compat);
cib_conn = cib_new();
@@ -780,7 +416,7 @@ main(int argc, char **argv)
}
if (options.xml_file != NULL) {
- cib_xml_copy = filename2xml(options.xml_file);
+ cib_xml_copy = pcmk__xml_read(options.xml_file);
} else {
rc = cib_conn->cmds->query(cib_conn, NULL, &cib_xml_copy, cib_scope_local | cib_sync_call);
@@ -794,8 +430,9 @@ main(int argc, char **argv)
}
}
- if (!cli_config_update(&cib_xml_copy, NULL, FALSE)) {
- exit_code = CRM_EX_CONFIG;
+ rc = pcmk_update_configured_schema(&cib_xml_copy, false);
+ if (rc != pcmk_rc_ok) {
+ exit_code = pcmk_rc2exitc(rc);
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
"Could not update local CIB to latest schema version");
goto done;
@@ -806,8 +443,9 @@ main(int argc, char **argv)
cluster_status(scheduler);
- /* For recording the tickets that are referenced in rsc_ticket constraints
- * but have never been granted yet. */
+ /* For recording the tickets that are referenced in PCMK_XE_RSC_TICKET
+ * constraints but have never been granted yet.
+ */
pcmk__unpack_constraints(scheduler);
if (options.ticket_cmd == 'l' || options.ticket_cmd == 'L' || options.ticket_cmd == 'w') {
@@ -820,32 +458,30 @@ main(int argc, char **argv)
raw = true;
}
- if (options.ticket_id) {
- pcmk_ticket_t *ticket = find_ticket(options.ticket_id, scheduler);
-
- if (ticket == NULL) {
- exit_code = CRM_EX_NOSUCH;
- g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
- "No such ticket '%s'", options.ticket_id);
- goto done;
- }
- print_ticket(ticket, raw, details);
+ rc = pcmk__ticket_info(out, scheduler, options.ticket_id, details, raw);
+ exit_code = pcmk_rc2exitc(rc);
- } else {
- print_ticket_list(scheduler, raw, details);
+ if (rc == ENXIO) {
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "No such ticket '%s'", options.ticket_id);
+ } else if (rc != pcmk_rc_ok) {
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "Could not get ticket info: %s", pcmk_rc_str(rc));
}
} else if (options.ticket_cmd == 'q') {
- rc = dump_ticket_xml(cib_conn, options.ticket_id);
- exit_code = pcmk_rc2exitc(rc);
+ rc = pcmk__ticket_state(out, cib_conn, options.ticket_id);
- if (rc != pcmk_rc_ok) {
+ if (rc != pcmk_rc_ok && rc != pcmk_rc_duplicate_id) {
+ exit_code = pcmk_rc2exitc(rc);
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
"Could not query ticket XML: %s", pcmk_rc_str(rc));
+ } else {
+ exit_code = CRM_EX_OK;
}
} else if (options.ticket_cmd == 'c') {
- rc = dump_constraints(cib_conn, options.ticket_id);
+ rc = pcmk__ticket_constraints(out, cib_conn, options.ticket_id);
exit_code = pcmk_rc2exitc(rc);
if (rc != pcmk_rc_ok) {
@@ -854,8 +490,6 @@ main(int argc, char **argv)
}
} else if (options.ticket_cmd == 'G') {
- const char *value = NULL;
-
if (options.ticket_id == NULL) {
exit_code = CRM_EX_NOSUCH;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
@@ -863,14 +497,8 @@ main(int argc, char **argv)
goto done;
}
- rc = get_ticket_state_attr(options.ticket_id, options.get_attr_name,
- &value, scheduler);
- if (rc == pcmk_rc_ok) {
- fprintf(stdout, "%s\n", value);
- } else if (rc == ENXIO && options.attr_default) {
- fprintf(stdout, "%s\n", options.attr_default);
- rc = pcmk_rc_ok;
- }
+ rc = pcmk__ticket_get_attr(out, scheduler, options.ticket_id,
+ options.get_attr_name, options.attr_default);
exit_code = pcmk_rc2exitc(rc);
} else if (options.ticket_cmd == 'C') {
@@ -881,30 +509,28 @@ main(int argc, char **argv)
goto done;
}
- if (options.force == FALSE) {
- pcmk_ticket_t *ticket = NULL;
+ rc = pcmk__ticket_delete(out, cib_conn, scheduler, options.ticket_id,
+ options.force);
+ exit_code = pcmk_rc2exitc(rc);
- ticket = find_ticket(options.ticket_id, scheduler);
- if (ticket == NULL) {
- exit_code = CRM_EX_NOSUCH;
+ switch (rc) {
+ case ENXIO:
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
"No such ticket '%s'", options.ticket_id);
- goto done;
- }
+ break;
- if (ticket->granted) {
- ticket_warning(options.ticket_id, "revoke");
- exit_code = CRM_EX_INSUFFICIENT_PRIV;
- goto done;
- }
- }
+ case EACCES:
+ ticket_revoke_warning(options.ticket_id);
+ break;
- rc = delete_ticket_state(options.ticket_id, cib_conn);
- exit_code = pcmk_rc2exitc(rc);
+ case pcmk_rc_ok:
+ case pcmk_rc_duplicate_id:
+ break;
- if (rc != pcmk_rc_ok) {
- g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
- "Could not clean up ticket: %s", pcmk_rc_str(rc));
+ default:
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "Could not clean up ticket: %s", pcmk_rc_str(rc));
+ break;
}
} else if (modified) {
@@ -931,17 +557,39 @@ main(int argc, char **argv)
goto done;
}
- if (!allow_modification(options.ticket_id)) {
- exit_code = CRM_EX_INSUFFICIENT_PRIV;
- g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
- "Ticket modification not allowed");
- goto done;
+ if (attr_delete != NULL) {
+ rc = pcmk__ticket_remove_attr(out, cib_conn, scheduler, options.ticket_id,
+ attr_delete, options.force);
+
+ if (rc == EACCES) {
+ ticket_revoke_warning(options.ticket_id);
+ exit_code = pcmk_rc2exitc(rc);
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "Ticket modification not allowed without --force");
+ }
+ } else {
+ rc = pcmk__ticket_set_attr(out, cib_conn, scheduler, options.ticket_id,
+ attr_set, options.force);
+
+ if (rc == EACCES) {
+ const char *value = NULL;
+
+ value = g_hash_table_lookup(attr_set, PCMK__XA_GRANTED);
+ if (crm_is_true(value)) {
+ ticket_grant_warning(options.ticket_id);
+ } else {
+ ticket_revoke_warning(options.ticket_id);
+ }
+
+ exit_code = pcmk_rc2exitc(rc);
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "Ticket modification not allowed without --force");
+ }
}
- rc = modify_ticket_state(options.ticket_id, cib_conn, scheduler);
exit_code = pcmk_rc2exitc(rc);
- if (rc != pcmk_rc_ok) {
+ if (rc != pcmk_rc_ok && error == NULL) {
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
"Could not modify ticket: %s", pcmk_rc_str(rc));
}
@@ -1005,7 +653,13 @@ main(int argc, char **argv)
g_free(options.ticket_id);
g_free(options.xml_file);
- pcmk__output_and_clear_error(&error, NULL);
+ pcmk__output_and_clear_error(&error, out);
+
+ if (out != NULL) {
+ out->finish(out, exit_code, true, NULL);
+ pcmk__output_free(out);
+ }
+ pcmk__unregister_formats();
crm_exit(exit_code);
}