Hostlist functionality for libvirt, libvirt-qpid
Signed-off-by: root <lon@users.sourceforge.net>
This commit is contained in:
parent
498ef770fe
commit
4d7839abce
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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");
|
||||
|
@ -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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user