mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-10 05:17:59 +03:00
Add support for another explicit IO error event
This introduces a new event type VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR event, but also includes a string describing the cause of the event. Thus there is a new callback definition for this event type typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn, virDomainPtr dom, const char *srcPath, const char *devAlias, int action, const char *reason, void *opaque); This is currently wired up to the QEMU block IO error events * daemon/remote.c: Dispatch IO error events to client * examples/domain-events/events-c/event-test.c: Watch for IO error events * include/libvirt/libvirt.h.in: Define new IO error event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle IO error events * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for block IO errors and emit a libvirt IO error event * src/remote/remote_driver.c: Receive and dispatch IO error events to application * src/remote/remote_protocol.x: Wire protocol definition for IO error events * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event from QEMU monitor
This commit is contained in:
parent
c90a1ad7d0
commit
34dcbbb470
@ -256,6 +256,43 @@ static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,
|
static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
virDomainPtr dom,
|
virDomainPtr dom,
|
||||||
int phase,
|
int phase,
|
||||||
@ -327,6 +364,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
|
|||||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog),
|
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog),
|
||||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
|
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
|
||||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
|
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
|
||||||
|
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOErrorReason),
|
||||||
};
|
};
|
||||||
|
|
||||||
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
|
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
|
||||||
|
@ -977,3 +977,8 @@
|
|||||||
.args_filter = (xdrproc_t) xdr_remote_domain_get_block_info_args,
|
.args_filter = (xdrproc_t) xdr_remote_domain_get_block_info_args,
|
||||||
.ret_filter = (xdrproc_t) xdr_remote_domain_get_block_info_ret,
|
.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,
|
||||||
|
},
|
||||||
|
@ -2053,6 +2053,28 @@ typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
|
|||||||
int action,
|
int action,
|
||||||
void *opaque);
|
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:
|
* virDomainEventGraphicsPhase:
|
||||||
*
|
*
|
||||||
@ -2161,6 +2183,7 @@ typedef enum {
|
|||||||
VIR_DOMAIN_EVENT_ID_WATCHDOG = 3, /* virConnectDomainEventWatchdogCallback */
|
VIR_DOMAIN_EVENT_ID_WATCHDOG = 3, /* virConnectDomainEventWatchdogCallback */
|
||||||
VIR_DOMAIN_EVENT_ID_IO_ERROR = 4, /* virConnectDomainEventIOErrorCallback */
|
VIR_DOMAIN_EVENT_ID_IO_ERROR = 4, /* virConnectDomainEventIOErrorCallback */
|
||||||
VIR_DOMAIN_EVENT_ID_GRAPHICS = 5, /* virConnectDomainEventGraphicsCallback */
|
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
|
* NB: this enum value will increase over time as new events are
|
||||||
|
@ -94,7 +94,19 @@
|
|||||||
cb = cbData["cb"]
|
cb = cbData["cb"]
|
||||||
opaque = cbData["opaque"]
|
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
|
return 0
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
@ -3207,6 +3207,58 @@ libvirt_virConnectDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED
|
|||||||
return ret;
|
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
|
static int
|
||||||
libvirt_virConnectDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
libvirt_virConnectDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
virDomainPtr dom,
|
virDomainPtr dom,
|
||||||
@ -3345,6 +3397,9 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
|
|||||||
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
|
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
|
||||||
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorCallback);
|
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorCallback);
|
||||||
break;
|
break;
|
||||||
|
case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
|
||||||
|
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorReasonCallback);
|
||||||
|
break;
|
||||||
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
||||||
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGraphicsCallback);
|
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGraphicsCallback);
|
||||||
break;
|
break;
|
||||||
|
@ -74,6 +74,7 @@ struct _virDomainEvent {
|
|||||||
char *srcPath;
|
char *srcPath;
|
||||||
char *devAlias;
|
char *devAlias;
|
||||||
int action;
|
int action;
|
||||||
|
char *reason;
|
||||||
} ioError;
|
} ioError;
|
||||||
struct {
|
struct {
|
||||||
int phase;
|
int phase;
|
||||||
@ -474,6 +475,7 @@ void virDomainEventFree(virDomainEventPtr event)
|
|||||||
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
|
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
|
||||||
VIR_FREE(event->data.ioError.srcPath);
|
VIR_FREE(event->data.ioError.srcPath);
|
||||||
VIR_FREE(event->data.ioError.devAlias);
|
VIR_FREE(event->data.ioError.devAlias);
|
||||||
|
VIR_FREE(event->data.ioError.reason);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
||||||
@ -630,19 +632,22 @@ virDomainEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj,
|
|||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
|
static virDomainEventPtr virDomainEventIOErrorNewFromDomImpl(int event,
|
||||||
|
virDomainPtr dom,
|
||||||
const char *srcPath,
|
const char *srcPath,
|
||||||
const char *devAlias,
|
const char *devAlias,
|
||||||
int action)
|
int action,
|
||||||
|
const char *reason)
|
||||||
{
|
{
|
||||||
virDomainEventPtr ev =
|
virDomainEventPtr ev =
|
||||||
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR,
|
virDomainEventNewInternal(event,
|
||||||
dom->id, dom->name, dom->uuid);
|
dom->id, dom->name, dom->uuid);
|
||||||
|
|
||||||
if (ev) {
|
if (ev) {
|
||||||
ev->data.ioError.action = action;
|
ev->data.ioError.action = action;
|
||||||
if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
|
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);
|
virDomainEventFree(ev);
|
||||||
ev = NULL;
|
ev = NULL;
|
||||||
}
|
}
|
||||||
@ -650,19 +655,23 @@ virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
|
|||||||
|
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
|
|
||||||
|
static virDomainEventPtr virDomainEventIOErrorNewFromObjImpl(int event,
|
||||||
|
virDomainObjPtr obj,
|
||||||
const char *srcPath,
|
const char *srcPath,
|
||||||
const char *devAlias,
|
const char *devAlias,
|
||||||
int action)
|
int action,
|
||||||
|
const char *reason)
|
||||||
{
|
{
|
||||||
virDomainEventPtr ev =
|
virDomainEventPtr ev =
|
||||||
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR,
|
virDomainEventNewInternal(event,
|
||||||
obj->def->id, obj->def->name, obj->def->uuid);
|
obj->def->id, obj->def->name, obj->def->uuid);
|
||||||
|
|
||||||
if (ev) {
|
if (ev) {
|
||||||
ev->data.ioError.action = action;
|
ev->data.ioError.action = action;
|
||||||
if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
|
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);
|
virDomainEventFree(ev);
|
||||||
ev = NULL;
|
ev = NULL;
|
||||||
}
|
}
|
||||||
@ -671,6 +680,48 @@ virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
|
|||||||
return ev;
|
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,
|
virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
|
||||||
int phase,
|
int phase,
|
||||||
@ -853,6 +904,15 @@ void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
|||||||
cbopaque);
|
cbopaque);
|
||||||
break;
|
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:
|
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
||||||
((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
|
((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
|
||||||
event->data.graphics.phase,
|
event->data.graphics.phase,
|
||||||
|
@ -129,6 +129,16 @@ virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
|
|||||||
const char *srcPath,
|
const char *srcPath,
|
||||||
const char *devAlias,
|
const char *devAlias,
|
||||||
int action);
|
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,
|
virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
|
||||||
int phase,
|
int phase,
|
||||||
|
@ -246,6 +246,8 @@ virDomainEventWatchdogNewFromDom;
|
|||||||
virDomainEventWatchdogNewFromObj;
|
virDomainEventWatchdogNewFromObj;
|
||||||
virDomainEventIOErrorNewFromDom;
|
virDomainEventIOErrorNewFromDom;
|
||||||
virDomainEventIOErrorNewFromObj;
|
virDomainEventIOErrorNewFromObj;
|
||||||
|
virDomainEventIOErrorReasonNewFromDom;
|
||||||
|
virDomainEventIOErrorReasonNewFromObj;
|
||||||
virDomainEventGraphicsNewFromDom;
|
virDomainEventGraphicsNewFromDom;
|
||||||
virDomainEventGraphicsNewFromObj;
|
virDomainEventGraphicsNewFromObj;
|
||||||
virDomainEventFree;
|
virDomainEventFree;
|
||||||
|
@ -1015,10 +1015,12 @@ static int
|
|||||||
qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
const char *diskAlias,
|
const char *diskAlias,
|
||||||
int action)
|
int action,
|
||||||
|
const char *reason)
|
||||||
{
|
{
|
||||||
struct qemud_driver *driver = qemu_driver;
|
struct qemud_driver *driver = qemu_driver;
|
||||||
virDomainEventPtr ioErrorEvent = NULL;
|
virDomainEventPtr ioErrorEvent = NULL;
|
||||||
|
virDomainEventPtr ioErrorEvent2 = NULL;
|
||||||
virDomainEventPtr lifecycleEvent = NULL;
|
virDomainEventPtr lifecycleEvent = NULL;
|
||||||
const char *srcPath;
|
const char *srcPath;
|
||||||
const char *devAlias;
|
const char *devAlias;
|
||||||
@ -1036,6 +1038,7 @@ qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action);
|
ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action);
|
||||||
|
ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, srcPath, devAlias, action, reason);
|
||||||
|
|
||||||
if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE &&
|
if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE &&
|
||||||
vm->state == VIR_DOMAIN_RUNNING) {
|
vm->state == VIR_DOMAIN_RUNNING) {
|
||||||
@ -1051,10 +1054,12 @@ qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
virDomainObjUnlock(vm);
|
virDomainObjUnlock(vm);
|
||||||
|
|
||||||
if (ioErrorEvent || lifecycleEvent) {
|
if (ioErrorEvent || ioErrorEvent2 || lifecycleEvent) {
|
||||||
qemuDriverLock(driver);
|
qemuDriverLock(driver);
|
||||||
if (ioErrorEvent)
|
if (ioErrorEvent)
|
||||||
qemuDomainEventQueue(driver, ioErrorEvent);
|
qemuDomainEventQueue(driver, ioErrorEvent);
|
||||||
|
if (ioErrorEvent2)
|
||||||
|
qemuDomainEventQueue(driver, ioErrorEvent2);
|
||||||
if (lifecycleEvent)
|
if (lifecycleEvent)
|
||||||
qemuDomainEventQueue(driver, lifecycleEvent);
|
qemuDomainEventQueue(driver, lifecycleEvent);
|
||||||
qemuDriverUnlock(driver);
|
qemuDriverUnlock(driver);
|
||||||
|
@ -833,7 +833,8 @@ int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action)
|
|||||||
|
|
||||||
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
|
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
|
||||||
const char *diskAlias,
|
const char *diskAlias,
|
||||||
int action)
|
int action,
|
||||||
|
const char *reason)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
VIR_DEBUG("mon=%p", mon);
|
VIR_DEBUG("mon=%p", mon);
|
||||||
@ -841,7 +842,7 @@ int qemuMonitorEmitIOError(qemuMonitorPtr mon,
|
|||||||
qemuMonitorRef(mon);
|
qemuMonitorRef(mon);
|
||||||
qemuMonitorUnlock(mon);
|
qemuMonitorUnlock(mon);
|
||||||
if (mon->cb && mon->cb->domainIOError)
|
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);
|
qemuMonitorLock(mon);
|
||||||
qemuMonitorUnref(mon);
|
qemuMonitorUnref(mon);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -95,7 +95,8 @@ struct _qemuMonitorCallbacks {
|
|||||||
int (*domainIOError)(qemuMonitorPtr mon,
|
int (*domainIOError)(qemuMonitorPtr mon,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
const char *diskAlias,
|
const char *diskAlias,
|
||||||
int action);
|
int action,
|
||||||
|
const char *reason);
|
||||||
int (*domainGraphics)(qemuMonitorPtr mon,
|
int (*domainGraphics)(qemuMonitorPtr mon,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
int phase,
|
int phase,
|
||||||
@ -148,7 +149,8 @@ int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset);
|
|||||||
int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action);
|
int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action);
|
||||||
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
|
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
|
||||||
const char *diskAlias,
|
const char *diskAlias,
|
||||||
int action);
|
int action,
|
||||||
|
const char *reason);
|
||||||
int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
|
int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
|
||||||
int phase,
|
int phase,
|
||||||
int localFamily,
|
int localFamily,
|
||||||
|
@ -514,6 +514,7 @@ static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr dat
|
|||||||
{
|
{
|
||||||
const char *device;
|
const char *device;
|
||||||
const char *action;
|
const char *action;
|
||||||
|
const char *reason;
|
||||||
int actionID;
|
int actionID;
|
||||||
|
|
||||||
/* Throughout here we try our best to carry on upon errors,
|
/* Throughout here we try our best to carry on upon errors,
|
||||||
@ -529,12 +530,17 @@ static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr dat
|
|||||||
VIR_WARN0("missing device in disk io error event");
|
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) {
|
if ((actionID = qemuMonitorIOErrorActionTypeFromString(action)) < 0) {
|
||||||
VIR_WARN("unknown disk io error action '%s'", action);
|
VIR_WARN("unknown disk io error action '%s'", action);
|
||||||
actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE;
|
actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemuMonitorEmitIOError(mon, device, actionID);
|
qemuMonitorEmitIOError(mon, device, actionID, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7429,6 +7429,37 @@ remoteDomainReadEventIOError(virConnectPtr conn, XDR *xdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
static virDomainEventPtr
|
||||||
remoteDomainReadEventGraphics(virConnectPtr conn, XDR *xdr)
|
remoteDomainReadEventGraphics(virConnectPtr conn, XDR *xdr)
|
||||||
{
|
{
|
||||||
@ -9327,6 +9358,10 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
|
|||||||
event = remoteDomainReadEventIOError(conn, xdr);
|
event = remoteDomainReadEventIOError(conn, xdr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON:
|
||||||
|
event = remoteDomainReadEventIOErrorReason(conn, xdr);
|
||||||
|
break;
|
||||||
|
|
||||||
case REMOTE_PROC_DOMAIN_EVENT_GRAPHICS:
|
case REMOTE_PROC_DOMAIN_EVENT_GRAPHICS:
|
||||||
event = remoteDomainReadEventGraphics(conn, xdr);
|
event = remoteDomainReadEventGraphics(conn, xdr);
|
||||||
break;
|
break;
|
||||||
|
@ -3289,6 +3289,23 @@ xdr_remote_domain_event_io_error_msg (XDR *xdrs, remote_domain_event_io_error_ms
|
|||||||
return TRUE;
|
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
|
bool_t
|
||||||
xdr_remote_domain_event_graphics_address (XDR *xdrs, remote_domain_event_graphics_address *objp)
|
xdr_remote_domain_event_graphics_address (XDR *xdrs, remote_domain_event_graphics_address *objp)
|
||||||
{
|
{
|
||||||
|
@ -1864,6 +1864,15 @@ struct remote_domain_event_io_error_msg {
|
|||||||
};
|
};
|
||||||
typedef struct remote_domain_event_io_error_msg remote_domain_event_io_error_msg;
|
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 {
|
struct remote_domain_event_graphics_address {
|
||||||
int family;
|
int family;
|
||||||
remote_nonnull_string node;
|
remote_nonnull_string node;
|
||||||
@ -2206,6 +2215,7 @@ enum remote_procedure {
|
|||||||
REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
|
REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
|
||||||
REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193,
|
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,
|
||||||
};
|
};
|
||||||
typedef enum remote_procedure remote_procedure;
|
typedef enum remote_procedure remote_procedure;
|
||||||
|
|
||||||
@ -2541,6 +2551,7 @@ extern bool_t xdr_remote_domain_event_reboot_msg (XDR *, remote_domain_event_re
|
|||||||
extern bool_t xdr_remote_domain_event_rtc_change_msg (XDR *, remote_domain_event_rtc_change_msg*);
|
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_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_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_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_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_graphics_msg (XDR *, remote_domain_event_graphics_msg*);
|
||||||
@ -2873,6 +2884,7 @@ extern bool_t xdr_remote_domain_event_reboot_msg ();
|
|||||||
extern bool_t xdr_remote_domain_event_rtc_change_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_watchdog_msg ();
|
||||||
extern bool_t xdr_remote_domain_event_io_error_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_address ();
|
||||||
extern bool_t xdr_remote_domain_event_graphics_identity ();
|
extern bool_t xdr_remote_domain_event_graphics_identity ();
|
||||||
extern bool_t xdr_remote_domain_event_graphics_msg ();
|
extern bool_t xdr_remote_domain_event_graphics_msg ();
|
||||||
|
@ -1659,6 +1659,14 @@ struct remote_domain_event_io_error_msg {
|
|||||||
int action;
|
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 {
|
struct remote_domain_event_graphics_address {
|
||||||
int family;
|
int family;
|
||||||
remote_nonnull_string node;
|
remote_nonnull_string node;
|
||||||
@ -1996,7 +2004,8 @@ enum remote_procedure {
|
|||||||
REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 191,
|
REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 191,
|
||||||
REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
|
REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
|
||||||
REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193,
|
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 ?
|
* Notice how the entries are grouped in sets of 10 ?
|
||||||
|
Loading…
Reference in New Issue
Block a user