Integrate config file processing

Signed-off-by: Lon Hohberger <lhh@redhat.com>
This commit is contained in:
Lon Hohberger 2009-08-17 16:53:58 -04:00
parent 9ec497ddc6
commit 61e0cc19c9
16 changed files with 749 additions and 14 deletions

View File

@ -12,11 +12,13 @@
all:
make -C config
make -C common
make -C client
make -C server
clean:
make -C config clean
make -C common clean
make -C client clean
make -C server clean

View File

@ -334,7 +334,7 @@ static struct arg_info _arg_info[] = {
"IP port (default=1229)",
assign_port },
{ 'I', "-I <interface>", "multicast_address",
{ 'I', "-I <interface>", "interface",
"Network interface name to listen on",
assign_interface },

49
config/Makefile Normal file
View File

@ -0,0 +1,49 @@
###############################################################################
###############################################################################
##
## Copyright (C) 2006 Red Hat, Inc.
##
## 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 ../Makefile.top
TARGETS=libsimpleconfig.a
libsimpleconfig_a_SOURCE= config.tab.c \
config.c simpleconfig.c
INCLUDES=-I../include \
-I/usr/include/openais -I/usr/include/libvirt \
-I/usr/include/nss3 -I/usr/include/nspr4 \
-I../../../cman/lib -I../../../ccs/lib -I/usr/include/libxml2 \
-I/usr/include/libvirt
CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" -Wno-unused
LIBS+=-L../../../cman/lib -L../../../ccs/lib -L${libdir}/openais \
-L../../../dlm/lib -lnss3 -lxml2
all: ${TARGETS}
libsimpleconfig.a: ${libsimpleconfig_a_SOURCE:.c=.o}
ar rc $@ $^
config.tab.c config.tab.h: config.y
bison -d $^
config.c: config.tab.h config.l
flex -oconfig.c config.l
%.o: %.c
gcc $(CFLAGS) -c -o $@ $^ $(INCLUDES)
clean:
rm -f ${TARGETS} *~ *.o testprog config.tab.c config.tab.h config.c
install:

32
config/config-stack.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef _CONFIG_STACK_H
#define _CONFIG_STACK_H
int yyparse (void);
extern FILE *yyin;
struct value {
char *id;
char *val;
struct value *next;
};
struct node {
char *id;
struct node *nodes;
struct value *values;
struct node *next;
};
struct parser_context {
struct value *val_list;
struct node *node_list;
struct parser_context *next;
};
extern struct value *val_list;
extern struct node *node_list;
extern struct parser_context *context_stack;
#endif

104
config/config.l Normal file
View File

@ -0,0 +1,104 @@
%{
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include "config-stack.h"
#include "config.tab.h"
#include "simpleconfig.h"
struct value *val_list = NULL;
struct node *node_list = NULL;
struct parser_context *context_stack = NULL;
int _line_count = 1;
%}
%%
[\n] {
++_line_count;
}
[ \t]* {}
\#[^\n]* {}
"{" {
struct parser_context *c = NULL;
//printf("obrace\n");
c = malloc(sizeof(*c));
assert(c);
c->next = context_stack;
c->val_list = val_list;
c->node_list = node_list;
context_stack = c;
val_list = NULL;
node_list = NULL;
return T_OBRACE;
}
"}" {
return T_CBRACE;
}
";" {
return T_SEMI;
}
"=" {
return T_EQ;
}
[^ \t{};=\"\n]+ {
yylval.sval = strdup(yytext);
return T_ID;
}
\"[^\"]+\" {
yylval.sval = strdup(yytext+1);
yylval.sval[strlen(yytext)-2] = 0;
return T_VAL;
}
%%
void
reset_vars(void)
{
_line_count = 1;
}
int
yywrap(void)
{
return 1;
}
#ifdef STANDALONE
int
main(int argc, char *argv[])
{
char value[80];
config_object_t *c = NULL;
yyout = fopen("/dev/null","w");
c = sc_init();
sc_parse(c, NULL);
sc_dump(c, stdout);
if (argc >= 2) {
if (sc_get(c, argv[1], value, sizeof(value)) == 0)
printf("%s = %s\n", argv[1], value);
else
printf("Not found\n");
}
sc_release(c);
return 0;
}
#endif

104
config/config.y Normal file
View File

@ -0,0 +1,104 @@
%{
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <assert.h>
#include "config-stack.h"
extern int yylex (void);
int yyerror(const char *foo);
static int
value_add(char *id, char *val, struct value **list)
{
struct value *v;
v = malloc(sizeof(*v));
assert(v);
memset(v, 0, sizeof(*v));
v->id = id;
v->val = val;
//snprintf(v->id, sizeof(v->id), "%s", id);
//snprintf(v->val, sizeof(v->val), "%s", val);
//printf("add %s %s on to %p\n", id, val, *list);
v->next = *list;
*list = v;
//printf("new list %p\n", *list);
return 0;
}
static int
node_add(char *id, struct value *vallist, struct node *nodelist,
struct node **list)
{
struct node *n;
n = malloc(sizeof(*n));
assert(n);
//printf("nodes %p values %p\n", nodelist, vallist);
memset(n, 0, sizeof(*n));
//snprintf(n->id, sizeof(n->id), "%s", id);
n->id = id; /* malloc'd during parsing */
n->values = vallist;
n->nodes = nodelist;
n->next = *list;
*list = n;
return 0;
}
%}
%token <sval> T_ID
%token <sval> T_VAL
%token T_OBRACE T_CBRACE T_EQ T_SEMI
%start stuff
%union {
char *sval;
int ival;
}
%%
node:
T_ID T_OBRACE stuff T_CBRACE {
struct parser_context *c = NULL;
c = context_stack;
node_add($1, val_list, node_list, &c->node_list);
val_list = c->val_list;
node_list = c->node_list;
context_stack = c->next;
free(c);
}
|
T_ID T_OBRACE T_CBRACE /* Empty config block */
;
stuff:
node stuff | assign stuff | node | assign
;
assign:
T_ID T_EQ T_VAL T_SEMI {
value_add($1, $3, &val_list);
}
;
%%
extern int _line_count;
int
yyerror(const char *foo)
{
printf("%s on line %d\n", foo, _line_count);
return 0;
}

26
config/example.conf Normal file
View File

@ -0,0 +1,26 @@
fence_virtd {
debug ="99";
listener = "multicast";
backend = "libvirt";
}
listeners {
multicast {
key_file = "/etc/cluster/fence_xvm.key";
ip_family = "ipv4";
multicast_address = "225.0.0.14";
interface = "virbr0";
hash = "sha256";
auth = "sha256";
}
serial {
directory = "/var/run/fence_virtd";
}
}
backends {
libvirt {
uri = "qemu:///system";
}
}

269
config/simpleconfig.c Normal file
View File

@ -0,0 +1,269 @@
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <malloc.h>
#include "simpleconfig.h"
#include "config-stack.h"
static pthread_mutex_t parser_mutex = PTHREAD_MUTEX_INITIALIZER;
static int
print_value(struct value *v, int depth, FILE *fp)
{
int x;
for (x = 0; x < depth; x++)
fprintf(fp, "\t");
fprintf(fp, "%s = \"%s\";\n", v->id, v->val);
return 0;
}
static void
_sc_dump_d(struct node *node, int depth, FILE *fp)
{
struct node *n;
struct value *v;
int x;
if (!node) {
//printf("Empty node\n");
return;
}
for (x = 0; x < depth; x++)
fprintf(fp, "\t");
fprintf(fp, "%s {\n", node->id);
for (n = node->nodes; n; n = n->next) {
_sc_dump_d(n, depth+1, fp);
}
for (v = node->values; v; v = v->next) {
print_value(v, depth+1, fp);
}
for (x = 0; x < depth; x++)
fprintf(fp, "\t");
fprintf(fp, "}\n\n");
}
static void
_sc_dump(config_info_t *config, FILE *fp)
{
struct node *n, *node;
struct value *v, *values;
if (!config)
return;
values = ((struct parser_context *)config)->val_list;
node = ((struct parser_context *)config)->node_list;
for (n = node; n; n = n->next) {
_sc_dump_d(n, 0, fp);
}
for (v = values; v; v = v->next) {
print_value(v, 0, fp);
}
}
static int
free_value(struct value *v)
{
int x;
if (v) {
free(v->id);
free(v->val);
free(v);
}
return 0;
}
static void
_sc_free_node(struct node *node)
{
struct node *n;
struct value *v;
int x;
if (!node)
return;
while (node->nodes) {
n = node->nodes;
if (n) {
node->nodes = node->nodes->next;
_sc_free_node(n);
}
}
while (node->values) {
v = node->values;
node->values = node->values->next;
free_value(v);
}
free(node->id);
free(node);
}
static int
_sc_free(config_info_t *config)
{
struct node *n, *nlist;
struct value *v, *vlist;
if (!config)
return -1;
vlist = ((struct parser_context *)config)->val_list;
nlist = ((struct parser_context *)config)->node_list;
while (nlist) {
n = nlist;
nlist = nlist->next;
_sc_free_node(n);
}
((struct parser_context *)config)->node_list = NULL;
while (vlist) {
v = vlist;
vlist = vlist->next;
free_value(v);
}
((struct parser_context *)config)->val_list = NULL;
free(config);
return 0;
}
static int
_sc_get(config_info_t *config, const char *key, char *value, size_t valuesz)
{
char buf[1024];
struct node *n, *node = ((struct parser_context *)config)->node_list;
struct value *v, *values = ((struct parser_context *)config)->val_list;
char *ptr;
char *slash;
int found;
ptr = (char *)key;
while ((slash = strchr(ptr, '/'))) {
memset(buf, 0, sizeof(buf));
strncpy(buf, ptr, (slash - ptr));
ptr = ++slash;
found = 0;
for (n = node; n; n = n->next) {
if (!strcasecmp(n->id, buf)) {
node = n->nodes;
values = n->values;
found = 1;
break;
}
}
if (!found)
return 1;
}
if (ptr[0] == '@') {
++ptr;
found = 0;
for (v = values; v; v = v->next) {
if (!strcasecmp(v->id, ptr)) {
snprintf(value, valuesz, "%s", v->val);
return 0;
}
}
}
return 1;
}
static int
_sc_parse(const char *filename, config_info_t **config)
{
struct parser_context *c;
FILE *fp = NULL;
int ret = 0;
if (!config)
return -1;
pthread_mutex_lock(&parser_mutex);
if (filename) {
fp = fopen(filename, "r");
yyin = fp;
if (!fp)
return -1;
}
ret = yyparse();
if (!ret) {
c = malloc(sizeof(*c));
if (!c)
return -1;
c->node_list = node_list;
c->val_list = val_list;
c->next = NULL;
val_list = NULL;
node_list = NULL;
*config = (config_info_t *)c;
}
if (fp)
fclose(fp);
pthread_mutex_unlock(&parser_mutex);
return ret;
}
static const config_object_t sc_object = {
.get = _sc_get,
.parse = _sc_parse,
.free = _sc_free,
.dump = _sc_dump,
.info = NULL
};
config_object_t *
sc_init(void)
{
config_object_t *o;
o = malloc(sizeof(*o));
if (!o)
return NULL;
memset(o, 0, sizeof(*o));
memcpy(o, &sc_object, sizeof(*o));
return o;
}
void
sc_release(config_object_t *c)
{
sc_free(c);
free(c);
}

49
config/simpleconfig.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef _SIMPLECONFIG_H
#define _SIMPLECONFIG_H
typedef void config_info_t;
typedef int (*config_get_t)(config_info_t *config, const char *key,
char *value, size_t valuesz);
typedef int (*config_parse_t)(const char *filename, config_info_t **config);
typedef int (*config_free_t)(config_info_t *config);
typedef void (*config_dump_t)(config_info_t *config, FILE *fp);
/*
* We use an abstract object here so we do not have to link loadable
* modules against the configuration library.
*/
typedef struct {
config_get_t get;
config_parse_t parse;
config_free_t free;
config_dump_t dump;
config_info_t *info;
} config_object_t;
/*
* These macros may be called from within a loadable module
*/
#define sc_get(obj, key, value, valuesz) \
obj->get(obj->info, key, value, valuesz)
#define sc_parse(obj, filename) \
obj->parse(filename, &obj->info)
#define sc_free(obj) \
obj->free(obj->info)
#define sc_dump(obj, fp) \
obj->dump(obj->info, fp)
/*
* Do not call the below functions from loadable modules. Doing so
* requires linking the configuration library in to the modules, which
* is what we want to avoid.
*/
/* Returns a copy of our simple config object */
config_object_t *sc_init(void);
/* Frees a previously-allocated copy of our simple config object */
void sc_release(config_object_t *c);
#endif

View File

@ -49,7 +49,7 @@ typedef int (*fence_status_callback)(const char *vm_name,
is responding to requests. */
typedef int (*fence_devstatus_callback)(void *priv);
typedef int (*fence_init_callback)(srv_context_t *c);
typedef int (*fence_init_callback)(srv_context_t *c, config_object_t *config);
typedef int (*fence_cleanup_callback)(srv_context_t c);
typedef struct _fence_callbacks {

49
include/simpleconfig.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef _SIMPLECONFIG_H
#define _SIMPLECONFIG_H
typedef void config_info_t;
typedef int (*config_get_t)(config_info_t *config, const char *key,
char *value, size_t valuesz);
typedef int (*config_parse_t)(const char *filename, config_info_t **config);
typedef int (*config_free_t)(config_info_t *config);
typedef void (*config_dump_t)(config_info_t *config, FILE *fp);
/*
* We use an abstract object here so we do not have to link loadable
* modules against the configuration library.
*/
typedef struct {
config_get_t get;
config_parse_t parse;
config_free_t free;
config_dump_t dump;
config_info_t *info;
} config_object_t;
/*
* These macros may be called from within a loadable module
*/
#define sc_get(obj, key, value, valuesz) \
obj->get(obj->info, key, value, valuesz)
#define sc_parse(obj, filename) \
obj->parse(filename, &obj->info)
#define sc_free(obj) \
obj->free(obj->info)
#define sc_dump(obj, fp) \
obj->dump(obj->info, fp)
/*
* Do not call the below functions from loadable modules. Doing so
* requires linking the configuration library in to the modules, which
* is what we want to avoid.
*/
/* Returns a copy of our simple config object */
config_object_t *sc_init(void);
/* Frees a previously-allocated copy of our simple config object */
void sc_release(config_object_t *c);
#endif

View File

@ -29,14 +29,16 @@ CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" -D_MODULE
LIBS+=-L/usr/lib64/openais -lnss3 -lxml2 -lSaCkpt -lccs -lvirt -lcman \
-L../common -lfence_virt
MAIN_LIBS=-L../config -lsimpleconfig
all: ${TARGETS}
fence_virtd: ${fence_virtd_SOURCES:.c=.o}
gcc -o $@ $^ $(LIBS) -L../common -lfence_virt
gcc -o $@ $^ $(LIBS) $(MAIN_LIBS)
libvirt.so: ${libvirt_so_SOURCES:.c=.o}
gcc -o $@ $^ $(LIBS) -shared -L../common -lvirt
gcc -o $@ $^ $(LIBS) -shared
%.o: %.c
gcc $(CFLAGS) -c -o $@ $^ $(INCLUDES)

View File

@ -44,6 +44,7 @@
#include <nss.h>
#include <libgen.h>
//#include <uuid/uuid.h>
#include <simpleconfig.h>
#include <server_plugin.h>
/* Local includes */
@ -277,11 +278,18 @@ libvirt_reboot(const char *vm_name, void *priv)
}
static int
libvirt_init(srv_context_t *c)
libvirt_init(srv_context_t *c, config_object_t *config)
{
virConnectPtr vp;
char value[256];
char *uri = NULL;
vp = virConnectOpen(NULL);
if (sc_get(config, "backends/libvirt/@uri", value, sizeof(value)) == 0) {
uri = value;
printf("Using %s\n", uri);
}
vp = virConnectOpen(uri);
if (!vp)
return -1;
*c = (void *)vp;

View File

@ -6,6 +6,7 @@
#include <sys/types.h>
/* Local includes */
#include <simpleconfig.h>
#include <server_plugin.h>
#include <debug.h>
@ -14,13 +15,51 @@ extern fence_callbacks_t libvirt_callbacks; /* should be in a header */
int
main(int argc, char **argv)
{
const char *plugin_name = "libvirt";
char val[80];
config_object_t *config;
const plugin_t *p;
srv_context_t mcast_context;
srv_context_t libvirt_context; /*XXX these should be differently
named context types */
int debug_set = 0;
int opt;
dset(99);
config = sc_init();
while ((opt = getopt(argc, argv, "f:d:")) != EOF) {
switch(opt) {
case 'f':
printf("Using %s\n", optarg);
if (sc_parse(config, optarg) != 0) {
printf("Failed to parse %s\n", optarg);
return -1;
}
break;
case 'd':
dset(atoi(optarg));
debug_set = 1;
break;
default:
break;
}
}
if (!debug_set) {
if (sc_get(config, "fence_virtd/@debug",
val, sizeof(val)) == 0)
dset(atoi(val));
}
sc_dump(config, stdout);
if (sc_get(config, "fence_virtd/@backend", val, sizeof(val))) {
printf("Failed to determine backend.\n");
printf("%s\n", val);
return -1;
}
printf("Backend plugin: %s\n", val);
#ifdef _MODULE
if (plugin_load("./libvirt.so") < 0) {
@ -29,13 +68,13 @@ main(int argc, char **argv)
#endif
plugin_dump();
p = plugin_find(plugin_name);
p = plugin_find(val);
if (!p) {
printf("Could not find plugin \"%s\n", plugin_name);
printf("Could not find plugin \"%s\n", val);
}
if (p->init(&libvirt_context) < 0) {
printf("%s failed to initialize\n", plugin_name);
if (p->init(&libvirt_context, config) < 0) {
printf("%s failed to initialize\n", val);
return 1;
}

View File

@ -42,6 +42,7 @@
#include <pthread.h>
#include <nss.h>
#include <libgen.h>
#include <simpleconfig.h>
#include <server_plugin.h>
/* Local includes */

View File

@ -29,6 +29,7 @@
#include <unistd.h>
#include <list.h>
#include <simpleconfig.h>
#include <server_plugin.h>
#include <malloc.h>
#include <string.h>
@ -82,9 +83,9 @@ plugin_find(const char *name)
int
plugin_init(const plugin_t *p, srv_context_t *c)
plugin_init(const plugin_t *p, srv_context_t *c, config_object_t *config)
{
return p->init(c);
return p->init(c, config);
}