mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-09 14:35:25 +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);
|
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
|
int
|
||||||
qemuAssignDeviceChrAlias(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
qemuAssignDeviceChrAlias(virDomainDefPtr def,
|
||||||
virDomainChrDefPtr chr,
|
virDomainChrDefPtr chr,
|
||||||
ssize_t idx)
|
ssize_t idx)
|
||||||
{
|
{
|
||||||
@ -891,6 +924,9 @@ qemuAssignDeviceChrAlias(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (idx == -1 && (idx = qemuGetNextChrDevIndex(def, chr, prefix)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return virAsprintf(&chr->info.alias, "%s%zd", prefix, idx);
|
return virAsprintf(&chr->info.alias, "%s%zd", prefix, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6390,6 +6390,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
|
|||||||
dev->data.redirdev = NULL;
|
dev->data.redirdev = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_CHR:
|
||||||
|
ret = qemuDomainAttachChrDevice(driver, vm,
|
||||||
|
dev->data.chr);
|
||||||
|
if (!ret)
|
||||||
|
dev->data.chr = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||||
_("live attach of device '%s' is not supported"),
|
_("live attach of device '%s' is not supported"),
|
||||||
@ -6477,6 +6484,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
|
|||||||
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
||||||
ret = qemuDomainDetachHostDevice(driver, vm, dev);
|
ret = qemuDomainDetachHostDevice(driver, vm, dev);
|
||||||
break;
|
break;
|
||||||
|
case VIR_DOMAIN_DEVICE_CHR:
|
||||||
|
ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||||
_("live detach of device '%s' is not supported"),
|
_("live detach of device '%s' is not supported"),
|
||||||
@ -6886,7 +6896,7 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
|
|||||||
virDomainDefPtr vmdef = NULL;
|
virDomainDefPtr vmdef = NULL;
|
||||||
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
|
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
unsigned int affect;
|
unsigned int affect, parse_flags = 0;
|
||||||
virQEMUCapsPtr qemuCaps = NULL;
|
virQEMUCapsPtr qemuCaps = NULL;
|
||||||
qemuDomainObjPrivatePtr priv;
|
qemuDomainObjPrivatePtr priv;
|
||||||
virQEMUDriverConfigPtr cfg = NULL;
|
virQEMUDriverConfigPtr cfg = NULL;
|
||||||
@ -6934,9 +6944,13 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
|
|||||||
goto endjob;
|
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,
|
dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
|
||||||
caps, driver->xmlopt,
|
caps, driver->xmlopt,
|
||||||
VIR_DOMAIN_XML_INACTIVE);
|
parse_flags);
|
||||||
if (dev == NULL)
|
if (dev == NULL)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
@ -7164,7 +7178,7 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
|
|||||||
virDomainDefPtr vmdef = NULL;
|
virDomainDefPtr vmdef = NULL;
|
||||||
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
|
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
unsigned int affect;
|
unsigned int affect, parse_flags = 0;
|
||||||
virQEMUCapsPtr qemuCaps = NULL;
|
virQEMUCapsPtr qemuCaps = NULL;
|
||||||
qemuDomainObjPrivatePtr priv;
|
qemuDomainObjPrivatePtr priv;
|
||||||
virQEMUDriverConfigPtr cfg = NULL;
|
virQEMUDriverConfigPtr cfg = NULL;
|
||||||
@ -7212,9 +7226,13 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
|
|||||||
goto endjob;
|
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,
|
dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
|
||||||
caps, driver->xmlopt,
|
caps, driver->xmlopt,
|
||||||
VIR_DOMAIN_XML_INACTIVE);
|
parse_flags);
|
||||||
if (dev == NULL)
|
if (dev == NULL)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
|
@ -1244,6 +1244,62 @@ qemuDomainChrRemove(virDomainDefPtr vmdef,
|
|||||||
|
|
||||||
return ret;
|
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,
|
int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainHostdevDefPtr hostdev)
|
virDomainHostdevDefPtr hostdev)
|
||||||
@ -3077,3 +3133,50 @@ int qemuDomainDetachLease(virQEMUDriverPtr driver,
|
|||||||
virDomainLeaseDefFree(det_lease);
|
virDomainLeaseDefFree(det_lease);
|
||||||
return 0;
|
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,
|
int qemuDomainDetachLease(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainLeaseDefPtr lease);
|
virDomainLeaseDefPtr lease);
|
||||||
|
int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainChrDefPtr chr);
|
||||||
|
int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainChrDefPtr chr);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
|
Loading…
Reference in New Issue
Block a user