event-test.c 23.5 KB
Newer Older
1
#include <config.h>
2

3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <signal.h>
7
#include <inttypes.h>
8

9 10
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
11

12
#define VIR_DEBUG(fmt) printf("%s:%d: " fmt "\n", __func__, __LINE__)
13
#define STREQ(a,b) (strcmp(a,b) == 0)
14

15 16 17
#ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__((__unused__))
#endif
18

19 20
int run = 1;

21 22 23
/* Prototypes */
const char *eventToString(int event);
int myEventAddHandleFunc  (int fd, int event,
24 25 26
                           virEventHandleCallback cb,
                           void *opaque,
                           virFreeCallback ff);
27 28
void myEventUpdateHandleFunc(int watch, int event);
int  myEventRemoveHandleFunc(int watch);
29

30 31 32 33
int myEventAddTimeoutFunc(int timeout,
                          virEventTimeoutCallback cb,
                          void *opaque,
                          virFreeCallback ff);
34 35 36 37 38 39 40 41 42 43
void myEventUpdateTimeoutFunc(int timer, int timout);
int myEventRemoveTimeoutFunc(int timer);

int myEventHandleTypeToPollEvent(virEventHandleType events);
virEventHandleType myPollEventToEventHandleType(int events);

void usage(const char *pname);

/* Callback functions */

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

static void connectClose(virConnectPtr conn ATTRIBUTE_UNUSED,
                         int reason,
                         void *opaque ATTRIBUTE_UNUSED)
{
    switch (reason) {
    case VIR_CONNECT_CLOSE_REASON_ERROR:
        fprintf(stderr, "Connection closed due to I/O error\n");
        break;
    case VIR_CONNECT_CLOSE_REASON_EOF:
        fprintf(stderr, "Connection closed due to end of file\n");
        break;
    case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
        fprintf(stderr, "Connection closed due to keepalive timeout\n");
        break;
    case VIR_CONNECT_CLOSE_REASON_CLIENT:
        fprintf(stderr, "Connection closed due to client request\n");
        break;
    default:
        fprintf(stderr, "Connection closed due to unknown reason\n");
        break;
    };
    run = 0;
}

69
const char *eventToString(int event) {
70
    const char *ret = "";
71
    switch ((virDomainEventType) event) {
72 73
        case VIR_DOMAIN_EVENT_DEFINED:
            ret ="Defined";
74
            break;
75 76
        case VIR_DOMAIN_EVENT_UNDEFINED:
            ret ="Undefined";
77 78 79 80 81 82 83 84 85 86 87 88 89
            break;
        case VIR_DOMAIN_EVENT_STARTED:
            ret ="Started";
            break;
        case VIR_DOMAIN_EVENT_SUSPENDED:
            ret ="Suspended";
            break;
        case VIR_DOMAIN_EVENT_RESUMED:
            ret ="Resumed";
            break;
        case VIR_DOMAIN_EVENT_STOPPED:
            ret ="Stopped";
            break;
90 91 92
        case VIR_DOMAIN_EVENT_SHUTDOWN:
            ret = "Shutdown";
            break;
J
Jiri Denemark 已提交
93 94 95
        case VIR_DOMAIN_EVENT_PMSUSPENDED:
            ret = "PMSuspended";
            break;
96 97 98 99 100 101
    }
    return ret;
}

static const char *eventDetailToString(int event, int detail) {
    const char *ret = "";
102
    switch ((virDomainEventType) event) {
103 104 105 106 107 108 109 110 111
        case VIR_DOMAIN_EVENT_DEFINED:
            if (detail == VIR_DOMAIN_EVENT_DEFINED_ADDED)
                ret = "Added";
            else if (detail == VIR_DOMAIN_EVENT_DEFINED_UPDATED)
                ret = "Updated";
            break;
        case VIR_DOMAIN_EVENT_UNDEFINED:
            if (detail == VIR_DOMAIN_EVENT_UNDEFINED_REMOVED)
                ret = "Removed";
112
            break;
113
        case VIR_DOMAIN_EVENT_STARTED:
114
            switch ((virDomainEventStartedDetailType) detail) {
115 116 117 118 119 120 121 122 123
            case VIR_DOMAIN_EVENT_STARTED_BOOTED:
                ret = "Booted";
                break;
            case VIR_DOMAIN_EVENT_STARTED_MIGRATED:
                ret = "Migrated";
                break;
            case VIR_DOMAIN_EVENT_STARTED_RESTORED:
                ret = "Restored";
                break;
124 125 126
            case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
127 128 129
            case VIR_DOMAIN_EVENT_STARTED_WAKEUP:
                ret = "Event wakeup";
                break;
130 131 132
            }
            break;
        case VIR_DOMAIN_EVENT_SUSPENDED:
133
            switch ((virDomainEventSuspendedDetailType) detail) {
134
            case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED:
135
                ret = "Paused";
136 137
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
138
                ret = "Migrated";
139 140 141 142 143 144 145 146 147 148 149 150 151
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR:
                ret = "I/O Error";
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG:
                ret = "Watchdog";
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED:
                ret = "Restored";
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
152 153 154
            case VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR:
                ret = "API error";
                break;
155
            }
156 157
            break;
        case VIR_DOMAIN_EVENT_RESUMED:
158
            switch ((virDomainEventResumedDetailType) detail) {
159
            case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED:
160
                ret = "Unpaused";
161 162
                break;
            case VIR_DOMAIN_EVENT_RESUMED_MIGRATED:
163
                ret = "Migrated";
164 165 166 167 168
                break;
            case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
            }
169 170
            break;
        case VIR_DOMAIN_EVENT_STOPPED:
171
            switch ((virDomainEventStoppedDetailType) detail) {
172 173 174 175 176 177 178 179 180 181 182 183 184
            case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN:
                ret = "Shutdown";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_DESTROYED:
                ret = "Destroyed";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_CRASHED:
                ret = "Crashed";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_MIGRATED:
                ret = "Migrated";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_SAVED:
185
                ret = "Saved";
186 187 188 189
                break;
            case VIR_DOMAIN_EVENT_STOPPED_FAILED:
                ret = "Failed";
                break;
190 191 192
            case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
193
            }
194
            break;
195 196 197 198 199 200 201
        case VIR_DOMAIN_EVENT_SHUTDOWN:
            switch ((virDomainEventShutdownDetailType) detail) {
            case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
                ret = "Finished";
                break;
            }
            break;
J
Jiri Denemark 已提交
202 203 204 205 206
        case VIR_DOMAIN_EVENT_PMSUSPENDED:
            switch ((virDomainEventPMSuspendedDetailType) detail) {
            case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY:
                ret = "Memory";
                break;
207 208 209
            case VIR_DOMAIN_EVENT_PMSUSPENDED_DISK:
                ret = "Disk";
                break;
J
Jiri Denemark 已提交
210 211
            }
            break;
212 213 214 215
    }
    return ret;
}

216 217 218 219 220
static int myDomainEventCallback1(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virDomainPtr dom,
                                  int event,
                                  int detail,
                                  void *opaque ATTRIBUTE_UNUSED)
221
{
222
    printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
223 224
           virDomainGetID(dom), eventToString(event),
           eventDetailToString(event, detail));
225 226 227
    return 0;
}

228 229 230 231 232
static int myDomainEventCallback2(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virDomainPtr dom,
                                  int event,
                                  int detail,
                                  void *opaque ATTRIBUTE_UNUSED)
233
{
234
    printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
235 236
           virDomainGetID(dom), eventToString(event),
           eventDetailToString(event, detail));
237 238 239
    return 0;
}

240 241 242 243 244 245 246 247 248 249
static int myDomainEventRebootCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                       virDomainPtr dom,
                                       void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) rebooted\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom));

    return 0;
}

250 251 252 253 254
static int myDomainEventRTCChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          long long offset,
                                          void *opaque ATTRIBUTE_UNUSED)
{
255 256 257 258 259 260 261 262 263 264
    char *str = NULL;
    /* HACK: use asprintf since we have gnulib's wrapper for %lld on Win32
     * but don't have a printf() replacement with %lld */
    if (asprintf(&str, "%s EVENT: Domain %s(%d) rtc change %lld\n",
                 __func__, virDomainGetName(dom),
                 virDomainGetID(dom), offset) < 0)
        return 0;

    printf("%s", str);
    free(str);
265 266 267 268

    return 0;
}

269 270 271 272 273 274 275 276 277 278 279
static int myDomainEventBalloonChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                              virDomainPtr dom,
                                              unsigned long long actual,
                                              void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) balloon change %" PRIuMAX "KB\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom), (uintmax_t)actual);

    return 0;
}

280 281 282 283 284 285 286 287 288 289 290
static int myDomainEventWatchdogCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         int action,
                                         void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) watchdog action=%d\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom), action);

    return 0;
}

291 292 293 294 295 296 297 298 299 300 301 302 303
static int myDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                        virDomainPtr dom,
                                        const char *srcPath,
                                        const char *devAlias,
                                        int action,
                                        void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) io error path=%s alias=%s action=%d\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom), srcPath, devAlias, action);

    return 0;
}

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
static int myDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         int phase,
                                         virDomainEventGraphicsAddressPtr local,
                                         virDomainEventGraphicsAddressPtr remote,
                                         const char *authScheme,
                                         virDomainEventGraphicsSubjectPtr subject,
                                         void *opaque ATTRIBUTE_UNUSED)
{
    int i;
    printf("%s EVENT: Domain %s(%d) graphics ", __func__, virDomainGetName(dom),
           virDomainGetID(dom));

    switch (phase) {
    case VIR_DOMAIN_EVENT_GRAPHICS_CONNECT:
        printf("connected ");
        break;
    case VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE:
        printf("initialized ");
        break;
    case VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT:
        printf("disconnected ");
        break;
    }

    printf("local: family=%d node=%s service=%s ",
           local->family, local->node, local->service);
    printf("remote: family=%d node=%s service=%s ",
           remote->family, remote->node, remote->service);

    printf("auth: %s ", authScheme);
    for (i = 0 ; i < subject->nidentity ; i++) {
        printf(" identity: %s=%s",
               subject->identities[i].type,
               subject->identities[i].name);
    }
    printf("\n");

    return 0;
}

345 346 347 348 349 350 351 352 353 354 355
static int myDomainEventControlErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                             virDomainPtr dom,
                                             void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) control error\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom));

    return 0;
}


356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
const char *diskChangeReasonStrings[] = {
    "startupPolicy", /* 0 */
    /* add new reason here */
};
static int myDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           const char *oldSrcPath,
                                           const char *newSrcPath,
                                           const char *devAlias,
                                           int reason,
                                           void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) disk change oldSrcPath: %s newSrcPath: %s devAlias: %s reason: %s\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom),
           oldSrcPath, newSrcPath, devAlias, diskChangeReasonStrings[reason]);
    return 0;
}

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
const char *trayChangeReasonStrings[] = {
    "open",
    "close",
};

static int myDomainEventTrayChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           const char *devAlias,
                                           int reason,
                                           void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) removable disk's tray change devAlias: %s reason: %s\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom),
           devAlias, trayChangeReasonStrings[reason]);
    return 0;
}
390

O
Osier Yang 已提交
391 392 393 394 395
static int myDomainEventPMWakeupCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         int reason ATTRIBUTE_UNUSED,
                                         void *opaque ATTRIBUTE_UNUSED)
{
396
    printf("%s EVENT: Domain %s(%d) system pmwakeup\n",
O
Osier Yang 已提交
397 398 399 400
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

O
Osier Yang 已提交
401 402 403 404 405
static int myDomainEventPMSuspendCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          int reason ATTRIBUTE_UNUSED,
                                          void *opaque ATTRIBUTE_UNUSED)
{
406
    printf("%s EVENT: Domain %s(%d) system pmsuspend\n",
O
Osier Yang 已提交
407 408 409 410
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

411 412 413 414 415 416 417 418 419 420
static int myDomainEventPMSuspendDiskCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                              virDomainPtr dom,
                                              int reason ATTRIBUTE_UNUSED,
                                              void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) system pmsuspend-disk\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

421 422 423
static void myFreeFunc(void *opaque)
{
    char *str = opaque;
424
    printf("%s: Freeing [%s]\n", __func__, str);
425 426 427
    free(str);
}

428 429 430 431 432 433 434 435

/* main test functions */

void usage(const char *pname)
{
    printf("%s uri\n", pname);
}

436 437 438 439 440 441 442 443

static void stop(int sig)
{
    printf("Exiting on signal %d\n", sig);
    run = 0;
}


444 445
int main(int argc, char **argv)
{
446 447
    int callback1ret = -1;
    int callback2ret = -1;
448
    int callback3ret = -1;
449
    int callback4ret = -1;
450
    int callback5ret = -1;
451
    int callback6ret = -1;
452
    int callback7ret = -1;
453
    int callback8ret = -1;
454
    int callback9ret = -1;
455
    int callback10ret = -1;
O
Osier Yang 已提交
456
    int callback11ret = -1;
O
Osier Yang 已提交
457
    int callback12ret = -1;
458
    int callback13ret = -1;
459
    int callback14ret = -1;
460
    struct sigaction action_stop;
461

462
    memset(&action_stop, 0, sizeof(action_stop));
463 464

    action_stop.sa_handler = stop;
465

466
    if (argc > 1 && STREQ(argv[1], "--help")) {
467 468 469
        usage(argv[0]);
        return -1;
    }
470

471
    virEventRegisterDefaultImpl();
472 473

    virConnectPtr dconn = NULL;
474 475 476
    dconn = virConnectOpenAuth(argc > 1 ? argv[1] : NULL,
                               virConnectAuthPtrDefault,
                               VIR_CONNECT_RO);
477 478 479 480 481
    if (!dconn) {
        printf("error opening\n");
        return -1;
    }

482 483 484
    virConnectRegisterCloseCallback(dconn,
                                    connectClose, NULL, NULL);

485 486 487
    sigaction(SIGTERM, &action_stop, NULL);
    sigaction(SIGINT, &action_stop, NULL);

488
    VIR_DEBUG("Registering domain event cbs");
489 490

    /* Add 2 callbacks to prove this works with more than just one */
491 492
    callback1ret = virConnectDomainEventRegister(dconn, myDomainEventCallback1,
                                                 strdup("callback 1"), myFreeFunc);
493 494 495 496 497
    callback2ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventCallback2),
                                                    strdup("callback 2"), myFreeFunc);
498 499 500 501 502
    callback3ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_REBOOT,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRebootCallback),
                                                    strdup("callback reboot"), myFreeFunc);
503 504 505 506 507
    callback4ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRTCChangeCallback),
                                                    strdup("callback rtcchange"), myFreeFunc);
508 509 510 511 512
    callback5ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_WATCHDOG,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventWatchdogCallback),
                                                    strdup("callback watchdog"), myFreeFunc);
513 514 515 516 517
    callback6ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_IO_ERROR,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventIOErrorCallback),
                                                    strdup("callback io error"), myFreeFunc);
518 519 520 521 522
    callback7ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_GRAPHICS,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventGraphicsCallback),
                                                    strdup("callback graphics"), myFreeFunc);
523 524 525 526 527
    callback8ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventControlErrorCallback),
                                                    strdup("callback control error"), myFreeFunc);
528 529 530 531 532
    callback9ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_DISK_CHANGE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventDiskChangeCallback),
                                                    strdup("disk change"), myFreeFunc);
533 534 535 536 537
    callback10ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_TRAY_CHANGE,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventTrayChangeCallback),
                                                     strdup("tray change"), myFreeFunc);
O
Osier Yang 已提交
538 539 540 541 542
    callback11ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMWAKEUP,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMWakeupCallback),
                                                     strdup("pmwakeup"), myFreeFunc);
O
Osier Yang 已提交
543 544 545 546 547
    callback12ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMSUSPEND,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMSuspendCallback),
                                                     strdup("pmsuspend"), myFreeFunc);
548 549 550 551 552
    callback13ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventBalloonChangeCallback),
                                                     strdup("callback balloonchange"), myFreeFunc);
553 554 555 556 557
    callback14ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMSuspendDiskCallback),
                                                     strdup("pmsuspend-disk"), myFreeFunc);
558
    if ((callback1ret != -1) &&
559
        (callback2ret != -1) &&
560
        (callback3ret != -1) &&
561
        (callback4ret != -1) &&
562
        (callback5ret != -1) &&
563
        (callback6ret != -1) &&
564
        (callback7ret != -1) &&
565
        (callback9ret != -1) &&
O
Osier Yang 已提交
566
        (callback10ret != -1) &&
O
Osier Yang 已提交
567
        (callback11ret != -1) &&
568
        (callback12ret != -1) &&
569 570
        (callback13ret != -1) &&
        (callback14ret != -1)) {
571 572 573 574 575 576 577
        if (virConnectSetKeepAlive(dconn, 5, 3) < 0) {
            virErrorPtr err = virGetLastError();
            fprintf(stderr, "Failed to start keepalive protocol: %s\n",
                    err && err->message ? err->message : "Unknown error");
            run = 0;
        }

578
        while (run) {
579 580 581 582
            if (virEventRunDefaultImpl() < 0) {
                virErrorPtr err = virGetLastError();
                fprintf(stderr, "Failed to run event loop: %s\n",
                        err && err->message ? err->message : "Unknown error");
583
            }
584 585
        }

586
        VIR_DEBUG("Deregistering event handlers");
587
        virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
588
        virConnectDomainEventDeregisterAny(dconn, callback2ret);
589
        virConnectDomainEventDeregisterAny(dconn, callback3ret);
590
        virConnectDomainEventDeregisterAny(dconn, callback4ret);
591
        virConnectDomainEventDeregisterAny(dconn, callback5ret);
592
        virConnectDomainEventDeregisterAny(dconn, callback6ret);
593
        virConnectDomainEventDeregisterAny(dconn, callback7ret);
594
        virConnectDomainEventDeregisterAny(dconn, callback9ret);
595
        virConnectDomainEventDeregisterAny(dconn, callback10ret);
O
Osier Yang 已提交
596
        virConnectDomainEventDeregisterAny(dconn, callback11ret);
O
Osier Yang 已提交
597
        virConnectDomainEventDeregisterAny(dconn, callback12ret);
598
        virConnectDomainEventDeregisterAny(dconn, callback13ret);
599 600
        if (callback8ret != -1)
            virConnectDomainEventDeregisterAny(dconn, callback8ret);
601 602
    }

603
    VIR_DEBUG("Closing connection");
604
    if (dconn && virConnectClose(dconn) < 0) {
605 606
        printf("error closing\n");
    }
607

608 609 610
    printf("done\n");
    return 0;
}