From nobody Mon May 6 00:05:59 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1524147686429451.4793159938215; Thu, 19 Apr 2018 07:21:26 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C2A313134698; Thu, 19 Apr 2018 14:21:24 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7426B8C7DA; Thu, 19 Apr 2018 14:21:23 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 4B05B4CAA6; Thu, 19 Apr 2018 14:21:13 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3JELA2s007168 for ; Thu, 19 Apr 2018 10:21:10 -0400 Received: by smtp.corp.redhat.com (Postfix) id 4BA8D92316; Thu, 19 Apr 2018 14:21:10 +0000 (UTC) Received: from mx1.redhat.com (ext-mx14.extmail.prod.ext.phx2.redhat.com [10.5.110.43]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A76C5922E4; Thu, 19 Apr 2018 14:20:41 +0000 (UTC) Received: from relay.sw.ru (relay.sw.ru [185.231.240.75]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 21E01312FF91; Thu, 19 Apr 2018 14:18:47 +0000 (UTC) Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=dim-vz7.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1f9AOa-0001Vs-0L; Thu, 19 Apr 2018 17:18:44 +0300 From: Nikolay Shirokovskiy To: libvir-list@redhat.com Date: Thu, 19 Apr 2018 17:18:37 +0300 Message-Id: <1524147517-348945-1-git-send-email-nshirokovskiy@virtuozzo.com> X-Greylist: Sender passed SPF test, ACL 227 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Thu, 19 Apr 2018 14:19:28 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Thu, 19 Apr 2018 14:19:28 +0000 (UTC) for IP:'185.231.240.75' DOMAIN:'relay.sw.ru' HELO:'relay.sw.ru' FROM:'nshirokovskiy@virtuozzo.com' RCPT:'' X-RedHat-Spam-Score: -0.001 (SPF_PASS) 185.231.240.75 relay.sw.ru 185.231.240.75 relay.sw.ru X-Scanned-By: MIMEDefang 2.84 on 10.5.110.43 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Cc: Peter Krempa Subject: [libvirt] [PATCH v2 REBASE] lib: provide error message in new blockjob event X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Thu, 19 Apr 2018 14:21:25 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 --- 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 t= oo. [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/e= vent-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 ATTRI= BUTE_UNUSED, =20 =20 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 =3D 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[] =3D { DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventD= eviceRemovalFailedCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadat= aChangeCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockTh= resholdCallback), + DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR, myDomainEventBlockJo= bErrorCallback), }; =20 struct storagePoolEventData { diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-dom= ain.h index 12fd340..ee55ab9 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4370,6 +4370,30 @@ typedef void (*virConnectDomainEventBlockThresholdCa= llback)(virConnectPtr conn, unsigned long = long excess, void *opaque); =20 + +/** + * 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 c= onn, + virDomainPtr do= m, + const char *dev, + int type, + unsigned int co= de, + const char *mes= sage, + void *opaque); + /** * VIR_DOMAIN_EVENT_CALLBACK: * @@ -4412,6 +4436,7 @@ typedef enum { VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED =3D 22, /* virConnectDomainE= ventDeviceRemovalFailedCallback */ VIR_DOMAIN_EVENT_ID_METADATA_CHANGE =3D 23, /* virConnectDomainEventMe= tadataChangeCallback */ VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD =3D 24, /* virConnectDomainEventBl= ockThresholdCallback */ + VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR =3D 25, /* virConnectDomainEventBl= ockJobErrorCallback */ =20 # 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; =20 +struct _virDomainEventBlockJobError { + virDomainEvent parent; + + char *dev; + int type; + unsigned int code; + char *message; +}; +typedef struct _virDomainEventBlockJobError virDomainEventBlockJobError; +typedef virDomainEventBlockJobError *virDomainEventBlockJobErrorPtr; + struct _virDomainEventGraphics { virDomainEvent parent; =20 @@ -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) } =20 static void +virDomainEventBlockJobErrorDispose(void *obj) +{ + virDomainEventBlockJobErrorPtr event =3D obj; + VIR_DEBUG("obj=3D%p", event); + + VIR_FREE(event->dev); + VIR_FREE(event->message); +} + +static void virDomainEventDiskChangeDispose(void *obj) { virDomainEventDiskChangePtr event =3D obj; @@ -977,6 +1002,59 @@ virDomainEventBlockJob2NewFromDom(virDomainPtr dom, dst, type, status); } =20 +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 =3D 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 =3D type; + ev->code =3D 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; } =20 + case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR: + { + virDomainEventBlockJobErrorPtr blockJobErrorEvent; + + blockJobErrorEvent =3D (virDomainEventBlockJobErrorPtr)event; + ((virConnectDomainEventBlockJobErrorCallback)cb)(conn, dom, + blockJobError= Event->dev, + blockJobError= Event->type, + blockJobError= Event->code, + blockJobError= Event->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); =20 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 !=3D -1) { qemuBlockJobEventProcess(driver, vm, disk, asyncJob, diskPriv->blockJobType, - diskPriv->blockJobStatus); + diskPriv->blockJobStatus, + diskPriv->blockJobError); diskPriv->blockJobStatus =3D -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 =3D NULL; virObjectEventPtr event2 =3D NULL; + virObjectEventPtr errorEvent =3D NULL; const char *path; virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); virDomainDiskDefPtr persistDisk =3D NULL; @@ -123,6 +126,8 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver, path =3D virDomainDiskGetSource(disk); event =3D virDomainEventBlockJobNewFromObj(vm, path, type, status); event2 =3D virDomainEventBlockJob2NewFromObj(vm, disk->dst, type, stat= us); + if (error) + errorEvent =3D virDomainEventBlockJobErrorNewFromObj(vm, disk->dst= , type, 0, error); =20 /* If we completed a block pull or commit, then update the XML * to match. */ @@ -213,6 +218,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver, =20 qemuDomainEventQueue(driver, event); qemuDomainEventQueue(driver, event2); + qemuDomainEventQueue(driver, errorEvent); =20 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); =20 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 *eve= nt) 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; }; =20 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; =20 @@ -4761,7 +4762,8 @@ processBlockJobEvent(virQEMUDriverPtr driver, } =20 if ((disk =3D qemuProcessFindDomainDiskByAlias(vm, diskAlias))) - qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE, ty= pe, status); + qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE, + type, status, error); =20 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 ATTRIBUT= E_UNUSED, processEvent->vm =3D virObjectRef(vm); processEvent->action =3D type; processEvent->status =3D status; + ignore_value(VIR_STRDUP_QUIET(processEvent->error, error)); =20 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 c= onn, } =20 =20 +static int +remoteRelayDomainEventBlockJobError(virConnectPtr conn, + virDomainPtr dom, + const char *dev, + int type, + unsigned int code, + const char *message, + void *opaque) +{ + daemonClientEventCallbackPtr callback =3D 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, ca= llback %d", + dom->name, dom->id, dev, type, code, NULLSTR(message), + callback->callbackID); + + memset(&msg, 0, sizeof(msg)); + msg.callbackID =3D 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 =3D type; + msg.code =3D 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[] =3D { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), @@ -1368,6 +1415,7 @@ static virConnectDomainEventGenericCallback domainEve= ntCallbacks[] =3D { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold), + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJobError), }; =20 verify(ARRAY_CARDINALITY(domainEventCallbacks) =3D=3D 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(virNetClientP= rogramPtr prog ATTRIBUTE_U virNetClientPtr client ATTRIBUTE_= UNUSED, void *evdata, void *opaque); =20 +static void +remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + static virNetClientProgramEvent remoteEvents[] =3D { { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, remoteDomainBuildEventLifecycle, @@ -611,6 +616,10 @@ static virNetClientProgramEvent remoteEvents[] =3D { 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 }, }; =20 static void @@ -5533,6 +5542,31 @@ remoteDomainBuildEventBlockThreshold(virNetClientPro= gramPtr prog ATTRIBUTE_UNUSE } =20 =20 +static void +remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog ATTRIBUTE_= UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSE= D, + void *evdata, void *opaque) +{ + virConnectPtr conn =3D opaque; + remote_domain_event_block_job_error_msg *msg =3D evdata; + struct private_data *priv =3D conn->privateData; + virDomainPtr dom; + virObjectEventPtr event =3D NULL; + + dom =3D get_nonnull_domain(conn, msg->dom); + if (!dom) + return; + + event =3D virDomainEventBlockJobErrorNewFromDom(dom, msg->dev, msg->ty= pe, + msg->code, + msg->message ? *msg->mes= sage : 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; }; =20 +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 =3D 391 + REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_TARGET_PATH =3D 391, + + /** + * @generate: none + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR =3D 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 =3D 389, REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION =3D 390, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_TARGET_PATH =3D 391, + REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR =3D 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 A= TTRIBUTE_UNUSED, } =20 =20 +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 =3D 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[] =3D { { "lifecycle", VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), }, @@ -13335,6 +13357,8 @@ static vshEventCallback vshEventCallbacks[] =3D { 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 =3D=3D ARRAY_CARDINALITY(vshEventCallbacks= )); =20 --=20 1.8.3.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list