+Tue Dec 13 17:20:11 CET 2005 Daniel Veillard <veillard@redhat.com>
+
+ * include/libvir.h src/Makefile.am src/internal.h src/libvir.c
+ src/libvir_sym.version src/virsh.c src/xml.c: started working on
+ the XML dump, added a dumpxml virsh version and a bit of
+ infrastructure code. Found a way to detect dead ID from xenstore
+ data.
+
Mon Dec 12 14:21:18 CET 2005 Daniel Veillard <veillard@redhat.com>
* src/libvir.c src/xen_internal.c src/xen_internal.h: completing the
*/
int virDomainGetInfo (virDomainPtr domain,
virDomainInfoPtr info);
+char * virDomainGetXMLDesc (virDomainPtr domain,
+ int flags);
/*
* Dynamic control of domains
libvir_la_SOURCES = \
libvir.c internal.h \
hash.c hash.h \
- xen_internal.c xen_internal.h
+ xen_internal.c xen_internal.h \
+ xml.c
noinst_PROGRAMS=virsh
#ifndef __VIR_INTERNAL_H__
#define __VIR_INTERNAL_H__
+#include "hash.h"
+#include "libvir.h"
+
#ifdef __cplusplus
extern "C" {
#endif
fprintf(stderr, "Unimplemented block at %s:%d\n", \
__FILE__, __LINE__);
+/**
+ * VIR_CONNECT_MAGIC:
+ *
+ * magic value used to protect the API when pointers to connection structures
+ * are passed down by the uers.
+ */
+#define VIR_CONNECT_MAGIC 0x4F23DEAD
+
+/**
+ * VIR_DOMAIN_MAGIC:
+ *
+ * magic value used to protect the API when pointers to domain structures
+ * are passed down by the uers.
+ */
+#define VIR_DOMAIN_MAGIC 0xDEAD4321
+
+/*
+ * Flags for Xen connections
+ */
+#define VIR_CONNECT_RO 1
+
+/**
+ * _virConnect:
+ *
+ * Internal structure associated to a connection
+ */
+struct _virConnect {
+ unsigned int magic; /* specific value to check */
+ int handle; /* internal handle used for hypercall */
+ struct xs_handle *xshandle; /* handle to talk to the xenstore */
+ virHashTablePtr domains; /* hash table for known domains */
+ int flags; /* a set of connection flags */
+};
+
+/**
+ * _virDomain:
+ *
+ * Internal structure associated to a domain
+ */
+struct _virDomain {
+ unsigned int magic; /* specific value to check */
+ virConnectPtr conn; /* pointer back to the connection */
+ char *name; /* the domain external name */
+ char *path; /* the domain internal path */
+ int handle; /* internal handle for the dmonain ID */
+};
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
* - memory wrappers for malloc/free ?
*/
-#define VIR_CONNECT_MAGIC 0x4F23DEAD
-
-/*
- * Flags for Xen connections
- */
-#define VIR_CONNECT_RO 1
-
-/**
- * _virConnect:
- *
- * Internal structure associated to a connection
- */
-struct _virConnect {
- unsigned int magic; /* specific value to check */
- int handle; /* internal handle used for hypercall */
- struct xs_handle *xshandle; /* handle to talk to the xenstore */
- virHashTablePtr domains; /* hash table for known domains */
- int flags; /* a set of connection flags */
-};
-
-#define VIR_DOMAIN_MAGIC 0xDEAD4321
-
-/**
- * _virDomain:
- *
- * Internal structure associated to a domain
- */
-struct _virDomain {
- unsigned int magic; /* specific value to check */
- virConnectPtr conn; /* pointer back to the connection */
- char *name; /* the domain external name */
- char *path; /* the domain internal path */
- int handle; /* internal handle for the dmonain ID */
-};
-
/**
* virGetVersion:
* @libVer: return value for the library version (OUT)
* @flags: an optional set of virDomainFlags
*
* Launch a new Linux guest domain
+ * Not implemented yet. Very likely to be modified in order to express
+ * hardware informations in a convenient way.
*
* Returns a new domain object or NULL in case of failure
*/
ret->handle = id;
ret->path = path;
ret->name = virDomainDoStoreQuery(ret, "name");
+ if (ret->name == NULL) {
+ free(path);
+ free(ret);
+ return(NULL);
+ }
return(ret);
}
* @conn: pointer to the hypervisor connection
* @name: name for the domain
*
- * Try to lookup a domain on the given hypervisor
+ * Try to lookup a domain on the given hypervisor based on its name.
*
* Returns a new domain object or NULL in case of failure
*/
/**
* virDomainGetInfo:
- * @domain: a domain object or NULL
+ * @domain: a domain object
* @info: pointer to a virDomainInfo structure allocated by the user
*
* Extract information about a domain. Note that if the connection
}
return(0);
}
+
virDomainResume;
virDomainSetMaxMemory;
virDomainSuspend;
+ virDomainGetXMLDesc;
virGetVersion;
local: *;
};
return ret;
}
+/*
+ * "dumpxml" command
+ */
+static vshCmdInfo info_dumpxml[] = {
+ { "syntax", "dumpxml [--id <number> | --name <string> ]" },
+ { "help", "domain information in XML" },
+ { "desc", "Ouput the domain informations as an XML dump to stdout" },
+ { NULL, NULL }
+};
+
+static vshCmdOptDef opts_dumpxml[] = {
+ { "name", VSH_OT_STRING, 0, "domain name" },
+ { "id", VSH_OT_INT, 0, "domain id" },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+cmdDumpXML(vshControl *ctl, vshCmd *cmd) {
+ virDomainPtr dom;
+ int found, ret = TRUE;
+ char *name = vshCommandOptString(cmd, "name", NULL);
+ int id = vshCommandOptInt(cmd, "id", &found);
+ char *dump;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ if (found) {
+ if (!(dom = virDomainLookupByID(ctl->conn, id)))
+ vshError(ctl, FALSE, "failed to get domain '%d'", id);
+ } else {
+ if (!(dom = virDomainLookupByName(ctl->conn, name)))
+ vshError(ctl, FALSE, "failed to get domain '%s'", name);
+ }
+
+ if (!dom)
+ return FALSE;
+
+ dump = virDomainGetXMLDesc(dom, 0);
+ if (dump != NULL) {
+ printf("%s", dump);
+ free(dump);
+ } else {
+ ret = FALSE;
+ }
+
+ virDomainFree(dom);
+ return ret;
+}
+
/*
* "nameof" command
*/
static vshCmdDef commands[] = {
{ "connect", cmdConnect, opts_connect, info_connect },
{ "dinfo", cmdDinfo, opts_dinfo, info_dinfo },
+ { "dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml },
{ "dstate", cmdDstate, opts_dstate, info_dstate },
{ "suspend", cmdSuspend, opts_suspend, info_suspend },
{ "resume", cmdResume, opts_resume, info_resume },
--- /dev/null
+/*
+ * xml.c: XML based interfaces for the libvir library
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#include "libvir.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <xs.h>
+#include "internal.h"
+#include "hash.h"
+
+/**
+ * virBuffer:
+ *
+ * A buffer structure.
+ */
+typedef struct _virBuffer virBuffer;
+typedef virBuffer *virBufferPtr;
+struct _virBuffer {
+ char *content; /* The buffer content UTF8 */
+ unsigned int use; /* The buffer size used */
+ unsigned int size; /* The buffer size */
+};
+
+/**
+ * virBufferGrow:
+ * @buf: the buffer
+ * @len: the minimum free size to allocate
+ *
+ * Grow the available space of an XML buffer.
+ *
+ * Returns the new available space or -1 in case of error
+ */
+static int
+virBufferGrow(virBufferPtr buf, unsigned int len) {
+ int size;
+ char *newbuf;
+
+ if (buf == NULL) return(-1);
+ if (len + buf->use < buf->size) return(0);
+
+ size = buf->use + len + 1000;
+
+ newbuf = (char *) realloc(buf->content, size);
+ if (newbuf == NULL) {
+ return(-1);
+ }
+ buf->content = newbuf;
+ buf->size = size;
+ return(buf->size - buf->use);
+}
+
+/**
+ * virBufferAdd:
+ * @buf: the buffer to dump
+ * @str: the string
+ * @len: the number of bytes to add
+ *
+ * Add a string range to an XML buffer. if len == -1, the length of
+ * str is recomputed to the full string.
+ *
+ * Returns 0 successful, -1 in case of internal or API error.
+ */
+static int
+virBufferAdd(virBufferPtr buf, const char *str, int len) {
+ unsigned int needSize;
+
+ if ((str == NULL) || (buf == NULL)) {
+ return -1;
+ }
+ if (len == 0) return 0;
+
+ if (len < 0)
+ len = strlen(str);
+
+ needSize = buf->use + len + 2;
+ if (needSize > buf->size){
+ if (!virBufferGrow(buf, needSize)){
+ return(-1);
+ }
+ }
+
+ memmove(&buf->content[buf->use], str, len);
+ buf->use += len;
+ buf->content[buf->use] = 0;
+ return(0);
+}
+
+/**
+ * virBufferVSprintf:
+ * @buf: the buffer to dump
+ * @format: the format
+ * @argptr: the variable list of arguments
+ *
+ * Do a formatted print to an XML buffer.
+ *
+ * Returns 0 successful, -1 in case of internal or API error.
+ */
+static int
+virBufferVSprintf(virBufferPtr buf, const char *format, ...) {
+ int size, count;
+ va_list locarg, argptr;
+
+ if ((format == NULL) || (buf == NULL)) {
+ return(-1);
+ }
+ size = buf->size - buf->use - 1;
+ va_start(argptr, format);
+ va_copy(locarg, argptr);
+ while (((count = vsnprintf(&buf->content[buf->use], size, format,
+ locarg)) < 0) || (count >= size - 1)) {
+ buf->content[buf->use] = 0;
+ va_end(locarg);
+ if (virBufferGrow(buf, 1000) < 0) {
+ return(-1);
+ }
+ size = buf->size - buf->use - 1;
+ va_copy(locarg, argptr);
+ }
+ va_end(locarg);
+ buf->use += count;
+ buf->content[buf->use] = 0;
+ return(0);
+}
+
+/**
+ * virDomainGetXMLDesc:
+ * @domain: a domain object
+ * @flags: and OR'ed set of extraction flags, not used yet
+ *
+ * Provide an XML description of the domain. NOTE: this API is subject
+ * to changes.
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
+ * the caller must free() the returned value.
+ */
+char *
+virDomainGetXMLDesc(virDomainPtr domain, int flags) {
+ char *ret = NULL;
+ virBuffer buf;
+ virDomainInfo info;
+
+ if ((domain == NULL) || (domain->magic != VIR_DOMAIN_MAGIC) ||
+ (flags != 0))
+ return(NULL);
+
+ if (virDomainGetInfo(domain, &info) < 0)
+ return(NULL);
+
+ ret = malloc(1000);
+ if (ret == NULL)
+ return(NULL);
+ buf.content = ret;
+ buf.size = 1000;
+ buf.use = 0;
+
+ virBufferVSprintf(&buf, "<domain type='xen' id='%d'>\n",
+ virDomainGetID(domain));
+ virBufferVSprintf(&buf, " <name>%s</name>\n", virDomainGetName(domain));
+ virBufferAdd(&buf, "</domain>\n", 10);
+
+ buf.content[buf.use] = 0;
+ return(ret);
+}