aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2008-08-01 13:31:37 +0000
committerDaniel P. Berrange <berrange@redhat.com>2008-08-01 13:31:37 +0000
commita7600746fbec6c9e2d8f1c89ac1b6262243655b0 (patch)
treefc51ecb92293d3a23c6040ee6a2f000cb3562256
parentAlways set forward-delay on bridge, even if 0 (diff)
downloadlibvirt-a7600746fbec6c9e2d8f1c89ac1b6262243655b0.tar.gz
libvirt-a7600746fbec6c9e2d8f1c89ac1b6262243655b0.tar.bz2
libvirt-a7600746fbec6c9e2d8f1c89ac1b6262243655b0.zip
Support for container related domain XML extensions
-rw-r--r--ChangeLog10
-rw-r--r--docs/libvirt.rng97
-rw-r--r--src/domain_conf.c211
-rw-r--r--src/domain_conf.h28
-rw-r--r--tests/domainschemadata/domain-lxc-simple.xml20
-rwxr-xr-x[-rw-r--r--]tests/domainschematest2
6 files changed, 360 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 45d7cfa8c..89b6ef36c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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_\.\+\-&amp;/%]+</param>
</data>
</define>
+ <define name='absDirPath'>
+ <data type='string'>
+ <param name="pattern">/[a-zA-Z0-9_\.\+\-&amp;/%]*</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