examples: Move and install shell examples
[libvirt/ericb.git] / examples / object-events / event-test.c
blobfcf449247067bebb968e42c015e295f017dac5b5
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <signal.h>
5 #include <inttypes.h>
7 #define VIR_ENUM_SENTINELS
9 #include <libvirt/libvirt.h>
10 #include <libvirt/virterror.h>
12 #define ARRAY_CARDINALITY(Array) (sizeof(Array) / sizeof(*(Array)))
13 #define STREQ(a, b) (strcmp(a, b) == 0)
14 #define NULLSTR(s) ((s) ? (s) : "<null>")
16 #if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \
17 && (201112L <= __STDC_VERSION__ || !defined __STRICT_ANSI__) \
18 && !defined __cplusplus)
19 # define verify(cond) _Static_assert(cond, "verify (" #cond ")")
20 #else
21 # define verify(cond)
22 #endif
24 #ifndef ATTRIBUTE_UNUSED
25 # define ATTRIBUTE_UNUSED __attribute__((__unused__))
26 #endif
28 int run = 1;
30 /* Callback functions */
31 static void
32 connectClose(virConnectPtr conn ATTRIBUTE_UNUSED,
33 int reason,
34 void *opaque ATTRIBUTE_UNUSED)
36 run = 0;
38 switch ((virConnectCloseReason) reason) {
39 case VIR_CONNECT_CLOSE_REASON_ERROR:
40 fprintf(stderr, "Connection closed due to I/O error\n");
41 return;
43 case VIR_CONNECT_CLOSE_REASON_EOF:
44 fprintf(stderr, "Connection closed due to end of file\n");
45 return;
47 case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
48 fprintf(stderr, "Connection closed due to keepalive timeout\n");
49 return;
51 case VIR_CONNECT_CLOSE_REASON_CLIENT:
52 fprintf(stderr, "Connection closed due to client request\n");
53 return;
55 case VIR_CONNECT_CLOSE_REASON_LAST:
56 break;
59 fprintf(stderr, "Connection closed due to unknown reason\n");
63 static const char *
64 eventToString(int event)
66 switch ((virDomainEventType) event) {
67 case VIR_DOMAIN_EVENT_DEFINED:
68 return "Defined";
70 case VIR_DOMAIN_EVENT_UNDEFINED:
71 return "Undefined";
73 case VIR_DOMAIN_EVENT_STARTED:
74 return "Started";
76 case VIR_DOMAIN_EVENT_SUSPENDED:
77 return "Suspended";
79 case VIR_DOMAIN_EVENT_RESUMED:
80 return "Resumed";
82 case VIR_DOMAIN_EVENT_STOPPED:
83 return "Stopped";
85 case VIR_DOMAIN_EVENT_SHUTDOWN:
86 return "Shutdown";
88 case VIR_DOMAIN_EVENT_PMSUSPENDED:
89 return "PMSuspended";
91 case VIR_DOMAIN_EVENT_CRASHED:
92 return "Crashed";
94 case VIR_DOMAIN_EVENT_LAST:
95 break;
98 return "unknown";
102 static const char *
103 eventDetailToString(int event,
104 int detail)
106 switch ((virDomainEventType) event) {
107 case VIR_DOMAIN_EVENT_DEFINED:
108 switch ((virDomainEventDefinedDetailType) detail) {
109 case VIR_DOMAIN_EVENT_DEFINED_ADDED:
110 return "Added";
112 case VIR_DOMAIN_EVENT_DEFINED_UPDATED:
113 return "Updated";
115 case VIR_DOMAIN_EVENT_DEFINED_RENAMED:
116 return "Renamed";
118 case VIR_DOMAIN_EVENT_DEFINED_FROM_SNAPSHOT:
119 return "Snapshot";
121 case VIR_DOMAIN_EVENT_DEFINED_LAST:
122 break;
124 break;
126 case VIR_DOMAIN_EVENT_UNDEFINED:
127 switch ((virDomainEventUndefinedDetailType) detail) {
128 case VIR_DOMAIN_EVENT_UNDEFINED_REMOVED:
129 return "Removed";
131 case VIR_DOMAIN_EVENT_UNDEFINED_RENAMED:
132 return "Renamed";
134 case VIR_DOMAIN_EVENT_UNDEFINED_LAST:
135 break;
137 break;
139 case VIR_DOMAIN_EVENT_STARTED:
140 switch ((virDomainEventStartedDetailType) detail) {
141 case VIR_DOMAIN_EVENT_STARTED_BOOTED:
142 return "Booted";
144 case VIR_DOMAIN_EVENT_STARTED_MIGRATED:
145 return "Migrated";
147 case VIR_DOMAIN_EVENT_STARTED_RESTORED:
148 return "Restored";
150 case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT:
151 return "Snapshot";
153 case VIR_DOMAIN_EVENT_STARTED_WAKEUP:
154 return "Event wakeup";
156 case VIR_DOMAIN_EVENT_STARTED_LAST:
157 break;
159 break;
161 case VIR_DOMAIN_EVENT_SUSPENDED:
162 switch ((virDomainEventSuspendedDetailType) detail) {
163 case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED:
164 return "Paused";
166 case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
167 return "Migrated";
169 case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR:
170 return "I/O Error";
172 case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG:
173 return "Watchdog";
175 case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED:
176 return "Restored";
178 case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT:
179 return "Snapshot";
181 case VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR:
182 return "API error";
184 case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY:
185 return "Post-copy";
187 case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY_FAILED:
188 return "Post-copy Error";
190 case VIR_DOMAIN_EVENT_SUSPENDED_LAST:
191 break;
193 break;
195 case VIR_DOMAIN_EVENT_RESUMED:
196 switch ((virDomainEventResumedDetailType) detail) {
197 case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED:
198 return "Unpaused";
200 case VIR_DOMAIN_EVENT_RESUMED_MIGRATED:
201 return "Migrated";
203 case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT:
204 return "Snapshot";
206 case VIR_DOMAIN_EVENT_RESUMED_POSTCOPY:
207 return "Post-copy";
209 case VIR_DOMAIN_EVENT_RESUMED_LAST:
210 break;
212 break;
214 case VIR_DOMAIN_EVENT_STOPPED:
215 switch ((virDomainEventStoppedDetailType) detail) {
216 case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN:
217 return "Shutdown";
219 case VIR_DOMAIN_EVENT_STOPPED_DESTROYED:
220 return "Destroyed";
222 case VIR_DOMAIN_EVENT_STOPPED_CRASHED:
223 return "Crashed";
225 case VIR_DOMAIN_EVENT_STOPPED_MIGRATED:
226 return "Migrated";
228 case VIR_DOMAIN_EVENT_STOPPED_SAVED:
229 return "Saved";
231 case VIR_DOMAIN_EVENT_STOPPED_FAILED:
232 return "Failed";
234 case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT:
235 return "Snapshot";
237 case VIR_DOMAIN_EVENT_STOPPED_LAST:
238 break;
240 break;
242 case VIR_DOMAIN_EVENT_SHUTDOWN:
243 switch ((virDomainEventShutdownDetailType) detail) {
244 case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
245 return "Finished";
247 case VIR_DOMAIN_EVENT_SHUTDOWN_GUEST:
248 return "Guest request";
250 case VIR_DOMAIN_EVENT_SHUTDOWN_HOST:
251 return "Host request";
253 case VIR_DOMAIN_EVENT_SHUTDOWN_LAST:
254 break;
256 break;
258 case VIR_DOMAIN_EVENT_PMSUSPENDED:
259 switch ((virDomainEventPMSuspendedDetailType) detail) {
260 case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY:
261 return "Memory";
263 case VIR_DOMAIN_EVENT_PMSUSPENDED_DISK:
264 return "Disk";
266 case VIR_DOMAIN_EVENT_PMSUSPENDED_LAST:
267 break;
269 break;
271 case VIR_DOMAIN_EVENT_CRASHED:
272 switch ((virDomainEventCrashedDetailType) detail) {
273 case VIR_DOMAIN_EVENT_CRASHED_PANICKED:
274 return "Panicked";
276 case VIR_DOMAIN_EVENT_CRASHED_LAST:
277 break;
279 break;
281 case VIR_DOMAIN_EVENT_LAST:
282 break;
285 return "unknown";
289 static const char *
290 networkEventToString(int event)
292 switch ((virNetworkEventLifecycleType) event) {
293 case VIR_NETWORK_EVENT_DEFINED:
294 return "Defined";
296 case VIR_NETWORK_EVENT_UNDEFINED:
297 return "Undefined";
299 case VIR_NETWORK_EVENT_STARTED:
300 return "Started";
302 case VIR_NETWORK_EVENT_STOPPED:
303 return "Stopped";
305 case VIR_NETWORK_EVENT_LAST:
306 break;
309 return "unknown";
313 static const char *
314 guestAgentLifecycleEventStateToString(int event)
316 switch ((virConnectDomainEventAgentLifecycleState) event) {
317 case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_DISCONNECTED:
318 return "Disconnected";
320 case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_CONNECTED:
321 return "Connected";
323 case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_LAST:
324 break;
327 return "unknown";
331 static const char *
332 guestAgentLifecycleEventReasonToString(int event)
334 switch ((virConnectDomainEventAgentLifecycleReason) event) {
335 case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_UNKNOWN:
336 return "Unknown";
338 case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_DOMAIN_STARTED:
339 return "Domain started";
341 case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL:
342 return "Channel event";
344 case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_LAST:
345 break;
348 return "unknown";
351 static const char *
352 storagePoolEventToString(int event)
354 switch ((virStoragePoolEventLifecycleType) event) {
355 case VIR_STORAGE_POOL_EVENT_DEFINED:
356 return "Defined";
357 case VIR_STORAGE_POOL_EVENT_UNDEFINED:
358 return "Undefined";
359 case VIR_STORAGE_POOL_EVENT_STARTED:
360 return "Started";
361 case VIR_STORAGE_POOL_EVENT_STOPPED:
362 return "Stopped";
363 case VIR_STORAGE_POOL_EVENT_CREATED:
364 return "Created";
365 case VIR_STORAGE_POOL_EVENT_DELETED:
366 return "Deleted";
367 case VIR_STORAGE_POOL_EVENT_LAST:
368 break;
370 return "unknown";
373 static const char *
374 nodeDeviceEventToString(int event)
376 switch ((virNodeDeviceEventLifecycleType) event) {
377 case VIR_NODE_DEVICE_EVENT_CREATED:
378 return "Created";
379 case VIR_NODE_DEVICE_EVENT_DELETED:
380 return "Deleted";
381 case VIR_NODE_DEVICE_EVENT_LAST:
382 break;
384 return "unknown";
388 static const char *
389 secretEventToString(int event)
391 switch ((virSecretEventLifecycleType) event) {
392 case VIR_SECRET_EVENT_DEFINED:
393 return "Defined";
395 case VIR_SECRET_EVENT_UNDEFINED:
396 return "Undefined";
398 case VIR_SECRET_EVENT_LAST:
399 break;
402 return "unknown";
406 static int
407 myDomainEventCallback1(virConnectPtr conn ATTRIBUTE_UNUSED,
408 virDomainPtr dom,
409 int event,
410 int detail,
411 void *opaque ATTRIBUTE_UNUSED)
413 printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
414 virDomainGetID(dom), eventToString(event),
415 eventDetailToString(event, detail));
416 return 0;
420 static int
421 myDomainEventCallback2(virConnectPtr conn ATTRIBUTE_UNUSED,
422 virDomainPtr dom,
423 int event,
424 int detail,
425 void *opaque ATTRIBUTE_UNUSED)
427 printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
428 virDomainGetID(dom), eventToString(event),
429 eventDetailToString(event, detail));
430 return 0;
434 static int
435 myDomainEventRebootCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
436 virDomainPtr dom,
437 void *opaque ATTRIBUTE_UNUSED)
439 printf("%s EVENT: Domain %s(%d) rebooted\n", __func__, virDomainGetName(dom),
440 virDomainGetID(dom));
442 return 0;
446 static int
447 myDomainEventRTCChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
448 virDomainPtr dom,
449 long long offset,
450 void *opaque ATTRIBUTE_UNUSED)
452 printf("%s EVENT: Domain %s(%d) rtc change %" PRIdMAX "\n",
453 __func__, virDomainGetName(dom), virDomainGetID(dom),
454 (intmax_t)offset);
456 return 0;
460 static int
461 myDomainEventBalloonChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
462 virDomainPtr dom,
463 unsigned long long actual,
464 void *opaque ATTRIBUTE_UNUSED)
466 printf("%s EVENT: Domain %s(%d) balloon change %" PRIuMAX "KB\n",
467 __func__, virDomainGetName(dom), virDomainGetID(dom), (uintmax_t)actual);
469 return 0;
473 static int
474 myDomainEventWatchdogCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
475 virDomainPtr dom,
476 int action,
477 void *opaque ATTRIBUTE_UNUSED)
479 printf("%s EVENT: Domain %s(%d) watchdog action=%d\n", __func__,
480 virDomainGetName(dom), virDomainGetID(dom), action);
482 return 0;
486 static int
487 myDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
488 virDomainPtr dom,
489 const char *srcPath,
490 const char *devAlias,
491 int action,
492 void *opaque ATTRIBUTE_UNUSED)
494 printf("%s EVENT: Domain %s(%d) io error path=%s alias=%s action=%d\n",
495 __func__, virDomainGetName(dom), virDomainGetID(dom),
496 srcPath, devAlias, action);
498 return 0;
502 static int
503 myDomainEventIOErrorReasonCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
504 virDomainPtr dom,
505 const char *srcPath,
506 const char *devAlias,
507 int action,
508 const char *reason,
509 void *opaque ATTRIBUTE_UNUSED)
511 printf("%s EVENT: Domain %s(%d) io error (reason) path=%s alias=%s "
512 "action=%d reason=%s\n",
513 __func__, virDomainGetName(dom), virDomainGetID(dom),
514 srcPath, devAlias, action, reason);
516 return 0;
520 static const char *
521 graphicsPhaseToStr(int phase)
523 switch ((virDomainEventGraphicsPhase) phase) {
524 case VIR_DOMAIN_EVENT_GRAPHICS_CONNECT:
525 return "connected";
527 case VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE:
528 return "initialized";
530 case VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT:
531 return "disconnected";
533 case VIR_DOMAIN_EVENT_GRAPHICS_LAST:
534 break;
537 return "unknown";
541 static int
542 myDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
543 virDomainPtr dom,
544 int phase,
545 virDomainEventGraphicsAddressPtr local,
546 virDomainEventGraphicsAddressPtr remote,
547 const char *authScheme,
548 virDomainEventGraphicsSubjectPtr subject,
549 void *opaque ATTRIBUTE_UNUSED)
551 size_t i;
552 printf("%s EVENT: Domain %s(%d) graphics ", __func__, virDomainGetName(dom),
553 virDomainGetID(dom));
555 printf("%s ", graphicsPhaseToStr(phase));
557 printf("local: family=%d node=%s service=%s ",
558 local->family, local->node, local->service);
559 printf("remote: family=%d node=%s service=%s ",
560 remote->family, remote->node, remote->service);
562 printf("auth: %s ", authScheme);
563 for (i = 0; i < subject->nidentity; i++) {
564 printf(" identity: %s=%s",
565 subject->identities[i].type,
566 subject->identities[i].name);
568 printf("\n");
570 return 0;
574 static int
575 myDomainEventControlErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
576 virDomainPtr dom,
577 void *opaque ATTRIBUTE_UNUSED)
579 printf("%s EVENT: Domain %s(%d) control error\n", __func__,
580 virDomainGetName(dom), virDomainGetID(dom));
582 return 0;
585 static const char *
586 diskChangeReasonToStr(int reason)
588 switch ((virConnectDomainEventDiskChangeReason) reason) {
589 case VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START:
590 return "disk empty due to startupPolicy";
592 case VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START:
593 return "disk dropped due to startupPolicy";
595 case VIR_DOMAIN_EVENT_DISK_CHANGE_LAST:
596 break;
599 return "unknown";
603 static int
604 myDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
605 virDomainPtr dom,
606 const char *oldSrcPath,
607 const char *newSrcPath,
608 const char *devAlias,
609 int reason,
610 void *opaque ATTRIBUTE_UNUSED)
612 printf("%s EVENT: Domain %s(%d) disk change oldSrcPath: %s newSrcPath: %s "
613 "devAlias: %s reason: %s\n",
614 __func__, virDomainGetName(dom), virDomainGetID(dom),
615 oldSrcPath, newSrcPath, devAlias, diskChangeReasonToStr(reason));
616 return 0;
619 static const char *
620 trayChangeReasonToStr(int reason)
622 switch ((virDomainEventTrayChangeReason) reason) {
623 case VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN:
624 return "open";
626 case VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE:
627 return "close";
629 case VIR_DOMAIN_EVENT_TRAY_CHANGE_LAST:
630 break;
633 return "unknown";
637 static int
638 myDomainEventTrayChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
639 virDomainPtr dom,
640 const char *devAlias,
641 int reason,
642 void *opaque ATTRIBUTE_UNUSED)
644 printf("%s EVENT: Domain %s(%d) removable disk's tray change devAlias: %s "
645 "reason: %s\n",
646 __func__, virDomainGetName(dom), virDomainGetID(dom),
647 devAlias, trayChangeReasonToStr(reason));
648 return 0;
652 static int
653 myDomainEventPMWakeupCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
654 virDomainPtr dom,
655 int reason ATTRIBUTE_UNUSED,
656 void *opaque ATTRIBUTE_UNUSED)
658 printf("%s EVENT: Domain %s(%d) system pmwakeup\n",
659 __func__, virDomainGetName(dom), virDomainGetID(dom));
660 return 0;
664 static int
665 myDomainEventPMSuspendCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
666 virDomainPtr dom,
667 int reason ATTRIBUTE_UNUSED,
668 void *opaque ATTRIBUTE_UNUSED)
670 printf("%s EVENT: Domain %s(%d) system pmsuspend\n",
671 __func__, virDomainGetName(dom), virDomainGetID(dom));
672 return 0;
676 static int
677 myDomainEventPMSuspendDiskCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
678 virDomainPtr dom,
679 int reason ATTRIBUTE_UNUSED,
680 void *opaque ATTRIBUTE_UNUSED)
682 printf("%s EVENT: Domain %s(%d) system pmsuspend-disk\n",
683 __func__, virDomainGetName(dom), virDomainGetID(dom));
684 return 0;
688 static int
689 myDomainEventDeviceRemovedCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
690 virDomainPtr dom,
691 const char *devAlias,
692 void *opaque ATTRIBUTE_UNUSED)
694 printf("%s EVENT: Domain %s(%d) device removed: %s\n",
695 __func__, virDomainGetName(dom), virDomainGetID(dom), devAlias);
696 return 0;
700 static int
701 myNetworkEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
702 virNetworkPtr dom,
703 int event,
704 int detail,
705 void *opaque ATTRIBUTE_UNUSED)
707 printf("%s EVENT: Network %s %s %d\n", __func__, virNetworkGetName(dom),
708 networkEventToString(event), detail);
709 return 0;
712 static int
713 myStoragePoolEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
714 virStoragePoolPtr pool,
715 int event,
716 int detail,
717 void *opaque ATTRIBUTE_UNUSED)
719 printf("%s EVENT: Storage pool %s %s %d\n", __func__,
720 virStoragePoolGetName(pool),
721 storagePoolEventToString(event),
722 detail);
723 return 0;
727 static int
728 myStoragePoolEventRefreshCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
729 virStoragePoolPtr pool,
730 void *opaque ATTRIBUTE_UNUSED)
732 printf("%s EVENT: Storage pool %s refresh\n", __func__,
733 virStoragePoolGetName(pool));
734 return 0;
738 static int
739 myNodeDeviceEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
740 virNodeDevicePtr dev,
741 int event,
742 int detail,
743 void *opaque ATTRIBUTE_UNUSED)
745 printf("%s EVENT: Node device %s %s %d\n", __func__,
746 virNodeDeviceGetName(dev),
747 nodeDeviceEventToString(event),
748 detail);
749 return 0;
753 static int
754 myNodeDeviceEventUpdateCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
755 virNodeDevicePtr dev,
756 void *opaque ATTRIBUTE_UNUSED)
758 printf("%s EVENT: Node device %s update\n", __func__,
759 virNodeDeviceGetName(dev));
760 return 0;
764 static int
765 mySecretEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
766 virSecretPtr secret,
767 int event,
768 int detail,
769 void *opaque ATTRIBUTE_UNUSED)
771 char uuid[VIR_UUID_STRING_BUFLEN];
772 virSecretGetUUIDString(secret, uuid);
773 printf("%s EVENT: Secret %s %s %d\n", __func__,
774 uuid,
775 secretEventToString(event),
776 detail);
777 return 0;
781 static int
782 mySecretEventValueChanged(virConnectPtr conn ATTRIBUTE_UNUSED,
783 virSecretPtr secret,
784 void *opaque ATTRIBUTE_UNUSED)
786 char uuid[VIR_UUID_STRING_BUFLEN];
787 virSecretGetUUIDString(secret, uuid);
788 printf("%s EVENT: Secret %s\n", __func__, uuid);
789 return 0;
793 static void
794 eventTypedParamsPrint(virTypedParameterPtr params,
795 int nparams)
797 size_t i;
799 for (i = 0; i < nparams; i++) {
800 switch (params[i].type) {
801 case VIR_TYPED_PARAM_INT:
802 printf("\t%s: %d\n", params[i].field, params[i].value.i);
803 break;
804 case VIR_TYPED_PARAM_UINT:
805 printf("\t%s: %u\n", params[i].field, params[i].value.ui);
806 break;
807 case VIR_TYPED_PARAM_LLONG:
808 printf("\t%s: %" PRId64 "\n", params[i].field,
809 (int64_t) params[i].value.l);
810 break;
811 case VIR_TYPED_PARAM_ULLONG:
812 printf("\t%s: %" PRIu64 "\n", params[i].field,
813 (uint64_t) params[i].value.ul);
814 break;
815 case VIR_TYPED_PARAM_DOUBLE:
816 printf("\t%s: %g\n", params[i].field, params[i].value.d);
817 break;
818 case VIR_TYPED_PARAM_BOOLEAN:
819 printf("\t%s: %d\n", params[i].field, params[i].value.b);
820 break;
821 case VIR_TYPED_PARAM_STRING:
822 printf("\t%s: %s\n", params[i].field, params[i].value.s);
823 break;
824 default:
825 printf("\t%s: unknown type\n", params[i].field);
831 static int
832 myDomainEventTunableCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
833 virDomainPtr dom,
834 virTypedParameterPtr params,
835 int nparams,
836 void *opaque ATTRIBUTE_UNUSED)
838 printf("%s EVENT: Domain %s(%d) tunable updated:\n",
839 __func__, virDomainGetName(dom), virDomainGetID(dom));
841 eventTypedParamsPrint(params, nparams);
843 return 0;
847 static int
848 myDomainEventAgentLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
849 virDomainPtr dom,
850 int state,
851 int reason,
852 void *opaque ATTRIBUTE_UNUSED)
854 printf("%s EVENT: Domain %s(%d) guest agent state changed: %s reason: %s\n",
855 __func__, virDomainGetName(dom), virDomainGetID(dom),
856 guestAgentLifecycleEventStateToString(state),
857 guestAgentLifecycleEventReasonToString(reason));
859 return 0;
863 static int
864 myDomainEventDeviceAddedCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
865 virDomainPtr dom,
866 const char *devAlias,
867 void *opaque ATTRIBUTE_UNUSED)
869 printf("%s EVENT: Domain %s(%d) device added: %s\n",
870 __func__, virDomainGetName(dom), virDomainGetID(dom), devAlias);
871 return 0;
875 static const char *
876 blockJobTypeToStr(int type)
878 switch ((virDomainBlockJobType) type) {
879 case VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN:
880 case VIR_DOMAIN_BLOCK_JOB_TYPE_LAST:
881 break;
883 case VIR_DOMAIN_BLOCK_JOB_TYPE_PULL:
884 return "block pull";
886 case VIR_DOMAIN_BLOCK_JOB_TYPE_COPY:
887 return "block copy";
889 case VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT:
890 return "block commit";
892 case VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT:
893 return "active layer block commit";
896 return "unknown";
900 static const char *
901 blockJobStatusToStr(int status)
903 switch ((virConnectDomainEventBlockJobStatus) status) {
904 case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
905 return "completed";
907 case VIR_DOMAIN_BLOCK_JOB_FAILED:
908 return "failed";
910 case VIR_DOMAIN_BLOCK_JOB_CANCELED:
911 return "cancelled";
913 case VIR_DOMAIN_BLOCK_JOB_READY:
914 return "ready";
916 case VIR_DOMAIN_BLOCK_JOB_LAST:
917 break;
920 return "unknown";
924 static int
925 myDomainEventBlockJobCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
926 virDomainPtr dom,
927 const char *disk,
928 int type,
929 int status,
930 void *opaque)
932 const char *eventName = opaque;
934 printf("%s EVENT: Domain %s(%d) block job callback '%s' disk '%s', "
935 "type '%s' status '%s'",
936 __func__, virDomainGetName(dom), virDomainGetID(dom), eventName,
937 disk, blockJobTypeToStr(type), blockJobStatusToStr(status));
938 return 0;
942 static int
943 myDomainEventBlockThresholdCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
944 virDomainPtr dom,
945 const char *dev,
946 const char *path,
947 unsigned long long threshold,
948 unsigned long long excess,
949 void *opaque ATTRIBUTE_UNUSED)
951 /* Casts to uint64_t to work around mingw not knowing %lld */
952 printf("%s EVENT: Domain %s(%d) block threshold callback dev '%s'(%s), "
953 "threshold: '%" PRIu64 "', excess: '%" PRIu64 "'",
954 __func__, virDomainGetName(dom), virDomainGetID(dom),
955 dev, NULLSTR(path), (uint64_t)threshold, (uint64_t)excess);
956 return 0;
960 static int
961 myDomainEventMigrationIterationCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
962 virDomainPtr dom,
963 int iteration,
964 void *opaque ATTRIBUTE_UNUSED)
966 printf("%s EVENT: Domain %s(%d) migration iteration '%d'\n",
967 __func__, virDomainGetName(dom), virDomainGetID(dom), iteration);
968 return 0;
972 static int
973 myDomainEventJobCompletedCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
974 virDomainPtr dom,
975 virTypedParameterPtr params,
976 int nparams,
977 void *opaque ATTRIBUTE_UNUSED)
979 printf("%s EVENT: Domain %s(%d) job completed:\n",
980 __func__, virDomainGetName(dom), virDomainGetID(dom));
982 eventTypedParamsPrint(params, nparams);
984 return 0;
988 static int
989 myDomainEventDeviceRemovalFailedCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
990 virDomainPtr dom,
991 const char *devAlias,
992 void *opaque ATTRIBUTE_UNUSED)
994 printf("%s EVENT: Domain %s(%d) device removal failed: %s\n",
995 __func__, virDomainGetName(dom), virDomainGetID(dom), devAlias);
996 return 0;
1000 static const char *
1001 metadataTypeToStr(int status)
1003 switch ((virDomainMetadataType) status) {
1004 case VIR_DOMAIN_METADATA_DESCRIPTION:
1005 return "description";
1007 case VIR_DOMAIN_METADATA_TITLE:
1008 return "title";
1010 case VIR_DOMAIN_METADATA_ELEMENT:
1011 return "element";
1013 case VIR_DOMAIN_METADATA_LAST:
1014 break;
1017 return "unknown";
1020 static int
1021 myDomainEventMetadataChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
1022 virDomainPtr dom,
1023 int type,
1024 const char *nsuri,
1025 void *opaque ATTRIBUTE_UNUSED)
1027 const char *typestr = metadataTypeToStr(type);
1028 printf("%s EVENT: Domain %s(%d) metadata type: %s (%s)\n",
1029 __func__, virDomainGetName(dom), virDomainGetID(dom), typestr, nsuri ? nsuri : "n/a");
1030 return 0;
1035 static void
1036 myFreeFunc(void *opaque)
1038 char *str = opaque;
1039 printf("%s: Freeing [%s]\n", __func__, str);
1040 free(str);
1044 /* main test functions */
1045 static void
1046 stop(int sig)
1048 printf("Exiting on signal %d\n", sig);
1049 run = 0;
1053 struct domainEventData {
1054 int event;
1055 int id;
1056 virConnectDomainEventGenericCallback cb;
1057 const char *name;
1061 #define DOMAIN_EVENT(event, callback) \
1062 {event, -1, VIR_DOMAIN_EVENT_CALLBACK(callback), #event}
1064 struct domainEventData domainEvents[] = {
1065 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_LIFECYCLE, myDomainEventCallback2),
1066 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_REBOOT, myDomainEventRebootCallback),
1067 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_RTC_CHANGE, myDomainEventRTCChangeCallback),
1068 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_WATCHDOG, myDomainEventWatchdogCallback),
1069 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_IO_ERROR, myDomainEventIOErrorCallback),
1070 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_GRAPHICS, myDomainEventGraphicsCallback),
1071 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, myDomainEventIOErrorReasonCallback),
1072 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR, myDomainEventControlErrorCallback),
1073 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB, myDomainEventBlockJobCallback),
1074 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DISK_CHANGE, myDomainEventDiskChangeCallback),
1075 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_TRAY_CHANGE, myDomainEventTrayChangeCallback),
1076 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_PMWAKEUP, myDomainEventPMWakeupCallback),
1077 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_PMSUSPEND, myDomainEventPMSuspendCallback),
1078 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, myDomainEventBalloonChangeCallback),
1079 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK, myDomainEventPMSuspendDiskCallback),
1080 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, myDomainEventDeviceRemovedCallback),
1081 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2, myDomainEventBlockJobCallback),
1082 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_TUNABLE, myDomainEventTunableCallback),
1083 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE, myDomainEventAgentLifecycleCallback),
1084 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_ADDED, myDomainEventDeviceAddedCallback),
1085 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION, myDomainEventMigrationIterationCallback),
1086 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, myDomainEventJobCompletedCallback),
1087 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback),
1088 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback),
1089 DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback),
1092 struct storagePoolEventData {
1093 int event;
1094 int id;
1095 virConnectStoragePoolEventGenericCallback cb;
1096 const char *name;
1099 #define STORAGE_POOL_EVENT(event, callback) \
1100 {event, -1, VIR_STORAGE_POOL_EVENT_CALLBACK(callback), #event}
1102 struct storagePoolEventData storagePoolEvents[] = {
1103 STORAGE_POOL_EVENT(VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE, myStoragePoolEventCallback),
1104 STORAGE_POOL_EVENT(VIR_STORAGE_POOL_EVENT_ID_REFRESH, myStoragePoolEventRefreshCallback),
1107 struct nodeDeviceEventData {
1108 int event;
1109 int id;
1110 virConnectNodeDeviceEventGenericCallback cb;
1111 const char *name;
1114 #define NODE_DEVICE_EVENT(event, callback) \
1115 {event, -1, VIR_NODE_DEVICE_EVENT_CALLBACK(callback), #event}
1117 struct nodeDeviceEventData nodeDeviceEvents[] = {
1118 NODE_DEVICE_EVENT(VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE, myNodeDeviceEventCallback),
1119 NODE_DEVICE_EVENT(VIR_NODE_DEVICE_EVENT_ID_UPDATE, myNodeDeviceEventUpdateCallback),
1122 struct secretEventData {
1123 int event;
1124 int id;
1125 virConnectSecretEventGenericCallback cb;
1126 const char *name;
1129 #define SECRET_EVENT(event, callback) \
1130 {event, -1, VIR_SECRET_EVENT_CALLBACK(callback), #event}
1132 struct secretEventData secretEvents[] = {
1133 SECRET_EVENT(VIR_SECRET_EVENT_ID_LIFECYCLE, mySecretEventCallback),
1134 SECRET_EVENT(VIR_SECRET_EVENT_ID_VALUE_CHANGED, mySecretEventValueChanged),
1137 /* make sure that the events are kept in sync */
1138 verify(ARRAY_CARDINALITY(domainEvents) == VIR_DOMAIN_EVENT_ID_LAST);
1139 verify(ARRAY_CARDINALITY(storagePoolEvents) == VIR_STORAGE_POOL_EVENT_ID_LAST);
1140 verify(ARRAY_CARDINALITY(nodeDeviceEvents) == VIR_NODE_DEVICE_EVENT_ID_LAST);
1141 verify(ARRAY_CARDINALITY(secretEvents) == VIR_SECRET_EVENT_ID_LAST);
1144 main(int argc, char **argv)
1146 int ret = EXIT_FAILURE;
1147 virConnectPtr dconn = NULL;
1148 int callback1ret = -1;
1149 int callback16ret = -1;
1150 size_t i;
1152 if (argc > 1 && STREQ(argv[1], "--help")) {
1153 printf("%s uri\n", argv[0]);
1154 goto cleanup;
1157 if (virInitialize() < 0) {
1158 fprintf(stderr, "Failed to initialize libvirt");
1159 goto cleanup;
1162 if (virEventRegisterDefaultImpl() < 0) {
1163 fprintf(stderr, "Failed to register event implementation: %s\n",
1164 virGetLastErrorMessage());
1165 goto cleanup;
1168 dconn = virConnectOpenAuth(argc > 1 ? argv[1] : NULL,
1169 virConnectAuthPtrDefault,
1170 VIR_CONNECT_RO);
1171 if (!dconn) {
1172 printf("error opening\n");
1173 goto cleanup;
1176 if (virConnectRegisterCloseCallback(dconn,
1177 connectClose, NULL, NULL) < 0) {
1178 fprintf(stderr, "Unable to register close callback\n");
1179 goto cleanup;
1182 /* The ideal program would use sigaction to set this handler, but
1183 * this way is portable to mingw. */
1184 signal(SIGTERM, stop);
1185 signal(SIGINT, stop);
1187 printf("Registering event callbacks\n");
1189 callback1ret = virConnectDomainEventRegister(dconn, myDomainEventCallback1,
1190 strdup("callback 1"), myFreeFunc);
1192 /* register common domain callbacks */
1193 for (i = 0; i < ARRAY_CARDINALITY(domainEvents); i++) {
1194 struct domainEventData *event = domainEvents + i;
1196 event->id = virConnectDomainEventRegisterAny(dconn, NULL,
1197 event->event,
1198 event->cb,
1199 strdup(event->name),
1200 myFreeFunc);
1202 if (event->id < 0) {
1203 fprintf(stderr, "Failed to register event '%s'\n", event->name);
1204 goto cleanup;
1208 callback16ret = virConnectNetworkEventRegisterAny(dconn,
1209 NULL,
1210 VIR_NETWORK_EVENT_ID_LIFECYCLE,
1211 VIR_NETWORK_EVENT_CALLBACK(myNetworkEventCallback),
1212 strdup("net callback"), myFreeFunc);
1214 /* register common storage pool callbacks */
1215 for (i = 0; i < ARRAY_CARDINALITY(storagePoolEvents); i++) {
1216 struct storagePoolEventData *event = storagePoolEvents + i;
1218 event->id = virConnectStoragePoolEventRegisterAny(dconn, NULL,
1219 event->event,
1220 event->cb,
1221 strdup(event->name),
1222 myFreeFunc);
1224 if (event->id < 0) {
1225 fprintf(stderr, "Failed to register event '%s'\n", event->name);
1226 goto cleanup;
1230 /* register common node device callbacks */
1231 for (i = 0; i < ARRAY_CARDINALITY(nodeDeviceEvents); i++) {
1232 struct nodeDeviceEventData *event = nodeDeviceEvents + i;
1234 event->id = virConnectNodeDeviceEventRegisterAny(dconn, NULL,
1235 event->event,
1236 event->cb,
1237 strdup(event->name),
1238 myFreeFunc);
1240 if (event->id < 0) {
1241 fprintf(stderr, "Failed to register event '%s'\n", event->name);
1242 goto cleanup;
1246 /* register common secret callbacks */
1247 for (i = 0; i < ARRAY_CARDINALITY(secretEvents); i++) {
1248 struct secretEventData *event = secretEvents + i;
1250 event->id = virConnectSecretEventRegisterAny(dconn, NULL,
1251 event->event,
1252 event->cb,
1253 strdup(event->name),
1254 myFreeFunc);
1256 if (event->id < 0) {
1257 fprintf(stderr, "Failed to register event '%s'\n", event->name);
1258 goto cleanup;
1262 if ((callback1ret == -1) ||
1263 (callback16ret == -1))
1264 goto cleanup;
1266 if (virConnectSetKeepAlive(dconn, 5, 3) < 0) {
1267 fprintf(stderr, "Failed to start keepalive protocol: %s\n",
1268 virGetLastErrorMessage());
1269 run = 0;
1272 while (run) {
1273 if (virEventRunDefaultImpl() < 0) {
1274 fprintf(stderr, "Failed to run event loop: %s\n",
1275 virGetLastErrorMessage());
1279 printf("Deregistering event callbacks\n");
1280 virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
1281 virConnectNetworkEventDeregisterAny(dconn, callback16ret);
1284 printf("Deregistering domain event callbacks\n");
1285 for (i = 0; i < ARRAY_CARDINALITY(domainEvents); i++) {
1286 if (domainEvents[i].id > 0)
1287 virConnectDomainEventDeregisterAny(dconn, domainEvents[i].id);
1291 printf("Deregistering storage pool event callbacks\n");
1292 for (i = 0; i < ARRAY_CARDINALITY(storagePoolEvents); i++) {
1293 if (storagePoolEvents[i].id > 0)
1294 virConnectStoragePoolEventDeregisterAny(dconn, storagePoolEvents[i].id);
1298 printf("Deregistering node device event callbacks\n");
1299 for (i = 0; i < ARRAY_CARDINALITY(nodeDeviceEvents); i++) {
1300 if (nodeDeviceEvents[i].id > 0)
1301 virConnectNodeDeviceEventDeregisterAny(dconn, nodeDeviceEvents[i].id);
1304 printf("Deregistering secret event callbacks\n");
1305 for (i = 0; i < ARRAY_CARDINALITY(secretEvents); i++) {
1306 if (secretEvents[i].id > 0)
1307 virConnectSecretEventDeregisterAny(dconn, secretEvents[i].id);
1311 virConnectUnregisterCloseCallback(dconn, connectClose);
1312 ret = EXIT_SUCCESS;
1315 cleanup:
1316 if (dconn) {
1317 printf("Closing connection: ");
1318 if (virConnectClose(dconn) < 0)
1319 printf("failed\n");
1320 printf("done\n");
1323 return ret;