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