The VIR_STORAGE_POOL_EVENT_REFRESHED constant does not reflect any change in the lifecycle of the storage pool. It should thus not be part of the storage pool lifecycle event set, but rather be a top level event in its own right. Thus we introduce VIR_STORAGE_POOL_EVENT_ID_REFRESH to replace it. Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- NB this breaks API and wire protocol, so we *must* include this before 2.0.0. Ideally we should get it into before we cut any rc release too. daemon/remote.c | 29 +++++++++++++++++ examples/object-events/event-test.c | 14 ++++++-- include/libvirt/libvirt-storage.h | 2 +- src/conf/storage_event.c | 57 +++++++++++++++++++++++++++++++++ src/conf/storage_event.h | 4 +++ src/libvirt_private.syms | 1 + src/remote/remote_driver.c | 30 +++++++++++++++++ src/remote/remote_protocol.x | 13 +++++++- src/remote_protocol-structs | 5 +++ src/storage/storage_driver.c | 12 +++---- src/test/test_driver.c | 4 +-- tests/objecteventtest.c | 29 ++++++++++++----- tools/virsh-pool.c | 64 +++++++++++++++++++++++++++++++------ 13 files changed, 232 insertions(+), 32 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 5ee82bb..4aa43c2 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1294,8 +1294,37 @@ remoteRelayStoragePoolEventLifecycle(virConnectPtr conn, return 0; } +static int +remoteRelayStoragePoolEventRefresh(virConnectPtr conn, + virStoragePoolPtr pool, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; + remote_storage_pool_event_refresh_msg data; + + if (callback->callbackID < 0 || + !remoteRelayStoragePoolEventCheckACL(callback->client, conn, pool)) + return -1; + + VIR_DEBUG("Relaying storage pool refresh event callback %d", + callback->callbackID); + + /* build return data */ + memset(&data, 0, sizeof(data)); + make_nonnull_storage_pool(&data.pool, pool); + data.callbackID = callback->callbackID; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_STORAGE_POOL_EVENT_REFRESH, + (xdrproc_t)xdr_remote_storage_pool_event_refresh_msg, + &data); + + return 0; +} + static virConnectStoragePoolEventGenericCallback storageEventCallbacks[] = { VIR_STORAGE_POOL_EVENT_CALLBACK(remoteRelayStoragePoolEventLifecycle), + VIR_STORAGE_POOL_EVENT_CALLBACK(remoteRelayStoragePoolEventRefresh), }; verify(ARRAY_CARDINALITY(storageEventCallbacks) == VIR_STORAGE_POOL_EVENT_ID_LAST); diff --git a/examples/object-events/event-test.c b/examples/object-events/event-test.c index 215e026..f2f71cc 100644 --- a/examples/object-events/event-test.c +++ b/examples/object-events/event-test.c @@ -349,8 +349,6 @@ storagePoolEventToString(int event) return "Started"; case VIR_STORAGE_POOL_EVENT_STOPPED: return "Stopped"; - case VIR_STORAGE_POOL_EVENT_REFRESHED: - return "Refreshed"; case VIR_STORAGE_POOL_EVENT_LAST: break; } @@ -679,6 +677,17 @@ myStoragePoolEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED, } +static int +myStoragePoolEventRefreshCallback(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolPtr pool, + void *opaque ATTRIBUTE_UNUSED) +{ + printf("%s EVENT: Storage pool %s refresh\n", __func__, + virStoragePoolGetName(pool)); + return 0; +} + + static void eventTypedParamsPrint(virTypedParameterPtr params, int nparams) @@ -936,6 +945,7 @@ struct storagePoolEventData { struct storagePoolEventData storagePoolEvents[] = { STORAGE_POOL_EVENT(VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE, myStoragePoolEventCallback), + STORAGE_POOL_EVENT(VIR_STORAGE_POOL_EVENT_ID_REFRESH, myStoragePoolEventRefreshCallback), }; /* make sure that the events are kept in sync */ diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h index a67a97f..0974f6e 100644 --- a/include/libvirt/libvirt-storage.h +++ b/include/libvirt/libvirt-storage.h @@ -394,6 +394,7 @@ int virStoragePoolIsPersistent(virStoragePoolPtr pool); */ typedef enum { VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE = 0, /* virConnectStoragePoolEventLifecycleCallback */ + VIR_STORAGE_POOL_EVENT_ID_REFRESH = 1, /* virConnectStoragePoolEventGenericCallback */ # ifdef VIR_ENUM_SENTINELS VIR_STORAGE_POOL_EVENT_ID_LAST @@ -443,7 +444,6 @@ typedef enum { VIR_STORAGE_POOL_EVENT_UNDEFINED = 1, VIR_STORAGE_POOL_EVENT_STARTED = 2, VIR_STORAGE_POOL_EVENT_STOPPED = 3, - VIR_STORAGE_POOL_EVENT_REFRESHED = 4, # ifdef VIR_ENUM_SENTINELS VIR_STORAGE_POOL_EVENT_LAST diff --git a/src/conf/storage_event.c b/src/conf/storage_event.c index c5688be..5768bab 100644 --- a/src/conf/storage_event.c +++ b/src/conf/storage_event.c @@ -48,10 +48,20 @@ struct _virStoragePoolEventLifecycle { typedef struct _virStoragePoolEventLifecycle virStoragePoolEventLifecycle; typedef virStoragePoolEventLifecycle *virStoragePoolEventLifecyclePtr; +struct _virStoragePoolEventRefresh { + virStoragePoolEvent parent; + + bool dummy; +}; +typedef struct _virStoragePoolEventRefresh virStoragePoolEventRefresh; +typedef virStoragePoolEventRefresh *virStoragePoolEventRefreshPtr; + static virClassPtr virStoragePoolEventClass; static virClassPtr virStoragePoolEventLifecycleClass; +static virClassPtr virStoragePoolEventRefreshClass; static void virStoragePoolEventDispose(void *obj); static void virStoragePoolEventLifecycleDispose(void *obj); +static void virStoragePoolEventRefreshDispose(void *obj); static int virStoragePoolEventsOnceInit(void) @@ -68,6 +78,12 @@ virStoragePoolEventsOnceInit(void) sizeof(virStoragePoolEventLifecycle), virStoragePoolEventLifecycleDispose))) return -1; + if (!(virStoragePoolEventRefreshClass = + virClassNew(virStoragePoolEventClass, + "virStoragePoolEventRefresh", + sizeof(virStoragePoolEventRefresh), + virStoragePoolEventRefreshDispose))) + return -1; return 0; } @@ -90,6 +106,14 @@ virStoragePoolEventLifecycleDispose(void *obj) static void +virStoragePoolEventRefreshDispose(void *obj) +{ + virStoragePoolEventRefreshPtr event = obj; + VIR_DEBUG("obj=%p", event); +} + + +static void virStoragePoolEventDispatchDefaultFunc(virConnectPtr conn, virObjectEventPtr event, virConnectObjectEventGenericCallback cb, @@ -115,6 +139,13 @@ virStoragePoolEventDispatchDefaultFunc(virConnectPtr conn, goto cleanup; } + case VIR_STORAGE_POOL_EVENT_ID_REFRESH: + { + ((virConnectStoragePoolEventGenericCallback)cb)(conn, pool, + cbopaque); + goto cleanup; + } + case VIR_STORAGE_POOL_EVENT_ID_LAST: break; } @@ -235,3 +266,29 @@ virStoragePoolEventLifecycleNew(const char *name, return (virObjectEventPtr)event; } + + +/** + * virStoragePoolEventRefreshNew: + * @name: name of the storage pool object the event describes + * @uuid: uuid of the storage pool object the event describes + * + * Create a new storage pool refresh event. + */ +virObjectEventPtr +virStoragePoolEventRefreshNew(const char *name, + const unsigned char *uuid) +{ + virStoragePoolEventRefreshPtr event; + + if (virStoragePoolEventsInitialize() < 0) + return NULL; + + if (!(event = virObjectEventNew(virStoragePoolEventRefreshClass, + virStoragePoolEventDispatchDefaultFunc, + VIR_STORAGE_POOL_EVENT_ID_REFRESH, + 0, name, uuid))) + return NULL; + + return (virObjectEventPtr)event; +} diff --git a/src/conf/storage_event.h b/src/conf/storage_event.h index 7c8ccb7..ea72691 100644 --- a/src/conf/storage_event.h +++ b/src/conf/storage_event.h @@ -57,4 +57,8 @@ virStoragePoolEventLifecycleNew(const char *name, int type, int detail); +virObjectEventPtr +virStoragePoolEventRefreshNew(const char *name, + const unsigned char *uuid); + #endif diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ef30f7f..0009f89 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -881,6 +881,7 @@ virStorageVolTypeToString; # conf/storage_event.h virStoragePoolEventLifecycleNew; +virStoragePoolEventRefreshNew; virStoragePoolEventStateRegisterID; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 1f81f03..e9904f8 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -362,6 +362,11 @@ remoteStoragePoolBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSE void *evdata, void *opaque); static void +remoteStoragePoolBuildEventRefresh(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque); + +static void remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque); @@ -544,6 +549,10 @@ static virNetClientProgramEvent remoteEvents[] = { remoteStoragePoolBuildEventLifecycle, sizeof(remote_storage_pool_event_lifecycle_msg), (xdrproc_t)xdr_remote_storage_pool_event_lifecycle_msg }, + { REMOTE_PROC_STORAGE_POOL_EVENT_REFRESH, + remoteStoragePoolBuildEventRefresh, + sizeof(remote_storage_pool_event_refresh_msg), + (xdrproc_t)xdr_remote_storage_pool_event_refresh_msg }, }; static void @@ -5134,6 +5143,27 @@ remoteStoragePoolBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSE } static void +remoteStoragePoolBuildEventRefresh(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + struct private_data *priv = conn->privateData; + remote_storage_pool_event_refresh_msg *msg = evdata; + virStoragePoolPtr pool; + virObjectEventPtr event = NULL; + + pool = get_nonnull_storage_pool(conn, msg->pool); + if (!pool) + return; + + event = virStoragePoolEventRefreshNew(pool->name, pool->uuid); + virObjectUnref(pool); + + remoteEventQueue(priv, event, msg->callbackID); +} + +static void remoteDomainBuildQemuMonitorEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, void *evdata, void *opaque) diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index d11bfdf..4403714 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3126,6 +3126,11 @@ struct remote_storage_pool_event_lifecycle_msg { int detail; }; +struct remote_storage_pool_event_refresh_msg { + int callbackID; + remote_nonnull_storage_pool pool; +}; + struct remote_domain_fsfreeze_args { remote_nonnull_domain dom; remote_nonnull_string mountpoints<REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX>; /* (const char **) */ @@ -5871,5 +5876,11 @@ enum remote_procedure { * @generate: both * @acl: domain:write */ - REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS = 372 + REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS = 372, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_STORAGE_POOL_EVENT_REFRESH = 373 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 0d89b15..46e798b 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2567,6 +2567,10 @@ struct remote_storage_pool_event_lifecycle_msg { int event; int detail; }; +struct remote_storage_pool_event_refresh_msg { + int callbackID; + remote_nonnull_storage_pool pool; +}; struct remote_domain_fsfreeze_args { remote_nonnull_domain dom; struct { @@ -3140,4 +3144,5 @@ enum remote_procedure { REMOTE_PROC_STORAGE_POOL_EVENT_LIFECYCLE = 370, REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS = 371, REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS = 372, + REMOTE_PROC_STORAGE_POOL_EVENT_REFRESH = 373, }; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index d75c5aa..cef2124 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1206,10 +1206,8 @@ storagePoolRefresh(virStoragePoolPtr obj, goto cleanup; } - event = virStoragePoolEventLifecycleNew(pool->def->name, - pool->def->uuid, - VIR_STORAGE_POOL_EVENT_REFRESHED, - 0); + event = virStoragePoolEventRefreshNew(pool->def->name, + pool->def->uuid); ret = 0; cleanup: @@ -2342,10 +2340,8 @@ virStorageVolPoolRefreshThread(void *opaque) if (backend->refreshPool(NULL, pool) < 0) VIR_DEBUG("Failed to refresh storage pool"); - event = virStoragePoolEventLifecycleNew(pool->def->name, - pool->def->uuid, - VIR_STORAGE_POOL_EVENT_REFRESHED, - 0); + event = virStoragePoolEventRefreshNew(pool->def->name, + pool->def->uuid); cleanup: if (event) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 2622335..baff085 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4480,9 +4480,7 @@ testStoragePoolRefresh(virStoragePoolPtr pool, goto cleanup; } - event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid, - VIR_STORAGE_POOL_EVENT_REFRESHED, - 0); + event = virStoragePoolEventRefreshNew(pool->name, pool->uuid); ret = 0; cleanup: diff --git a/tests/objecteventtest.c b/tests/objecteventtest.c index ac8cce3..5e8087b 100644 --- a/tests/objecteventtest.c +++ b/tests/objecteventtest.c @@ -67,7 +67,6 @@ typedef struct { int defineEvents; int undefineEvents; int unexpectedEvents; - int refreshEvents; } lifecycleEventCounter; static void @@ -78,7 +77,6 @@ lifecycleEventCounter_reset(lifecycleEventCounter *counter) counter->defineEvents = 0; counter->undefineEvents = 0; counter->unexpectedEvents = 0; - counter->refreshEvents = 0; } typedef struct { @@ -153,8 +151,16 @@ storagePoolLifecycleCb(virConnectPtr conn ATTRIBUTE_UNUSED, counter->defineEvents++; else if (event == VIR_STORAGE_POOL_EVENT_UNDEFINED) counter->undefineEvents++; - else if (event == VIR_STORAGE_POOL_EVENT_REFRESHED) - counter->refreshEvents++; +} + +static void +storagePoolRefreshCb(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolPtr pool ATTRIBUTE_UNUSED, + void* opaque) +{ + int *counter = opaque; + + (*counter)++; } static int @@ -646,18 +652,24 @@ testStoragePoolStartStopEvent(const void *data) { const objecteventTest *test = data; lifecycleEventCounter counter; - int id; + int refreshCounter; + int id1, id2; int ret = 0; if (!test->pool) return -1; lifecycleEventCounter_reset(&counter); + refreshCounter = 0; - id = virConnectStoragePoolEventRegisterAny(test->conn, test->pool, + id1 = virConnectStoragePoolEventRegisterAny(test->conn, test->pool, VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE, VIR_STORAGE_POOL_EVENT_CALLBACK(&storagePoolLifecycleCb), &counter, NULL); + id2 = virConnectStoragePoolEventRegisterAny(test->conn, test->pool, + VIR_STORAGE_POOL_EVENT_ID_REFRESH, + VIR_STORAGE_POOL_EVENT_CALLBACK(&storagePoolRefreshCb), + &refreshCounter, NULL); virStoragePoolCreate(test->pool, 0); virStoragePoolRefresh(test->pool, 0); virStoragePoolDestroy(test->pool); @@ -668,13 +680,14 @@ testStoragePoolStartStopEvent(const void *data) } if (counter.startEvents != 1 || counter.stopEvents != 1 || - counter.refreshEvents != 1 || counter.unexpectedEvents > 0) { + refreshCounter != 1 || counter.unexpectedEvents > 0) { ret = -1; goto cleanup; } cleanup: - virConnectStoragePoolEventDeregisterAny(test->conn, id); + virConnectStoragePoolEventDeregisterAny(test->conn, id1); + virConnectStoragePoolEventDeregisterAny(test->conn, id2); return ret; } diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index 18e218c..6045331 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -1899,8 +1899,7 @@ VIR_ENUM_IMPL(virshPoolEvent, N_("Defined"), N_("Undefined"), N_("Started"), - N_("Stopped"), - N_("Refreshed")) + N_("Stopped")) static const char * virshPoolEventToString(int event) @@ -1909,18 +1908,21 @@ virshPoolEventToString(int event) return str ? _(str) : _("unknown"); } +struct vshEventCallback { + const char *name; + virConnectStoragePoolEventGenericCallback cb; +}; +typedef struct vshEventCallback vshEventCallback; + struct virshPoolEventData { vshControl *ctl; bool loop; bool timestamp; int count; + vshEventCallback *cb; }; typedef struct virshPoolEventData virshPoolEventData; -VIR_ENUM_DECL(virshPoolEventId) -VIR_ENUM_IMPL(virshPoolEventId, - VIR_STORAGE_POOL_EVENT_ID_LAST, - "lifecycle") static void vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED, @@ -1955,6 +1957,45 @@ vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED, vshEventDone(data->ctl); } +static void +vshEventGenericPrint(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolPtr pool, + void *opaque) +{ + virshPoolEventData *data = opaque; + + if (!data->loop && data->count) + return; + + if (data->timestamp) { + char timestamp[VIR_TIME_STRING_BUFLEN]; + + if (virTimeStringNowRaw(timestamp) < 0) + timestamp[0] = '\0'; + + vshPrint(data->ctl, _("%s: event '%s'' for storage pool %s\n"), + timestamp, + data->cb->name, + virStoragePoolGetName(pool)); + } else { + vshPrint(data->ctl, _("event '%s' for storage pool %s\n"), + data->cb->name, + virStoragePoolGetName(pool)); + } + + data->count++; + if (!data->loop) + vshEventDone(data->ctl); +} + +static vshEventCallback vshEventCallbacks[] = { + { "lifecycle", + VIR_STORAGE_POOL_EVENT_CALLBACK(vshEventLifecyclePrint), }, + { "refresh", vshEventGenericPrint, } +}; +verify(VIR_STORAGE_POOL_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks)); + + static const vshCmdInfo info_pool_event[] = { {.name = "help", .data = N_("Storage Pool Events") @@ -2009,7 +2050,7 @@ cmdPoolEvent(vshControl *ctl, const vshCmd *cmd) size_t i; for (i = 0; i < VIR_STORAGE_POOL_EVENT_ID_LAST; i++) - vshPrint(ctl, "%s\n", virshPoolEventIdTypeToString(i)); + vshPrint(ctl, "%s\n", vshEventCallbacks[i].name); return true; } @@ -2019,7 +2060,11 @@ cmdPoolEvent(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("either --list or event type is required")); return false; } - if ((event = virshPoolEventIdTypeFromString(eventName)) < 0) { + + for (event = 0; event < VIR_STORAGE_POOL_EVENT_ID_LAST; event++) + if (STREQ(eventName, vshEventCallbacks[event].name)) + break; + if (event == VIR_STORAGE_POOL_EVENT_ID_LAST) { vshError(ctl, _("unknown event type %s"), eventName); return false; } @@ -2028,6 +2073,7 @@ cmdPoolEvent(vshControl *ctl, const vshCmd *cmd) data.loop = vshCommandOptBool(cmd, "loop"); data.timestamp = vshCommandOptBool(cmd, "timestamp"); data.count = 0; + data.cb = &vshEventCallbacks[event]; if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) return false; @@ -2037,7 +2083,7 @@ cmdPoolEvent(vshControl *ctl, const vshCmd *cmd) goto cleanup; if ((eventId = virConnectStoragePoolEventRegisterAny(priv->conn, pool, event, - VIR_STORAGE_POOL_EVENT_CALLBACK(vshEventLifecyclePrint), + data.cb->cb, &data, NULL)) < 0) goto cleanup; switch (vshEventWait(ctl)) { -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list