Add support for an explicit guest reboot event

The reboot event is not a normal lifecycle event, since the
virtual machine on the host does not change state. Rather the
guest OS is resetting the virtual CPUs. ie, the QEMU process
does not restart. Thus, this does not belong in the current
lifecycle events callback.

This introduces a new event type

    VIR_DOMAIN_EVENT_ID_REBOOT

It takes no parameters, besides the virDomainPtr, so it can
use the generic callback signature.

* daemon/remote.c: Dispatch reboot events to client
* examples/domain-events/events-c/event-test.c: Watch for
  reboot events
* include/libvirt/libvirt.h.in: Define new reboot event ID
* src/conf/domain_event.c, src/conf/domain_event.h,
  src/libvirt_private.syms: Extend API to handle reboot events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
  for reboots and emit a libvirt reboot event
* src/remote/remote_driver.c: Receive and dispatch reboot
  events to application
* src/remote/remote_protocol.x: Wire protocol definition for
  reboot events
This commit is contained in:
Daniel P. Berrange 2010-03-18 15:25:38 +00:00
parent d51638d0ad
commit 8613273458
12 changed files with 151 additions and 3 deletions

View File

@ -129,9 +129,37 @@ static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED,
return 0;
}
static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
void *opaque)
{
struct qemud_client *client = opaque;
remote_domain_event_reboot_msg data;
static virConnectDomainEventGenericCallback domainEventCallbacks[VIR_DOMAIN_EVENT_ID_LAST] = {
if (!client)
return -1;
REMOTE_DEBUG("Relaying domain reboot event %s %d", dom->name, dom->id);
virMutexLock(&client->lock);
/* build return data */
memset(&data, 0, sizeof data);
make_nonnull_domain (&data.dom, dom);
remoteDispatchDomainEventSend (client,
REMOTE_PROC_DOMAIN_EVENT_REBOOT,
(xdrproc_t)xdr_remote_domain_event_reboot_msg, &data);
virMutexUnlock(&client->lock);
return 0;
}
static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
};
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);

View File

@ -847,3 +847,8 @@
.args_filter = (xdrproc_t) xdr_remote_domain_events_deregister_any_args,
.ret_filter = (xdrproc_t) xdr_void,
},
{ /* Async event DomainEventReboot => 169 */
.fn = NULL,
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_void,
},

View File

@ -172,6 +172,16 @@ static int myDomainEventCallback2(virConnectPtr conn ATTRIBUTE_UNUSED,
return 0;
}
static int myDomainEventRebootCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
void *opaque ATTRIBUTE_UNUSED)
{
printf("%s EVENT: Domain %s(%d) rebooted\n", __func__, virDomainGetName(dom),
virDomainGetID(dom));
return 0;
}
static void myFreeFunc(void *opaque)
{
char *str = opaque;
@ -289,6 +299,7 @@ int main(int argc, char **argv)
int sts;
int callback1ret = -1;
int callback2ret = -1;
int callback3ret = -1;
struct sigaction action_stop = {
.sa_handler = stop
@ -326,9 +337,15 @@ int main(int argc, char **argv)
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(myDomainEventCallback2),
strdup("callback 2"), myFreeFunc);
callback3ret = virConnectDomainEventRegisterAny(dconn,
NULL,
VIR_DOMAIN_EVENT_ID_REBOOT,
VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRebootCallback),
strdup("callback reboot"), myFreeFunc);
if ((callback1ret != -1) &&
(callback2ret != -1)) {
(callback2ret != -1) &&
(callback3ret != -1)) {
while(run) {
struct pollfd pfd = { .fd = h_fd,
.events = h_event,
@ -366,6 +383,7 @@ int main(int argc, char **argv)
DEBUG0("Deregistering event handlers");
virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
virConnectDomainEventDeregisterAny(dconn, callback2ret);
virConnectDomainEventDeregisterAny(dconn, callback3ret);
}

View File

@ -1874,6 +1874,7 @@ typedef void (*virConnectDomainEventGenericCallback)(virConnectPtr conn,
typedef enum {
VIR_DOMAIN_EVENT_ID_LIFECYCLE = 0, /* virConnectDomainEventCallback */
VIR_DOMAIN_EVENT_ID_REBOOT = 1, /* virConnectDomainEventGenericCallback */
/*
* NB: this enum value will increase over time as new events are

View File

@ -523,6 +523,17 @@ virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int de
return virDomainEventNew(def->id, def->name, def->uuid, type, detail);
}
virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom)
{
return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT,
dom->id, dom->name, dom->uuid);
}
virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj)
{
return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT,
obj->def->id, obj->def->name, obj->def->uuid);
}
/**
* virDomainEventQueueFree:
* @queue: pointer to the queue
@ -628,6 +639,11 @@ void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
cbopaque);
break;
case VIR_DOMAIN_EVENT_ID_REBOOT:
(cb)(conn, dom,
cbopaque);
break;
default:
VIR_WARN("Unexpected event ID %d", event->eventID);
break;

View File

@ -112,6 +112,9 @@ virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detai
virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail);
virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail);
virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom);
virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj);
int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
virDomainEventPtr event);

View File

@ -214,6 +214,8 @@ virDomainEventNew;
virDomainEventNewFromDom;
virDomainEventNewFromObj;
virDomainEventNewFromDef;
virDomainEventRebootNewFromDom;
virDomainEventRebootNewFromObj;
virDomainEventFree;
virDomainEventDispatchDefaultFunc;
virDomainEventDispatch;

View File

@ -864,9 +864,32 @@ cleanup:
return ret;
}
static int
qemuHandleDomainReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virDomainObjPtr vm)
{
struct qemud_driver *driver = qemu_driver;
virDomainEventPtr event;
virDomainObjLock(vm);
event = virDomainEventRebootNewFromObj(vm);
virDomainObjUnlock(vm);
if (event) {
qemuDriverLock(driver);
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver);
}
return 0;
}
static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuHandleMonitorEOF,
.diskSecretLookup = findVolumeQcowPassphrase,
.domainReset = qemuHandleDomainReset,
};
static int

View File

@ -6913,6 +6913,33 @@ remoteDomainReadEventLifecycle(virConnectPtr conn, XDR *xdr)
}
static virDomainEventPtr
remoteDomainReadEventReboot(virConnectPtr conn, XDR *xdr)
{
remote_domain_event_reboot_msg msg;
virDomainPtr dom;
virDomainEventPtr event = NULL;
memset (&msg, 0, sizeof msg);
/* unmarshall parameters, and process it*/
if (! xdr_remote_domain_event_reboot_msg(xdr, &msg) ) {
error (conn, VIR_ERR_RPC,
_("unable to demarshall reboot event"));
return NULL;
}
dom = get_nonnull_domain(conn,msg.dom);
if (!dom)
return NULL;
event = virDomainEventRebootNewFromDom(dom);
xdr_free ((xdrproc_t) &xdr_remote_domain_event_reboot_msg, (char *) &msg);
virDomainFree(dom);
return event;
}
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
remoteSecretOpen (virConnectPtr conn,
virConnectAuthPtr auth,
@ -8456,6 +8483,10 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
event = remoteDomainReadEventLifecycle(conn, xdr);
break;
case REMOTE_PROC_DOMAIN_EVENT_REBOOT:
event = remoteDomainReadEventReboot(conn, xdr);
break;
default:
DEBUG("Unexpected event proc %d", hdr->proc);
break;

View File

@ -3050,6 +3050,15 @@ xdr_remote_domain_events_deregister_any_args (XDR *xdrs, remote_domain_events_de
return TRUE;
}
bool_t
xdr_remote_domain_event_reboot_msg (XDR *xdrs, remote_domain_event_reboot_msg *objp)
{
if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
return FALSE;
return TRUE;
}
bool_t
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
{

View File

@ -1727,6 +1727,11 @@ struct remote_domain_events_deregister_any_args {
int eventID;
};
typedef struct remote_domain_events_deregister_any_args remote_domain_events_deregister_any_args;
struct remote_domain_event_reboot_msg {
remote_nonnull_domain dom;
};
typedef struct remote_domain_event_reboot_msg remote_domain_event_reboot_msg;
#define REMOTE_PROGRAM 0x20008086
#define REMOTE_PROTOCOL_VERSION 1
@ -1899,6 +1904,7 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME = 166,
REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167,
REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168,
REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169,
};
typedef enum remote_procedure remote_procedure;
@ -2212,6 +2218,7 @@ extern bool_t xdr_remote_domain_abort_job_args (XDR *, remote_domain_abort_job_
extern bool_t xdr_remote_domain_migrate_set_max_downtime_args (XDR *, remote_domain_migrate_set_max_downtime_args*);
extern bool_t xdr_remote_domain_events_register_any_args (XDR *, remote_domain_events_register_any_args*);
extern bool_t xdr_remote_domain_events_deregister_any_args (XDR *, remote_domain_events_deregister_any_args*);
extern bool_t xdr_remote_domain_event_reboot_msg (XDR *, remote_domain_event_reboot_msg*);
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
extern bool_t xdr_remote_message_type (XDR *, remote_message_type*);
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
@ -2499,6 +2506,7 @@ extern bool_t xdr_remote_domain_abort_job_args ();
extern bool_t xdr_remote_domain_migrate_set_max_downtime_args ();
extern bool_t xdr_remote_domain_events_register_any_args ();
extern bool_t xdr_remote_domain_events_deregister_any_args ();
extern bool_t xdr_remote_domain_event_reboot_msg ();
extern bool_t xdr_remote_procedure ();
extern bool_t xdr_remote_message_type ();
extern bool_t xdr_remote_message_status ();

View File

@ -1536,6 +1536,9 @@ struct remote_domain_events_deregister_any_args {
int eventID;
};
struct remote_domain_event_reboot_msg {
remote_nonnull_domain dom;
};
/*----- Protocol. -----*/
@ -1727,7 +1730,8 @@ enum remote_procedure {
REMOTE_PROC_STORAGE_VOL_WIPE = 165,
REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME = 166,
REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167,
REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168
REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168,
REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169
/*
* Notice how the entries are grouped in sets of 10 ?