A lock manager may operate in various modes. The direct mode of
operation is to obtain locks based on the resources associated
with devices in the XML. The indirect mode is where the app
creating the domain provides explicit leases for each resource
that needs to be locked. This XML extension allows for listing
resources in the XML
<leases>
<lease>
<key>thequickbrownfoxjumpsoverthelazydog</key>
<target path='/some/lease/path' offset='23432'
length='256'/>
</lease>
</leases>
* docs/schemas/domain.rng: Add lease schema
* src/conf/domain_conf.c, src/conf/domain_conf.h: parsing and
formatting for leases
* tests/qemuxml2argvdata/qemuxml2argv-lease.args,
tests/qemuxml2argvdata/qemuxml2argv-lease.xml,
tests/qemuxml2xmltest.c: Test XML handling for leases
---
docs/schemas/domain.rng | 32 ++++++
src/conf/domain_conf.c | 133 ++++++++++++++++++++++++
src/conf/domain_conf.h | 12 ++
tests/qemuxml2argvdata/qemuxml2argv-lease.args | 1 +
tests/qemuxml2argvdata/qemuxml2argv-lease.xml | 37 +++++++
tests/qemuxml2xmltest.c | 1 +
6 files changed, 216 insertions(+), 0 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-lease.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-lease.xml
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index d4756e6..fda7a3f 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -39,6 +39,9 @@
<ref name="features"/>
<ref name="termination"/>
<optional>
+ <ref name="leases"/>
+ </optional>
+ <optional>
<ref name="devices"/>
</optional>
<optional>
@@ -550,6 +553,35 @@
<ref name="address"/>
</optional>
</define>
+
+ <define name="leases">
+ <element name="leases">
+ <zeroOrMore>
+ <ref name="lease"/>
+ </zeroOrMore>
+ </element>
+ </define>
+
+ <define name="lease">
+ <element name="lease">
+ <element name="key">
+ <text/>
+ </element>
+ <element name="target">
+ <attribute name="path">
+ <text/>
+ </attribute>
+ <optional>
+ <attribute name="offset">
+ <ref name="unsignedInt"/>
+ </attribute>
+ <attribute name="length">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </optional>
+ </element>
+ </element>
+ </define>
<!--
A disk description can be either of type file or block
The name of the attribute on the source element depends on the type
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 699fee7..c10bb8f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -514,6 +514,17 @@ void virDomainInputDefFree(virDomainInputDefPtr def)
VIR_FREE(def);
}
+static void virDomainLeaseDefFree(virDomainLeaseDefPtr def)
+{
+ if (!def)
+ return;
+
+ VIR_FREE(def->key);
+ VIR_FREE(def->path);
+
+ VIR_FREE(def);
+}
+
void virDomainDiskDefFree(virDomainDiskDefPtr def)
{
unsigned int i;
@@ -804,6 +815,10 @@ void virDomainDefFree(virDomainDefPtr def)
if (!def)
return;
+ for (i = 0 ; i < def->nleases ; i++)
+ virDomainLeaseDefFree(def->leases[i]);
+ VIR_FREE(def->leases);
+
for (i = 0 ; i < def->ngraphics ; i++)
virDomainGraphicsDefFree(def->graphics[i]);
VIR_FREE(def->graphics);
@@ -1659,6 +1674,82 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr
def)
return 0;
}
+/* Parse the XML definition for a lease
+ */
+static virDomainLeaseDefPtr
+virDomainLeaseDefParseXML(xmlNodePtr node)
+{
+ virDomainLeaseDefPtr def;
+ xmlNodePtr cur;
+ char *key = NULL;
+ char *path = NULL;
+ char *offset = NULL;
+ char *length = NULL;
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ cur = node->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if ((key == NULL) &&
+ (xmlStrEqual(cur->name, BAD_CAST "key"))) {
+ key = (char *)xmlNodeGetContent(cur);
+ } else if ((path == NULL) &&
+ (xmlStrEqual(cur->name, BAD_CAST "target"))) {
+ path = virXMLPropString(cur, "path");
+ offset = virXMLPropString(cur, "offset");
+ length = virXMLPropString(cur, "length");
+ }
+ }
+ cur = cur->next;
+ }
+
+ if (!key) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Missing 'key' element for lease"));
+ goto error;
+ }
+ if (!path) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Missing 'target' element for lease"));
+ goto error;
+ }
+
+ if (offset &&
+ virStrToLong_ull(offset, NULL, 10, &def->offset) < 0) {
+ virDomainReportError(VIR_ERR_XML_ERROR,
+ _("Malformed lease target offset %s"), offset);
+ goto error;
+ }
+ if (length &&
+ virStrToLong_ull(length, NULL, 10, &def->length) < 0) {
+ virDomainReportError(VIR_ERR_XML_ERROR,
+ _("Malformed lease target length %s"), length);
+ goto error;
+ }
+
+ def->key = key;
+ def->path = path;
+ path = key = NULL;
+
+cleanup:
+ VIR_FREE(key);
+ VIR_FREE(path);
+ VIR_FREE(offset);
+ VIR_FREE(length);
+
+ return def;
+
+ error:
+ virDomainLeaseDefFree(def);
+ def = NULL;
+ goto cleanup;
+}
+
+
/* Parse the XML definition for a disk
* @param node XML nodeset to parse for disk definition
*/
@@ -5154,6 +5245,23 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
goto error;
}
+ /* analysis of the resource leases */
+ if ((n = virXPathNodeSet("./leases/lease", ctxt, &nodes)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot extract lease
devices"));
+ goto error;
+ }
+ if (n && VIR_ALLOC_N(def->leases, n) < 0)
+ goto no_memory;
+ for (i = 0 ; i < n ; i++) {
+ virDomainLeaseDefPtr lease = virDomainLeaseDefParseXML(nodes[i]);
+ if (!lease)
+ goto error;
+
+ def->leases[def->nleases++] = lease;
+ }
+ VIR_FREE(nodes);
+
/* analysis of the disk devices */
if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -6155,6 +6263,23 @@ virDomainLifecycleDefFormat(virBufferPtr buf,
static int
+virDomainLeaseDefFormat(virBufferPtr buf,
+ virDomainLeaseDefPtr def)
+{
+ virBufferAddLit(buf, " <lease>\n");
+ virBufferEscapeString(buf, " <key>%s</key>\n",
def->key);
+ virBufferEscapeString(buf, " <target path='%s'",
def->path);
+ if (def->offset)
+ virBufferVSprintf(buf, " offset='%llu'", def->offset);
+ if (def->length)
+ virBufferVSprintf(buf, " length='%llu'", def->length);
+ virBufferAddLit(buf, "/>\n");
+ virBufferAddLit(buf, " </lease>\n");
+
+ return 0;
+}
+
+static int
virDomainDiskDefFormat(virBufferPtr buf,
virDomainDiskDefPtr def,
int flags)
@@ -7485,6 +7610,14 @@ char *virDomainDefFormat(virDomainDefPtr def,
virDomainLifecycleCrashTypeToString) < 0)
goto cleanup;
+ if (def->nleases) {
+ virBufferAddLit(&buf, " <leases>\n");
+ for (n = 0 ; n < def->nleases ; n++)
+ if (virDomainLeaseDefFormat(&buf, def->leases[n]) < 0)
+ goto cleanup;
+ virBufferAddLit(&buf, " </leases>\n");
+ }
+
virBufferAddLit(&buf, " <devices>\n");
if (def->emulator)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3b00ba0..4f9c044 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -114,6 +114,15 @@ struct _virDomainDeviceInfo {
} addr;
};
+typedef struct _virDomainLeaseDef virDomainLeaseDef;
+typedef virDomainLeaseDef *virDomainLeaseDefPtr;
+struct _virDomainLeaseDef {
+ char *key;
+ char *path;
+ unsigned long long offset;
+ unsigned long long length;
+};
+
/* Two types of disk backends */
enum virDomainDiskType {
@@ -992,6 +1001,9 @@ struct _virDomainDef {
char *emulator;
int features;
+ int nleases;
+ virDomainLeaseDefPtr *leases;
+
virDomainClockDef clock;
int ngraphics;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-lease.args
b/tests/qemuxml2argvdata/qemuxml2argv-lease.args
new file mode 100644
index 0000000..4a347ad
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-lease.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda
/dev/HostVG/QEMUGuest1 -cdrom /root/boot.iso -net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-lease.xml
b/tests/qemuxml2argvdata/qemuxml2argv-lease.xml
new file mode 100644
index 0000000..5304f89
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-lease.xml
@@ -0,0 +1,37 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <leases>
+ <lease>
+ <key>thequickbrownfoxjumpedoverthelazydog</key>
+ <target path='/some/lease/path' offset='1024'
length='512'/>
+ </lease>
+ </leases>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
unit='0'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <source file='/root/boot.iso'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1'
unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index ab82d36..7d9466b 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -183,6 +183,7 @@ mymain(int argc, char **argv)
DO_TEST("memtune");
DO_TEST("smp");
+ DO_TEST("lease");
/* These tests generate different XML */
DO_TEST_DIFFERENT("balloon-device-auto");
--
1.7.3.4