mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 09:17:52 +03:00
qemu: Add handling for VSERPORT_CHANGE event
New qemu added a new event that is emitted when a virtio serial channel is opened in the guest OS. This allows us to update the state of the port in the output-only XML element. This patch implements the monitor callbacks and necessary handlers to update the state in the definition.
This commit is contained in:
parent
24c25a68c2
commit
15bbaaf014
@ -196,6 +196,7 @@ typedef enum {
|
||||
QEMU_PROCESS_EVENT_GUESTPANIC,
|
||||
QEMU_PROCESS_EVENT_DEVICE_DELETED,
|
||||
QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,
|
||||
QEMU_PROCESS_EVENT_SERIAL_CHANGED,
|
||||
|
||||
QEMU_PROCESS_EVENT_LAST
|
||||
} qemuProcessEventType;
|
||||
|
@ -4334,6 +4334,60 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
processSerialChangedEvent(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
char *devAlias,
|
||||
bool connected)
|
||||
{
|
||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||
virDomainChrDeviceState newstate;
|
||||
virDomainDeviceDef dev;
|
||||
|
||||
if (connected)
|
||||
newstate = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
|
||||
else
|
||||
newstate = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
|
||||
|
||||
VIR_DEBUG("Changing serial port state %s in domain %p %s",
|
||||
devAlias, vm, vm->def->name);
|
||||
|
||||
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!virDomainObjIsActive(vm)) {
|
||||
VIR_DEBUG("Domain is not running");
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
|
||||
goto endjob;
|
||||
|
||||
/* we care only about certain devices */
|
||||
if (dev.type != VIR_DOMAIN_DEVICE_CHR ||
|
||||
dev.data.chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL ||
|
||||
dev.data.chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
|
||||
goto endjob;
|
||||
|
||||
dev.data.chr->state = newstate;
|
||||
|
||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
||||
VIR_WARN("unable to save status of domain %s after updating state of "
|
||||
"channel %s", vm->def->name, devAlias);
|
||||
|
||||
endjob:
|
||||
/* We had an extra reference to vm before starting a new job so ending the
|
||||
* job is guaranteed not to remove the last reference.
|
||||
*/
|
||||
ignore_value(qemuDomainObjEndJob(driver, vm));
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(devAlias);
|
||||
virObjectUnref(cfg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void qemuProcessEventHandler(void *data, void *opaque)
|
||||
{
|
||||
struct qemuProcessEvent *processEvent = data;
|
||||
@ -4357,6 +4411,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
|
||||
case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
|
||||
processNicRxFilterChangedEvent(driver, vm, processEvent->data);
|
||||
break;
|
||||
case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
|
||||
processSerialChangedEvent(driver, vm, processEvent->data,
|
||||
processEvent->action);
|
||||
case QEMU_PROCESS_EVENT_LAST:
|
||||
break;
|
||||
}
|
||||
|
@ -1400,6 +1400,20 @@ qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorEmitSerialChange(qemuMonitorPtr mon,
|
||||
const char *devAlias,
|
||||
bool connected)
|
||||
{
|
||||
int ret = -1;
|
||||
VIR_DEBUG("mon=%p, devAlias='%s', connected=%d", mon, devAlias, connected);
|
||||
|
||||
QEMU_MONITOR_CALLBACK(mon, ret, domainSerialChange, mon->vm, devAlias, connected);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
|
||||
{
|
||||
int ret;
|
||||
|
@ -176,6 +176,12 @@ typedef int (*qemuMonitorDomainNicRxFilterChangedCallback)(qemuMonitorPtr mon,
|
||||
const char *devAlias,
|
||||
void *opaque);
|
||||
|
||||
typedef int (*qemuMonitorDomainSerialChangeCallback)(qemuMonitorPtr mon,
|
||||
virDomainObjPtr vm,
|
||||
const char *devAlias,
|
||||
bool connected,
|
||||
void *opaque);
|
||||
|
||||
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
|
||||
typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
|
||||
struct _qemuMonitorCallbacks {
|
||||
@ -202,6 +208,7 @@ struct _qemuMonitorCallbacks {
|
||||
qemuMonitorDomainGuestPanicCallback domainGuestPanic;
|
||||
qemuMonitorDomainDeviceDeletedCallback domainDeviceDeleted;
|
||||
qemuMonitorDomainNicRxFilterChangedCallback domainNicRxFilterChanged;
|
||||
qemuMonitorDomainSerialChangeCallback domainSerialChange;
|
||||
};
|
||||
|
||||
char *qemuMonitorEscapeArg(const char *in);
|
||||
@ -292,6 +299,9 @@ int qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
|
||||
const char *devAlias);
|
||||
int qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
|
||||
const char *devAlias);
|
||||
int qemuMonitorEmitSerialChange(qemuMonitorPtr mon,
|
||||
const char *devAlias,
|
||||
bool connected);
|
||||
|
||||
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
|
||||
virConnectPtr conn);
|
||||
|
@ -82,6 +82,7 @@ static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValueP
|
||||
static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
|
||||
typedef struct {
|
||||
const char *type;
|
||||
@ -112,6 +113,7 @@ static qemuEventHandler eventHandlers[] = {
|
||||
{ "VNC_CONNECTED", qemuMonitorJSONHandleVNCConnect, },
|
||||
{ "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, },
|
||||
{ "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, },
|
||||
{ "VSERPORT_CHANGE", qemuMonitorJSONHandleSerialChange, },
|
||||
{ "WAKEUP", qemuMonitorJSONHandlePMWakeup, },
|
||||
{ "WATCHDOG", qemuMonitorJSONHandleWatchdog, },
|
||||
/* We use bsearch, so keep this list sorted. */
|
||||
@ -895,6 +897,27 @@ qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon,
|
||||
virJSONValuePtr data)
|
||||
{
|
||||
const char *name;
|
||||
bool connected;
|
||||
|
||||
if (!(name = virJSONValueObjectGetString(data, "id"))) {
|
||||
VIR_WARN("missing device alias in VSERPORT_CHANGE event");
|
||||
return;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectGetBoolean(data, "open", &connected) < 0) {
|
||||
VIR_WARN("missing port state for '%s' in VSERPORT_CHANGE event", name);
|
||||
return;
|
||||
}
|
||||
|
||||
qemuMonitorEmitSerialChange(mon, name, connected);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
|
||||
const char *cmd_str,
|
||||
|
@ -1540,6 +1540,49 @@ qemuProcessHandleNicRxFilterChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessHandleSerialChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
virDomainObjPtr vm,
|
||||
const char *devAlias,
|
||||
bool connected,
|
||||
void *opaque)
|
||||
{
|
||||
virQEMUDriverPtr driver = opaque;
|
||||
struct qemuProcessEvent *processEvent = NULL;
|
||||
char *data;
|
||||
|
||||
virObjectLock(vm);
|
||||
|
||||
VIR_DEBUG("Serial port %s state changed to '%d' in domain %p %s",
|
||||
devAlias, connected, vm, vm->def->name);
|
||||
|
||||
if (VIR_ALLOC(processEvent) < 0)
|
||||
goto error;
|
||||
|
||||
processEvent->eventType = QEMU_PROCESS_EVENT_SERIAL_CHANGED;
|
||||
if (VIR_STRDUP(data, devAlias) < 0)
|
||||
goto error;
|
||||
processEvent->data = data;
|
||||
processEvent->action = connected;
|
||||
processEvent->vm = vm;
|
||||
|
||||
virObjectRef(vm);
|
||||
if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
|
||||
ignore_value(virObjectUnref(vm));
|
||||
goto error;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
virObjectUnlock(vm);
|
||||
return 0;
|
||||
error:
|
||||
if (processEvent)
|
||||
VIR_FREE(processEvent->data);
|
||||
VIR_FREE(processEvent);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
static qemuMonitorCallbacks monitorCallbacks = {
|
||||
.eofNotify = qemuProcessHandleMonitorEOF,
|
||||
.errorNotify = qemuProcessHandleMonitorError,
|
||||
@ -1562,6 +1605,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
|
||||
.domainGuestPanic = qemuProcessHandleGuestPanic,
|
||||
.domainDeviceDeleted = qemuProcessHandleDeviceDeleted,
|
||||
.domainNicRxFilterChanged = qemuProcessHandleNicRxFilterChanged,
|
||||
.domainSerialChange = qemuProcessHandleSerialChanged,
|
||||
};
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user