diff options
author | Daniel P. Berrange <berrange@redhat.com> | 2008-08-01 13:31:37 +0000 |
---|---|---|
committer | Daniel P. Berrange <berrange@redhat.com> | 2008-08-01 13:31:37 +0000 |
commit | a7600746fbec6c9e2d8f1c89ac1b6262243655b0 (patch) | |
tree | fc51ecb92293d3a23c6040ee6a2f000cb3562256 | |
parent | Always set forward-delay on bridge, even if 0 (diff) | |
download | libvirt-a7600746fbec6c9e2d8f1c89ac1b6262243655b0.tar.gz libvirt-a7600746fbec6c9e2d8f1c89ac1b6262243655b0.tar.bz2 libvirt-a7600746fbec6c9e2d8f1c89ac1b6262243655b0.zip |
Support for container related domain XML extensions
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | docs/libvirt.rng | 97 | ||||
-rw-r--r-- | src/domain_conf.c | 211 | ||||
-rw-r--r-- | src/domain_conf.h | 28 | ||||
-rw-r--r-- | tests/domainschemadata/domain-lxc-simple.xml | 20 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/domainschematest | 2 |
6 files changed, 360 insertions, 8 deletions
@@ -1,3 +1,13 @@ +Fri Aug 1 13:57:00 BST 2008 Daniel P. Berrange <berrange@redhat.com> + + * src/domain_conf.h, src/domain_conf.c, docs/libvirt.rng: Add + support for an <init> element in <os> block, and <filesystem> + device type, and 'exe' OS type. + * tests/domainschematest: Check domainschemadata directory for + XML files + * tests/domainschemadata/domain-lxc-simple.xml: Simple example + for LXC driver to validate + Fri Aug 1 13:54:00 BST 2008 Daniel P. Berrange <berrange@redhat.com> * src/qemu_driver.c: Always set forward-delay even if zero because diff --git a/docs/libvirt.rng b/docs/libvirt.rng index 045a9c2b7..cd5d79866 100644 --- a/docs/libvirt.rng +++ b/docs/libvirt.rng @@ -44,6 +44,7 @@ <choice> <ref name='osxen'/> <ref name='oshvm'/> + <ref name='osexe'/> </choice> </define> @@ -187,6 +188,23 @@ </define> + <define name='osexe'> + <element name='os'> + <element name='type'> + <value>exe</value> + </element> + <interleave> + <optional> + <element name='init'> + <ref name='absFilePath'/> + </element> + </optional> + </interleave> + </element> + </define> + + + <!-- The Identifiers can be: - an optional id attribute with a number on the domain element @@ -418,6 +436,79 @@ <empty/> </element> </define> + + <define name='filesystem'> + <element name='filesystem'> + <choice> + <group> + <attribute name='type'> + <value>file</value> + </attribute> + <interleave> + <element name='source'> + <attribute name='file'> + <ref name='absFilePath'/> + </attribute> + <empty/> + </element> + <ref name='filesystemtgt'/> + </interleave> + </group> + <group> + <attribute name='type'> + <value>block</value> + </attribute> + <interleave> + <element name='source'> + <attribute name='dev'> + <ref name='deviceName'/> + </attribute> + <empty/> + </element> + <ref name='filesystemtgt'/> + </interleave> + </group> + <group> + <attribute name='type'> + <value>mount</value> + </attribute> + <interleave> + <element name='source'> + <attribute name='dir'> + <ref name='absFilePath'/> + </attribute> + <empty/> + </element> + <ref name='filesystemtgt'/> + </interleave> + </group> + <group> + <attribute name='type'> + <value>template</value> + </attribute> + <interleave> + <element name='source'> + <attribute name='name'> + <ref name='genericName'/> + </attribute> + <empty/> + </element> + <ref name='filesystemtgt'/> + </interleave> + </group> + </choice> + </element> + </define> + + <define name='filesystemtgt'> + <element name='target'> + <attribute name='dir'> + <ref name='absDirPath'/> + </attribute> + <empty/> + </element> + </define> + <!-- An interface description can either be of type bridge in which case it will use a bridging source, or of type ethernet which uses a device @@ -770,6 +861,7 @@ <choice> <ref name='graphic'/> <ref name='disk'/> + <ref name='filesystem'/> <ref name='interface'/> <ref name='console'/> <ref name='sound'/> @@ -869,6 +961,11 @@ <param name="pattern">/[a-zA-Z0-9_\.\+\-&/%]+</param> </data> </define> + <define name='absDirPath'> + <data type='string'> + <param name="pattern">/[a-zA-Z0-9_\.\+\-&/%]*</param> + </data> + </define> <define name='devicePath'> <data type='string'> <param name="pattern">/[a-zA-Z0-9_\+\-/%]+</param> diff --git a/src/domain_conf.c b/src/domain_conf.c index 0e99ccc5e..a844c8244 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -86,6 +86,12 @@ VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST, "virtio", "xen") +VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST, + "mount", + "block", + "file", + "template") + VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, "user", "ethernet", @@ -237,6 +243,18 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def) VIR_FREE(def); } +void virDomainFSDefFree(virDomainFSDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->src); + VIR_FREE(def->dst); + + virDomainFSDefFree(def->next); + VIR_FREE(def); +} + void virDomainNetDefFree(virDomainNetDefPtr def) { if (!def) @@ -345,6 +363,7 @@ void virDomainDefFree(virDomainDefPtr def) virDomainGraphicsDefFree(def->graphics); virDomainInputDefFree(def->inputs); virDomainDiskDefFree(def->disks); + virDomainFSDefFree(def->fss); virDomainNetDefFree(def->nets); virDomainChrDefFree(def->serials); virDomainChrDefFree(def->parallels); @@ -355,6 +374,7 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->os.type); VIR_FREE(def->os.arch); VIR_FREE(def->os.machine); + VIR_FREE(def->os.init); VIR_FREE(def->os.kernel); VIR_FREE(def->os.initrd); VIR_FREE(def->os.cmdline); @@ -625,6 +645,89 @@ cleanup: } +/* Parse the XML definition for a disk + * @param node XML nodeset to parse for disk definition + */ +static virDomainFSDefPtr +virDomainFSDefParseXML(virConnectPtr conn, + xmlNodePtr node) { + virDomainFSDefPtr def; + xmlNodePtr cur; + char *type = NULL; + char *source = NULL; + char *target = NULL; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + type = virXMLPropString(node, "type"); + if (type) { + if ((def->type = virDomainFSTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown filesystem type '%s'"), type); + goto error; + } + } else { + def->type = VIR_DOMAIN_FS_TYPE_MOUNT; + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if ((source == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "source"))) { + + if (def->type == VIR_DOMAIN_FS_TYPE_MOUNT) + source = virXMLPropString(cur, "dir"); + else if (def->type == VIR_DOMAIN_FS_TYPE_FILE) + source = virXMLPropString(cur, "file"); + else if (def->type == VIR_DOMAIN_FS_TYPE_BLOCK) + source = virXMLPropString(cur, "dev"); + else if (def->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) + source = virXMLPropString(cur, "name"); + } else if ((target == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "target"))) { + target = virXMLPropString(cur, "dir"); + } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { + def->readonly = 1; + } + } + cur = cur->next; + } + + if (source == NULL) { + virDomainReportError(conn, VIR_ERR_NO_SOURCE, + target ? "%s" : NULL, target); + goto error; + } + + if (target == NULL) { + virDomainReportError(conn, VIR_ERR_NO_TARGET, + source ? "%s" : NULL, source); + goto error; + } + + def->src = source; + source = NULL; + def->dst = target; + target = NULL; + +cleanup: + VIR_FREE(type); + VIR_FREE(target); + VIR_FREE(source); + + return def; + + error: + virDomainFSDefFree(def); + def = NULL; + goto cleanup; +} + + static void virDomainNetRandomMAC(virDomainNetDefPtr def) { /* XXX there different vendor prefixes per hypervisor */ def->mac[0] = 0x52; @@ -1351,6 +1454,10 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, dev->type = VIR_DOMAIN_DEVICE_DISK; if (!(dev->data.disk = virDomainDiskDefParseXML(conn, node))) goto error; + } else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) { + dev->type = VIR_DOMAIN_DEVICE_FS; + if (!(dev->data.fs = virDomainFSDefParseXML(conn, node))) + goto error; } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { dev->type = VIR_DOMAIN_DEVICE_NET; if (!(dev->data.net = virDomainNetDefParseXML(conn, node))) @@ -1560,7 +1667,21 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, } } - if (!def->os.bootloader) { + /* + * Booting options for different OS types.... + * + * - A bootloader (and optional kernel+initrd) (xen) + * - A kernel + initrd (xen) + * - A boot device (and optional kernel+initrd) (hvm) + * - An init script (exe) + */ + + if (STREQ(def->os.type, "exe")) { + def->os.init = virXPathString(conn, "string(./os/init[1])", ctxt); + } + + if (STREQ(def->os.type, "xen") || + STREQ(def->os.type, "hvm")) { def->os.kernel = virXPathString(conn, "string(./os/kernel[1])", ctxt); def->os.initrd = virXPathString(conn, "string(./os/initrd[1])", ctxt); def->os.cmdline = virXPathString(conn, "string(./os/cmdline[1])", ctxt); @@ -1610,12 +1731,9 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, def->os.type, def->os.arch, type); - if (!emulator) { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("unsupported guest type")); - goto error; - } - if (!(def->emulator = strdup(emulator))) { + + if (emulator && + !(def->emulator = strdup(emulator))) { virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); goto error; } @@ -1651,6 +1769,23 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, } VIR_FREE(nodes); + /* analysis of the filesystems */ + if ((n = virXPathNodeSet(conn, "./devices/filesystem", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract filesystem devices")); + goto error; + } + for (i = n - 1 ; i >= 0 ; i--) { + virDomainFSDefPtr fs = virDomainFSDefParseXML(conn, + nodes[i]); + if (!fs) + goto error; + + fs->next = def->fss; + def->fss = fs; + } + VIR_FREE(nodes); + /* analysis of the network devices */ if ((n = virXPathNodeSet(conn, "./devices/interface", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, @@ -2248,6 +2383,57 @@ virDomainDiskDefFormat(virConnectPtr conn, } static int +virDomainFSDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainFSDefPtr def) +{ + const char *type = virDomainFSTypeToString(def->type); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected filesystem type %d"), def->type); + return -1; + } + + virBufferVSprintf(buf, + " <filesystem type='%s'>\n", + type); + + if (def->src) { + switch (def->type) { + case VIR_DOMAIN_FS_TYPE_MOUNT: + virBufferEscapeString(buf, " <source dir='%s'/>\n", + def->src); + break; + + case VIR_DOMAIN_FS_TYPE_BLOCK: + virBufferEscapeString(buf, " <source dev='%s'/>\n", + def->src); + break; + + case VIR_DOMAIN_FS_TYPE_FILE: + virBufferEscapeString(buf, " <source file='%s'/>\n", + def->src); + break; + + case VIR_DOMAIN_FS_TYPE_TEMPLATE: + virBufferEscapeString(buf, " <source name='%s'/>\n", + def->src); + } + } + + virBufferVSprintf(buf, " <target dir='%s'/>\n", + def->dst); + + if (def->readonly) + virBufferAddLit(buf, " <readonly/>\n"); + + virBufferAddLit(buf, " </filesystem>\n"); + + return 0; +} + +static int virDomainNetDefFormat(virConnectPtr conn, virBufferPtr buf, virDomainNetDefPtr def) @@ -2527,6 +2713,7 @@ char *virDomainDefFormat(virConnectPtr conn, unsigned char *uuid; char uuidstr[VIR_UUID_STRING_BUFLEN]; virDomainDiskDefPtr disk; + virDomainFSDefPtr fs; virDomainNetDefPtr net; virDomainSoundDefPtr sound; virDomainInputDefPtr input; @@ -2596,6 +2783,9 @@ char *virDomainDefFormat(virConnectPtr conn, else virBufferVSprintf(&buf, ">%s</type>\n", def->os.type); + if (def->os.init) + virBufferEscapeString(&buf, " <init>%s</init>\n", + def->os.init); if (def->os.loader) virBufferEscapeString(&buf, " <loader>%s</loader>\n", def->os.loader); @@ -2671,6 +2861,13 @@ char *virDomainDefFormat(virConnectPtr conn, disk = disk->next; } + fs = def->fss; + while (fs) { + if (virDomainFSDefFormat(conn, &buf, fs) < 0) + goto cleanup; + fs = fs->next; + } + net = def->nets; while (net) { if (virDomainNetDefFormat(conn, &buf, net) < 0) diff --git a/src/domain_conf.h b/src/domain_conf.h index e2c513d3e..527dc712f 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -94,6 +94,28 @@ struct _virDomainDiskDef { }; +/* Two types of disk backends */ +enum virDomainFSType { + VIR_DOMAIN_FS_TYPE_MOUNT, /* Better named 'bind' */ + VIR_DOMAIN_FS_TYPE_BLOCK, + VIR_DOMAIN_FS_TYPE_FILE, + VIR_DOMAIN_FS_TYPE_TEMPLATE, + + VIR_DOMAIN_FS_TYPE_LAST +}; + +typedef struct _virDomainFSDef virDomainFSDef; +typedef virDomainFSDef *virDomainFSDefPtr; +struct _virDomainFSDef { + int type; + char *src; + char *dst; + unsigned int readonly : 1; + + virDomainFSDefPtr next; +}; + + /* 5 different types of networking config */ enum virDomainNetType { VIR_DOMAIN_NET_TYPE_USER, @@ -262,6 +284,7 @@ struct _virDomainGraphicsDef { /* Flags for the 'type' field in next struct */ enum virDomainDeviceType { VIR_DOMAIN_DEVICE_DISK, + VIR_DOMAIN_DEVICE_FS, VIR_DOMAIN_DEVICE_NET, VIR_DOMAIN_DEVICE_INPUT, VIR_DOMAIN_DEVICE_SOUND, @@ -273,6 +296,7 @@ struct _virDomainDeviceDef { int type; union { virDomainDiskDefPtr disk; + virDomainFSDefPtr fs; virDomainNetDefPtr net; virDomainInputDefPtr input; virDomainSoundDefPtr sound; @@ -318,6 +342,7 @@ struct _virDomainOSDef { char *machine; int nBootDevs; int bootDevs[VIR_DOMAIN_BOOT_LAST]; + char *init; char *kernel; char *initrd; char *cmdline; @@ -357,6 +382,7 @@ struct _virDomainDef { virDomainGraphicsDefPtr graphics; virDomainDiskDefPtr disks; + virDomainFSDefPtr fss; virDomainNetDefPtr nets; virDomainInputDefPtr inputs; virDomainSoundDefPtr sounds; @@ -411,6 +437,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjPtr doms, void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def); void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); +void virDomainFSDefFree(virDomainFSDefPtr def); void virDomainNetDefFree(virDomainNetDefPtr def); void virDomainChrDefFree(virDomainChrDefPtr def); void virDomainSoundDefFree(virDomainSoundDefPtr def); @@ -484,6 +511,7 @@ VIR_ENUM_DECL(virDomainLifecycle) VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) +VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainChr) VIR_ENUM_DECL(virDomainSoundModel) diff --git a/tests/domainschemadata/domain-lxc-simple.xml b/tests/domainschemadata/domain-lxc-simple.xml new file mode 100644 index 000000000..653bbc7fb --- /dev/null +++ b/tests/domainschemadata/domain-lxc-simple.xml @@ -0,0 +1,20 @@ +<domain type='lxc'> + <name>demo</name> + <uuid>8369f1ac-7e46-e869-4ca5-759d51478066</uuid> + <os> + <type>exe</type> + <init>/sh</init> + </os> + <memory>500000</memory> + <devices> + <filesystem type='mount'> + <source dir='/root/container'/> + <target dir='/'/> + </filesystem> + <filesystem type='mount'> + <source dir='/home'/> + <target dir='/home'/> + </filesystem> + <console type='pty'/> + </devices> +</domain> diff --git a/tests/domainschematest b/tests/domainschematest index 39244008c..e410cdcab 100644..100755 --- a/tests/domainschematest +++ b/tests/domainschematest @@ -2,7 +2,7 @@ test -z "$srcdir" && srcdir=`pwd` -DOMAINDIRS="qemuxml2argvdata sexpr2xmldata xmconfigdata xml2sexprdata" +DOMAINDIRS="domainschemadata qemuxml2argvdata sexpr2xmldata xmconfigdata xml2sexprdata" n=0 f=0 |