}
+static int remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int reason,
+ void *opaque)
+{
+ virNetServerClientPtr client = opaque;
+ remote_domain_event_disk_change_msg data;
+ char **oldSrcPath_p = NULL, **newSrcPath_p = NULL;
+
+ if (!client)
+ return -1;
+
+ VIR_DEBUG("Relaying domain %s %d disk change %s %s %s %d",
+ dom->name, dom->id, oldSrcPath, newSrcPath, devAlias, reason);
+
+ /* build return data */
+ memset(&data, 0, sizeof data);
+ if (oldSrcPath &&
+ ((VIR_ALLOC(oldSrcPath_p) < 0) ||
+ !(*oldSrcPath_p = strdup(oldSrcPath))))
+ goto mem_error;
+
+ if (newSrcPath &&
+ ((VIR_ALLOC(newSrcPath_p) < 0) ||
+ !(*newSrcPath_p = strdup(newSrcPath))))
+ goto mem_error;
+
+ data.oldSrcPath = oldSrcPath_p;
+ data.newSrcPath = newSrcPath_p;
+ if (!(data.devAlias = strdup(devAlias)))
+ goto mem_error;
+ data.reason = reason;
+
+ make_nonnull_domain(&data.dom, dom);
+
+ remoteDispatchDomainEventSend(client, remoteProgram,
+ REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE,
+ (xdrproc_t)xdr_remote_domain_event_disk_change_msg, &data);
+
+ return 0;
+
+mem_error:
+ virReportOOMError();
+ return -1;
+}
+
+
static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOErrorReason),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventControlError),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob),
+ VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDiskChange),
};
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
}
+const char *diskChangeReasonStrings[] = {
+ "startupPolicy", /* 0 */
+ /* add new reason here */
+};
+static int myDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int reason,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ printf("%s EVENT: Domain %s(%d) disk change oldSrcPath: %s newSrcPath: %s devAlias: %s reason: %s\n",
+ __func__, virDomainGetName(dom), virDomainGetID(dom),
+ oldSrcPath, newSrcPath, devAlias, diskChangeReasonStrings[reason]);
+ return 0;
+}
+
+
static void myFreeFunc(void *opaque)
{
char *str = opaque;
int callback6ret = -1;
int callback7ret = -1;
int callback8ret = -1;
+ int callback9ret = -1;
struct sigaction action_stop;
memset(&action_stop, 0, sizeof action_stop);
VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
VIR_DOMAIN_EVENT_CALLBACK(myDomainEventControlErrorCallback),
strdup("callback control error"), myFreeFunc);
+ callback9ret = virConnectDomainEventRegisterAny(dconn,
+ NULL,
+ VIR_DOMAIN_EVENT_ID_DISK_CHANGE,
+ VIR_DOMAIN_EVENT_CALLBACK(myDomainEventDiskChangeCallback),
+ strdup("disk change"), myFreeFunc);
if ((callback1ret != -1) &&
(callback2ret != -1) &&
(callback4ret != -1) &&
(callback5ret != -1) &&
(callback6ret != -1) &&
- (callback7ret != -1)) {
+ (callback7ret != -1) &&
+ (callback9ret != -1)) {
while (run) {
if (virEventRunDefaultImpl() < 0) {
virErrorPtr err = virGetLastError();
virConnectDomainEventDeregisterAny(dconn, callback5ret);
virConnectDomainEventDeregisterAny(dconn, callback6ret);
virConnectDomainEventDeregisterAny(dconn, callback7ret);
+ virConnectDomainEventDeregisterAny(dconn, callback9ret);
if (callback8ret != -1)
virConnectDomainEventDeregisterAny(dconn, callback8ret);
}
def myDomainEventGraphicsCallback(conn, dom, phase, localAddr, remoteAddr, authScheme, subject, opaque):
print "myDomainEventGraphicsCallback: Domain %s(%s) %d %s" % (dom.name(), dom.ID(), phase, authScheme)
+def myDomainEventDiskChangeCallback(conn, dom, oldSrcPath, newSrcPath, devAlias, reason, opaque):
+ print "myDomainEventDiskChangeCallback: Domain %s(%s) disk change oldSrcPath: %s newSrcPath: %s devAlias: %s reason: %s" % (
+ dom.name(), dom.ID(), oldSrcPath, newSrcPath, devAlias, reason)
def usage(out=sys.stderr):
print >>out, "usage: "+os.path.basename(sys.argv[0])+" [-hdl] [uri]"
print >>out, " uri will default to qemu:///system"
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR, myDomainEventIOErrorCallback, None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, myDomainEventWatchdogCallback, None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, myDomainEventGraphicsCallback, None)
+ vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_DISK_CHANGE, myDomainEventDiskChangeCallback, None)
# The rest of your app would go here normally, but for sake
# of demo we'll just go to sleep. The other option is to
int status,
void *opaque);
+/**
+ * virConnectDomainEventDisChangeReason:
+ *
+ * The reason describing why this callback is called
+ */
+typedef enum {
+ VIR_DOMAIN_DISK_CHANGE_MISSING_ON_START = 0, /* oldSrcPath is set */
+} virConnectDomainEventDiskChangeReason;
+
+/**
+ * virConnectDomainEventDiskChangeCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @oldSrcPath: old source path
+ * @newSrcPath: new source path
+ * @reason: reason why this callback was called; any of
+ * virConnectDomainEventDiskChangeReason
+ * @opaque: application specified data
+ *
+ * This callback occurs when disk gets changed. However,
+ * not all @reason will cause both @oldSrcPath and @newSrcPath
+ * to be non-NULL. Please see virConnectDomainEventDiskChangeReason
+ * for more details.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_IO_ERROR with virConnectDomainEventRegisterAny()
+ */
+typedef void (*virConnectDomainEventDiskChangeCallback)(virConnectPtr conn,
+ virDomainPtr dom,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int reason,
+ void *opaque);
+
/**
* VIR_DOMAIN_EVENT_CALLBACK:
*
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON = 6, /* virConnectDomainEventIOErrorReasonCallback */
VIR_DOMAIN_EVENT_ID_CONTROL_ERROR = 7, /* virConnectDomainEventGenericCallback */
VIR_DOMAIN_EVENT_ID_BLOCK_JOB = 8, /* virConnectDomainEventBlockJobCallback */
+ VIR_DOMAIN_EVENT_ID_DISK_CHANGE = 9, /* virConnectDomainEventDiskChangeCallback */
/*
* NB: this enum value will increase over time as new events are
except AttributeError:
pass
+ def _dispatchDomainEventDiskChangeCallback(self, dom, oldSrcPath, newSrcPath, devAlias, reason, cbData):
+ """Dispatches event to python user domain diskChange event callbacks
+ """
+ cb = cbData["cb"]
+ opaque = cbData["opaque"]
+
+ cb(self, virDomain(self, _obj=dom), oldSrcPath, newSrcPath, devAlias, reason, opaque)
+ return 0;
+
def domainEventDeregisterAny(self, callbackID):
"""Removes a Domain Event Callback. De-registering for a
domain callback will disable delivery of this event type """
return ret;
}
+static int
+libvirt_virConnectDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int 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*)"_dispatchDomainEventDiskChangeCallback",
+ (char*)"OsssiO",
+ pyobj_dom,
+ oldSrcPath, newSrcPath,
+ devAlias, reason, pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if(!pyobj_ret) {
+ DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ ret = 0;
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+ return ret;
+}
+
static PyObject *
libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
PyObject * args)
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventBlockJobCallback);
break;
+ case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
+ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDiskChangeCallback);
+ break;
}
if (!cb) {
int type;
int status;
} blockJob;
+ struct {
+ char *oldSrcPath;
+ char *newSrcPath;
+ char *devAlias;
+ int reason;
+ } diskChange;
} data;
};
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
VIR_FREE(event->data.blockJob.path);
break;
+
+ case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
+ VIR_FREE(event->data.diskChange.oldSrcPath);
+ VIR_FREE(event->data.diskChange.newSrcPath);
+ VIR_FREE(event->data.diskChange.devAlias);
+ break;
}
VIR_FREE(event->dom.name);
return ev;
}
+static virDomainEventPtr
+virDomainEventDiskChangeNew(int id, const char *name,
+ unsigned char *uuid,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias, int reason)
+{
+ virDomainEventPtr ev =
+ virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_DISK_CHANGE,
+ id, name, uuid);
+
+ if (ev) {
+ if (!(ev->data.diskChange.devAlias = strdup(devAlias)))
+ goto error;
+
+ if (oldSrcPath &&
+ !(ev->data.diskChange.oldSrcPath = strdup(oldSrcPath)))
+ goto error;
+
+ if (newSrcPath &&
+ !(ev->data.diskChange.newSrcPath = strdup(newSrcPath)))
+ goto error;
+
+ ev->data.diskChange.reason = reason;
+ }
+
+ return ev;
+
+error:
+ virReportOOMError();
+ virDomainEventFree(ev);
+ return NULL;
+}
+
+virDomainEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int reason)
+{
+ return virDomainEventDiskChangeNew(obj->def->id, obj->def->name,
+ obj->def->uuid, oldSrcPath,
+ newSrcPath, devAlias, reason);
+}
+
+virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int reason)
+{
+ return virDomainEventDiskChangeNew(dom->id, dom->name, dom->uuid,
+ oldSrcPath, newSrcPath,
+ devAlias, reason);
+}
/**
* virDomainEventQueuePop:
cbopaque);
break;
+ case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
+ ((virConnectDomainEventDiskChangeCallback)cb)(conn, dom,
+ event->data.diskChange.oldSrcPath,
+ event->data.diskChange.newSrcPath,
+ event->data.diskChange.devAlias,
+ event->data.diskChange.reason,
+ cbopaque);
+ break;
+
default:
VIR_WARN("Unexpected event ID %d", event->eventID);
break;
int type,
int status);
+virDomainEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int reason);
+virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom,
+ const char *oldSrcPath,
+ const char *newSrcPath,
+ const char *devAlias,
+ int reason);
+
int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
virDomainEventPtr event);
virDomainEventCallbackListRemoveID;
virDomainEventControlErrorNewFromDom;
virDomainEventControlErrorNewFromObj;
+virDomainEventDiskChangeNewFromDom;
+virDomainEventDiskChangeNewFromObj;
virDomainEventDispatch;
virDomainEventDispatchDefaultFunc;
virDomainEventFree;
#include "ignore-value.h"
#include "uuid.h"
#include "virfile.h"
+#include "domain_event.h"
#include <sys/time.h>
#include <fcntl.h>
int accessRet;
virDomainDiskDefPtr disk;
char uuid[VIR_UUID_STRING_BUFLEN] ATTRIBUTE_UNUSED;
+ virDomainEventPtr event = NULL;
virUUIDFormat(vm->def->uuid, uuid);
"due to not accessible source '%s'",
disk->dst, vm->def->name, uuid, disk->src);
+ event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL, disk->info.alias,
+ VIR_DOMAIN_DISK_CHANGE_MISSING_ON_START);
+ if (event)
+ qemuDomainEventQueue(driver, event);
+
VIR_FREE(disk->src);
}
NULL) < 0)
goto cleanup;
- if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
- goto cleanup;
-
- VIR_DEBUG("Checking for CDROM and floppy presence");
- if (qemuDomainCheckDiskPresence(driver, vm, migrateFrom != NULL) < 0)
- goto cleanup;
-
/* If you are using a SecurityDriver with dynamic labelling,
then generate a security label for isolation */
VIR_DEBUG("Generating domain security label (if required)");
&priv->qemuCaps) < 0)
goto cleanup;
+ if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
+ goto cleanup;
+
+ VIR_DEBUG("Checking for CDROM and floppy presence");
+ if (qemuDomainCheckDiskPresence(driver, vm, migrateFrom != NULL) < 0)
+ goto cleanup;
+
VIR_DEBUG("Setting up domain cgroup (if required)");
if (qemuSetupCgroup(driver, vm) < 0)
goto cleanup;
virNetClientPtr client,
void *evdata, void *opaque);
+static void
+remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog,
+ virNetClientPtr client,
+ void *evdata, void *opaque);
+
static virNetClientProgramEvent remoteDomainEvents[] = {
{ REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
remoteDomainBuildEventRTCChange,
remoteDomainBuildEventBlockJob,
sizeof(remote_domain_event_block_job_msg),
(xdrproc_t)xdr_remote_domain_event_block_job_msg },
+ { REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE,
+ remoteDomainBuildEventDiskChange,
+ sizeof(remote_domain_event_disk_change_msg),
+ (xdrproc_t)xdr_remote_domain_event_disk_change_msg },
};
enum virDrvOpenRemoteFlags {
}
+static void
+remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque)
+{
+ virConnectPtr conn = opaque;
+ struct private_data *priv = conn->privateData;
+ remote_domain_event_disk_change_msg *msg = evdata;
+ virDomainPtr dom;
+ virDomainEventPtr event = NULL;
+
+ dom = get_nonnull_domain(conn, msg->dom);
+ if (!dom)
+ return;
+
+ event = virDomainEventDiskChangeNewFromDom(dom,
+ msg->oldSrcPath ? *msg->oldSrcPath : NULL,
+ msg->newSrcPath ? *msg->newSrcPath : NULL,
+ msg->devAlias,
+ msg->reason);
+
+ virDomainFree(dom);
+
+ remoteDomainEventQueue(priv, event);
+}
+
+
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
unsigned int flags)
int status;
};
+struct remote_domain_event_disk_change_msg {
+ remote_nonnull_domain dom;
+ remote_string oldSrcPath;
+ remote_string newSrcPath;
+ remote_nonnull_string devAlias;
+ int reason;
+};
+
struct remote_domain_managed_save_args {
remote_nonnull_domain dom;
unsigned int flags;
REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_RESET = 245, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_NUM_CHILDREN = 246, /* autogen autogen priority:high */
- REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_CHILDREN_NAMES = 247 /* autogen autogen priority:high */
+ REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_CHILDREN_NAMES = 247, /* autogen autogen priority:high */
+ REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE = 248 /* skipgen skipgen */
/*
* Notice how the entries are grouped in sets of 10 ?
int type;
int status;
};
+struct remote_domain_event_disk_change_msg {
+ remote_nonnull_domain dom;
+ remote_string oldSrcPath;
+ remote_string newSrcPath;
+ remote_nonnull_string devAlias;
+ int reason;
+};
struct remote_domain_managed_save_args {
remote_nonnull_domain dom;
u_int flags;