]> xenbits.xensource.com Git - libvirt.git/commitdiff
Add VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED event
authorPeter Krempa <pkrempa@redhat.com>
Wed, 30 Mar 2016 16:09:45 +0000 (18:09 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Wed, 13 Apr 2016 11:26:29 +0000 (13:26 +0200)
Since we didn't opt to use one single event for device lifecycle for a
VM we are missing one last event if the device removal failed. This
event will be emitted once we asked to eject the device but for some
reason it is not possible.

daemon/remote.c
include/libvirt/libvirt-domain.h
src/conf/domain_event.c
src/conf/domain_event.h
src/libvirt_private.syms
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs
tools/virsh-domain.c

index 9db93ffefbc3cae73490615b3cdbc9f5c9505d18..fde029da21f2f52164d890466c18eeea65ad39f6 100644 (file)
@@ -1136,6 +1136,41 @@ remoteRelayDomainEventJobCompleted(virConnectPtr conn,
 }
 
 
+static int
+remoteRelayDomainEventDeviceRemovalFailed(virConnectPtr conn,
+                                          virDomainPtr dom,
+                                          const char *devAlias,
+                                          void *opaque)
+{
+    daemonClientEventCallbackPtr callback = opaque;
+    remote_domain_event_callback_device_removal_failed_msg data;
+
+    if (callback->callbackID < 0 ||
+        !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
+        return -1;
+
+    VIR_DEBUG("Relaying domain device removal failed event %s %d %s, callback %d",
+              dom->name, dom->id, devAlias, callback->callbackID);
+
+    /* build return data */
+    memset(&data, 0, sizeof(data));
+
+    if (VIR_STRDUP(data.devAlias, devAlias) < 0)
+        return -1;
+
+    make_nonnull_domain(&data.dom, dom);
+    data.callbackID = callback->callbackID;
+
+    remoteDispatchObjectEventSend(callback->client, remoteProgram,
+                                  REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVAL_FAILED,
+                                  (xdrproc_t)xdr_remote_domain_event_callback_device_removal_failed_msg,
+                                  &data);
+
+    return 0;
+}
+
+
+
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -1159,6 +1194,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceAdded),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMigrationIteration),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventJobCompleted),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed),
 };
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
index 728b6eb35eaa00b38b19df871a4a2db4fb7ad505..8220ab090aca7b8c575f39188f30680bee7c47df 100644 (file)
@@ -3342,6 +3342,26 @@ typedef void (*virConnectDomainEventDeviceAddedCallback)(virConnectPtr conn,
                                                          const char *devAlias,
                                                          void *opaque);
 
+
+/**
+ * virConnectDomainEventDeviceRemovalFailedCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @devAlias: device alias
+ * @opaque: application specified data
+ *
+ * This callback occurs when it's certain that removal of a device failed.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED with
+ * virConnectDomainEventRegisterAny().
+ */
+typedef void (*virConnectDomainEventDeviceRemovalFailedCallback)(virConnectPtr conn,
+                                                                 virDomainPtr dom,
+                                                                 const char *devAlias,
+                                                                 void *opaque);
+
+
 /**
  * virConnectDomainEventMigrationIterationCallback:
  * @conn: connection object
@@ -3687,6 +3707,7 @@ typedef enum {
     VIR_DOMAIN_EVENT_ID_DEVICE_ADDED = 19,   /* virConnectDomainEventDeviceAddedCallback */
     VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION = 20, /* virConnectDomainEventMigrationIterationCallback */
     VIR_DOMAIN_EVENT_ID_JOB_COMPLETED = 21,  /* virConnectDomainEventJobCompletedCallback */
+    VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED = 22, /* virConnectDomainEventDeviceRemovalFailedCallback */
 
 # ifdef VIR_ENUM_SENTINELS
     VIR_DOMAIN_EVENT_ID_LAST
index a9107e5f5ed48333482a0129b80b2d7fdc2abf09..58823e89d400cf5fdef21251c15e6c70b85465c4 100644 (file)
@@ -58,6 +58,7 @@ static virClassPtr virDomainEventAgentLifecycleClass;
 static virClassPtr virDomainEventDeviceAddedClass;
 static virClassPtr virDomainEventMigrationIterationClass;
 static virClassPtr virDomainEventJobCompletedClass;
+static virClassPtr virDomainEventDeviceRemovalFailedClass;
 
 static void virDomainEventDispose(void *obj);
 static void virDomainEventLifecycleDispose(void *obj);
@@ -77,6 +78,7 @@ static void virDomainEventAgentLifecycleDispose(void *obj);
 static void virDomainEventDeviceAddedDispose(void *obj);
 static void virDomainEventMigrationIterationDispose(void *obj);
 static void virDomainEventJobCompletedDispose(void *obj);
+static void virDomainEventDeviceRemovalFailedDispose(void *obj);
 
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
@@ -256,6 +258,16 @@ struct _virDomainEventJobCompleted {
 typedef struct _virDomainEventJobCompleted virDomainEventJobCompleted;
 typedef virDomainEventJobCompleted *virDomainEventJobCompletedPtr;
 
+struct _virDomainEventDeviceRemovalFailed {
+    virDomainEvent parent;
+
+    char *devAlias;
+};
+typedef struct _virDomainEventDeviceRemovalFailed virDomainEventDeviceRemovalFailed;
+typedef virDomainEventDeviceRemovalFailed *virDomainEventDeviceRemovalFailedPtr;
+
+
+
 static int
 virDomainEventsOnceInit(void)
 {
@@ -367,6 +379,12 @@ virDomainEventsOnceInit(void)
                       sizeof(virDomainEventJobCompleted),
                       virDomainEventJobCompletedDispose)))
         return -1;
+    if (!(virDomainEventDeviceRemovalFailedClass =
+          virClassNew(virDomainEventClass,
+                      "virDomainEventDeviceRemovalFailed",
+                      sizeof(virDomainEventDeviceRemovalFailed),
+                      virDomainEventDeviceRemovalFailedDispose)))
+        return -1;
     return 0;
 }
 
@@ -494,6 +512,17 @@ virDomainEventDeviceAddedDispose(void *obj)
     VIR_FREE(event->devAlias);
 }
 
+
+static void
+virDomainEventDeviceRemovalFailedDispose(void *obj)
+{
+    virDomainEventDeviceRemovalFailedPtr event = obj;
+    VIR_DEBUG("obj=%p", event);
+
+    VIR_FREE(event->devAlias);
+}
+
+
 static void
 virDomainEventPMDispose(void *obj)
 {
@@ -1340,6 +1369,50 @@ virDomainEventDeviceAddedNewFromDom(virDomainPtr dom,
                                           devAlias);
 }
 
+
+static virObjectEventPtr
+virDomainEventDeviceRemovalFailedNew(int id,
+                                     const char *name,
+                                     unsigned char *uuid,
+                                     const char *devAlias)
+{
+    virDomainEventDeviceRemovalFailedPtr ev;
+
+    if (virDomainEventsInitialize() < 0)
+        return NULL;
+
+    if (!(ev = virDomainEventNew(virDomainEventDeviceAddedClass,
+                                 VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED,
+                                 id, name, uuid)))
+        return NULL;
+
+    if (VIR_STRDUP(ev->devAlias, devAlias) < 0)
+        goto error;
+
+    return (virObjectEventPtr)ev;
+
+ error:
+    virObjectUnref(ev);
+    return NULL;
+}
+
+virObjectEventPtr
+virDomainEventDeviceRemovalFailedNewFromObj(virDomainObjPtr obj,
+                                            const char *devAlias)
+{
+    return virDomainEventDeviceRemovalFailedNew(obj->def->id, obj->def->name,
+                                                obj->def->uuid, devAlias);
+}
+
+virObjectEventPtr
+virDomainEventDeviceRemovalFailedNewFromDom(virDomainPtr dom,
+                                            const char *devAlias)
+{
+    return virDomainEventDeviceRemovalFailedNew(dom->id, dom->name, dom->uuid,
+                                                devAlias);
+}
+
+
 static virObjectEventPtr
 virDomainEventAgentLifecycleNew(int id,
                                 const char *name,
@@ -1768,6 +1841,17 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
             goto cleanup;
         }
 
+    case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED:
+        {
+            virDomainEventDeviceRemovalFailedPtr deviceRemovalFailedEvent;
+
+            deviceRemovalFailedEvent = (virDomainEventDeviceRemovalFailedPtr)event;
+            ((virConnectDomainEventDeviceRemovalFailedCallback)cb)(conn, dom,
+                                                                   deviceRemovalFailedEvent->devAlias,
+                                                                   cbopaque);
+            goto cleanup;
+        }
+
     case VIR_DOMAIN_EVENT_ID_LAST:
         break;
     }
index 3eb13c818796754be3f6541f4938e906ff8e4202..54fa87991a484bdad5824ddaa993f7044d42ed4c 100644 (file)
@@ -191,6 +191,13 @@ virObjectEventPtr
 virDomainEventDeviceAddedNewFromDom(virDomainPtr dom,
                                     const char *devAlias);
 virObjectEventPtr
+virDomainEventDeviceRemovalFailedNewFromObj(virDomainObjPtr obj,
+                                            const char *devAlias);
+virObjectEventPtr
+virDomainEventDeviceRemovalFailedNewFromDom(virDomainPtr dom,
+                                            const char *devAlias);
+
+virObjectEventPtr
 virDomainEventTunableNewFromObj(virDomainObjPtr obj,
                                 virTypedParameterPtr params,
                                 int nparams);
index a9719ea169cac5b4566dc54aa9888ed33dd8685d..d9e1f6cb90d10d2137ec3792a23477ea001b1e57 100644 (file)
@@ -492,6 +492,8 @@ virDomainEventControlErrorNewFromDom;
 virDomainEventControlErrorNewFromObj;
 virDomainEventDeviceAddedNewFromDom;
 virDomainEventDeviceAddedNewFromObj;
+virDomainEventDeviceRemovalFailedNewFromDom;
+virDomainEventDeviceRemovalFailedNewFromObj;
 virDomainEventDeviceRemovedNewFromDom;
 virDomainEventDeviceRemovedNewFromObj;
 virDomainEventDiskChangeNewFromDom;
index b03c9ca0a2fc21a8207be46e3856a5d1667cbd36..da9441107b2056bea3082ad561adcf9dc8336fe3 100644 (file)
@@ -322,6 +322,10 @@ static void
 remoteDomainBuildEventCallbackDeviceAdded(virNetClientProgramPtr prog,
                                           virNetClientPtr client,
                                           void *evdata, void *opaque);
+static void
+remoteDomainBuildEventCallbackDeviceRemovalFailed(virNetClientProgramPtr prog,
+                                                  virNetClientPtr client,
+                                                  void *evdata, void *opaque);
 
 static void
 remoteDomainBuildEventBlockJob2(virNetClientProgramPtr prog,
@@ -528,6 +532,10 @@ static virNetClientProgramEvent remoteEvents[] = {
       remoteDomainBuildEventCallbackJobCompleted,
       sizeof(remote_domain_event_callback_job_completed_msg),
       (xdrproc_t)xdr_remote_domain_event_callback_job_completed_msg },
+    { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVAL_FAILED,
+      remoteDomainBuildEventCallbackDeviceRemovalFailed,
+      sizeof(remote_domain_event_callback_device_removal_failed_msg),
+      (xdrproc_t)xdr_remote_domain_event_callback_device_removal_failed_msg },
 };
 
 static void
@@ -4829,6 +4837,28 @@ remoteDomainBuildEventCallbackDeviceAdded(virNetClientProgramPtr prog ATTRIBUTE_
     remoteEventQueue(priv, event, msg->callbackID);
 }
 
+
+static void
+remoteDomainBuildEventCallbackDeviceRemovalFailed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                                                  virNetClientPtr client ATTRIBUTE_UNUSED,
+                                                  void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    remote_domain_event_callback_device_added_msg *msg = evdata;
+    struct private_data *priv = conn->privateData;
+    virDomainPtr dom;
+    virObjectEventPtr event = NULL;
+
+    if (!(dom = get_nonnull_domain(conn, msg->dom)))
+        return;
+
+    event = virDomainEventDeviceRemovalFailedNewFromDom(dom, msg->devAlias);
+
+    virObjectUnref(dom);
+
+    remoteEventQueue(priv, event, msg->callbackID);
+}
+
 static void
 remoteDomainBuildEventCallbackTunable(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
                                       virNetClientPtr client ATTRIBUTE_UNUSED,
index 8bda792ab0be5268bee9b8c62f280e0d4306b23a..bab8ef2304874d39d2e4ba963d3f62c0a685fd5d 100644 (file)
@@ -3261,6 +3261,12 @@ struct remote_domain_migrate_start_post_copy_args {
     unsigned int flags;
 };
 
+struct remote_domain_event_callback_device_removal_failed_msg {
+    int callbackID;
+    remote_nonnull_domain dom;
+    remote_nonnull_string devAlias;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -5781,5 +5787,11 @@ enum remote_procedure {
      * @generate: both
      * @acl: domain:write
      */
-    REMOTE_PROC_DOMAIN_SET_PERF_EVENTS = 366
+    REMOTE_PROC_DOMAIN_SET_PERF_EVENTS = 366,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVAL_FAILED = 367
 };
index 6dddd52ab1160251fcc661f63ccf47db9e785427..fe1b8a8adfda13357617c27044ef03564e87f9e2 100644 (file)
@@ -2730,6 +2730,11 @@ struct remote_domain_migrate_start_post_copy_args {
         remote_nonnull_domain      dom;
         u_int                      flags;
 };
+struct remote_domain_event_callback_device_removal_failed_msg {
+        int                        callbackID;
+        remote_nonnull_domain      dom;
+        remote_nonnull_string      devAlias;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3097,4 +3102,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_MIGRATE_START_POST_COPY = 364,
         REMOTE_PROC_DOMAIN_GET_PERF_EVENTS = 365,
         REMOTE_PROC_DOMAIN_SET_PERF_EVENTS = 366,
+        REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVAL_FAILED = 367,
 };
index 36d0353fdfbd865d28f3ef73704d18c64976a72c..6d4265c506484df06a9d80a4d1a22c11477aefed 100644 (file)
@@ -12301,6 +12301,22 @@ virshEventJobCompletedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
     virshEventPrint(opaque, &buf);
 }
 
+
+static void
+virshEventDeviceRemovalFailedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                   virDomainPtr dom,
+                                   const char *alias,
+                                   void *opaque)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAsprintf(&buf, _("event 'device-removal-failed' for domain %s: %s\n"),
+                      virDomainGetName(dom),
+                      alias);
+    virshEventPrint(opaque, &buf);
+}
+
+
 static vshEventCallback vshEventCallbacks[] = {
     { "lifecycle",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@@ -12344,6 +12360,8 @@ static vshEventCallback vshEventCallbacks[] = {
       VIR_DOMAIN_EVENT_CALLBACK(virshEventMigrationIterationPrint), },
     { "job-completed",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventJobCompletedPrint), },
+    { "device-removal-failed",
+      VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceRemovalFailedPrint), },
 };
 verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));