event-test.c 22.4 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 152
                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;
            }
153 154
            break;
        case VIR_DOMAIN_EVENT_RESUMED:
155
            switch ((virDomainEventResumedDetailType) detail) {
156
            case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED:
157
                ret = "Unpaused";
158 159
                break;
            case VIR_DOMAIN_EVENT_RESUMED_MIGRATED:
160
                ret = "Migrated";
161 162 163 164 165
                break;
            case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
            }
166 167
            break;
        case VIR_DOMAIN_EVENT_STOPPED:
168
            switch ((virDomainEventStoppedDetailType) detail) {
169 170 171 172 173 174 175 176 177 178 179 180 181
            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:
182
                ret = "Saved";
183 184 185 186
                break;
            case VIR_DOMAIN_EVENT_STOPPED_FAILED:
                ret = "Failed";
                break;
187 188 189
            case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
190
            }
191
            break;
192 193 194 195 196 197 198
        case VIR_DOMAIN_EVENT_SHUTDOWN:
            switch ((virDomainEventShutdownDetailType) detail) {
            case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
                ret = "Finished";
                break;
            }
            break;
J
Jiri Denemark 已提交
199 200 201 202 203 204 205
        case VIR_DOMAIN_EVENT_PMSUSPENDED:
            switch ((virDomainEventPMSuspendedDetailType) detail) {
            case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY:
                ret = "Memory";
                break;
            }
            break;
206 207 208 209
    }
    return ret;
}

210 211 212 213 214
static int myDomainEventCallback1(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virDomainPtr dom,
                                  int event,
                                  int detail,
                                  void *opaque ATTRIBUTE_UNUSED)
215
{
216
    printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
217 218
           virDomainGetID(dom), eventToString(event),
           eventDetailToString(event, detail));
219 220 221
    return 0;
}

222 223 224 225 226
static int myDomainEventCallback2(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virDomainPtr dom,
                                  int event,
                                  int detail,
                                  void *opaque ATTRIBUTE_UNUSED)
227
{
228
    printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
229 230
           virDomainGetID(dom), eventToString(event),
           eventDetailToString(event, detail));
231 232 233
    return 0;
}

234 235 236 237 238 239 240 241 242 243
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;
}

244 245 246 247 248
static int myDomainEventRTCChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          long long offset,
                                          void *opaque ATTRIBUTE_UNUSED)
{
249 250 251 252 253 254 255 256 257 258
    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);
259 260 261 262

    return 0;
}

263 264 265 266 267 268 269 270 271 272 273
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;
}

274 275 276 277 278 279 280 281 282 283 284
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;
}

285 286 287 288 289 290 291 292 293 294 295 296 297
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;
}

298 299 300 301 302 303 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
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;
}

339 340 341 342 343 344 345 346 347 348 349
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;
}


350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
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;
}

368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
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;
}
384

O
Osier Yang 已提交
385 386 387 388 389
static int myDomainEventPMWakeupCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         int reason ATTRIBUTE_UNUSED,
                                         void *opaque ATTRIBUTE_UNUSED)
{
390
    printf("%s EVENT: Domain %s(%d) system pmwakeup\n",
O
Osier Yang 已提交
391 392 393 394
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

O
Osier Yang 已提交
395 396 397 398 399
static int myDomainEventPMSuspendCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          int reason ATTRIBUTE_UNUSED,
                                          void *opaque ATTRIBUTE_UNUSED)
{
400
    printf("%s EVENT: Domain %s(%d) system pmsuspend\n",
O
Osier Yang 已提交
401 402 403 404
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

405 406 407
static void myFreeFunc(void *opaque)
{
    char *str = opaque;
408
    printf("%s: Freeing [%s]\n", __func__, str);
409 410 411
    free(str);
}

412 413 414 415 416 417 418 419

/* main test functions */

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

420 421 422 423 424 425 426 427

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


428 429
int main(int argc, char **argv)
{
430 431
    int callback1ret = -1;
    int callback2ret = -1;
432
    int callback3ret = -1;
433
    int callback4ret = -1;
434
    int callback5ret = -1;
435
    int callback6ret = -1;
436
    int callback7ret = -1;
437
    int callback8ret = -1;
438
    int callback9ret = -1;
439
    int callback10ret = -1;
O
Osier Yang 已提交
440
    int callback11ret = -1;
O
Osier Yang 已提交
441
    int callback12ret = -1;
442
    int callback13ret = -1;
443
    struct sigaction action_stop;
444

445
    memset(&action_stop, 0, sizeof(action_stop));
446 447

    action_stop.sa_handler = stop;
448

449
    if (argc > 1 && STREQ(argv[1], "--help")) {
450 451 452
        usage(argv[0]);
        return -1;
    }
453

454
    virEventRegisterDefaultImpl();
455 456

    virConnectPtr dconn = NULL;
457 458 459
    dconn = virConnectOpenAuth(argc > 1 ? argv[1] : NULL,
                               virConnectAuthPtrDefault,
                               VIR_CONNECT_RO);
460 461 462 463 464
    if (!dconn) {
        printf("error opening\n");
        return -1;
    }

465 466 467
    virConnectRegisterCloseCallback(dconn,
                                    connectClose, NULL, NULL);

468 469 470
    sigaction(SIGTERM, &action_stop, NULL);
    sigaction(SIGINT, &action_stop, NULL);

471
    VIR_DEBUG("Registering domain event cbs");
472 473

    /* Add 2 callbacks to prove this works with more than just one */
474 475
    callback1ret = virConnectDomainEventRegister(dconn, myDomainEventCallback1,
                                                 strdup("callback 1"), myFreeFunc);
476 477 478 479 480
    callback2ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventCallback2),
                                                    strdup("callback 2"), myFreeFunc);
481 482 483 484 485
    callback3ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_REBOOT,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRebootCallback),
                                                    strdup("callback reboot"), myFreeFunc);
486 487 488 489 490
    callback4ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRTCChangeCallback),
                                                    strdup("callback rtcchange"), myFreeFunc);
491 492 493 494 495
    callback5ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_WATCHDOG,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventWatchdogCallback),
                                                    strdup("callback watchdog"), myFreeFunc);
496 497 498 499 500
    callback6ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_IO_ERROR,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventIOErrorCallback),
                                                    strdup("callback io error"), myFreeFunc);
501 502 503 504 505
    callback7ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_GRAPHICS,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventGraphicsCallback),
                                                    strdup("callback graphics"), myFreeFunc);
506 507 508 509 510
    callback8ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventControlErrorCallback),
                                                    strdup("callback control error"), myFreeFunc);
511 512 513 514 515
    callback9ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_DISK_CHANGE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventDiskChangeCallback),
                                                    strdup("disk change"), myFreeFunc);
516 517 518 519 520
    callback10ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_TRAY_CHANGE,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventTrayChangeCallback),
                                                     strdup("tray change"), myFreeFunc);
O
Osier Yang 已提交
521 522 523 524 525
    callback11ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMWAKEUP,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMWakeupCallback),
                                                     strdup("pmwakeup"), myFreeFunc);
O
Osier Yang 已提交
526 527 528 529 530
    callback12ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMSUSPEND,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMSuspendCallback),
                                                     strdup("pmsuspend"), myFreeFunc);
531 532 533 534 535
    callback13ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventBalloonChangeCallback),
                                                     strdup("callback balloonchange"), myFreeFunc);
536
    if ((callback1ret != -1) &&
537
        (callback2ret != -1) &&
538
        (callback3ret != -1) &&
539
        (callback4ret != -1) &&
540
        (callback5ret != -1) &&
541
        (callback6ret != -1) &&
542
        (callback7ret != -1) &&
543
        (callback9ret != -1) &&
O
Osier Yang 已提交
544
        (callback10ret != -1) &&
O
Osier Yang 已提交
545
        (callback11ret != -1) &&
546 547
        (callback12ret != -1) &&
        (callback13ret != -1)) {
548 549 550 551 552 553 554
        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;
        }

555
        while (run) {
556 557 558 559
            if (virEventRunDefaultImpl() < 0) {
                virErrorPtr err = virGetLastError();
                fprintf(stderr, "Failed to run event loop: %s\n",
                        err && err->message ? err->message : "Unknown error");
560
            }
561 562
        }

563
        VIR_DEBUG("Deregistering event handlers");
564
        virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
565
        virConnectDomainEventDeregisterAny(dconn, callback2ret);
566
        virConnectDomainEventDeregisterAny(dconn, callback3ret);
567
        virConnectDomainEventDeregisterAny(dconn, callback4ret);
568
        virConnectDomainEventDeregisterAny(dconn, callback5ret);
569
        virConnectDomainEventDeregisterAny(dconn, callback6ret);
570
        virConnectDomainEventDeregisterAny(dconn, callback7ret);
571
        virConnectDomainEventDeregisterAny(dconn, callback9ret);
572
        virConnectDomainEventDeregisterAny(dconn, callback10ret);
O
Osier Yang 已提交
573
        virConnectDomainEventDeregisterAny(dconn, callback11ret);
O
Osier Yang 已提交
574
        virConnectDomainEventDeregisterAny(dconn, callback12ret);
575
        virConnectDomainEventDeregisterAny(dconn, callback13ret);
576 577
        if (callback8ret != -1)
            virConnectDomainEventDeregisterAny(dconn, callback8ret);
578 579
    }

580
    VIR_DEBUG("Closing connection");
581
    if (dconn && virConnectClose(dconn) < 0) {
582 583
        printf("error closing\n");
    }
584

585 586 587
    printf("done\n");
    return 0;
}