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
This commit is contained in:
Daniel P. Berrange 2011-05-18 12:20:53 -04:00
parent 7474560bef
commit 30ffe7bceb
6 changed files with 179 additions and 1 deletions

View File

@ -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;

View File

@ -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);

View File

@ -288,6 +288,12 @@ virDomainHostdevDefFree;
virDomainHostdevModeTypeToString;
virDomainHostdevSubsysTypeToString;
virDomainInputDefFree;
virDomainLeaseIndex;
virDomainLeaseInsert;
virDomainLeaseInsertPreAlloc;
virDomainLeaseInsertPreAlloced;
virDomainLeaseRemove;
virDomainLeaseRemoveAt;
virDomainLifecycleCrashTypeFromString;
virDomainLifecycleCrashTypeToString;
virDomainLifecycleTypeFromString;

View File

@ -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"));

View File

@ -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;
}

View File

@ -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__ */