Hostlist functionality for libvirt, libvirt-qpid

Signed-off-by: root <lon@users.sourceforge.net>
This commit is contained in:
root 2009-12-07 12:55:48 -05:00
parent 498ef770fe
commit 4d7839abce
10 changed files with 268 additions and 9 deletions

View File

@ -95,7 +95,8 @@ main(int argc, char **argv)
args_print(&args);
/* Additional validation here */
if (!args.domain) {
if (!args.domain && (args.op != FENCE_DEVSTATUS &&
args.op != FENCE_HOSTLIST)) {
printf("No domain specified!\n");
args.flags |= F_ERR;
}

View File

@ -54,6 +54,7 @@
#include "tcp.h"
#include "mcast.h"
#include "debug.h"
#include "fdops.h"
static int
@ -86,6 +87,43 @@ tcp_wait_connect(int lfd, int retry_tenths)
}
void
do_read_hostlist(int fd, int timeout)
{
host_state_t hinfo;
fd_set rfds;
struct timeval tv;
int ret;
do {
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = timeout;
tv.tv_usec = 0;
ret = _select_retry(fd+1, &rfds, NULL, NULL, &tv);
if (ret == 0) {
printf("Timed out!\n");
break;
}
ret = _read_retry(fd, &hinfo, sizeof(hinfo), &tv);
if (ret < sizeof(hinfo)) {
printf("Bad read!\n");
break;
}
if (strlen((char *)hinfo.uuid) == 0 &&
strlen((char *)hinfo.domain) == 0)
break;
printf("%-20.20s %s %s\n", hinfo.domain, hinfo.uuid,
(hinfo.state == 0) ? "off" : "on");
} while (1);
}
static int
tcp_exchange(int fd, fence_auth_type_t auth, void *key,
size_t key_len, int timeout)
@ -118,12 +156,18 @@ tcp_exchange(int fd, fence_auth_type_t auth, void *key,
ret = 1;
dbg_printf(3, "Waiting for return value from XVM host\n");
if (select(fd + 1, &rfds, NULL, NULL, &tv) <= 0)
if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0)
return -1;
/* Read return code */
if (read(fd, &ret, 1) < 0)
if (_read_retry(fd, &ret, 1, &tv) < 0)
ret = 1;
if (ret == (char)253) /* hostlist */ {
do_read_hostlist(fd, timeout);
ret = 0;
}
close(fd);
if (ret == 0)
@ -178,8 +222,10 @@ send_multicast_packets(ip_list_t *ipl, fence_virt_args_t *args,
/* Build our packet */
memset(&freq, 0, sizeof(freq));
strncpy((char *)freq.domain, args->domain,
sizeof(freq.domain));
if (args->domain && strlen((char *)args->domain)) {
strncpy((char *)freq.domain, args->domain,
sizeof(freq.domain));
}
freq.request = args->op;
freq.hashtype = args->net.hash;
freq.seqno = seqno;

View File

@ -192,6 +192,8 @@ assign_op(fence_virt_args_t *args, struct arg_info *arg, char *value)
args->op = FENCE_STATUS;
} else if (!strcasecmp(value, "devstatus")) {
args->op = FENCE_DEVSTATUS;
} else if (!strcasecmp(value, "hostlist")) {
args->op = FENCE_HOSTLIST;
} else {
printf("Unsupported operation: %s\n", value);
args->flags |= F_ERR;

View File

@ -48,6 +48,13 @@ typedef int (*fence_status_callback)(const char *vm_name,
is responding to requests. */
typedef int (*fence_devstatus_callback)(void *priv);
/* VMs available to fence. Returns 0 to caller if backend
is responding to requests and a host list can be produced */
typedef int (*hostlist_callback)(const char *vm_name, const char *uuid,
int state, void *arg);
typedef int (*fence_hostlist_callback)(hostlist_callback cb,
void *arg, void *priv);
typedef int (*backend_init_fn)(backend_context_t *c,
config_object_t *config);
typedef int (*backend_cleanup_fn)(backend_context_t c);
@ -59,6 +66,7 @@ typedef struct _fence_callbacks {
fence_reboot_callback reboot;
fence_status_callback status;
fence_devstatus_callback devstatus;
fence_hostlist_callback hostlist;
} fence_callbacks_t;
typedef struct backend_plugin {

View File

@ -85,6 +85,15 @@ typedef struct __attribute__ ((packed)) _fence_req {
} fence_req_t;
/* for host list */
typedef struct __attribute__ ((packed)) _host_info {
uint8_t domain[MAX_DOMAINNAME_LENGTH];
uint8_t uuid[MAX_DOMAINNAME_LENGTH];
uint8_t state;
uint8_t pad;
} host_state_t;
#define DEFAULT_SERIAL_DEVICE "/dev/ttyS1"
#define DEFAULT_SERIAL_SPEED "115200,8N1"
#define SERIAL_MAGIC 0x61626261 /* endian doesn't matter */

View File

@ -651,6 +651,16 @@ checkpoint_reboot(const char *vm_name, uint32_t seqno, void *priv)
}
static int
checkpoint_hostlist(hostlist_callback callback, void *arg, void *priv)
{
VALIDATE(priv);
printf("[CKPT] HOSTLIST operation\n");
return 1;
}
static int
checkpoint_init(backend_context_t *c, config_object_t *config)
{
@ -752,7 +762,8 @@ static fence_callbacks_t checkpoint_callbacks = {
.on = checkpoint_on,
.reboot = checkpoint_reboot,
.status = checkpoint_status,
.devstatus = checkpoint_devstatus
.devstatus = checkpoint_devstatus,
.hostlist = checkpoint_hostlist
};
static backend_plugin_t checkpoint_plugin = {

View File

@ -219,6 +219,79 @@ lq_reboot(const char *vm_name, uint32_t seqno, void *priv)
}
static int
lq_hostlist(hostlist_callback callback, void *arg, void *priv)
{
VALIDATE(priv);
Broker *b = NULL;
ConnectionSettings cs;
SessionManager::NameVector names;
Object::Vector domains;
unsigned i, tries = 0;
const char *vm_name, *vm_uuid, *vm_state_str;
int vm_state = 0, ret = 1;
printf("[libvirt-qpid] HOSTLIST operation\n");
cs.host = "127.0.0.1";
cs.port = 5672;
SessionManager::Settings s;
s.rcvObjects = true;
s.rcvEvents = false;
s.rcvHeartbeats = false;
s.userBindings = false;
s.methodTimeout = 10;
s.getTimeout = 10;
SessionManager sm(NULL, s);
// todo - authentication info!
try {
b = sm.addBroker(cs);
}
catch (...) {
std::cout << "Error connecting.\n";
return 1;
}
while (tries < 10) {
sleep(1);
sm.getObjects(domains, "domain", NULL, NULL);
if (domains.size() >= 1) {
break;
}
}
if (domains.size() < 1)
goto out;
for (i = 0; i < domains.size(); i++) {
vm_name = domains[i].attrString("name").c_str();
vm_uuid = domains[i].attrString("uuid").c_str();
vm_state_str = domains[i].attrString("state").c_str();
if (!strcasecmp(vm_state_str, "shutoff"))
vm_state = 0;
else
vm_state = 1;
callback(vm_name, vm_uuid, vm_state, arg);
}
ret = 0;
out:
sm.delBroker(b);
return 0;
}
static int
lq_init(backend_context_t *c, config_object_t *config)
{
@ -264,7 +337,8 @@ lq_shutdown(backend_context_t c)
static fence_callbacks_t lq_callbacks = {
lq_null, lq_off, lq_on, lq_reboot, lq_status, lq_devstatus
lq_null, lq_off, lq_on, lq_reboot, lq_status, lq_devstatus,
lq_hostlist
};
static backend_plugin_t lq_plugin = {

View File

@ -374,6 +374,34 @@ libvirt_reboot(const char *vm_name, uint32_t seqno, void *priv)
return ret;
}
static int
libvirt_hostlist(hostlist_callback callback, void *arg, void *priv)
{
struct libvirt_info *info = (struct libvirt_info *)priv;
virt_list_t *vl;
int x;
dbg_printf(5, "%s\n", __FUNCTION__);
VALIDATE(info);
vl = vl_get(info->vp, 1);
if (!vl)
return 1;
for (x = 0; x < vl->vm_count; x++) {
printf("Sending %s\n", vl->vm_states[x].v_uuid);
callback(vl->vm_states[x].v_name,
vl->vm_states[x].v_uuid,
vl->vm_states[x].v_state.s_state, arg);
}
vl_free(vl);
return 0;
}
static int
libvirt_init(backend_context_t *c, config_object_t *config)
{
@ -458,7 +486,8 @@ static fence_callbacks_t libvirt_callbacks = {
.on = libvirt_on,
.reboot = libvirt_reboot,
.status = libvirt_status,
.devstatus = libvirt_devstatus
.devstatus = libvirt_devstatus,
.hostlist = libvirt_hostlist
};
static backend_plugin_t libvirt_plugin = {

View File

@ -54,6 +54,7 @@
#include "mcast.h"
#include "tcp.h"
#include "debug.h"
#include "fdops.h"
#define NAME "multicast"
#define VERSION "1.0"
@ -91,6 +92,11 @@ typedef struct _mcast_info {
} mcast_info;
struct mcast_hostlist_arg {
int fd;
};
/*
* See if we fenced this node recently (successfully)
* If so, ignore the request for a few seconds.
@ -170,11 +176,66 @@ connect_tcp(fence_req_t *req, fence_auth_type_t auth,
}
static int
mcast_hostlist(const char *vm_name, const char *vm_uuid,
int state, void *priv)
{
struct mcast_hostlist_arg *arg = (struct mcast_hostlist_arg *)priv;
host_state_t hinfo;
struct timeval tv;
int ret;
strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain));
strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid));
hinfo.state = state;
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv);
if (ret == sizeof(hinfo))
return 0;
return 1;
}
static int
mcast_hostlist_begin(int fd)
{
struct timeval tv;
char val = (char)253;
tv.tv_sec = 1;
tv.tv_usec = 0;
return _write_retry(fd, &val, 1, &tv);
}
static int
mcast_hostlist_end(int fd)
{
host_state_t hinfo;
struct timeval tv;
int ret;
printf("Sending terminator packet\n");
memset(&hinfo, 0, sizeof(hinfo));
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = _write_retry(fd, &hinfo, sizeof(hinfo), &tv);
if (ret == sizeof(hinfo))
return 0;
return 1;
}
static int
do_fence_request_tcp(fence_req_t *req, mcast_info *info)
{
int fd = -1;
char response = 1;
struct mcast_hostlist_arg arg;
fd = connect_tcp(req, info->args.auth, info->key, info->key_len);
if (fd < 0) {
@ -182,6 +243,7 @@ do_fence_request_tcp(fence_req_t *req, mcast_info *info)
strerror(errno));
goto out;
}
arg.fd = fd;
switch(req->request) {
case FENCE_NULL:
@ -205,6 +267,12 @@ do_fence_request_tcp(fence_req_t *req, mcast_info *info)
case FENCE_DEVSTATUS:
response = info->cb->devstatus(info->priv);
break;
case FENCE_HOSTLIST:
mcast_hostlist_begin(arg.fd);
response = info->cb->hostlist(mcast_hostlist, &arg,
info->priv);
mcast_hostlist_end(arg.fd);
break;
}
dbg_printf(3, "Sending response to caller...\n");

View File

@ -112,6 +112,16 @@ null_reboot(const char *vm_name, uint32_t seqno, void *priv)
}
static int
null_hostlist(hostlist_callback callback, void *arg, void *priv)
{
VALIDATE(priv);
printf("[Null] HOSTLIST operation\n");
return 1;
}
static int
null_init(backend_context_t *c, config_object_t *config)
{
@ -164,7 +174,8 @@ static fence_callbacks_t null_callbacks = {
.on = null_on,
.reboot = null_reboot,
.status = null_status,
.devstatus = null_devstatus
.devstatus = null_devstatus,
.hostlist = null_hostlist
};
static backend_plugin_t null_plugin = {