}
+static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason,
+ void *opaque)
+{
+ struct qemud_client *client = opaque;
+ remote_domain_event_io_error_reason_msg data;
+
+ if (!client)
+ return -1;
+
+ REMOTE_DEBUG("Relaying domain io error %s %d %s %s %d %s",
+ dom->name, dom->id, srcPath, devAlias, action, reason);
+
+ virMutexLock(&client->lock);
+
+ /* build return data */
+ memset(&data, 0, sizeof data);
+ make_nonnull_domain (&data.dom, dom);
+ data.srcPath = (char*)srcPath;
+ data.devAlias = (char*)devAlias;
+ data.action = action;
+ data.reason = (char*)reason;
+
+ remoteDispatchDomainEventSend (client,
+ REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON,
+ (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data);
+
+ virMutexUnlock(&client->lock);
+
+ return 0;
+}
+
+
static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
int phase,
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
+ VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOErrorReason),
};
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
.args_filter = (xdrproc_t) xdr_remote_domain_get_block_info_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_get_block_info_ret,
},
+{ /* Async event DomainEventIoErrorReason => 195 */
+ .fn = NULL,
+ .args_filter = (xdrproc_t) xdr_void,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
int action,
void *opaque);
+/**
+ * virConnectDomainEventWatchdogCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @srcPath: The host file on which the IO error occurred
+ * @devAlias: The guest device alias associated with the path
+ * @action: action that is to be taken due to the IO error
+ * @reason: the cause of the IO error
+ * @opaque: application specified data
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_IO_ERROR with virConnectDomainEventRegisterAny()
+ *
+ */
+typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
+ virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason,
+ void *opaque);
+
/**
* virDomainEventGraphicsPhase:
*
VIR_DOMAIN_EVENT_ID_WATCHDOG = 3, /* virConnectDomainEventWatchdogCallback */
VIR_DOMAIN_EVENT_ID_IO_ERROR = 4, /* virConnectDomainEventIOErrorCallback */
VIR_DOMAIN_EVENT_ID_GRAPHICS = 5, /* virConnectDomainEventGraphicsCallback */
+ VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON = 6, /* virConnectDomainEventIOErrorReasonCallback */
/*
* NB: this enum value will increase over time as new events are
cb = cbData["cb"]
opaque = cbData["opaque"]
- cb(self, virDomain(self, _obj=dom), opaque)
+ cb(self, virDomain(self, _obj=dom), srcPath, devAlias, opaque)
+ return 0
+ except AttributeError:
+ pass
+
+ def dispatchDomainEventIOErrorReasonCallback(self, dom, srcPath, devAlias, action, reason, cbData):
+ """Dispatches events to python user domain IO error event callbacks
+ """
+ try:
+ cb = cbData["cb"]
+ opaque = cbData["opaque"]
+
+ cb(self, virDomain(self, _obj=dom), srcPath, devAlias, action, reason, opaque)
return 0
except AttributeError:
pass
return ret;
}
+static int
+libvirt_virConnectDomainEventIOErrorReasonCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ int ret = -1;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ Py_INCREF(pyobj_cbData);
+
+ dictKey = libvirt_constcharPtrWrap("conn");
+ pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
+ Py_DECREF(dictKey);
+
+ /* Call the Callback Dispatcher */
+ pyobj_ret = PyObject_CallMethod(pyobj_conn,
+ (char*)"dispatchDomainEventIOErrorCallback",
+ (char*)"OssisO",
+ pyobj_dom,
+ srcPath, devAlias, action, reason,
+ pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+#if DEBUG_ERROR
+ printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
static int
libvirt_virConnectDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorCallback);
break;
+ case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorReasonCallback);
+ break;
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGraphicsCallback);
break;
char *srcPath;
char *devAlias;
int action;
+ char *reason;
} ioError;
struct {
int phase;
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
VIR_FREE(event->data.ioError.srcPath);
VIR_FREE(event->data.ioError.devAlias);
+ VIR_FREE(event->data.ioError.reason);
break;
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
return ev;
}
-virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
- const char *srcPath,
- const char *devAlias,
- int action)
+static virDomainEventPtr virDomainEventIOErrorNewFromDomImpl(int event,
+ virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason)
{
virDomainEventPtr ev =
- virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+ virDomainEventNewInternal(event,
dom->id, dom->name, dom->uuid);
if (ev) {
ev->data.ioError.action = action;
if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
- !(ev->data.ioError.devAlias = strdup(devAlias))) {
+ !(ev->data.ioError.devAlias = strdup(devAlias)) ||
+ (reason && !(ev->data.ioError.reason = strdup(reason)))) {
virDomainEventFree(ev);
ev = NULL;
}
return ev;
}
-virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
- const char *srcPath,
- const char *devAlias,
- int action)
+
+static virDomainEventPtr virDomainEventIOErrorNewFromObjImpl(int event,
+ virDomainObjPtr obj,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason)
{
virDomainEventPtr ev =
- virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+ virDomainEventNewInternal(event,
obj->def->id, obj->def->name, obj->def->uuid);
if (ev) {
ev->data.ioError.action = action;
if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
- !(ev->data.ioError.devAlias = strdup(devAlias))) {
+ !(ev->data.ioError.devAlias = strdup(devAlias)) ||
+ !(ev->data.ioError.reason = strdup(reason))) {
virDomainEventFree(ev);
ev = NULL;
}
return ev;
}
+virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action)
+{
+ return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+ dom, srcPath, devAlias,
+ action, NULL);
+}
+
+virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
+ const char *srcPath,
+ const char *devAlias,
+ int action)
+{
+ return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+ obj, srcPath, devAlias,
+ action, NULL);
+}
+
+virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason)
+{
+ return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
+ dom, srcPath, devAlias,
+ action, reason);
+}
+
+virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason)
+{
+ return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
+ obj, srcPath, devAlias,
+ action, reason);
+}
+
virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
int phase,
cbopaque);
break;
+ case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
+ ((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom,
+ event->data.ioError.srcPath,
+ event->data.ioError.devAlias,
+ event->data.ioError.action,
+ event->data.ioError.reason,
+ cbopaque);
+ break;
+
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
event->data.graphics.phase,
const char *srcPath,
const char *devAlias,
int action);
+virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason);
+virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason);
virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
int phase,
virDomainEventWatchdogNewFromObj;
virDomainEventIOErrorNewFromDom;
virDomainEventIOErrorNewFromObj;
+virDomainEventIOErrorReasonNewFromDom;
+virDomainEventIOErrorReasonNewFromObj;
virDomainEventGraphicsNewFromDom;
virDomainEventGraphicsNewFromObj;
virDomainEventFree;
qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virDomainObjPtr vm,
const char *diskAlias,
- int action)
+ int action,
+ const char *reason)
{
struct qemud_driver *driver = qemu_driver;
virDomainEventPtr ioErrorEvent = NULL;
+ virDomainEventPtr ioErrorEvent2 = NULL;
virDomainEventPtr lifecycleEvent = NULL;
const char *srcPath;
const char *devAlias;
}
ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action);
+ ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, srcPath, devAlias, action, reason);
if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE &&
vm->state == VIR_DOMAIN_RUNNING) {
}
virDomainObjUnlock(vm);
- if (ioErrorEvent || lifecycleEvent) {
+ if (ioErrorEvent || ioErrorEvent2 || lifecycleEvent) {
qemuDriverLock(driver);
if (ioErrorEvent)
qemuDomainEventQueue(driver, ioErrorEvent);
+ if (ioErrorEvent2)
+ qemuDomainEventQueue(driver, ioErrorEvent2);
if (lifecycleEvent)
qemuDomainEventQueue(driver, lifecycleEvent);
qemuDriverUnlock(driver);
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
const char *diskAlias,
- int action)
+ int action,
+ const char *reason)
{
int ret = -1;
VIR_DEBUG("mon=%p", mon);
qemuMonitorRef(mon);
qemuMonitorUnlock(mon);
if (mon->cb && mon->cb->domainIOError)
- ret = mon->cb->domainIOError(mon, mon->vm, diskAlias, action);
+ ret = mon->cb->domainIOError(mon, mon->vm, diskAlias, action, reason);
qemuMonitorLock(mon);
qemuMonitorUnref(mon);
return ret;
int (*domainIOError)(qemuMonitorPtr mon,
virDomainObjPtr vm,
const char *diskAlias,
- int action);
+ int action,
+ const char *reason);
int (*domainGraphics)(qemuMonitorPtr mon,
virDomainObjPtr vm,
int phase,
int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action);
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
const char *diskAlias,
- int action);
+ int action,
+ const char *reason);
int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
int phase,
int localFamily,
{
const char *device;
const char *action;
+ const char *reason;
int actionID;
/* Throughout here we try our best to carry on upon errors,
VIR_WARN0("missing device in disk io error event");
}
+ if ((reason = virJSONValueObjectGetString(data, "reason")) == NULL) {
+ VIR_WARN0("missing reason in disk io error event");
+ reason = "";
+ }
+
if ((actionID = qemuMonitorIOErrorActionTypeFromString(action)) < 0) {
VIR_WARN("unknown disk io error action '%s'", action);
actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE;
}
- qemuMonitorEmitIOError(mon, device, actionID);
+ qemuMonitorEmitIOError(mon, device, actionID, reason);
}
}
+static virDomainEventPtr
+remoteDomainReadEventIOErrorReason(virConnectPtr conn, XDR *xdr)
+{
+ remote_domain_event_io_error_reason_msg msg;
+ virDomainPtr dom;
+ virDomainEventPtr event = NULL;
+ memset (&msg, 0, sizeof msg);
+
+ /* unmarshall parameters, and process it*/
+ if (! xdr_remote_domain_event_io_error_reason_msg(xdr, &msg) ) {
+ remoteError(VIR_ERR_RPC, "%s",
+ _("unable to demarshall reboot event"));
+ return NULL;
+ }
+
+ dom = get_nonnull_domain(conn,msg.dom);
+ if (!dom)
+ return NULL;
+
+ event = virDomainEventIOErrorReasonNewFromDom(dom,
+ msg.srcPath,
+ msg.devAlias,
+ msg.action,
+ msg.reason);
+ xdr_free ((xdrproc_t) &xdr_remote_domain_event_io_error_reason_msg, (char *) &msg);
+
+ virDomainFree(dom);
+ return event;
+}
+
+
static virDomainEventPtr
remoteDomainReadEventGraphics(virConnectPtr conn, XDR *xdr)
{
event = remoteDomainReadEventIOError(conn, xdr);
break;
+ case REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON:
+ event = remoteDomainReadEventIOErrorReason(conn, xdr);
+ break;
+
case REMOTE_PROC_DOMAIN_EVENT_GRAPHICS:
event = remoteDomainReadEventGraphics(conn, xdr);
break;
return TRUE;
}
+bool_t
+xdr_remote_domain_event_io_error_reason_msg (XDR *xdrs, remote_domain_event_io_error_reason_msg *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->srcPath))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->devAlias))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->action))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->reason))
+ return FALSE;
+ return TRUE;
+}
+
bool_t
xdr_remote_domain_event_graphics_address (XDR *xdrs, remote_domain_event_graphics_address *objp)
{
};
typedef struct remote_domain_event_io_error_msg remote_domain_event_io_error_msg;
+struct remote_domain_event_io_error_reason_msg {
+ remote_nonnull_domain dom;
+ remote_nonnull_string srcPath;
+ remote_nonnull_string devAlias;
+ int action;
+ remote_nonnull_string reason;
+};
+typedef struct remote_domain_event_io_error_reason_msg remote_domain_event_io_error_reason_msg;
+
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193,
REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194,
+ REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195,
};
typedef enum remote_procedure remote_procedure;
extern bool_t xdr_remote_domain_event_rtc_change_msg (XDR *, remote_domain_event_rtc_change_msg*);
extern bool_t xdr_remote_domain_event_watchdog_msg (XDR *, remote_domain_event_watchdog_msg*);
extern bool_t xdr_remote_domain_event_io_error_msg (XDR *, remote_domain_event_io_error_msg*);
+extern bool_t xdr_remote_domain_event_io_error_reason_msg (XDR *, remote_domain_event_io_error_reason_msg*);
extern bool_t xdr_remote_domain_event_graphics_address (XDR *, remote_domain_event_graphics_address*);
extern bool_t xdr_remote_domain_event_graphics_identity (XDR *, remote_domain_event_graphics_identity*);
extern bool_t xdr_remote_domain_event_graphics_msg (XDR *, remote_domain_event_graphics_msg*);
extern bool_t xdr_remote_domain_event_rtc_change_msg ();
extern bool_t xdr_remote_domain_event_watchdog_msg ();
extern bool_t xdr_remote_domain_event_io_error_msg ();
+extern bool_t xdr_remote_domain_event_io_error_reason_msg ();
extern bool_t xdr_remote_domain_event_graphics_address ();
extern bool_t xdr_remote_domain_event_graphics_identity ();
extern bool_t xdr_remote_domain_event_graphics_msg ();
int action;
};
+struct remote_domain_event_io_error_reason_msg {
+ remote_nonnull_domain dom;
+ remote_nonnull_string srcPath;
+ remote_nonnull_string devAlias;
+ int action;
+ remote_nonnull_string reason;
+};
+
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 191,
REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193,
- REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194
+ REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194,
+ REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195
/*
* Notice how the entries are grouped in sets of 10 ?