Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/include/crm/common/Makefile.am b/include/crm/common/Makefile.am
index 02f16866e6..076d4bd452 100644
--- a/include/crm/common/Makefile.am
+++ b/include/crm/common/Makefile.am
@@ -1,25 +1,26 @@
#
# Copyright 2004-2021 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
MAINTAINERCLEANFILES = Makefile.in
headerdir=$(pkgincludedir)/crm/common
header_HEADERS = xml.h ipc.h util.h iso8601.h mainloop.h logging.h results.h \
- nvpair.h acl.h agents.h ipc_controld.h ipc_pacemakerd.h output.h \
+ nvpair.h acl.h agents.h ipc_controld.h ipc_pacemakerd.h ipc_schedulerd.h \
+ output.h \
agents_compat.h \
logging_compat.h \
mainloop_compat.h \
util_compat.h \
xml_compat.h
noinst_HEADERS = internal.h alerts_internal.h \
iso8601_internal.h remote_internal.h xml_internal.h \
ipc_internal.h output_internal.h cmdline_internal.h \
attrd_internal.h options_internal.h results_internal.h \
strings_internal.h lists_internal.h logging_internal.h
diff --git a/include/crm/common/ipc_schedulerd.h b/include/crm/common/ipc_schedulerd.h
new file mode 100644
index 0000000000..995d15a1bd
--- /dev/null
+++ b/include/crm/common/ipc_schedulerd.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2021 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 PCMK__IPC_SCHEDULERD__H
+# define PCMK__IPC_SCHEDULERD__H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file
+ * \brief IPC commands for Schedulerd
+ *
+ * \ingroup core
+ */
+
+#include <crm/common/ipc.h> // pcmk_ipc_api_t
+
+//! Possible types of schedulerd replies
+enum pcmk_schedulerd_api_reply {
+ pcmk_schedulerd_reply_unknown,
+ pcmk_schedulerd_reply_graph,
+};
+
+/*!
+ * Schedulerd reply passed to event callback
+ */
+typedef struct {
+ enum pcmk_schedulerd_api_reply reply_type;
+
+ union {
+ // pcmk__schedulerd_reply_graph
+ struct {
+ xmlNode *tgraph;
+ const char *reference;
+ const char *input;
+ } graph;
+ } data;
+} pcmk_schedulerd_api_reply_t;
+
+/*!
+ * \brief Make an IPC request to the scheduler for the transition graph
+ *
+ * \param[in] api IPC API connection
+ * \param[in] cib The CIB to create a transition graph for
+ * \param[out] ref The reference ID a response will have
+ *
+ * \return Standard Pacemaker return code
+ */
+int pcmk_schedulerd_api_graph(pcmk_ipc_api_t *api, xmlNode *cib, char **ref);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PCMK__IPC_SCHEDULERD__H
diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am
index 5b0d069879..8de0337961 100644
--- a/lib/common/Makefile.am
+++ b/lib/common/Makefile.am
@@ -1,112 +1,113 @@
#
# Copyright 2004-2021 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
include $(top_srcdir)/mk/common.mk
include $(top_srcdir)/lib/common/mock.mk
AM_CPPFLAGS += -I$(top_builddir)/lib/gnu -I$(top_srcdir)/lib/gnu
MOSTLYCLEANFILES = md5.c
## libraries
lib_LTLIBRARIES = libcrmcommon.la
check_LTLIBRARIES = libcrmcommon_test.la
# Disable -Wcast-qual if used, because we do some hacky casting,
# and because libxml2 has some signatures that should be const but aren't
# for backward compatibility reasons.
# s390 needs -fPIC
# s390-suse-linux/bin/ld: .libs/ipc.o: relocation R_390_PC32DBL against `__stack_chk_fail@@GLIBC_2.4' can not be used when making a shared object; recompile with -fPIC
CFLAGS = $(CFLAGS_COPY:-Wcast-qual=) -fPIC
# Without "." here, check-recursive will run through the subdirectories first
# and then run "make check" here. This will fail, because there's things in
# the subdirectories that need check_LTLIBRARIES built first. Adding "." here
# changes the order so the subdirectories are processed afterwards.
SUBDIRS = . tests
noinst_HEADERS = crmcommon_private.h mock_private.h
libcrmcommon_la_LDFLAGS = -version-info 42:0:8
libcrmcommon_la_CFLAGS = $(CFLAGS_HARDENED_LIB)
libcrmcommon_la_LDFLAGS += $(LDFLAGS_HARDENED_LIB)
libcrmcommon_la_LIBADD = @LIBADD_DL@
# If configured with --with-profiling or --with-coverage, BUILD_PROFILING will
# be set and -fno-builtin will be added to the CFLAGS. However, libcrmcommon
# uses the fabs() function which is normally supplied by gcc as one of its
# builtins. Therefore we need to explicitly link against libm here or the
# tests won't link.
if BUILD_PROFILING
libcrmcommon_la_LIBADD += -lm
endif
# Use += rather than backlashed continuation lines for parsing by bumplibs
libcrmcommon_la_SOURCES =
libcrmcommon_la_SOURCES += acl.c
libcrmcommon_la_SOURCES += agents.c
libcrmcommon_la_SOURCES += alerts.c
libcrmcommon_la_SOURCES += attrd_client.c
if BUILD_CIBSECRETS
libcrmcommon_la_SOURCES += cib_secrets.c
endif
libcrmcommon_la_SOURCES += cmdline.c
libcrmcommon_la_SOURCES += digest.c
libcrmcommon_la_SOURCES += io.c
libcrmcommon_la_SOURCES += ipc_client.c
libcrmcommon_la_SOURCES += ipc_common.c
libcrmcommon_la_SOURCES += ipc_controld.c
libcrmcommon_la_SOURCES += ipc_pacemakerd.c
+libcrmcommon_la_SOURCES += ipc_schedulerd.c
libcrmcommon_la_SOURCES += ipc_server.c
libcrmcommon_la_SOURCES += iso8601.c
libcrmcommon_la_SOURCES += lists.c
libcrmcommon_la_SOURCES += logging.c
libcrmcommon_la_SOURCES += mainloop.c
libcrmcommon_la_SOURCES += messages.c
libcrmcommon_la_SOURCES += nvpair.c
libcrmcommon_la_SOURCES += operations.c
libcrmcommon_la_SOURCES += options.c
libcrmcommon_la_SOURCES += output.c
libcrmcommon_la_SOURCES += output_html.c
libcrmcommon_la_SOURCES += output_log.c
libcrmcommon_la_SOURCES += output_none.c
libcrmcommon_la_SOURCES += output_text.c
libcrmcommon_la_SOURCES += output_xml.c
libcrmcommon_la_SOURCES += patchset.c
libcrmcommon_la_SOURCES += pid.c
libcrmcommon_la_SOURCES += procfs.c
libcrmcommon_la_SOURCES += remote.c
libcrmcommon_la_SOURCES += results.c
libcrmcommon_la_SOURCES += schemas.c
libcrmcommon_la_SOURCES += strings.c
libcrmcommon_la_SOURCES += utils.c
libcrmcommon_la_SOURCES += watchdog.c
libcrmcommon_la_SOURCES += xml.c
libcrmcommon_la_SOURCES += xpath.c
# It's possible to build the library adding ../gnu/md5.c directly to SOURCES,
# but distclean chokes on that because it tries to include the source's .Plo
# file, which may have already been cleaned.
nodist_libcrmcommon_la_SOURCES = md5.c
libcrmcommon_test_la_SOURCES = $(libcrmcommon_la_SOURCES)
libcrmcommon_test_la_SOURCES += mock.c
libcrmcommon_test_la_LDFLAGS = $(LDFLAGS_HARDENED_LIB) $(WRAPPED_FLAGS)
libcrmcommon_test_la_CFLAGS = $(libcrmcommon_la_CFLAGS)
libcrmcommon_test_la_LIBADD = $(libcrmcommon_la_LIBADD)
nodist_libcrmcommon_test_la_SOURCES = $(nodist_libcrmcommon_la_SOURCES)
md5.c: ../gnu/md5.c
cp "$<" "$@"
clean-generic:
rm -f *.log *.debug *.xml *~
diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h
index ba41983441..c1dc32a781 100644
--- a/lib/common/crmcommon_private.h
+++ b/lib/common/crmcommon_private.h
@@ -1,311 +1,314 @@
/*
* Copyright 2018-2021 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 CRMCOMMON_PRIVATE__H
# define CRMCOMMON_PRIVATE__H
/* This header is for the sole use of libcrmcommon, so that functions can be
* declared with G_GNUC_INTERNAL for efficiency.
*/
#include <stdint.h> // uint8_t, uint32_t
#include <stdbool.h> // bool
#include <sys/types.h> // size_t
#include <glib.h> // GList
#include <libxml/tree.h> // xmlNode, xmlAttr
#include <qb/qbipcc.h> // struct qb_ipc_response_header
// Decent chunk size for processing large amounts of data
#define PCMK__BUFFER_SIZE 4096
/*
* XML and ACLs
*/
enum xml_private_flags {
pcmk__xf_none = 0x0000,
pcmk__xf_dirty = 0x0001,
pcmk__xf_deleted = 0x0002,
pcmk__xf_created = 0x0004,
pcmk__xf_modified = 0x0008,
pcmk__xf_tracking = 0x0010,
pcmk__xf_processed = 0x0020,
pcmk__xf_skip = 0x0040,
pcmk__xf_moved = 0x0080,
pcmk__xf_acl_enabled = 0x0100,
pcmk__xf_acl_read = 0x0200,
pcmk__xf_acl_write = 0x0400,
pcmk__xf_acl_deny = 0x0800,
pcmk__xf_acl_create = 0x1000,
pcmk__xf_acl_denied = 0x2000,
pcmk__xf_lazy = 0x4000,
};
/* When deleting portions of an XML tree, we keep a record so we can know later
* (e.g. when checking differences) that something was deleted.
*/
typedef struct pcmk__deleted_xml_s {
char *path;
int position;
} pcmk__deleted_xml_t;
typedef struct xml_private_s {
long check;
uint32_t flags;
char *user;
GList *acls;
GList *deleted_objs; // List of pcmk__deleted_xml_t
} xml_private_t;
#define pcmk__set_xml_flags(xml_priv, flags_to_set) do { \
(xml_priv)->flags = pcmk__set_flags_as(__func__, __LINE__, \
LOG_NEVER, "XML", "XML node", (xml_priv)->flags, \
(flags_to_set), #flags_to_set); \
} while (0)
#define pcmk__clear_xml_flags(xml_priv, flags_to_clear) do { \
(xml_priv)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
LOG_NEVER, "XML", "XML node", (xml_priv)->flags, \
(flags_to_clear), #flags_to_clear); \
} while (0)
G_GNUC_INTERNAL
void pcmk__xml2text(xmlNode *data, int options, char **buffer, int *offset,
int *max, int depth);
G_GNUC_INTERNAL
void pcmk__buffer_add_char(char **buffer, int *offset, int *max, char c);
G_GNUC_INTERNAL
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag);
G_GNUC_INTERNAL
bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy);
G_GNUC_INTERNAL
int pcmk__element_xpath(const char *prefix, xmlNode *xml, char *buffer,
int offset, size_t buffer_size);
G_GNUC_INTERNAL
void pcmk__mark_xml_created(xmlNode *xml);
G_GNUC_INTERNAL
int pcmk__xml_position(xmlNode *xml, enum xml_private_flags ignore_if_set);
G_GNUC_INTERNAL
xmlNode *pcmk__xml_match(xmlNode *haystack, xmlNode *needle, bool exact);
G_GNUC_INTERNAL
void pcmk__xe_log(int log_level, const char *file, const char *function,
int line, const char *prefix, xmlNode *data, int depth,
int options);
G_GNUC_INTERNAL
void pcmk__xml_update(xmlNode *parent, xmlNode *target, xmlNode *update,
bool as_diff);
G_GNUC_INTERNAL
xmlNode *pcmk__xc_match(xmlNode *root, xmlNode *search_comment, bool exact);
G_GNUC_INTERNAL
void pcmk__xc_update(xmlNode *parent, xmlNode *target, xmlNode *update);
G_GNUC_INTERNAL
void pcmk__free_acls(GList *acls);
G_GNUC_INTERNAL
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user);
G_GNUC_INTERNAL
bool pcmk__check_acl(xmlNode *xml, const char *name,
enum xml_private_flags mode);
G_GNUC_INTERNAL
void pcmk__apply_acl(xmlNode *xml);
G_GNUC_INTERNAL
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top);
G_GNUC_INTERNAL
void pcmk__mark_xml_attr_dirty(xmlAttr *a);
G_GNUC_INTERNAL
bool pcmk__xa_filterable(const char *name);
static inline const char *
pcmk__xml_attr_value(const xmlAttr *attr)
{
return ((attr == NULL) || (attr->children == NULL))? NULL
: (const char *) attr->children->content;
}
/*
* IPC
*/
#define PCMK__IPC_VERSION 1
#define PCMK__CONTROLD_API_MAJOR "1"
#define PCMK__CONTROLD_API_MINOR "0"
// IPC behavior that varies by daemon
typedef struct pcmk__ipc_methods_s {
/*!
* \internal
* \brief Allocate any private data needed by daemon IPC
*
* \param[in] api IPC API connection
*
* \return Standard Pacemaker return code
*/
int (*new_data)(pcmk_ipc_api_t *api);
/*!
* \internal
* \brief Free any private data used by daemon IPC
*
* \param[in] api_data Data allocated by new_data() method
*/
void (*free_data)(void *api_data);
/*!
* \internal
* \brief Perform daemon-specific handling after successful connection
*
* Some daemons require clients to register before sending any other
* commands. The controller requires a CRM_OP_HELLO (with no reply), and
* the CIB manager, executor, and fencer require a CRM_OP_REGISTER (with a
* reply). Ideally this would be consistent across all daemons, but for now
* this allows each to do its own authorization.
*
* \param[in] api IPC API connection
*
* \return Standard Pacemaker return code
*/
int (*post_connect)(pcmk_ipc_api_t *api);
/*!
* \internal
* \brief Check whether an IPC request results in a reply
*
* \param[in] api IPC API connection
* \param[in] request IPC request XML
*
* \return true if request would result in an IPC reply, false otherwise
*/
bool (*reply_expected)(pcmk_ipc_api_t *api, xmlNode *request);
/*!
* \internal
* \brief Perform daemon-specific handling of an IPC message
*
* \param[in] api IPC API connection
* \param[in] msg Message read from IPC connection
*/
void (*dispatch)(pcmk_ipc_api_t *api, xmlNode *msg);
/*!
* \internal
* \brief Perform daemon-specific handling of an IPC disconnect
*
* \param[in] api IPC API connection
*/
void (*post_disconnect)(pcmk_ipc_api_t *api);
} pcmk__ipc_methods_t;
// Implementation of pcmk_ipc_api_t
struct pcmk_ipc_api_s {
enum pcmk_ipc_server server; // Daemon this IPC API instance is for
enum pcmk_ipc_dispatch dispatch_type; // How replies should be dispatched
size_t ipc_size_max; // maximum IPC buffer size
crm_ipc_t *ipc; // IPC connection
mainloop_io_t *mainloop_io; // If using mainloop, I/O source for IPC
bool free_on_disconnect; // Whether disconnect should free object
pcmk_ipc_callback_t cb; // Caller-registered callback (if any)
void *user_data; // Caller-registered data (if any)
void *api_data; // For daemon-specific use
pcmk__ipc_methods_t *cmds; // Behavior that varies by daemon
};
typedef struct pcmk__ipc_header_s {
struct qb_ipc_response_header qb;
uint32_t size_uncompressed;
uint32_t size_compressed;
uint32_t flags;
uint8_t version;
} pcmk__ipc_header_t;
G_GNUC_INTERNAL
int pcmk__send_ipc_request(pcmk_ipc_api_t *api, xmlNode *request);
G_GNUC_INTERNAL
void pcmk__call_ipc_callback(pcmk_ipc_api_t *api,
enum pcmk_ipc_event event_type,
crm_exit_t status, void *event_data);
G_GNUC_INTERNAL
unsigned int pcmk__ipc_buffer_size(unsigned int max);
G_GNUC_INTERNAL
bool pcmk__valid_ipc_header(const pcmk__ipc_header_t *header);
G_GNUC_INTERNAL
pcmk__ipc_methods_t *pcmk__controld_api_methods(void);
G_GNUC_INTERNAL
pcmk__ipc_methods_t *pcmk__pacemakerd_api_methods(void);
+G_GNUC_INTERNAL
+pcmk__ipc_methods_t *pcmk__schedulerd_api_methods(void);
+
/*
* Logging
*/
/*!
* \brief Check the authenticity of the IPC socket peer process
*
* If everything goes well, peer's authenticity is verified by the means
* of comparing against provided referential UID and GID (either satisfies),
* and the result of this check can be deduced from the return value.
* As an exception, detected UID of 0 ("root") satisfies arbitrary
* provided referential daemon's credentials.
*
* \param[in] qb_ipc libqb client connection if available
* \param[in] sock IPC related, connected Unix socket to check peer of
* \param[in] refuid referential UID to check against
* \param[in] refgid referential GID to check against
* \param[out] gotpid to optionally store obtained PID of the peer
* (not available on FreeBSD, special value of 1
* used instead, and the caller is required to
* special case this value respectively)
* \param[out] gotuid to optionally store obtained UID of the peer
* \param[out] gotgid to optionally store obtained GID of the peer
*
* \return Standard Pacemaker return code
* ie: 0 if it the connection is authentic
* pcmk_rc_ipc_unauthorized if the connection is not authentic,
* standard errors.
*
* \note While this function is tolerant on what constitutes authorized
* IPC daemon process (its effective user matches UID=0 or \p refuid,
* or at least its group matches \p refgid), either or both (in case
* of UID=0) mismatches on the expected credentials of such peer
* process \e shall be investigated at the caller when value of 1
* gets returned there, since higher-than-expected privileges in
* respect to the expected/intended credentials possibly violate
* the least privilege principle and may pose an additional risk
* (i.e. such accidental inconsistency shall be eventually fixed).
*/
int pcmk__crm_ipc_is_authentic_process(qb_ipcc_connection_t *qb_ipc, int sock, uid_t refuid, gid_t refgid,
pid_t *gotpid, uid_t *gotuid, gid_t *gotgid);
#endif // CRMCOMMON_PRIVATE__H
diff --git a/lib/common/ipc_schedulerd.c b/lib/common/ipc_schedulerd.c
new file mode 100644
index 0000000000..f8f8112888
--- /dev/null
+++ b/lib/common/ipc_schedulerd.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2021 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 <crm_internal.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+#include <crm/crm.h>
+#include <crm/msg_xml.h>
+#include <crm/common/xml.h>
+#include <crm/common/ipc.h>
+#include <crm/common/ipc_internal.h>
+#include <crm/common/ipc_schedulerd.h>
+#include "crmcommon_private.h"
+
+typedef struct schedulerd_api_private_s {
+ char *client_uuid;
+} schedulerd_api_private_t;
+
+// \return Standard Pacemaker return code
+static int
+new_data(pcmk_ipc_api_t *api)
+{
+ struct schedulerd_api_private_s *private = NULL;
+
+ api->api_data = calloc(1, sizeof(struct schedulerd_api_private_s));
+
+ if (api->api_data == NULL) {
+ return errno;
+ }
+
+ private = api->api_data;
+ /* See comments in ipc_pacemakerd.c. */
+ private->client_uuid = pcmk__getpid_s();
+
+ return pcmk_rc_ok;
+}
+
+static void
+free_data(void *data)
+{
+ free(((struct schedulerd_api_private_s *) data)->client_uuid);
+ free(data);
+}
+
+// \return Standard Pacemaker return code
+static int
+post_connect(pcmk_ipc_api_t *api)
+{
+ if (api->api_data == NULL) {
+ return EINVAL;
+ }
+
+ return pcmk_rc_ok;
+}
+
+static bool
+reply_expected(pcmk_ipc_api_t *api, xmlNode *request)
+{
+ const char *command = crm_element_value(request, F_CRM_TASK);
+
+ if (command == NULL) {
+ return false;
+ }
+
+ // We only need to handle commands that functions in this file can send
+ return pcmk__str_any_of(command, CRM_OP_PECALC, NULL);
+}
+
+static void
+dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
+{
+ crm_exit_t status = CRM_EX_OK;
+ xmlNode *msg_data = NULL;
+ pcmk_schedulerd_api_reply_t reply_data = {
+ pcmk_schedulerd_reply_unknown
+ };
+ const char *value = NULL;
+
+ if (pcmk__str_eq((const char *) reply->name, "ack", pcmk__str_casei)) {
+ return;
+ }
+
+ value = crm_element_value(reply, F_CRM_MSG_TYPE);
+ if ((value == NULL) || (strcmp(value, XML_ATTR_RESPONSE))) {
+ crm_debug("Unrecognizable schedulerd message: invalid message type '%s'",
+ crm_str(value));
+ status = CRM_EX_PROTOCOL;
+ goto done;
+ }
+
+ if (crm_element_value(reply, XML_ATTR_REFERENCE) == NULL) {
+ crm_debug("Unrecognizable schedulerd message: no reference");
+ status = CRM_EX_PROTOCOL;
+ goto done;
+ }
+
+ // Parse useful info from reply
+ msg_data = get_message_xml(reply, F_CRM_DATA);
+ value = crm_element_value(reply, F_CRM_TASK);
+
+ if (pcmk__str_eq(value, CRM_OP_PECALC, pcmk__str_none)) {
+ reply_data.reply_type = pcmk_schedulerd_reply_graph;
+ reply_data.data.graph.reference = crm_element_value(reply, XML_ATTR_REFERENCE);
+ reply_data.data.graph.input = crm_element_value(reply, F_CRM_TGRAPH_INPUT);
+ reply_data.data.graph.tgraph = msg_data;
+ } else {
+ crm_debug("Unrecognizable pacemakerd message: '%s'", crm_str(value));
+ status = CRM_EX_PROTOCOL;
+ goto done;
+ }
+
+done:
+ pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
+}
+
+pcmk__ipc_methods_t *
+pcmk__schedulerd_api_methods()
+{
+ pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
+
+ if (cmds != NULL) {
+ cmds->new_data = new_data;
+ cmds->free_data = free_data;
+ cmds->post_connect = post_connect;
+ cmds->reply_expected = reply_expected;
+ cmds->dispatch = dispatch;
+ }
+ return cmds;
+}
+
+static int
+do_schedulerd_api_call(pcmk_ipc_api_t *api, const char *task, xmlNode *cib, char **ref)
+{
+ schedulerd_api_private_t *private;
+ xmlNode *cmd = NULL;
+ int rc;
+
+ if (api == NULL) {
+ return EINVAL;
+ }
+
+ private = api->api_data;
+ CRM_ASSERT(private != NULL);
+
+ cmd = create_request(task, cib, NULL, CRM_SYSTEM_PENGINE,
+ crm_system_name? crm_system_name : "client",
+ private->client_uuid);
+
+ if (cmd) {
+ rc = pcmk__send_ipc_request(api, cmd);
+ if (rc != pcmk_rc_ok) {
+ crm_debug("Couldn't send request to schedulerd: %s rc=%d",
+ pcmk_rc_str(rc), rc);
+ }
+
+ *ref = strdup(crm_element_value(cmd, F_CRM_REFERENCE));
+ free_xml(cmd);
+ } else {
+ rc = ENOMSG;
+ }
+
+ return rc;
+}
+
+int
+pcmk_schedulerd_api_graph(pcmk_ipc_api_t *api, xmlNode *cib, char **ref)
+{
+ return do_schedulerd_api_call(api, CRM_OP_PECALC, cib, ref);
+}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 1:02 AM (8 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009382
Default Alt Text
(22 KB)

Event Timeline