Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F1842009
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
52 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/cman/daemon/cman-preconfig.c b/cman/daemon/cman-preconfig.c
index 4e691f49d..6715b3f79 100644
--- a/cman/daemon/cman-preconfig.c
+++ b/cman/daemon/cman-preconfig.c
@@ -1,996 +1,1075 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netdb.h>
#define SYSLOG_NAMES
#include <sys/syslog.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
/* corosync headers */
#include <corosync/engine/logsys.h>
#include <corosync/lcr/lcr_comp.h>
#include <corosync/engine/objdb.h>
#include <corosync/engine/config.h>
#include "cman.h"
#define OBJDB_API struct objdb_iface_ver0
#include "cnxman-socket.h"
#include "nodelist.h"
#include "logging.h"
#define MAX_PATH_LEN PATH_MAX
static unsigned int debug_mask;
static int cmanpre_readconfig(struct objdb_iface_ver0 *objdb, char **error_string);
static char *nodename_env;
static int expected_votes;
static int votes;
static int num_interfaces;
static int startup_pipe;
static unsigned int cluster_id;
static char nodename[MAX_CLUSTER_MEMBER_NAME_LEN];
static int nodeid;
static int two_node;
static unsigned int disable_openais;
static unsigned int portnum;
static int num_nodenames;
static char *key_filename;
static char *mcast_name;
static char *cluster_name;
static char error_reason[1024] = { '\0' };
static unsigned int cluster_parent_handle;
/*
* Exports the interface for the service
*/
static struct config_iface_ver0 cmanpreconfig_iface_ver0 = {
.config_readconfig = cmanpre_readconfig
};
static struct lcr_iface ifaces_ver0[2] = {
{
.name = "cmanpreconfig",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = NULL,
}
};
static struct lcr_comp cmanpre_comp_ver0 = {
.iface_count = 1,
.ifaces = ifaces_ver0,
};
__attribute__ ((constructor)) static void cmanpre_comp_register(void) {
lcr_interfaces_set(&ifaces_ver0[0], &cmanpreconfig_iface_ver0);
lcr_component_register(&cmanpre_comp_ver0);
}
static char *facility_name_get (unsigned int facility)
{
unsigned int i;
for (i = 0; facilitynames[i].c_name != NULL; i++) {
if (facility == facilitynames[i].c_val) {
return (facilitynames[i].c_name);
}
}
return (NULL);
}
static char *priority_name_get (unsigned int priority)
{
unsigned int i;
for (i = 0; prioritynames[i].c_name != NULL; i++) {
if (priority == prioritynames[i].c_val) {
return (prioritynames[i].c_name);
}
}
return (NULL);
}
#define LOCALHOST_IPV4 "127.0.0.1"
#define LOCALHOST_IPV6 "::1"
/* Compare two addresses */
static int ipaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
{
int addrlen = 0;
struct sockaddr *saddr1 = (struct sockaddr *)addr1;
struct sockaddr *saddr2 = (struct sockaddr *)addr2;
if (saddr1->sa_family != saddr2->sa_family)
return 0;
if (saddr1->sa_family == AF_INET) {
addrlen = sizeof(struct sockaddr_in);
}
if (saddr1->sa_family == AF_INET6) {
addrlen = sizeof(struct sockaddr_in6);
}
assert(addrlen);
if (memcmp(saddr1, saddr2, addrlen) == 0)
return 1;
else
return 0;
}
/* Build a localhost ip_address */
static int get_localhost(int family, struct sockaddr_storage *localhost)
{
char *addr_text;
struct addrinfo *ainfo;
struct addrinfo ahints;
int ret;
if (family == AF_INET) {
addr_text = LOCALHOST_IPV4;
} else {
addr_text = LOCALHOST_IPV6;
}
memset(&ahints, 0, sizeof(ahints));
ahints.ai_socktype = SOCK_DGRAM;
ahints.ai_protocol = IPPROTO_UDP;
ahints.ai_family = family;
/* Lookup the nodename address */
ret = getaddrinfo(addr_text, NULL, &ahints, &ainfo);
if (ret)
return -1;
memset(localhost, 0, sizeof(struct sockaddr_storage));
memcpy(localhost, ainfo->ai_addr, ainfo->ai_addrlen);
freeaddrinfo(ainfo);
return 0;
}
/* Return the address family of an IP[46] name */
static int address_family(char *addr, struct sockaddr_storage *ssaddr)
{
struct addrinfo *ainfo;
struct addrinfo ahints;
int family;
int ret;
memset(&ahints, 0, sizeof(ahints));
ahints.ai_socktype = SOCK_DGRAM;
ahints.ai_protocol = IPPROTO_UDP;
/* Lookup the nodename address */
ret = getaddrinfo(addr, NULL, &ahints, &ainfo);
if (ret)
return -1;
memset(ssaddr, 0, sizeof(struct sockaddr_storage));
memcpy(ssaddr, ainfo->ai_addr, ainfo->ai_addrlen);
family = ainfo->ai_family;
freeaddrinfo(ainfo);
return family;
}
/* Find the "CMAN" logger_subsys object. Or create one if it does not
exist
*/
static unsigned int find_cman_logger(struct objdb_iface_ver0 *objdb, unsigned int object_handle)
{
unsigned int subsys_handle;
unsigned int find_handle;
char *str;
objdb->object_find_create(object_handle, "logger_subsys", strlen("logger_subsys"), &find_handle);
while (!objdb->object_find_next(object_handle, &subsys_handle)) {
if (objdb_get_string(objdb, subsys_handle, "subsys", &str)) {
continue;
}
if (strcmp(str, CMAN_NAME) == 0)
return subsys_handle;
}
objdb->object_find_destroy(find_handle);
/* We can't find it ... create one */
if (objdb->object_create(object_handle, &subsys_handle,
"logger_subsys", strlen("logger_subsys")) == 0) {
objdb->object_key_create(subsys_handle, "subsys", strlen("subsys"),
CMAN_NAME, strlen(CMAN_NAME)+1);
}
return subsys_handle;
}
static int add_ifaddr(struct objdb_iface_ver0 *objdb, char *mcast, char *ifaddr, int portnum)
{
unsigned int totem_object_handle;
unsigned int find_handle;
unsigned int interface_object_handle;
struct sockaddr_storage if_addr, localhost, mcast_addr;
char tmp[132];
int ret = 0;
/* Check the families match */
if (address_family(mcast, &mcast_addr) !=
address_family(ifaddr, &if_addr)) {
sprintf(error_reason, "Node address family does not match multicast address family");
return -1;
}
/* Check it's not bound to localhost, sigh */
get_localhost(if_addr.ss_family, &localhost);
if (ipaddr_equal(&localhost, &if_addr)) {
sprintf(error_reason, "Node address is localhost, please choose a real host address");
return -1;
}
objdb->object_find_create(OBJECT_PARENT_HANDLE, "totem", strlen("totem"), &find_handle);
if (objdb->object_find_next(find_handle, &totem_object_handle)) {
objdb->object_create(OBJECT_PARENT_HANDLE, &totem_object_handle,
"totem", strlen("totem"));
}
objdb->object_find_destroy(find_handle);
if (objdb->object_create(totem_object_handle, &interface_object_handle,
"interface", strlen("interface")) == 0) {
sprintf(tmp, "%d", num_interfaces);
objdb->object_key_create(interface_object_handle, "ringnumber", strlen("ringnumber"),
tmp, strlen(tmp)+1);
objdb->object_key_create(interface_object_handle, "bindnetaddr", strlen("bindnetaddr"),
ifaddr, strlen(ifaddr)+1);
objdb->object_key_create(interface_object_handle, "mcastaddr", strlen("mcastaddr"),
mcast, strlen(mcast)+1);
sprintf(tmp, "%d", portnum);
objdb->object_key_create(interface_object_handle, "mcastport", strlen("mcastport"),
tmp, strlen(tmp)+1);
num_interfaces++;
}
return ret;
}
static uint16_t generate_cluster_id(char *name)
{
int i;
int value = 0;
for (i=0; i<strlen(name); i++) {
value <<= 1;
value += name[i];
}
sprintf(error_reason, "Generated cluster id for '%s' is %d\n", name, value & 0xFFFF);
return value & 0xFFFF;
}
static char *default_mcast(char *nodename, uint16_t cluster_id)
{
struct addrinfo *ainfo;
struct addrinfo ahints;
int ret;
int family;
static char addr[132];
memset(&ahints, 0, sizeof(ahints));
/* Lookup the the nodename address and use it's IP type to
default a multicast address */
ret = getaddrinfo(nodename, NULL, &ahints, &ainfo);
if (ret) {
sprintf(error_reason, "Can't determine address family of nodename %s\n", nodename);
write_cman_pipe("Can't determine address family of nodename");
return NULL;
}
family = ainfo->ai_family;
freeaddrinfo(ainfo);
if (family == AF_INET) {
snprintf(addr, sizeof(addr), "239.192.%d.%d", cluster_id >> 8, cluster_id % 0xFF);
return addr;
}
if (family == AF_INET6) {
snprintf(addr, sizeof(addr), "ff15::%x", cluster_id);
return addr;
}
return NULL;
}
static int verify_nodename(struct objdb_iface_ver0 *objdb, char *nodename)
{
char nodename2[MAX_CLUSTER_MEMBER_NAME_LEN+1];
char nodename3[MAX_CLUSTER_MEMBER_NAME_LEN+1];
char *str, *dot = NULL;
struct ifaddrs *ifa, *ifa_list;
struct sockaddr *sa;
unsigned int nodes_handle;
unsigned int find_handle = 0;
int error;
/* nodename is either from commandline or from uname */
if (nodelist_byname(objdb, cluster_parent_handle, nodename))
return 0;
/* If nodename was from uname, try a domain-less version of it */
strcpy(nodename2, nodename);
dot = strchr(nodename2, '.');
if (dot) {
*dot = '\0';
if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) {
strcpy(nodename, nodename2);
return 0;
}
}
/* If nodename (from uname) is domain-less, try to match against
cluster.conf names which may have domainname specified */
nodes_handle = nodeslist_init(objdb, cluster_parent_handle, &find_handle);
do {
int len;
if (objdb_get_string(objdb, nodes_handle, "name", &str)) {
sprintf(error_reason, "Cannot get node name");
break;
}
strcpy(nodename3, str);
dot = strchr(nodename3, '.');
if (dot)
len = dot-nodename3;
else
len = strlen(nodename3);
if (strlen(nodename2) == len &&
!strncmp(nodename2, nodename3, len)) {
strcpy(nodename, str);
return 0;
}
nodes_handle = nodeslist_next(objdb, find_handle);
} while (nodes_handle);
objdb->object_find_destroy(find_handle);
/* The cluster.conf names may not be related to uname at all,
they may match a hostname on some network interface.
NOTE: This is IPv4 only */
error = getifaddrs(&ifa_list);
if (error)
return -1;
for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
/* Restore this */
strcpy(nodename2, nodename);
sa = ifa->ifa_addr;
if (!sa || sa->sa_family != AF_INET)
continue;
error = getnameinfo(sa, sizeof(*sa), nodename2,
sizeof(nodename2), NULL, 0, 0);
if (error)
goto out;
if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) {
strcpy(nodename, nodename2);
goto out;
}
/* truncate this name and try again */
dot = strchr(nodename2, '.');
if (!dot)
continue;
*dot = '\0';
if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) {
strcpy(nodename, nodename2);
goto out;
}
/* See if it's the IP address that's in cluster.conf */
error = getnameinfo(sa, sizeof(*sa), nodename2,
sizeof(nodename2), NULL, 0, NI_NUMERICHOST);
if (error)
goto out;
if (nodelist_byname(objdb, cluster_parent_handle, nodename2)) {
strcpy(nodename, nodename2);
goto out;
}
}
error = -1;
out:
freeifaddrs(ifa_list);
return error;
}
/* Get any environment variable overrides */
static int get_env_overrides()
{
if (getenv("CMAN_CLUSTER_NAME")) {
cluster_name = strdup(getenv("CMAN_CLUSTER_NAME"));
}
nodename_env = getenv("CMAN_NODENAME");
expected_votes = 0;
if (getenv("CMAN_EXPECTEDVOTES")) {
expected_votes = atoi(getenv("CMAN_EXPECTEDVOTES"));
if (expected_votes < 1) {
expected_votes = 0;
}
}
/* optional port */
if (getenv("CMAN_IP_PORT")) {
portnum = atoi(getenv("CMAN_IP_PORT"));
}
/* optional security key filename */
if (getenv("CMAN_KEYFILE")) {
key_filename = strdup(getenv("CMAN_KEYFILE"));
if (key_filename == NULL) {
write_cman_pipe("Cannot allocate memory for key filename");
return -1;
}
}
/* find our own number of votes */
if (getenv("CMAN_VOTES")) {
votes = atoi(getenv("CMAN_VOTES"));
}
/* nodeid */
if (getenv("CMAN_NODEID")) {
nodeid = atoi(getenv("CMAN_NODEID"));
}
if (getenv("CMAN_MCAST_ADDR")) {
mcast_name = getenv("CMAN_MCAST_ADDR");
}
if (getenv("CMAN_2NODE")) {
two_node = 1;
expected_votes = 1;
votes = 1;
}
if (getenv("CMAN_DEBUGLOG")) {
debug_mask = atoi(getenv("CMAN_DEBUGLOG"));
}
return 0;
}
static int get_nodename(struct objdb_iface_ver0 *objdb)
{
char *nodeid_str;
unsigned int object_handle;
unsigned int find_handle;
unsigned int node_object_handle;
unsigned int alt_object;
int error;
if (!getenv("CMAN_NOCONFIG")) {
/* our nodename */
if (nodename_env != NULL) {
if (strlen(nodename_env) >= sizeof(nodename)) {
sprintf(error_reason, "Overridden node name %s is too long", nodename);
write_cman_pipe("Overridden node name is too long");
error = -1;
goto out;
}
strcpy(nodename, nodename_env);
if (!(node_object_handle = nodelist_byname(objdb, cluster_parent_handle, nodename))) {
sprintf(error_reason, "Overridden node name %s is not in CCS", nodename);
write_cman_pipe("Overridden node name is not in CCS");
error = -1;
goto out;
}
} else {
struct utsname utsname;
error = uname(&utsname);
if (error) {
sprintf(error_reason, "cannot get node name, uname failed");
write_cman_pipe("Can't determine local node name");
error = -1;
goto out;
}
if (strlen(utsname.nodename) >= sizeof(nodename)) {
sprintf(error_reason, "node name from uname is too long");
write_cman_pipe("Can't determine local node name");
error = -1;
goto out;
}
strcpy(nodename, utsname.nodename);
}
if (verify_nodename(objdb, nodename))
return -1;
}
/* Add <cman> bits to pass down to the main module*/
if ( (node_object_handle = nodelist_byname(objdb, cluster_parent_handle, nodename))) {
if (objdb_get_string(objdb, node_object_handle, "nodeid", &nodeid_str)) {
sprintf(error_reason, "This node has no nodeid in cluster.conf");
write_cman_pipe("This node has no nodeid in cluster.conf");
return -1;
}
}
objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle) == 0) {
unsigned int mcast_handle;
unsigned int find_handle2;
if (!mcast_name) {
objdb->object_find_create(object_handle, "multicast", strlen("multicast"), &find_handle2);
if (objdb->object_find_next(find_handle2, &mcast_handle) == 0) {
objdb_get_string(objdb, mcast_handle, "addr", &mcast_name);
}
objdb->object_find_destroy(find_handle2);
}
if (!mcast_name) {
mcast_name = default_mcast(nodename, cluster_id);
}
/* See if the user wants our default set of openais services (default=yes) */
objdb_get_int(objdb, object_handle, "disable_openais", &disable_openais, 0);
objdb->object_key_create(object_handle, "nodename", strlen("nodename"),
nodename, strlen(nodename)+1);
}
objdb->object_find_destroy(find_handle);
nodeid = atoi(nodeid_str);
error = 0;
/* optional port */
if (!portnum) {
objdb_get_int(objdb, object_handle, "port", &portnum, DEFAULT_PORT);
}
if (add_ifaddr(objdb, mcast_name, nodename, portnum))
return -1;
/* Get all alternative node names */
num_nodenames = 1;
objdb->object_find_create(node_object_handle,"altname", strlen("altname"), &find_handle);
while (objdb->object_find_next(find_handle, &alt_object) == 0) {
unsigned int port;
char *nodename;
char *mcast;
if (objdb_get_string(objdb, alt_object, "name", &nodename)) {
continue;
}
objdb_get_int(objdb, alt_object, "port", &port, portnum);
if (objdb_get_string(objdb, alt_object, "mcast", &mcast)) {
mcast = mcast_name;
}
if (add_ifaddr(objdb, mcast, nodename, portnum))
return -1;
num_nodenames++;
}
objdb->object_find_destroy(find_handle);
out:
return error;
}
/* These are basically cman overrides to the totem config bits */
static void add_cman_overrides(struct objdb_iface_ver0 *objdb)
{
unsigned int logger_object_handle;
char *logstr;
char *logfacility;
unsigned int object_handle;
unsigned int find_handle;
char tmp[256];
/* "totem" key already exists, because we have added the interfaces by now */
objdb->object_find_create(OBJECT_PARENT_HANDLE,"totem", strlen("totem"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle) == 0)
{
char *value;
objdb->object_key_create(object_handle, "version", strlen("version"),
"2", 2);
sprintf(tmp, "%d", nodeid);
objdb->object_key_create(object_handle, "nodeid", strlen("nodeid"),
tmp, strlen(tmp)+1);
objdb->object_key_create(object_handle, "vsftype", strlen("vsftype"),
"none", strlen("none")+1);
/* Set the token timeout is 10 seconds, but don't overrride anything that
might be in cluster.conf */
if (objdb_get_string(objdb, object_handle, "token", &value)) {
objdb->object_key_create(object_handle, "token", strlen("token"),
"10000", strlen("10000")+1);
}
if (objdb_get_string(objdb, object_handle, "token_retransmits_before_loss_const", &value)) {
objdb->object_key_create(object_handle, "token_retransmits_before_loss_const",
strlen("token_retransmits_before_loss_const"),
"20", strlen("20")+1);
}
/* Extend consensus & join timeouts per bz#214290 */
if (objdb_get_string(objdb, object_handle, "join", &value)) {
objdb->object_key_create(object_handle, "join", strlen("join"),
"60", strlen("60")+1);
}
if (objdb_get_string(objdb, object_handle, "consensus", &value)) {
objdb->object_key_create(object_handle, "consensus", strlen("consensus"),
"4800", strlen("4800")+1);
}
/* Set RRP mode appropriately */
if (objdb_get_string(objdb, object_handle, "rrp_mode", &value)) {
if (num_interfaces > 1) {
objdb->object_key_create(object_handle, "rrp_mode", strlen("rrp_mode"),
"active", strlen("active")+1);
}
else {
objdb->object_key_create(object_handle, "rrp_mode", strlen("rrp_mode"),
"none", strlen("none")+1);
}
}
if (objdb_get_string(objdb, object_handle, "secauth", &value)) {
sprintf(tmp, "%d", 1);
objdb->object_key_create(object_handle, "secauth", strlen("secauth"),
tmp, strlen(tmp)+1);
}
/* optional security key filename */
if (!key_filename) {
objdb_get_string(objdb, object_handle, "keyfile", &key_filename);
}
else {
objdb->object_key_create(object_handle, "keyfile", strlen("keyfile"),
key_filename, strlen(key_filename)+1);
}
if (!key_filename) {
/* Use the cluster name as key,
* This isn't a good isolation strategy but it does make sure that
* clusters on the same port/multicast by mistake don't actually interfere
* and that we have some form of encryption going.
*/
int keylen;
memset(tmp, 0, sizeof(tmp));
strcpy(tmp, cluster_name);
/* Key length must be a multiple of 4 */
keylen = (strlen(cluster_name)+4) & 0xFC;
objdb->object_key_create(object_handle, "key", strlen("key"),
tmp, keylen);
}
}
objdb->object_find_destroy(find_handle);
/* Make sure mainconfig doesn't stomp on our logging options */
objdb->object_find_create(OBJECT_PARENT_HANDLE, "logging", strlen("logging"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle)) {
objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle,
"logging", strlen("logging"));
}
objdb->object_find_destroy(find_handle);
logfacility = facility_name_get(SYSLOGFACILITY);
logger_object_handle = find_cman_logger(objdb, object_handle);
if (objdb_get_string(objdb, object_handle, "syslog_facility", &logstr)) {
objdb->object_key_create(object_handle, "syslog_facility", strlen("syslog_facility"),
logfacility, strlen(logfacility)+1);
}
if (objdb_get_string(objdb, object_handle, "to_file", &logstr)) {
objdb->object_key_create(object_handle, "to_file", strlen("to_file"),
"yes", strlen("yes")+1);
}
if (objdb_get_string(objdb, object_handle, "logfile", &logstr)) {
objdb->object_key_create(object_handle, "logfile", strlen("logfile"),
LOGDIR "/cman.log", strlen(LOGDIR "/cman.log")+1);
}
if (debug_mask) {
objdb->object_key_create(object_handle, "to_stderr", strlen("to_stderr"),
"yes", strlen("yes")+1);
objdb->object_key_create(logger_object_handle, "debug", strlen("debug"),
"on", strlen("on")+1);
objdb->object_key_create(logger_object_handle, "syslog_level", strlen("syslog_level"),
"debug", strlen("debug")+1);
}
else {
char *loglevel;
loglevel = priority_name_get(SYSLOGLEVEL);
objdb->object_key_create(logger_object_handle, "syslog_level", strlen("syslog_level"),
loglevel, strlen(loglevel)+1);
}
/* Don't run under user "ais" */
objdb->object_find_create(OBJECT_PARENT_HANDLE, "aisexec", strlen("aisexec"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle) != 0) {
objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle,
"aisexec", strlen("aisexec"));
}
objdb->object_find_destroy(find_handle);
objdb->object_key_create(object_handle, "user", strlen("user"),
"root", strlen("root") + 1);
objdb->object_key_create(object_handle, "group", strlen("group"),
"root", strlen("root") + 1);
objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle) == 0)
{
char str[255];
sprintf(str, "%d", cluster_id);
objdb->object_key_create(object_handle, "cluster_id", strlen("cluster_id"),
str, strlen(str) + 1);
if (two_node) {
sprintf(str, "%d", 1);
objdb->object_key_create(object_handle, "two_node", strlen("two_node"),
str, strlen(str) + 1);
}
if (debug_mask) {
sprintf(str, "%d", debug_mask);
objdb->object_key_create(object_handle, "debug_mask", strlen("debug_mask"),
str, strlen(str) + 1);
}
}
objdb->object_find_destroy(find_handle);
/* Make sure we load our alter-ego - the main cman module */
objdb->object_create(OBJECT_PARENT_HANDLE, &object_handle,
"service", strlen("service"));
objdb->object_key_create(object_handle, "name", strlen("name"),
"corosync_cman", strlen("corosync_cman") + 1);
objdb->object_key_create(object_handle, "ver", strlen("ver"),
"0", 2);
}
/* If ccs is not available then use some defaults */
static int set_noccs_defaults(struct objdb_iface_ver0 *objdb)
{
char tmp[255];
unsigned int object_handle;
unsigned int find_handle;
/* Enforce key */
key_filename = NOCCS_KEY_FILENAME;
if (!cluster_name)
cluster_name = DEFAULT_CLUSTER_NAME;
if (!cluster_id)
cluster_id = generate_cluster_id(cluster_name);
if (!nodename_env) {
int error;
struct utsname utsname;
error = uname(&utsname);
if (error) {
sprintf(error_reason, "cannot get node name, uname failed");
write_cman_pipe("Can't determine local node name");
return -1;
}
nodename_env = (char *)&utsname.nodename;
}
strcpy(nodename, nodename_env);
num_nodenames = 1;
if (!mcast_name) {
mcast_name = default_mcast(nodename, cluster_id);
}
/* This will increase as nodes join the cluster */
if (!expected_votes)
expected_votes = 1;
if (!votes)
votes = 1;
if (!portnum)
portnum = DEFAULT_PORT;
/* Invent a node ID */
if (!nodeid) {
struct addrinfo *ainfo;
struct addrinfo ahints;
int ret;
memset(&ahints, 0, sizeof(ahints));
ret = getaddrinfo(nodename, NULL, &ahints, &ainfo);
if (ret) {
sprintf(error_reason, "Can't determine address family of nodename %s\n", nodename);
write_cman_pipe("Can't determine address family of nodename");
return -1;
}
if (ainfo->ai_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)ainfo->ai_addr;
memcpy(&nodeid, &addr->sin_addr, sizeof(int));
}
if (ainfo->ai_family == AF_INET6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ainfo->ai_addr;
memcpy(&nodeid, &addr->sin6_addr.s6_addr32[3], sizeof(int));
}
freeaddrinfo(ainfo);
}
/* Write a local <clusternode> entry to keep the rest of the code happy */
objdb->object_create(cluster_parent_handle, &object_handle,
"clusternodes", strlen("clusternodes"));
objdb->object_create(object_handle, &object_handle,
"clusternode", strlen("clusternode"));
objdb->object_key_create(object_handle, "name", strlen("name"),
nodename, strlen(nodename)+1);
sprintf(tmp, "%d", votes);
objdb->object_key_create(object_handle, "votes", strlen("votes"),
tmp, strlen(tmp)+1);
sprintf(tmp, "%d", nodeid);
objdb->object_key_create(object_handle, "nodeid", strlen("nodeid"),
tmp, strlen(tmp)+1);
/* Write the default cluster name & ID in here too */
objdb->object_key_create(cluster_parent_handle, "name", strlen("name"),
cluster_name, strlen(cluster_name)+1);
objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle) == 0) {
objdb->object_create(cluster_parent_handle, &object_handle,
"cman", strlen("cman"));
}
sprintf(tmp, "%d", cluster_id);
objdb->object_key_create(object_handle, "cluster_id", strlen("cluster_id"),
tmp, strlen(tmp)+1);
sprintf(tmp, "%d", expected_votes);
objdb->object_key_create(object_handle, "expected_votes", strlen("expected_votes"),
tmp, strlen(tmp)+1);
objdb->object_find_destroy(find_handle);
return 0;
}
+/* Move an object/key tree */
+static int move_config_tree(struct objdb_iface_ver0 *objdb, unsigned int source_object, unsigned int target_parent_object)
+{
+ unsigned int object_handle;
+ unsigned int new_object;
+ unsigned int find_handle;
+ char object_name[1024];
+ int object_name_len;
+ void *key_name;
+ int key_name_len;
+ void *key_value;
+ int key_value_len;
+ int res;
+
+ /* Create new parent object if necessary */
+ objdb->object_name_get(source_object, object_name, &object_name_len);
+
+ objdb->object_find_create(target_parent_object, object_name, strlen(object_name), &find_handle);
+ if (objdb->object_find_next(find_handle, &object_handle))
+ objdb->object_create(target_parent_object, &new_object, object_name, object_name_len);
+ objdb->object_find_destroy(find_handle);
+
+ /* Copy the keys */
+ objdb->object_key_iter_reset(new_object);
+
+ while (!objdb->object_key_iter(source_object, &key_name, &key_name_len,
+ &key_value, &key_value_len)) {
+
+ objdb->object_key_create(new_object, key_name, key_name_len,
+ key_value, key_value_len);
+ }
+
+ /* Create sub-objects */
+ res = objdb->object_find_create(source_object, NULL, 0, &find_handle);
+ if (res) {
+ sprintf(error_reason, "error resetting object iterator for object %d: %d\n", source_object, res);
+ return -1;
+ }
+
+ while ( (res = objdb->object_find_next(find_handle, &object_handle) == 0)) {
+
+ /* Down we go ... */
+ move_config_tree(objdb, object_handle, new_object);
+ }
+ objdb->object_find_destroy(find_handle);
+
+ return 0;
+}
+
+/*
+ * Move trees from /cluster where they live in cluster.conf, into the root
+ * of the config tree where corosync expects to find them.
+ */
+static int move_tree_to_root(struct objdb_iface_ver0 *objdb, char *name)
+{
+ unsigned int find_handle;
+ unsigned int object_handle;
+ int res=0;
+
+ objdb->object_find_create(cluster_parent_handle, name, strlen(name), &find_handle);
+ if (objdb->object_find_next(find_handle, &object_handle) == 0) {
+ res = move_config_tree(objdb, object_handle, OBJECT_PARENT_HANDLE);
+ }
+ objdb->object_find_destroy(find_handle);
+
+ // TODO Destroy original ??
+ // objdb->object_destroy(object_handle);
+ return res;
+}
+
static int get_cman_globals(struct objdb_iface_ver0 *objdb)
{
unsigned int object_handle;
unsigned int find_handle;
objdb_get_string(objdb, cluster_parent_handle, "name", &cluster_name);
/* Get the <cman> bits that override <totem> bits */
objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle) == 0) {
if (!portnum)
objdb_get_int(objdb, object_handle, "port", &portnum, DEFAULT_PORT);
if (!key_filename)
objdb_get_string(objdb, object_handle, "keyfile", &key_filename);
if (!cluster_id)
objdb_get_int(objdb, object_handle, "cluster_id", &cluster_id, 0);
if (!cluster_id)
cluster_id = generate_cluster_id(cluster_name);
}
objdb->object_find_destroy(find_handle);
return 0;
}
static int cmanpre_readconfig(struct objdb_iface_ver0 *objdb, char **error_string)
{
int ret = 0;
unsigned int object_handle;
unsigned int find_handle;
if (getenv("CMAN_PIPE"))
startup_pipe = atoi(getenv("CMAN_PIPE"));
objdb->object_find_create(OBJECT_PARENT_HANDLE, "cluster", strlen("cluster"), &find_handle);
objdb->object_find_next(find_handle, &cluster_parent_handle);
objdb->object_find_destroy(find_handle);
+ /* Move these to a place where corosync expects to find them */
+ ret = move_tree_to_root(objdb, "totem");
+ ret = move_tree_to_root(objdb, "logging");
+ ret = move_tree_to_root(objdb, "event");
+ ret = move_tree_to_root(objdb, "amf");
+ ret = move_tree_to_root(objdb, "aisexec");
+
objdb->object_find_create(cluster_parent_handle, "cman", strlen("cman"), &find_handle);
if (objdb->object_find_next(find_handle, &object_handle)) {
objdb->object_create(cluster_parent_handle, &object_handle,
"cman", strlen("cman"));
}
objdb->object_find_destroy(find_handle);
get_env_overrides();
if (getenv("CMAN_NOCONFIG"))
ret = set_noccs_defaults(objdb);
else
ret = get_cman_globals(objdb);
if (!ret) {
ret = get_nodename(objdb);
add_cman_overrides(objdb);
}
+
+
if (!ret) {
sprintf (error_reason, "%s", "Successfully parsed cman config\n");
}
else {
if (error_reason[0] == '\0')
sprintf (error_reason, "%s", "Error parsing cman config\n");
}
*error_string = error_reason;
return ret;
}
/* Write an error message down the CMAN startup pipe so
that cman_tool can display it */
int write_cman_pipe(char *message)
{
if (startup_pipe)
return write(startup_pipe, message, strlen(message)+1);
return 0;
}
diff --git a/config/plugins/ccsais/config.c b/config/plugins/ccsais/config.c
index b56a24f2d..4db379b53 100644
--- a/config/plugins/ccsais/config.c
+++ b/config/plugins/ccsais/config.c
@@ -1,224 +1,216 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <syslog.h>
#include <netinet/in.h>
#include "list.h"
#include "cnxman-socket.h"
#include "cnxman-private.h"
#include <corosync/lcr/lcr_comp.h>
#include <corosync/engine/objdb.h>
#include <corosync/engine/config.h>
#include "libccscompat.h"
#include "logging.h"
#define CONFIG_VERSION_PATH "/cluster/@config_version"
#define CONFIG_NAME_PATH "/cluster/@name"
static int ccs_readconfig(struct objdb_iface_ver0 *objdb, char **error_string);
static int init_config(struct objdb_iface_ver0 *objdb, char *error_string);
static char error_reason[1024];
/*
* Exports the interface for the service
*/
static struct config_iface_ver0 ccsconfig_iface_ver0 = {
.config_readconfig = ccs_readconfig
};
static struct lcr_iface ifaces_ver0[2] = {
{
.name = "ccsconfig",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = NULL,
}
};
static struct lcr_comp ccs_comp_ver0 = {
.iface_count = 1,
.ifaces = ifaces_ver0,
};
__attribute__ ((constructor)) static void ccs_comp_register(void) {
lcr_interfaces_set(&ifaces_ver0[0], &ccsconfig_iface_ver0);
lcr_component_register(&ccs_comp_ver0);
};
static int should_alloc(int ccs_fd, char *key)
{
int keyerror, childerr;
char path[256];
char *str = NULL;
sprintf(path, "%s/@*", key);
keyerror = ccs_get_list(ccs_fd, path, &str);
if(str) {
free(str);
str = NULL;
}
sprintf(path, "%s/child::*", key);
childerr = ccs_get_list(ccs_fd, path, &str);
if(str)
free(str);
if (childerr && keyerror)
return 0;
return 1;
}
static int read_config_for(int ccs_fd, struct objdb_iface_ver0 *objdb, unsigned int parent,
char *object, char *key, int always_create)
{
int error;
char *str;
unsigned int object_handle = 0;
char path[256];
int gotcount = 0;
char *subkeys[52];
int subkeycount = 0;
int i;
if (should_alloc(ccs_fd, key) || always_create)
objdb->object_create(parent, &object_handle, object, strlen(object));
sprintf(path, "%s/@*", key);
/* Get the keys */
for (;;)
{
char *equal;
error = ccs_get_list(ccs_fd, path, &str);
if (error || !str)
break;
equal = strchr(str, '=');
if (equal)
{
*equal = 0;
objdb->object_key_create(object_handle, str, strlen(str),
equal+1, strlen(equal+1)+1);
gotcount++;
}
free(str);
}
/* Now look for sub-objects.
CCS can't cope with recursive queries so we have to store the result of
the subkey search */
memset(subkeys, 0, sizeof(subkeys));
sprintf(path, "%s/child::*", key);
for (;;)
{
char *equal;
error = ccs_get_list(ccs_fd, path, &str);
if (error || !str)
break;
/* CCS returns duplicate values for the numbered entries we use below.
eg. if there are 4 <clusternode/> entries it will return
clusternode=
clusternode=
clusternode=
clusternode=
which is not helpful to us cos we retrieve them as
clusternode[1]
clusternode[2]
clusternode[3]
clusternode[4]
so we just store unique keys.
*/
equal = strchr(str, '=');
if (equal)
*equal = 0;
if (subkeycount > 0 && strcmp(str, subkeys[subkeycount-1]) == 0)
{
free(str);
break;
}
subkeys[subkeycount++] = str;
}
for (i=0; i<subkeycount; i++)
{
int count = 0;
str = subkeys[i];
gotcount++;
for (;;)
{
char subpath[1024];
/* Found a subkey, iterate through it's sub sections */
sprintf(subpath, "%s/%s[%d]", key, str, ++count);
if (!read_config_for(ccs_fd, objdb, object_handle, str, subpath, 0))
break;
}
free(str);
}
return gotcount;
}
static int ccs_readconfig(struct objdb_iface_ver0 *objdb, char **error_string)
{
int ret;
/* We need to set this up to internal defaults too early */
openlog("corosync", LOG_CONS|LOG_PID, SYSLOGFACILITY);
/* Read low-level totem/aisexec etc config from CCS */
if ( !(ret = init_config(objdb, error_reason)) )
sprintf (error_reason, "%s", "Successfully read config from CCS\n");
*error_string = error_reason;
return ret;
}
static int init_config(struct objdb_iface_ver0 *objdb, char *error_string)
{
int cd;
char *cname = NULL;
/* Connect to ccsd */
if (getenv("CCS_CLUSTER_NAME")) {
cname = getenv("CCS_CLUSTER_NAME");
}
cd = ccs_force_connect(cname, 0);
if (cd < 0) {
strcpy(error_string, "Error connecting to CCS to get configuration. Check ccsd is running");
return -1;
}
- /* These first few are just versions of openais.conf */
- read_config_for(cd, objdb, OBJECT_PARENT_HANDLE, "totem", "/cluster/totem", 1);
- read_config_for(cd, objdb, OBJECT_PARENT_HANDLE, "logging", "/cluster/logging", 1);
- read_config_for(cd, objdb, OBJECT_PARENT_HANDLE, "event", "/cluster/event", 1);
- read_config_for(cd, objdb, OBJECT_PARENT_HANDLE, "aisexec", "/cluster/aisexec", 1);
- read_config_for(cd, objdb, OBJECT_PARENT_HANDLE, "amf", "/cluster/amf", 1);
-
- /* This is stuff specific to us, eg quorum device timeout */
read_config_for(cd, objdb, OBJECT_PARENT_HANDLE, "cluster", "/cluster", 1);
ccs_disconnect(cd);
return 0;
}
diff --git a/config/plugins/ldap/configldap.c b/config/plugins/ldap/configldap.c
index e5a571a81..0f49cc041 100644
--- a/config/plugins/ldap/configldap.c
+++ b/config/plugins/ldap/configldap.c
@@ -1,294 +1,290 @@
/******************************************************************************
*******************************************************************************
**
** Copyright (C) 2008 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
** of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
// CC: temp until I tame SASL ... is this necessary?
#define LDAP_DEPRECATED 1
#include <ldap.h>
/* corosync headers */
#include <corosync/lcr/lcr_comp.h>
#include <corosync/engine/objdb.h>
#include <corosync/engine/config.h>
/* These are defaults. they can be overridden with environment variables
* LDAP_URL & LDAP_BASEDN
*/
#define DEFAULT_LDAP_URL "ldap:///"
#define DEFAULT_LDAP_BASEDN "dc=chrissie,dc=net"
static int ldap_readconfig(struct objdb_iface_ver0 *objdb, char **error_string);
static int init_config(struct objdb_iface_ver0 *objdb);
static char error_reason[1024];
static char *ldap_url = DEFAULT_LDAP_URL;
static char *ldap_basedn = DEFAULT_LDAP_BASEDN;
/*
* Exports the interface for the service
*/
static struct config_iface_ver0 ldapconfig_iface_ver0 = {
.config_readconfig = ldap_readconfig
};
static struct lcr_iface ifaces_ver0[2] = {
{
.name = "ldapconfig",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = NULL,
}
};
static struct lcr_comp ldap_comp_ver0 = {
.iface_count = 1,
.ifaces = ifaces_ver0,
};
__attribute__ ((constructor)) static void ldap_comp_register(void) {
lcr_interfaces_set(&ifaces_ver0[0], &ldapconfig_iface_ver0);
lcr_component_register(&ldap_comp_ver0);
};
static int ldap_readconfig(struct objdb_iface_ver0 *objdb, char **error_string)
{
int ret;
/* Read config tree from LDAP */
if (!(ret = init_config(objdb)))
sprintf(error_reason, "%s", "Successfully read config from LDAP\n");
*error_string = error_reason;
return ret;
}
/*
* Convert hyphens to underscores in all attribute names
*/
static void convert_underscores(char *s, int len)
{
int j;
for (j=0; j < len; j++) {
if (s[j] == '-')
s[j] = '_';
}
}
static void convert_dn_underscores(LDAPDN dn)
{
int i=0;
while (dn[i]) {
convert_underscores(dn[i][0][0].la_attr.bv_val, dn[i][0][0].la_attr.bv_len);
i++;
}
}
/*
* Return the parent object of a DN.
* Actually, this returns the LAST parent with that name. which should (!) be correct.
*/
static unsigned int find_parent(struct objdb_iface_ver0 *objdb, LDAPDN dn, int startdn, char *parent)
{
int i=startdn;
int gotstart=0;
int start=0, end=startdn;
unsigned int parent_handle = OBJECT_PARENT_HANDLE;
unsigned int object_handle=0;
unsigned int find_handle;
/*
* Find the start and end positions first.
* start is where the 'parent' entry is.
* end is the end of the list
*/
do {
if (!gotstart && dn[i][0][0].la_value.bv_len == 7 &&
!strncmp(parent, dn[i][0][0].la_value.bv_val, 7)) {
gotstart = 1;
start = i;
}
i++;
} while (dn[i]);
if (start <= 0)
return parent_handle;
for (i=start; i>=end; i--) {
objdb->object_find_create(parent_handle,
dn[i][0][0].la_value.bv_val, dn[i][0][0].la_value.bv_len,
&find_handle);
if (!objdb->object_find_next(find_handle, &object_handle)) {
parent_handle = object_handle;
}
objdb->object_find_destroy(find_handle);
}
return object_handle;
}
static int read_config_for(LDAP *ld, struct objdb_iface_ver0 *objdb, unsigned int parent,
char *object, char *sub_dn, int always_create)
{
char search_dn[4096];
int rc;
char *dn;
LDAPMessage *result, *e;
unsigned int parent_handle = OBJECT_PARENT_HANDLE;
unsigned int object_handle;
sprintf(search_dn, "%s,%s", sub_dn, ldap_basedn);
/* Search the whole tree from the base DN provided */
rc = ldap_search_ext_s(ld, search_dn, LDAP_SCOPE_SUBTREE, "(objectClass=*)", NULL, 0,
NULL, NULL, NULL, 0, &result);
if (rc != LDAP_SUCCESS) {
sprintf(error_reason, "ldap_search_ext_s: %s\n", ldap_err2string(rc));
if (rc == LDAP_NO_SUCH_OBJECT)
return 0;
else
return -1;
}
for (e = ldap_first_entry(ld, result); e != NULL;
e = ldap_next_entry(ld, e)) {
if ((dn = ldap_get_dn(ld, e)) != NULL) {
char *attr;
BerElement *attr_ber;
LDAPDN parsed_dn;
/* Make it parsable so we can discern the hierarchy */
if (ldap_str2dn(dn, &parsed_dn, LDAP_DN_PEDANTIC)) {
sprintf(error_reason, "ldap_str2dn failed: %s\n", ldap_err2string(rc));
return -1;
}
/*
* LDAP doesn't allow underscores in dn names so we replace hypens with
* underscores so we can have thing like config_version, appear as
* config-version in ldap
*/
convert_dn_underscores(parsed_dn);
/* Create a new object if the top-level is NOT name= */
if (strncmp(parsed_dn[0][0][0].la_attr.bv_val, "name", 4)) {
parent_handle = find_parent(objdb, parsed_dn, 0, object);
objdb->object_create(parent_handle, &object_handle, parsed_dn[0][0][0].la_value.bv_val,
parsed_dn[0][0][0].la_value.bv_len);
}
else {
parent_handle = find_parent(objdb, parsed_dn, 2, object);
/* Create a new object with the same name as the current one */
objdb->object_create(parent_handle, &object_handle, parsed_dn[1][0][0].la_value.bv_val,
parsed_dn[1][0][0].la_value.bv_len);
}
/* Finished with the text representation */
ldap_memfree(dn);
/* Store the attributes as keys */
attr = ldap_first_attribute(ld, e, &attr_ber);
while (attr) {
int i;
struct berval **val_ber;
val_ber = ldap_get_values_len(ld, e, attr);
i=0;
while (val_ber[i]) {
/*
* If the attribute starts "rhcs" then remove that bit
* and make the first letter lower case so it matches the
* cluster.conf entry.
* so, after the above underscore change too:
* eg 'rhcsConfig-version' becomes 'config_version'. magic!
*/
if (strncmp(attr, "rhcs", 4) == 0) {
memmove(attr, attr+4, strlen(attr+4)+1);
attr[0] |= 0x60;
}
convert_underscores(attr, strlen(attr));
/*
* Add a key - but ignore "objectClass" & "cn" attributes
* as they don't provide anything we can use
*/
if (strcmp("objectClass", attr) &&
strcmp("cn", attr))
objdb->object_key_create(object_handle, attr, strlen(attr),
val_ber[i]->bv_val,
val_ber[i]->bv_len+1);
i++;
}
ldap_memfree(attr);
attr = ldap_next_attribute(ld, e, attr_ber);
ldap_value_free_len(val_ber);
}
ldap_memfree(attr);
ber_free(attr_ber, 0);
}
}
ldap_msgfree(result);
return 0;
}
/* The real work starts here */
static int init_config(struct objdb_iface_ver0 *objdb)
{
LDAP *ld;
int version, rc;
if (getenv("COROSYNC_LDAP_URL"))
ldap_url = getenv("COROSYNC_LDAP_URL");
if (getenv("COROSYNC_LDAP_BASEDN"))
ldap_basedn = getenv("COROSYNC_LDAP_BASEDN");
/* Connect to the LDAP server */
if (ldap_initialize(&ld, ldap_url)) {
sprintf(error_reason, "ldap_simple_bind failed: %s\n", strerror(errno));
return -1;
}
version = LDAP_VERSION3;
ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
/*
* CC: Do I need to use sasl ?!
*/
rc = ldap_simple_bind_s(ld, getenv("COROSYNC_LDAP_BINDDN"), getenv("COROSYNC_LDAP_BINDPWD"));
if (rc != LDAP_SUCCESS) {
sprintf(error_reason, "ldap_simple_bind failed: %s\n", ldap_err2string(rc));
return -1;
}
rc = read_config_for(ld, objdb, OBJECT_PARENT_HANDLE, "cluster", "cn=cluster", 1);
- if (!rc)
- rc = read_config_for(ld, objdb, OBJECT_PARENT_HANDLE, "totem", "cn=totem,cn=cluster", 1);
- if (!rc)
- rc = read_config_for(ld, objdb, OBJECT_PARENT_HANDLE, "logging", "cn=logging,cn=cluster", 1);
ldap_unbind(ld);
return 0;
}
diff --git a/config/plugins/xml/config.c b/config/plugins/xml/config.c
index 9d597720b..8ba290bf5 100644
--- a/config/plugins/xml/config.c
+++ b/config/plugins/xml/config.c
@@ -1,312 +1,303 @@
#include <string.h>
#include <limits.h>
#include <syslog.h>
#include <arpa/inet.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <corosync/lcr/lcr_comp.h>
#include <corosync/engine/objdb.h>
#include <corosync/engine/config.h>
#include "logging.h"
static int xml_readconfig(struct objdb_iface_ver0 *objdb, char **error_string);
static int init_config(struct objdb_iface_ver0 *objdb, char *configfile, char *error_string);
static char error_reason[1024];
static int xmllistindex = 0;
static char previous_query[PATH_MAX];
#define DEFAULT_CONFIG DEFAULT_CONFIG_DIR "/" DEFAULT_CONFIG_FILE
/*
* Exports the interface for the service
*/
static struct config_iface_ver0 xmlconfig_iface_ver0 = {
.config_readconfig = xml_readconfig
};
static struct lcr_iface ifaces_ver0[2] = {
{
.name = "xmlconfig",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = NULL,
}
};
static struct lcr_comp xml_comp_ver0 = {
.iface_count = 1,
.ifaces = ifaces_ver0,
};
__attribute__ ((constructor)) static void xml_comp_register(void) {
lcr_interfaces_set(&ifaces_ver0[0], &xmlconfig_iface_ver0);
lcr_component_register(&xml_comp_ver0);
};
static char *do_xml_query(xmlXPathContextPtr ctx, char *query, int list) {
xmlXPathObjectPtr obj = NULL;
xmlNodePtr node = NULL;
char *rtn = NULL;
int size = 0, nnv = 0, child = 0;
if (list && !strcmp(query, previous_query))
xmllistindex++;
else {
memset(previous_query, 0, PATH_MAX);
xmllistindex = 0;
}
obj = xmlXPathEvalExpression((xmlChar *)query, ctx);
if (obj && obj->nodesetval && (obj->nodesetval->nodeNr > 0)) {
if (xmllistindex >= obj->nodesetval->nodeNr) {
memset(previous_query, 0, PATH_MAX);
xmllistindex = 0;
goto fail;
}
node = obj->nodesetval->nodeTab[xmllistindex];
if (!node)
goto fail;
if (((node->type == XML_ATTRIBUTE_NODE) && strstr(query, "@*")) ||
((node->type == XML_ELEMENT_NODE) && strstr(query, "child::*"))) {
if (node->children && node->children->content) {
size = strlen((char *)node->children->content) +
strlen((char *)node->name)+2;
child = 1;
} else
size = strlen((char *)node->name)+2;
nnv = 1;
} else {
if (node->children && node->children->content)
size = strlen((char *)node->children->content)+1;
else
goto fail;
}
rtn = malloc(size);
if (!rtn)
goto fail;
memset(rtn, 0, size);
if (nnv) {
if (child)
sprintf(rtn, "%s=%s", node->name, (char *)node->children->content);
else
sprintf(rtn, "%s=", node->name);
} else
sprintf(rtn, "%s", node->children ? node->children->content : node->name);
if(list)
strncpy(previous_query, query, PATH_MAX-1);
}
fail:
if (obj)
xmlXPathFreeObject(obj);
return rtn;
}
static int should_alloc(xmlXPathContextPtr ctx, char *key)
{
int keyerror = 1, childerr = 1;
char path[256];
char *str = NULL;
sprintf(path, "%s/@*", key);
str = do_xml_query(ctx, path, 1);
if (str) {
keyerror = 0;
free(str);
str = NULL;
}
sprintf(path, "%s/child::*", key);
str = do_xml_query(ctx, path, 1);
if(str) {
childerr = 0;
free(str);
str = NULL;
}
if (childerr && keyerror)
return 0;
return 1;
}
static int read_config_for(xmlXPathContextPtr ctx, struct objdb_iface_ver0 *objdb, unsigned int parent,
char *object, char *key, int always_create)
{
char *str;
unsigned int object_handle = 0;
char path[256];
int gotcount = 0;
char *subkeys[52];
int subkeycount = 0;
int i;
if (should_alloc(ctx, key) || always_create) {
objdb->object_create(parent, &object_handle, object, strlen(object));
}
memset(previous_query, 0, PATH_MAX);
sprintf(path, "%s/@*", key);
/* Get the keys */
for (;;)
{
char *equal;
str = do_xml_query(ctx, path, 1);
if (!str)
break;
equal = strchr(str, '=');
if (equal)
{
*equal = 0;
objdb->object_key_create(object_handle, str, strlen(str),
equal+1, strlen(equal+1)+1);
gotcount++;
}
free(str);
}
/* Now look for sub-objects.
CCS can't cope with recursive queries so we have to store the result of
the subkey search */
memset(previous_query, 0, PATH_MAX);
memset(subkeys, 0, sizeof(subkeys));
sprintf(path, "%s/child::*", key);
for (;;)
{
char *equal;
str = do_xml_query(ctx, path, 1);
if (!str)
break;
/* CCS returns duplicate values for the numbered entries we use below.
eg. if there are 4 <clusternode/> entries it will return
clusternode=
clusternode=
clusternode=
clusternode=
which is not helpful to us cos we retrieve them as
clusternode[1]
clusternode[2]
clusternode[3]
clusternode[4]
so we just store unique keys.
*/
equal = strchr(str, '=');
if (equal)
*equal = 0;
if (subkeycount > 0 && strcmp(str, subkeys[subkeycount-1]) == 0)
{
free(str);
break;
}
subkeys[subkeycount++] = str;
}
for (i=0; i<subkeycount; i++)
{
int count = 0;
str = subkeys[i];
gotcount++;
for (;;)
{
char subpath[1024];
/* Found a subkey, iterate through it's sub sections */
sprintf(subpath, "%s/%s[%d]", key, str, ++count);
if (!read_config_for(ctx, objdb, object_handle, str, subpath, 0))
break;
}
free(str);
}
return gotcount;
}
static int xml_readconfig(struct objdb_iface_ver0 *objdb, char **error_string)
{
int ret = 0;
char *configfile = DEFAULT_CONFIG;
/* We need to set this up to internal defaults too early */
openlog("corosync", LOG_CONS|LOG_PID, SYSLOGFACILITY);
if(getenv("COROSYNC_CLUSTER_CONFIG_FILE"))
configfile = getenv("COROSYNC_CLUSTER_CONFIG_FILE");
/* Read low-level totem/aisexec etc config from cluster.conf */
if ( !(ret = init_config(objdb, configfile, error_reason)) )
sprintf (error_reason, "Successfully read config from %s\n", configfile);
else
sprintf (error_reason, "Unable to read config from %s\n", configfile);
*error_string = error_reason;
return ret;
}
static int init_config(struct objdb_iface_ver0 *objdb, char *configfile, char *error_string)
{
int err = 0;
xmlDocPtr doc = NULL;
xmlXPathContextPtr ctx = NULL;
/* openfile */
doc = xmlParseFile(configfile);
if (!doc) {
err = -1;
goto fail;
}
ctx = xmlXPathNewContext(doc);
if (!ctx) {
err = -1;
goto fail;
}
/* load it in objdb */
-
- /* These first few are just versions of openais.conf */
- read_config_for(ctx, objdb, OBJECT_PARENT_HANDLE, "totem", "/cluster/totem", 1);
- read_config_for(ctx, objdb, OBJECT_PARENT_HANDLE, "logging", "/cluster/logging", 1);
- read_config_for(ctx, objdb, OBJECT_PARENT_HANDLE, "event", "/cluster/event", 1);
- read_config_for(ctx, objdb, OBJECT_PARENT_HANDLE, "aisexec", "/cluster/aisexec", 1);
- read_config_for(ctx, objdb, OBJECT_PARENT_HANDLE, "amf", "/cluster/amf", 1);
-
- /* This is stuff specific to us, eg quorum device timeout */
read_config_for(ctx, objdb, OBJECT_PARENT_HANDLE, "cluster", "/cluster", 1);
fail:
if (ctx)
xmlXPathFreeContext(ctx);
if (doc)
xmlFreeDoc(doc);
return err;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 11:06 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018631
Default Alt Text
(52 KB)
Attached To
Mode
rR Resource Agents
Attached
Detach File
Event Timeline
Log In to Comment