Create server-side plugin architecture

Signed-off-by: Lon Hohberger <lhh@redhat.com>
This commit is contained in:
Lon Hohberger 2009-08-17 09:58:06 -04:00
parent aa4d011b75
commit 9ec497ddc6
10 changed files with 185 additions and 26 deletions

1
Makefile.top Normal file
View File

@ -0,0 +1 @@
CFLAGS=-fPIC -Wall -Wstrict-prototypes -Werror -ggdb -D_GNU_SOURCE

View File

@ -10,6 +10,7 @@
###############################################################################
###############################################################################
include=../Makefile.top
TARGETS=fence_virt fence_xvm
@ -21,8 +22,7 @@ INCLUDES=-I../include\
-I../../../cman/lib -I../../../ccs/lib -I/usr/include/libxml2 \
-I/usr/include/libvirt
CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" \
-Wall -Werror -Wstrict-prototypes -Wshadow -ggdb -D_GNU_SOURCE
CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\"
LIBS+=-L../../../cman/lib -L../../../ccs/lib -L${libdir}/openais \
-L../../../dlm/lib -lnss3 -lxml2

View File

@ -10,6 +10,7 @@
###############################################################################
###############################################################################
include ../Makefile.top
TARGETS=libfence_virt.a
@ -22,8 +23,7 @@ INCLUDES=-I../include \
-I../../../cman/lib -I../../../ccs/lib -I/usr/include/libxml2 \
-I/usr/include/libvirt
CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" \
-Wall -Werror -Wstrict-prototypes -Wshadow -ggdb -D_GNU_SOURCE
CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\"
LIBS+=-L../../../cman/lib -L../../../ccs/lib -L${libdir}/openais \
-L../../../dlm/lib -lnss3 -lxml2

View File

@ -33,7 +33,7 @@ typedef enum {
typedef enum {
MODE_MULTICAST = 0,
//MODE_BROADCAST = 1,
/*MODE_BROADCAST = 1,*/
MODE_SERIAL = 2,
MODE_VMCHANNEL = 3
} client_mode_t;

View File

@ -1,8 +1,21 @@
/* */
#include <uuid/uuid.h>
#define PLUGIN_VERSION_FRONTEND ((double)0.1)
#define PLUGIN_VERSION_BACKEND ((double)0.1)
#define FRONTEND_VER_SYM frontend_plugin_version
#define BACKEND_VER_SYM backend_plugin_version
#define FRONTEND_INFO_SYM frontend_plugin_info
#define BACKEND_INFO_SYM backend_plugin_info
#define FRONTEND_VER_STR "frontend_plugin_version"
#define BACKEND_VER_STR "backend_plugin_version"
#define FRONTEND_INFO_STR "frontend_plugin_info"
#define BACKEND_INFO_STR "backend_plugin_info"
typedef void * srv_context_t;
/* These callbacks hand requests off to the
@ -56,10 +69,11 @@ typedef struct _backend_plugin {
fence_cleanup_callback cleanup;
} plugin_t;
#ifndef _USE_MODULES
void plugin_register(const plugin_t *plugin);
int plugin_register(const plugin_t *plugin);
const plugin_t *plugin_find(const char *name);
void plugin_dump(void);
#ifdef _MODULE
int plugin_load(const char *libpath);
#endif

View File

@ -43,7 +43,7 @@ typedef enum {
AUTH_NONE = 0x0, /* Plain TCP */
AUTH_SHA1 = 0x1, /* Challenge-response (SHA1) */
AUTH_SHA256 = 0x2, /* Challenge-response (SHA256) */
AUTH_SHA512 = 0x3, /* Challenge-response (SHA512) */
AUTH_SHA512 = 0x3 /* Challenge-response (SHA512) */
/* AUTH_SSL_X509 = 0x10 SSL X509 certificates */
} fence_auth_type_t;

View File

@ -10,10 +10,14 @@
###############################################################################
###############################################################################
include ../Makefile.top
TARGETS=fence_virtd
fence_virtd_SOURCES = mcast.c libvirt.c main.c plugin.c
TARGETS=fence_virtd libvirt.so
fence_virtd_SOURCES = mcast.c main.c plugin.c
libvirt_so_SOURCES = libvirt.c
INCLUDES=-I../include\
-I/usr/include/openais -I/usr/include/libvirt \
@ -21,8 +25,7 @@ INCLUDES=-I../include\
-I../../../cman/lib -I../../../ccs/lib -I/usr/include/libxml2 \
-I/usr/include/libvirt
CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" \
-Wall -Werror -Wstrict-prototypes -Wshadow -ggdb -D_GNU_SOURCE
CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" -D_MODULE
LIBS+=-L/usr/lib64/openais -lnss3 -lxml2 -lSaCkpt -lccs -lvirt -lcman \
-L../common -lfence_virt
@ -32,6 +35,9 @@ all: ${TARGETS}
fence_virtd: ${fence_virtd_SOURCES:.c=.o}
gcc -o $@ $^ $(LIBS) -L../common -lfence_virt
libvirt.so: ${libvirt_so_SOURCES:.c=.o}
gcc -o $@ $^ $(LIBS) -shared -L../common -lvirt
%.o: %.c
gcc $(CFLAGS) -c -o $@ $^ $(INCLUDES)

View File

@ -305,14 +305,6 @@ static fence_callbacks_t libvirt_callbacks = {
.devstatus = libvirt_devstatus
};
#ifdef _MODULE
fence_callbacks_t *
plugin_callbacks(void)
{
return &libvirt_callbacks;
}
#else
static plugin_t libvirt_plugin = {
.name = NAME,
.version = VERSION,
@ -321,8 +313,22 @@ static plugin_t libvirt_plugin = {
.cleanup = libvirt_shutdown,
};
#ifdef _MODULE
double
BACKEND_VER_SYM(void)
{
return PLUGIN_VERSION_BACKEND;
}
const plugin_t *
BACKEND_INFO_SYM(void)
{
return &libvirt_plugin;
}
#else
static void __attribute__((constructor))
initialize_plugin(void)
libvirt_register_plugin(void)
{
plugin_register(&libvirt_plugin);
}

View File

@ -22,6 +22,11 @@ main(int argc, char **argv)
dset(99);
#ifdef _MODULE
if (plugin_load("./libvirt.so") < 0) {
printf("Doom\n");
}
#endif
plugin_dump();
p = plugin_find(plugin_name);

View File

@ -1,4 +1,33 @@
/*
Copyright Red Hat, Inc. 2002-2004, 2009
The Magma Cluster API Library is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version
2.1 of the License, or (at your option) any later version.
The Magma Cluster API Library is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
*/
/** @file
* Plugin loading routines
*/
#include <dlfcn.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <list.h>
#include <server_plugin.h>
#include <malloc.h>
@ -12,17 +41,18 @@ typedef struct _plugin_list {
static plugin_list_t *server_plugins = NULL;
void
int
plugin_register(const plugin_t *plugin)
{
plugin_list_t *newplug;
newplug = malloc(sizeof(*newplug));
if (!newplug)
return;
return -1;
memset(newplug, 0, sizeof(*newplug));
newplug->plugin = plugin;
list_insert(&server_plugins, newplug);
return 0;
}
void
@ -64,4 +94,101 @@ plugin_shutdown(const plugin_t *p, srv_context_t c)
return p->cleanup(c);
}
/**
* Load a cluster plugin .so file and map all the functions
* provided to entries in a plugin_t structure.
*
* @param libpath Path to file.
* @return NULL on failure, or plugin-specific
* (const) plugin_t * structure on
* success.
*/
int
plugin_load(const char *libpath)
{
void *handle = NULL;
const plugin_t *plug = NULL;
double (*modversion)(void);
plugin_t *(*modinfo)(void);
struct stat sb;
errno = 0;
if (!libpath) {
errno = EINVAL;
return -1;
}
if (stat(libpath, &sb) != 0) {
return -1;
}
/*
If it's not owner-readable or it's a directory,
ignore/fail. Thus, a user may change the permission of
a plugin "u-r" and this would then prevent magma apps
from loading it.
*/
if (S_ISDIR(sb.st_mode)) {
errno = EISDIR;
return -1;
}
if (!(sb.st_mode & S_IRUSR)) {
#ifdef DEBUG
printf("Ignoring %s (User-readable bit not set)\n",
libpath);
#endif
errno = EPERM;
return -1;
}
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
dlclose(handle);
errno = EINVAL;
return -1;
}
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;
}
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_register(plug) < 0) {
dlclose(handle);
errno = EINVAL;
return -1;
} else {
printf("Registered plugin %s %s\n",
plug->name, plug->version);
}
return 0;
}