diff --git a/lib/common/output_html.c b/lib/common/output_html.c
index a106d80fe8..31fc515e7f 100644
--- a/lib/common/output_html.c
+++ b/lib/common/output_html.c
@@ -1,342 +1,339 @@
/*
* Copyright 2019 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include
#include
#include
#include
#include
#include
#include
#include
static const char *stylesheet_default =
".bold { font-weight: bold }\n"
".warning { color: red, font-weight: bold }";
static gboolean cgi_output = FALSE;
static int meta_refresh = 0;
static char *stylesheet_link = NULL;
static char *title = NULL;
GOptionEntry pcmk__html_output_entries[] = {
{ "cgi-output", 0, 0, G_OPTION_ARG_NONE, &cgi_output,
"Add text needed to use output in a CGI program",
NULL },
{ "meta-refresh", 0, 0, G_OPTION_ARG_INT, &meta_refresh,
"How often to refresh",
"SECONDS" },
{ "stylesheet-link", 0, 0, G_OPTION_ARG_STRING, &stylesheet_link,
"Link to an external CSS stylesheet",
"URI" },
{ "title", 0, 0, G_OPTION_ARG_STRING, &title,
"Page title (defaults to command line)",
"TITLE" },
{ NULL }
};
typedef struct private_data_s {
xmlNode *root;
GQueue *parent_q;
GSList *errors;
} private_data_t;
static void
html_free_priv(pcmk__output_t *out) {
private_data_t *priv = out->priv;
if (priv == NULL) {
return;
}
xmlFreeNode(priv->root);
g_queue_free(priv->parent_q);
g_slist_free(priv->errors);
free(priv);
}
static bool
html_init(pcmk__output_t *out) {
private_data_t *priv = NULL;
/* If html_init was previously called on this output struct, just return. */
if (out->priv != NULL) {
return true;
} else {
out->priv = calloc(1, sizeof(private_data_t));
if (out->priv == NULL) {
return false;
}
priv = out->priv;
}
priv->parent_q = g_queue_new();
priv->root = create_xml_node(NULL, "html");
xmlCreateIntSubset(priv->root->doc, (pcmkXmlStr) "html", NULL, NULL);
xmlSetProp(priv->root, (pcmkXmlStr) "lang", (pcmkXmlStr) "en");
g_queue_push_tail(priv->parent_q, priv->root);
priv->errors = NULL;
pcmk__output_xml_create_parent(out, "body");
return true;
}
static void
add_error_node(gpointer data, gpointer user_data) {
char *str = (char *) data;
pcmk__output_t *out = (pcmk__output_t *) user_data;
out->list_item(out, NULL, str);
}
static void
html_finish(pcmk__output_t *out, crm_exit_t exit_status) {
private_data_t *priv = out->priv;
htmlNodePtr head_node = NULL;
htmlNodePtr charset_node = NULL;
/* If root is NULL, html_init failed and we are being called from pcmk__output_free
* in the pcmk__output_new path.
*/
if (priv->root == NULL) {
return;
}
if (cgi_output) {
fprintf(out->dest, "Content-Type: text/html\n\n");
}
/* Add the head node last - it's not needed earlier because it doesn't contain
* anything else that the user could add, and we want it done last to pick up
* any options that may have been given.
*/
head_node = xmlNewNode(NULL, (pcmkXmlStr) "head");
if (title != NULL ) {
pcmk_create_xml_text_node(head_node, "title", title);
} else if (out->request != NULL) {
pcmk_create_xml_text_node(head_node, "title", out->request);
}
charset_node = create_xml_node(head_node, "meta");
xmlSetProp(charset_node, (pcmkXmlStr) "charset", (pcmkXmlStr) "utf-8");
if (meta_refresh != 0) {
htmlNodePtr refresh_node = create_xml_node(head_node, "meta");
xmlSetProp(refresh_node, (pcmkXmlStr) "http-equiv", (pcmkXmlStr) "refresh");
xmlSetProp(refresh_node, (pcmkXmlStr) "content", (pcmkXmlStr) crm_itoa(meta_refresh));
}
/* Stylesheets are included two different ways. The first is via a built-in
* default (see the stylesheet_default const above). The second is via the
* "stylesheet-link" option, and this should obviously be a link to a
* stylesheet. The second can override the first. At least one should be
* given.
*/
pcmk_create_xml_text_node(head_node, "style", stylesheet_default);
if (stylesheet_link != NULL) {
htmlNodePtr link_node = create_xml_node(head_node, "link");
xmlSetProp(link_node, (pcmkXmlStr) "rel", (pcmkXmlStr) "stylesheet");
xmlSetProp(link_node, (pcmkXmlStr) "href", (pcmkXmlStr) stylesheet_link);
}
xmlAddPrevSibling(priv->root->children, head_node);
if (g_slist_length(priv->errors) > 0) {
out->begin_list(out, "Errors", NULL, NULL);
g_slist_foreach(priv->errors, add_error_node, (gpointer) out);
out->end_list(out);
}
htmlDocDump(out->dest, priv->root->doc);
}
static void
html_reset(pcmk__output_t *out) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
htmlDocDump(out->dest, priv->root->doc);
html_free_priv(out);
html_init(out);
}
static void
html_subprocess_output(pcmk__output_t *out, int exit_status,
const char *proc_stdout, const char *proc_stderr) {
char *rc_buf = NULL;
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
rc_buf = crm_strdup_printf("Return code: %d", exit_status);
- pcmk_create_xml_text_node(g_queue_peek_tail(priv->parent_q), "h2", "Command Output");
+ pcmk__output_create_xml_text_node(out, "h2", "Command Output");
pcmk__output_create_html_node(out, "div", NULL, NULL, rc_buf);
if (proc_stdout != NULL) {
pcmk__output_create_html_node(out, "div", NULL, NULL, "Stdout");
pcmk__output_create_html_node(out, "div", NULL, "output", proc_stdout);
}
if (proc_stderr != NULL) {
pcmk__output_create_html_node(out, "div", NULL, NULL, "Stderr");
pcmk__output_create_html_node(out, "div", NULL, "output", proc_stderr);
}
free(rc_buf);
}
static void
html_version(pcmk__output_t *out, bool extended) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
- pcmk_create_xml_text_node(g_queue_peek_tail(priv->parent_q), "h2", "Version Information");
+ pcmk__output_create_xml_text_node(out, "h2", "Version Information");
pcmk__output_create_html_node(out, "div", NULL, NULL, "Program: Pacemaker");
pcmk__output_create_html_node(out, "div", NULL, NULL, crm_strdup_printf("Version: %s", PACEMAKER_VERSION));
pcmk__output_create_html_node(out, "div", NULL, NULL, "Author: Andrew Beekhof");
pcmk__output_create_html_node(out, "div", NULL, NULL, crm_strdup_printf("Build: %s", BUILD_VERSION));
pcmk__output_create_html_node(out, "div", NULL, NULL, crm_strdup_printf("Features: %s", CRM_FEATURES));
}
G_GNUC_PRINTF(2, 3)
static void
html_err(pcmk__output_t *out, const char *format, ...) {
private_data_t *priv = out->priv;
int len = 0;
char *buf = NULL;
va_list ap;
CRM_ASSERT(priv != NULL);
va_start(ap, format);
len = vasprintf(&buf, format, ap);
CRM_ASSERT(len > 0);
va_end(ap);
priv->errors = g_slist_append(priv->errors, buf);
}
G_GNUC_PRINTF(2, 3)
static void
html_info(pcmk__output_t *out, const char *format, ...) {
/* This function intentially left blank */
}
static void
html_output_xml(pcmk__output_t *out, const char *name, const char *buf) {
htmlNodePtr node = NULL;
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
node = pcmk__output_create_html_node(out, "pre", NULL, NULL, buf);
xmlSetProp(node, (pcmkXmlStr) "lang", (pcmkXmlStr) "xml");
}
static void
html_begin_list(pcmk__output_t *out, const char *name,
const char *singular_noun, const char *plural_noun) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
if (name != NULL) {
- pcmk_create_xml_text_node(g_queue_peek_tail(priv->parent_q), "h2", name);
+ pcmk__output_create_xml_text_node(out, "h2", name);
}
pcmk__output_xml_create_parent(out, "ul");
}
static void
html_list_item(pcmk__output_t *out, const char *name, const char *content) {
private_data_t *priv = out->priv;
htmlNodePtr item_node = NULL;
CRM_ASSERT(priv != NULL);
- item_node = pcmk_create_xml_text_node(g_queue_peek_tail(priv->parent_q), "li", content);
+ item_node = pcmk__output_create_xml_text_node(out, "li", content);
if (name != NULL) {
xmlSetProp(item_node, (pcmkXmlStr) "class", (pcmkXmlStr) name);
}
}
static void
html_end_list(pcmk__output_t *out) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
g_queue_pop_tail(priv->parent_q);
}
pcmk__output_t *
pcmk__mk_html_output(char **argv) {
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
if (retval == NULL) {
return NULL;
}
retval->fmt_name = "html";
retval->request = g_strjoinv(" ", argv);
retval->supports_quiet = false;
retval->init = html_init;
retval->free_priv = html_free_priv;
retval->finish = html_finish;
retval->reset = html_reset;
retval->register_message = pcmk__register_message;
retval->message = pcmk__call_message;
retval->subprocess_output = html_subprocess_output;
retval->version = html_version;
retval->info = html_info;
retval->err = html_err;
retval->output_xml = html_output_xml;
retval->begin_list = html_begin_list;
retval->list_item = html_list_item;
retval->end_list = html_end_list;
return retval;
}
xmlNodePtr
pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id,
const char *class_name, const char *text) {
- htmlNodePtr node = xmlNewNode(NULL, (pcmkXmlStr) element_name);
-
- xmlNodeSetContent(node, (pcmkXmlStr) text);
+ htmlNodePtr node = pcmk__output_create_xml_text_node(out, element_name, text);
if (class_name != NULL) {
xmlSetProp(node, (pcmkXmlStr) "class", (pcmkXmlStr) class_name);
}
if (id != NULL) {
xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) id);
}
- pcmk__output_xml_add_node(out, node);
return node;
}
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
index 7a8438b346..52f1e429ba 100644
--- a/lib/common/output_xml.c
+++ b/lib/common/output_xml.c
@@ -1,335 +1,334 @@
/*
* Copyright 2019 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include
#include
#include
#include
#include
#include
#include
#include
GOptionEntry pcmk__xml_output_entries[] = {
{ NULL }
};
typedef struct private_data_s {
xmlNode *root;
GQueue *parent_q;
GSList *errors;
} private_data_t;
static void
xml_free_priv(pcmk__output_t *out) {
private_data_t *priv = out->priv;
if (priv == NULL) {
return;
}
xmlFreeNode(priv->root);
g_queue_free(priv->parent_q);
g_slist_free(priv->errors);
free(priv);
}
static bool
xml_init(pcmk__output_t *out) {
private_data_t *priv = NULL;
/* If xml_init was previously called on this output struct, just return. */
if (out->priv != NULL) {
return true;
} else {
out->priv = calloc(1, sizeof(private_data_t));
if (out->priv == NULL) {
return false;
}
priv = out->priv;
}
priv->root = create_xml_node(NULL, "pacemaker-result");
xmlSetProp(priv->root, (pcmkXmlStr) "api-version", (pcmkXmlStr) PCMK__API_VERSION);
if (out->request != NULL) {
xmlSetProp(priv->root, (pcmkXmlStr) "request", (pcmkXmlStr) out->request);
}
priv->parent_q = g_queue_new();
priv->errors = NULL;
g_queue_push_tail(priv->parent_q, priv->root);
return true;
}
static void
add_error_node(gpointer data, gpointer user_data) {
char *str = (char *) data;
xmlNodePtr node = (xmlNodePtr) user_data;
pcmk_create_xml_text_node(node, "error", str);
}
static void
xml_finish(pcmk__output_t *out, crm_exit_t exit_status) {
xmlNodePtr node;
char *rc_as_str = NULL;
char *buf = NULL;
private_data_t *priv = out->priv;
/* If root is NULL, xml_init failed and we are being called from pcmk__output_free
* in the pcmk__output_new path.
*/
if (priv->root == NULL) {
return;
}
rc_as_str = crm_itoa(exit_status);
node = create_xml_node(priv->root, "status");
xmlSetProp(node, (pcmkXmlStr) "code", (pcmkXmlStr) rc_as_str);
xmlSetProp(node, (pcmkXmlStr) "message", (pcmkXmlStr) crm_exit_str(exit_status));
if (g_slist_length(priv->errors) > 0) {
xmlNodePtr errors_node = create_xml_node(node, "errors");
g_slist_foreach(priv->errors, add_error_node, (gpointer) errors_node);
}
buf = dump_xml_formatted_with_text(priv->root);
fprintf(out->dest, "%s", buf);
free(rc_as_str);
free(buf);
}
static void
xml_reset(pcmk__output_t *out) {
char *buf = NULL;
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
buf = dump_xml_formatted_with_text(priv->root);
fprintf(out->dest, "%s", buf);
free(buf);
xml_free_priv(out);
xml_init(out);
}
static void
xml_subprocess_output(pcmk__output_t *out, int exit_status,
const char *proc_stdout, const char *proc_stderr) {
xmlNodePtr node, child_node;
char *rc_as_str = NULL;
rc_as_str = crm_itoa(exit_status);
node = pcmk__output_xml_create_parent(out, "command");
xmlSetProp(node, (pcmkXmlStr) "code", (pcmkXmlStr) rc_as_str);
if (proc_stdout != NULL) {
child_node = pcmk_create_xml_text_node(node, "output", proc_stdout);
xmlSetProp(child_node, (pcmkXmlStr) "source", (pcmkXmlStr) "stdout");
}
if (proc_stderr != NULL) {
child_node = pcmk_create_xml_text_node(node, "output", proc_stderr);
xmlSetProp(child_node, (pcmkXmlStr) "source", (pcmkXmlStr) "stderr");
}
pcmk__output_xml_add_node(out, node);
free(rc_as_str);
}
static void
xml_version(pcmk__output_t *out, bool extended) {
xmlNodePtr node;
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
- node = create_xml_node(g_queue_peek_tail(priv->parent_q), "version");
-
+ node = pcmk__output_create_xml_node(out, "version");
xmlSetProp(node, (pcmkXmlStr) "program", (pcmkXmlStr) "Pacemaker");
xmlSetProp(node, (pcmkXmlStr) "version", (pcmkXmlStr) PACEMAKER_VERSION);
xmlSetProp(node, (pcmkXmlStr) "author", (pcmkXmlStr) "Andrew Beekhof");
xmlSetProp(node, (pcmkXmlStr) "build", (pcmkXmlStr) BUILD_VERSION);
xmlSetProp(node, (pcmkXmlStr) "features", (pcmkXmlStr) CRM_FEATURES);
}
G_GNUC_PRINTF(2, 3)
static void
xml_err(pcmk__output_t *out, const char *format, ...) {
private_data_t *priv = out->priv;
int len = 0;
char *buf = NULL;
va_list ap;
CRM_ASSERT(priv != NULL);
va_start(ap, format);
len = vasprintf(&buf, format, ap);
CRM_ASSERT(len > 0);
va_end(ap);
priv->errors = g_slist_append(priv->errors, buf);
}
G_GNUC_PRINTF(2, 3)
static void
xml_info(pcmk__output_t *out, const char *format, ...) {
/* This function intentially left blank */
}
static void
xml_output_xml(pcmk__output_t *out, const char *name, const char *buf) {
xmlNodePtr parent = NULL;
xmlNodePtr cdata_node = NULL;
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
- parent = create_xml_node(g_queue_peek_tail(priv->parent_q), name);
+ parent = pcmk__output_create_xml_node(out, name);
cdata_node = xmlNewCDataBlock(getDocPtr(parent), (pcmkXmlStr) buf, strlen(buf));
xmlAddChild(parent, cdata_node);
}
static void
xml_begin_list(pcmk__output_t *out, const char *name,
const char *singular_noun, const char *plural_noun) {
xmlNodePtr list_node = NULL;
list_node = pcmk__output_xml_create_parent(out, "list");
xmlSetProp(list_node, (pcmkXmlStr) "name", (pcmkXmlStr) name);
}
static void
xml_list_item(pcmk__output_t *out, const char *name, const char *content) {
private_data_t *priv = out->priv;
xmlNodePtr item_node = NULL;
CRM_ASSERT(priv != NULL);
- item_node = pcmk_create_xml_text_node(g_queue_peek_tail(priv->parent_q), "item", content);
+ item_node = pcmk__output_create_xml_text_node(out, "item", content);
xmlSetProp(item_node, (pcmkXmlStr) "name", (pcmkXmlStr) name);
}
static void
xml_end_list(pcmk__output_t *out) {
char *buf = NULL;
private_data_t *priv = out->priv;
xmlNodePtr node;
CRM_ASSERT(priv != NULL);
node = g_queue_pop_tail(priv->parent_q);
buf = crm_strdup_printf("%lu", xmlChildElementCount(node));
xmlSetProp(node, (pcmkXmlStr) "count", (pcmkXmlStr) buf);
free(buf);
}
pcmk__output_t *
pcmk__mk_xml_output(char **argv) {
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
if (retval == NULL) {
return NULL;
}
retval->fmt_name = "xml";
retval->request = g_strjoinv(" ", argv);
retval->supports_quiet = false;
retval->init = xml_init;
retval->free_priv = xml_free_priv;
retval->finish = xml_finish;
retval->reset = xml_reset;
retval->register_message = pcmk__register_message;
retval->message = pcmk__call_message;
retval->subprocess_output = xml_subprocess_output;
retval->version = xml_version;
retval->info = xml_info;
retval->err = xml_err;
retval->output_xml = xml_output_xml;
retval->begin_list = xml_begin_list;
retval->list_item = xml_list_item;
retval->end_list = xml_end_list;
return retval;
}
xmlNodePtr
pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name) {
xmlNodePtr node = pcmk__output_create_xml_node(out, name);
pcmk__output_xml_push_parent(out, node);
return node;
}
void
pcmk__output_xml_add_node(pcmk__output_t *out, xmlNodePtr node) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
CRM_ASSERT(node != NULL);
xmlAddChild(g_queue_peek_tail(priv->parent_q), node);
}
xmlNodePtr
pcmk__output_create_xml_node(pcmk__output_t *out, const char *name) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
return create_xml_node(g_queue_peek_tail(priv->parent_q), name);
}
xmlNodePtr
pcmk__output_create_xml_text_node(pcmk__output_t *out, const char *name, const char *content) {
xmlNodePtr node = pcmk__output_create_xml_node(out, name);
xmlNodeSetContent(node, (pcmkXmlStr) content);
return node;
}
void
pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr parent) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
CRM_ASSERT(parent != NULL);
g_queue_push_tail(priv->parent_q, parent);
}
void
pcmk__output_xml_pop_parent(pcmk__output_t *out) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
CRM_ASSERT(g_queue_get_length(priv->parent_q) > 0);
g_queue_pop_tail(priv->parent_q);
}
xmlNodePtr
pcmk__output_xml_peek_parent(pcmk__output_t *out) {
private_data_t *priv = out->priv;
CRM_ASSERT(priv != NULL);
/* If queue is empty NULL will be returned */
return g_queue_peek_tail(priv->parent_q);
}
diff --git a/lib/fencing/st_output.c b/lib/fencing/st_output.c
index dfe1c739cc..a9d47f587c 100644
--- a/lib/fencing/st_output.c
+++ b/lib/fencing/st_output.c
@@ -1,203 +1,203 @@
/*
* Copyright 2019 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#include
#include
#include
#include
#include
#include
#include
static int
last_fenced_text(pcmk__output_t *out, va_list args) {
const char *target = va_arg(args, const char *);
time_t when = va_arg(args, time_t);
if (when) {
pcmk__indented_printf(out, "Node %s last fenced at: %s", target, ctime(&when));
} else {
pcmk__indented_printf(out, "Node %s has never been fenced\n", target);
}
return 0;
}
static int
last_fenced_xml(pcmk__output_t *out, va_list args) {
const char *target = va_arg(args, const char *);
time_t when = va_arg(args, time_t);
if (when) {
crm_time_t *crm_when = crm_time_new(NULL);
- xmlNodePtr node = pcmk__output_xml_create_parent(out, "last-fenced");
+ xmlNodePtr node = pcmk__output_create_xml_node(out, "last-fenced");
char *buf = NULL;
crm_time_set_timet(crm_when, &when);
buf = crm_time_as_string(crm_when, crm_time_log_date | crm_time_log_timeofday | crm_time_log_with_timezone);
xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) target);
xmlSetProp(node, (pcmkXmlStr) "when", (pcmkXmlStr) buf);
crm_time_free(crm_when);
free(buf);
}
return 0;
}
static int
stonith_event_text(pcmk__output_t *out, va_list args) {
stonith_history_t *event = va_arg(args, stonith_history_t *);
switch (event->state) {
case st_failed:
pcmk__indented_printf(out, "%s failed %s node %s on behalf of %s from %s at %s",
event->delegate ? event->delegate : "We",
stonith_action_str(event->action), event->target,
event->client, event->origin, ctime(&event->completed));
break;
case st_done:
pcmk__indented_printf(out, "%s succeeded %s node %s on behalf of %s from %s at %s",
event->delegate ? event->delegate : "This node",
stonith_action_str(event->action), event->target,
event->client, event->origin, ctime(&event->completed));
break;
default:
/* ocf:pacemaker:controld depends on "wishes to" being
* in this output, when used with older versions of DLM
* that don't report stateful_merge_wait
*/
pcmk__indented_printf(out, "%s at %s wishes to %s node %s - %d %lld\n",
event->client, event->origin, stonith_action_str(event->action),
event->target, event->state, (long long) event->completed);
break;
}
return 0;
}
static int
stonith_event_xml(pcmk__output_t *out, va_list args) {
- xmlNodePtr node = pcmk__output_xml_create_parent(out, "fence_event");
+ xmlNodePtr node = pcmk__output_create_xml_node(out, "fence_event");
stonith_history_t *event = va_arg(args, stonith_history_t *);
crm_time_t *crm_when = crm_time_new(NULL);
char *buf = NULL;
switch (event->state) {
case st_failed:
xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "failed");
break;
case st_done:
xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "success");
break;
default: {
char *state = crm_itoa(event->state);
xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) "pending");
xmlSetProp(node, (pcmkXmlStr) "extended-status", (pcmkXmlStr) state);
free(state);
break;
}
}
if (event->delegate != NULL) {
xmlSetProp(node, (pcmkXmlStr) "delegate", (pcmkXmlStr) event->delegate);
}
xmlSetProp(node, (pcmkXmlStr) "action", (pcmkXmlStr) event->action);
xmlSetProp(node, (pcmkXmlStr) "target", (pcmkXmlStr) event->target);
xmlSetProp(node, (pcmkXmlStr) "client", (pcmkXmlStr) event->client);
xmlSetProp(node, (pcmkXmlStr) "origin", (pcmkXmlStr) event->origin);
if (event->state == st_failed || event->state == st_done) {
crm_time_set_timet(crm_when, &event->completed);
buf = crm_time_as_string(crm_when, crm_time_log_date | crm_time_log_timeofday | crm_time_log_with_timezone);
xmlSetProp(node, (pcmkXmlStr) "completed", (pcmkXmlStr) buf);
free(buf);
}
crm_time_free(crm_when);
return 0;
}
static int
validate_agent_text(pcmk__output_t *out, va_list args) {
const char *agent = va_arg(args, const char *);
const char *device = va_arg(args, const char *);
const char *output = va_arg(args, const char *);
const char *error_output = va_arg(args, const char *);
int rc = va_arg(args, int);
if (device) {
pcmk__indented_printf(out, "Validation of %s on %s %s\n", agent, device,
rc ? "failed" : "succeeded");
} else {
pcmk__indented_printf(out, "Validation of %s %s\n", agent,
rc ? "failed" : "succeeded");
}
if (output) {
puts(output);
}
if (error_output) {
puts(error_output);
}
return rc;
}
static int
validate_agent_xml(pcmk__output_t *out, va_list args) {
- xmlNodePtr node = pcmk__output_xml_create_parent(out, "validate");
+ xmlNodePtr node = pcmk__output_create_xml_node(out, "validate");
const char *agent = va_arg(args, const char *);
const char *device = va_arg(args, const char *);
const char *output = va_arg(args, const char *);
const char *error_output = va_arg(args, const char *);
int rc = va_arg(args, int);
xmlSetProp(node, (pcmkXmlStr) "agent", (pcmkXmlStr) agent);
if (device != NULL) {
xmlSetProp(node, (pcmkXmlStr) "device", (pcmkXmlStr) device);
}
xmlSetProp(node, (pcmkXmlStr) "valid", (pcmkXmlStr) (rc ? "false" : "true"));
pcmk__output_xml_push_parent(out, node);
out->subprocess_output(out, rc, output, error_output);
pcmk__output_xml_pop_parent(out);
return rc;
}
static pcmk__message_entry_t fmt_functions[] = {
{ "last-fenced", "text", last_fenced_text },
{ "last-fenced", "xml", last_fenced_xml },
{ "stonith-event", "text", stonith_event_text },
{ "stonith-event", "xml", stonith_event_xml },
{ "validate", "text", validate_agent_text },
{ "validate", "xml", validate_agent_xml },
{ NULL, NULL, NULL }
};
void
stonith__register_messages(pcmk__output_t *out) {
static bool registered = FALSE;
if (!registered) {
pcmk__register_messages(out, fmt_functions);
registered = TRUE;
}
}