summaryrefslogtreecommitdiffstats
path: root/lib/services
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:39:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:39:29 +0000
commitb41961d74fe7ff2d4d4abaca92454e87c561e49f (patch)
treeb34e3826a7b649dafdbd05081140c990c96d736d /lib/services
parentReleasing progress-linux version 2.1.7-1~progress7.99u1. (diff)
downloadpacemaker-b41961d74fe7ff2d4d4abaca92454e87c561e49f.tar.xz
pacemaker-b41961d74fe7ff2d4d4abaca92454e87c561e49f.zip
Merging upstream version 2.1.8~rc1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/services')
-rw-r--r--lib/services/Makefile.am2
-rw-r--r--lib/services/services.c12
-rw-r--r--lib/services/services_linux.c50
-rw-r--r--lib/services/services_lsb.c191
-rw-r--r--lib/services/services_nagios.c8
-rw-r--r--lib/services/systemd.c65
-rw-r--r--lib/services/upstart.c55
7 files changed, 227 insertions, 156 deletions
diff --git a/lib/services/Makefile.am b/lib/services/Makefile.am
index 5a19003..69c8a2c 100644
--- a/lib/services/Makefile.am
+++ b/lib/services/Makefile.am
@@ -14,7 +14,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcrmservice.la
noinst_HEADERS = $(wildcard *.h)
-libcrmservice_la_LDFLAGS = -version-info 32:0:4
+libcrmservice_la_LDFLAGS = -version-info 32:1:4
libcrmservice_la_CFLAGS =
libcrmservice_la_CFLAGS += $(CFLAGS_HARDENED_LIB)
diff --git a/lib/services/services.c b/lib/services/services.c
index e438443..94a8afc 100644
--- a/lib/services/services.c
+++ b/lib/services/services.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2023 the Pacemaker project contributors
+ * Copyright 2010-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -26,7 +26,7 @@
#include <crm/services.h>
#include <crm/services_internal.h>
#include <crm/stonith-ng.h>
-#include <crm/msg_xml.h>
+#include <crm/common/xml.h>
#include "services_private.h"
#include "services_ocf.h"
#include "services_lsb.h"
@@ -357,7 +357,7 @@ services_action_create_generic(const char *exec, const char *args[])
{
svc_action_t *op = new_action();
- CRM_ASSERT(op != NULL);
+ pcmk__mem_assert(op);
op->opaque->exec = strdup(exec);
op->opaque->args[0] = strdup(exec);
@@ -415,10 +415,8 @@ services_alert_create(const char *id, const char *exec, int timeout,
{
svc_action_t *action = services_action_create_generic(exec, NULL);
- action->id = strdup(id);
- action->standard = strdup(PCMK_RESOURCE_CLASS_ALERT);
- CRM_ASSERT((action->id != NULL) && (action->standard != NULL));
-
+ action->id = pcmk__str_copy(id);
+ action->standard = pcmk__str_copy(PCMK_RESOURCE_CLASS_ALERT);
action->timeout = timeout;
action->params = params;
action->sequence = sequence;
diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c
index c7792f0..971d38c 100644
--- a/lib/services/services_linux.c
+++ b/lib/services/services_linux.c
@@ -51,6 +51,7 @@ static void close_pipe(int fildes[]);
struct sigchld_data_s {
sigset_t mask; // Signals to block now (including SIGCHLD)
sigset_t old_mask; // Previous set of blocked signals
+ bool ignored; // If SIGCHLD for another child has been ignored
};
// Initialize SIGCHLD data and prepare for use
@@ -68,6 +69,9 @@ sigchld_setup(struct sigchld_data_s *data)
CRM_XS " source=sigprocmask", pcmk_rc_str(errno));
return false;
}
+
+ data->ignored = false;
+
return true;
}
@@ -98,7 +102,7 @@ sigchld_close(int fd)
// Return true if SIGCHLD was received from polled fd
static bool
-sigchld_received(int fd)
+sigchld_received(int fd, int pid, struct sigchld_data_s *data)
{
struct signalfd_siginfo fdsi;
ssize_t s;
@@ -112,7 +116,18 @@ sigchld_received(int fd)
CRM_XS " source=read", pcmk_rc_str(errno));
} else if (fdsi.ssi_signo == SIGCHLD) {
- return true;
+ if (fdsi.ssi_pid == pid) {
+ return true;
+
+ } else {
+ /* This SIGCHLD is for another child. We have to ignore it here but
+ * will still need to resend it after this synchronous action has
+ * completed and SIGCHLD has been restored to be handled by the
+ * previous SIGCHLD handler, so that it will be handled.
+ */
+ data->ignored = true;
+ return false;
+ }
}
return false;
}
@@ -127,6 +142,12 @@ sigchld_cleanup(struct sigchld_data_s *data)
crm_warn("Could not clean up after child process completion: %s",
pcmk_rc_str(errno));
}
+
+ // Resend any ignored SIGCHLD for other children so that they'll be handled.
+ if (data->ignored && kill(getpid(), SIGCHLD) != 0) {
+ crm_warn("Could not resend ignored SIGCHLD to ourselves: %s",
+ pcmk_rc_str(errno));
+ }
}
#else // HAVE_SYS_SIGNALFD_H not defined
@@ -137,6 +158,7 @@ struct sigchld_data_s {
int pipe_fd[2]; // Pipe file descriptors
struct sigaction sa; // Signal handling info (with SIGCHLD)
struct sigaction old_sa; // Previous signal handling info
+ bool ignored; // If SIGCHLD for another child has been ignored
};
// We need a global to use in the signal handler
@@ -187,6 +209,8 @@ sigchld_setup(struct sigchld_data_s *data)
CRM_XS " source=sigaction", pcmk_rc_str(errno));
}
+ data->ignored = false;
+
// Remember data for use in signal handler
last_sigchld_data = data;
return true;
@@ -207,7 +231,7 @@ sigchld_close(int fd)
}
static bool
-sigchld_received(int fd)
+sigchld_received(int fd, int pid, struct sigchld_data_s *data)
{
char ch;
@@ -230,6 +254,12 @@ sigchld_cleanup(struct sigchld_data_s *data)
}
close_pipe(data->pipe_fd);
+
+ // Resend any ignored SIGCHLD for other children so that they'll be handled.
+ if (data->ignored && kill(getpid(), SIGCHLD) != 0) {
+ crm_warn("Could not resend ignored SIGCHLD to ourselves: %s",
+ pcmk_rc_str(errno));
+ }
}
#endif
@@ -1054,7 +1084,8 @@ wait_for_sync_result(svc_action_t *op, struct sigchld_data_s *data)
svc_read_output(op->opaque->stderr_fd, op, TRUE);
}
- if ((fds[2].revents & POLLIN) && sigchld_received(fds[2].fd)) {
+ if ((fds[2].revents & POLLIN)
+ && sigchld_received(fds[2].fd, op->pid, data)) {
wait_rc = waitpid(op->pid, &status, WNOHANG);
if ((wait_rc > 0) || ((wait_rc < 0) && (errno == ECHILD))) {
@@ -1067,6 +1098,17 @@ wait_for_sync_result(svc_action_t *op, struct sigchld_data_s *data)
CRM_XS " source=waitpid",
op->id, op->pid, wait_reason);
wait_rc = 0; // Act as if process is still running
+
+#ifndef HAVE_SYS_SIGNALFD_H
+ } else {
+ /* The child hasn't exited, so this SIGCHLD could be for
+ * another child. We have to ignore it here but will still
+ * need to resend it after this synchronous action has
+ * completed and SIGCHLD has been restored to be handled by
+ * the previous handler, so that it will be handled.
+ */
+ data->ignored = true;
+#endif
}
}
diff --git a/lib/services/services_lsb.c b/lib/services/services_lsb.c
index 9ad7025..83587f2 100644
--- a/lib/services/services_lsb.c
+++ b/lib/services/services_lsb.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2023 the Pacemaker project contributors
+ * Copyright 2010-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -18,63 +18,67 @@
#include <sys/stat.h>
#include <crm/crm.h>
+#include <crm/common/xml.h>
#include <crm/services.h>
#include "services_private.h"
#include "services_lsb.h"
+// @TODO Use XML string constants and maybe a real XML object
#define lsb_metadata_template \
- "<?xml version='1.0'?>\n" \
- "<!DOCTYPE resource-agent SYSTEM 'ra-api-1.dtd'>\n" \
- "<resource-agent name='%s' version='" PCMK_DEFAULT_AGENT_VERSION "'>\n" \
- " <version>1.0</version>\n" \
- " <longdesc lang='en'>\n" \
- "%s" \
- " </longdesc>\n" \
- " <shortdesc lang='en'>%s</shortdesc>\n" \
- " <parameters>\n" \
- " </parameters>\n" \
- " <actions>\n" \
- " <action name='meta-data' timeout='5' />\n" \
- " <action name='start' timeout='15' />\n" \
- " <action name='stop' timeout='15' />\n" \
- " <action name='status' timeout='15' />\n" \
- " <action name='restart' timeout='15' />\n" \
- " <action name='force-reload' timeout='15' />\n" \
- " <action name='monitor' timeout='15' interval='15' />\n" \
- " </actions>\n" \
- " <special tag='LSB'>\n" \
- " <Provides>%s</Provides>\n" \
- " <Required-Start>%s</Required-Start>\n" \
- " <Required-Stop>%s</Required-Stop>\n" \
- " <Should-Start>%s</Should-Start>\n" \
- " <Should-Stop>%s</Should-Stop>\n" \
- " <Default-Start>%s</Default-Start>\n" \
- " <Default-Stop>%s</Default-Stop>\n" \
- " </special>\n" \
- "</resource-agent>\n"
+ "<?xml " PCMK_XA_VERSION "='1.0'?>\n" \
+ "<" PCMK_XE_RESOURCE_AGENT " " \
+ PCMK_XA_NAME "='%s' " \
+ PCMK_XA_VERSION "='" PCMK_DEFAULT_AGENT_VERSION "'>\n" \
+ " <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n" \
+ " <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "='" PCMK__VALUE_EN "'>\n" \
+ "%s" \
+ " </" PCMK_XE_LONGDESC ">\n" \
+ " <" PCMK_XE_SHORTDESC " " PCMK_XA_LANG "='" PCMK__VALUE_EN "'>" \
+ "%s" \
+ "</" PCMK_XE_SHORTDESC ">\n" \
+ " <" PCMK_XE_PARAMETERS "/>\n" \
+ " <" PCMK_XE_ACTIONS ">\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_META_DATA "'" \
+ " " PCMK_META_TIMEOUT "='5s' />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_START "'" \
+ " " PCMK_META_TIMEOUT "='15s' />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_STOP "'" \
+ " " PCMK_META_TIMEOUT "='15s' />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_STATUS "'" \
+ " " PCMK_META_TIMEOUT "='15s' />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='restart'" \
+ " " PCMK_META_TIMEOUT "='15s' />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='force-reload'" \
+ " " PCMK_META_TIMEOUT "='15s' />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "'" \
+ " " PCMK_META_TIMEOUT "='15s'" \
+ " " PCMK_META_INTERVAL "='15s' />\n" \
+ " </" PCMK_XE_ACTIONS ">\n" \
+ " <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "='LSB'>\n" \
+ " <Provides>%s</Provides>\n" \
+ " <Required-Start>%s</Required-Start>\n" \
+ " <Required-Stop>%s</Required-Stop>\n" \
+ " <Should-Start>%s</Should-Start>\n" \
+ " <Should-Stop>%s</Should-Stop>\n" \
+ " <Default-Start>%s</Default-Start>\n" \
+ " <Default-Stop>%s</Default-Stop>\n" \
+ " </" PCMK_XE_SPECIAL ">\n" \
+ "</" PCMK_XE_RESOURCE_AGENT ">\n"
/* See "Comment Conventions for Init Scripts" in the LSB core specification at:
* http://refspecs.linuxfoundation.org/lsb.shtml
*/
-#define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO"
-#define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO"
-#define PROVIDES "# Provides:"
-#define REQ_START "# Required-Start:"
-#define REQ_STOP "# Required-Stop:"
-#define SHLD_START "# Should-Start:"
-#define SHLD_STOP "# Should-Stop:"
-#define DFLT_START "# Default-Start:"
-#define DFLT_STOP "# Default-Stop:"
-#define SHORT_DSCR "# Short-Description:"
-#define DESCRIPTION "# Description:"
-
-#define lsb_meta_helper_free_value(m) \
- do { \
- if ((m) != NULL) { \
- xmlFree(m); \
- (m) = NULL; \
- } \
- } while(0)
+#define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO"
+#define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO"
+#define PROVIDES "# Provides:"
+#define REQUIRED_START "# Required-Start:"
+#define REQUIRED_STOP "# Required-Stop:"
+#define SHOULD_START "# Should-Start:"
+#define SHOULD_STOP "# Should-Stop:"
+#define DEFAULT_START "# Default-Start:"
+#define DEFAULT_STOP "# Default-Stop:"
+#define SHORT_DESC "# Short-Description:"
+#define DESCRIPTION "# Description:"
/*!
* \internal
@@ -87,10 +91,13 @@
* \return TRUE if value was set, FALSE otherwise
*/
static inline gboolean
-lsb_meta_helper_get_value(const char *line, char **value, const char *prefix)
+lsb_meta_helper_get_value(const char *line, gchar **value, const char *prefix)
{
- if (!*value && pcmk__starts_with(line, prefix)) {
- *value = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST line+strlen(prefix));
+ /* @TODO Perhaps update later to use pcmk__xml_needs_escape(). Involves many
+ * extra variables in the caller.
+ */
+ if ((*value == NULL) && pcmk__starts_with(line, prefix)) {
+ *value = pcmk__xml_escape(line + strlen(prefix), pcmk__xml_escape_text);
return TRUE;
}
return FALSE;
@@ -102,15 +109,15 @@ services__get_lsb_metadata(const char *type, char **output)
char ra_pathname[PATH_MAX] = { 0, };
FILE *fp = NULL;
char buffer[1024] = { 0, };
- char *provides = NULL;
- char *req_start = NULL;
- char *req_stop = NULL;
- char *shld_start = NULL;
- char *shld_stop = NULL;
- char *dflt_start = NULL;
- char *dflt_stop = NULL;
- char *s_dscrpt = NULL;
- char *xml_l_dscrpt = NULL;
+ gchar *provides = NULL;
+ gchar *required_start = NULL;
+ gchar *required_stop = NULL;
+ gchar *should_start = NULL;
+ gchar *should_stop = NULL;
+ gchar *default_start = NULL;
+ gchar *default_stop = NULL;
+ gchar *short_desc = NULL;
+ gchar *long_desc = NULL;
bool in_header = FALSE;
if (type[0] == '/') {
@@ -142,30 +149,31 @@ services__get_lsb_metadata(const char *type, char **output)
if (lsb_meta_helper_get_value(buffer, &provides, PROVIDES)) {
continue;
}
- if (lsb_meta_helper_get_value(buffer, &req_start, REQ_START)) {
+ if (lsb_meta_helper_get_value(buffer, &required_start,
+ REQUIRED_START)) {
continue;
}
- if (lsb_meta_helper_get_value(buffer, &req_stop, REQ_STOP)) {
+ if (lsb_meta_helper_get_value(buffer, &required_stop, REQUIRED_STOP)) {
continue;
}
- if (lsb_meta_helper_get_value(buffer, &shld_start, SHLD_START)) {
+ if (lsb_meta_helper_get_value(buffer, &should_start, SHOULD_START)) {
continue;
}
- if (lsb_meta_helper_get_value(buffer, &shld_stop, SHLD_STOP)) {
+ if (lsb_meta_helper_get_value(buffer, &should_stop, SHOULD_STOP)) {
continue;
}
- if (lsb_meta_helper_get_value(buffer, &dflt_start, DFLT_START)) {
+ if (lsb_meta_helper_get_value(buffer, &default_start, DEFAULT_START)) {
continue;
}
- if (lsb_meta_helper_get_value(buffer, &dflt_stop, DFLT_STOP)) {
+ if (lsb_meta_helper_get_value(buffer, &default_stop, DEFAULT_STOP)) {
continue;
}
- if (lsb_meta_helper_get_value(buffer, &s_dscrpt, SHORT_DSCR)) {
+ if (lsb_meta_helper_get_value(buffer, &short_desc, SHORT_DESC)) {
continue;
}
/* Long description may cross multiple lines */
- if ((xml_l_dscrpt == NULL) // haven't already found long description
+ if ((long_desc == NULL) // Haven't already found long description
&& pcmk__starts_with(buffer, DESCRIPTION)) {
bool processed_line = TRUE;
GString *desc = g_string_sized_new(2048);
@@ -192,9 +200,7 @@ services__get_lsb_metadata(const char *type, char **output)
}
// Make long description safe to use in XML
- xml_l_dscrpt =
- (char *) xmlEncodeEntitiesReentrant(NULL,
- (pcmkXmlStr) desc->str);
+ long_desc = pcmk__xml_escape(desc->str, pcmk__xml_escape_text);
g_string_free(desc, TRUE);
if (processed_line) {
@@ -214,28 +220,25 @@ services__get_lsb_metadata(const char *type, char **output)
fclose(fp);
*output = crm_strdup_printf(lsb_metadata_template, type,
- (xml_l_dscrpt? xml_l_dscrpt : type),
- (s_dscrpt? s_dscrpt : type),
- (provides? provides : ""),
- (req_start? req_start : ""),
- (req_stop? req_stop : ""),
- (shld_start? shld_start : ""),
- (shld_stop? shld_stop : ""),
- (dflt_start? dflt_start : ""),
- (dflt_stop? dflt_stop : ""));
-
- lsb_meta_helper_free_value(xml_l_dscrpt);
- lsb_meta_helper_free_value(s_dscrpt);
- lsb_meta_helper_free_value(provides);
- lsb_meta_helper_free_value(req_start);
- lsb_meta_helper_free_value(req_stop);
- lsb_meta_helper_free_value(shld_start);
- lsb_meta_helper_free_value(shld_stop);
- lsb_meta_helper_free_value(dflt_start);
- lsb_meta_helper_free_value(dflt_stop);
-
- crm_trace("Created fake metadata: %llu",
- (unsigned long long) strlen(*output));
+ pcmk__s(long_desc, type),
+ pcmk__s(short_desc, type),
+ pcmk__s(provides, ""),
+ pcmk__s(required_start, ""),
+ pcmk__s(required_stop, ""),
+ pcmk__s(should_start, ""),
+ pcmk__s(should_stop, ""),
+ pcmk__s(default_start, ""),
+ pcmk__s(default_stop, ""));
+
+ g_free(long_desc);
+ g_free(short_desc);
+ g_free(provides);
+ g_free(required_start);
+ g_free(required_stop);
+ g_free(should_start);
+ g_free(should_stop);
+ g_free(default_start);
+ g_free(default_stop);
return pcmk_ok;
}
diff --git a/lib/services/services_nagios.c b/lib/services/services_nagios.c
index 10759b5..f4b1320 100644
--- a/lib/services/services_nagios.c
+++ b/lib/services/services_nagios.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2023 the Pacemaker project contributors
+ * Copyright 2010-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -25,7 +25,7 @@
#include <sys/resource.h>
#include "crm/crm.h"
-#include <crm/msg_xml.h>
+#include <crm/common/xml.h>
#include "crm/common/mainloop.h"
#include "crm/services.h"
@@ -73,7 +73,7 @@ services__nagios_prepare(svc_action_t *op)
return E2BIG;
}
- if (pcmk__str_eq(key, XML_ATTR_CRM_VERSION, pcmk__str_casei)
+ if (pcmk__str_eq(key, PCMK_XA_CRM_FEATURE_SET, pcmk__str_casei)
|| strstr(key, CRM_META "_")) {
continue;
}
@@ -203,7 +203,7 @@ services__get_nagios_metadata(const char *type, char **output)
} else {
crm_trace("Reading %d bytes from file", length);
- *output = calloc(1, (length + 1));
+ *output = pcmk__assert_alloc(1, (length + 1));
read_len = fread(*output, 1, length, file_strm);
if (read_len != length) {
crm_err("Calculated and read bytes differ: %d vs. %d",
diff --git a/lib/services/systemd.c b/lib/services/systemd.c
index ecac86c..0563c49 100644
--- a/lib/services/systemd.c
+++ b/lib/services/systemd.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.
*
@@ -9,6 +9,7 @@
#include <crm_internal.h>
#include <crm/crm.h>
+#include <crm/common/xml.h>
#include <crm/services.h>
#include <crm/services_internal.h>
#include <crm/common/mainloop.h>
@@ -663,25 +664,35 @@ systemd_unit_exists(const char *name)
return FALSE;
}
-#define METADATA_FORMAT \
- "<?xml version=\"1.0\"?>\n" \
- "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n" \
- "<resource-agent name=\"%s\" version=\"" PCMK_DEFAULT_AGENT_VERSION "\">\n" \
- " <version>1.1</version>\n" \
- " <longdesc lang=\"en\">\n" \
- " %s\n" \
- " </longdesc>\n" \
- " <shortdesc lang=\"en\">systemd unit file for %s</shortdesc>\n" \
- " <parameters/>\n" \
- " <actions>\n" \
- " <action name=\"start\" timeout=\"100\" />\n" \
- " <action name=\"stop\" timeout=\"100\" />\n" \
- " <action name=\"status\" timeout=\"100\" />\n" \
- " <action name=\"monitor\" timeout=\"100\" interval=\"60\"/>\n" \
- " <action name=\"meta-data\" timeout=\"5\" />\n" \
- " </actions>\n" \
- " <special tag=\"systemd\"/>\n" \
- "</resource-agent>\n"
+// @TODO Use XML string constants and maybe a real XML object
+#define METADATA_FORMAT \
+ "<?xml " PCMK_XA_VERSION "=\"1.0\"?>\n" \
+ "<" PCMK_XE_RESOURCE_AGENT " " \
+ PCMK_XA_NAME "=\"%s\" " \
+ PCMK_XA_VERSION "=\"" PCMK_DEFAULT_AGENT_VERSION "\">\n" \
+ " <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n" \
+ " <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">\n" \
+ " %s\n" \
+ " </" PCMK_XE_LONGDESC ">\n" \
+ " <" PCMK_XE_SHORTDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">" \
+ "systemd unit file for %s" \
+ "</" PCMK_XE_SHORTDESC ">\n" \
+ " <" PCMK_XE_PARAMETERS "/>\n" \
+ " <" PCMK_XE_ACTIONS ">\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_START "\"" \
+ " " PCMK_META_TIMEOUT "=\"100s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STOP "\"" \
+ " " PCMK_META_TIMEOUT "=\"100s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STATUS "\"" \
+ " " PCMK_META_TIMEOUT "=\"100s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_MONITOR "\"" \
+ " " PCMK_META_TIMEOUT "=\"100s\"" \
+ " " PCMK_META_INTERVAL "=\"60s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_META_DATA "\"" \
+ " " PCMK_META_TIMEOUT "=\"5s\" />\n" \
+ " </" PCMK_XE_ACTIONS ">\n" \
+ " <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "=\"systemd\"/>\n" \
+ "</" PCMK_XE_RESOURCE_AGENT ">\n"
static char *
systemd_unit_metadata(const char *name, int timeout)
@@ -690,8 +701,6 @@ systemd_unit_metadata(const char *name, int timeout)
char *desc = NULL;
char *path = NULL;
- char *escaped = NULL;
-
if (invoke_unit_by_name(name, NULL, &path) == pcmk_rc_ok) {
/* TODO: Worth a making blocking call for? Probably not. Possibly if cached. */
desc = systemd_get_property(path, "Description", NULL, NULL, NULL,
@@ -700,12 +709,18 @@ systemd_unit_metadata(const char *name, int timeout)
desc = crm_strdup_printf("Systemd unit file for %s", name);
}
- escaped = crm_xml_escape(desc);
+ if (pcmk__xml_needs_escape(desc, pcmk__xml_escape_text)) {
+ gchar *escaped = pcmk__xml_escape(desc, pcmk__xml_escape_text);
+
+ meta = crm_strdup_printf(METADATA_FORMAT, name, escaped, name);
+ g_free(escaped);
+
+ } else {
+ meta = crm_strdup_printf(METADATA_FORMAT, name, desc, name);
+ }
- meta = crm_strdup_printf(METADATA_FORMAT, name, escaped, name);
free(desc);
free(path);
- free(escaped);
return meta;
}
diff --git a/lib/services/upstart.c b/lib/services/upstart.c
index 2306e73..b6f58f4 100644
--- a/lib/services/upstart.c
+++ b/lib/services/upstart.c
@@ -1,7 +1,7 @@
/*
* Original copyright 2010 Senko Rasic <senko.rasic@dobarkod.hr>
* and Ante Karamatic <ivoks@init.hr>
- * Later changes copyright 2012-2023 the Pacemaker project contributors
+ * Later changes copyright 2012-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <crm/crm.h>
+#include <crm/common/xml.h>
#include <crm/services.h>
#include <crm/common/mainloop.h>
@@ -370,26 +371,38 @@ parse_status_result(const char *name, const char *state, void *userdata)
}
}
-#define METADATA_FORMAT \
- "<?xml version=\"1.0\"?>\n" \
- "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n" \
- "<resource-agent name=\"%s\" version=\"" PCMK_DEFAULT_AGENT_VERSION "\">\n" \
- " <version>1.1</version>\n" \
- " <longdesc lang=\"en\">\n" \
- " Upstart agent for controlling the system %s service\n" \
- " </longdesc>\n" \
- " <shortdesc lang=\"en\">Upstart job for %s</shortdesc>\n" \
- " <parameters/>\n" \
- " <actions>\n" \
- " <action name=\"start\" timeout=\"15\" />\n" \
- " <action name=\"stop\" timeout=\"15\" />\n" \
- " <action name=\"status\" timeout=\"15\" />\n" \
- " <action name=\"restart\" timeout=\"15\" />\n" \
- " <action name=\"monitor\" timeout=\"15\" interval=\"15\" start-delay=\"15\" />\n" \
- " <action name=\"meta-data\" timeout=\"5\" />\n" \
- " </actions>\n" \
- " <special tag=\"upstart\"/>\n" \
- "</resource-agent>\n"
+// @TODO Use XML string constants and maybe a real XML object
+#define METADATA_FORMAT \
+ "<?xml " PCMK_XA_VERSION "=\"1.0\"?>\n" \
+ "<" PCMK_XE_RESOURCE_AGENT " " \
+ PCMK_XA_NAME "=\"%s\" " \
+ PCMK_XA_VERSION "=\"" PCMK_DEFAULT_AGENT_VERSION "\">\n" \
+ " <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n" \
+ " <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">\n" \
+ " Upstart agent for controlling the system %s service\n" \
+ " </" PCMK_XE_LONGDESC ">\n" \
+ " <" PCMK_XE_SHORTDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">" \
+ "Upstart job for %s" \
+ "</" PCMK_XE_SHORTDESC ">\n" \
+ " <" PCMK_XE_PARAMETERS "/>\n" \
+ " <" PCMK_XE_ACTIONS ">\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_START "\"" \
+ " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STOP "\"" \
+ " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STATUS "\"" \
+ " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"restart\"" \
+ " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_MONITOR "\"" \
+ " " PCMK_META_TIMEOUT "=\"15s\"" \
+ " " PCMK_META_INTERVAL "=\"15s\"" \
+ " " PCMK_META_START_DELAY "=\"15s\" />\n" \
+ " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_META_DATA "\"" \
+ " " PCMK_META_TIMEOUT "=\"5s\" />\n" \
+ " </" PCMK_XE_ACTIONS ">\n" \
+ " <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "=\"upstart\"/>\n" \
+ "</" PCMK_XE_RESOURCE_AGENT ">\n"
static char *
upstart_job_metadata(const char *name)