mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-09 06:25:19 +00:00
qemu: Implement chardev hotplug on live level
Since previous patches has prepared everything for us, we may now implement live hotplug of a character device.
This commit is contained in:
parent
75f0fd5112
commit
24b0821926
@ -863,8 +863,41 @@ qemuAssignDeviceControllerAlias(virDomainControllerDefPtr controller)
|
||||
return virAsprintf(&controller->info.alias, "%s%d", prefix, controller->idx);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
qemuGetNextChrDevIndex(virDomainDefPtr def,
|
||||
virDomainChrDefPtr chr,
|
||||
const char *prefix)
|
||||
{
|
||||
virDomainChrDefPtr **arrPtr;
|
||||
size_t *cntPtr;
|
||||
size_t i;
|
||||
ssize_t idx = 0;
|
||||
const char *prefix2 = NULL;
|
||||
|
||||
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE)
|
||||
prefix2 = "serial";
|
||||
|
||||
virDomainChrGetDomainPtrs(def, chr, &arrPtr, &cntPtr);
|
||||
|
||||
for (i = 0; i < *cntPtr; i++) {
|
||||
ssize_t thisidx;
|
||||
if (((thisidx = qemuDomainDeviceAliasIndex(&(*arrPtr)[i]->info, prefix)) < 0) &&
|
||||
(prefix2 &&
|
||||
(thisidx = qemuDomainDeviceAliasIndex(&(*arrPtr)[i]->info, prefix2)) < 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to determine device index for character device"));
|
||||
return -1;
|
||||
}
|
||||
if (thisidx >= idx)
|
||||
idx = thisidx + 1;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuAssignDeviceChrAlias(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
||||
qemuAssignDeviceChrAlias(virDomainDefPtr def,
|
||||
virDomainChrDefPtr chr,
|
||||
ssize_t idx)
|
||||
{
|
||||
@ -891,6 +924,9 @@ qemuAssignDeviceChrAlias(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (idx == -1 && (idx = qemuGetNextChrDevIndex(def, chr, prefix)) < 0)
|
||||
return -1;
|
||||
|
||||
return virAsprintf(&chr->info.alias, "%s%zd", prefix, idx);
|
||||
}
|
||||
|
||||
|
@ -6390,6 +6390,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
|
||||
dev->data.redirdev = NULL;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DEVICE_CHR:
|
||||
ret = qemuDomainAttachChrDevice(driver, vm,
|
||||
dev->data.chr);
|
||||
if (!ret)
|
||||
dev->data.chr = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
_("live attach of device '%s' is not supported"),
|
||||
@ -6477,6 +6484,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
|
||||
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
||||
ret = qemuDomainDetachHostDevice(driver, vm, dev);
|
||||
break;
|
||||
case VIR_DOMAIN_DEVICE_CHR:
|
||||
ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr);
|
||||
break;
|
||||
default:
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
_("live detach of device '%s' is not supported"),
|
||||
@ -6886,7 +6896,7 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
|
||||
virDomainDefPtr vmdef = NULL;
|
||||
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
|
||||
int ret = -1;
|
||||
unsigned int affect;
|
||||
unsigned int affect, parse_flags = 0;
|
||||
virQEMUCapsPtr qemuCaps = NULL;
|
||||
qemuDomainObjPrivatePtr priv;
|
||||
virQEMUDriverConfigPtr cfg = NULL;
|
||||
@ -6934,9 +6944,13 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
|
||||
!(flags & VIR_DOMAIN_AFFECT_LIVE))
|
||||
parse_flags |= VIR_DOMAIN_XML_INACTIVE;
|
||||
|
||||
dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
|
||||
caps, driver->xmlopt,
|
||||
VIR_DOMAIN_XML_INACTIVE);
|
||||
parse_flags);
|
||||
if (dev == NULL)
|
||||
goto endjob;
|
||||
|
||||
@ -7164,7 +7178,7 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
|
||||
virDomainDefPtr vmdef = NULL;
|
||||
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
|
||||
int ret = -1;
|
||||
unsigned int affect;
|
||||
unsigned int affect, parse_flags = 0;
|
||||
virQEMUCapsPtr qemuCaps = NULL;
|
||||
qemuDomainObjPrivatePtr priv;
|
||||
virQEMUDriverConfigPtr cfg = NULL;
|
||||
@ -7212,9 +7226,13 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
|
||||
!(flags & VIR_DOMAIN_AFFECT_LIVE))
|
||||
parse_flags |= VIR_DOMAIN_XML_INACTIVE;
|
||||
|
||||
dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
|
||||
caps, driver->xmlopt,
|
||||
VIR_DOMAIN_XML_INACTIVE);
|
||||
parse_flags);
|
||||
if (dev == NULL)
|
||||
goto endjob;
|
||||
|
||||
|
@ -1244,6 +1244,62 @@ qemuDomainChrRemove(virDomainDefPtr vmdef,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainChrDefPtr chr)
|
||||
{
|
||||
int ret = -1;
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
virDomainDefPtr vmdef = vm->def;
|
||||
char *devstr = NULL;
|
||||
char *charAlias = NULL;
|
||||
bool remove = false;
|
||||
|
||||
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("qemu does not support -device"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (qemuAssignDeviceChrAlias(vmdef, chr, -1) < 0)
|
||||
return ret;
|
||||
|
||||
if (qemuBuildChrDeviceStr(&devstr, vm->def, chr, priv->qemuCaps) < 0)
|
||||
return ret;
|
||||
|
||||
if (virAsprintf(&charAlias, "char%s", chr->info.alias) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qemuDomainChrInsert(vmdef, chr) < 0)
|
||||
goto cleanup;
|
||||
remove = true;
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0) {
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (devstr && qemuMonitorAddDevice(priv->mon, devstr) < 0) {
|
||||
/* detach associated chardev on error */
|
||||
qemuMonitorDetachCharDev(priv->mon, charAlias);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
goto cleanup;
|
||||
}
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
if (ret < 0 && remove)
|
||||
qemuDomainChrRemove(vmdef, chr);
|
||||
VIR_FREE(charAlias);
|
||||
VIR_FREE(devstr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainHostdevDefPtr hostdev)
|
||||
@ -3077,3 +3133,50 @@ int qemuDomainDetachLease(virQEMUDriverPtr driver,
|
||||
virDomainLeaseDefFree(det_lease);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainChrDefPtr chr)
|
||||
{
|
||||
int ret = -1;
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
virDomainDefPtr vmdef = vm->def;
|
||||
virDomainChrDefPtr tmpChr;
|
||||
char *charAlias = NULL;
|
||||
char *devstr = NULL;
|
||||
|
||||
if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("device not present in domain configuration"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (qemuBuildChrDeviceStr(&devstr, vm->def, chr, priv->qemuCaps) < 0)
|
||||
return ret;
|
||||
|
||||
if (virAsprintf(&charAlias, "char%s", tmpChr->info.alias) < 0) {
|
||||
virReportOOMError();
|
||||
return ret;
|
||||
}
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qemuMonitorDetachCharDev(priv->mon, charAlias) < 0) {
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
goto cleanup;
|
||||
}
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
|
||||
qemuDomainChrRemove(vmdef, tmpChr);
|
||||
virDomainChrDefFree(tmpChr);
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(devstr);
|
||||
VIR_FREE(charAlias);
|
||||
return ret;
|
||||
}
|
||||
|
@ -104,6 +104,12 @@ int qemuDomainAttachLease(virQEMUDriverPtr driver,
|
||||
int qemuDomainDetachLease(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainLeaseDefPtr lease);
|
||||
int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainChrDefPtr chr);
|
||||
int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
virDomainChrDefPtr chr);
|
||||
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user