Support for container related domain XML extensions

This commit is contained in:
Daniel P. Berrange 2008-08-01 13:31:37 +00:00
parent ffc839fb20
commit a7600746fb
6 changed files with 360 additions and 8 deletions

View File

@ -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

View File

@ -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>

View File

@ -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,
@ -2247,6 +2382,57 @@ virDomainDiskDefFormat(virConnectPtr conn,
return 0;
}
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,
@ -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)

View File

@ -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)

View File

@ -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>

2
tests/domainschematest Normal file → Executable file
View File

@ -2,7 +2,7 @@
test -z "$srcdir" && srcdir=`pwd`
DOMAINDIRS="qemuxml2argvdata sexpr2xmldata xmconfigdata xml2sexprdata"
DOMAINDIRS="domainschemadata qemuxml2argvdata sexpr2xmldata xmconfigdata xml2sexprdata"
n=0
f=0