diff options
Diffstat (limited to 'agents/virt/config')
-rw-r--r-- | agents/virt/config/Makefile.am | 44 | ||||
-rw-r--r-- | agents/virt/config/config-stack.h | 38 | ||||
-rw-r--r-- | agents/virt/config/config.l | 106 | ||||
-rw-r--r-- | agents/virt/config/config.y | 140 | ||||
-rw-r--r-- | agents/virt/config/fence_virt.conf | 20 | ||||
-rw-r--r-- | agents/virt/config/simpleconfig.c | 494 |
6 files changed, 842 insertions, 0 deletions
diff --git a/agents/virt/config/Makefile.am b/agents/virt/config/Makefile.am new file mode 100644 index 0000000..19d9742 --- /dev/null +++ b/agents/virt/config/Makefile.am @@ -0,0 +1,44 @@ +############################################################################### +############################################################################### +## +## Copyright (C) 2009-2019 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. +## +############################################################################### +############################################################################### + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = config.l config.y fence_virt.conf + +noinst_LIBRARIES = libsimpleconfig.a + +libsimpleconfig_a_SOURCES = \ + simpleconfig.c + +nodist_libsimpleconfig_a_SOURCES = \ + y.tab.c \ + config.c + +libsimpleconfig_a_CFLAGS = $(VIRT_AM_CFLAGS) $(AM_CFLAGS) -Wno-unused + +noinst_HEADERS = config-stack.h + + +sysconf_DATA = fence_virt.conf + +# local rules +y.tab.c: config.y + $(YACC) -d $^ + +config.c: y.tab.c config.l + $(LEX) -oconfig.c $(srcdir)/config.l + +install-exec-hook: + chmod 600 $(DESTDIR)$(sysconfdir)/fence_virt.conf + +clean-local: + rm -f config.tab.c config.tab.h config.c y.tab.c y.tab.h diff --git a/agents/virt/config/config-stack.h b/agents/virt/config/config-stack.h new file mode 100644 index 0000000..1eb3cfa --- /dev/null +++ b/agents/virt/config/config-stack.h @@ -0,0 +1,38 @@ +#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; + char *val; + 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; + +int _sc_value_add(char *id, char *val, struct value **list); +int _sc_node_add(char *id, char *val, struct value *vallist, + struct node *nodelist, struct node **list); + + +#endif diff --git a/agents/virt/config/config.l b/agents/virt/config/config.l new file mode 100644 index 0000000..78462f3 --- /dev/null +++ b/agents/virt/config/config.l @@ -0,0 +1,106 @@ +%{ +#include "config.h" +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include "config-stack.h" +#include "y.tab.h" +#include "simpleconfig.h" + +/* Some distributions can't use the output from flex without help */ +#define ECHO if(fwrite( yytext, yyleng, 1, yyout )) + +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; +} + +%% +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"); + } else if (argc == 3) { + printf("---------\n"); + if (sc_set(c, argv[1], argv[2]) == 0) + sc_dump(c, stdout); + } + + sc_release(c); + + return 0; +} +#endif diff --git a/agents/virt/config/config.y b/agents/virt/config/config.y new file mode 100644 index 0000000..2ae0380 --- /dev/null +++ b/agents/virt/config/config.y @@ -0,0 +1,140 @@ +%{ +#include "config.h" +#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); + +int +_sc_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; +} + + +int +_sc_node_add(char *id, char *val, 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->val = val; /* 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; + _sc_node_add($1, NULL, 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_EQ T_VAL T_OBRACE stuff T_CBRACE { + struct parser_context *c = NULL; + + c = context_stack; + _sc_node_add($1, $3, 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 { + struct parser_context *c = NULL; + + c = context_stack; + _sc_node_add($1, NULL, 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_EQ T_VAL T_OBRACE T_CBRACE { + struct parser_context *c = NULL; + + c = context_stack; + _sc_node_add($1, $3, val_list, node_list, &c->node_list); + val_list = c->val_list; + node_list = c->node_list; + context_stack = c->next; + + free(c); + } + ; + +stuff: + node stuff | assign stuff | node | assign + ; + +assign: + T_ID T_EQ T_VAL T_SEMI { + _sc_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; +} diff --git a/agents/virt/config/fence_virt.conf b/agents/virt/config/fence_virt.conf new file mode 100644 index 0000000..03e2c58 --- /dev/null +++ b/agents/virt/config/fence_virt.conf @@ -0,0 +1,20 @@ +fence_virtd { + listener = "multicast"; + backend = "libvirt"; +} + +listeners { + multicast { + key_file = "/etc/cluster/fence_xvm.key"; + address = "225.0.0.12"; + # Needed on Fedora systems + interface = "virbr0"; + } +} + +backends { + libvirt { + uri = "qemu:///system"; + } +} + diff --git a/agents/virt/config/simpleconfig.c b/agents/virt/config/simpleconfig.c new file mode 100644 index 0000000..3315b32 --- /dev/null +++ b/agents/virt/config/simpleconfig.c @@ -0,0 +1,494 @@ +#include "config.h" + +#include <stdio.h> +#include <pthread.h> +#include <string.h> +#include <malloc.h> +#include <stdlib.h> +#include <assert.h> + +#include "simpleconfig.h" +#include "config-stack.h" +#include "static_map.h" + + +static pthread_mutex_t parser_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int +print_value(struct value *v, int depth, FILE *fp) +{ + int x; + + if (v->val == NULL) + return 0; + + 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"); + + if (node->val) { + fprintf(fp, "%s = \"%s\" {\n", node->id, node->val); + } else { + 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(void *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) +{ + 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; + + 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(void *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(void *config, const char *key, char *value, size_t valuesz) +{ + char buf[1024]; + struct node *n, *node; + struct value *v, *values; + char *ptr; + char *slash; + char *bracket; + char *id; + int req_index = 0; + int curr_index = 0; + int found; + + if (!config) + return -1; + + node = ((struct parser_context *)config)->node_list; + values = ((struct parser_context *)config)->val_list; + + assert(strlen(key) < sizeof(buf)); + + ptr = (char *)key; + + while ((slash = strchr(ptr, '/'))) { + memset(buf, 0, sizeof(buf)); + strncpy(buf, ptr, (slash - ptr)); + ptr = ++slash; + + id = NULL; + bracket = strchr(buf, '['); + if (bracket) { + *bracket = 0; + ++bracket; + + id = bracket; + + bracket = strchr(bracket, ']'); + if (!bracket) + return 1; + *bracket = 0; + + if (id[0] == '@') { + ++id; + if (!strlen(id)) { + return 1; + } + } else { + req_index = atoi(id); + if (req_index <= 0) + return 1; + id = NULL; + } + } + + found = 0; + curr_index = 0; + + for (n = node; n; n = n->next) { + + if (strcasecmp(n->id, buf)) + continue; + + ++curr_index; + + if (req_index && (curr_index != req_index)) { + continue; + } else if (id && strcasecmp(n->val, id)) { + continue; + } + + node = n->nodes; + values = n->values; + found = 1; + break; + } + + if (!found) + return 1; + } + + if (ptr[0] != '@') { + + strncpy(buf, ptr, sizeof(buf) - 1); + id = NULL; + bracket = strchr(buf, '['); + if (bracket) { + *bracket = 0; + ++bracket; + + id = bracket; + + bracket = strchr(bracket, ']'); + if (!bracket) + return 1; + *bracket = 0; + + if (id[0] == '@') { + ++id; + if (!strlen(id)) { + return 1; + } + } else { + req_index = atoi(id); + if (req_index <= 0) + return 1; + id = NULL; + } + } + + found = 0; + curr_index = 0; + + for (n = node; n; n = n->next) { + + if (strcasecmp(n->id, buf)) + continue; + + ++curr_index; + + if (req_index && (curr_index != req_index)) { + continue; + } else if (id && strcasecmp(n->val, id)) { + continue; + } + if (node->val) { + strncpy(value, node->val, valuesz); + return 0; + } + return 1; + } + } + + ++ptr; + found = 0; + id = NULL; + + strncpy(buf, ptr, sizeof(buf) - 1); + bracket = strchr(buf, '['); + + req_index = 0; + curr_index = 0; + + if (bracket) { + *bracket = 0; + ++bracket; + + id = bracket; + + bracket = strchr(bracket, ']'); + if (!bracket) + return 1; + *bracket = 0; + + req_index = atoi(id); + if (req_index <= 0) + return 1; + id = NULL; + } + + for (v = values; v; v = v->next) { + + if (strcasecmp(v->id, buf)) + continue; + + ++curr_index; + if (req_index && (curr_index != req_index)) + continue; + snprintf(value, valuesz, "%s", v->val); + return 0; + } + + return 1; +} + + +static int +_sc_set(void *config, const char *key, const char *value) +{ + char buf[1024]; + struct node *n, **nodes = &((struct parser_context *)config)->node_list; + struct value *v, **values = &((struct parser_context *)config)->val_list; + char *ptr; + char *slash; + char *id_dup, *val_dup; + int found = 0; + + ptr = (char *)key; + while ((slash = strchr(ptr, '/'))) { + memset(buf, 0, sizeof(buf)); + strncpy(buf, ptr, (slash - ptr)); + ptr = ++slash; + found = 0; + + for (n = *nodes; n; n = n->next) { + if (strcasecmp(n->id, buf)) + continue; + + nodes = &n->nodes; + values = &n->values; + found = 1; + break; + } + + if (!found) { + id_dup = strdup(buf); + if (!id_dup) + return -1; + _sc_node_add(id_dup, NULL, NULL, NULL, nodes); + n = *nodes; + nodes = &n->nodes; + values = &n->values; + } + } + + if (ptr[0] != '@') + return 1; + ++ptr; + + for (v = *values; v; v = v->next) { + if (strcasecmp(v->id, ptr)) + continue; + + ptr = v->val; + if (value) { + v->val = strdup(value); + if (!v->val) { + v->val = ptr; + return -1; + } + } else { + v->val = NULL; + } + free(ptr); + + return 0; + } + + if (!value) + return 0; + + id_dup = strdup(ptr); + if (!id_dup) + return -1; + + val_dup = strdup(value); + if (!val_dup) { + free(id_dup); + return -1; + } + _sc_value_add(id_dup, val_dup, values); + + return 0; +} + + +static int +_sc_parse(const char *filename, void **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) + ret = yyparse(); + else + ret = 1; + } else { + ret = 1; + } + + c = malloc(sizeof(*c)); + if (!c) { + ret = -1; + goto out_unlock; + } + c->node_list = node_list; + c->val_list = val_list; + c->next = NULL; + val_list = NULL; + node_list = NULL; + *config = (void *)c; + + if (fp) + fclose(fp); + +out_unlock: + pthread_mutex_unlock(&parser_mutex); + return ret; +} + + +static const config_object_t sc_object = { + .get = _sc_get, + .set = _sc_set, + .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); +} |