sub-element.
</p>
+ <h4><a name="elementsLease">Device leases</a></h4>
+
+ <p>
+ When using a lock manager, it may be desirable to record device leases
+ against a VM. The lock manager will ensure the VM won't start unless
+ the leases can be acquired.
+ </p>
+
+<pre>
+ ...
+ <devices>
+ ...
+ <lease>
+ <lockspace>somearea</lockspace>
+ <key>somekey</key>
+ <target path='/some/lease/path' offset='1024'/>
+ </lease>
+ ...
+ </devices>
+ ...</pre>
+
+ <dl>
+ <dt>lockspace</dt>
+ <dd>This is an arbitrary string, identifying the lockspace
+ within which the key is held. Lock managers may impose
+ extra restrictions on the format, or length of the lockspace
+ name.</dd>
+ <dt>key</dt>
+ <dd>This is an arbitrary string, uniquely identifying the
+ lease to be acquired. Lock managers may impose extra
+ restrictions on the format, or length of the key.
+ </dd>
+ <dt>target</dt>
+ <dd>This is the fully qualified path of the file associated
+ with the lockspace. The offset specifies where the lease
+ is stored within the file. If the lock manager does not
+ require a offset, just pass 0.
+ </dd>
+ </dl>
<h4><a name="elementsUSB">USB and PCI devices</a></h4>
VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
"disk",
+ "lease",
"filesystem",
"interface",
"input",
VIR_FREE(def);
}
+static void virDomainLeaseDefFree(virDomainLeaseDefPtr def)
+{
+ if (!def)
+ return;
+
+ VIR_FREE(def->lockspace);
+ VIR_FREE(def->key);
+ VIR_FREE(def->path);
+
+ VIR_FREE(def);
+}
+
void virDomainDiskDefFree(virDomainDiskDefPtr def)
{
unsigned int i;
case VIR_DOMAIN_DEVICE_DISK:
virDomainDiskDefFree(def->data.disk);
break;
+ case VIR_DOMAIN_DEVICE_LEASE:
+ virDomainLeaseDefFree(def->data.lease);
+ break;
case VIR_DOMAIN_DEVICE_NET:
virDomainNetDefFree(def->data.net);
break;
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);
return 0;
}
+/* Parse the XML definition for a lease
+ */
+static virDomainLeaseDefPtr
+virDomainLeaseDefParseXML(xmlNodePtr node)
+{
+ virDomainLeaseDefPtr def;
+ xmlNodePtr cur;
+ char *lockspace = NULL;
+ char *key = NULL;
+ char *path = NULL;
+ char *offset = 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 ((lockspace == NULL) &&
+ (xmlStrEqual(cur->name, BAD_CAST "lockspace"))) {
+ lockspace = (char *)xmlNodeGetContent(cur);
+ } else if ((path == NULL) &&
+ (xmlStrEqual(cur->name, BAD_CAST "target"))) {
+ path = virXMLPropString(cur, "path");
+ offset = virXMLPropString(cur, "offset");
+ }
+ }
+ 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;
+ }
+
+ def->key = key;
+ def->lockspace = lockspace;
+ def->path = path;
+ path = key = lockspace = NULL;
+
+cleanup:
+ VIR_FREE(lockspace);
+ VIR_FREE(key);
+ VIR_FREE(path);
+ VIR_FREE(offset);
+
+ 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
*/
if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node,
NULL, flags)))
goto error;
+ } else if (xmlStrEqual(node->name, BAD_CAST "lease")) {
+ dev->type = VIR_DOMAIN_DEVICE_LEASE;
+ if (!(dev->data.lease = virDomainLeaseDefParseXML(node)))
+ goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
dev->type = VIR_DOMAIN_DEVICE_FS;
if (!(dev->data.fs = virDomainFSDefParseXML(node, flags)))
}
VIR_FREE(nodes);
+ /* analysis of the resource leases */
+ if ((n = virXPathNodeSet("./devices/lease", ctxt, &nodes)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot extract device leases"));
+ 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 filesystems */
if ((n = virXPathNodeSet("./devices/filesystem", ctxt, &nodes)) < 0) {
goto error;
}
+static int
+virDomainLeaseDefFormat(virBufferPtr buf,
+ virDomainLeaseDefPtr def)
+{
+ virBufferAddLit(buf, " <lease>\n");
+ virBufferEscapeString(buf, " <lockspace>%s</lockspace>\n", def->lockspace);
+ virBufferEscapeString(buf, " <key>%s</key>\n", def->key);
+ virBufferEscapeString(buf, " <target path='%s'", def->path);
+ if (def->offset)
+ virBufferAsprintf(buf, " offset='%llu'", def->offset);
+ virBufferAddLit(buf, "/>\n");
+ virBufferAddLit(buf, " </lease>\n");
+
+ return 0;
+}
+
static int
virDomainDiskDefFormat(virBufferPtr buf,
virDomainDiskDefPtr def,
if (virDomainControllerDefFormat(&buf, def->controllers[n], flags) < 0)
goto cleanup;
+ for (n = 0 ; n < def->nleases ; n++)
+ if (virDomainLeaseDefFormat(&buf, def->leases[n]) < 0)
+ goto cleanup;
+
for (n = 0 ; n < def->nfss ; n++)
if (virDomainFSDefFormat(&buf, def->fss[n], flags) < 0)
goto cleanup;
--- /dev/null
+<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>
+ <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'/>
+ <lease>
+ <lockspace>somearea</lockspace>
+ <key>thequickbrownfoxjumpedoverthelazydog</key>
+ <target path='/some/lease/path' offset='1024'/>
+ </lease>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>