// // 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 // #include #include #include #include #include #include #include #include #include #include "uuid-test.h" #include 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