}
+int virDomainLeaseIndex(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease)
+{
+ virDomainLeaseDefPtr vlease;
+ int i;
+
+ for (i = 0; i < def->nleases; i++) {
+ vlease = def->leases[i];
+ /* Either both must have lockspaces present which match.. */
+ if (vlease->lockspace && lease->lockspace &&
+ STRNEQ(vlease->lockspace, lease->lockspace))
+ continue;
+ /* ...or neither must have a lockspace present */
+ if (vlease->lockspace || lease->lockspace)
+ continue;
+ if (STREQ(vlease->key, lease->key))
+ return i;
+ }
+ return -1;
+}
+
+
+int virDomainLeaseInsertPreAlloc(virDomainDefPtr def)
+{
+ if (VIR_EXPAND_N(def->leases, def->nleases, 1) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ return 0;
+}
+
+int virDomainLeaseInsert(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease)
+{
+ if (virDomainLeaseInsertPreAlloc(def) < 0)
+ return -1;
+
+ virDomainLeaseInsertPreAlloced(def, lease);
+ return 0;
+}
+
+
+void virDomainLeaseInsertPreAlloced(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease)
+{
+ if (lease == NULL)
+ VIR_SHRINK_N(def->leases, def->nleases, 1);
+ else
+ def->leases[def->nleases-1] = lease;
+}
+
+
+void virDomainLeaseRemoveAt(virDomainDefPtr def, size_t i)
+{
+ if (def->nleases > 1) {
+ memmove(def->leases + i,
+ def->leases + i + 1,
+ sizeof(*def->leases) *
+ (def->nleases - (i + 1)));
+ VIR_SHRINK_N(def->leases, def->nleases, 1);
+ } else {
+ VIR_FREE(def->leases);
+ def->nleases = 0;
+ }
+}
+
+
+int virDomainLeaseRemove(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease)
+{
+ int i = virDomainLeaseIndex(def, lease);
+ if (i < 0)
+ return -1;
+ virDomainLeaseRemoveAt(def, i);
+ return 0;
+}
+
+
static char *virDomainDefDefaultEmulator(virDomainDefPtr def,
virCapsPtr caps) {
const char *type;
int nchannels;
virDomainChrDefPtr *channels;
- int nleases;
+ size_t nleases;
virDomainLeaseDefPtr *leases;
/* Only 1 */
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
virDomainControllerDefPtr controller);
+
+int virDomainLeaseIndex(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease);
+int virDomainLeaseInsert(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease);
+int virDomainLeaseInsertPreAlloc(virDomainDefPtr def);
+void virDomainLeaseInsertPreAlloced(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease);
+void virDomainLeaseRemoveAt(virDomainDefPtr def, size_t i);
+int virDomainLeaseRemove(virDomainDefPtr def,
+ virDomainLeaseDefPtr lease);
+
int virDomainSaveXML(const char *configDir,
virDomainDefPtr def,
const char *xml);
virDomainHostdevModeTypeToString;
virDomainHostdevSubsysTypeToString;
virDomainInputDefFree;
+virDomainLeaseIndex;
+virDomainLeaseInsert;
+virDomainLeaseInsertPreAlloc;
+virDomainLeaseInsertPreAlloced;
+virDomainLeaseRemove;
+virDomainLeaseRemoveAt;
virDomainLifecycleCrashTypeFromString;
virDomainLifecycleCrashTypeToString;
virDomainLifecycleTypeFromString;
dev->data.controller = NULL;
break;
+ case VIR_DOMAIN_DEVICE_LEASE:
+ ret = qemuDomainAttachLease(driver, vm,
+ dev->data.lease);
+ if (ret == 0)
+ dev->data.lease = NULL;
+ break;
+
case VIR_DOMAIN_DEVICE_NET:
qemuDomainObjCheckNetTaint(driver, vm, dev->data.net, -1);
ret = qemuDomainAttachNetDevice(dom->conn, driver, vm,
case VIR_DOMAIN_DEVICE_CONTROLLER:
ret = qemuDomainDetachDeviceControllerLive(driver, vm, dev);
break;
+ case VIR_DOMAIN_DEVICE_LEASE:
+ ret = qemuDomainDetachLease(driver, vm, dev->data.lease);
+ break;
case VIR_DOMAIN_DEVICE_NET:
ret = qemuDomainDetachNetDevice(driver, vm, dev);
break;
{
virDomainDiskDefPtr disk;
virDomainNetDefPtr net;
+ virDomainLeaseDefPtr lease;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
if (qemuDomainAssignPCIAddresses(vmdef) < 0)
return -1;
break;
+
+ case VIR_DOMAIN_DEVICE_LEASE:
+ lease = dev->data.lease;
+ if (virDomainLeaseIndex(vmdef, lease) >= 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("Lease %s in lockspace %s already exists"),
+ lease->key, NULLSTR(lease->lockspace));
+ return -1;
+ }
+ if (virDomainLeaseInsert(vmdef, lease) < 0)
+ return -1;
+
+ /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
+ dev->data.lease = NULL;
+ break;
+
default:
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("persistent attach of device is not supported"));
{
virDomainDiskDefPtr disk;
virDomainNetDefPtr net;
+ virDomainLeaseDefPtr lease;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
return -1;
}
break;
+
case VIR_DOMAIN_DEVICE_NET:
net = dev->data.net;
if (virDomainNetRemoveByMac(vmdef, net->mac)) {
return -1;
}
break;
+
+ case VIR_DOMAIN_DEVICE_LEASE:
+ lease = dev->data.lease;
+ if (virDomainLeaseRemove(vmdef, lease) < 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("Lease %s in lockspace %s does not exist"),
+ lease->key, NULLSTR(lease->lockspace));
+ return -1;
+ }
+ break;
+
default:
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("persistent detach of device is not supported"));
return ret;
}
+
+int qemuDomainAttachLease(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainLeaseDefPtr lease)
+{
+ if (virDomainLeaseInsertPreAlloc(vm->def) < 0)
+ return -1;
+
+ if (virDomainLockLeaseAttach(driver->lockManager, vm, lease) < 0) {
+ virDomainLeaseInsertPreAlloced(vm->def, NULL);
+ return -1;
+ }
+
+ virDomainLeaseInsertPreAlloced(vm->def, lease);
+ return 0;
+}
+
+int qemuDomainDetachLease(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainLeaseDefPtr lease)
+{
+ int i;
+
+ if ((i = virDomainLeaseIndex(vm->def, lease)) < 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("Lease %s in lockspace %s does not exist"),
+ lease->key, NULLSTR(lease->lockspace));
+ return -1;
+ }
+
+ if (virDomainLockLeaseDetach(driver->lockManager, vm, lease) < 0)
+ return -1;
+
+ virDomainLeaseRemoveAt(vm->def, i);
+ return 0;
+}
int qemuDomainDetachHostDevice(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev);
+int qemuDomainAttachLease(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainLeaseDefPtr lease);
+int qemuDomainDetachLease(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainLeaseDefPtr lease);
#endif /* __QEMU_HOTPLUG_H__ */