[libvirt] [PATCH v2 REBASE] lib: provide error message in new blockjob event
Nikolay Shirokovskiy
nshirokovskiy at virtuozzo.com
Thu May 3 09:27:57 UTC 2018
ping
On 19.04.2018 17:18, Nikolay Shirokovskiy wrote:
> If block job is completed with error qemu additionally
> provides error message. This patch introduces new event
> VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR to pass error message to client.
>
> This error message has no semantics and should not be interpreted.
> API and RPC layer also have reserved 'code' field to pass semantics
> loaded error code value in the future.
>
> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
>
> ---
>
> Diff from v1 [1]:
> - replace block job event version 3 with block job error event
> - add code field to API/RPC to pass error code in the future
>
> Peter, I decided not to use enum/union as this looks like to much effort to extend
> code generation for this simple case. Using typed params looks unsuitable too.
>
> [1] https://www.redhat.com/archives/libvir-list/2017-October/msg01369.html
>
> examples/object-events/event-test.c | 20 ++++++++
> include/libvirt/libvirt-domain.h | 25 ++++++++++
> src/conf/domain_event.c | 92 +++++++++++++++++++++++++++++++++++++
> src/conf/domain_event.h | 13 ++++++
> src/libvirt_private.syms | 2 +
> src/qemu/qemu_blockjob.c | 10 +++-
> src/qemu/qemu_blockjob.h | 3 +-
> src/qemu/qemu_domain.c | 4 +-
> src/qemu/qemu_domain.h | 1 +
> src/qemu/qemu_driver.c | 9 ++--
> src/qemu/qemu_process.c | 1 +
> src/remote/remote_daemon_dispatch.c | 48 +++++++++++++++++++
> src/remote/remote_driver.c | 34 ++++++++++++++
> src/remote/remote_protocol.x | 17 ++++++-
> src/remote_protocol-structs | 9 ++++
> tools/virsh-domain.c | 24 ++++++++++
> 16 files changed, 304 insertions(+), 8 deletions(-)
>
> diff --git a/examples/object-events/event-test.c b/examples/object-events/event-test.c
> index 8499e0b..23d5a3f 100644
> --- a/examples/object-events/event-test.c
> +++ b/examples/object-events/event-test.c
> @@ -936,6 +936,25 @@ myDomainEventBlockJobCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
>
>
> static int
> +myDomainEventBlockJobErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virDomainPtr dom,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message,
> + void *opaque)
> +{
> + const char *eventName = opaque;
> +
> + printf("%s EVENT: Domain %s(%d) block job error callback '%s' disk '%s', "
> + "type '%s' code '%u' message '%s'",
> + __func__, virDomainGetName(dom), virDomainGetID(dom), eventName,
> + dev, blockJobTypeToStr(type), code, NULLSTR(message));
> + return 0;
> +}
> +
> +
> +static int
> myDomainEventBlockThresholdCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
> virDomainPtr dom,
> const char *dev,
> @@ -1082,6 +1101,7 @@ struct domainEventData domainEvents[] = {
> DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback),
> DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback),
> DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback),
> + DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR, myDomainEventBlockJobErrorCallback),
> };
>
> struct storagePoolEventData {
> diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
> index 12fd340..ee55ab9 100644
> --- a/include/libvirt/libvirt-domain.h
> +++ b/include/libvirt/libvirt-domain.h
> @@ -4370,6 +4370,30 @@ typedef void (*virConnectDomainEventBlockThresholdCallback)(virConnectPtr conn,
> unsigned long long excess,
> void *opaque);
>
> +
> +/**
> + * virConnectDomainEventBlockJobErrorCallback:
> + * @conn: connection object
> + * @dom: domain on which the event occurred
> + * @dev: name associated with the affected disk or storage backing chain
> + * element
> + * @type: type of block job (virDomainBlockJobType)
> + * @code: always 0, reserved for future use
> + * @message: error message with no semantics, can be NULL
> + * @opaque: application specified data
> + *
> + * The callback occurs when block job is completed with error and provides
> + * error message in @message.
> + *
> + */
> +typedef void (*virConnectDomainEventBlockJobErrorCallback)(virConnectPtr conn,
> + virDomainPtr dom,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message,
> + void *opaque);
> +
> /**
> * VIR_DOMAIN_EVENT_CALLBACK:
> *
> @@ -4412,6 +4436,7 @@ typedef enum {
> VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED = 22, /* virConnectDomainEventDeviceRemovalFailedCallback */
> VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* virConnectDomainEventMetadataChangeCallback */
> VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD = 24, /* virConnectDomainEventBlockThresholdCallback */
> + VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR = 25, /* virConnectDomainEventBlockJobErrorCallback */
>
> # ifdef VIR_ENUM_SENTINELS
> VIR_DOMAIN_EVENT_ID_LAST
> diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
> index 9752070..54f4cf4 100644
> --- a/src/conf/domain_event.c
> +++ b/src/conf/domain_event.c
> @@ -47,6 +47,7 @@ static virClassPtr virDomainEventWatchdogClass;
> static virClassPtr virDomainEventIOErrorClass;
> static virClassPtr virDomainEventGraphicsClass;
> static virClassPtr virDomainEventBlockJobClass;
> +static virClassPtr virDomainEventBlockJobErrorClass;
> static virClassPtr virDomainEventDiskChangeClass;
> static virClassPtr virDomainEventTrayChangeClass;
> static virClassPtr virDomainEventBalloonChangeClass;
> @@ -69,6 +70,7 @@ static void virDomainEventWatchdogDispose(void *obj);
> static void virDomainEventIOErrorDispose(void *obj);
> static void virDomainEventGraphicsDispose(void *obj);
> static void virDomainEventBlockJobDispose(void *obj);
> +static void virDomainEventBlockJobErrorDispose(void *obj);
> static void virDomainEventDiskChangeDispose(void *obj);
> static void virDomainEventTrayChangeDispose(void *obj);
> static void virDomainEventBalloonChangeDispose(void *obj);
> @@ -151,6 +153,17 @@ struct _virDomainEventBlockJob {
> typedef struct _virDomainEventBlockJob virDomainEventBlockJob;
> typedef virDomainEventBlockJob *virDomainEventBlockJobPtr;
>
> +struct _virDomainEventBlockJobError {
> + virDomainEvent parent;
> +
> + char *dev;
> + int type;
> + unsigned int code;
> + char *message;
> +};
> +typedef struct _virDomainEventBlockJobError virDomainEventBlockJobError;
> +typedef virDomainEventBlockJobError *virDomainEventBlockJobErrorPtr;
> +
> struct _virDomainEventGraphics {
> virDomainEvent parent;
>
> @@ -309,6 +322,8 @@ virDomainEventsOnceInit(void)
> return -1;
> if (!VIR_CLASS_NEW(virDomainEventBlockJob, virDomainEventClass))
> return -1;
> + if (!VIR_CLASS_NEW(virDomainEventBlockJobError, virDomainEventClass))
> + return -1;
> if (!VIR_CLASS_NEW(virDomainEventDiskChange, virDomainEventClass))
> return -1;
> if (!VIR_CLASS_NEW(virDomainEventTrayChange, virDomainEventClass))
> @@ -420,6 +435,16 @@ virDomainEventBlockJobDispose(void *obj)
> }
>
> static void
> +virDomainEventBlockJobErrorDispose(void *obj)
> +{
> + virDomainEventBlockJobErrorPtr event = obj;
> + VIR_DEBUG("obj=%p", event);
> +
> + VIR_FREE(event->dev);
> + VIR_FREE(event->message);
> +}
> +
> +static void
> virDomainEventDiskChangeDispose(void *obj)
> {
> virDomainEventDiskChangePtr event = obj;
> @@ -977,6 +1002,59 @@ virDomainEventBlockJob2NewFromDom(virDomainPtr dom,
> dst, type, status);
> }
>
> +static virObjectEventPtr
> +virDomainEventBlockJobErrorNew(int id,
> + const char *name,
> + unsigned char *uuid,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message)
> +{
> + virDomainEventBlockJobErrorPtr ev;
> +
> + if (virDomainEventsInitialize() < 0)
> + return NULL;
> +
> + if (!(ev = virDomainEventNew(virDomainEventBlockJobErrorClass,
> + VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR,
> + id, name, uuid)))
> + return NULL;
> +
> + if (VIR_STRDUP(ev->dev, dev) < 0) {
> + virObjectUnref(ev);
> + return NULL;
> + }
> + ignore_value(VIR_STRDUP_QUIET(ev->message, message));
> + ev->type = type;
> + ev->code = code;
> +
> + return (virObjectEventPtr)ev;
> +}
> +
> +virObjectEventPtr
> +virDomainEventBlockJobErrorNewFromObj(virDomainObjPtr obj,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message)
> +{
> + return virDomainEventBlockJobErrorNew(obj->def->id, obj->def->name,
> + obj->def->uuid, dev, type, code,
> + message);
> +}
> +
> +virObjectEventPtr
> +virDomainEventBlockJobErrorNewFromDom(virDomainPtr dom,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message)
> +{
> + return virDomainEventBlockJobErrorNew(dom->id, dom->name, dom->uuid,
> + dev, type, code, message);
> +}
> +
> virObjectEventPtr
> virDomainEventControlErrorNewFromDom(virDomainPtr dom)
> {
> @@ -1787,6 +1865,20 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
> goto cleanup;
> }
>
> + case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR:
> + {
> + virDomainEventBlockJobErrorPtr blockJobErrorEvent;
> +
> + blockJobErrorEvent = (virDomainEventBlockJobErrorPtr)event;
> + ((virConnectDomainEventBlockJobErrorCallback)cb)(conn, dom,
> + blockJobErrorEvent->dev,
> + blockJobErrorEvent->type,
> + blockJobErrorEvent->code,
> + blockJobErrorEvent->message,
> + cbopaque);
> + goto cleanup;
> + }
> +
> case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
> {
> virDomainEventDiskChangePtr diskChangeEvent;
> diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
> index 3992a29..456026c 100644
> --- a/src/conf/domain_event.h
> +++ b/src/conf/domain_event.h
> @@ -138,6 +138,19 @@ virDomainEventBlockJob2NewFromDom(virDomainPtr dom,
> int status);
>
> virObjectEventPtr
> +virDomainEventBlockJobErrorNewFromObj(virDomainObjPtr obj,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message);
> +virObjectEventPtr
> +virDomainEventBlockJobErrorNewFromDom(virDomainPtr dom,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message);
> +
> +virObjectEventPtr
> virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj,
> const char *oldSrcPath,
> const char *newSrcPath,
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index b31f599..303f28c 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -589,6 +589,8 @@ virDomainEventBalloonChangeNewFromDom;
> virDomainEventBalloonChangeNewFromObj;
> virDomainEventBlockJob2NewFromDom;
> virDomainEventBlockJob2NewFromObj;
> +virDomainEventBlockJobErrorNewFromDom;
> +virDomainEventBlockJobErrorNewFromObj;
> virDomainEventBlockJobNewFromDom;
> virDomainEventBlockJobNewFromObj;
> virDomainEventBlockThresholdNewFromDom;
> diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
> index 617e4ee..4df4ed6 100644
> --- a/src/qemu/qemu_blockjob.c
> +++ b/src/qemu/qemu_blockjob.c
> @@ -70,7 +70,8 @@ qemuBlockJobUpdate(virQEMUDriverPtr driver,
> if (status != -1) {
> qemuBlockJobEventProcess(driver, vm, disk, asyncJob,
> diskPriv->blockJobType,
> - diskPriv->blockJobStatus);
> + diskPriv->blockJobStatus,
> + diskPriv->blockJobError);
> diskPriv->blockJobStatus = -1;
> if (error)
> VIR_STEAL_PTR(*error, diskPriv->blockJobError);
> @@ -100,10 +101,12 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
> virDomainDiskDefPtr disk,
> qemuDomainAsyncJob asyncJob,
> int type,
> - int status)
> + int status,
> + const char *error)
> {
> virObjectEventPtr event = NULL;
> virObjectEventPtr event2 = NULL;
> + virObjectEventPtr errorEvent = NULL;
> const char *path;
> virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
> virDomainDiskDefPtr persistDisk = NULL;
> @@ -123,6 +126,8 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
> path = virDomainDiskGetSource(disk);
> event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
> event2 = virDomainEventBlockJob2NewFromObj(vm, disk->dst, type, status);
> + if (error)
> + errorEvent = virDomainEventBlockJobErrorNewFromObj(vm, disk->dst, type, 0, error);
>
> /* If we completed a block pull or commit, then update the XML
> * to match. */
> @@ -213,6 +218,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
>
> qemuDomainEventQueue(driver, event);
> qemuDomainEventQueue(driver, event2);
> + qemuDomainEventQueue(driver, errorEvent);
>
> virObjectUnref(cfg);
> }
> diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
> index e71d691..18bcaaa 100644
> --- a/src/qemu/qemu_blockjob.h
> +++ b/src/qemu/qemu_blockjob.h
> @@ -36,7 +36,8 @@ void qemuBlockJobEventProcess(virQEMUDriverPtr driver,
> virDomainDiskDefPtr disk,
> qemuDomainAsyncJob asyncJob,
> int type,
> - int status);
> + int status,
> + const char *error);
>
> void qemuBlockJobSyncBegin(virDomainDiskDefPtr disk);
> void qemuBlockJobSyncEnd(virQEMUDriverPtr driver,
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index e2a8450..883652d 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -11951,12 +11951,14 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
> case QEMU_PROCESS_EVENT_GUESTPANIC:
> qemuMonitorEventPanicInfoFree(event->data);
> break;
> + case QEMU_PROCESS_EVENT_MONITOR_EOF:
> + VIR_FREE(event->error);
> + ATTRIBUTE_FALLTHROUGH;
> case QEMU_PROCESS_EVENT_WATCHDOG:
> case QEMU_PROCESS_EVENT_DEVICE_DELETED:
> case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
> case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
> case QEMU_PROCESS_EVENT_BLOCK_JOB:
> - case QEMU_PROCESS_EVENT_MONITOR_EOF:
> VIR_FREE(event->data);
> break;
> case QEMU_PROCESS_EVENT_LAST:
> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> index 2c27dfb..f3b262f 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -456,6 +456,7 @@ struct qemuProcessEvent {
> int action;
> int status;
> void *data;
> + char *error;
> };
>
> void qemuProcessEventFree(struct qemuProcessEvent *event);
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 5673d9f..cefbe52 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -4748,7 +4748,8 @@ processBlockJobEvent(virQEMUDriverPtr driver,
> virDomainObjPtr vm,
> const char *diskAlias,
> int type,
> - int status)
> + int status,
> + char *error)
> {
> virDomainDiskDefPtr disk;
>
> @@ -4761,7 +4762,8 @@ processBlockJobEvent(virQEMUDriverPtr driver,
> }
>
> if ((disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias)))
> - qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE, type, status);
> + qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE,
> + type, status, error);
>
> endjob:
> qemuDomainObjEndJob(driver, vm);
> @@ -4846,7 +4848,8 @@ static void qemuProcessEventHandler(void *data, void *opaque)
> processBlockJobEvent(driver, vm,
> processEvent->data,
> processEvent->action,
> - processEvent->status);
> + processEvent->status,
> + processEvent->error);
> break;
> case QEMU_PROCESS_EVENT_MONITOR_EOF:
> processMonitorEOFEvent(driver, vm);
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 6a5262a..12b156f 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -1026,6 +1026,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> processEvent->vm = virObjectRef(vm);
> processEvent->action = type;
> processEvent->status = status;
> + ignore_value(VIR_STRDUP_QUIET(processEvent->error, error));
>
> if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
> ignore_value(virObjectUnref(vm));
> diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
> index a8a5932..07c9dbb 100644
> --- a/src/remote/remote_daemon_dispatch.c
> +++ b/src/remote/remote_daemon_dispatch.c
> @@ -1342,6 +1342,53 @@ remoteRelayDomainEventBlockThreshold(virConnectPtr conn,
> }
>
>
> +static int
> +remoteRelayDomainEventBlockJobError(virConnectPtr conn,
> + virDomainPtr dom,
> + const char *dev,
> + int type,
> + unsigned int code,
> + const char *message,
> + void *opaque)
> +{
> + daemonClientEventCallbackPtr callback = opaque;
> + remote_domain_event_block_job_error_msg msg;
> +
> + if (callback->callbackID < 0 ||
> + !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
> + return -1;
> +
> + VIR_DEBUG("Relaying domain block job error event %s %d %s %i %u %s, callback %d",
> + dom->name, dom->id, dev, type, code, NULLSTR(message),
> + callback->callbackID);
> +
> + memset(&msg, 0, sizeof(msg));
> + msg.callbackID = callback->callbackID;
> + if (VIR_STRDUP(msg.dev, dev) < 0)
> + return -1;
> + if (message) {
> + if (VIR_ALLOC(msg.message) < 0 ||
> + VIR_STRDUP(*(msg.message), message) < 0)
> + goto error;
> + }
> + msg.type = type;
> + msg.code = code;
> + make_nonnull_domain(&msg.dom, dom);
> +
> + remoteDispatchObjectEventSend(callback->client, remoteProgram,
> + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR,
> + (xdrproc_t)xdr_remote_domain_event_block_job_error_msg,
> + &msg);
> + return 0;
> +
> + error:
> + VIR_FREE(msg.dev);
> + VIR_FREE(msg.message);
> +
> + return -1;
> +}
> +
> +
> static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
> @@ -1368,6 +1415,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold),
> + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJobError),
> };
>
> verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index d3b588c..0d30bf3 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -405,6 +405,11 @@ remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_U
> virNetClientPtr client ATTRIBUTE_UNUSED,
> void *evdata, void *opaque);
>
> +static void
> +remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog,
> + virNetClientPtr client,
> + void *evdata, void *opaque);
> +
> static virNetClientProgramEvent remoteEvents[] = {
> { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
> remoteDomainBuildEventLifecycle,
> @@ -611,6 +616,10 @@ static virNetClientProgramEvent remoteEvents[] = {
> remoteDomainBuildEventBlockThreshold,
> sizeof(remote_domain_event_block_threshold_msg),
> (xdrproc_t)xdr_remote_domain_event_block_threshold_msg },
> + { REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR,
> + remoteDomainBuildEventBlockJobError,
> + sizeof(remote_domain_event_block_job_error_msg),
> + (xdrproc_t)xdr_remote_domain_event_block_job_error_msg },
> };
>
> static void
> @@ -5533,6 +5542,31 @@ remoteDomainBuildEventBlockThreshold(virNetClientProgramPtr prog ATTRIBUTE_UNUSE
> }
>
>
> +static void
> +remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> + virNetClientPtr client ATTRIBUTE_UNUSED,
> + void *evdata, void *opaque)
> +{
> + virConnectPtr conn = opaque;
> + remote_domain_event_block_job_error_msg *msg = evdata;
> + struct private_data *priv = conn->privateData;
> + virDomainPtr dom;
> + virObjectEventPtr event = NULL;
> +
> + dom = get_nonnull_domain(conn, msg->dom);
> + if (!dom)
> + return;
> +
> + event = virDomainEventBlockJobErrorNewFromDom(dom, msg->dev, msg->type,
> + msg->code,
> + msg->message ? *msg->message : NULL);
> +
> + virObjectUnref(dom);
> +
> + remoteEventQueue(priv, event, msg->callbackID);
> +}
> +
> +
> static int
> remoteStreamSend(virStreamPtr st,
> const char *data,
> diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
> index 296a087..051a773 100644
> --- a/src/remote/remote_protocol.x
> +++ b/src/remote/remote_protocol.x
> @@ -3103,6 +3103,15 @@ struct remote_domain_event_block_job_2_msg {
> int status;
> };
>
> +struct remote_domain_event_block_job_error_msg {
> + int callbackID;
> + remote_nonnull_domain dom;
> + remote_nonnull_string dev;
> + int type;
> + int code;
> + remote_string message;
> +};
> +
> struct remote_domain_event_block_threshold_msg {
> int callbackID;
> remote_nonnull_domain dom;
> @@ -6135,5 +6144,11 @@ enum remote_procedure {
> * @priority: high
> * @acl: storage_pool:getattr
> */
> - REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_TARGET_PATH = 391
> + REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_TARGET_PATH = 391,
> +
> + /**
> + * @generate: none
> + * @acl: none
> + */
> + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR = 392
> };
> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
> index fe163db..567f307 100644
> --- a/src/remote_protocol-structs
> +++ b/src/remote_protocol-structs
> @@ -2541,6 +2541,14 @@ struct remote_domain_event_block_job_2_msg {
> int type;
> int status;
> };
> +struct remote_domain_event_block_job_error_msg {
> + int callbackID;
> + remote_nonnull_domain dom;
> + remote_nonnull_string dev;
> + int type;
> + int code;
> + remote_string message;
> +};
> struct remote_domain_event_block_threshold_msg {
> int callbackID;
> remote_nonnull_domain dom;
> @@ -3269,4 +3277,5 @@ enum remote_procedure {
> REMOTE_PROC_DOMAIN_MANAGED_SAVE_DEFINE_XML = 389,
> REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION = 390,
> REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_TARGET_PATH = 391,
> + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR = 392,
> };
> diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
> index 2b775fc..40d3c82 100644
> --- a/tools/virsh-domain.c
> +++ b/tools/virsh-domain.c
> @@ -13286,6 +13286,28 @@ virshEventBlockThresholdPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
> }
>
>
> +static void
> +virshEventBlockJobErrorPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virDomainPtr dom,
> + const char *dev,
> + int type,
> + unsigned int code ATTRIBUTE_UNUSED,
> + const char *message,
> + void *opaque)
> +{
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
> +
> + virBufferAsprintf(&buf, _("event '%s' for domain %s: %s for %s, "
> + "error: %s\n"),
> + ((virshDomEventData *) opaque)->cb->name,
> + virDomainGetName(dom),
> + virshDomainBlockJobToString(type),
> + dev,
> + NULLSTR(message));
> + virshEventPrint(opaque, &buf);
> +}
> +
> +
> static vshEventCallback vshEventCallbacks[] = {
> { "lifecycle",
> VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
> @@ -13335,6 +13357,8 @@ static vshEventCallback vshEventCallbacks[] = {
> VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), },
> { "block-threshold",
> VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), },
> + { "block-job-error",
> + VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockJobErrorPrint), },
> };
> verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
>
>
More information about the libvir-list
mailing list