mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 03:25:20 +00:00
Support for container related domain XML extensions
This commit is contained in:
parent
ffc839fb20
commit
a7600746fb
10
ChangeLog
10
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
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
20
tests/domainschemadata/domain-lxc-simple.xml
Normal file
20
tests/domainschemadata/domain-lxc-simple.xml
Normal 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
2
tests/domainschematest
Normal file → Executable 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
|
||||
|
Loading…
Reference in New Issue
Block a user