Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/include/crm/cib.h b/include/crm/cib.h
index d723000c18..f72c6cb132 100644
--- a/include/crm/cib.h
+++ b/include/crm/cib.h
@@ -1,402 +1,403 @@
/* $Id: cib.h,v 1.43 2006/06/22 15:11:56 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* 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.1 of the License, or (at your option) any later version.
*
* This software 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CIB__H
#define CIB__H
#include <portability.h>
#include <clplumbing/ipc.h>
#include <crm/common/ipc.h>
#include <crm/common/xml.h>
#include <ha_msg.h>
#define CIB_FEATURE_SET "1.3"
#define USE_PESKY_FRAGMENTS 1
#define CIB_OPTIONS_FIRST "cib-bootstrap-options"
/* use compare_version() for doing comparisons */
enum cib_variant {
cib_native,
cib_database,
cib_edir
};
enum cib_state {
cib_connected_command,
cib_connected_query,
cib_disconnected
};
enum cib_conn_type {
cib_command,
cib_query,
cib_query_synchronous,
cib_command_synchronous,
cib_no_connection
};
enum cib_call_options {
cib_none = 0x00000000,
cib_verbose = 0x00000001,
cib_discard_reply = 0x00000010,
cib_scope_local = 0x00000100,
cib_sync_call = 0x00001000,
cib_inhibit_notify = 0x00010000,
cib_quorum_override = 0x00100000,
cib_inhibit_bcast = 0x01000000,
cib_force_diff = 0x10000000
};
#define cib_default_options = cib_none
enum cib_errors {
cib_ok = 0,
cib_operation = -1,
cib_create_msg = -2,
cib_not_connected = -3,
cib_not_authorized = -4,
cib_send_failed = -5,
cib_reply_failed = -6,
cib_return_code = -7,
cib_output_ptr = -8,
cib_output_data = -9,
cib_connection = -10,
cib_authentication = -11,
cib_missing = -12,
cib_variant = -28,
CIBRES_MISSING_ID = -13,
CIBRES_MISSING_TYPE = -14,
CIBRES_MISSING_FIELD = -15,
CIBRES_OBJTYPE_MISMATCH = -16,
CIBRES_CORRUPT = -17,
CIBRES_OTHER = -18,
cib_unknown = -19,
cib_STALE = -20,
cib_EXISTS = -21,
cib_NOTEXISTS = -22,
cib_ACTIVATION = -23,
cib_NOSECTION = -24,
cib_NOOBJECT = -25,
cib_NOPARENT = -26,
cib_NODECOPY = -27,
cib_NOTSUPPORTED = -29,
cib_registration_msg = -30,
cib_callback_token = -31,
cib_callback_register = -32,
cib_msg_field_add = -33,
cib_client_gone = -34,
cib_not_master = -35,
cib_client_corrupt = -36,
cib_master_timeout = -37,
cib_revision_unsupported= -38,
cib_revision_unknown = -39,
cib_missing_data = -40,
cib_remote_timeout = -41,
cib_no_quorum = -42,
cib_diff_failed = -43,
cib_diff_resync = -44,
cib_old_data = -45,
cib_id_check = -46,
cib_dtd_validation = -47,
cib_bad_section = -48,
cib_bad_digest = -49,
cib_bad_permissions = -50,
- cib_bad_config = -51
+ cib_bad_config = -51,
+ cib_invalid_argument = -52
};
enum cib_update_op {
CIB_UPDATE_OP_NONE = 0,
CIB_UPDATE_OP_ADD,
CIB_UPDATE_OP_MODIFY,
CIB_UPDATE_OP_DELETE,
CIB_UPDATE_OP_MAX
};
enum cib_section {
cib_section_none,
cib_section_all,
cib_section_nodes,
cib_section_constraints,
cib_section_resources,
cib_section_crmconfig,
cib_section_status
};
#define CIB_OP_SLAVE "cib_slave"
#define CIB_OP_SLAVEALL "cib_slave_all"
#define CIB_OP_MASTER "cib_master"
#define CIB_OP_SYNC "cib_sync"
#define CIB_OP_SYNC_ONE "cib_sync_one"
#define CIB_OP_ISMASTER "cib_ismaster"
#define CIB_OP_BUMP "cib_bump"
#define CIB_OP_QUERY "cib_query"
#define CIB_OP_CREATE "cib_create"
#define CIB_OP_UPDATE "cib_update"
#define CIB_OP_MODIFY "cib_modify"
#define CIB_OP_DELETE "cib_delete"
#define CIB_OP_DELETE_ALT "cib_delete_alt"
#define CIB_OP_ERASE "cib_erase"
#define CIB_OP_REPLACE "cib_replace"
#define CIB_OP_NOTIFY "cib_notify"
#define CIB_OP_APPLY_DIFF "cib_apply_diff"
#define F_CIB_CLIENTID "cib_clientid"
#define F_CIB_CALLOPTS "cib_callopt"
#define F_CIB_CALLID "cib_callid"
#define F_CIB_CALLDATA "cib_calldata"
#define F_CIB_OPERATION "cib_op"
#define F_CIB_ISREPLY "cib_isreplyto"
#define F_CIB_SECTION "cib_section"
#define F_CIB_HOST "cib_host"
#define F_CIB_RC "cib_rc"
#define F_CIB_DELEGATED "cib_delegated_from"
#define F_CIB_OBJID "cib_object"
#define F_CIB_OBJTYPE "cib_object_type"
#define F_CIB_EXISTING "cib_existing_object"
#define F_CIB_SEENCOUNT "cib_seen"
#define F_CIB_TIMEOUT "cib_timeout"
#define F_CIB_UPDATE "cib_update"
#define F_CIB_CALLBACK_TOKEN "cib_callback_token"
#define F_CIB_GLOBAL_UPDATE "cib_update"
#define F_CIB_UPDATE_RESULT "cib_update_result"
#define F_CIB_CLIENTNAME "cib_clientname"
#define F_CIB_NOTIFY_TYPE "cib_notify_type"
#define F_CIB_NOTIFY_ACTIVATE "cib_notify_activate"
#define F_CIB_UPDATE_DIFF "cib_update_diff"
#define T_CIB "cib"
#define T_CIB_NOTIFY "cib_notify"
/* notify sub-types */
#define T_CIB_PRE_NOTIFY "cib_pre_notify"
#define T_CIB_POST_NOTIFY "cib_post_notify"
#define T_CIB_UPDATE_CONFIRM "cib_update_confirmation"
#define T_CIB_DIFF_NOTIFY "cib_diff_notify"
#define T_CIB_REPLACE_NOTIFY "cib_refresh_notify"
#define cib_channel_ro "cib_ro"
#define cib_channel_rw "cib_rw"
#define cib_channel_callback "cib_callback"
#define cib_channel_ro_synchronous "cib_ro_syncronous"
#define cib_channel_rw_synchronous "cib_rw_syncronous"
typedef struct cib_s cib_t;
typedef struct cib_api_operations_s
{
int (*variant_op)(
cib_t *cib, const char *op, const char *host,
const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int (*signon) (
cib_t *cib, const char *name, enum cib_conn_type type);
int (*signoff)(cib_t *cib);
int (*free) (cib_t *cib);
int (*set_op_callback)(
cib_t *cib, void (*callback)(
const HA_Message *msg, int callid ,
int rc, crm_data_t *output));
int (*add_notify_callback)(
cib_t *cib, const char *event, void (*callback)(
const char *event, HA_Message *msg));
int (*del_notify_callback)(
cib_t *cib, const char *event, void (*callback)(
const char *event, HA_Message *msg));
int (*set_connection_dnotify)(
cib_t *cib, void (*dnotify)(gpointer user_data));
IPC_Channel *(*channel)(cib_t* cib);
int (*inputfd)(cib_t* cib);
int (*noop)(cib_t *cib, int call_options);
int (*ping)(
cib_t *cib, crm_data_t **output_data, int call_options);
int (*query)(cib_t *cib, const char *section,
crm_data_t **output_data, int call_options);
int (*query_from)(
cib_t *cib, const char *host, const char *section,
crm_data_t **output_data, int call_options);
int (*is_master) (cib_t *cib);
int (*set_master)(cib_t *cib, int call_options);
int (*set_slave) (cib_t *cib, int call_options);
int (*set_slave_all)(cib_t *cib, int call_options);
int (*sync)(cib_t *cib, const char *section, int call_options);
int (*sync_from)(
cib_t *cib, const char *host, const char *section,
int call_options);
int (*bump_epoch)(cib_t *cib, int call_options);
int (*create)(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int (*modify)(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int (*update)(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int (*replace)(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int (*delete)(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int (*delete_absolute)(
cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int (*erase)(
cib_t *cib, crm_data_t **output_data, int call_options);
int (*quit)(cib_t *cib, int call_options);
gboolean (*msgready)(cib_t* cib);
int (*rcvmsg)(cib_t* cib, int blocking);
gboolean (*dispatch)(IPC_Channel *channel, gpointer user_data);
int (*register_callback)(
cib_t* cib, const char *callback, int enabled);
} cib_api_operations_t;
struct cib_s
{
enum cib_state state;
enum cib_conn_type type;
int call_id;
int call_timeout;
void *variant_opaque;
GList *notify_list;
void (*op_callback)(const HA_Message *msg, int call_id,
int rc, crm_data_t *output);
cib_api_operations_t *cmds;
};
typedef struct cib_notify_client_s
{
const char *event;
const char *obj_id; /* implement one day */
const char *obj_type; /* implement one day */
void (*callback)(
const char *event, HA_Message *msg);
} cib_notify_client_t;
typedef struct cib_callback_client_s
{
void (*callback)(
const HA_Message*, int, int, crm_data_t*, void*);
void *user_data;
gboolean only_success;
} cib_callback_client_t;
/* Core functions */
extern cib_t *cib_new(void);
extern void cib_delete(cib_t *cib);
extern gboolean startCib(const char *filename);
extern crm_data_t *get_cib_copy(cib_t *cib);
extern crm_data_t *cib_get_generation(cib_t *cib);
extern int cib_compare_generation(crm_data_t *left, crm_data_t *right);
extern gboolean add_cib_op_callback(
int call_id, gboolean only_success, void *user_data,
void (*callback)(const HA_Message*, int, int, crm_data_t*,void*));
extern void remove_cib_op_callback(int call_id, gboolean all_callbacks);
extern int num_cib_op_callbacks(void);
/* Utility functions */
extern crm_data_t *get_object_root(const char *object_type,crm_data_t *the_root);
extern crm_data_t *create_cib_fragment_adv(
crm_data_t *update, const char *section, const char *source);
extern char *cib_pluralSection(const char *a_section);
extern const char *get_crm_option(
crm_data_t *cib, const char *name, gboolean do_warn);
/* Error Interpretation*/
extern const char *cib_error2string(enum cib_errors);
extern const char *cib_op2string(enum cib_update_op);
extern crm_data_t *createEmptyCib(void);
extern gboolean verifyCibXml(crm_data_t *cib);
extern int cib_section2enum(const char *a_section);
#define create_cib_fragment(update,cib_section) create_cib_fragment_adv(update, cib_section, __FUNCTION__)
extern crm_data_t *diff_cib_object(
crm_data_t *old, crm_data_t *new,gboolean suppress);
extern gboolean apply_cib_diff(
crm_data_t *old, crm_data_t *diff, crm_data_t **new);
extern void log_cib_diff(int log_level, crm_data_t *diff, const char *function);
extern gboolean cib_diff_version_details(
crm_data_t *diff, int *admin_epoch, int *epoch, int *updates,
int *_admin_epoch, int *_epoch, int *_updates);
extern gboolean cib_version_details(
crm_data_t *cib, int *admin_epoch, int *epoch, int *updates);
extern enum cib_errors update_attr(
cib_t *the_cib, int call_options,
const char *section, const char *node_uuid, const char *set_name,
const char *attr_id, const char *attr_name, const char *attr_value);
extern crm_data_t *find_attr_details(crm_data_t *xml_search, const char *node_uuid,
const char *set_name, const char *attr_id, const char *attr_name);
extern enum cib_errors read_attr(
cib_t *the_cib,
const char *section, const char *node_uuid, const char *set_name,
const char *attr_id, const char *attr_name, char **attr_value);
extern enum cib_errors delete_attr(
cib_t *the_cib, int options,
const char *section, const char *node_uuid, const char *set_name,
const char *attr_id, const char *attr_name, const char *attr_value);
extern enum cib_errors query_node_uuid(
cib_t *the_cib, const char *uname, char **uuid);
extern enum cib_errors query_node_uname(
cib_t *the_cib, const char *uuid, char **uname);
extern enum cib_errors query_standby(cib_t *the_cib, const char *uuid,
char **scope, char **standby_value);
extern enum cib_errors set_standby(
cib_t *the_cib,
const char *uuid, const char *scope, const char *standby_value);
enum cib_errors delete_standby(
cib_t *the_cib,
const char *uuid, const char *scope, const char *standby_value);
extern const char *feature_set(crm_data_t *xml_obj);
#endif
diff --git a/lib/crm/cib/cib_client.c b/lib/crm/cib/cib_client.c
index 9a6397671a..8afacd9cfe 100755
--- a/lib/crm/cib/cib_client.c
+++ b/lib/crm/cib/cib_client.c
@@ -1,1518 +1,1521 @@
/*
* 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>
#include <cib_private.h>
/* short term hack to reduce callback messages */
typedef struct cib_native_opaque_s
{
IPC_Channel *command_channel;
IPC_Channel *callback_channel;
GCHSource *callback_source;
} cib_native_opaque_t;
GHashTable *cib_op_callback_table = NULL;
gboolean verify_cib_cmds(cib_t *cib);
int cib_client_set_op_callback(
cib_t *cib, void (*callback)(const struct ha_msg *msg, int call_id,
int rc, crm_data_t *output));
int cib_client_noop(cib_t *cib, int call_options);
int cib_client_ping(cib_t *cib, crm_data_t **output_data, int call_options);
int cib_client_query(cib_t *cib, const char *section,
crm_data_t **output_data, int call_options);
int cib_client_query_from(cib_t *cib, const char *host, const char *section,
crm_data_t **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);
int cib_client_is_master(cib_t *cib);
int cib_client_set_slave(cib_t *cib, int call_options);
int cib_client_set_slave_all(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, crm_data_t *data,
crm_data_t **output_data, int call_options);
int cib_client_modify(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int cib_client_update(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int cib_client_replace(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int cib_client_delete(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int cib_client_delete_absolute(
cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **output_data, int call_options);
int cib_client_erase(
cib_t *cib, crm_data_t **output_data, int call_options);
int cib_client_quit(cib_t *cib, int call_options);
int cib_client_add_notify_callback(
cib_t *cib, const char *event, void (*callback)(
const char *event, struct ha_msg *msg));
int cib_client_del_notify_callback(
cib_t *cib, const char *event, void (*callback)(
const char *event, struct ha_msg *msg));
gint ciblib_GCompareFunc(gconstpointer a, gconstpointer b);
extern cib_t *cib_native_new(cib_t *cib);
extern void cib_native_delete(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;
}
if(cib_op_callback_table != NULL) {
g_hash_table_destroy(cib_op_callback_table);
cib_op_callback_table = NULL;
}
if(cib_op_callback_table == NULL) {
cib_op_callback_table = g_hash_table_new_full(
g_direct_hash, g_direct_equal,
NULL, g_hash_destroy_str);
}
crm_malloc0(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_list = NULL;
/* the rest will get filled in by the variant constructor */
crm_malloc0(new_cib->cmds, sizeof(cib_api_operations_t));
new_cib->cmds->set_op_callback = cib_client_set_op_callback;
new_cib->cmds->add_notify_callback = cib_client_add_notify_callback;
new_cib->cmds->del_notify_callback = cib_client_del_notify_callback;
new_cib->cmds->noop = cib_client_noop;
new_cib->cmds->ping = cib_client_ping;
new_cib->cmds->query = cib_client_query;
new_cib->cmds->sync = cib_client_sync;
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_master = cib_client_set_master;
new_cib->cmds->set_slave = cib_client_set_slave;
new_cib->cmds->set_slave_all = cib_client_set_slave_all;
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->update = cib_client_update;
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;
new_cib->cmds->delete_absolute = cib_client_delete_absolute;
cib_native_new(new_cib);
if(verify_cib_cmds(new_cib) == FALSE) {
return NULL;
}
return new_cib;
}
void
cib_delete(cib_t *cib)
{
cib_native_delete(cib);
g_hash_table_destroy(cib_op_callback_table);
crm_free(cib->cmds);
crm_free(cib);
}
int
cib_client_set_op_callback(
cib_t *cib, void (*callback)(const struct ha_msg *msg, int call_id,
int rc, crm_data_t *output))
{
if(callback == NULL) {
crm_info("Un-Setting operation callback");
} else {
crm_debug_3("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, NULL, call_options);
}
int cib_client_ping(cib_t *cib, crm_data_t **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,NULL, output_data, call_options);
}
int cib_client_query(cib_t *cib, const char *section,
crm_data_t **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,
crm_data_t **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, CIB_OP_QUERY, host, section,
NULL, output_data, call_options);
}
int 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, CIB_OP_ISMASTER, NULL, 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, CIB_OP_SLAVE, NULL,NULL,NULL,NULL, call_options);
}
int cib_client_set_slave_all(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, CIB_OP_SLAVEALL, NULL,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;
}
crm_debug_3("Adding cib_scope_local to options");
return cib->cmds->variant_op(
cib, CIB_OP_MASTER, NULL,NULL,NULL,NULL,
call_options|cib_scope_local);
}
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, CIB_OP_BUMP, NULL, 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)
{
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, CIB_OP_SYNC, host, section, NULL, NULL, call_options);
}
int cib_client_create(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **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, CIB_OP_CREATE, NULL, section,
data, output_data, call_options);
}
int cib_client_modify(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **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, CIB_OP_MODIFY, NULL, section,
data, output_data, call_options);
}
int cib_client_update(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **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, CIB_OP_UPDATE, NULL, section,
data, output_data, call_options);
}
int cib_client_replace(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **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;
} else if(data == NULL) {
return cib_missing_data;
}
return cib->cmds->variant_op(cib, CIB_OP_REPLACE, NULL, section,
data, output_data, call_options);
}
int cib_client_delete(cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **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, CIB_OP_DELETE, NULL, section,
data, output_data, call_options);
}
int cib_client_delete_absolute(
cib_t *cib, const char *section, crm_data_t *data,
crm_data_t **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, CIB_OP_DELETE_ALT, NULL, section,
data, output_data, call_options);
}
int cib_client_erase(
cib_t *cib, crm_data_t **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, CIB_OP_ERASE, NULL, 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, NULL, call_options);
}
int cib_client_add_notify_callback(
cib_t *cib, const char *event, void (*callback)(
const char *event, struct ha_msg *msg))
{
GList *list_item = NULL;
cib_notify_client_t *new_client = NULL;
crm_debug_2("Adding callback for %s events (%d)",
event, g_list_length(cib->notify_list));
crm_malloc0(new_client, sizeof(cib_notify_client_t));
new_client->event = event;
new_client->callback = callback;
list_item = g_list_find_custom(
cib->notify_list, new_client, ciblib_GCompareFunc);
if(list_item != NULL) {
crm_warn("Callback already present");
} else {
cib->notify_list = g_list_append(
cib->notify_list, new_client);
cib->cmds->register_callback(cib, event, 1);
crm_debug_3("Callback added (%d)", g_list_length(cib->notify_list));
}
return cib_ok;
}
int cib_client_del_notify_callback(
cib_t *cib, const char *event, void (*callback)(
const char *event, struct ha_msg *msg))
{
GList *list_item = NULL;
cib_notify_client_t *new_client = NULL;
crm_debug("Removing callback for %s events", event);
crm_malloc0(new_client, sizeof(cib_notify_client_t));
new_client->event = event;
new_client->callback = callback;
list_item = g_list_find_custom(
cib->notify_list, new_client, ciblib_GCompareFunc);
cib->cmds->register_callback(cib, event, 0);
if(list_item != NULL) {
cib_notify_client_t *list_client = list_item->data;
cib->notify_list =
g_list_remove(cib->notify_list, list_client);
crm_free(list_client);
crm_debug_3("Removed callback");
} else {
crm_debug_3("Callback not present");
}
crm_free(new_client);
return cib_ok;
}
gint ciblib_GCompareFunc(gconstpointer a, gconstpointer b)
{
const cib_notify_client_t *a_client = a;
const cib_notify_client_t *b_client = b;
if(a_client->callback == b_client->callback
&& safe_str_neq(a_client->event, b_client->event)) {
return 0;
} else if(((long)a_client->callback) < ((long)b_client->callback)) {
return -1;
}
return 1;
}
gboolean
add_cib_op_callback(
int call_id, gboolean only_success, void *user_data,
void (*callback)(const HA_Message*, int, int, crm_data_t*,void*))
{
cib_callback_client_t *blob = NULL;
if(call_id < 0) {
crm_warn("CIB call failed: %s", cib_error2string(call_id));
if(only_success == FALSE) {
callback(NULL, call_id, call_id, NULL, user_data);
}
return FALSE;
}
crm_malloc0(blob, sizeof(cib_callback_client_t));
blob->only_success = only_success;
blob->user_data = user_data;
blob->callback = callback;
g_hash_table_insert(
cib_op_callback_table, GINT_TO_POINTER(call_id), blob);
return TRUE;
}
void
remove_cib_op_callback(int call_id, gboolean all_callbacks)
{
if(all_callbacks) {
if(cib_op_callback_table != NULL) {
g_hash_table_destroy(cib_op_callback_table);
}
cib_op_callback_table = g_hash_table_new_full(
g_direct_hash, g_direct_equal,
NULL, g_hash_destroy_str);
} else {
g_hash_table_remove(
cib_op_callback_table,
GINT_TO_POINTER(call_id));
}
}
int
num_cib_op_callbacks(void)
{
if(cib_op_callback_table == NULL) {
return 0;
}
return g_hash_table_size(cib_op_callback_table);
}
char *
cib_pluralSection(const char *a_section)
{
char *a_section_parent = NULL;
if (a_section == NULL) {
a_section_parent = crm_strdup("all");
} else if(strcasecmp(a_section, XML_TAG_CIB) == 0) {
a_section_parent = crm_strdup("all");
} else if(strcasecmp(a_section, XML_CIB_TAG_NODE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_NODES);
} else if(strcasecmp(a_section, XML_CIB_TAG_STATE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_STATUS);
} else if(strcasecmp(a_section, XML_CIB_TAG_CONSTRAINT) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, XML_CONS_TAG_RSC_LOCATION) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, XML_CONS_TAG_RSC_DEPEND) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, XML_CONS_TAG_RSC_ORDER) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, "resource") == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_RESOURCE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_GROUP) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_INCARNATION) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_NVPAIR) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CRMCONFIG);
} else if(strcasecmp(a_section, XML_TAG_ATTR_SETS) == 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_debug_2("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_bad_permissions:
error_msg = "bad permissions for the on-disk configuration. shutdown heartbeat and repair.";
break;
case cib_bad_digest:
error_msg = "the on-disk configuration was manually altered. shutdown heartbeat and repair.";
break;
case cib_bad_config:
error_msg = "the on-disk configuration is not valid";
break;
case cib_msg_field_add:
error_msg = "failed adding field to cib message";
break;
case cib_id_check:
error_msg = "missing id or id-collision detected";
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/attribute 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;
case cib_not_master:
error_msg = "Local service is not the master instance";
break;
case cib_client_corrupt:
error_msg = "Service client not valid";
break;
case cib_remote_timeout:
error_msg = "Remote node did not respond";
break;
case cib_master_timeout:
error_msg = "No master service is currently active";
break;
case cib_revision_unsupported:
error_msg = "The required CIB revision number is not supported";
break;
case cib_revision_unknown:
error_msg = "The CIB revision number could not be determined";
break;
case cib_missing_data:
error_msg = "Required data for this CIB API call not found";
break;
case cib_no_quorum:
error_msg = "Write requires quorum";
break;
case cib_diff_failed:
error_msg = "Application of an update diff failed";
break;
case cib_diff_resync:
error_msg = "Application of an update diff failed, requesting a full refresh";
break;
case cib_bad_section:
error_msg = "Invalid CIB section specified";
break;
case cib_old_data:
error_msg = "Update was older than existing configuration";
break;
case cib_dtd_validation:
error_msg = "Update does conform to the DTD in "HA_LIBDIR"/heartbeat/crm.dtd";
break;
+ case cib_invalid_argument:
+ error_msg = "Invalid argument";
+ 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_update_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_UPDATE_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 || strcasecmp(a_section, "all") == 0) {
return cib_section_all;
} else if(strcasecmp(a_section, XML_CIB_TAG_NODES) == 0) {
return cib_section_nodes;
} else if(strcasecmp(a_section, XML_CIB_TAG_STATUS) == 0) {
return cib_section_status;
} else if(strcasecmp(a_section, XML_CIB_TAG_CONSTRAINTS) == 0) {
return cib_section_constraints;
} else if(strcasecmp(a_section, XML_CIB_TAG_RESOURCES) == 0) {
return cib_section_resources;
} else if(strcasecmp(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(crm_data_t *left, crm_data_t *right)
{
int lpc = 0;
const char *attributes[] = {
XML_ATTR_GENERATION_ADMIN,
XML_ATTR_GENERATION,
XML_ATTR_NUMUPDATES,
XML_ATTR_NUMPEERS
};
crm_log_xml_debug_3(left, "left");
crm_log_xml_debug_3(right, "right");
for(lpc = 0; lpc < DIMOF(attributes); lpc++) {
int int_elem_l = -1;
int int_elem_r = -1;
const char *elem_r = NULL;
const char *elem_l = crm_element_value(left, attributes[lpc]);
if(right != NULL) {
elem_r = crm_element_value(right, attributes[lpc]);
}
if(elem_l != NULL) { int_elem_l = crm_parse_int(elem_l, NULL); }
if(elem_r != NULL) { int_elem_r = crm_parse_int(elem_r, NULL); }
if(int_elem_l < int_elem_r) {
crm_debug_2("%s (%s < %s)", attributes[lpc],
crm_str(elem_l), crm_str(elem_r));
return -1;
} else if(int_elem_l > int_elem_r) {
crm_debug_2("%s (%s > %s)", attributes[lpc],
crm_str(elem_l), crm_str(elem_r));
return 1;
}
}
return 0;
}
crm_data_t*
get_cib_copy(cib_t *cib)
{
crm_data_t *xml_cib;
#if CRM_DEPRECATED_SINCE_2_0_4
crm_data_t *xml_cib_copy;
#endif
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;
} else if(xml_cib == NULL) {
crm_err("The CIB result was empty");
return NULL;
}
if(safe_str_eq(crm_element_name(xml_cib), XML_TAG_CIB)) {
return xml_cib;
#if CRM_DEPRECATED_SINCE_2_0_4
} else {
xml_cib_copy = copy_xml(
find_xml_node(xml_cib, XML_TAG_CIB, TRUE));
free_xml(xml_cib);
return xml_cib_copy;
#endif
}
free_xml(xml_cib);
return NULL;
}
crm_data_t*
cib_get_generation(cib_t *cib)
{
crm_data_t *the_cib = get_cib_copy(cib);
crm_data_t *generation = create_xml_node(
NULL, XML_CIB_TAG_GENERATION_TUPPLE);
if(the_cib != NULL) {
copy_in_properties(generation, the_cib);
free_xml(the_cib);
}
return generation;
}
gboolean
apply_cib_diff(crm_data_t *old, crm_data_t *diff, crm_data_t **new)
{
gboolean result = TRUE;
const char *value = NULL;
int this_updates = 0;
int this_epoch = 0;
int this_admin_epoch = 0;
int diff_add_updates = 0;
int diff_add_epoch = 0;
int diff_add_admin_epoch = 0;
int diff_del_updates = 0;
int diff_del_epoch = 0;
int diff_del_admin_epoch = 0;
CRM_CHECK(diff != NULL, return FALSE);
CRM_CHECK(old != NULL, return FALSE);
value = crm_element_value(old, XML_ATTR_GENERATION_ADMIN);
this_admin_epoch = crm_parse_int(value, "0");
crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION_ADMIN,
this_admin_epoch, value);
value = crm_element_value(old, XML_ATTR_GENERATION);
this_epoch = crm_parse_int(value, "0");
crm_debug_3("%s=%d (%s)", XML_ATTR_GENERATION, this_epoch, value);
value = crm_element_value(old, XML_ATTR_NUMUPDATES);
this_updates = crm_parse_int(value, "0");
crm_debug_3("%s=%d (%s)", XML_ATTR_NUMUPDATES, this_updates, value);
cib_diff_version_details(
diff,
&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
value = NULL;
if(result && diff_del_admin_epoch != this_admin_epoch) {
value = XML_ATTR_GENERATION_ADMIN;
result = FALSE;
crm_debug_3("%s=%d", value, diff_del_admin_epoch);
} else if(result && diff_del_epoch != this_epoch) {
value = XML_ATTR_GENERATION;
result = FALSE;
crm_debug_3("%s=%d", value, diff_del_epoch);
} else if(result && diff_del_updates != this_updates) {
value = XML_ATTR_NUMUPDATES;
result = FALSE;
crm_debug_3("%s=%d", value, diff_del_updates);
}
if(result) {
int len = 0;
crm_data_t *tmp = NULL;
crm_data_t *diff_copy = copy_xml(diff);
tmp = find_xml_node(diff_copy, "diff-removed", TRUE);
if(tmp != NULL) {
len = tmp->nfields;
cl_msg_remove(tmp, XML_ATTR_GENERATION_ADMIN);
cl_msg_remove(tmp, XML_ATTR_GENERATION);
cl_msg_remove(tmp, XML_ATTR_NUMUPDATES);
}
tmp = find_xml_node(diff_copy, "diff-added", TRUE);
if(tmp != NULL) {
len = tmp->nfields;
cl_msg_remove(tmp, XML_ATTR_GENERATION_ADMIN);
cl_msg_remove(tmp, XML_ATTR_GENERATION);
cl_msg_remove(tmp, XML_ATTR_NUMUPDATES);
}
result = apply_xml_diff(old, diff_copy, new);
free_xml(diff_copy);
} else {
crm_err("target and diff %s values didnt match", value);
}
return result;
}
crm_data_t *
diff_cib_object(crm_data_t *old_cib, crm_data_t *new_cib, gboolean suppress)
{
crm_data_t *diff = diff_xml_object(old_cib, new_cib, suppress);
crm_data_t *dest = NULL;
crm_data_t *src = NULL;
const char *name = NULL;
const char *value = NULL;
/* add complete version information */
src = old_cib;
dest = find_xml_node(diff, "diff-removed", FALSE);
if(src != NULL && dest != NULL) {
name = XML_ATTR_GENERATION_ADMIN;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_GENERATION;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_NUMUPDATES;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
}
src = new_cib;
dest = find_xml_node(diff, "diff-added", FALSE);
if(src != NULL && dest != NULL) {
name = XML_ATTR_GENERATION_ADMIN;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_GENERATION;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
name = XML_ATTR_NUMUPDATES;
value = crm_element_value(src, name);
if(value == NULL) {
value = "0";
}
crm_xml_add(dest, name, value);
}
return diff;
}
void
log_cib_diff(int log_level, crm_data_t *diff, const char *function)
{
int add_updates = 0;
int add_epoch = 0;
int add_admin_epoch = 0;
int del_updates = 0;
int del_epoch = 0;
int del_admin_epoch = 0;
if(diff == NULL) {
return;
}
cib_diff_version_details(
diff, &add_admin_epoch, &add_epoch, &add_updates,
&del_admin_epoch, &del_epoch, &del_updates);
if(add_updates != del_updates) {
do_crm_log(log_level, "%s: Diff: --- %d.%d.%d", function,
del_admin_epoch, del_epoch, del_updates);
do_crm_log(log_level, "%s: Diff: +++ %d.%d.%d", function,
add_admin_epoch, add_epoch, add_updates);
} else if(diff != NULL) {
do_crm_log(log_level,
"%s: Local-only Change: %d.%d.%d", function,
add_admin_epoch, add_epoch, add_updates);
}
log_xml_diff(log_level, diff, function);
}
gboolean
cib_version_details(
crm_data_t *cib, int *admin_epoch, int *epoch, int *updates)
{
const char *value = NULL;
if(cib == NULL) {
*admin_epoch = -1;
*epoch = -1;
*updates = -1;
return FALSE;
} else {
value = crm_element_value(cib, XML_ATTR_GENERATION_ADMIN);
*admin_epoch = crm_parse_int(value, "-1");
value = crm_element_value(cib, XML_ATTR_GENERATION);
*epoch = crm_parse_int(value, "-1");
value = crm_element_value(cib, XML_ATTR_NUMUPDATES);
*updates = crm_parse_int(value, "-1");
}
return TRUE;
}
gboolean
cib_diff_version_details(
crm_data_t *diff, int *admin_epoch, int *epoch, int *updates,
int *_admin_epoch, int *_epoch, int *_updates)
{
crm_data_t *tmp = NULL;
tmp = find_xml_node(diff, "diff-added", FALSE);
cib_version_details(tmp, admin_epoch, epoch, updates);
tmp = find_xml_node(diff, "diff-removed", FALSE);
cib_version_details(tmp, _admin_epoch, _epoch, _updates);
return TRUE;
}
/*
* The caller should never free the return value
*/
crm_data_t*
get_object_root(const char *object_type, crm_data_t *the_root)
{
const char *node_stack[2];
crm_data_t *tmp_node = NULL;
if(the_root == NULL) {
crm_err("CIB root object was NULL");
return NULL;
}
node_stack[0] = XML_CIB_TAG_CONFIGURATION;
node_stack[1] = object_type;
if(object_type == NULL
|| strlen(object_type) == 0
|| safe_str_eq(XML_CIB_TAG_SECTION_ALL, object_type)
|| safe_str_eq(XML_TAG_CIB, object_type)) {
/* get the whole cib */
return the_root;
} else if(strcasecmp(object_type, XML_CIB_TAG_STATUS) == 0) {
/* these live in a different place */
tmp_node = find_xml_node(the_root, XML_CIB_TAG_STATUS, FALSE);
node_stack[0] = object_type;
node_stack[1] = NULL;
} else {
tmp_node = find_xml_node_nested(the_root, node_stack, 2);
}
if (tmp_node == NULL) {
crm_debug_2("Section [%s [%s]] not present in %s",
node_stack[0],
node_stack[1]?node_stack[1]:"",
crm_element_name(the_root));
}
return tmp_node;
}
const char *
get_crm_option(crm_data_t *cib, const char *name, gboolean do_warn)
{
const char * value = NULL;
crm_data_t * a_default = NULL;
crm_data_t * config = get_object_root(XML_CIB_TAG_CRMCONFIG, cib);
if(config != NULL) {
a_default = find_entity(config, XML_CIB_TAG_NVPAIR, name);
}
if(a_default == NULL) {
if(do_warn) {
crm_warn("Option %s not set", name);
}
return NULL;
}
value = crm_element_value(a_default, XML_NVPAIR_ATTR_VALUE);
if(safe_str_eq(value, "")) {
value = NULL;
}
return value;
}
crm_data_t*
create_cib_fragment_adv(
crm_data_t *update, const char *update_section, const char *source)
{
crm_data_t *cib = NULL;
gboolean whole_cib = FALSE;
crm_data_t *object_root = NULL;
const char *update_name = NULL;
/* crm_debug("Creating a blank fragment: %s", update_section); */
if(update == NULL && update_section == NULL) {
crm_debug_3("Creating a blank fragment");
update = createEmptyCib();
crm_xml_add(cib, XML_ATTR_ORIGIN, source);
return update;
} else if(update == NULL) {
crm_err("No update to create a fragment for");
return NULL;
} else if(update_section == NULL) {
update_section = cib_pluralSection(update_name);
}
if(safe_str_eq(crm_element_name(update), XML_TAG_CIB)) {
whole_cib = TRUE;
}
if(whole_cib == FALSE) {
cib = createEmptyCib();
crm_xml_add(cib, XML_ATTR_ORIGIN, source);
object_root = get_object_root(update_section, cib);
add_node_copy(object_root, update);
} else {
cib = copy_xml(update);
crm_xml_add(cib, XML_ATTR_ORIGIN, source);
}
crm_debug_3("Verifying created fragment");
if(verifyCibXml(cib) == FALSE) {
crm_err("Fragment creation failed");
crm_log_xml_err(cib, "[src]");
free_xml(cib);
cib = NULL;
}
return cib;
}
/*
* It is the callers responsibility to free both the new CIB (output)
* and the new CIB (input)
*/
crm_data_t*
createEmptyCib(void)
{
crm_data_t *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);
/* crm_xml_add(cib_root, "version", "1"); */
crm_xml_add(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;
}
free_xml(cib_root);
crm_crit("The generated CIB did not pass integrity testing!!"
" All hope is lost.");
return NULL;
}
gboolean
verifyCibXml(crm_data_t *cib)
{
int lpc = 0;
gboolean is_valid = TRUE;
crm_data_t *tmp_node = NULL;
const char *sections[] = {
XML_CIB_TAG_NODES,
XML_CIB_TAG_RESOURCES,
XML_CIB_TAG_CONSTRAINTS,
XML_CIB_TAG_STATUS,
XML_CIB_TAG_CRMCONFIG
};
if (cib == NULL) {
crm_warn("CIB was empty.");
return FALSE;
}
/* basic tests... are the standard section all there */
for(lpc = 0; lpc < DIMOF(sections); lpc++) {
tmp_node = get_object_root(sections[lpc], cib);
if (tmp_node == NULL) {
crm_warn("Section %s is not present in the CIB",
sections[lpc]);
is_valid = FALSE;
}
}
/* more integrity tests */
return is_valid;
}
gboolean verify_cib_cmds(cib_t *cib)
{
gboolean valid = TRUE;
if(cib->cmds->variant_op == NULL) {
crm_err("Operation variant_op not set");
valid = FALSE;
}
if(cib->cmds->signon == NULL) {
crm_err("Operation signon not set");
valid = FALSE;
}
if(cib->cmds->signoff == NULL) {
crm_err("Operation signoff not set");
valid = FALSE;
}
if(cib->cmds->free == NULL) {
crm_err("Operation free not set");
valid = FALSE;
}
if(cib->cmds->set_op_callback == NULL) {
crm_err("Operation set_op_callback not set");
valid = FALSE;
}
if(cib->cmds->add_notify_callback == NULL) {
crm_err("Operation add_notify_callback not set");
valid = FALSE;
}
if(cib->cmds->del_notify_callback == NULL) {
crm_err("Operation del_notify_callback not set");
valid = FALSE;
}
if(cib->cmds->set_connection_dnotify == NULL) {
crm_err("Operation set_connection_dnotify not set");
valid = FALSE;
}
if(cib->cmds->channel == NULL) {
crm_err("Operation channel not set");
valid = FALSE;
}
if(cib->cmds->inputfd == NULL) {
crm_err("Operation inputfd not set");
valid = FALSE;
}
if(cib->cmds->noop == NULL) {
crm_err("Operation noop not set");
valid = FALSE;
}
if(cib->cmds->ping == NULL) {
crm_err("Operation ping not set");
valid = FALSE;
}
if(cib->cmds->query == NULL) {
crm_err("Operation query not set");
valid = FALSE;
}
if(cib->cmds->query_from == NULL) {
crm_err("Operation query_from not set");
valid = FALSE;
}
if(cib->cmds->is_master == NULL) {
crm_err("Operation is_master not set");
valid = FALSE;
}
if(cib->cmds->set_master == NULL) {
crm_err("Operation set_master not set");
valid = FALSE;
}
if(cib->cmds->set_slave == NULL) {
crm_err("Operation set_slave not set");
valid = FALSE;
}
if(cib->cmds->set_slave_all == NULL) {
crm_err("Operation set_slave_all not set");
valid = FALSE;
}
if(cib->cmds->sync == NULL) {
crm_err("Operation sync not set");
valid = FALSE;
} if(cib->cmds->sync_from == NULL) {
crm_err("Operation sync_from not set");
valid = FALSE;
}
if(cib->cmds->bump_epoch == NULL) {
crm_err("Operation bump_epoch not set");
valid = FALSE;
}
if(cib->cmds->create == NULL) {
crm_err("Operation create not set");
valid = FALSE;
}
if(cib->cmds->modify == NULL) {
crm_err("Operation modify not set");
valid = FALSE;
}
if(cib->cmds->replace == NULL) {
crm_err("Operation replace not set");
valid = FALSE;
}
if(cib->cmds->delete == NULL) {
crm_err("Operation delete not set");
valid = FALSE;
}
if(cib->cmds->erase == NULL) {
crm_err("Operation erase not set");
valid = FALSE;
}
if(cib->cmds->quit == NULL) {
crm_err("Operation quit not set");
valid = FALSE;
}
if(cib->cmds->msgready == NULL) {
crm_err("Operation msgready not set");
valid = FALSE;
}
if(cib->cmds->rcvmsg == NULL) {
crm_err("Operation rcvmsg not set");
valid = FALSE;
}
if(cib->cmds->dispatch == NULL) {
crm_err("Operation dispatch not set");
valid = FALSE;
}
return valid;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 26, 7:50 PM (1 d, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1959609
Default Alt Text
(52 KB)

Event Timeline