fence-virt/server/libvirt-qpid.cpp
Lon Hohberger 2635e075b9 Pass source VM UUID (if known) to backend
Some backends (not yet implemented) which talk to management
layers will have mappings for what VMs can control what other
VMs.  So, the source VM UUID of the original request needs to
be sent along with the target VM UUID to the management layer
for arbitration.

Signed-off-by: Lon Hohberger <lon@users.sourceforge.net>
2010-01-13 13:52:55 -05:00

436 lines
8.1 KiB
C++

//
// Copyright Red Hat, Inc. 2009
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option) any
// later version.
//
// This program 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
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING. If not, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
// MA 02139, USA.
//
// Author: Lon Hohberger <lhh at redhat.com>
//
#include <stdio.h>
#include <simpleconfig.h>
#include <sys/types.h>
#include <stdint.h>
#include <time.h>
#include <server_plugin.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include "uuid-test.h"
#include <qpid/console/SessionManager.h>
using namespace qpid::console;
using namespace qpid::client;
#define NAME "libvirt-qpid"
#define VERSION "0.1"
#define MAGIC 0x1e01017a
struct lq_info {
int magic;
int port;
char *host;
char *username;
char *service;
int use_gssapi;
};
#define VALIDATE(arg) \
do {\
if (!arg || ((struct lq_info *)arg)->magic != MAGIC) { \
errno = EINVAL;\
return -1; \
} \
} while(0)
int
do_lq_request(struct lq_info *info, const char *vm_name,
const char *action)
{
Broker *b = NULL;
SessionManager::NameVector names;
Object::Vector domains;
Object *domain = NULL;
const char *property = "name";
unsigned i, tries = 0, found = 0;
if (is_uuid(vm_name) == 1) {
property = "uuid";
}
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);
ConnectionSettings cs;
if (info->host)
cs.host = info->host;
if (info->port)
cs.port = info->port;
if (info->username)
cs.username = info->username;
if (info->service)
cs.service = info->service;
if (info->use_gssapi)
cs.mechanism = "GSSAPI";
try {
b = sm.addBroker(cs);
}
catch (...) {
std::cout << "Error connecting.\n";
return 1;
}
while (tries < 10 && !found) {
sleep(1);
// why not com.redhat.libvirt:domain or having
// a way to specify that I want the domain objects from
// the com.redhat.libvirt namespace?!
sm.getObjects(domains, "domain", NULL, NULL);
for (i = 0; i < domains.size(); i++) {
#if 0
SchemaClass *c;
c = domains[i].getSchema();
#endif
if (strcmp(domains[i].attrString(property).c_str(),
vm_name)) {
continue;
}
found = 1;
domain = &domains[i];
break;
#if 0
for (j = 0; j < c->properties.size(); j++) {
if (!strcmp(c->properties[j]->name.c_str(), "name") &&
!strcmp(domains[i].attrString(c->properties[j]->name).c_str(), argv[1])) {
std::cout << c->properties[j]->name << " " << domains[i].attrString(c->properties[j]->name) << std::endl;
}
}
#endif
}
}
if (!found) {
return 1;
}
Object::AttributeMap attrs;
MethodResponse result;
std::cout << domain->attrString(property) << " "
<< domain->attrString("state") << std::endl;
domain->invokeMethod(action, attrs, result);
std::cout << "Response: " << result.code << " (" << result.text << ")" << std::endl;
sm.delBroker(b);
return result.code;
}
static int
lq_null(const char *vm_name, void *priv)
{
VALIDATE(priv);
printf("[libvirt-qpid] libvirt-qpid operation on %s\n", vm_name);
return 1;
}
static int
lq_off(const char *vm_name, const char *src, uint32_t seqno, void *priv)
{
VALIDATE(priv);
printf("[libvirt-qpid] OFF operation on %s\n", vm_name);
return do_lq_request((lq_info *)priv, vm_name, "destroy");
return 1;
}
static int
lq_on(const char *vm_name, const char *src, uint32_t seqno, void *priv)
{
VALIDATE(priv);
printf("[libvirt-qpid] ON operation on %s\n", vm_name);
return do_lq_request((lq_info *)priv, vm_name, "create");
}
static int
lq_devstatus(void *priv)
{
VALIDATE(priv);
printf("[libvirt-qpid] Device status\n");
return 0;
}
static int
lq_status(const char *vm_name, void *priv)
{
VALIDATE(priv);
printf("[libvirt-qpid] STATUS operation on %s\n", vm_name);
return 1;
}
static int
lq_reboot(const char *vm_name, const char *src, uint32_t seqno, void *priv)
{
VALIDATE(priv);
printf("[libvirt-qpid] REBOOT operation on %s\n", vm_name);
if (lq_off(vm_name, src, seqno, priv) != 0)
return 1;
sleep(1);
lq_on(vm_name, src, seqno, priv);
return 1;
}
static int
lq_hostlist(hostlist_callback callback, void *arg, void *priv)
{
VALIDATE(priv);
struct lq_info *info = (struct lq_info *)priv;
Broker *b = NULL;
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");
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);
ConnectionSettings cs;
if (info->host)
cs.host = info->host;
if (info->port)
cs.port = info->port;
if (info->username)
cs.username = info->username;
if (info->service)
cs.service = info->service;
if (info->use_gssapi)
cs.mechanism = "GSSAPI";
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)
{
char value[256];
struct lq_info *info = NULL;
info = (lq_info *)malloc(sizeof(*info));
if (!info)
return -1;
memset(info, 0, sizeof(*info));
info->port = 5672;
if(sc_get(config, "backends/libvirt-qpid/@host",
value, sizeof(value))==0){
printf("\n\nHOST = %s\n\n",value);
info->host = strdup(value);
if (!info->host) {
goto out_fail;
}
} else {
info->host = strdup("127.0.0.1");
}
if(sc_get(config, "backends/libvirt-qpid/@port",
value, sizeof(value)-1)==0){
printf("\n\nPORT = %d\n\n",atoi(value));
info->port = atoi(value);
}
if(sc_get(config, "backends/libvirt-qpid/@username",
value, sizeof(value))==0){
printf("\n\nUSERNAME = %s\n\n",value);
info->username = strdup(value);
if (!info->username) {
goto out_fail;
}
}
if(sc_get(config, "backends/libvirt-qpid/@service",
value, sizeof(value))==0){
printf("\n\nSERVICE = %s\n\n",value);
info->service = strdup(value);
if (!info->service) {
goto out_fail;
}
}
if(sc_get(config, "backends/libvirt-qpid/@gssapi",
value, sizeof(value)-1)==0){
printf("\n\nGSSAPI = %d\n\n",atoi(value));
if (atoi(value) > 0) {
info->use_gssapi = 1;
}
}
info->magic = MAGIC;
*c = (void *)info;
return 0;
out_fail:
free(info->service);
free(info->username);
free(info->host);
free(info);
return -1;
}
static int
lq_shutdown(backend_context_t c)
{
struct lq_info *info = (struct lq_info *)c;
VALIDATE(info);
info->magic = 0;
free(info->service);
free(info->username);
free(info->host);
free(info);
return 0;
}
static fence_callbacks_t lq_callbacks = {
lq_null, lq_off, lq_on, lq_reboot, lq_status, lq_devstatus,
lq_hostlist
};
static backend_plugin_t lq_plugin = {
NAME, VERSION, &lq_callbacks, lq_init, lq_shutdown
};
#ifdef _MODULE
extern "C" double
BACKEND_VER_SYM(void)
{
return PLUGIN_VERSION_BACKEND;
}
extern "C" const backend_plugin_t *
BACKEND_INFO_SYM(void)
{
return &lq_plugin;
}
#else
static void __attribute__((constructor))
lq_register_plugin(void)
{
plugin_reg_backend(&lq_plugin);
}
#endif