Make all plugins dynamically loaded.
Signed-off-by: Lon Hohberger <lhh@redhat.com>
This commit is contained in:
parent
ac60769002
commit
5beaad3390
@ -3,6 +3,7 @@ fence_virtd {
|
||||
listener = "multicast";
|
||||
backend = "libvirt";
|
||||
name_mode = "name";
|
||||
module_path = "/usr/lib64/fence_virt";
|
||||
}
|
||||
|
||||
listeners {
|
||||
|
@ -103,6 +103,7 @@ const listener_plugin_t *plugin_find_listener(const char *name);
|
||||
|
||||
void plugin_dump(void);
|
||||
#ifdef _MODULE
|
||||
int plugin_load(const char *libpath);
|
||||
int plugin_load(const char *filename);
|
||||
int plugin_search(const char *pathname);
|
||||
#endif
|
||||
|
||||
|
@ -15,12 +15,14 @@ include ../Makefile.top
|
||||
|
||||
TARGETS=fence_virtd
|
||||
|
||||
MODULES=libvirt.so checkpoint.so
|
||||
MODULES=libvirt.so checkpoint.so multicast.so
|
||||
|
||||
fence_virtd_SOURCES = mcast.c main.c plugin.c
|
||||
fence_virtd_SOURCES = main.c plugin.c
|
||||
|
||||
libvirt_so_SOURCES = libvirt.c
|
||||
|
||||
multicast_so_SOURCES = mcast.c
|
||||
|
||||
checkpoint_so_SOURCES = virt.c vm_states.c
|
||||
|
||||
INCLUDES=-I../include\
|
||||
@ -41,6 +43,9 @@ all: ${TARGETS} ${MODULES}
|
||||
fence_virtd: ${fence_virtd_SOURCES:.c=.o}
|
||||
gcc -o $@ $^ $(LIBS) $(MAIN_LIBS)
|
||||
|
||||
multicast.so: ${multicast_so_SOURCES:.c=.o}
|
||||
gcc -o $@ $^ $(LIBS) -shared
|
||||
|
||||
libvirt.so: ${libvirt_so_SOURCES:.c=.o}
|
||||
gcc -o $@ $^ $(LIBS) -shared
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char val[80];
|
||||
char val[4096];
|
||||
char listener_name[80];
|
||||
char backend_name[80];
|
||||
const char *config_file = DEFAULT_CONFIG_FILE;
|
||||
@ -74,14 +74,24 @@ main(int argc, char **argv)
|
||||
printf("Backend plugin: %s\n", backend_name);
|
||||
|
||||
#ifdef _MODULE
|
||||
if (plugin_load("./libvirt.so") < 0) {
|
||||
printf("Doom\n");
|
||||
if (sc_get(config, "fence_virtd/@module_path", val,
|
||||
sizeof(val))) {
|
||||
printf("Failed to determine module path.\n");
|
||||
return -1;
|
||||
}
|
||||
if (plugin_load("/usr/lib64/fence_virt/libvirt.so") < 0) {
|
||||
printf("Doom\n");
|
||||
|
||||
printf("Searching %s for plugins...\n", val);
|
||||
|
||||
opt = plugin_search(val);
|
||||
if (opt > 0) {
|
||||
printf("%d plugins found\n", opt);
|
||||
} else {
|
||||
printf("No plugins found\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
plugin_dump();
|
||||
#endif
|
||||
|
||||
lp = plugin_find_listener(listener_name);
|
||||
if (!lp) {
|
||||
|
@ -552,7 +552,7 @@ static listener_plugin_t mcast_plugin = {
|
||||
};
|
||||
|
||||
|
||||
#ifdef _MODULE_FOO
|
||||
#ifdef _MODULE
|
||||
double
|
||||
LISTENER_VER_SYM(void)
|
||||
{
|
||||
|
277
server/plugin.c
277
server/plugin.c
@ -25,7 +25,6 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <list.h>
|
||||
@ -33,7 +32,7 @@
|
||||
#include <server_plugin.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
typedef struct _plugin_list {
|
||||
list_head();
|
||||
@ -44,11 +43,17 @@ typedef struct _plugin_list {
|
||||
|
||||
static plugin_list_t *server_plugins = NULL;
|
||||
|
||||
|
||||
int
|
||||
plugin_reg_backend(const backend_plugin_t *plugin)
|
||||
{
|
||||
plugin_list_t *newplug;
|
||||
|
||||
if (plugin_find_backend(plugin->name)) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
newplug = malloc(sizeof(*newplug));
|
||||
if (!newplug)
|
||||
return -1;
|
||||
@ -66,6 +71,11 @@ plugin_reg_listener(const listener_plugin_t *plugin)
|
||||
{
|
||||
plugin_list_t *newplug;
|
||||
|
||||
if (plugin_find_listener(plugin->name)) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
newplug = malloc(sizeof(*newplug));
|
||||
if (!newplug)
|
||||
return -1;
|
||||
@ -95,6 +105,7 @@ plugin_dump(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const backend_plugin_t *
|
||||
plugin_find_backend(const char *name)
|
||||
{
|
||||
@ -129,6 +140,109 @@ plugin_find_listener(const char *name)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
backend_plugin_load(void *handle, const char *libpath)
|
||||
{
|
||||
const backend_plugin_t *plug = NULL;
|
||||
double (*modversion)(void);
|
||||
backend_plugin_t *(*modinfo)(void);
|
||||
|
||||
modversion = dlsym(handle, BACKEND_VER_STR);
|
||||
if (!modversion) {
|
||||
#ifdef DEBUG
|
||||
printf("Failed to map %s\n", BACKEND_VER_STR);
|
||||
#endif
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (modversion() != PLUGIN_VERSION_BACKEND) {
|
||||
#ifdef DEBUG
|
||||
printf("API version mismatch in %s: \n"
|
||||
" %f expected; %f received.\n", libpath,
|
||||
PLUGIN_VERSION_BACKEND, modversion());
|
||||
#endif
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
modinfo = dlsym(handle, BACKEND_INFO_STR);
|
||||
if (!modinfo) {
|
||||
#ifdef DEBUG
|
||||
printf("Failed to map %s\n", BACKEND_INFO_STR);
|
||||
#endif
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
plug = modinfo();
|
||||
if (plugin_reg_backend(plug) < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
printf("Registered backend plugin %s %s\n",
|
||||
plug->name, plug->version);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
listener_plugin_load(void *handle, const char *libpath)
|
||||
{
|
||||
const listener_plugin_t *plug = NULL;
|
||||
double (*modversion)(void);
|
||||
listener_plugin_t *(*modinfo)(void);
|
||||
|
||||
modversion = dlsym(handle, LISTENER_VER_STR);
|
||||
if (!modversion) {
|
||||
#ifdef DEBUG
|
||||
printf("Failed to map %s\n", LISTENER_VER_STR);
|
||||
#endif
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (modversion() != PLUGIN_VERSION_LISTENER) {
|
||||
#ifdef DEBUG
|
||||
printf("API version mismatch in %s: \n"
|
||||
" %f expected; %f received.\n", libpath,
|
||||
PLUGIN_VERSION_LISTENER, modversion());
|
||||
#endif
|
||||
dlclose(handle);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
modinfo = dlsym(handle, LISTENER_INFO_STR);
|
||||
if (!modinfo) {
|
||||
#ifdef DEBUG
|
||||
printf("Failed to map %s\n", LISTENER_INFO_STR);
|
||||
#endif
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
plug = modinfo();
|
||||
if (plugin_reg_listener(plug) < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
printf("Registered listener plugin %s %s\n",
|
||||
plug->name, plug->version);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load a cluster plugin .so file and map all the functions
|
||||
* provided to entries in a backend_plugin_t structure.
|
||||
@ -142,9 +256,6 @@ int
|
||||
plugin_load(const char *libpath)
|
||||
{
|
||||
void *handle = NULL;
|
||||
const backend_plugin_t *plug = NULL;
|
||||
double (*modversion)(void);
|
||||
backend_plugin_t *(*modinfo)(void);
|
||||
struct stat sb;
|
||||
|
||||
errno = 0;
|
||||
@ -178,52 +289,140 @@ plugin_load(const char *libpath)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Loading plugin from %s\n", libpath);
|
||||
#endif
|
||||
handle = dlopen(libpath, RTLD_LAZY);
|
||||
if (!handle) {
|
||||
errno = ELIBACC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
modversion = dlsym(handle, BACKEND_VER_STR);
|
||||
if (!modversion) {
|
||||
#ifdef DEBUG
|
||||
printf("Failed to map %s\n", BACKEND_VER_STR);
|
||||
#endif
|
||||
if (!backend_plugin_load(handle, libpath) ||
|
||||
!listener_plugin_load(handle, libpath))
|
||||
return 0;
|
||||
|
||||
dlclose(handle);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
Free up a null-terminated array of strings
|
||||
*/
|
||||
static void
|
||||
free_dirnames(char **dirnames)
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
for (; dirnames[x]; x++)
|
||||
free(dirnames[x]);
|
||||
|
||||
free(dirnames);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_compare(const void *a, const void *b)
|
||||
{
|
||||
return strcmp((const char *)a, (const char *)b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read all entries in a directory and return them in a NULL-terminated,
|
||||
sorted array.
|
||||
*/
|
||||
static int
|
||||
read_dirnames_sorted(const char *directory, char ***dirnames)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
char filename[1024];
|
||||
int count = 0, x = 0;
|
||||
|
||||
dir = opendir(directory);
|
||||
if (!dir)
|
||||
return -1;
|
||||
|
||||
/* Count the number of plugins */
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
++count;
|
||||
|
||||
/* Malloc the entries */
|
||||
*dirnames = malloc(sizeof(char *) * (count+1));
|
||||
if (!*dirnames) {
|
||||
#ifdef DEBUG
|
||||
printf("%s: Failed to malloc %d bytes",
|
||||
__FUNCTION__, (int)(sizeof(char *) * (count+1)));
|
||||
#endif
|
||||
closedir(dir);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
memset(*dirnames, 0, sizeof(char *) * (count + 1));
|
||||
rewinddir(dir);
|
||||
|
||||
/* Store the directory names. */
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
snprintf(filename, sizeof(filename), "%s/%s", directory,
|
||||
entry->d_name);
|
||||
|
||||
(*dirnames)[x] = strdup(filename);
|
||||
if (!(*dirnames)[x]) {
|
||||
#ifdef DEBUG
|
||||
printf("Failed to duplicate %s\n",
|
||||
filename);
|
||||
#endif
|
||||
free_dirnames(*dirnames);
|
||||
closedir(dir);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
|
||||
if (modversion() != PLUGIN_VERSION_BACKEND) {
|
||||
#ifdef DEBUG
|
||||
printf("API version mismatch in %s: \n"
|
||||
" %f expected; %f received.\n", libpath,
|
||||
, modversion());
|
||||
#endif
|
||||
dlclose(handle);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
modinfo = dlsym(handle, BACKEND_INFO_STR);
|
||||
if (!modinfo) {
|
||||
#ifdef DEBUG
|
||||
printf("Failed to map %s\n", BACKEND_INFO_STR);
|
||||
#endif
|
||||
dlclose(handle);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
plug = modinfo();
|
||||
if (plugin_reg_backend(plug) < 0) {
|
||||
dlclose(handle);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
} else {
|
||||
printf("Registered plugin %s %s\n",
|
||||
plug->name, plug->version);
|
||||
}
|
||||
/* Sort the directory names. */
|
||||
qsort((*dirnames), count, sizeof(char *), _compare);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
int
|
||||
plugin_search(const char *pathname)
|
||||
{
|
||||
int found = 0;
|
||||
int fcount = 0;
|
||||
char **filenames;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Trying plugins in %s\n", pathname);
|
||||
#endif
|
||||
if (read_dirnames_sorted(pathname, &filenames) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (fcount = 0; filenames[fcount]; fcount++) {
|
||||
|
||||
if (plugin_load(filenames[fcount]) == 0)
|
||||
++found;
|
||||
}
|
||||
|
||||
free_dirnames(filenames);
|
||||
if (!found) {
|
||||
#ifdef DEBUG
|
||||
printf("No usable plugins found.\n");
|
||||
#endif
|
||||
errno = ELIBACC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user