forked from altcloud/fence-virt
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);
|
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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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 */
|
||||||
|
@ -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 = {
|
||||||
|
@ -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 = {
|
||||||
|
@ -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 = {
|
||||||
|
@ -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");
|
||||||
|
@ -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 = {
|
||||||
|
Loading…
Reference in New Issue
Block a user