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); args_print(&args);
/* Additional validation here */ /* Additional validation here */
if (!args.domain) { if (!args.domain && (args.op != FENCE_DEVSTATUS &&
args.op != FENCE_HOSTLIST)) {
printf("No domain specified!\n"); printf("No domain specified!\n");
args.flags |= F_ERR; args.flags |= F_ERR;
} }

View File

@ -54,6 +54,7 @@
#include "tcp.h" #include "tcp.h"
#include "mcast.h" #include "mcast.h"
#include "debug.h" #include "debug.h"
#include "fdops.h"
static int 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 static int
tcp_exchange(int fd, fence_auth_type_t auth, void *key, tcp_exchange(int fd, fence_auth_type_t auth, void *key,
size_t key_len, int timeout) size_t key_len, int timeout)
@ -118,12 +156,18 @@ tcp_exchange(int fd, fence_auth_type_t auth, void *key,
ret = 1; ret = 1;
dbg_printf(3, "Waiting for return value from XVM host\n"); 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; return -1;
/* Read return code */ /* Read return code */
if (read(fd, &ret, 1) < 0) if (_read_retry(fd, &ret, 1, &tv) < 0)
ret = 1; ret = 1;
if (ret == (char)253) /* hostlist */ {
do_read_hostlist(fd, timeout);
ret = 0;
}
close(fd); close(fd);
if (ret == 0) if (ret == 0)
@ -178,8 +222,10 @@ send_multicast_packets(ip_list_t *ipl, fence_virt_args_t *args,
/* Build our packet */ /* Build our packet */
memset(&freq, 0, sizeof(freq)); memset(&freq, 0, sizeof(freq));
strncpy((char *)freq.domain, args->domain, if (args->domain && strlen((char *)args->domain)) {
sizeof(freq.domain)); strncpy((char *)freq.domain, args->domain,
sizeof(freq.domain));
}
freq.request = args->op; freq.request = args->op;
freq.hashtype = args->net.hash; freq.hashtype = args->net.hash;
freq.seqno = seqno; 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; args->op = FENCE_STATUS;
} else if (!strcasecmp(value, "devstatus")) { } else if (!strcasecmp(value, "devstatus")) {
args->op = FENCE_DEVSTATUS; args->op = FENCE_DEVSTATUS;
} else if (!strcasecmp(value, "hostlist")) {
args->op = FENCE_HOSTLIST;
} else { } else {
printf("Unsupported operation: %s\n", value); printf("Unsupported operation: %s\n", value);
args->flags |= F_ERR; args->flags |= F_ERR;

View File

@ -48,6 +48,13 @@ typedef int (*fence_status_callback)(const char *vm_name,
is responding to requests. */ is responding to requests. */
typedef int (*fence_devstatus_callback)(void *priv); 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, typedef int (*backend_init_fn)(backend_context_t *c,
config_object_t *config); config_object_t *config);
typedef int (*backend_cleanup_fn)(backend_context_t c); typedef int (*backend_cleanup_fn)(backend_context_t c);
@ -59,6 +66,7 @@ typedef struct _fence_callbacks {
fence_reboot_callback reboot; fence_reboot_callback reboot;
fence_status_callback status; fence_status_callback status;
fence_devstatus_callback devstatus; fence_devstatus_callback devstatus;
fence_hostlist_callback hostlist;
} fence_callbacks_t; } fence_callbacks_t;
typedef struct backend_plugin { typedef struct backend_plugin {

View File

@ -85,6 +85,15 @@ typedef struct __attribute__ ((packed)) _fence_req {
} fence_req_t; } 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_DEVICE "/dev/ttyS1"
#define DEFAULT_SERIAL_SPEED "115200,8N1" #define DEFAULT_SERIAL_SPEED "115200,8N1"
#define SERIAL_MAGIC 0x61626261 /* endian doesn't matter */ #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 static int
checkpoint_init(backend_context_t *c, config_object_t *config) checkpoint_init(backend_context_t *c, config_object_t *config)
{ {
@ -752,7 +762,8 @@ static fence_callbacks_t checkpoint_callbacks = {
.on = checkpoint_on, .on = checkpoint_on,
.reboot = checkpoint_reboot, .reboot = checkpoint_reboot,
.status = checkpoint_status, .status = checkpoint_status,
.devstatus = checkpoint_devstatus .devstatus = checkpoint_devstatus,
.hostlist = checkpoint_hostlist
}; };
static backend_plugin_t checkpoint_plugin = { 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 static int
lq_init(backend_context_t *c, config_object_t *config) 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 = { 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 = { 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; 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 static int
libvirt_init(backend_context_t *c, config_object_t *config) libvirt_init(backend_context_t *c, config_object_t *config)
{ {
@ -458,7 +486,8 @@ static fence_callbacks_t libvirt_callbacks = {
.on = libvirt_on, .on = libvirt_on,
.reboot = libvirt_reboot, .reboot = libvirt_reboot,
.status = libvirt_status, .status = libvirt_status,
.devstatus = libvirt_devstatus .devstatus = libvirt_devstatus,
.hostlist = libvirt_hostlist
}; };
static backend_plugin_t libvirt_plugin = { static backend_plugin_t libvirt_plugin = {

View File

@ -54,6 +54,7 @@
#include "mcast.h" #include "mcast.h"
#include "tcp.h" #include "tcp.h"
#include "debug.h" #include "debug.h"
#include "fdops.h"
#define NAME "multicast" #define NAME "multicast"
#define VERSION "1.0" #define VERSION "1.0"
@ -91,6 +92,11 @@ typedef struct _mcast_info {
} mcast_info; } mcast_info;
struct mcast_hostlist_arg {
int fd;
};
/* /*
* See if we fenced this node recently (successfully) * See if we fenced this node recently (successfully)
* If so, ignore the request for a few seconds. * 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 static int
do_fence_request_tcp(fence_req_t *req, mcast_info *info) do_fence_request_tcp(fence_req_t *req, mcast_info *info)
{ {
int fd = -1; int fd = -1;
char response = 1; char response = 1;
struct mcast_hostlist_arg arg;
fd = connect_tcp(req, info->args.auth, info->key, info->key_len); fd = connect_tcp(req, info->args.auth, info->key, info->key_len);
if (fd < 0) { if (fd < 0) {
@ -182,6 +243,7 @@ do_fence_request_tcp(fence_req_t *req, mcast_info *info)
strerror(errno)); strerror(errno));
goto out; goto out;
} }
arg.fd = fd;
switch(req->request) { switch(req->request) {
case FENCE_NULL: case FENCE_NULL:
@ -205,6 +267,12 @@ do_fence_request_tcp(fence_req_t *req, mcast_info *info)
case FENCE_DEVSTATUS: case FENCE_DEVSTATUS:
response = info->cb->devstatus(info->priv); response = info->cb->devstatus(info->priv);
break; 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"); 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 static int
null_init(backend_context_t *c, config_object_t *config) null_init(backend_context_t *c, config_object_t *config)
{ {
@ -164,7 +174,8 @@ static fence_callbacks_t null_callbacks = {
.on = null_on, .on = null_on,
.reboot = null_reboot, .reboot = null_reboot,
.status = null_status, .status = null_status,
.devstatus = null_devstatus .devstatus = null_devstatus,
.hostlist = null_hostlist
}; };
static backend_plugin_t null_plugin = { static backend_plugin_t null_plugin = {