From 30ffe7bceb083540c542e9bf81148f194668d77d Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 18 May 2011 12:20:53 -0400 Subject: [PATCH] Allow leases to be hotpluged with QEMU guests * src/conf/domain_conf.c, src/conf/domain_conf.h: APIs for inserting/finding/removing virDomainLeaseDefPtr instances * src/qemu/qemu_driver.c: Wire up hotplug/unplug for leases * src/qemu/qemu_hotplug.h, src/qemu/qemu_hotplug.c: Support for hotplug and unplug of leases --- src/conf/domain_conf.c | 78 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 14 +++++++- src/libvirt_private.syms | 6 ++++ src/qemu/qemu_driver.c | 40 +++++++++++++++++++++ src/qemu/qemu_hotplug.c | 36 +++++++++++++++++++ src/qemu/qemu_hotplug.h | 6 ++++ 6 files changed, 179 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 41455edc71..9975bcae89 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5395,6 +5395,84 @@ void virDomainControllerInsertPreAlloced(virDomainDefPtr def, } +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; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7545e0a84d..41c8136ce8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1196,7 +1196,7 @@ struct _virDomainDef { int nchannels; virDomainChrDefPtr *channels; - int nleases; + size_t nleases; virDomainLeaseDefPtr *leases; /* Only 1 */ @@ -1400,6 +1400,18 @@ int virDomainControllerInsert(virDomainDefPtr def, 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); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 10ed863658..644da894c1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -288,6 +288,12 @@ virDomainHostdevDefFree; virDomainHostdevModeTypeToString; virDomainHostdevSubsysTypeToString; virDomainInputDefFree; +virDomainLeaseIndex; +virDomainLeaseInsert; +virDomainLeaseInsertPreAlloc; +virDomainLeaseInsertPreAlloced; +virDomainLeaseRemove; +virDomainLeaseRemoveAt; virDomainLifecycleCrashTypeFromString; virDomainLifecycleCrashTypeToString; virDomainLifecycleTypeFromString; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e68ecadb4a..5632d62956 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4084,6 +4084,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, 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, @@ -4173,6 +4180,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr 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; @@ -4267,6 +4277,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, { virDomainDiskDefPtr disk; virDomainNetDefPtr net; + virDomainLeaseDefPtr lease; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -4306,6 +4317,22 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, 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")); @@ -4321,6 +4348,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, { virDomainDiskDefPtr disk; virDomainNetDefPtr net; + virDomainLeaseDefPtr lease; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -4331,6 +4359,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, return -1; } break; + case VIR_DOMAIN_DEVICE_NET: net = dev->data.net; if (virDomainNetRemoveByMac(vmdef, net->mac)) { @@ -4342,6 +4371,17 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, 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")); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index a8e73c46cc..c9e2d08a37 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1846,3 +1846,39 @@ cleanup: 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; +} diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index d18b393b3e..009f1f625f 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -85,6 +85,12 @@ int qemuDomainDetachHostUsbDevice(struct qemud_driver *driver, 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__ */