+
+/* PersistentNotification is false by default */
+static _Bool persistent_notification = 0;
+
+/* libvirt event loop */
+static pthread_t event_loop_tid;
+
+static int domain_event_cb_id;
+
+const char *domain_states[] = {
+ [VIR_DOMAIN_NOSTATE] = "no state",
+ [VIR_DOMAIN_RUNNING] = "the domain is running",
+ [VIR_DOMAIN_BLOCKED] = "the domain is blocked on resource",
+ [VIR_DOMAIN_PAUSED] = "the domain is paused by user",
+ [VIR_DOMAIN_SHUTDOWN] = "the domain is being shut down",
+ [VIR_DOMAIN_SHUTOFF] = "the domain is shut off",
+ [VIR_DOMAIN_CRASHED] = "the domain is crashed",
+#ifdef HAVE_DOM_STATE_PMSUSPENDED
+ [VIR_DOMAIN_PMSUSPENDED] =
+ "the domain is suspended by guest power management",
+#endif
+};
+
+static int map_domain_event_to_state(int event) {
+ int ret;
+ switch (event) {
+ case VIR_DOMAIN_EVENT_STARTED:
+ ret = VIR_DOMAIN_RUNNING;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED:
+ ret = VIR_DOMAIN_PAUSED;
+ break;
+ case VIR_DOMAIN_EVENT_RESUMED:
+ ret = VIR_DOMAIN_RUNNING;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED:
+ ret = VIR_DOMAIN_SHUTOFF;
+ break;
+ case VIR_DOMAIN_EVENT_SHUTDOWN:
+ ret = VIR_DOMAIN_SHUTDOWN;
+ break;
+ case VIR_DOMAIN_EVENT_PMSUSPENDED:
+ ret = VIR_DOMAIN_PMSUSPENDED;
+ break;
+ case VIR_DOMAIN_EVENT_CRASHED:
+ ret = VIR_DOMAIN_CRASHED;
+ break;
+ default:
+ ret = VIR_DOMAIN_NOSTATE;
+ }
+ return ret;
+}
+
+static int map_domain_event_detail_to_reason(int event, int detail) {
+ int ret;
+ switch (event) {
+ case VIR_DOMAIN_EVENT_STARTED:
+ switch (detail) {
+ case VIR_DOMAIN_EVENT_STARTED_BOOTED: /* Normal startup from boot */
+ ret = VIR_DOMAIN_RUNNING_BOOTED;
+ break;
+ case VIR_DOMAIN_EVENT_STARTED_MIGRATED: /* Incoming migration from another host */
+ ret = VIR_DOMAIN_RUNNING_MIGRATED;
+ break;
+ case VIR_DOMAIN_EVENT_STARTED_RESTORED: /* Restored from a state file */
+ ret = VIR_DOMAIN_RUNNING_RESTORED;
+ break;
+ case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT: /* Restored from snapshot */
+ ret = VIR_DOMAIN_RUNNING_FROM_SNAPSHOT;
+ break;
+ case VIR_DOMAIN_EVENT_STARTED_WAKEUP: /* Started due to wakeup event */
+ ret = VIR_DOMAIN_RUNNING_WAKEUP;
+ break;
+ default:
+ ret = VIR_DOMAIN_RUNNING_UNKNOWN;
+ }
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED:
+ switch (detail) {
+ case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED: /* Normal suspend due to admin pause */
+ ret = VIR_DOMAIN_PAUSED_USER;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED: /* Suspended for offline migration */
+ ret = VIR_DOMAIN_PAUSED_MIGRATION;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR: /* Suspended due to a disk I/O error */
+ ret = VIR_DOMAIN_PAUSED_IOERROR;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG: /* Suspended due to a watchdog firing */
+ ret = VIR_DOMAIN_PAUSED_WATCHDOG;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED: /* Restored from paused state file */
+ ret = VIR_DOMAIN_PAUSED_UNKNOWN;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT: /* Restored from paused snapshot */
+ ret = VIR_DOMAIN_PAUSED_FROM_SNAPSHOT;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR: /* Suspended after failure during libvirt API call */
+ ret = VIR_DOMAIN_PAUSED_UNKNOWN;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY: /* Suspended for post-copy migration */
+ ret = VIR_DOMAIN_PAUSED_POSTCOPY;
+ break;
+ case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY_FAILED: /* Suspended after failed post-copy */
+ ret = VIR_DOMAIN_PAUSED_POSTCOPY_FAILED;
+ break;
+ default:
+ ret = VIR_DOMAIN_PAUSED_UNKNOWN;
+ }
+ break;
+ case VIR_DOMAIN_EVENT_RESUMED:
+ switch (detail) {
+ case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED: /* Normal resume due to admin unpause */
+ ret = VIR_DOMAIN_RUNNING_UNPAUSED;
+ break;
+ case VIR_DOMAIN_EVENT_RESUMED_MIGRATED: /* Resumed for completion of migration */
+ ret = VIR_DOMAIN_RUNNING_MIGRATED;
+ break;
+ case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT: /* Resumed from snapshot */
+ ret = VIR_DOMAIN_RUNNING_FROM_SNAPSHOT;
+ break;
+ case VIR_DOMAIN_EVENT_RESUMED_POSTCOPY: /* Resumed, but migration is still running in post-copy mode */
+ ret = VIR_DOMAIN_RUNNING_POSTCOPY;
+ break;
+ default:
+ ret = VIR_DOMAIN_RUNNING_UNKNOWN;
+ }
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED:
+ switch (detail) {
+ case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN: /* Normal shutdown */
+ ret = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED_DESTROYED: /* Forced poweroff from host */
+ ret = VIR_DOMAIN_SHUTOFF_DESTROYED;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED_CRASHED: /* Guest crashed */
+ ret = VIR_DOMAIN_SHUTOFF_CRASHED;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED_MIGRATED: /* Migrated off to another host */
+ ret = VIR_DOMAIN_SHUTOFF_MIGRATED;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED_SAVED: /* Saved to a state file */
+ ret = VIR_DOMAIN_SHUTOFF_SAVED;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED_FAILED: /* Host emulator/mgmt failed */
+ ret = VIR_DOMAIN_SHUTOFF_FAILED;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT: /* Offline snapshot loaded */
+ ret = VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT;
+ break;
+ default:
+ ret = VIR_DOMAIN_SHUTOFF_UNKNOWN;
+ }
+ break;
+ case VIR_DOMAIN_EVENT_SHUTDOWN:
+ switch (detail) {
+ case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED: /* Guest finished shutdown sequence */
+ ret = VIR_DOMAIN_SHUTDOWN_USER;
+ break;
+ default:
+ ret = VIR_DOMAIN_SHUTDOWN_UNKNOWN;
+ }
+ break;
+ case VIR_DOMAIN_EVENT_PMSUSPENDED:
+ switch (detail) {
+ case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY: /* Guest was PM suspended to memory */
+ ret = VIR_DOMAIN_PMSUSPENDED_UNKNOWN;
+ break;
+ case VIR_DOMAIN_EVENT_PMSUSPENDED_DISK: /* Guest was PM suspended to disk */
+ ret = VIR_DOMAIN_PMSUSPENDED_DISK_UNKNOWN;
+ break;
+ default:
+ ret = VIR_DOMAIN_PMSUSPENDED_UNKNOWN;
+ }
+ break;
+ case VIR_DOMAIN_EVENT_CRASHED:
+ switch (detail) {
+ case VIR_DOMAIN_EVENT_CRASHED_PANICKED: /* Guest was panicked */
+ ret = VIR_DOMAIN_CRASHED_PANICKED;
+ break;
+ default:
+ ret = VIR_DOMAIN_CRASHED_UNKNOWN;
+ }
+ break;
+ default:
+ ret = VIR_DOMAIN_NOSTATE_UNKNOWN;
+ }
+ return ret;
+}
+
+#ifdef HAVE_DOM_REASON
+#define DOMAIN_STATE_REASON_MAX_SIZE 20
+const char *domain_reasons[][DOMAIN_STATE_REASON_MAX_SIZE] = {
+ [VIR_DOMAIN_NOSTATE][VIR_DOMAIN_NOSTATE_UNKNOWN] =
+ "the reason is unknown",
+
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_UNKNOWN] =
+ "the reason is unknown",
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_BOOTED] =
+ "normal startup from boot",
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_MIGRATED] =
+ "migrated from another host",
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_RESTORED] =
+ "restored from a state file",
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_FROM_SNAPSHOT] =
+ "restored from snapshot",
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_UNPAUSED] =
+ "returned from paused state",
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_MIGRATION_CANCELED] =
+ "returned from migration",
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_SAVE_CANCELED] =
+ "returned from failed save process",
+#ifdef HAVE_DOM_REASON_RUNNING_WAKEUP
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_WAKEUP] =
+ "returned from pmsuspended due to wakeup event",
+#endif
+#ifdef HAVE_DOM_REASON_CRASHED
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_CRASHED] =
+ "resumed from crashed",
+#endif
+#ifdef HAVE_DOM_REASON_POSTCOPY
+ [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_POSTCOPY] =
+ "running in post-copy migration mode",
+#endif
+
+ [VIR_DOMAIN_BLOCKED][VIR_DOMAIN_BLOCKED_UNKNOWN] =
+ "the reason is unknown",
+
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_UNKNOWN] =
+ "the reason is unknown",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_USER] = "paused on user request",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_MIGRATION] =
+ "paused for offline migration",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SAVE] = "paused for save",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_DUMP] =
+ "paused for offline core dump",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_IOERROR] =
+ "paused due to a disk I/O error",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_WATCHDOG] =
+ "paused due to a watchdog event",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_FROM_SNAPSHOT] =
+ "paused after restoring from snapshot",
+#ifdef HAVE_DOM_REASON_PAUSED_SHUTTING_DOWN
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SHUTTING_DOWN] =
+ "paused during shutdown process",
+#endif
+#ifdef HAVE_DOM_REASON_PAUSED_SNAPSHOT
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SNAPSHOT] =
+ "paused while creating a snapshot",
+#endif
+#ifdef HAVE_DOM_REASON_PAUSED_CRASHED
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_CRASHED] =
+ "paused due to a guest crash",
+#endif
+#ifdef HAVE_DOM_REASON_PAUSED_STARTING_UP
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_STARTING_UP] =
+ "the domain is being started",
+#endif
+#ifdef HAVE_DOM_REASON_POSTCOPY
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_POSTCOPY] =
+ "paused for post-copy migration",
+ [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_POSTCOPY_FAILED] =
+ "paused after failed post-copy",
+#endif
+
+ [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_UNKNOWN] =
+ "the reason is unknown",
+ [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_USER] =
+ "shutting down on user request",
+
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_UNKNOWN] =
+ "the reason is unknown",
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_SHUTDOWN] = "normal shutdown",
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_DESTROYED] = "forced poweroff",
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_CRASHED] = "domain crashed",
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_MIGRATED] =
+ "migrated to another host",
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_SAVED] = "saved to a file",
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_FAILED] =
+ "domain failed to start",
+ [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT] =
+ "restored from a snapshot which was taken while domain was shutoff",
+
+ [VIR_DOMAIN_CRASHED][VIR_DOMAIN_CRASHED_UNKNOWN] =
+ "the reason is unknown",
+#ifdef VIR_DOMAIN_CRASHED_PANICKED
+ [VIR_DOMAIN_CRASHED][VIR_DOMAIN_CRASHED_PANICKED] = "domain panicked",
+#endif
+
+#ifdef HAVE_DOM_STATE_PMSUSPENDED
+ [VIR_DOMAIN_PMSUSPENDED][VIR_DOMAIN_PMSUSPENDED_UNKNOWN] =
+ "the reason is unknown",
+#endif
+};
+#endif /* HAVE_DOM_REASON */
+