1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <signal.h>
5 #include <inttypes.h>
6 
7 #define VIR_ENUM_SENTINELS
8 
9 #include <libvirt/libvirt.h>
10 #include <libvirt/virterror.h>
11 
12 #define G_N_ELEMENTS(Array) (sizeof(Array) / sizeof(*(Array)))
13 #define STREQ(a, b) (strcmp(a, b) == 0)
14 #define NULLSTR(s) ((s) ? (s) : "<null>")
15 
16 #if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \
17      && (201112L <= __STDC_VERSION__  || !defined __STRICT_ANSI__) \
18      && !defined __cplusplus)
19 # define G_STATIC_ASSERT(cond) _Static_assert(cond, "verify (" #cond ")")
20 #else
21 # define G_STATIC_ASSERT(cond)
22 #endif
23 
24 #ifndef G_GNUC_UNUSED
25 # define G_GNUC_UNUSED __attribute__((__unused__))
26 #endif
27 
28 int run = 1;
29 
30 /* Callback functions */
31 static void
connectClose(virConnectPtr conn G_GNUC_UNUSED,int reason,void * opaque G_GNUC_UNUSED)32 connectClose(virConnectPtr conn G_GNUC_UNUSED,
33              int reason,
34              void *opaque G_GNUC_UNUSED)
35 {
36     run = 0;
37 
38     switch ((virConnectCloseReason) reason) {
39     case VIR_CONNECT_CLOSE_REASON_ERROR:
40         fprintf(stderr, "Connection closed due to I/O error\n");
41         return;
42 
43     case VIR_CONNECT_CLOSE_REASON_EOF:
44         fprintf(stderr, "Connection closed due to end of file\n");
45         return;
46 
47     case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
48         fprintf(stderr, "Connection closed due to keepalive timeout\n");
49         return;
50 
51     case VIR_CONNECT_CLOSE_REASON_CLIENT:
52         fprintf(stderr, "Connection closed due to client request\n");
53         return;
54 
55     case VIR_CONNECT_CLOSE_REASON_LAST:
56         break;
57     };
58 
59     fprintf(stderr, "Connection closed due to unknown reason\n");
60 }
61 
62 
63 static const char *
eventToString(int event)64 eventToString(int event)
65 {
66     switch ((virDomainEventType) event) {
67         case VIR_DOMAIN_EVENT_DEFINED:
68             return "Defined";
69 
70         case VIR_DOMAIN_EVENT_UNDEFINED:
71             return "Undefined";
72 
73         case VIR_DOMAIN_EVENT_STARTED:
74             return "Started";
75 
76         case VIR_DOMAIN_EVENT_SUSPENDED:
77             return "Suspended";
78 
79         case VIR_DOMAIN_EVENT_RESUMED:
80             return "Resumed";
81 
82         case VIR_DOMAIN_EVENT_STOPPED:
83             return "Stopped";
84 
85         case VIR_DOMAIN_EVENT_SHUTDOWN:
86             return "Shutdown";
87 
88         case VIR_DOMAIN_EVENT_PMSUSPENDED:
89             return "PMSuspended";
90 
91         case VIR_DOMAIN_EVENT_CRASHED:
92             return "Crashed";
93 
94         case VIR_DOMAIN_EVENT_LAST:
95             break;
96     }
97 
98     return "unknown";
99 }
100 
101 
102 static const char *
eventDetailToString(int event,int detail)103 eventDetailToString(int event,
104                     int detail)
105 {
106     switch ((virDomainEventType) event) {
107         case VIR_DOMAIN_EVENT_DEFINED:
108             switch ((virDomainEventDefinedDetailType) detail) {
109             case VIR_DOMAIN_EVENT_DEFINED_ADDED:
110                 return "Added";
111 
112             case VIR_DOMAIN_EVENT_DEFINED_UPDATED:
113                 return "Updated";
114 
115             case VIR_DOMAIN_EVENT_DEFINED_RENAMED:
116                 return "Renamed";
117 
118             case  VIR_DOMAIN_EVENT_DEFINED_FROM_SNAPSHOT:
119                 return "Snapshot";
120 
121             case VIR_DOMAIN_EVENT_DEFINED_LAST:
122                 break;
123             }
124             break;
125 
126         case VIR_DOMAIN_EVENT_UNDEFINED:
127             switch ((virDomainEventUndefinedDetailType) detail) {
128             case VIR_DOMAIN_EVENT_UNDEFINED_REMOVED:
129                 return "Removed";
130 
131             case VIR_DOMAIN_EVENT_UNDEFINED_RENAMED:
132                 return "Renamed";
133 
134             case VIR_DOMAIN_EVENT_UNDEFINED_LAST:
135                 break;
136             }
137             break;
138 
139         case VIR_DOMAIN_EVENT_STARTED:
140             switch ((virDomainEventStartedDetailType) detail) {
141             case VIR_DOMAIN_EVENT_STARTED_BOOTED:
142                 return "Booted";
143 
144             case VIR_DOMAIN_EVENT_STARTED_MIGRATED:
145                 return "Migrated";
146 
147             case VIR_DOMAIN_EVENT_STARTED_RESTORED:
148                 return "Restored";
149 
150             case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT:
151                 return "Snapshot";
152 
153             case VIR_DOMAIN_EVENT_STARTED_WAKEUP:
154                 return "Event wakeup";
155 
156             case VIR_DOMAIN_EVENT_STARTED_LAST:
157                 break;
158             }
159             break;
160 
161         case VIR_DOMAIN_EVENT_SUSPENDED:
162             switch ((virDomainEventSuspendedDetailType) detail) {
163             case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED:
164                 return "Paused";
165 
166             case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
167                 return "Migrated";
168 
169             case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR:
170                 return "I/O Error";
171 
172             case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG:
173                 return "Watchdog";
174 
175             case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED:
176                 return "Restored";
177 
178             case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT:
179                 return "Snapshot";
180 
181             case VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR:
182                 return "API error";
183 
184             case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY:
185                 return "Post-copy";
186 
187             case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY_FAILED:
188                 return "Post-copy Error";
189 
190             case VIR_DOMAIN_EVENT_SUSPENDED_LAST:
191                 break;
192             }
193             break;
194 
195         case VIR_DOMAIN_EVENT_RESUMED:
196             switch ((virDomainEventResumedDetailType) detail) {
197             case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED:
198                 return "Unpaused";
199 
200             case VIR_DOMAIN_EVENT_RESUMED_MIGRATED:
201                 return "Migrated";
202 
203             case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT:
204                 return "Snapshot";
205 
206             case VIR_DOMAIN_EVENT_RESUMED_POSTCOPY:
207                 return "Post-copy";
208 
209             case VIR_DOMAIN_EVENT_RESUMED_LAST:
210                 break;
211             }
212             break;
213 
214         case VIR_DOMAIN_EVENT_STOPPED:
215             switch ((virDomainEventStoppedDetailType) detail) {
216             case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN:
217                 return "Shutdown";
218 
219             case VIR_DOMAIN_EVENT_STOPPED_DESTROYED:
220                 return "Destroyed";
221 
222             case VIR_DOMAIN_EVENT_STOPPED_CRASHED:
223                 return "Crashed";
224 
225             case VIR_DOMAIN_EVENT_STOPPED_MIGRATED:
226                 return "Migrated";
227 
228             case VIR_DOMAIN_EVENT_STOPPED_SAVED:
229                 return "Saved";
230 
231             case VIR_DOMAIN_EVENT_STOPPED_FAILED:
232                 return "Failed";
233 
234             case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT:
235                 return "Snapshot";
236 
237             case VIR_DOMAIN_EVENT_STOPPED_LAST:
238                 break;
239             }
240             break;
241 
242         case VIR_DOMAIN_EVENT_SHUTDOWN:
243             switch ((virDomainEventShutdownDetailType) detail) {
244             case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
245                 return "Finished";
246 
247             case VIR_DOMAIN_EVENT_SHUTDOWN_GUEST:
248                 return "Guest request";
249 
250             case VIR_DOMAIN_EVENT_SHUTDOWN_HOST:
251                 return "Host request";
252 
253             case VIR_DOMAIN_EVENT_SHUTDOWN_LAST:
254                 break;
255             }
256             break;
257 
258         case VIR_DOMAIN_EVENT_PMSUSPENDED:
259             switch ((virDomainEventPMSuspendedDetailType) detail) {
260             case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY:
261                 return "Memory";
262 
263             case VIR_DOMAIN_EVENT_PMSUSPENDED_DISK:
264                 return "Disk";
265 
266             case VIR_DOMAIN_EVENT_PMSUSPENDED_LAST:
267                 break;
268             }
269             break;
270 
271         case VIR_DOMAIN_EVENT_CRASHED:
272            switch ((virDomainEventCrashedDetailType) detail) {
273            case VIR_DOMAIN_EVENT_CRASHED_PANICKED:
274                return "Panicked";
275 
276            case VIR_DOMAIN_EVENT_CRASHED_CRASHLOADED:
277                return "Crashloaded";
278 
279            case VIR_DOMAIN_EVENT_CRASHED_LAST:
280                break;
281            }
282            break;
283 
284         case VIR_DOMAIN_EVENT_LAST:
285            break;
286     }
287 
288     return "unknown";
289 }
290 
291 
292 static const char *
networkEventToString(int event)293 networkEventToString(int event)
294 {
295     switch ((virNetworkEventLifecycleType) event) {
296         case VIR_NETWORK_EVENT_DEFINED:
297             return "Defined";
298 
299         case VIR_NETWORK_EVENT_UNDEFINED:
300             return "Undefined";
301 
302         case VIR_NETWORK_EVENT_STARTED:
303             return "Started";
304 
305         case VIR_NETWORK_EVENT_STOPPED:
306             return "Stopped";
307 
308         case VIR_NETWORK_EVENT_LAST:
309             break;
310     }
311 
312     return "unknown";
313 }
314 
315 
316 static const char *
guestAgentLifecycleEventStateToString(int event)317 guestAgentLifecycleEventStateToString(int event)
318 {
319     switch ((virConnectDomainEventAgentLifecycleState) event) {
320     case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_DISCONNECTED:
321         return "Disconnected";
322 
323     case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_CONNECTED:
324         return "Connected";
325 
326     case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_LAST:
327         break;
328     }
329 
330     return "unknown";
331 }
332 
333 
334 static const char *
guestAgentLifecycleEventReasonToString(int event)335 guestAgentLifecycleEventReasonToString(int event)
336 {
337     switch ((virConnectDomainEventAgentLifecycleReason) event) {
338     case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_UNKNOWN:
339         return "Unknown";
340 
341     case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_DOMAIN_STARTED:
342         return "Domain started";
343 
344     case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL:
345         return "Channel event";
346 
347     case VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_LAST:
348         break;
349     }
350 
351     return "unknown";
352 }
353 
354 static const char *
storagePoolEventToString(int event)355 storagePoolEventToString(int event)
356 {
357     switch ((virStoragePoolEventLifecycleType) event) {
358         case VIR_STORAGE_POOL_EVENT_DEFINED:
359             return "Defined";
360         case VIR_STORAGE_POOL_EVENT_UNDEFINED:
361             return "Undefined";
362         case VIR_STORAGE_POOL_EVENT_STARTED:
363             return "Started";
364         case VIR_STORAGE_POOL_EVENT_STOPPED:
365             return "Stopped";
366         case VIR_STORAGE_POOL_EVENT_CREATED:
367             return "Created";
368         case VIR_STORAGE_POOL_EVENT_DELETED:
369             return "Deleted";
370         case VIR_STORAGE_POOL_EVENT_LAST:
371             break;
372     }
373     return "unknown";
374 }
375 
376 static const char *
nodeDeviceEventToString(int event)377 nodeDeviceEventToString(int event)
378 {
379     switch ((virNodeDeviceEventLifecycleType) event) {
380         case VIR_NODE_DEVICE_EVENT_CREATED:
381             return "Created";
382         case VIR_NODE_DEVICE_EVENT_DELETED:
383             return "Deleted";
384         case VIR_NODE_DEVICE_EVENT_DEFINED:
385             return "Defined";
386         case VIR_NODE_DEVICE_EVENT_UNDEFINED:
387             return "Undefined";
388         case VIR_NODE_DEVICE_EVENT_LAST:
389             break;
390     }
391     return "unknown";
392 }
393 
394 
395 static const char *
secretEventToString(int event)396 secretEventToString(int event)
397 {
398     switch ((virSecretEventLifecycleType) event) {
399         case VIR_SECRET_EVENT_DEFINED:
400             return "Defined";
401 
402         case VIR_SECRET_EVENT_UNDEFINED:
403             return "Undefined";
404 
405         case VIR_SECRET_EVENT_LAST:
406             break;
407     }
408 
409     return "unknown";
410 }
411 
412 
413 static int
myDomainEventCallback1(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int event,int detail,void * opaque G_GNUC_UNUSED)414 myDomainEventCallback1(virConnectPtr conn G_GNUC_UNUSED,
415                        virDomainPtr dom,
416                        int event,
417                        int detail,
418                        void *opaque G_GNUC_UNUSED)
419 {
420     printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
421            virDomainGetID(dom), eventToString(event),
422            eventDetailToString(event, detail));
423     return 0;
424 }
425 
426 
427 static int
myDomainEventCallback2(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int event,int detail,void * opaque G_GNUC_UNUSED)428 myDomainEventCallback2(virConnectPtr conn G_GNUC_UNUSED,
429                        virDomainPtr dom,
430                        int event,
431                        int detail,
432                        void *opaque G_GNUC_UNUSED)
433 {
434     printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
435            virDomainGetID(dom), eventToString(event),
436            eventDetailToString(event, detail));
437     return 0;
438 }
439 
440 
441 static int
myDomainEventRebootCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,void * opaque G_GNUC_UNUSED)442 myDomainEventRebootCallback(virConnectPtr conn G_GNUC_UNUSED,
443                             virDomainPtr dom,
444                             void *opaque G_GNUC_UNUSED)
445 {
446     printf("%s EVENT: Domain %s(%d) rebooted\n", __func__, virDomainGetName(dom),
447            virDomainGetID(dom));
448 
449     return 0;
450 }
451 
452 
453 static int
myDomainEventRTCChangeCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,long long offset,void * opaque G_GNUC_UNUSED)454 myDomainEventRTCChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
455                                virDomainPtr dom,
456                                long long offset,
457                                void *opaque G_GNUC_UNUSED)
458 {
459     printf("%s EVENT: Domain %s(%d) rtc change %" PRIdMAX "\n",
460            __func__, virDomainGetName(dom), virDomainGetID(dom),
461            (intmax_t)offset);
462 
463     return 0;
464 }
465 
466 
467 static int
myDomainEventBalloonChangeCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,unsigned long long actual,void * opaque G_GNUC_UNUSED)468 myDomainEventBalloonChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
469                                    virDomainPtr dom,
470                                    unsigned long long actual,
471                                    void *opaque G_GNUC_UNUSED)
472 {
473     printf("%s EVENT: Domain %s(%d) balloon change %" PRIuMAX "KB\n",
474            __func__, virDomainGetName(dom), virDomainGetID(dom), (uintmax_t)actual);
475 
476     return 0;
477 }
478 
479 
480 static int
myDomainEventWatchdogCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int action,void * opaque G_GNUC_UNUSED)481 myDomainEventWatchdogCallback(virConnectPtr conn G_GNUC_UNUSED,
482                               virDomainPtr dom,
483                               int action,
484                               void *opaque G_GNUC_UNUSED)
485 {
486     printf("%s EVENT: Domain %s(%d) watchdog action=%d\n", __func__,
487            virDomainGetName(dom), virDomainGetID(dom), action);
488 
489     return 0;
490 }
491 
492 
493 static int
myDomainEventIOErrorCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * srcPath,const char * devAlias,int action,void * opaque G_GNUC_UNUSED)494 myDomainEventIOErrorCallback(virConnectPtr conn G_GNUC_UNUSED,
495                              virDomainPtr dom,
496                              const char *srcPath,
497                              const char *devAlias,
498                              int action,
499                              void *opaque G_GNUC_UNUSED)
500 {
501     printf("%s EVENT: Domain %s(%d) io error path=%s alias=%s action=%d\n",
502            __func__, virDomainGetName(dom), virDomainGetID(dom),
503            srcPath, devAlias, action);
504 
505     return 0;
506 }
507 
508 
509 static int
myDomainEventIOErrorReasonCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * srcPath,const char * devAlias,int action,const char * reason,void * opaque G_GNUC_UNUSED)510 myDomainEventIOErrorReasonCallback(virConnectPtr conn G_GNUC_UNUSED,
511                                    virDomainPtr dom,
512                                    const char *srcPath,
513                                    const char *devAlias,
514                                    int action,
515                                    const char *reason,
516                                    void *opaque G_GNUC_UNUSED)
517 {
518     printf("%s EVENT: Domain %s(%d) io error (reason) path=%s alias=%s "
519            "action=%d reason=%s\n",
520            __func__, virDomainGetName(dom), virDomainGetID(dom),
521            srcPath, devAlias, action, reason);
522 
523     return 0;
524 }
525 
526 
527 static const char *
graphicsPhaseToStr(int phase)528 graphicsPhaseToStr(int phase)
529 {
530     switch ((virDomainEventGraphicsPhase) phase) {
531     case VIR_DOMAIN_EVENT_GRAPHICS_CONNECT:
532         return "connected";
533 
534     case VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE:
535         return "initialized";
536 
537     case VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT:
538         return "disconnected";
539 
540     case VIR_DOMAIN_EVENT_GRAPHICS_LAST:
541         break;
542     }
543 
544     return "unknown";
545 }
546 
547 
548 static int
myDomainEventGraphicsCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int phase,virDomainEventGraphicsAddressPtr local,virDomainEventGraphicsAddressPtr remote,const char * authScheme,virDomainEventGraphicsSubjectPtr subject,void * opaque G_GNUC_UNUSED)549 myDomainEventGraphicsCallback(virConnectPtr conn G_GNUC_UNUSED,
550                               virDomainPtr dom,
551                               int phase,
552                               virDomainEventGraphicsAddressPtr local,
553                               virDomainEventGraphicsAddressPtr remote,
554                               const char *authScheme,
555                               virDomainEventGraphicsSubjectPtr subject,
556                               void *opaque G_GNUC_UNUSED)
557 {
558     size_t i;
559     printf("%s EVENT: Domain %s(%d) graphics ", __func__, virDomainGetName(dom),
560            virDomainGetID(dom));
561 
562     printf("%s ", graphicsPhaseToStr(phase));
563 
564     printf("local: family=%d node=%s service=%s ",
565            local->family, local->node, local->service);
566     printf("remote: family=%d node=%s service=%s ",
567            remote->family, remote->node, remote->service);
568 
569     printf("auth: %s ", authScheme);
570     for (i = 0; i < subject->nidentity; i++) {
571         printf(" identity: %s=%s",
572                subject->identities[i].type,
573                subject->identities[i].name);
574     }
575     printf("\n");
576 
577     return 0;
578 }
579 
580 
581 static int
myDomainEventControlErrorCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,void * opaque G_GNUC_UNUSED)582 myDomainEventControlErrorCallback(virConnectPtr conn G_GNUC_UNUSED,
583                                   virDomainPtr dom,
584                                   void *opaque G_GNUC_UNUSED)
585 {
586     printf("%s EVENT: Domain %s(%d) control error\n", __func__,
587            virDomainGetName(dom), virDomainGetID(dom));
588 
589     return 0;
590 }
591 
592 static const char *
diskChangeReasonToStr(int reason)593 diskChangeReasonToStr(int reason)
594 {
595     switch ((virConnectDomainEventDiskChangeReason) reason) {
596     case VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START:
597         return "disk empty due to startupPolicy";
598 
599     case VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START:
600         return "disk dropped due to startupPolicy";
601 
602     case VIR_DOMAIN_EVENT_DISK_CHANGE_LAST:
603         break;
604     }
605 
606     return "unknown";
607 }
608 
609 
610 static int
myDomainEventDiskChangeCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * oldSrcPath,const char * newSrcPath,const char * devAlias,int reason,void * opaque G_GNUC_UNUSED)611 myDomainEventDiskChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
612                                 virDomainPtr dom,
613                                 const char *oldSrcPath,
614                                 const char *newSrcPath,
615                                 const char *devAlias,
616                                 int reason,
617                                 void *opaque G_GNUC_UNUSED)
618 {
619     printf("%s EVENT: Domain %s(%d) disk change oldSrcPath: %s newSrcPath: %s "
620            "devAlias: %s reason: %s\n",
621            __func__, virDomainGetName(dom), virDomainGetID(dom),
622            oldSrcPath, newSrcPath, devAlias, diskChangeReasonToStr(reason));
623     return 0;
624 }
625 
626 static const char *
trayChangeReasonToStr(int reason)627 trayChangeReasonToStr(int reason)
628 {
629     switch ((virDomainEventTrayChangeReason) reason) {
630     case VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN:
631         return "open";
632 
633     case VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE:
634         return "close";
635 
636     case VIR_DOMAIN_EVENT_TRAY_CHANGE_LAST:
637         break;
638     }
639 
640     return "unknown";
641 };
642 
643 
644 static int
myDomainEventTrayChangeCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * devAlias,int reason,void * opaque G_GNUC_UNUSED)645 myDomainEventTrayChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
646                                 virDomainPtr dom,
647                                 const char *devAlias,
648                                 int reason,
649                                 void *opaque G_GNUC_UNUSED)
650 {
651     printf("%s EVENT: Domain %s(%d) removable disk's tray change devAlias: %s "
652            "reason: %s\n",
653            __func__, virDomainGetName(dom), virDomainGetID(dom),
654            devAlias, trayChangeReasonToStr(reason));
655     return 0;
656 }
657 
658 
659 static int
myDomainEventPMWakeupCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int reason G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)660 myDomainEventPMWakeupCallback(virConnectPtr conn G_GNUC_UNUSED,
661                               virDomainPtr dom,
662                               int reason G_GNUC_UNUSED,
663                               void *opaque G_GNUC_UNUSED)
664 {
665     printf("%s EVENT: Domain %s(%d) system pmwakeup\n",
666            __func__, virDomainGetName(dom), virDomainGetID(dom));
667     return 0;
668 }
669 
670 
671 static int
myDomainEventPMSuspendCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int reason G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)672 myDomainEventPMSuspendCallback(virConnectPtr conn G_GNUC_UNUSED,
673                                virDomainPtr dom,
674                                int reason G_GNUC_UNUSED,
675                                void *opaque G_GNUC_UNUSED)
676 {
677     printf("%s EVENT: Domain %s(%d) system pmsuspend\n",
678            __func__, virDomainGetName(dom), virDomainGetID(dom));
679     return 0;
680 }
681 
682 
683 static int
myDomainEventPMSuspendDiskCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int reason G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)684 myDomainEventPMSuspendDiskCallback(virConnectPtr conn G_GNUC_UNUSED,
685                                    virDomainPtr dom,
686                                    int reason G_GNUC_UNUSED,
687                                    void *opaque G_GNUC_UNUSED)
688 {
689     printf("%s EVENT: Domain %s(%d) system pmsuspend-disk\n",
690            __func__, virDomainGetName(dom), virDomainGetID(dom));
691     return 0;
692 }
693 
694 
695 static int
myDomainEventDeviceRemovedCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * devAlias,void * opaque G_GNUC_UNUSED)696 myDomainEventDeviceRemovedCallback(virConnectPtr conn G_GNUC_UNUSED,
697                                    virDomainPtr dom,
698                                    const char *devAlias,
699                                    void *opaque G_GNUC_UNUSED)
700 {
701     printf("%s EVENT: Domain %s(%d) device removed: %s\n",
702            __func__, virDomainGetName(dom), virDomainGetID(dom), devAlias);
703     return 0;
704 }
705 
706 
707 static int
myNetworkEventCallback(virConnectPtr conn G_GNUC_UNUSED,virNetworkPtr dom,int event,int detail,void * opaque G_GNUC_UNUSED)708 myNetworkEventCallback(virConnectPtr conn G_GNUC_UNUSED,
709                        virNetworkPtr dom,
710                        int event,
711                        int detail,
712                        void *opaque G_GNUC_UNUSED)
713 {
714     printf("%s EVENT: Network %s %s %d\n", __func__, virNetworkGetName(dom),
715            networkEventToString(event), detail);
716     return 0;
717 }
718 
719 static int
myStoragePoolEventCallback(virConnectPtr conn G_GNUC_UNUSED,virStoragePoolPtr pool,int event,int detail,void * opaque G_GNUC_UNUSED)720 myStoragePoolEventCallback(virConnectPtr conn G_GNUC_UNUSED,
721                            virStoragePoolPtr pool,
722                            int event,
723                            int detail,
724                            void *opaque G_GNUC_UNUSED)
725 {
726     printf("%s EVENT: Storage pool %s %s %d\n", __func__,
727            virStoragePoolGetName(pool),
728            storagePoolEventToString(event),
729            detail);
730     return 0;
731 }
732 
733 
734 static int
myStoragePoolEventRefreshCallback(virConnectPtr conn G_GNUC_UNUSED,virStoragePoolPtr pool,void * opaque G_GNUC_UNUSED)735 myStoragePoolEventRefreshCallback(virConnectPtr conn G_GNUC_UNUSED,
736                                   virStoragePoolPtr pool,
737                                   void *opaque G_GNUC_UNUSED)
738 {
739     printf("%s EVENT: Storage pool %s refresh\n", __func__,
740            virStoragePoolGetName(pool));
741     return 0;
742 }
743 
744 
745 static int
myNodeDeviceEventCallback(virConnectPtr conn G_GNUC_UNUSED,virNodeDevicePtr dev,int event,int detail,void * opaque G_GNUC_UNUSED)746 myNodeDeviceEventCallback(virConnectPtr conn G_GNUC_UNUSED,
747                           virNodeDevicePtr dev,
748                           int event,
749                           int detail,
750                           void *opaque G_GNUC_UNUSED)
751 {
752     printf("%s EVENT: Node device %s %s %d\n", __func__,
753            virNodeDeviceGetName(dev),
754            nodeDeviceEventToString(event),
755            detail);
756     return 0;
757 }
758 
759 
760 static int
myNodeDeviceEventUpdateCallback(virConnectPtr conn G_GNUC_UNUSED,virNodeDevicePtr dev,void * opaque G_GNUC_UNUSED)761 myNodeDeviceEventUpdateCallback(virConnectPtr conn G_GNUC_UNUSED,
762                                 virNodeDevicePtr dev,
763                                 void *opaque G_GNUC_UNUSED)
764 {
765     printf("%s EVENT: Node device %s update\n", __func__,
766            virNodeDeviceGetName(dev));
767     return 0;
768 }
769 
770 
771 static int
mySecretEventCallback(virConnectPtr conn G_GNUC_UNUSED,virSecretPtr secret,int event,int detail,void * opaque G_GNUC_UNUSED)772 mySecretEventCallback(virConnectPtr conn G_GNUC_UNUSED,
773                       virSecretPtr secret,
774                       int event,
775                       int detail,
776                       void *opaque G_GNUC_UNUSED)
777 {
778     char uuid[VIR_UUID_STRING_BUFLEN];
779     virSecretGetUUIDString(secret, uuid);
780     printf("%s EVENT: Secret %s %s %d\n", __func__,
781            uuid,
782            secretEventToString(event),
783            detail);
784     return 0;
785 }
786 
787 
788 static int
mySecretEventValueChanged(virConnectPtr conn G_GNUC_UNUSED,virSecretPtr secret,void * opaque G_GNUC_UNUSED)789 mySecretEventValueChanged(virConnectPtr conn G_GNUC_UNUSED,
790                           virSecretPtr secret,
791                           void *opaque G_GNUC_UNUSED)
792 {
793     char uuid[VIR_UUID_STRING_BUFLEN];
794     virSecretGetUUIDString(secret, uuid);
795     printf("%s EVENT: Secret %s\n", __func__, uuid);
796     return 0;
797 }
798 
799 
800 static void
eventTypedParamsPrint(virTypedParameterPtr params,int nparams)801 eventTypedParamsPrint(virTypedParameterPtr params,
802                       int nparams)
803 {
804     size_t i;
805 
806     for (i = 0; i < nparams; i++) {
807         switch (params[i].type) {
808         case VIR_TYPED_PARAM_INT:
809             printf("\t%s: %d\n", params[i].field, params[i].value.i);
810             break;
811         case VIR_TYPED_PARAM_UINT:
812             printf("\t%s: %u\n", params[i].field, params[i].value.ui);
813             break;
814         case VIR_TYPED_PARAM_LLONG:
815             printf("\t%s: %" PRId64 "\n", params[i].field,
816                    (int64_t) params[i].value.l);
817             break;
818         case VIR_TYPED_PARAM_ULLONG:
819             printf("\t%s: %" PRIu64 "\n", params[i].field,
820                    (uint64_t) params[i].value.ul);
821             break;
822         case VIR_TYPED_PARAM_DOUBLE:
823             printf("\t%s: %g\n", params[i].field, params[i].value.d);
824             break;
825         case VIR_TYPED_PARAM_BOOLEAN:
826             printf("\t%s: %d\n", params[i].field, params[i].value.b);
827             break;
828         case VIR_TYPED_PARAM_STRING:
829             printf("\t%s: %s\n", params[i].field, params[i].value.s);
830             break;
831         default:
832             printf("\t%s: unknown type\n", params[i].field);
833         }
834     }
835 }
836 
837 
838 static int
myDomainEventTunableCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,virTypedParameterPtr params,int nparams,void * opaque G_GNUC_UNUSED)839 myDomainEventTunableCallback(virConnectPtr conn G_GNUC_UNUSED,
840                              virDomainPtr dom,
841                              virTypedParameterPtr params,
842                              int nparams,
843                              void *opaque G_GNUC_UNUSED)
844 {
845     printf("%s EVENT: Domain %s(%d) tunable updated:\n",
846            __func__, virDomainGetName(dom), virDomainGetID(dom));
847 
848     eventTypedParamsPrint(params, nparams);
849 
850     return 0;
851 }
852 
853 
854 static int
myDomainEventAgentLifecycleCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int state,int reason,void * opaque G_GNUC_UNUSED)855 myDomainEventAgentLifecycleCallback(virConnectPtr conn G_GNUC_UNUSED,
856                                     virDomainPtr dom,
857                                     int state,
858                                     int reason,
859                                     void *opaque G_GNUC_UNUSED)
860 {
861     printf("%s EVENT: Domain %s(%d) guest agent state changed: %s reason: %s\n",
862            __func__, virDomainGetName(dom), virDomainGetID(dom),
863            guestAgentLifecycleEventStateToString(state),
864            guestAgentLifecycleEventReasonToString(reason));
865 
866     return 0;
867 }
868 
869 
870 static int
myDomainEventDeviceAddedCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * devAlias,void * opaque G_GNUC_UNUSED)871 myDomainEventDeviceAddedCallback(virConnectPtr conn G_GNUC_UNUSED,
872                                  virDomainPtr dom,
873                                  const char *devAlias,
874                                  void *opaque G_GNUC_UNUSED)
875 {
876     printf("%s EVENT: Domain %s(%d) device added: %s\n",
877            __func__, virDomainGetName(dom), virDomainGetID(dom), devAlias);
878     return 0;
879 }
880 
881 
882 static const char *
blockJobTypeToStr(int type)883 blockJobTypeToStr(int type)
884 {
885     switch ((virDomainBlockJobType) type) {
886     case VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN:
887     case VIR_DOMAIN_BLOCK_JOB_TYPE_LAST:
888         break;
889 
890     case VIR_DOMAIN_BLOCK_JOB_TYPE_PULL:
891         return "block pull";
892 
893     case VIR_DOMAIN_BLOCK_JOB_TYPE_COPY:
894         return "block copy";
895 
896     case VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT:
897         return "block commit";
898 
899     case VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT:
900         return "active layer block commit";
901 
902     case VIR_DOMAIN_BLOCK_JOB_TYPE_BACKUP:
903         return "backup";
904     }
905 
906     return "unknown";
907 }
908 
909 
910 static const char *
blockJobStatusToStr(int status)911 blockJobStatusToStr(int status)
912 {
913     switch ((virConnectDomainEventBlockJobStatus) status) {
914     case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
915         return "completed";
916 
917     case VIR_DOMAIN_BLOCK_JOB_FAILED:
918         return "failed";
919 
920     case VIR_DOMAIN_BLOCK_JOB_CANCELED:
921         return "cancelled";
922 
923     case VIR_DOMAIN_BLOCK_JOB_READY:
924         return "ready";
925 
926     case VIR_DOMAIN_BLOCK_JOB_LAST:
927         break;
928     }
929 
930     return "unknown";
931 }
932 
933 
934 static int
myDomainEventBlockJobCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * disk,int type,int status,void * opaque)935 myDomainEventBlockJobCallback(virConnectPtr conn G_GNUC_UNUSED,
936                               virDomainPtr dom,
937                               const char *disk,
938                               int type,
939                               int status,
940                               void *opaque)
941 {
942     const char *eventName = opaque;
943 
944     printf("%s EVENT: Domain %s(%d) block job callback '%s' disk '%s', "
945            "type '%s' status '%s'\n",
946            __func__, virDomainGetName(dom), virDomainGetID(dom), eventName,
947            disk, blockJobTypeToStr(type), blockJobStatusToStr(status));
948     return 0;
949 }
950 
951 
952 static int
myDomainEventBlockThresholdCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * dev,const char * path,unsigned long long threshold,unsigned long long excess,void * opaque G_GNUC_UNUSED)953 myDomainEventBlockThresholdCallback(virConnectPtr conn G_GNUC_UNUSED,
954                                     virDomainPtr dom,
955                                     const char *dev,
956                                     const char *path,
957                                     unsigned long long threshold,
958                                     unsigned long long excess,
959                                     void *opaque G_GNUC_UNUSED)
960 {
961     /* Casts to uint64_t to work around mingw not knowing %lld */
962     printf("%s EVENT: Domain %s(%d) block threshold callback dev '%s'(%s), "
963            "threshold: '%" PRIu64 "', excess: '%" PRIu64 "'\n",
964            __func__, virDomainGetName(dom), virDomainGetID(dom),
965            dev, NULLSTR(path), (uint64_t)threshold, (uint64_t)excess);
966     return 0;
967 }
968 
969 
970 static int
myDomainEventMemoryFailureCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int recipient,int action,unsigned int flags,void * opaque G_GNUC_UNUSED)971 myDomainEventMemoryFailureCallback(virConnectPtr conn G_GNUC_UNUSED,
972                                    virDomainPtr dom,
973                                    int recipient,
974                                    int action,
975                                    unsigned int flags,
976                                    void *opaque G_GNUC_UNUSED)
977 {
978     printf("%s EVENT: Domain %s(%d) memory failure: recipient '%d', "
979            "aciont '%d', flags '%d'\n", __func__, virDomainGetName(dom),
980            virDomainGetID(dom), recipient, action, flags);
981     return 0;
982 }
983 
984 
985 static int
myDomainEventMemoryDeviceSizeChangeCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * alias,unsigned long long size,void * opaque G_GNUC_UNUSED)986 myDomainEventMemoryDeviceSizeChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
987                                             virDomainPtr dom,
988                                             const char *alias,
989                                             unsigned long long size,
990                                             void *opaque G_GNUC_UNUSED)
991 {
992     /* Casts to uint64_t to work around mingw not knowing %lld */
993     printf("%s EVENT: Domain %s(%d) memory device size change: "
994            "alias: '%s' new size %" PRIu64 "'\n",
995            __func__, virDomainGetName(dom), virDomainGetID(dom),
996            alias, (uint64_t)size);
997     return 0;
998 }
999 
1000 
1001 static int
myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int iteration,void * opaque G_GNUC_UNUSED)1002 myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED,
1003                                         virDomainPtr dom,
1004                                         int iteration,
1005                                         void *opaque G_GNUC_UNUSED)
1006 {
1007     printf("%s EVENT: Domain %s(%d) migration iteration '%d'\n",
1008            __func__, virDomainGetName(dom), virDomainGetID(dom), iteration);
1009     return 0;
1010 }
1011 
1012 
1013 static int
myDomainEventJobCompletedCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,virTypedParameterPtr params,int nparams,void * opaque G_GNUC_UNUSED)1014 myDomainEventJobCompletedCallback(virConnectPtr conn G_GNUC_UNUSED,
1015                                   virDomainPtr dom,
1016                                   virTypedParameterPtr params,
1017                                   int nparams,
1018                                   void *opaque G_GNUC_UNUSED)
1019 {
1020     printf("%s EVENT: Domain %s(%d) job completed:\n",
1021            __func__, virDomainGetName(dom), virDomainGetID(dom));
1022 
1023     eventTypedParamsPrint(params, nparams);
1024 
1025     return 0;
1026 }
1027 
1028 
1029 static int
myDomainEventDeviceRemovalFailedCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,const char * devAlias,void * opaque G_GNUC_UNUSED)1030 myDomainEventDeviceRemovalFailedCallback(virConnectPtr conn G_GNUC_UNUSED,
1031                                          virDomainPtr dom,
1032                                          const char *devAlias,
1033                                          void *opaque G_GNUC_UNUSED)
1034 {
1035     printf("%s EVENT: Domain %s(%d) device removal failed: %s\n",
1036            __func__, virDomainGetName(dom), virDomainGetID(dom), devAlias);
1037     return 0;
1038 }
1039 
1040 
1041 static const char *
metadataTypeToStr(int status)1042 metadataTypeToStr(int status)
1043 {
1044     switch ((virDomainMetadataType) status) {
1045     case VIR_DOMAIN_METADATA_DESCRIPTION:
1046         return "description";
1047 
1048     case VIR_DOMAIN_METADATA_TITLE:
1049         return "title";
1050 
1051     case VIR_DOMAIN_METADATA_ELEMENT:
1052         return "element";
1053 
1054     case VIR_DOMAIN_METADATA_LAST:
1055         break;
1056     }
1057 
1058     return "unknown";
1059 }
1060 
1061 static int
myDomainEventMetadataChangeCallback(virConnectPtr conn G_GNUC_UNUSED,virDomainPtr dom,int type,const char * nsuri,void * opaque G_GNUC_UNUSED)1062 myDomainEventMetadataChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
1063                                     virDomainPtr dom,
1064                                     int type,
1065                                     const char *nsuri,
1066                                     void *opaque G_GNUC_UNUSED)
1067 {
1068     const char *typestr = metadataTypeToStr(type);
1069     printf("%s EVENT: Domain %s(%d) metadata type: %s (%s)\n",
1070            __func__, virDomainGetName(dom), virDomainGetID(dom), typestr, nsuri ? nsuri : "n/a");
1071     return 0;
1072 }
1073 
1074 
1075 
1076 static void
myFreeFunc(void * opaque)1077 myFreeFunc(void *opaque)
1078 {
1079     char *str = opaque;
1080     printf("%s: Freeing [%s]\n", __func__, str);
1081     free(str);
1082 }
1083 
1084 
1085 /* main test functions */
1086 static void
stop(int sig)1087 stop(int sig)
1088 {
1089     printf("Exiting on signal %d\n", sig);
1090     run = 0;
1091 }
1092 
1093 
1094 struct domainEventData {
1095     int event;
1096     int id;
1097     virConnectDomainEventGenericCallback cb;
1098     const char *name;
1099 };
1100 
1101 
1102 #define DOMAIN_EVENT(event, callback) \
1103     {event, -1, VIR_DOMAIN_EVENT_CALLBACK(callback), #event}
1104 
1105 struct domainEventData domainEvents[] = {
1106     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_LIFECYCLE, myDomainEventCallback2),
1107     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_REBOOT, myDomainEventRebootCallback),
1108     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_RTC_CHANGE, myDomainEventRTCChangeCallback),
1109     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_WATCHDOG, myDomainEventWatchdogCallback),
1110     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_IO_ERROR, myDomainEventIOErrorCallback),
1111     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_GRAPHICS, myDomainEventGraphicsCallback),
1112     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, myDomainEventIOErrorReasonCallback),
1113     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR, myDomainEventControlErrorCallback),
1114     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB, myDomainEventBlockJobCallback),
1115     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DISK_CHANGE, myDomainEventDiskChangeCallback),
1116     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_TRAY_CHANGE, myDomainEventTrayChangeCallback),
1117     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_PMWAKEUP, myDomainEventPMWakeupCallback),
1118     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_PMSUSPEND, myDomainEventPMSuspendCallback),
1119     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, myDomainEventBalloonChangeCallback),
1120     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK, myDomainEventPMSuspendDiskCallback),
1121     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, myDomainEventDeviceRemovedCallback),
1122     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2, myDomainEventBlockJobCallback),
1123     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_TUNABLE, myDomainEventTunableCallback),
1124     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE, myDomainEventAgentLifecycleCallback),
1125     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_ADDED, myDomainEventDeviceAddedCallback),
1126     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION, myDomainEventMigrationIterationCallback),
1127     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, myDomainEventJobCompletedCallback),
1128     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback),
1129     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback),
1130     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback),
1131     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE, myDomainEventMemoryFailureCallback),
1132     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE, myDomainEventMemoryDeviceSizeChangeCallback),
1133 };
1134 
1135 struct storagePoolEventData {
1136     int event;
1137     int id;
1138     virConnectStoragePoolEventGenericCallback cb;
1139     const char *name;
1140 };
1141 
1142 #define STORAGE_POOL_EVENT(event, callback) \
1143     {event, -1, VIR_STORAGE_POOL_EVENT_CALLBACK(callback), #event}
1144 
1145 struct storagePoolEventData storagePoolEvents[] = {
1146     STORAGE_POOL_EVENT(VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE, myStoragePoolEventCallback),
1147     STORAGE_POOL_EVENT(VIR_STORAGE_POOL_EVENT_ID_REFRESH, myStoragePoolEventRefreshCallback),
1148 };
1149 
1150 struct nodeDeviceEventData {
1151     int event;
1152     int id;
1153     virConnectNodeDeviceEventGenericCallback cb;
1154     const char *name;
1155 };
1156 
1157 #define NODE_DEVICE_EVENT(event, callback) \
1158     {event, -1, VIR_NODE_DEVICE_EVENT_CALLBACK(callback), #event}
1159 
1160 struct nodeDeviceEventData nodeDeviceEvents[] = {
1161     NODE_DEVICE_EVENT(VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE, myNodeDeviceEventCallback),
1162     NODE_DEVICE_EVENT(VIR_NODE_DEVICE_EVENT_ID_UPDATE, myNodeDeviceEventUpdateCallback),
1163 };
1164 
1165 struct secretEventData {
1166     int event;
1167     int id;
1168     virConnectSecretEventGenericCallback cb;
1169     const char *name;
1170 };
1171 
1172 #define SECRET_EVENT(event, callback) \
1173     {event, -1, VIR_SECRET_EVENT_CALLBACK(callback), #event}
1174 
1175 struct secretEventData secretEvents[] = {
1176     SECRET_EVENT(VIR_SECRET_EVENT_ID_LIFECYCLE, mySecretEventCallback),
1177     SECRET_EVENT(VIR_SECRET_EVENT_ID_VALUE_CHANGED, mySecretEventValueChanged),
1178 };
1179 
1180 /* make sure that the events are kept in sync */
1181 G_STATIC_ASSERT(G_N_ELEMENTS(domainEvents) == VIR_DOMAIN_EVENT_ID_LAST);
1182 G_STATIC_ASSERT(G_N_ELEMENTS(storagePoolEvents) == VIR_STORAGE_POOL_EVENT_ID_LAST);
1183 G_STATIC_ASSERT(G_N_ELEMENTS(nodeDeviceEvents) == VIR_NODE_DEVICE_EVENT_ID_LAST);
1184 G_STATIC_ASSERT(G_N_ELEMENTS(secretEvents) == VIR_SECRET_EVENT_ID_LAST);
1185 
1186 int
main(int argc,char ** argv)1187 main(int argc, char **argv)
1188 {
1189     int ret = EXIT_FAILURE;
1190     virConnectPtr dconn = NULL;
1191     int callback1ret = -1;
1192     int callback16ret = -1;
1193     size_t i;
1194 
1195     if (argc > 1 && STREQ(argv[1], "--help")) {
1196         printf("%s uri\n", argv[0]);
1197         goto cleanup;
1198     }
1199 
1200     if (virInitialize() < 0) {
1201         fprintf(stderr, "Failed to initialize libvirt");
1202         goto cleanup;
1203     }
1204 
1205     if (virEventRegisterDefaultImpl() < 0) {
1206         fprintf(stderr, "Failed to register event implementation: %s\n",
1207                 virGetLastErrorMessage());
1208         goto cleanup;
1209     }
1210 
1211     dconn = virConnectOpenAuth(argc > 1 ? argv[1] : NULL,
1212                                virConnectAuthPtrDefault,
1213                                VIR_CONNECT_RO);
1214     if (!dconn) {
1215         printf("error opening\n");
1216         goto cleanup;
1217     }
1218 
1219     if (virConnectRegisterCloseCallback(dconn,
1220                                         connectClose, NULL, NULL) < 0) {
1221         fprintf(stderr, "Unable to register close callback\n");
1222         goto cleanup;
1223     }
1224 
1225     /* The ideal program would use sigaction to set this handler, but
1226      * this way is portable to mingw. */
1227     signal(SIGTERM, stop);
1228     signal(SIGINT, stop);
1229 
1230     printf("Registering event callbacks\n");
1231 
1232     callback1ret = virConnectDomainEventRegister(dconn, myDomainEventCallback1,
1233                                                  strdup("callback 1"), myFreeFunc);
1234 
1235     /* register common domain callbacks */
1236     for (i = 0; i < G_N_ELEMENTS(domainEvents); i++) {
1237         struct domainEventData *event = domainEvents + i;
1238 
1239         event->id = virConnectDomainEventRegisterAny(dconn, NULL,
1240                                                      event->event,
1241                                                      event->cb,
1242                                                      strdup(event->name),
1243                                                      myFreeFunc);
1244 
1245         if (event->id < 0) {
1246             fprintf(stderr, "Failed to register event '%s'\n", event->name);
1247             goto cleanup;
1248         }
1249     }
1250 
1251     callback16ret = virConnectNetworkEventRegisterAny(dconn,
1252                                                       NULL,
1253                                                       VIR_NETWORK_EVENT_ID_LIFECYCLE,
1254                                                       VIR_NETWORK_EVENT_CALLBACK(myNetworkEventCallback),
1255                                                       strdup("net callback"), myFreeFunc);
1256 
1257     /* register common storage pool callbacks */
1258     for (i = 0; i < G_N_ELEMENTS(storagePoolEvents); i++) {
1259         struct storagePoolEventData *event = storagePoolEvents + i;
1260 
1261         event->id = virConnectStoragePoolEventRegisterAny(dconn, NULL,
1262                                                           event->event,
1263                                                           event->cb,
1264                                                           strdup(event->name),
1265                                                           myFreeFunc);
1266 
1267         if (event->id < 0) {
1268             fprintf(stderr, "Failed to register event '%s'\n", event->name);
1269             goto cleanup;
1270         }
1271     }
1272 
1273     /* register common node device callbacks */
1274     for (i = 0; i < G_N_ELEMENTS(nodeDeviceEvents); i++) {
1275         struct nodeDeviceEventData *event = nodeDeviceEvents + i;
1276 
1277         event->id = virConnectNodeDeviceEventRegisterAny(dconn, NULL,
1278                                                          event->event,
1279                                                          event->cb,
1280                                                          strdup(event->name),
1281                                                          myFreeFunc);
1282 
1283         if (event->id < 0) {
1284             fprintf(stderr, "Failed to register event '%s'\n", event->name);
1285             goto cleanup;
1286         }
1287     }
1288 
1289     /* register common secret callbacks */
1290     for (i = 0; i < G_N_ELEMENTS(secretEvents); i++) {
1291         struct secretEventData *event = secretEvents + i;
1292 
1293         event->id = virConnectSecretEventRegisterAny(dconn, NULL,
1294                                                      event->event,
1295                                                      event->cb,
1296                                                      strdup(event->name),
1297                                                      myFreeFunc);
1298 
1299         if (event->id < 0) {
1300             fprintf(stderr, "Failed to register event '%s'\n", event->name);
1301             goto cleanup;
1302         }
1303     }
1304 
1305     if ((callback1ret == -1) ||
1306         (callback16ret == -1))
1307         goto cleanup;
1308 
1309     if (virConnectSetKeepAlive(dconn, 5, 3) < 0) {
1310         fprintf(stderr, "Failed to start keepalive protocol: %s\n",
1311                 virGetLastErrorMessage());
1312         run = 0;
1313     }
1314 
1315     while (run) {
1316         if (virEventRunDefaultImpl() < 0) {
1317             fprintf(stderr, "Failed to run event loop: %s\n",
1318                     virGetLastErrorMessage());
1319         }
1320     }
1321 
1322     printf("Deregistering event callbacks\n");
1323     virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
1324     virConnectNetworkEventDeregisterAny(dconn, callback16ret);
1325 
1326 
1327     printf("Deregistering domain event callbacks\n");
1328     for (i = 0; i < G_N_ELEMENTS(domainEvents); i++) {
1329         if (domainEvents[i].id > 0)
1330             virConnectDomainEventDeregisterAny(dconn, domainEvents[i].id);
1331     }
1332 
1333 
1334     printf("Deregistering storage pool event callbacks\n");
1335     for (i = 0; i < G_N_ELEMENTS(storagePoolEvents); i++) {
1336         if (storagePoolEvents[i].id > 0)
1337             virConnectStoragePoolEventDeregisterAny(dconn, storagePoolEvents[i].id);
1338     }
1339 
1340 
1341     printf("Deregistering node device event callbacks\n");
1342     for (i = 0; i < G_N_ELEMENTS(nodeDeviceEvents); i++) {
1343         if (nodeDeviceEvents[i].id > 0)
1344             virConnectNodeDeviceEventDeregisterAny(dconn, nodeDeviceEvents[i].id);
1345     }
1346 
1347     printf("Deregistering secret event callbacks\n");
1348     for (i = 0; i < G_N_ELEMENTS(secretEvents); i++) {
1349         if (secretEvents[i].id > 0)
1350             virConnectSecretEventDeregisterAny(dconn, secretEvents[i].id);
1351     }
1352 
1353 
1354     virConnectUnregisterCloseCallback(dconn, connectClose);
1355     ret = EXIT_SUCCESS;
1356 
1357 
1358  cleanup:
1359     if (dconn) {
1360         printf("Closing connection: ");
1361         if (virConnectClose(dconn) < 0)
1362             printf("failed\n");
1363         printf("done\n");
1364     }
1365 
1366     return ret;
1367 }
1368