Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624724
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
37 KB
Referenced Files
None
Subscribers
None
View Options
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, ¤t_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
Details
Attached
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)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment