[Cluster-devel] cluster/fence/agents/xvm Makefile fence_xvmd.c ...
lhh at sourceware.org
lhh at sourceware.org
Tue Jun 26 17:23:42 UTC 2007
CVSROOT: /cvs/cluster
Module name: cluster
Changes by: lhh at sourceware.org 2007-06-26 17:23:41
Modified files:
fence/agents/xvm: Makefile fence_xvmd.c options.c options.h
Added files:
fence/agents/xvm: xml.c
fence/agents/xvm/tests: hvm.xml linux.xml
Log message:
Fix full-virt rebooting (#243872); add local-only / no-cluster mode to fence_xvmd
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/xvm/xml.c.diff?cvsroot=cluster&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/xvm/Makefile.diff?cvsroot=cluster&r1=1.8&r2=1.9
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/xvm/fence_xvmd.c.diff?cvsroot=cluster&r1=1.8&r2=1.9
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/xvm/options.c.diff?cvsroot=cluster&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/xvm/options.h.diff?cvsroot=cluster&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/xvm/tests/hvm.xml.diff?cvsroot=cluster&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/xvm/tests/linux.xml.diff?cvsroot=cluster&r1=1.1&r2=1.2
--- cluster/fence/agents/xvm/xml.c 2007/06/26 17:17:40 1.1
+++ cluster/fence/agents/xvm/xml.c 2007/06/26 17:23:41 1.2
@@ -0,0 +1,306 @@
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+
+
+xmlNodePtr
+get_os_node(xmlDocPtr doc)
+{
+ xmlNodePtr node;
+
+ /* Flip the property of the graphics port if it exists */
+ node = xmlDocGetRootElement(doc);
+ node = node->children;
+
+ while (node) {
+ if (!xmlStrcmp(node->name, (xmlChar *)"os"))
+ break;
+ node = node->next;
+ }
+
+ return node;
+}
+
+
+int
+flip_graphics_port(xmlDocPtr doc)
+{
+ xmlNodePtr node, curr;
+
+ /* Flip the property of the graphics port if it exists */
+ node = xmlDocGetRootElement(doc);
+ node = node->children;
+
+ while (node) {
+ if (!xmlStrcmp(node->name, (xmlChar *)"devices"))
+ break;
+ node = node->next;
+ }
+
+ node = node->children;
+ curr = node;
+ while (curr) {
+ if (!xmlStrcmp(curr->name, (xmlChar *)"graphics"))
+ break;
+ curr = curr->next;
+ }
+
+ if (xmlGetProp(curr, (xmlChar *)"port")) {
+ printf("Zapping the port spec\n");
+ xmlSetProp(curr, (xmlChar *)"port", (xmlChar *)"-1");
+ }
+
+ return 0;
+}
+
+
+int
+cleanup_xml_doc(xmlDocPtr doc)
+{
+ xmlNodePtr os_node, curr;
+ int type = 0;
+ char *val;
+
+ curr = xmlDocGetRootElement(doc);
+ if (xmlStrcmp(curr->name, (xmlChar *)"domain")) {
+ printf("Invalid XML\n");
+ return -1;
+ }
+
+ flip_graphics_port(doc);
+
+ os_node = get_os_node(doc);
+
+ curr = os_node->children;
+ while (curr) {
+ if (!xmlStrcmp(curr->name, (xmlChar *)"type"))
+ break;
+ curr = curr->next;
+ }
+ if (!curr) {
+ printf("Unable to determine the domain type\n");
+ return -1;
+ }
+
+ val = (char *)xmlNodeGetContent(curr);
+ while (isspace(*val)) val++;
+
+ if (!strcasecmp(val, "hvm")) {
+ type = 1;
+ printf("Virtual machine is HVM\n");
+ } else if (!strcasecmp(val, "linux")) {
+ type = 2;
+ printf("Virtual machine is Linux\n");
+ }
+
+ /* Node is still pointing to the <os> block */
+ if (type == 2) {
+ printf("Unlinkiking %s block\n", (char *)os_node->name);
+ xmlUnlinkNode(os_node);
+ xmlFreeNode(os_node);
+ }
+
+ return 0;
+}
+
+
+int
+xtree_readfile(const char *filename, xmlDocPtr *xtreep)
+{
+ xmlNodePtr cur;
+
+ xmlKeepBlanksDefault(0);
+ xmlIndentTreeOutput = 1;
+
+ *xtreep = xmlParseFile(filename);
+
+ if (!*xtreep)
+ return -1;
+
+ if (!((cur = xmlDocGetRootElement(*xtreep)))) {
+ xmlFreeDoc(*xtreep);
+ *xtreep = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+xtree_readbuffer(const char *buffer, size_t size, xmlDocPtr *xtreep)
+{
+ xmlNodePtr cur;
+
+ xmlKeepBlanksDefault(0);
+ xmlIndentTreeOutput = 1;
+
+ *xtreep = xmlParseMemory(buffer, size);
+
+ if (!*xtreep) {
+ printf("parse failure %p %d\n", buffer, (int)size);
+ return -1;
+ }
+
+ if (!((cur = xmlDocGetRootElement(*xtreep)))) {
+ printf("root element failure\n");
+ xmlFreeDoc(*xtreep);
+ *xtreep = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+xtree_writefile(const char *filename, xmlDocPtr xtree)
+{
+ char tmpfn[1024];
+ int fd, tmpfd;
+ xmlChar *buffer;
+ struct flock flock;
+ int n, remain, written, size = 0;
+
+ snprintf(tmpfn, sizeof(tmpfn), "%s.XXXXXX", filename);
+ tmpfd = mkstemp(tmpfn);
+ if (tmpfd == -1)
+ return -1;
+
+ memset(&flock, 0, sizeof(flock));
+ flock.l_type = F_WRLCK;
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_SYNC);
+ if (fd == -1) {
+ n = errno;
+ close(tmpfd);
+ unlink(tmpfn);
+ errno = n;
+ return -1;
+ }
+
+ while (fcntl(fd, F_SETLKW, &flock) == -1) {
+ if (errno == EINTR)
+ continue;
+ n = errno;
+ close(fd);
+ close(tmpfd);
+ unlink(tmpfn);
+ errno = n;
+ return -1;
+ }
+
+ xmlDocDumpFormatMemory(xtree, (xmlChar **)&buffer, (int *)&size, 1);
+
+ written = 0;
+ remain = size;
+ while (remain) {
+ n = write(tmpfd, buffer + written, remain);
+
+ if (n == -1) {
+ if (errno == EINTR)
+ continue;
+
+ free(buffer);
+ n = errno;
+ close(fd);
+ close(tmpfd);
+ unlink(tmpfn);
+ errno = n;
+ return -1;
+ }
+
+ written += n;
+ remain -= n;
+ }
+
+ xmlFree(buffer);
+ if (rename(tmpfn, filename) == -1) {
+ n = errno;
+ close(fd);
+ close(tmpfd);
+ unlink(tmpfn);
+ errno = n;
+ return -1;
+ }
+
+ close(fd);
+ fsync(tmpfd);
+ close(tmpfd);
+ return 0;
+}
+
+
+int
+xtree_writebuffer(xmlDocPtr xtree, char **buffer, size_t *size)
+{
+ *size = 0;
+ xmlDocDumpFormatMemory(xtree, (xmlChar **)buffer, (int *)size, 1);
+ return 0;
+}
+
+
+int
+cleanup_xml(char *desc, char **ret, size_t *retsz)
+{
+ xmlDocPtr xtree;
+ int rv;
+
+ *ret = NULL;
+ if (xtree_readbuffer(desc, strlen(desc), &xtree) < 0) {
+ xmlCleanupParser();
+ return -1;
+ }
+
+ rv = cleanup_xml_doc(xtree);
+ if (xtree_writebuffer(xtree, ret, retsz) < 0)
+ rv = -1;
+
+ if (*ret && rv < 0)
+ free(*ret);
+ xmlFreeDoc(xtree);
+ xmlCleanupParser();
+ return rv;
+}
+
+
+#ifdef STANDALONE
+int
+main(int argc, char **argv)
+{
+ char *file = NULL;
+ char *buf;
+ size_t sz;
+ int opt;
+ xmlDocPtr xtree;
+
+ while ((opt = getopt(argc, argv, "f:")) != EOF) {
+ switch(opt) {
+ case 'f':
+ file = optarg;
+ break;
+ }
+ }
+
+ if (!file) {
+ printf("No file specified\n");
+ return 1;
+ }
+
+ if (xtree_readfile(file, &xtree) < 0)
+ return -1;
+
+ cleanup_xml_doc(xtree);
+
+ xtree_writebuffer(xtree, &buf, &sz);
+ write(1, buf, sz);
+
+ return 0;
+}
+#endif
--- cluster/fence/agents/xvm/Makefile 2007/06/01 09:45:32 1.8
+++ cluster/fence/agents/xvm/Makefile 2007/06/26 17:23:41 1.9
@@ -22,7 +22,8 @@
OBJS2= fence_xvmd.o \
virt.o \
options-ccs.o \
- vm_states.o
+ vm_states.o \
+ xml.o
SHAREDOBJS= mcast.o \
simple_auth.o \
@@ -35,12 +36,14 @@
CFLAGS += -I${ccsincdir} -I${cmanincdir} -I${openaisincdir}
CFLAGS += -I${virtincdir} -I${nssincdir} -I${nsprincdir}
CFLAGS += -I${incdir}
+CFLAGS += `xml2-config --cflags`
LDFLAGS += -L${ccslibdir} -L${cmanlibdir} -L${dlmlibdir}
LDFLAGS += -L${nsslibdir} -L${nsprlibdir} -L${libdir}
-LDFLAGS += -lccs -lcman -ldlm -lnss3 -lnspr4
+LDFLAGS += -lccs -lcman -ldlm -lnss3 -lnspr4
EXTRA_LDFLAGS += -L${virtlibdir} -lvirt -L${openaislibdir} -lSaCkpt
+EXTRA_LDFLAGS += `xml2-config --libs`
all: ${TARGET1} ${TARGET2}
@@ -56,6 +59,10 @@
clean:
rm -f ${TARGET1} ${TARGET2} *~ *.o
+testprog:
+ gcc -o testprog xml.c -I/usr/include/libxml2 -lxml2 \
+ -DSTANDALONE -ggdb
+
install: all
if [ ! -d ${sbindir} ]; then \
install -d ${sbindir}; \
--- cluster/fence/agents/xvm/fence_xvmd.c 2007/01/10 20:30:47 1.8
+++ cluster/fence/agents/xvm/fence_xvmd.c 2007/06/26 17:23:41 1.9
@@ -55,6 +55,9 @@
static int running = 1;
+
+int cleanup_xml(char *xmldesc, char **ret, size_t *retsz);
+
int
connect_tcp(fence_req_t *req, fence_auth_type_t auth,
void *key, size_t key_len)
@@ -165,48 +168,6 @@
}
-/*
- Nuke the OS block if this domain was booted using a bootloader.
- XXX We probably should use libxml2 to do this, but this is very fast
- */
-void
-cleanup_xmldesc(char *xmldesc)
-{
- char *start = NULL;
- char *end = NULL;
-
-#define STARTBOOTTAG "<bootloader>"
-#define ENDBOOTTAG "</bootloader>"
-#define STARTOSTAG "<os>"
-#define ENDOSTAG "</os>"
-
- /* Part 1: Check for a boot loader */
- start = strcasestr(xmldesc, STARTBOOTTAG);
- if (start) {
- start += strlen(STARTBOOTTAG);
- end = strcasestr(start, ENDBOOTTAG);
- if (end == start) {
- /* Empty bootloader tag -> return */
- return;
- }
- }
-
- /* Part 2: Nuke the <os> tag */
- start = strcasestr(xmldesc, STARTOSTAG);
- if (!start)
- return;
- end = strcasestr(start, ENDOSTAG);
- if (!end)
- return;
- end += strlen(ENDOSTAG);
-
- dprintf(3, "Clearing %d bytes starting @ %p\n", (int)(end-start),
- start);
-
- memset(start, ' ', end-start);
-}
-
-
static inline int
wait_domain(fence_req_t *req, virConnectPtr vp, int timeout)
{
@@ -262,7 +223,8 @@
int fd, ret = -1;
virDomainPtr vdp;
char response = 1;
- char *domain_desc;
+ char *domain_desc, *domain_desc_sanitized;
+ size_t sz;
if (!(vdp = get_domain(req, vp))) {
dprintf(2, "Could not find domain: %s\n", req->domain);
@@ -305,7 +267,14 @@
if (domain_desc) {
dprintf(3, "[[ XML Domain Info ]]\n");
dprintf(3, "%s\n[[ XML END ]]\n", domain_desc);
- cleanup_xmldesc(domain_desc);
+
+ sz = 0;
+ if (cleanup_xml(domain_desc,
+ &domain_desc_sanitized, &sz) == 0) {
+ free(domain_desc);
+ domain_desc = domain_desc_sanitized;
+ }
+
dprintf(3, "[[ XML Domain Info (modified) ]]\n");
dprintf(3, "%s\n[[ XML END ]]\n", domain_desc);
} else {
@@ -431,7 +400,7 @@
if (!hp || !domain || !state || !strlen((char *)domain))
return -1;
- if (!strcmp("Domain-0", (char *)domain))
+ if (!strcmp(DOMAIN0NAME, (char *)domain))
return -1;
return ckpt_read(hp, (char *)domain, state, sizeof(*state));
@@ -564,10 +533,10 @@
struct sockaddr_in sin;
int len;
int n;
- int my_id;
+ int my_id = 1;
socklen_t slen;
fence_req_t data;
- virConnectPtr vp;
+ virConnectPtr vp = NULL;
virt_list_t *vl = NULL;
virt_state_t *dom = NULL;
@@ -575,7 +544,9 @@
if (!vp)
perror("virConnectOpen");
- get_cman_ids(ch, &my_id, NULL);
+ if (!(args->flags & F_NOCLUSTER))
+ get_cman_ids(ch, &my_id, NULL);
+
printf("My Node ID = %d\n", my_id);
if (vp) {
@@ -615,11 +586,14 @@
/* Update list of VMs from libvirt. */
virt_list_update(vp, &vl, my_id);
vl_print(vl);
+
/* Store information here */
- if (args->flags & F_USE_UUID)
- store_domains_by_uuid(h, vl);
- else
- store_domains_by_name(h, vl);
+ if (!(args->flags & F_NOCLUSTER)) {
+ if (args->flags & F_USE_UUID)
+ store_domains_by_uuid(h, vl);
+ else
+ store_domains_by_name(h, vl);
+ }
/*
* If no requests, we're done
@@ -661,7 +635,7 @@
dom = vl_find_uuid(vl, (char *)data.domain);
else
dom = vl_find_name(vl, (char *)data.domain);
- if (!dom) {
+ if (!dom && !(args->flags & F_NOCLUSTER)) {
handle_remote_domain(ch, h, &data, args->auth,
key, key_len, my_id);
continue;
@@ -702,8 +676,8 @@
int mc_sock;
char key[4096];
int key_len = 0, x;
- char *my_options = "dfi:a:p:C:c:k:u?hV";
- cman_handle_t ch;
+ char *my_options = "dfi:a:p:C:c:k:u?hLXV";
+ cman_handle_t ch = NULL;
void *h;
args_init(&args);
@@ -735,8 +709,10 @@
if (args.auth != AUTH_NONE || args.hash != HASH_NONE) {
key_len = read_key_file(args.key_file, key, sizeof(key));
if (key_len < 0) {
- printf("Could not read key file\n");
- return 1;
+ printf("Could not read %s; operating without "
+ "authentication\n", args.key_file);
+ args.auth = AUTH_NONE;
+ args.hash = HASH_NONE;
}
}
@@ -758,32 +734,34 @@
return 1;
}
- /* Wait for cman to start. */
- x = 0;
- while ((ch = cman_init(NULL)) == NULL) {
- if (!x) {
- printf("Could not connect to CMAN; retrying...\n");
- x = 1;
- }
- sleep(3);
- }
- if (x)
- printf("Connected to CMAN\n");
- /* Wait for quorum */
- while (!cman_is_quorate(ch))
- sleep(3);
-
- /* Wait for openais checkpointing to become available */
- x = 0;
- while ((h = ckpt_init("vm_states", 262144, 4096, 64, 10)) == NULL) {
- if (!x) {
- printf("Could not initialize saCkPt; retrying...\n");
- x = 1;
+ if (!(args.flags & F_NOCLUSTER)) {
+ /* Wait for cman to start. */
+ x = 0;
+ while ((ch = cman_init(NULL)) == NULL) {
+ if (!x) {
+ printf("Could not connect to CMAN; retrying...\n");
+ x = 1;
+ }
+ sleep(3);
+ }
+ if (x)
+ printf("Connected to CMAN\n");
+ /* Wait for quorum */
+ while (!cman_is_quorate(ch))
+ sleep(3);
+
+ /* Wait for openais checkpointing to become available */
+ x = 0;
+ while ((h = ckpt_init("vm_states", 262144, 4096, 64, 10)) == NULL) {
+ if (!x) {
+ printf("Could not initialize saCkPt; retrying...\n");
+ x = 1;
+ }
+ sleep(3);
}
- sleep(3);
+ if (x)
+ printf("Checkpoint initialized\n");
}
- if (x)
- printf("Checkpoint initialized\n");
if (args.family == PF_INET)
mc_sock = ipv4_recv_sk(args.addr, args.port);
--- cluster/fence/agents/xvm/options.c 2006/11/30 21:15:00 1.4
+++ cluster/fence/agents/xvm/options.c 2007/06/26 17:23:41 1.5
@@ -253,6 +253,13 @@
}
+static inline void
+assign_nocluster(fence_xvm_args_t *args, struct arg_info *arg, char *value)
+{
+ args->flags |= F_NOCLUSTER;
+}
+
+
/** ALL valid command line and stdin arguments for this fencing agent */
static struct arg_info _arg_info[] = {
{ '\xff', NULL, "agent",
@@ -326,6 +333,10 @@
{ 'X', "-X", NULL,
"Do not connect to CCS for configuration",
assign_noccs },
+
+ { 'L', "-L", NULL,
+ "Local mode only (no cluster)",
+ assign_nocluster },
{ 'V', "-V", NULL,
"Display version and exit",
--- cluster/fence/agents/xvm/options.h 2006/11/13 16:13:50 1.2
+++ cluster/fence/agents/xvm/options.h 2007/06/26 17:23:41 1.3
@@ -27,7 +27,8 @@
F_USE_UUID = 0x10,
F_VERSION = 0x20,
F_CCSERR = 0x40,
- F_CCSFAIL = 0x80
+ F_CCSFAIL = 0x80,
+ F_NOCLUSTER = 0x100
} arg_flags_t;
--- cluster/fence/agents/xvm/tests/hvm.xml 2007/06/26 17:17:40 1.1
+++ cluster/fence/agents/xvm/tests/hvm.xml 2007/06/26 17:23:41 1.2
@@ -0,0 +1,32 @@
+<domain type='xen' id='707'>
+ <name>pjc-xen-06</name>
+ <uuid>081b372c69a68432a13640fa03339353</uuid>
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ </os>
+ <memory>524288</memory>
+ <vcpu>1</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <features>
+ <pae/>
+ </features>
+ <devices>
+ <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+ <interface type='bridge'>
+ <source bridge='xenbr0'/>
+ <mac address='02:10:15:84:04:06'/>
+ <script path='vif-bridge'/>
+ </interface>
+ <disk type='file' device='disk'>
+ <driver name='file'/>
+ <source file='/root/pjc6'/>
+ <target dev='hda'/>
+ </disk>
+ <graphics type='vnc' port='5905'/>
+ <console tty='/dev/pts/5'/>
+ </devices>
+</domain>
+
--- cluster/fence/agents/xvm/tests/linux.xml 2007/06/26 17:17:40 1.1
+++ cluster/fence/agents/xvm/tests/linux.xml 2007/06/26 17:23:41 1.2
@@ -0,0 +1,31 @@
+<domain type='xen' id='2'>
+ <name>r5filebacked1</name>
+ <uuid>1a31981a01944fe7b7486a384e93dbae</uuid>
+ <bootloader>/usr/bin/pygrub</bootloader>
+ <os>
+ <type>linux</type>
+ <kernel>/var/lib/xen/boot_kernel.jGsgBH</kernel>
+ <initrd>/var/lib/xen/boot_ramdisk.bYFu-q</initrd>
+ <cmdline>ro root=/dev/VolGroup00/LogVol00</cmdline>
+ </os>
+ <memory>512000</memory>
+ <vcpu>1</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <interface type='bridge'>
+ <source bridge='xenbr0'/>
+ <mac address='C0:D1:F1:ED:1D:11'/>
+ <script path='vif-bridge'/>
+ </interface>
+ <graphics type='vnc' port='5900'/>
+ <disk type='file' device='disk'>
+ <driver name='tap' type='aio'/>
+ <source file='/mnt/xen/r5filebacked1'/>
+ <target dev='xvda'/>
+ </disk>
+ <console tty='/dev/pts/0'/>
+ </devices>
+</domain>
+
More information about the Cluster-devel
mailing list