summaryrefslogtreecommitdiffstats
path: root/agents/virt/config
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--agents/virt/config/Makefile.am44
-rw-r--r--agents/virt/config/config-stack.h38
-rw-r--r--agents/virt/config/config.l106
-rw-r--r--agents/virt/config/config.y140
-rw-r--r--agents/virt/config/fence_virt.conf20
-rw-r--r--agents/virt/config/simpleconfig.c494
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);
+}