add XML parsing for qemu/kvm status files

This commit is contained in:
Guido Günther 2008-12-20 13:09:45 +00:00
parent f1bd11bf87
commit b679ebe877
6 changed files with 256 additions and 11 deletions

View File

@ -1,3 +1,17 @@
Sat Dec 20 13:53:14 CET 2008 Guido Günther <agx@sigxcpu.org>
add XML parsing for qemu/kvm status files
* src/domain_conf.c, src/domain_conf.h (virDomainSaveXML): new function
* src/domain_conf.c (virDomainSaveConfig): split out XML writing into
virDomainSaveXML
* src/qemu_conf.c (qemudDomainStatusParseFile): new function to parse
status XML
(qemudDomainStatusFormat): new function to format status XML
(qemudSaveDomainStatus): new function to write status XML, uses
virDomainSaveXML
* src/libvirt_sym.version.in: add virBufferEscapeString, virDomainSaveXML,
virXPathNode symbols
Fri Dec 19 10:41:00 UTC 2008 Richard W.M. Jones <rjones@redhat.com>
* docs/formatdomain.html.in: Fix documentation typo

View File

@ -430,6 +430,7 @@ void virDomainObjFree(virDomainObjPtr dom)
virDomainDefFree(dom->def);
virDomainDefFree(dom->newDef);
VIR_FREE(dom->monitorpath);
VIR_FREE(dom->vcpupids);
VIR_FREE(dom);
@ -3243,11 +3244,11 @@ char *virDomainDefFormat(virConnectPtr conn,
#ifndef PROXY
int virDomainSaveConfig(virConnectPtr conn,
const char *configDir,
virDomainDefPtr def)
int virDomainSaveXML(virConnectPtr conn,
const char *configDir,
virDomainDefPtr def,
const char *xml)
{
char *xml;
char *configFile = NULL;
int fd = -1, ret = -1;
size_t towrite;
@ -3256,11 +3257,6 @@ int virDomainSaveConfig(virConnectPtr conn,
if ((configFile = virDomainConfigFile(conn, configDir, def->name)) == NULL)
goto cleanup;
if (!(xml = virDomainDefFormat(conn,
def,
VIR_DOMAIN_XML_SECURE)))
goto cleanup;
if ((err = virFileMakePath(configDir))) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot create config directory %s: %s"),
@ -3293,12 +3289,30 @@ int virDomainSaveConfig(virConnectPtr conn,
}
ret = 0;
cleanup:
VIR_FREE(xml);
if (fd != -1)
close(fd);
return ret;
}
int virDomainSaveConfig(virConnectPtr conn,
const char *configDir,
virDomainDefPtr def)
{
int ret = -1;
char *xml;
if (!(xml = virDomainDefFormat(conn,
def,
VIR_DOMAIN_XML_SECURE)))
goto cleanup;
if (virDomainSaveXML(conn, configDir, def, xml))
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(xml);
return ret;
}

View File

@ -464,6 +464,7 @@ struct _virDomainObj {
int stderr_fd;
int stderr_watch;
int monitor;
char *monitorpath;
int monitorWatch;
int logfile;
int pid;
@ -555,6 +556,11 @@ int virDomainDiskQSort(const void *a, const void *b);
int virDomainDiskCompare(virDomainDiskDefPtr a,
virDomainDiskDefPtr b);
int virDomainSaveXML(virConnectPtr conn,
const char *configDir,
virDomainDefPtr def,
const char *xml);
int virDomainSaveConfig(virConnectPtr conn,
const char *configDir,
virDomainDefPtr def);

View File

@ -281,6 +281,7 @@ LIBVIRT_PRIVATE_@VERSION@ {
# buf.h
virBufferVSprintf;
virBufferEscapeString;
virBufferAdd;
virBufferAddChar;
virBufferContentAndReset;
@ -360,6 +361,7 @@ LIBVIRT_PRIVATE_@VERSION@ {
virDomainObjFree;
virDomainObjListFree;
virDomainRemoveInactive;
virDomainSaveXML;
virDomainSaveConfig;
virDomainSoundDefFree;
virDomainSoundModelTypeFromString;
@ -601,6 +603,7 @@ LIBVIRT_PRIVATE_@VERSION@ {
# xml.h
virXPathLong;
virXPathNode;
virXPathNodeSet;
virXPathString;
virXMLPropString;

View File

@ -49,6 +49,8 @@
#include "util.h"
#include "memory.h"
#include "verify.h"
#include "datatypes.h"
#include "xml.h"
VIR_ENUM_DECL(virDomainDiskQEMUBus)
VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
@ -1334,3 +1336,192 @@ int qemudBuildCommandLine(virConnectPtr conn,
#undef ADD_ENV_LIT
#undef ADD_ENV_SPACE
}
/* Called from SAX on parsing errors in the XML. */
static void
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
if (ctxt) {
virConnectPtr conn = ctxt->_private;
if (ctxt->lastError.level == XML_ERR_FATAL &&
ctxt->lastError.message != NULL) {
qemudReportError (conn, NULL, NULL, VIR_ERR_XML_DETAIL,
_("at line %d: %s"),
ctxt->lastError.line,
ctxt->lastError.message);
}
}
}
/**
* qemudDomainStatusParseFile
*
* read the last known status of a domain
*
* Returns 0 on success
*/
qemudDomainStatusPtr
qemudDomainStatusParseFile(virConnectPtr conn,
virCapsPtr caps,
const char *filename, int flags)
{
xmlParserCtxtPtr pctxt = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlDocPtr xml = NULL;
xmlNodePtr root, config_root;
virDomainDefPtr def = NULL;
char *tmp = NULL;
long val;
qemudDomainStatusPtr status = NULL;
if (VIR_ALLOC(status) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for vm status"));
goto error;
}
/* Set up a parser context so we can catch the details of XML errors. */
pctxt = xmlNewParserCtxt ();
if (!pctxt || !pctxt->sax)
goto error;
pctxt->sax->error = catchXMLError;
pctxt->_private = conn;
if (conn) virResetError (&conn->err);
xml = xmlCtxtReadFile (pctxt, filename, NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
if (!xml) {
if (conn && conn->err.code == VIR_ERR_NONE)
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR,
"%s", _("failed to parse xml document"));
goto error;
}
if ((root = xmlDocGetRootElement(xml)) == NULL) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("missing root element"));
goto error;
}
ctxt = xmlXPathNewContext(xml);
if (ctxt == NULL) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
goto error;
}
if (!xmlStrEqual(root->name, BAD_CAST "domstatus")) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("incorrect root element"));
goto error;
}
ctxt->node = root;
if((virXPathLong(conn, "string(./@state)", ctxt, &val)) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("invalid domain state"));
goto error;
} else
status->state = (int)val;
if((virXPathLong(conn, "string(./@pid)", ctxt, &val)) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("invalid pid"));
goto error;
} else
status->pid = (pid_t)val;
if(!(tmp = virXPathString(conn, "string(./monitor[1]/@path)", ctxt))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("no monitor path"));
goto error;
} else
status->monitorpath = tmp;
if(!(config_root = virXPathNode(conn, "./domain", ctxt))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("no domain config"));
goto error;
}
if(!(def = virDomainDefParseNode(conn, caps, xml, config_root, flags)))
goto error;
else
status->def = def;
cleanup:
xmlFreeParserCtxt (pctxt);
xmlXPathFreeContext(ctxt);
xmlFreeDoc (xml);
return status;
error:
VIR_FREE(tmp);
VIR_FREE(status);
goto cleanup;
}
/**
* qemudDomainStatusFormat
*
* Get the state of a running domain as XML
*
* Returns xml on success
*/
static char*
qemudDomainStatusFormat(virConnectPtr conn,
virDomainObjPtr vm)
{
char *config_xml = NULL, *xml = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferVSprintf(&buf, "<domstatus state='%d' pid='%d'>\n", vm->state, vm->pid);
virBufferEscapeString(&buf, " <monitor path='%s'/>\n", vm->monitorpath);
if (!(config_xml = virDomainDefFormat(conn,
vm->def,
VIR_DOMAIN_XML_SECURE)))
goto cleanup;
virBufferAdd(&buf, config_xml, strlen(config_xml));
virBufferAddLit(&buf, "</domstatus>\n");
xml = virBufferContentAndReset(&buf);
cleanup:
VIR_FREE(config_xml);
return xml;
}
/**
* qemudSaveDomainStatus
*
* Save the current status of a running domain
*
* Returns 0 on success
*/
int
qemudSaveDomainStatus(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm)
{
int ret = -1;
char *xml = NULL;
if (!(xml = qemudDomainStatusFormat(conn, vm)))
goto cleanup;
if ((ret = virDomainSaveXML(conn, driver->stateDir, vm->def, xml)))
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(xml);
return ret;
}

View File

@ -77,6 +77,16 @@ struct qemud_driver {
int domainEventDispatching;
};
/* Status needed to reconenct to running VMs */
typedef struct _qemudDomainStatus qemudDomainStatus;
typedef qemudDomainStatus *qemudDomainStatusPtr;
struct _qemudDomainStatus {
char *monitorpath;
pid_t pid;
int state;
virDomainDefPtr def;
};
/* Port numbers used for KVM migration. */
#define QEMUD_MIGRATION_FIRST_PORT 49152
#define QEMUD_MIGRATION_NUM_PORTS 64
@ -108,5 +118,12 @@ int qemudBuildCommandLine (virConnectPtr conn,
const char *migrateFrom);
const char *qemudVirtTypeToString (int type);
qemudDomainStatusPtr qemudDomainStatusParseFile(virConnectPtr conn,
virCapsPtr caps,
const char *filename,
int flags);
int qemudSaveDomainStatus(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm);
#endif /* __QEMUD_CONF_H */