Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/lib/crm/Makefile.am b/lib/crm/Makefile.am
new file mode 100644
index 0000000000..dc59cdeae1
--- /dev/null
+++ b/lib/crm/Makefile.am
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2004 Andrew Beekhof
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+MAINTAINERCLEANFILES = Makefile.in
+
+## Subdirectories...
+SUBDIRS = cib
+DIST_SUBDIRS = cib
diff --git a/lib/crm/cib/Makefile.am b/lib/crm/cib/Makefile.am
new file mode 100644
index 0000000000..e950a2b2a7
--- /dev/null
+++ b/lib/crm/cib/Makefile.am
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2004 Andrew Beekhof
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
+ -I$(top_builddir)/libltdl -I$(top_srcdir)/libltdl \
+ -I$(top_builddir)/linux-ha -I$(top_srcdir)/linux-ha \
+ -I$(top_builddir) -I$(top_srcdir)
+
+hadir = $(sysconfdir)/ha.d
+halibdir = $(libdir)/@HB_PKG@
+commmoddir = $(halibdir)/modules/comm
+havarlibdir = $(localstatedir)/lib/@HB_PKG@
+crmdir = $(havarlibdir)/crm
+XML_FLAGS = `xml2-config --cflags`
+XML_LIBS = `xml2-config --libs`
+
+# sockets with path
+apigid = @HA_APIGID@
+crmuid = @HA_CCMUID@
+
+LIBRT = @LIBRT@
+AM_CFLAGS = @CFLAGS@ -DPIDFILE='"$(PIDFILE)"' $(CRM_DEBUG_FLAGS)
+
+## libraries
+lib_LTLIBRARIES = libcib.la
+
+## SOURCES
+noinst_HEADERS =
+libcib_la_SOURCES = cib_client.c cib_native.c
+
+libcib_la_LDFLAGS = -version-info 0:0:0
+libcib_la_CFLAGS = -I$(top_builddir)
+
+clean-generic:
+ rm -f *.log *.debug *.xml *~
+
+install-exec-local:
+
+uninstall-local:
diff --git a/lib/crm/cib/cib_client.c b/lib/crm/cib/cib_client.c
new file mode 100755
index 0000000000..c2c98e851d
--- /dev/null
+++ b/lib/crm/cib/cib_client.c
@@ -0,0 +1,835 @@
+/*
+ * Copyright (c) 2004 International Business Machines
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <portability.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <glib.h>
+#include <heartbeat.h>
+#include <clplumbing/ipc.h>
+
+#include <crm/crm.h>
+#include <crm/cib.h>
+#include <crm/msg_xml.h>
+#include <crm/common/xml.h>
+
+int cib_client_set_op_callback(
+ cib_t *cib, void (*callback)(const struct ha_msg *msg, int call_id,
+ int rc, xmlNodePtr output));
+int cib_client_noop(cib_t *cib, int call_options);
+int cib_client_ping(cib_t *cib, xmlNodePtr *output_data, int call_options);
+
+int cib_client_query(cib_t *cib, const char *section,
+ xmlNodePtr *output_data, int call_options);
+int cib_client_query_from(cib_t *cib, const char *host, const char *section,
+ xmlNodePtr *output_data, int call_options);
+
+int cib_client_sync(cib_t *cib, const char *section, int call_options);
+int cib_client_sync_from(
+ cib_t *cib, const char *host, const char *section, int call_options);
+
+gboolean cib_client_is_master(cib_t *cib);
+int cib_client_set_slave(cib_t *cib, int call_options);
+int cib_client_set_master(cib_t *cib, int call_options);
+
+int cib_client_bump_epoch(cib_t *cib, int call_options);
+int cib_client_create(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options) ;
+int cib_client_modify(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options) ;
+int cib_client_replace(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options) ;
+int cib_client_delete(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options) ;
+int cib_client_erase(
+ cib_t *cib, xmlNodePtr *output_data, int call_options);
+int cib_client_quit(cib_t *cib, int call_options);
+
+extern cib_t *cib_native_new(cib_t *cib);
+
+static enum cib_variant configured_variant = cib_native;
+
+/* define of the api functions*/
+cib_t*
+cib_new(void)
+{
+ cib_t* new_cib = NULL;
+
+ if(configured_variant != cib_native) {
+ crm_err("Only the native CIB type is currently implemented");
+ return NULL;
+ }
+
+ crm_malloc(new_cib, sizeof(cib_t));
+
+ new_cib->call_id = 1;
+
+ new_cib->type = cib_none;
+ new_cib->state = cib_disconnected;
+
+ new_cib->op_callback = NULL;
+ new_cib->variant_opaque = NULL;
+ new_cib->notify_callback_list = NULL;
+
+ /* the rest will get filled in by the variant constructor */
+ crm_malloc(new_cib->cmds, sizeof(cib_api_operations_t));
+ memset(new_cib->cmds, 0, sizeof(cib_api_operations_t));
+
+ new_cib->cmds->set_op_callback = cib_client_set_op_callback;
+
+ new_cib->cmds->sync = cib_client_sync;
+ new_cib->cmds->noop = cib_client_noop;
+ new_cib->cmds->ping = cib_client_ping;
+ new_cib->cmds->query = cib_client_query;
+ new_cib->cmds->query_from = cib_client_query_from;
+ new_cib->cmds->sync_from = cib_client_sync_from;
+ new_cib->cmds->is_master = cib_client_is_master;
+ new_cib->cmds->set_slave = cib_client_set_slave;
+ new_cib->cmds->set_master = cib_client_set_master;
+ new_cib->cmds->bump_epoch = cib_client_bump_epoch;
+ new_cib->cmds->create = cib_client_create;
+ new_cib->cmds->modify = cib_client_modify;
+ new_cib->cmds->replace = cib_client_replace;
+ new_cib->cmds->delete = cib_client_delete;
+ new_cib->cmds->erase = cib_client_erase;
+ new_cib->cmds->quit = cib_client_quit;
+
+ cib_native_new(new_cib);
+
+ return new_cib;
+}
+
+int
+cib_client_set_op_callback(
+ cib_t *cib, void (*callback)(const struct ha_msg *msg, int call_id,
+ int rc, xmlNodePtr output))
+{
+ if(callback == NULL) {
+ crm_info("Un-Setting operation callback");
+
+ } else {
+ crm_debug("Setting operation callback");
+ }
+ cib->op_callback = callback;
+ return cib_ok;
+}
+
+int cib_client_noop(cib_t *cib, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_NOOP, NULL,NULL,NULL, call_options);
+}
+
+int cib_client_ping(cib_t *cib, xmlNodePtr *output_data, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_PING, NULL,NULL, output_data, call_options);
+}
+
+
+int cib_client_query(cib_t *cib, const char *section,
+ xmlNodePtr *output_data, int call_options)
+{
+ return cib->cmds->query_from(
+ cib, NULL, section, output_data, call_options);
+}
+
+int cib_client_query_from(cib_t *cib, const char *host, const char *section,
+ xmlNodePtr *output_data, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_QUERY, section, NULL, output_data, call_options);
+}
+
+
+gboolean cib_client_is_master(cib_t *cib)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_ISMASTER, NULL,NULL,NULL,
+ cib_scope_local|cib_sync_call);
+}
+
+int cib_client_set_slave(cib_t *cib, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_SLAVE, NULL,NULL,NULL, call_options);
+}
+
+
+int cib_client_set_master(cib_t *cib, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_MASTER, NULL,NULL,NULL, call_options);
+}
+
+
+
+int cib_client_bump_epoch(cib_t *cib, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_BUMP, NULL, NULL, NULL, call_options);
+}
+
+int cib_client_sync(cib_t *cib, const char *section, int call_options)
+{
+ return cib->cmds->sync_from(cib, NULL, section, call_options);
+}
+
+int cib_client_sync_from(
+ cib_t *cib, const char *host, const char *section, int call_options)
+{
+ enum cib_errors rc = cib_ok;
+ xmlNodePtr stored_cib = NULL;
+ xmlNodePtr current_cib = NULL;
+
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ crm_debug("Retrieving current CIB from %s", host);
+ rc = cib->cmds->query_from(
+ cib, host, section, &current_cib, call_options|cib_sync_call);
+
+ if(rc == cib_ok) {
+ if(call_options & cib_scope_local) {
+ /* having scope == local makes no sense from here on */
+ call_options ^= cib_scope_local;
+ }
+
+ crm_debug("Storing current CIB (should trigger a store everywhere)");
+ crm_xml_debug(current_cib, "XML to store");
+ rc = cib->cmds->replace(
+ cib, section, current_cib, &stored_cib, call_options);
+ }
+ free_xml(current_cib);
+ free_xml(stored_cib);
+
+ return rc;
+
+}
+
+
+int cib_client_create(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_CREATE, section, data, output_data, call_options);
+}
+
+
+int cib_client_modify(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_UPDATE, section, data, output_data, call_options);
+}
+
+
+int cib_client_replace(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_REPLACE, NULL,NULL,NULL, call_options);
+}
+
+
+int cib_client_delete(cib_t *cib, const char *section, xmlNodePtr data,
+ xmlNodePtr *output_data, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_DELETE, section, data, output_data, call_options);
+}
+
+
+int cib_client_erase(
+ cib_t *cib, xmlNodePtr *output_data, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_CIB_ERASE, NULL,NULL, output_data, call_options);
+}
+
+
+int cib_client_quit(cib_t *cib, int call_options)
+{
+ if(cib == NULL) {
+ return cib_missing;
+ } else if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ } else if(cib->cmds->variant_op == NULL) {
+ return cib_variant;
+ }
+
+ return cib->cmds->variant_op(
+ cib, CRM_OP_QUIT, NULL,NULL,NULL, call_options);
+}
+
+
+char *
+cib_pluralSection(const char *a_section)
+{
+ char *a_section_parent = NULL;
+ if (a_section == NULL) {
+ a_section_parent = crm_strdup("all");
+
+ } else if(strcmp(a_section, XML_TAG_CIB) == 0) {
+ a_section_parent = crm_strdup("all");
+
+ } else if(strcmp(a_section, XML_CIB_TAG_NODE) == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_NODES);
+
+ } else if(strcmp(a_section, XML_CIB_TAG_STATE) == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_STATUS);
+
+ } else if(strcmp(a_section, XML_CIB_TAG_CONSTRAINT) == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
+
+ } else if(strcmp(a_section, "rsc_location") == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
+
+ } else if(strcmp(a_section, "rsc_dependancy") == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
+
+ } else if(strcmp(a_section, "rsc_order") == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
+
+ } else if(strcmp(a_section, XML_CIB_TAG_RESOURCE) == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
+
+ } else if(strcmp(a_section, XML_CIB_TAG_NVPAIR) == 0) {
+ a_section_parent = crm_strdup(XML_CIB_TAG_CRMCONFIG);
+
+ } else {
+ crm_err("Unknown section %s", a_section);
+ a_section_parent = crm_strdup("all");
+ }
+
+ crm_verbose("Plural of %s is %s", crm_str(a_section), a_section_parent);
+
+ return a_section_parent;
+}
+
+const char *
+cib_error2string(enum cib_errors return_code)
+{
+ const char *error_msg = NULL;
+ switch(return_code) {
+ case cib_msg_field_add:
+ error_msg = "failed adding field to cib message";
+ break;
+ case cib_operation:
+ error_msg = "invalid operation";
+ break;
+ case cib_create_msg:
+ error_msg = "couldnt create cib message";
+ break;
+ case cib_client_gone:
+ error_msg = "client left before we could send reply";
+ break;
+ case cib_not_connected:
+ error_msg = "not connected";
+ break;
+ case cib_not_authorized:
+ error_msg = "not authorized";
+ break;
+ case cib_send_failed:
+ error_msg = "send failed";
+ break;
+ case cib_reply_failed:
+ error_msg = "reply failed";
+ break;
+ case cib_return_code:
+ error_msg = "no return code";
+ break;
+ case cib_output_ptr:
+ error_msg = "nowhere to store output";
+ break;
+ case cib_output_data:
+ error_msg = "corrupt output data";
+ break;
+ case cib_connection:
+ error_msg = "connection failed";
+ break;
+ case cib_callback_register:
+ error_msg = "couldnt register callback channel";
+ break;
+ case cib_authentication:
+ error_msg = "";
+ break;
+ case cib_registration_msg:
+ error_msg = "invalid registration msg";
+ break;
+ case cib_callback_token:
+ error_msg = "callback token not found";
+ break;
+ case cib_missing:
+ error_msg = "cib object missing";
+ break;
+ case cib_variant:
+ error_msg = "unknown/corrupt cib variant";
+ break;
+ case CIBRES_MISSING_ID:
+ error_msg = "The id field is missing";
+ break;
+ case CIBRES_MISSING_TYPE:
+ error_msg = "The type field is missing";
+ break;
+ case CIBRES_MISSING_FIELD:
+ error_msg = "A required field is missing";
+ break;
+ case CIBRES_OBJTYPE_MISMATCH:
+ error_msg = "CIBRES_OBJTYPE_MISMATCH";
+ break;
+ case cib_EXISTS:
+ error_msg = "The object already exists";
+ break;
+ case cib_NOTEXISTS:
+ error_msg = "The object does not exist";
+ break;
+ case CIBRES_CORRUPT:
+ error_msg = "The CIB is corrupt";
+ break;
+ case cib_NOOBJECT:
+ error_msg = "The update was empty";
+ break;
+ case cib_NOPARENT:
+ error_msg = "The parent object does not exist";
+ break;
+ case cib_NODECOPY:
+ error_msg = "Failed while copying update";
+ break;
+ case CIBRES_OTHER:
+ error_msg = "CIBRES_OTHER";
+ break;
+ case cib_ok:
+ error_msg = "ok";
+ break;
+ case cib_unknown:
+ error_msg = "Unknown error";
+ break;
+ case cib_STALE:
+ error_msg = "Discarded old update";
+ break;
+ case cib_ACTIVATION:
+ error_msg = "Activation Failed";
+ break;
+ case cib_NOSECTION:
+ error_msg = "Required section was missing";
+ break;
+ case cib_NOTSUPPORTED:
+ error_msg = "Supplied information is not supported";
+ break;
+ }
+
+ if(error_msg == NULL) {
+ crm_err("Unknown CIB Error Code: %d", return_code);
+ error_msg = "<unknown error>";
+ }
+
+ return error_msg;
+}
+
+const char *
+cib_op2string(enum cib_op operation)
+{
+ const char *operation_msg = NULL;
+ switch(operation) {
+ case 0:
+ operation_msg = "none";
+ break;
+ case 1:
+ operation_msg = "add";
+ break;
+ case 2:
+ operation_msg = "modify";
+ break;
+ case 3:
+ operation_msg = "delete";
+ break;
+ case CIB_OP_MAX:
+ operation_msg = "invalid operation";
+ break;
+
+ }
+
+ if(operation_msg == NULL) {
+ crm_err("Unknown CIB operation %d", operation);
+ operation_msg = "<unknown operation>";
+ }
+
+ return operation_msg;
+}
+
+
+
+
+int
+cib_section2enum(const char *a_section)
+{
+ if(a_section == NULL || strcmp(a_section, "all") == 0) {
+ return cib_section_all;
+
+ } else if(strcmp(a_section, XML_CIB_TAG_NODES) == 0) {
+ return cib_section_nodes;
+
+ } else if(strcmp(a_section, XML_CIB_TAG_STATUS) == 0) {
+ return cib_section_status;
+
+ } else if(strcmp(a_section, XML_CIB_TAG_CONSTRAINTS) == 0) {
+ return cib_section_constraints;
+
+ } else if(strcmp(a_section, XML_CIB_TAG_RESOURCES) == 0) {
+ return cib_section_resources;
+
+ } else if(strcmp(a_section, XML_CIB_TAG_CRMCONFIG) == 0) {
+ return cib_section_crmconfig;
+
+ }
+ crm_err("Unknown CIB section: %s", a_section);
+ return cib_section_none;
+}
+
+
+int
+cib_compare_generation(xmlNodePtr left, xmlNodePtr right)
+{
+ int int_gen_l = -1;
+ int int_gen_r = -1;
+ const char *gen_l = xmlGetProp(left, XML_ATTR_GENERATION);
+ const char *gen_r = xmlGetProp(right, XML_ATTR_GENERATION);
+
+ if(gen_l != NULL) int_gen_l = atoi(gen_l);
+ if(gen_r != NULL) int_gen_r = atoi(gen_r);
+
+ if(int_gen_l < int_gen_r) {
+ return -1;
+
+ } else if(int_gen_l > int_gen_r) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+xmlNodePtr
+get_cib_copy(cib_t *cib)
+{
+ xmlNodePtr xml_cib;
+ int options = cib_scope_local|cib_sync_call;
+ if(cib->cmds->query(cib, NULL, &xml_cib, options) != cib_ok) {
+ crm_err("Couldnt retrieve the CIB");
+ return NULL;
+ }
+ return xml_cib;
+}
+
+xmlNodePtr
+cib_get_generation(cib_t *cib)
+{
+ xmlNodePtr the_cib = get_cib_copy(cib);
+ xmlNodePtr generation = create_xml_node(NULL, "generation_tuple");
+
+ copy_in_properties(generation, the_cib);
+ free_xml(the_cib);
+
+ return generation;
+}
+
+/*
+ * The caller should never free the return value
+ */
+xmlNodePtr
+get_object_root(const char *object_type, xmlNodePtr the_root)
+{
+ const char *node_stack[2];
+ xmlNodePtr tmp_node = NULL;
+
+ if(the_root == NULL) {
+ crm_err("CIB root object was NULL");
+ return NULL;
+
+ } else if(object_type == NULL) {
+ crm_debug("Returning the whole CIB");
+ return the_root;
+ }
+
+ node_stack[0] = XML_CIB_TAG_CONFIGURATION;
+ node_stack[1] = object_type;
+
+ if(object_type == NULL
+ || strlen(object_type) == 0
+ || safe_str_eq("all", object_type)) {
+ return the_root;
+ /* get the whole cib */
+
+ } else if(strcmp(object_type, XML_CIB_TAG_STATUS) == 0) {
+ /* these live in a different place */
+ tmp_node = find_xml_node(the_root, XML_CIB_TAG_STATUS);
+
+ node_stack[0] = XML_CIB_TAG_STATUS;
+ node_stack[1] = NULL;
+
+/* } else if(strcmp(object_type, XML_CIB_TAG_CRMCONFIG) == 0) { */
+/* /\* these live in a different place too *\/ */
+/* tmp_node = find_xml_node(the_root, XML_CIB_TAG_CRMCONFIG); */
+
+/* node_stack[0] = XML_CIB_TAG_CRMCONFIG; */
+/* node_stack[1] = NULL; */
+
+ } else {
+ tmp_node = find_xml_node_nested(the_root, node_stack, 2);
+ }
+
+ if (tmp_node == NULL) {
+ crm_err("[cib] Section %s [%s [%s]] not present",
+ the_root->name,
+ node_stack[0],
+ node_stack[1]?node_stack[1]:"");
+ }
+ return tmp_node;
+}
+
+
+xmlNodePtr
+create_cib_fragment_adv(
+ xmlNodePtr update, const char *section, const char *source)
+{
+ gboolean whole_cib = FALSE;
+ xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT);
+ xmlNodePtr cib = NULL;
+ xmlNodePtr object_root = NULL;
+ char *auto_section = cib_pluralSection(update?update->name:NULL);
+
+ if(update == NULL) {
+ crm_err("No update to create a fragment for");
+ crm_free(auto_section);
+ return NULL;
+
+ } else if(section == NULL) {
+ section = auto_section;
+
+ } else if(strcmp(auto_section, section) != 0) {
+ crm_err("Values for update (tag=%s) and section (%s)"
+ " were not consistent", update->name, section);
+ crm_free(auto_section);
+ return NULL;
+
+ }
+
+ if(strcmp(section, "all")==0 && strcmp(update->name, XML_TAG_CIB)==0) {
+ whole_cib = TRUE;
+ }
+
+ set_xml_property_copy(fragment, XML_ATTR_SECTION, section);
+
+ if(whole_cib == FALSE) {
+ cib = createEmptyCib();
+ object_root = get_object_root(section, cib);
+ xmlAddChildList(object_root, xmlCopyNodeList(update));
+
+ } else {
+ cib = xmlCopyNodeList(update);
+ }
+
+ xmlAddChild(fragment, cib);
+ set_xml_property_copy(cib, "debug_source", source);
+
+ crm_free(auto_section);
+
+ crm_debug("Verifying created fragment");
+ if(verifyCibXml(cib) == FALSE) {
+ crm_err("Fragment creation failed");
+ crm_err("[src] %s", dump_xml_formatted(update));
+ crm_err("[created] %s", dump_xml_formatted(fragment));
+ free_xml(fragment);
+ fragment = NULL;
+ }
+
+ return fragment;
+}
+
+/*
+ * It is the callers responsibility to free both the new CIB (output)
+ * and the new CIB (input)
+ */
+xmlNodePtr
+createEmptyCib(void)
+{
+ xmlNodePtr cib_root = NULL, config = NULL, status = NULL;
+
+ cib_root = create_xml_node(NULL, XML_TAG_CIB);
+
+ config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION);
+ status = create_xml_node(cib_root, XML_CIB_TAG_STATUS);
+
+ set_node_tstamp(cib_root);
+ set_node_tstamp(config);
+ set_node_tstamp(status);
+
+ set_xml_property_copy(cib_root, "version", "1");
+ set_xml_property_copy(cib_root, "generated", XML_BOOLEAN_TRUE);
+
+ create_xml_node(config, XML_CIB_TAG_CRMCONFIG);
+ create_xml_node(config, XML_CIB_TAG_NODES);
+ create_xml_node(config, XML_CIB_TAG_RESOURCES);
+ create_xml_node(config, XML_CIB_TAG_CONSTRAINTS);
+
+ if (verifyCibXml(cib_root)) {
+ return cib_root;
+ }
+ crm_crit("The generated CIB did not pass integrity testing!!"
+ " All hope is lost.");
+ return NULL;
+}
+
+
+gboolean
+verifyCibXml(xmlNodePtr cib)
+{
+ gboolean is_valid = TRUE;
+ xmlNodePtr tmp_node = NULL;
+
+ if (cib == NULL) {
+ crm_warn("XML Buffer was empty.");
+ return FALSE;
+ }
+
+ tmp_node = get_object_root(XML_CIB_TAG_NODES, cib);
+ if (tmp_node == NULL) is_valid = FALSE;
+
+ tmp_node = get_object_root(XML_CIB_TAG_RESOURCES, cib);
+ if (tmp_node == NULL) is_valid = FALSE;
+
+ tmp_node = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
+ if (tmp_node == NULL) is_valid = FALSE;
+
+ tmp_node = get_object_root(XML_CIB_TAG_STATUS, cib);
+ if (tmp_node == NULL) is_valid = FALSE;
+
+ tmp_node = get_object_root(XML_CIB_TAG_CRMCONFIG, cib);
+ if (tmp_node == NULL) is_valid = FALSE;
+
+ /* more integrity tests */
+
+ return is_valid;
+}
+
diff --git a/lib/crm/cib/cib_native.c b/lib/crm/cib/cib_native.c
new file mode 100755
index 0000000000..c3b3c0bee8
--- /dev/null
+++ b/lib/crm/cib/cib_native.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2004 International Business Machines
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <portability.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <glib.h>
+#include <heartbeat.h>
+#include <clplumbing/ipc.h>
+#include <ha_msg.h>
+#include <crm/crm.h>
+#include <crm/cib.h>
+#include <crm/common/ipc.h>
+
+typedef struct cib_native_opaque_s
+{
+ IPC_Channel *command_channel;
+ IPC_Channel *callback_channel;
+/* GCHSource *callback_source; */
+
+} cib_native_opaque_t;
+
+int cib_native_perform_op(
+ cib_t *cib, const char *op, const char *section,
+ xmlNodePtr data, xmlNodePtr *output_data, int call_options);
+
+int cib_native_signon(cib_t* cib, enum cib_conn_type type);
+int cib_native_signoff(cib_t* cib);
+int cib_native_free(cib_t* cib);
+
+IPC_Channel *cib_native_channel(cib_t* cib);
+int cib_native_inputfd(cib_t* cib);
+
+gboolean cib_native_msgready(cib_t* cib);
+int cib_native_rcvmsg(cib_t* cib, int blocking);
+gboolean cib_native_dispatch(IPC_Channel *channel, gpointer user_data);
+cib_t *cib_native_new (cib_t *cib);
+int cib_native_set_connection_dnotify(
+ cib_t *cib, void (*dnotify)(gpointer user_data));
+
+cib_t*
+cib_native_new (cib_t *cib)
+{
+ cib_native_opaque_t *native = NULL;
+ crm_malloc(cib->variant_opaque, sizeof(cib_native_opaque_t));
+
+ native = cib->variant_opaque;
+ native->command_channel = NULL;
+ native->callback_channel = NULL;
+
+ /* assign variant specific ops*/
+ cib->cmds->variant_op = cib_native_perform_op;
+ cib->cmds->signon = cib_native_signon;
+ cib->cmds->signoff = cib_native_signoff;
+ cib->cmds->free = cib_native_free;
+ cib->cmds->channel = cib_native_channel;
+ cib->cmds->inputfd = cib_native_inputfd;
+ cib->cmds->msgready = cib_native_msgready;
+ cib->cmds->rcvmsg = cib_native_rcvmsg;
+ cib->cmds->dispatch = cib_native_dispatch;
+
+ cib->cmds->set_connection_dnotify = cib_native_set_connection_dnotify;
+
+ return cib;
+}
+
+int
+cib_native_signon(cib_t* cib, enum cib_conn_type type)
+{
+ int rc = cib_ok;
+ char *uuid_ticket = NULL;
+ struct ha_msg *reg_msg = NULL;
+ cib_native_opaque_t *native = cib->variant_opaque;
+
+ crm_trace("Connecting command channel");
+ if(type == cib_command) {
+ cib->state = cib_connected_command;
+ native->command_channel = init_client_ipc_comms_nodispatch(
+ "cib_rw");
+
+ } else {
+ cib->state = cib_connected_query;
+ native->command_channel = init_client_ipc_comms_nodispatch(
+ "cib_ro");
+ }
+
+ if(native->command_channel == NULL) {
+ crm_err("Connection to command channel failed");
+ rc = cib_connection;
+
+ } else if(native->command_channel->ch_status != IPC_CONNECT) {
+ crm_err("Connection may have succeeded,"
+ " but authentication to command channel failed");
+ rc = cib_authentication;
+ }
+
+ if(rc == cib_ok) {
+ crm_trace("Connecting callback channel");
+/* native->callback_source = init_client_ipc_comms( */
+ native->callback_channel = init_client_ipc_comms(
+ "cib_callback", cib_native_dispatch, cib);
+/* native->callback_channel = native->callback_source->ch; */
+
+ if(native->callback_channel == NULL) {
+ crm_err("Connection to callback channel failed");
+ rc = cib_connection;
+ }
+
+ } else if(rc == cib_ok
+ && native->callback_channel->ch_status != IPC_CONNECT) {
+ crm_err("Connection may have succeeded,"
+ " but authentication to callback channel failed");
+ rc = cib_authentication;
+ }
+
+ if(rc == cib_ok) {
+ const char *msg_type = NULL;
+ crm_trace("Waiting for msg on command channel");
+ reg_msg = msgfromIPC_noauth(native->command_channel);
+
+ msg_type = cl_get_string(reg_msg, F_CIB_OPERATION);
+ if(safe_str_neq(msg_type, CRM_OP_REGISTER) ) {
+ crm_err("Invalid registration message: %s", msg_type);
+ rc = cib_registration_msg;
+
+ } else {
+ const char *tmp_ticket = NULL;
+ crm_trace("Retrieving callback channel ticket");
+ tmp_ticket = cl_get_string(
+ reg_msg, F_CIB_CALLBACK_TOKEN);
+
+ if(tmp_ticket == NULL) {
+ rc = cib_callback_token;
+ } else {
+ uuid_ticket = crm_strdup(tmp_ticket);
+ }
+ }
+
+ ha_msg_del(reg_msg);
+ reg_msg = NULL;
+ }
+
+ if(rc == cib_ok) {
+ crm_trace("Registering callback channel with ticket %s",
+ uuid_ticket);
+ reg_msg = ha_msg_new(2);
+ ha_msg_add(reg_msg, F_CIB_OPERATION, CRM_OP_REGISTER);
+ ha_msg_add(reg_msg, F_CIB_CALLBACK_TOKEN, uuid_ticket);
+ if(msg2ipcchan(reg_msg, native->callback_channel) != HA_OK) {
+ rc = cib_callback_register;
+ }
+ crm_free(uuid_ticket);
+ ha_msg_del(reg_msg);
+
+ }
+ if(rc == cib_ok) {
+ crm_trace("wait for the callback channel setup to complete");
+ reg_msg = msgfromIPC_noauth(native->callback_channel);
+
+ if(reg_msg == NULL) {
+ crm_err("Connection to callback channel not maintined");
+ rc = cib_connection;
+ }
+ ha_msg_del(reg_msg);
+ }
+
+ if(rc == cib_ok) {
+ crm_info("Connection to CIB successful");
+ return cib_ok;
+ }
+ crm_err("Connection to CIB failed: %s", cib_error2string(rc));
+ cib_native_signoff(cib);
+ return rc;
+}
+
+int
+cib_native_signoff(cib_t* cib)
+{
+ cib_native_opaque_t *native = cib->variant_opaque;
+
+ crm_info("Signing out of the CIB Service");
+
+ /* close channels */
+ if (native->command_channel != NULL) {
+ native->command_channel->ops->destroy(
+ native->command_channel);
+ native->command_channel = NULL;
+ }
+ if (native->callback_channel != NULL) {
+ native->callback_channel->ops->destroy(
+ native->callback_channel);
+ native->callback_channel = NULL;
+ }
+ cib->state = cib_disconnected;
+ cib->type = cib_none;
+
+ return cib_ok;
+}
+
+int
+cib_native_free (cib_t* cib)
+{
+ int rc = cib_ok;
+
+ crm_warn("Freeing CIB");
+ if(cib->state != cib_disconnected) {
+ rc = cib_native_signoff(cib);
+ if(rc == cib_ok) {
+ crm_free(cib);
+ }
+ }
+
+ return rc;
+}
+
+IPC_Channel *
+cib_native_channel(cib_t* cib)
+{
+ cib_native_opaque_t *native = NULL;
+ if(cib == NULL) {
+ crm_err("Missing cib object");
+ return NULL;
+ }
+
+ native = cib->variant_opaque;
+
+ if(native != NULL) {
+ return native->callback_channel;
+ }
+
+ crm_err("couldnt find variant specific data in %p", cib);
+ return NULL;
+}
+
+
+int
+cib_native_inputfd(cib_t* cib)
+{
+ IPC_Channel *ch = cib_native_channel(cib);
+ return ch->ops->get_recv_select_fd(ch);
+}
+
+int
+cib_native_perform_op(
+ cib_t *cib, const char *op, const char *section,
+ xmlNodePtr data, xmlNodePtr *output_data, int call_options)
+{
+ int rc = HA_OK;
+
+ size_t calldata_len = 0;
+
+ char *calldata = NULL;
+ const char *output = NULL;
+
+ struct ha_msg *op_msg = NULL;
+ struct ha_msg *op_reply = NULL;
+
+ cib_native_opaque_t *native = cib->variant_opaque;
+
+ if(cib->state == cib_disconnected) {
+ return cib_not_connected;
+ }
+
+ if(output_data != NULL) {
+ *output_data = NULL;
+ }
+
+ op_msg = ha_msg_new(5);
+ if(op == NULL) {
+ crm_err("No operation specified");
+ rc = cib_operation;
+ }
+
+ if(rc == HA_OK) {
+ rc = ha_msg_add(op_msg, F_TYPE, "cib");
+ }
+ if(rc == HA_OK) {
+ rc = ha_msg_add(op_msg, F_CIB_OPERATION, op);
+ }
+ if(rc == HA_OK && section != NULL) {
+ rc = ha_msg_add(op_msg, F_CIB_SECTION, section);
+ }
+ if(rc == HA_OK) {
+ char *tmp = crm_itoa(cib->call_id);
+ rc = ha_msg_add(op_msg, F_CIB_CALLID, tmp);
+ crm_free(tmp);
+ }
+ if(rc == HA_OK) {
+ char *tmp = crm_itoa(call_options);
+ crm_trace("Sending call options: %.8lx, %d, %s",
+ (long)call_options, call_options, tmp);
+ rc = ha_msg_add(op_msg, F_CIB_CALLOPTS, tmp);
+ crm_free(tmp);
+ }
+ if(rc == HA_OK) {
+ calldata = dump_xml_unformatted(data);
+ if(calldata != NULL) {
+ calldata_len = strlen(calldata) + 1;
+ rc = ha_msg_add(op_msg, F_CIB_CALLDATA, calldata);
+ }
+
+ crm_free(calldata);
+ }
+
+ if (rc != HA_OK) {
+ ha_msg_del(op_msg);
+ crm_err("Failed to create CIB operation message");
+ return cib_create_msg;
+ }
+
+ cib->call_id++;
+
+ rc = msg2ipcchan(op_msg, native->command_channel);
+ ha_msg_del(op_msg);
+
+ if (rc != HA_OK) {
+ return cib_send_failed;
+ }
+
+ if( !(call_options & cib_sync_call)) {
+ return cib->call_id - 1;
+ }
+
+ op_reply = msgfromIPC_noauth(native->command_channel);
+ if (op_reply == NULL) {
+ crm_err("No reply message");
+ return cib_reply_failed;
+ }
+
+ rc = cib_ok;
+
+ /* Start processing the reply... */
+ if(cl_get_int(op_reply, F_CIB_RC, &rc) != HA_OK) {
+ rc = cib_return_code;
+ }
+
+ /* eg. op may have been a privelidged action and we are in query mode */
+ if(rc != cib_ok) {
+ ha_msg_del(op_reply);
+ return rc;
+ }
+
+ if(!(call_options & cib_discard_reply)) {
+ output = cl_get_string(op_msg, F_CIB_CALLDATA);
+ }
+
+ if(output != NULL && output_data == NULL) {
+ rc = cib_output_ptr;
+
+ } else if(output != NULL) {
+ *output_data = string2xml(output);
+ if(*output_data == NULL) {
+ rc = cib_output_data;
+ }
+ } else {
+ crm_debug("No output in reply to \"%s\" command %d",
+ op, cib->call_id - 1);
+ }
+
+ ha_msg_del(op_reply);
+
+ return rc;
+}
+
+gboolean
+cib_native_msgready(cib_t* cib)
+{
+ IPC_Channel *ch = NULL;
+ cib_native_opaque_t *native = NULL;
+
+ if (cib == NULL) {
+ crm_err("No CIB!");
+ return FALSE;
+ }
+
+ native = cib->variant_opaque;
+
+ ch = cib_native_channel(cib);
+ if (ch == NULL) {
+ crm_err("No channel");
+ return FALSE;
+ }
+
+ if(native->command_channel->ops->is_message_pending(
+ native->command_channel)) {
+ crm_warn("Message pending on command channel");
+ }
+ if(native->callback_channel->ops->is_message_pending(
+ native->callback_channel)) {
+ crm_info("Message pending on callback channel");
+ return TRUE;
+ }
+ crm_info("No message pending");
+ return FALSE;
+}
+
+int
+cib_native_rcvmsg(cib_t* cib, int blocking)
+{
+ const char *type = NULL;
+ struct ha_msg* msg = NULL;
+ IPC_Channel *ch = cib_native_channel(cib);
+
+ /* if it is not blocking mode and no message in the channel, return */
+ if (blocking == 0 && cib_native_msgready(cib) == FALSE) {
+ crm_debug("No message ready and non-blocking...");
+ return 0;
+
+ } else if (cib_native_msgready(cib) == FALSE) {
+ crm_debug("Waiting for message from CIB service...");
+ ch->ops->waitin(ch);
+ }
+
+ /* get the message */
+ msg = msgfromIPC_noauth(ch);
+ if (msg == NULL) {
+ crm_warn("Received a NULL msg from CIB service.");
+ return 0;
+ }
+
+ /* do callbacks */
+ type = cl_get_string(msg, F_TYPE);
+ crm_trace("Activating %s callbacks...", type);
+
+ if(cib->op_callback == NULL) {
+ crm_debug("No OP callback set, ignoring reply");
+
+ } else {
+ int rc = 0;
+ int call_id = 0;
+ xmlNodePtr output = NULL;
+ const char *output_s = NULL;
+
+ cl_get_int(msg, F_CIB_CALLID, &call_id);
+ cl_get_int(msg, F_CIB_RC, &rc);
+ output_s = cl_get_string(msg, F_CIB_CALLDATA);
+ if(output_s != NULL) {
+ output = string2xml(output_s);
+ }
+
+ cib->op_callback(msg, call_id, rc, output);
+
+ crm_trace("OP callback activated.");
+ }
+
+ ha_msg_del(msg);
+
+ return 1;
+}
+
+
+gboolean
+cib_native_dispatch(IPC_Channel *channel, gpointer user_data)
+{
+ int lpc = 0;
+ cib_t *cib = user_data;
+
+ crm_debug("Received callback");
+
+ if(user_data == NULL){
+ crm_err("user_data field must contain the CIB struct");
+ return FALSE;
+ }
+
+ while(cib_native_msgready(cib)) {
+ lpc++;
+ /* invoke the callbacks but dont block */
+ if(cib_native_rcvmsg(cib, 0) < 1) {
+ break;
+ }
+ }
+
+ crm_debug("%d CIB messages dispatched", lpc);
+
+ if (channel && (channel->ch_status == IPC_DISCONNECT)) {
+ crm_crit("Lost connection to the CIB service.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int cib_native_set_connection_dnotify(
+ cib_t *cib, void (*dnotify)(gpointer user_data))
+{
+ cib_native_opaque_t *native = NULL;
+
+ if (cib == NULL) {
+ crm_err("No CIB!");
+ return FALSE;
+ }
+
+ native = cib->variant_opaque;
+
+#if 0
+ if(dnotify == NULL) {
+ crm_warn("Setting dnotify back to default value");
+ native->callback_source->dnotify =
+ default_ipc_connection_destroy;
+
+ } else {
+ crm_debug("Setting dnotify");
+ native->callback_source->dnotify = dnotify;
+ }
+#endif
+ return cib_ok;
+}
+
+

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:43 PM (2 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2001247
Default Alt Text
(37 KB)

Event Timeline