qemu_migration.c 160.3 KB
Newer Older
1 2 3
/*
 * qemu_migration.c: QEMU migration handling
 *
4
 * Copyright (C) 2006-2014 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20 21 22 23
 *
 */

#include <config.h>

J
Ján Tomko 已提交
24 25
#include <netdb.h>
#include <sys/socket.h>
26
#include <sys/time.h>
27
#ifdef WITH_GNUTLS
28 29 30
# include <gnutls/gnutls.h>
# include <gnutls/x509.h>
#endif
31
#include <fcntl.h>
32
#include <poll.h>
33 34 35 36 37 38

#include "qemu_migration.h"
#include "qemu_monitor.h"
#include "qemu_domain.h"
#include "qemu_process.h"
#include "qemu_capabilities.h"
39
#include "qemu_command.h"
40
#include "qemu_cgroup.h"
41
#include "qemu_hotplug.h"
42

43
#include "domain_audit.h"
44
#include "virlog.h"
45
#include "virerror.h"
46
#include "viralloc.h"
E
Eric Blake 已提交
47
#include "virfile.h"
48 49
#include "datatypes.h"
#include "fdstream.h"
50
#include "viruuid.h"
51
#include "virtime.h"
52
#include "locking/domain_lock.h"
53
#include "rpc/virnetsocket.h"
54
#include "virstoragefile.h"
M
Martin Kletzander 已提交
55
#include "viruri.h"
56
#include "virhook.h"
57
#include "virstring.h"
58
#include "virtypedparam.h"
59 60 61

#define VIR_FROM_THIS VIR_FROM_QEMU

62 63
VIR_LOG_INIT("qemu.qemu_migration");

64 65 66 67 68 69 70 71 72 73 74 75 76
VIR_ENUM_IMPL(qemuMigrationJobPhase, QEMU_MIGRATION_PHASE_LAST,
              "none",
              "perform2",
              "begin3",
              "perform3",
              "perform3_done",
              "confirm3_cancelled",
              "confirm3",
              "prepare",
              "finish2",
              "finish3",
);

77
enum qemuMigrationCookieFlags {
78
    QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
79
    QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
80
    QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
81
    QEMU_MIGRATION_COOKIE_FLAG_NETWORK,
82
    QEMU_MIGRATION_COOKIE_FLAG_NBD,
83 84 85 86 87 88 89

    QEMU_MIGRATION_COOKIE_FLAG_LAST
};

VIR_ENUM_DECL(qemuMigrationCookieFlag);
VIR_ENUM_IMPL(qemuMigrationCookieFlag,
              QEMU_MIGRATION_COOKIE_FLAG_LAST,
90 91 92 93 94
              "graphics",
              "lockstate",
              "persistent",
              "network",
              "nbd");
95 96 97

enum qemuMigrationCookieFeatures {
    QEMU_MIGRATION_COOKIE_GRAPHICS  = (1 << QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS),
98
    QEMU_MIGRATION_COOKIE_LOCKSTATE = (1 << QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE),
99
    QEMU_MIGRATION_COOKIE_PERSISTENT = (1 << QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT),
100
    QEMU_MIGRATION_COOKIE_NETWORK = (1 << QEMU_MIGRATION_COOKIE_FLAG_NETWORK),
101
    QEMU_MIGRATION_COOKIE_NBD = (1 << QEMU_MIGRATION_COOKIE_FLAG_NBD),
102 103 104 105 106 107 108 109 110 111 112 113
};

typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
typedef qemuMigrationCookieGraphics *qemuMigrationCookieGraphicsPtr;
struct _qemuMigrationCookieGraphics {
    int type;
    int port;
    int tlsPort;
    char *listen;
    char *tlsSubject;
};

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
typedef struct _qemuMigrationCookieNetData qemuMigrationCookieNetData;
typedef qemuMigrationCookieNetData *qemuMigrationCookieNetDataPtr;
struct _qemuMigrationCookieNetData {
    int vporttype; /* enum virNetDevVPortProfile */

    /*
     * Array of pointers to saved data. Each VIF will have it's own
     * data to transfer.
     */
    char *portdata;
};

typedef struct _qemuMigrationCookieNetwork qemuMigrationCookieNetwork;
typedef qemuMigrationCookieNetwork *qemuMigrationCookieNetworkPtr;
struct _qemuMigrationCookieNetwork {
    /* How many virtual NICs are we saving data for? */
    int nnets;

    qemuMigrationCookieNetDataPtr net;
};

135 136 137 138 139 140
typedef struct _qemuMigrationCookieNBD qemuMigrationCookieNBD;
typedef qemuMigrationCookieNBD *qemuMigrationCookieNBDPtr;
struct _qemuMigrationCookieNBD {
    int port; /* on which port does NBD server listen for incoming data */
};

141 142 143
typedef struct _qemuMigrationCookie qemuMigrationCookie;
typedef qemuMigrationCookie *qemuMigrationCookiePtr;
struct _qemuMigrationCookie {
E
Eric Blake 已提交
144 145
    unsigned int flags;
    unsigned int flagsMandatory;
146 147

    /* Host properties */
148 149 150 151
    unsigned char localHostuuid[VIR_UUID_BUFLEN];
    unsigned char remoteHostuuid[VIR_UUID_BUFLEN];
    char *localHostname;
    char *remoteHostname;
152 153 154 155

    /* Guest properties */
    unsigned char uuid[VIR_UUID_BUFLEN];
    char *name;
156

157 158 159 160
    /* If (flags & QEMU_MIGRATION_COOKIE_LOCKSTATE) */
    char *lockState;
    char *lockDriver;

161 162
    /* If (flags & QEMU_MIGRATION_COOKIE_GRAPHICS) */
    qemuMigrationCookieGraphicsPtr graphics;
163 164 165

    /* If (flags & QEMU_MIGRATION_COOKIE_PERSISTENT) */
    virDomainDefPtr persistent;
166 167 168

    /* If (flags & QEMU_MIGRATION_COOKIE_NETWORK) */
    qemuMigrationCookieNetworkPtr network;
169 170 171

    /* If (flags & QEMU_MIGRATION_COOKIE_NBD) */
    qemuMigrationCookieNBDPtr nbd;
172 173
};

174 175 176 177 178 179 180 181 182
static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
{
    if (!grap)
        return;
    VIR_FREE(grap->listen);
    VIR_FREE(grap->tlsSubject);
    VIR_FREE(grap);
}

183

184 185 186
static void
qemuMigrationCookieNetworkFree(qemuMigrationCookieNetworkPtr network)
{
187
    size_t i;
188 189 190 191 192 193 194 195 196 197 198 199 200

    if (!network)
        return;

    if (network->net) {
        for (i = 0; i < network->nnets; i++)
            VIR_FREE(network->net[i].portdata);
    }
    VIR_FREE(network->net);
    VIR_FREE(network);
}


201 202 203 204 205
static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
{
    if (!mig)
        return;

206 207
    qemuMigrationCookieGraphicsFree(mig->graphics);
    qemuMigrationCookieNetworkFree(mig->network);
208

209 210
    VIR_FREE(mig->localHostname);
    VIR_FREE(mig->remoteHostname);
211
    VIR_FREE(mig->name);
212 213
    VIR_FREE(mig->lockState);
    VIR_FREE(mig->lockDriver);
214
    VIR_FREE(mig->nbd);
215 216 217 218
    VIR_FREE(mig);
}


219
#ifdef WITH_GNUTLS
220 221 222 223 224 225 226 227 228 229 230 231
static char *
qemuDomainExtractTLSSubject(const char *certdir)
{
    char *certfile = NULL;
    char *subject = NULL;
    char *pemdata = NULL;
    gnutls_datum_t pemdatum;
    gnutls_x509_crt_t cert;
    int ret;
    size_t subjectlen;

    if (virAsprintf(&certfile, "%s/server-cert.pem", certdir) < 0)
232
        goto error;
233 234

    if (virFileReadAll(certfile, 8192, &pemdata) < 0) {
235 236
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unable to read server cert %s"), certfile);
237 238 239 240 241
        goto error;
    }

    ret = gnutls_x509_crt_init(&cert);
    if (ret < 0) {
242 243 244
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot initialize cert object: %s"),
                       gnutls_strerror(ret));
245 246 247 248 249 250 251 252
        goto error;
    }

    pemdatum.data = (unsigned char *)pemdata;
    pemdatum.size = strlen(pemdata);

    ret = gnutls_x509_crt_import(cert, &pemdatum, GNUTLS_X509_FMT_PEM);
    if (ret < 0) {
253 254 255
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot load cert data from %s: %s"),
                       certfile, gnutls_strerror(ret));
256 257 258 259 260
        goto error;
    }

    subjectlen = 1024;
    if (VIR_ALLOC_N(subject, subjectlen+1) < 0)
261
        goto error;
262 263 264 265 266 267 268 269 270

    gnutls_x509_crt_get_dn(cert, subject, &subjectlen);
    subject[subjectlen] = '\0';

    VIR_FREE(certfile);
    VIR_FREE(pemdata);

    return subject;

271
 error:
272 273 274 275
    VIR_FREE(certfile);
    VIR_FREE(pemdata);
    return NULL;
}
276
#endif
277 278

static qemuMigrationCookieGraphicsPtr
279
qemuMigrationCookieGraphicsAlloc(virQEMUDriverPtr driver,
280 281 282 283
                                 virDomainGraphicsDefPtr def)
{
    qemuMigrationCookieGraphicsPtr mig = NULL;
    const char *listenAddr;
284
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
285 286

    if (VIR_ALLOC(mig) < 0)
287
        goto error;
288 289 290 291

    mig->type = def->type;
    if (mig->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
        mig->port = def->data.vnc.port;
292
        listenAddr = virDomainGraphicsListenGetAddress(def, 0);
293
        if (!listenAddr)
294
            listenAddr = cfg->vncListen;
295

296
#ifdef WITH_GNUTLS
297 298
        if (cfg->vncTLS &&
            !(mig->tlsSubject = qemuDomainExtractTLSSubject(cfg->vncTLSx509certdir)))
299
            goto error;
300
#endif
301 302
    } else {
        mig->port = def->data.spice.port;
303
        if (cfg->spiceTLS)
304 305 306
            mig->tlsPort = def->data.spice.tlsPort;
        else
            mig->tlsPort = -1;
307
        listenAddr = virDomainGraphicsListenGetAddress(def, 0);
308
        if (!listenAddr)
309
            listenAddr = cfg->spiceListen;
310

311
#ifdef WITH_GNUTLS
312 313
        if (cfg->spiceTLS &&
            !(mig->tlsSubject = qemuDomainExtractTLSSubject(cfg->spiceTLSx509certdir)))
314
            goto error;
315
#endif
316
    }
317 318
    if (VIR_STRDUP(mig->listen, listenAddr) < 0)
        goto error;
319

320
    virObjectUnref(cfg);
321 322
    return mig;

323
 error:
324
    qemuMigrationCookieGraphicsFree(mig);
325
    virObjectUnref(cfg);
326 327 328 329
    return NULL;
}


330
static qemuMigrationCookieNetworkPtr
331
qemuMigrationCookieNetworkAlloc(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
332 333 334
                                virDomainDefPtr def)
{
    qemuMigrationCookieNetworkPtr mig;
335
    size_t i;
336 337

    if (VIR_ALLOC(mig) < 0)
338
        goto error;
339 340 341 342

    mig->nnets = def->nnets;

    if (VIR_ALLOC_N(mig->net, def->nnets) <0)
343
        goto error;
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358

    for (i = 0; i < def->nnets; i++) {
        virDomainNetDefPtr netptr;
        virNetDevVPortProfilePtr vport;

        netptr = def->nets[i];
        vport = virDomainNetGetActualVirtPortProfile(netptr);

        if (vport) {
            mig->net[i].vporttype = vport->virtPortType;

            switch (vport->virtPortType) {
            case VIR_NETDEV_VPORT_PROFILE_NONE:
            case VIR_NETDEV_VPORT_PROFILE_8021QBG:
            case VIR_NETDEV_VPORT_PROFILE_8021QBH:
359
               break;
360
            case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
361 362 363 364 365 366 367 368
                if (virNetDevOpenvswitchGetMigrateData(&mig->net[i].portdata,
                                                       netptr->ifname) != 0) {
                        virReportSystemError(VIR_ERR_INTERNAL_ERROR,
                                             _("Unable to run command to get OVS port data for "
                                             "interface %s"), netptr->ifname);
                        goto error;
                }
                break;
369 370 371 372 373 374 375
            default:
                break;
            }
        }
    }
    return mig;

376
 error:
377 378 379 380
    qemuMigrationCookieNetworkFree(mig);
    return NULL;
}

381 382 383
static qemuMigrationCookiePtr
qemuMigrationCookieNew(virDomainObjPtr dom)
{
J
Jiri Denemark 已提交
384
    qemuDomainObjPrivatePtr priv = dom->privateData;
385
    qemuMigrationCookiePtr mig = NULL;
J
Jiri Denemark 已提交
386
    const char *name;
387 388

    if (VIR_ALLOC(mig) < 0)
389
        goto error;
390

J
Jiri Denemark 已提交
391 392 393 394
    if (priv->origname)
        name = priv->origname;
    else
        name = dom->def->name;
395 396
    if (VIR_STRDUP(mig->name, name) < 0)
        goto error;
397 398
    memcpy(mig->uuid, dom->def->uuid, VIR_UUID_BUFLEN);

399
    if (!(mig->localHostname = virGetHostname()))
400
        goto error;
401
    if (virGetHostUUID(mig->localHostuuid) < 0) {
402 403
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to obtain host UUID"));
404 405 406 407 408
        goto error;
    }

    return mig;

409
 error:
410 411 412 413 414
    qemuMigrationCookieFree(mig);
    return NULL;
}


415 416
static int
qemuMigrationCookieAddGraphics(qemuMigrationCookiePtr mig,
417
                               virQEMUDriverPtr driver,
418 419
                               virDomainObjPtr dom)
{
420 421
    size_t i = 0;

422
    if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS) {
423 424
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Migration graphics data already present"));
425 426 427
        return -1;
    }

428 429 430 431 432 433 434 435
    for (i = 0; i < dom->def->ngraphics; i++) {
       if (dom->def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
           if (!(mig->graphics =
                 qemuMigrationCookieGraphicsAlloc(driver, dom->def->graphics[i])))
               return -1;
           mig->flags |= QEMU_MIGRATION_COOKIE_GRAPHICS;
           break;
       }
436
    }
437 438 439 440 441

    return 0;
}


442 443
static int
qemuMigrationCookieAddLockstate(qemuMigrationCookiePtr mig,
444
                                virQEMUDriverPtr driver,
445 446 447 448 449
                                virDomainObjPtr dom)
{
    qemuDomainObjPrivatePtr priv = dom->privateData;

    if (mig->flags & QEMU_MIGRATION_COOKIE_LOCKSTATE) {
450 451
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Migration lockstate data already present"));
452 453 454 455
        return -1;
    }

    if (virDomainObjGetState(dom, NULL) == VIR_DOMAIN_PAUSED) {
456
        if (VIR_STRDUP(mig->lockState, priv->lockState) < 0)
457 458 459 460 461 462
            return -1;
    } else {
        if (virDomainLockProcessInquire(driver->lockManager, dom, &mig->lockState) < 0)
            return -1;
    }

463
    if (VIR_STRDUP(mig->lockDriver, virLockManagerPluginGetName(driver->lockManager)) < 0) {
464 465 466 467 468 469 470 471 472 473 474
        VIR_FREE(mig->lockState);
        return -1;
    }

    mig->flags |= QEMU_MIGRATION_COOKIE_LOCKSTATE;
    mig->flagsMandatory |= QEMU_MIGRATION_COOKIE_LOCKSTATE;

    return 0;
}


475 476 477 478 479
static int
qemuMigrationCookieAddPersistent(qemuMigrationCookiePtr mig,
                                 virDomainObjPtr dom)
{
    if (mig->flags & QEMU_MIGRATION_COOKIE_PERSISTENT) {
480 481
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Migration persistent data already present"));
482 483 484 485 486 487 488 489 490 491 492 493 494
        return -1;
    }

    if (!dom->newDef)
        return 0;

    mig->persistent = dom->newDef;
    mig->flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
    mig->flagsMandatory |= QEMU_MIGRATION_COOKIE_PERSISTENT;
    return 0;
}


495 496
static int
qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
497
                              virQEMUDriverPtr driver,
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
                              virDomainObjPtr dom)
{
    if (mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Network migration data already present"));
        return -1;
    }

    if (dom->def->nnets > 0) {
        mig->network = qemuMigrationCookieNetworkAlloc(driver, dom->def);
        if (!mig->network)
            return -1;
        mig->flags |= QEMU_MIGRATION_COOKIE_NETWORK;
    }

    return 0;
}

516

517 518 519 520 521 522 523 524 525
static int
qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig,
                          virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
                          virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;

    /* It is not a bug if there already is a NBD data */
    if (!mig->nbd &&
526
        VIR_ALLOC(mig->nbd) < 0)
527 528 529 530 531 532 533 534 535
        return -1;

    mig->nbd->port = priv->nbdPort;
    mig->flags |= QEMU_MIGRATION_COOKIE_NBD;

    return 0;
}


536 537 538
static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
                                                 qemuMigrationCookieGraphicsPtr grap)
{
539
    virBufferAsprintf(buf, "<graphics type='%s' port='%d' listen='%s'",
540 541 542 543 544 545
                      virDomainGraphicsTypeToString(grap->type),
                      grap->port, grap->listen);
    if (grap->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
        virBufferAsprintf(buf, " tlsPort='%d'", grap->tlsPort);
    if (grap->tlsSubject) {
        virBufferAddLit(buf, ">\n");
546 547 548 549
        virBufferAdjustIndent(buf, 2);
        virBufferEscapeString(buf, "<cert info='subject' value='%s'/>\n", grap->tlsSubject);
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</graphics>\n");
550 551 552 553 554 555
    } else {
        virBufferAddLit(buf, "/>\n");
    }
}


556 557 558 559
static void
qemuMigrationCookieNetworkXMLFormat(virBufferPtr buf,
                                    qemuMigrationCookieNetworkPtr optr)
{
560
    size_t i;
561 562 563 564 565 566
    bool empty = true;

    for (i = 0; i < optr->nnets; i++) {
        /* If optr->net[i].vporttype is not set, there is nothing to transfer */
        if (optr->net[i].vporttype != VIR_NETDEV_VPORT_PROFILE_NONE) {
            if (empty) {
567 568
                virBufferAddLit(buf, "<network>\n");
                virBufferAdjustIndent(buf, 2);
569 570
                empty = false;
            }
571
            virBufferAsprintf(buf, "<interface index='%zu' vporttype='%s'",
572 573 574
                              i, virNetDevVPortTypeToString(optr->net[i].vporttype));
            if (optr->net[i].portdata) {
                virBufferAddLit(buf, ">\n");
575 576
                virBufferAdjustIndent(buf, 2);
                virBufferEscapeString(buf, "<portdata>%s</portdata>\n",
577
                                      optr->net[i].portdata);
578 579
                virBufferAdjustIndent(buf, -2);
                virBufferAddLit(buf, "</interface>\n");
580 581 582 583 584
            } else {
                virBufferAddLit(buf, "/>\n");
            }
        }
    }
585 586 587 588
    if (!empty) {
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</network>\n");
    }
589 590 591
}


592
static int
593
qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
594
                             virBufferPtr buf,
595
                             qemuMigrationCookiePtr mig)
596 597 598
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    char hostuuidstr[VIR_UUID_STRING_BUFLEN];
599
    size_t i;
600 601

    virUUIDFormat(mig->uuid, uuidstr);
602
    virUUIDFormat(mig->localHostuuid, hostuuidstr);
603

604
    virBufferAddLit(buf, "<qemu-migration>\n");
605 606 607 608 609
    virBufferAdjustIndent(buf, 2);
    virBufferEscapeString(buf, "<name>%s</name>\n", mig->name);
    virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
    virBufferEscapeString(buf, "<hostname>%s</hostname>\n", mig->localHostname);
    virBufferAsprintf(buf, "<hostuuid>%s</hostuuid>\n", hostuuidstr);
610

611
    for (i = 0; i < QEMU_MIGRATION_COOKIE_FLAG_LAST; i++) {
612
        if (mig->flagsMandatory & (1 << i))
613
            virBufferAsprintf(buf, "<feature name='%s'/>\n",
614 615 616
                              qemuMigrationCookieFlagTypeToString(i));
    }

617 618
    if ((mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS) &&
        mig->graphics)
619 620
        qemuMigrationCookieGraphicsXMLFormat(buf, mig->graphics);

621 622
    if ((mig->flags & QEMU_MIGRATION_COOKIE_LOCKSTATE) &&
        mig->lockState) {
623
        virBufferAsprintf(buf, "<lockstate driver='%s'>\n",
624
                          mig->lockDriver);
625 626
        virBufferAdjustIndent(buf, 2);
        virBufferAsprintf(buf, "<leases>%s</leases>\n",
627
                          mig->lockState);
628 629
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</lockstate>\n");
630 631
    }

632 633
    if ((mig->flags & QEMU_MIGRATION_COOKIE_PERSISTENT) &&
        mig->persistent) {
634 635 636
        if (qemuDomainDefFormatBuf(driver,
                                   mig->persistent,
                                   VIR_DOMAIN_XML_INACTIVE |
637 638
                                   VIR_DOMAIN_XML_SECURE |
                                   VIR_DOMAIN_XML_MIGRATABLE,
639
                                   buf) < 0)
640
            return -1;
641 642
    }

643 644 645
    if ((mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) && mig->network)
        qemuMigrationCookieNetworkXMLFormat(buf, mig->network);

646
    if ((mig->flags & QEMU_MIGRATION_COOKIE_NBD) && mig->nbd) {
647
        virBufferAddLit(buf, "<nbd");
648 649 650 651 652
        if (mig->nbd->port)
            virBufferAsprintf(buf, " port='%d'", mig->nbd->port);
        virBufferAddLit(buf, "/>\n");
    }

653
    virBufferAdjustIndent(buf, -2);
654
    virBufferAddLit(buf, "</qemu-migration>\n");
655
    return 0;
656 657 658
}


659
static char *qemuMigrationCookieXMLFormatStr(virQEMUDriverPtr driver,
660
                                             qemuMigrationCookiePtr mig)
661 662 663
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

664
    if (qemuMigrationCookieXMLFormat(driver, &buf, mig) < 0) {
665 666 667
        virBufferFreeAndReset(&buf);
        return NULL;
    }
668 669 670

    if (virBufferError(&buf)) {
        virReportOOMError();
671
        virBufferFreeAndReset(&buf);
672 673 674 675 676 677 678
        return NULL;
    }

    return virBufferContentAndReset(&buf);
}


679 680 681 682 683 684 685
static qemuMigrationCookieGraphicsPtr
qemuMigrationCookieGraphicsXMLParse(xmlXPathContextPtr ctxt)
{
    qemuMigrationCookieGraphicsPtr grap;
    char *tmp;

    if (VIR_ALLOC(grap) < 0)
686
        goto error;
687 688

    if (!(tmp = virXPathString("string(./graphics/@type)", ctxt))) {
689 690
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing type attribute in migration data"));
691 692 693
        goto error;
    }
    if ((grap->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
694 695
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown graphics type %s"), tmp);
696 697 698
        VIR_FREE(tmp);
        goto error;
    }
E
Eric Blake 已提交
699
    VIR_FREE(tmp);
700
    if (virXPathInt("string(./graphics/@port)", ctxt, &grap->port) < 0) {
701 702
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing port attribute in migration data"));
703 704 705 706
        goto error;
    }
    if (grap->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
        if (virXPathInt("string(./graphics/@tlsPort)", ctxt, &grap->tlsPort) < 0) {
707 708
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("missing tlsPort attribute in migration data"));
709 710 711 712
            goto error;
        }
    }
    if (!(grap->listen = virXPathString("string(./graphics/@listen)", ctxt))) {
713 714
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing listen attribute in migration data"));
715 716 717
        goto error;
    }
    /* Optional */
718
    grap->tlsSubject = virXPathString("string(./graphics/cert[@info='subject']/@value)", ctxt);
719 720 721

    return grap;

722
 error:
723 724 725 726 727
    qemuMigrationCookieGraphicsFree(grap);
    return NULL;
}


728 729 730 731
static qemuMigrationCookieNetworkPtr
qemuMigrationCookieNetworkXMLParse(xmlXPathContextPtr ctxt)
{
    qemuMigrationCookieNetworkPtr optr;
732
    size_t i;
733 734 735 736 737 738
    int n;
    xmlNodePtr *interfaces = NULL;
    char *vporttype;
    xmlNodePtr save_ctxt = ctxt->node;

    if (VIR_ALLOC(optr) < 0)
739
        goto error;
740 741 742 743 744 745 746 747

    if ((n = virXPathNodeSet("./network/interface", ctxt, &interfaces)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing interface information"));
        goto error;
    }

    optr->nnets = n;
748
    if (VIR_ALLOC_N(optr->net, optr->nnets) < 0)
749
        goto error;
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765

    for (i = 0; i < n; i++) {
        /* portdata is optional, and may not exist */
        ctxt->node = interfaces[i];
        optr->net[i].portdata = virXPathString("string(./portdata[1])", ctxt);

        if (!(vporttype = virXMLPropString(interfaces[i], "vporttype"))) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("missing vporttype attribute in migration data"));
            goto error;
        }
        optr->net[i].vporttype = virNetDevVPortTypeFromString(vporttype);
    }

    VIR_FREE(interfaces);

766
 cleanup:
767 768 769
    ctxt->node = save_ctxt;
    return optr;

770
 error:
771 772 773 774 775 776 777
    VIR_FREE(interfaces);
    qemuMigrationCookieNetworkFree(optr);
    optr = NULL;
    goto cleanup;
}


778 779
static int
qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
780
                            virQEMUDriverPtr driver,
781
                            xmlDocPtr doc,
782
                            xmlXPathContextPtr ctxt,
E
Eric Blake 已提交
783
                            unsigned int flags)
784 785
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];
786
    char *tmp = NULL;
787
    xmlNodePtr *nodes = NULL;
788 789
    size_t i;
    int n;
790 791 792 793
    virCapsPtr caps = NULL;

    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto error;
794 795 796 797 798 799 800 801

    /* We don't store the uuid, name, hostname, or hostuuid
     * values. We just compare them to local data to do some
     * sanity checking on migration operation
     */

    /* Extract domain name */
    if (!(tmp = virXPathString("string(./name[1])", ctxt))) {
802 803
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing name element in migration data"));
804 805 806
        goto error;
    }
    if (STRNEQ(tmp, mig->name)) {
807 808 809
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Incoming cookie data had unexpected name %s vs %s"),
                       tmp, mig->name);
810 811 812 813 814 815 816
        goto error;
    }
    VIR_FREE(tmp);

    /* Extract domain uuid */
    tmp = virXPathString("string(./uuid[1])", ctxt);
    if (!tmp) {
817 818
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing uuid element in migration data"));
819 820 821 822
        goto error;
    }
    virUUIDFormat(mig->uuid, uuidstr);
    if (STRNEQ(tmp, uuidstr)) {
823 824 825
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Incoming cookie data had unexpected UUID %s vs %s"),
                       tmp, uuidstr);
826 827 828 829
    }
    VIR_FREE(tmp);

    /* Check & forbid "localhost" migration */
830
    if (!(mig->remoteHostname = virXPathString("string(./hostname[1])", ctxt))) {
831 832
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing hostname element in migration data"));
833 834
        goto error;
    }
835
    if (STREQ(mig->remoteHostname, mig->localHostname)) {
836 837 838
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Attempt to migrate guest to the same host %s"),
                       mig->remoteHostname);
839 840 841 842
        goto error;
    }

    if (!(tmp = virXPathString("string(./hostuuid[1])", ctxt))) {
843 844 845
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing hostuuid element in migration data"));
        goto error;
846
    }
847 848 849 850 851 852 853 854 855 856 857 858
    if (virUUIDParse(tmp, mig->remoteHostuuid) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed hostuuid element in migration data"));
        goto error;
    }
    if (memcmp(mig->remoteHostuuid, mig->localHostuuid, VIR_UUID_BUFLEN) == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Attempt to migrate guest to the same host %s"),
                       tmp);
        goto error;
    }
    VIR_FREE(tmp);
859

860 861
    /* Check to ensure all mandatory features from XML are also
     * present in 'flags' */
862
    if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0)
863 864
        goto error;

865
    for (i = 0; i < n; i++) {
866 867 868
        int val;
        char *str = virXMLPropString(nodes[i], "name");
        if (!str) {
869 870
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("missing feature name"));
871 872 873 874
            goto error;
        }

        if ((val = qemuMigrationCookieFlagTypeFromString(str)) < 0) {
875 876 877
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unknown migration cookie feature %s"),
                           str);
878 879 880 881 882
            VIR_FREE(str);
            goto error;
        }

        if ((flags & (1 << val)) == 0) {
883 884 885
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unsupported migration cookie feature %s"),
                           str);
886 887 888 889 890 891
            VIR_FREE(str);
        }
        VIR_FREE(str);
    }
    VIR_FREE(nodes);

892 893 894 895 896
    if ((flags & QEMU_MIGRATION_COOKIE_GRAPHICS) &&
        virXPathBoolean("count(./graphics) > 0", ctxt) &&
        (!(mig->graphics = qemuMigrationCookieGraphicsXMLParse(ctxt))))
        goto error;

897 898 899 900
    if ((flags & QEMU_MIGRATION_COOKIE_LOCKSTATE) &&
        virXPathBoolean("count(./lockstate) > 0", ctxt)) {
        mig->lockDriver = virXPathString("string(./lockstate[1]/@driver)", ctxt);
        if (!mig->lockDriver) {
901 902
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing lock driver name in migration cookie"));
903 904 905 906 907 908 909
            goto error;
        }
        mig->lockState = virXPathString("string(./lockstate[1]/leases[1])", ctxt);
        if (mig->lockState && STREQ(mig->lockState, ""))
            VIR_FREE(mig->lockState);
    }

910 911 912
    if ((flags & QEMU_MIGRATION_COOKIE_PERSISTENT) &&
        virXPathBoolean("count(./domain) > 0", ctxt)) {
        if ((n = virXPathNodeSet("./domain", ctxt, &nodes)) > 1) {
913 914 915 916
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Too many domain elements in "
                             "migration cookie: %d"),
                           n);
917 918
            goto error;
        }
919 920
        mig->persistent = virDomainDefParseNode(doc, nodes[0],
                                                caps, driver->xmlopt,
921 922 923 924 925 926 927 928 929
                                                -1, VIR_DOMAIN_XML_INACTIVE);
        if (!mig->persistent) {
            /* virDomainDefParseNode already reported
             * an error for us */
            goto error;
        }
        VIR_FREE(nodes);
    }

930 931 932 933 934
    if ((flags & QEMU_MIGRATION_COOKIE_NETWORK) &&
        virXPathBoolean("count(./network) > 0", ctxt) &&
        (!(mig->network = qemuMigrationCookieNetworkXMLParse(ctxt))))
        goto error;

935 936 937 938
    if (flags & QEMU_MIGRATION_COOKIE_NBD &&
        virXPathBoolean("boolean(./nbd)", ctxt)) {
        char *port;

939
        if (VIR_ALLOC(mig->nbd) < 0)
940 941 942 943 944 945 946 947 948 949 950 951 952
            goto error;

        port = virXPathString("string(./nbd/@port)", ctxt);
        if (port && virStrToLong_i(port, NULL, 10, &mig->nbd->port) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Malformed nbd port '%s'"),
                           port);
            VIR_FREE(port);
            goto error;
        }
        VIR_FREE(port);
    }

953
    virObjectUnref(caps);
954 955
    return 0;

956
 error:
957
    VIR_FREE(tmp);
958
    VIR_FREE(nodes);
959
    virObjectUnref(caps);
960 961 962 963 964 965
    return -1;
}


static int
qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig,
966
                               virQEMUDriverPtr driver,
967
                               const char *xml,
E
Eric Blake 已提交
968
                               unsigned int flags)
969 970 971
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
972
    int ret = -1;
973 974 975

    VIR_DEBUG("xml=%s", NULLSTR(xml));

976
    if (!(doc = virXMLParseStringCtxt(xml, _("(qemu_migration_cookie)"), &ctxt)))
977 978
        goto cleanup;

979
    ret = qemuMigrationCookieXMLParse(mig, driver, doc, ctxt, flags);
980

981
 cleanup:
982 983 984 985 986 987 988 989 990
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);

    return ret;
}


static int
qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
991
                        virQEMUDriverPtr driver,
992
                        virDomainObjPtr dom,
993 994
                        char **cookieout,
                        int *cookieoutlen,
E
Eric Blake 已提交
995
                        unsigned int flags)
996
{
997 998
    if (!cookieout || !cookieoutlen)
        return 0;
999 1000 1001

    *cookieoutlen = 0;

1002 1003 1004 1005
    if (flags & QEMU_MIGRATION_COOKIE_GRAPHICS &&
        qemuMigrationCookieAddGraphics(mig, driver, dom) < 0)
        return -1;

1006 1007 1008 1009
    if (flags & QEMU_MIGRATION_COOKIE_LOCKSTATE &&
        qemuMigrationCookieAddLockstate(mig, driver, dom) < 0)
        return -1;

1010 1011 1012 1013
    if (flags & QEMU_MIGRATION_COOKIE_PERSISTENT &&
        qemuMigrationCookieAddPersistent(mig, dom) < 0)
        return -1;

1014 1015 1016 1017 1018
    if (flags & QEMU_MIGRATION_COOKIE_NETWORK &&
        qemuMigrationCookieAddNetwork(mig, driver, dom) < 0) {
        return -1;
    }

1019 1020 1021 1022
    if ((flags & QEMU_MIGRATION_COOKIE_NBD) &&
        qemuMigrationCookieAddNBD(mig, driver, dom) < 0)
        return -1;

1023
    if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
        return -1;

    *cookieoutlen = strlen(*cookieout) + 1;

    VIR_DEBUG("cookielen=%d cookie=%s", *cookieoutlen, *cookieout);

    return 0;
}


static qemuMigrationCookiePtr
1035
qemuMigrationEatCookie(virQEMUDriverPtr driver,
1036
                       virDomainObjPtr dom,
1037 1038
                       const char *cookiein,
                       int cookieinlen,
E
Eric Blake 已提交
1039
                       unsigned int flags)
1040 1041 1042 1043 1044 1045
{
    qemuMigrationCookiePtr mig = NULL;

    /* Parse & validate incoming cookie (if any) */
    if (cookiein && cookieinlen &&
        cookiein[cookieinlen-1] != '\0') {
1046 1047
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Migration cookie was not NULL terminated"));
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
        goto error;
    }

    VIR_DEBUG("cookielen=%d cookie='%s'", cookieinlen, NULLSTR(cookiein));

    if (!(mig = qemuMigrationCookieNew(dom)))
        return NULL;

    if (cookiein && cookieinlen &&
        qemuMigrationCookieXMLParseStr(mig,
1058
                                       driver,
1059 1060 1061 1062
                                       cookiein,
                                       flags) < 0)
        goto error;

1063 1064 1065
    if (mig->flags & QEMU_MIGRATION_COOKIE_LOCKSTATE) {
        if (!mig->lockDriver) {
            if (virLockManagerPluginUsesState(driver->lockManager)) {
1066 1067 1068
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Missing %s lock state for migration cookie"),
                               virLockManagerPluginGetName(driver->lockManager));
1069 1070 1071 1072
                goto error;
            }
        } else if (STRNEQ(mig->lockDriver,
                          virLockManagerPluginGetName(driver->lockManager))) {
1073 1074 1075 1076
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Source host lock driver %s different from target %s"),
                           mig->lockDriver,
                           virLockManagerPluginGetName(driver->lockManager));
1077 1078 1079 1080
            goto error;
        }
    }

1081 1082
    return mig;

1083
 error:
1084 1085 1086
    qemuMigrationCookieFree(mig);
    return NULL;
}
1087

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
static void
qemuMigrationStoreDomainState(virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    priv->preMigrationState = virDomainObjGetState(vm, NULL);

    VIR_DEBUG("Storing pre-migration state=%d domain=%p",
              priv->preMigrationState, vm);
}

/* Returns true if the domain was resumed, false otherwise */
static bool
qemuMigrationRestoreDomainState(virConnectPtr conn, virDomainObjPtr vm)
{
    virQEMUDriverPtr driver = conn->privateData;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int state = virDomainObjGetState(vm, NULL);
    bool ret = false;

    VIR_DEBUG("driver=%p, vm=%p, pre-mig-state=%d, state=%d",
              driver, vm, priv->preMigrationState, state);

    if (state == VIR_DOMAIN_PAUSED &&
        priv->preMigrationState == VIR_DOMAIN_RUNNING) {
        /* This is basically the only restore possibility that's safe
         * and we should attempt to do */

        VIR_DEBUG("Restoring pre-migration state due to migration error");

        /* we got here through some sort of failure; start the domain again */
        if (qemuProcessStartCPUs(driver, vm, conn,
                                 VIR_DOMAIN_RUNNING_MIGRATION_CANCELED,
                                 QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) {
            /* Hm, we already know we are in error here.  We don't want to
             * overwrite the previous error, though, so we just throw something
             * to the logs and hope for the best */
            VIR_ERROR(_("Failed to resume guest %s after failure"), vm->def->name);
            goto cleanup;
        }
        ret = true;
    }

 cleanup:
    priv->preMigrationState = VIR_DOMAIN_NOSTATE;
    return ret;
}

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
/**
 * qemuMigrationStartNBDServer:
 * @driver: qemu driver
 * @vm: domain
 *
 * Starts NBD server. This is a newer method to copy
 * storage during migration than using 'blk' and 'inc'
 * arguments in 'migrate' monitor command.
 * Error is reported here.
 *
 * Returns 0 on success, -1 otherwise.
 */
static int
qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
J
Ján Tomko 已提交
1149 1150
                            virDomainObjPtr vm,
                            const char *listenAddr)
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
{
    int ret = -1;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    unsigned short port = 0;
    char *diskAlias = NULL;
    size_t i;

    for (i = 0; i < vm->def->ndisks; i++) {
        virDomainDiskDefPtr disk = vm->def->disks[i];

        /* skip shared, RO and source-less disks */
1162
        if (disk->shared || disk->readonly || !virDomainDiskGetSource(disk))
1163 1164 1165 1166
            continue;

        VIR_FREE(diskAlias);
        if (virAsprintf(&diskAlias, "%s%s",
1167
                        QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0)
1168 1169 1170 1171 1172 1173 1174
            goto cleanup;

        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
            goto cleanup;

        if (!port &&
1175
            ((virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) ||
1176
             (qemuMonitorNBDServerStart(priv->mon, listenAddr, port) < 0))) {
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
            qemuDomainObjExitMonitor(driver, vm);
            goto cleanup;
        }

        if (qemuMonitorNBDServerAdd(priv->mon, diskAlias, true) < 0) {
            qemuDomainObjExitMonitor(driver, vm);
            goto cleanup;
        }
        qemuDomainObjExitMonitor(driver, vm);
    }

    priv->nbdPort = port;
    ret = 0;

1191
 cleanup:
1192
    VIR_FREE(diskAlias);
1193
    if (ret < 0)
1194 1195 1196 1197
        virPortAllocatorRelease(driver->remotePorts, port);
    return ret;
}

1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
/**
 * qemuMigrationDriveMirror:
 * @driver: qemu driver
 * @vm: domain
 * @mig: migration cookie
 * @host: where are we migrating to
 * @speed: how much should the copying be limited
 * @migrate_flags: migrate monitor command flags
 *
 * Run drive-mirror to feed NBD server running on dst and wait
 * till the process switches into another phase where writes go
 * simultaneously to both source and destination. And this switch
 * is what we are waiting for before proceeding with the next
 * disk. On success, update @migrate_flags so we don't tell
 * 'migrate' command to do the very same operation.
 *
 * Returns 0 on success (@migrate_flags updated),
 *        -1 otherwise.
 */
static int
qemuMigrationDriveMirror(virQEMUDriverPtr driver,
                         virDomainObjPtr vm,
                         qemuMigrationCookiePtr mig,
                         const char *host,
                         unsigned long speed,
                         unsigned int *migrate_flags)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int ret = -1;
    int mon_ret;
    int port;
    size_t i, lastGood = 0;
    char *diskAlias = NULL;
    char *nbd_dest = NULL;
1232
    char *hoststr = NULL;
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
    unsigned int mirror_flags = VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT;
    virErrorPtr err = NULL;

    if (!(*migrate_flags & (QEMU_MONITOR_MIGRATE_NON_SHARED_DISK |
                            QEMU_MONITOR_MIGRATE_NON_SHARED_INC)))
        return 0;

    if (!mig->nbd) {
        /* Destination doesn't support NBD server.
         * Fall back to previous implementation. */
        VIR_DEBUG("Destination doesn't support NBD server "
                  "Falling back to previous implementation.");
        return 0;
    }

    /* steal NBD port and thus prevent its propagation back to destination */
    port = mig->nbd->port;
    mig->nbd->port = 0;

1252 1253
    /* escape literal IPv6 address */
    if (strchr(host, ':')) {
1254
        if (virAsprintf(&hoststr, "[%s]", host) < 0)
1255 1256 1257 1258 1259
            goto error;
    } else if (VIR_STRDUP(hoststr, host) < 0) {
        goto error;
    }

1260 1261 1262 1263 1264 1265 1266 1267
    if (*migrate_flags & QEMU_MONITOR_MIGRATE_NON_SHARED_INC)
        mirror_flags |= VIR_DOMAIN_BLOCK_REBASE_SHALLOW;

    for (i = 0; i < vm->def->ndisks; i++) {
        virDomainDiskDefPtr disk = vm->def->disks[i];
        virDomainBlockJobInfo info;

        /* skip shared, RO and source-less disks */
1268
        if (disk->shared || disk->readonly || !virDomainDiskGetSource(disk))
1269 1270 1271 1272 1273 1274 1275
            continue;

        VIR_FREE(diskAlias);
        VIR_FREE(nbd_dest);
        if ((virAsprintf(&diskAlias, "%s%s",
                         QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) ||
            (virAsprintf(&nbd_dest, "nbd:%s:%d:exportname=%s",
1276
                         hoststr, port, diskAlias) < 0))
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
            goto error;

        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            goto error;
        mon_ret = qemuMonitorDriveMirror(priv->mon, diskAlias, nbd_dest,
                                         NULL, speed, mirror_flags);
        qemuDomainObjExitMonitor(driver, vm);

        if (mon_ret < 0)
            goto error;

        lastGood = i;

        /* wait for completion */
        while (true) {
            /* Poll every 500ms for progress & to allow cancellation */
            struct timespec ts = { .tv_sec = 0, .tv_nsec = 500 * 1000 * 1000ull };

            memset(&info, 0, sizeof(info));

            if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                               QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
                goto error;
            if (priv->job.asyncAbort) {
                /* explicitly do this *after* we entered the monitor,
                 * as this is a critical section so we are guaranteed
                 * priv->job.asyncAbort will not change */
                qemuDomainObjExitMonitor(driver, vm);
                virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
                               qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
                               _("canceled by client"));
                goto error;
            }
            mon_ret = qemuMonitorBlockJob(priv->mon, diskAlias, NULL, 0,
                                          &info, BLOCK_JOB_INFO, true);
            qemuDomainObjExitMonitor(driver, vm);

            if (mon_ret < 0)
                goto error;

            if (info.cur == info.end) {
                VIR_DEBUG("Drive mirroring of '%s' completed", diskAlias);
                break;
            }

            /* XXX Frankly speaking, we should listen to the events,
             * instead of doing this. But this works for now and we
             * are doing something similar in migration itself anyway */

            virObjectUnlock(vm);

            nanosleep(&ts, NULL);

            virObjectLock(vm);
        }
    }

    /* Okay, copied. Modify migrate_flags */
    *migrate_flags &= ~(QEMU_MONITOR_MIGRATE_NON_SHARED_DISK |
                        QEMU_MONITOR_MIGRATE_NON_SHARED_INC);
    ret = 0;

1340
 cleanup:
1341 1342
    VIR_FREE(diskAlias);
    VIR_FREE(nbd_dest);
1343
    VIR_FREE(hoststr);
1344 1345
    return ret;

1346
 error:
1347 1348 1349 1350 1351 1352 1353
    /* don't overwrite any errors */
    err = virSaveLastError();
    /* cancel any outstanding jobs */
    while (lastGood) {
        virDomainDiskDefPtr disk = vm->def->disks[--lastGood];

        /* skip shared, RO disks */
1354
        if (disk->shared || disk->readonly || !virDomainDiskGetSource(disk))
1355 1356 1357 1358
            continue;

        VIR_FREE(diskAlias);
        if (virAsprintf(&diskAlias, "%s%s",
1359
                        QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0)
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
            continue;
        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
            if (qemuMonitorBlockJob(priv->mon, diskAlias, NULL, 0,
                                    NULL, BLOCK_JOB_ABORT, true) < 0) {
                VIR_WARN("Unable to cancel block-job on '%s'", diskAlias);
            }
            qemuDomainObjExitMonitor(driver, vm);
        } else {
            VIR_WARN("Unable to enter monitor. No block job cancelled");
        }
    }
    if (err)
        virSetError(err);
    virFreeError(err);
    goto cleanup;
}
1377

1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401

static void
qemuMigrationStopNBDServer(virQEMUDriverPtr driver,
                           virDomainObjPtr vm,
                           qemuMigrationCookiePtr mig)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;

    if (!mig->nbd)
        return;

    if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                       QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
        return;

    if (qemuMonitorNBDServerStop(priv->mon) < 0)
        VIR_WARN("Unable to stop NBD server");

    qemuDomainObjExitMonitor(driver, vm);

    virPortAllocatorRelease(driver->remotePorts, priv->nbdPort);
    priv->nbdPort = 0;
}

1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
static void
qemuMigrationCancelDriveMirror(qemuMigrationCookiePtr mig,
                               virQEMUDriverPtr driver,
                               virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    size_t i;
    char *diskAlias = NULL;

    VIR_DEBUG("mig=%p nbdPort=%d", mig->nbd, priv->nbdPort);

    for (i = 0; i < vm->def->ndisks; i++) {
        virDomainDiskDefPtr disk = vm->def->disks[i];

        /* skip shared, RO and source-less disks */
1417
        if (disk->shared || disk->readonly || !virDomainDiskGetSource(disk))
1418 1419 1420 1421
            continue;

        VIR_FREE(diskAlias);
        if (virAsprintf(&diskAlias, "%s%s",
1422
                        QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0)
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
            goto cleanup;

        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            goto cleanup;

        if (qemuMonitorBlockJob(priv->mon, diskAlias, NULL, 0,
                                NULL, BLOCK_JOB_ABORT, true) < 0)
            VIR_WARN("Unable to stop block job on %s", diskAlias);
        qemuDomainObjExitMonitor(driver, vm);
    }

1435
 cleanup:
1436 1437 1438 1439
    VIR_FREE(diskAlias);
    return;
}

1440 1441 1442 1443 1444 1445 1446 1447 1448
/* Validate whether the domain is safe to migrate.  If vm is NULL,
 * then this is being run in the v2 Prepare stage on the destination
 * (where we only have the target xml); if vm is provided, then this
 * is being run in either v2 Perform or v3 Begin (where we also have
 * access to all of the domain's metadata, such as whether it is
 * marked autodestroy or has snapshots).  While it would be nice to
 * assume that checking on source is sufficient to prevent ever
 * talking to the destination in the first place, we are stuck with
 * the fact that older servers did not do checks on the source. */
1449
bool
1450
qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm,
1451
                       virDomainDefPtr def, bool remote, bool abort_on_error)
1452
{
1453
    int nsnapshots;
1454
    int pauseReason;
1455
    bool forbid;
1456
    size_t i;
1457 1458 1459

    if (vm) {
        if (qemuProcessAutoDestroyActive(driver, vm)) {
1460 1461
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is marked for auto destroy"));
1462 1463
            return false;
        }
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476

        /* perform these checks only when migrating to remote hosts */
        if (remote) {
            nsnapshots = virDomainSnapshotObjListNum(vm->snapshots, NULL, 0);
            if (nsnapshots < 0)
                return false;

            if (nsnapshots > 0) {
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("cannot migrate domain with %d snapshots"),
                               nsnapshots);
                return false;
            }
1477 1478

            /* cancel migration if disk I/O error is emitted while migrating */
1479 1480
            if (abort_on_error &&
                virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
1481 1482 1483 1484 1485 1486
                pauseReason == VIR_DOMAIN_PAUSED_IOERROR) {
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("cannot migrate domain with I/O error"));
                return false;
            }

1487
        }
1488

E
Eric Blake 已提交
1489 1490
        if (virDomainHasDiskMirror(vm)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1491
                           _("domain has an active block job"));
E
Eric Blake 已提交
1492 1493
            return false;
        }
1494 1495 1496

        def = vm->def;
    }
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511

    /* Migration with USB host devices is allowed, all other devices are
     * forbidden.
     */
    forbid = false;
    for (i = 0; i < def->nhostdevs; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];
        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
            hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
            forbid = true;
            break;
        }
    }
    if (forbid) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1512
                       _("domain has assigned non-USB host devices"));
1513 1514 1515 1516 1517 1518
        return false;
    }

    return true;
}

1519 1520 1521
static bool
qemuMigrationIsSafe(virDomainDefPtr def)
{
1522
    size_t i;
1523

1524
    for (i = 0; i < def->ndisks; i++) {
1525
        virDomainDiskDefPtr disk = def->disks[i];
1526
        const char *src = virDomainDiskGetSource(disk);
1527

1528 1529
        /* Our code elsewhere guarantees shared disks are either readonly (in
         * which case cache mode doesn't matter) or used with cache=none */
1530
        if (src &&
1531 1532 1533
            !disk->shared &&
            !disk->readonly &&
            disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE) {
1534
            int rc;
1535

E
Eric Blake 已提交
1536
            if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_FILE) {
1537
                if ((rc = virStorageFileIsSharedFS(src)) < 0)
1538 1539
                    return false;
                else if (rc == 0)
1540
                    continue;
1541
                if ((rc = virStorageFileIsClusterFS(src)) < 0)
1542
                    return false;
1543 1544
                else if (rc == 1)
                    continue;
E
Eric Blake 已提交
1545
            } else if (disk->src.type == VIR_STORAGE_TYPE_NETWORK &&
1546
                       disk->src.protocol == VIR_STORAGE_NET_PROTOCOL_RBD) {
1547
                continue;
1548
            }
1549

1550 1551 1552
            virReportError(VIR_ERR_MIGRATE_UNSAFE, "%s",
                           _("Migration may lead to data corruption if disks"
                             " use cache != none"));
1553 1554 1555 1556 1557 1558 1559
            return false;
        }
    }

    return true;
}

1560 1561 1562 1563
/** qemuMigrationSetOffline
 * Pause domain for non-live migration.
 */
int
1564
qemuMigrationSetOffline(virQEMUDriverPtr driver,
1565 1566 1567
                        virDomainObjPtr vm)
{
    int ret;
1568
    VIR_DEBUG("driver=%p vm=%p", driver, vm);
1569 1570
    ret = qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_MIGRATION,
                              QEMU_ASYNC_JOB_MIGRATION_OUT);
1571
    if (ret == 0) {
1572
        virObjectEventPtr event;
1573

1574
        event = virDomainEventLifecycleNewFromObj(vm,
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }

    return ret;
}


1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
static int
qemuMigrationSetCompression(virQEMUDriverPtr driver,
                            virDomainObjPtr vm,
                            enum qemuDomainAsyncJob job)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int ret;

    if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0)
        return -1;

    ret = qemuMonitorGetMigrationCapability(
                priv->mon,
                QEMU_MONITOR_MIGRATION_CAPS_XBZRLE);

    if (ret < 0) {
        goto cleanup;
    } else if (ret == 0) {
        if (job == QEMU_ASYNC_JOB_MIGRATION_IN) {
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("Compressed migration is not supported by "
                             "target QEMU binary"));
        } else {
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("Compressed migration is not supported by "
                             "source QEMU binary"));
        }
        ret = -1;
        goto cleanup;
    }

    ret = qemuMonitorSetMigrationCapability(
                priv->mon,
                QEMU_MONITOR_MIGRATION_CAPS_XBZRLE);

1620
 cleanup:
1621 1622 1623 1624
    qemuDomainObjExitMonitor(driver, vm);
    return ret;
}

1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653
static int
qemuMigrationSetAutoConverge(virQEMUDriverPtr driver,
                             virDomainObjPtr vm,
                             enum qemuDomainAsyncJob job)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int ret;

    if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0)
        return -1;

    ret = qemuMonitorGetMigrationCapability(
                priv->mon,
                QEMU_MONITOR_MIGRATION_CAPS_AUTO_CONVERGE);

    if (ret < 0) {
        goto cleanup;
    } else if (ret == 0) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Auto-Converge is not supported by "
                         "QEMU binary"));
        ret = -1;
        goto cleanup;
    }

    ret = qemuMonitorSetMigrationCapability(
                priv->mon,
                QEMU_MONITOR_MIGRATION_CAPS_AUTO_CONVERGE);

1654
 cleanup:
1655 1656 1657 1658 1659
    qemuDomainObjExitMonitor(driver, vm);
    return ret;
}


1660 1661 1662 1663 1664 1665 1666
static int
qemuMigrationWaitForSpice(virQEMUDriverPtr driver,
                          virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    bool wait_for_spice = false;
    bool spice_migrated = false;
1667
    size_t i = 0;
1668

1669 1670 1671 1672 1673 1674 1675 1676
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION)) {
        for (i = 0; i < vm->def->ngraphics; i++) {
            if (vm->def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
                wait_for_spice = true;
                break;
            }
        }
    }
1677 1678 1679 1680 1681 1682 1683 1684

    if (!wait_for_spice)
        return 0;

    while (!spice_migrated) {
        /* Poll every 50ms for progress & to allow cancellation */
        struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };

1685 1686 1687 1688
        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            return -1;

1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701
        if (qemuMonitorGetSpiceMigrationStatus(priv->mon,
                                               &spice_migrated) < 0) {
            qemuDomainObjExitMonitor(driver, vm);
            return -1;
        }
        qemuDomainObjExitMonitor(driver, vm);
        virObjectUnlock(vm);
        nanosleep(&ts, NULL);
        virObjectLock(vm);
    }

    return 0;
}
1702

1703
static int
1704
qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
1705
                             virDomainObjPtr vm,
1706 1707
                             const char *job,
                             enum qemuDomainAsyncJob asyncJob)
1708
{
1709
    qemuDomainObjPrivatePtr priv = vm->privateData;
1710
    int ret;
1711 1712 1713
    qemuMonitorMigrationStatus status;

    memset(&status, 0, sizeof(status));
1714

1715 1716 1717
    ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob);
    if (ret < 0) {
        /* Guest already exited; nothing further to update.  */
1718 1719
        return -1;
    }
1720
    ret = qemuMonitorGetMigrationStatus(priv->mon, &status);
1721

1722
    qemuDomainObjExitMonitor(driver, vm);
1723

1724 1725
    priv->job.status = status;

1726
    if (ret < 0 || virTimeMillisNow(&priv->job.info.timeElapsed) < 0) {
1727
        priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
1728 1729
        return -1;
    }
1730
    priv->job.info.timeElapsed -= priv->job.start;
1731

1732
    ret = -1;
1733
    switch (priv->job.status.status) {
1734
    case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
1735
        priv->job.info.type = VIR_DOMAIN_JOB_NONE;
1736 1737
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("%s: %s"), job, _("is not active"));
1738 1739
        break;

M
Michael Avdienko 已提交
1740 1741 1742 1743
    case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
        ret = 0;
        break;

1744
    case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
        priv->job.info.fileTotal = priv->job.status.disk_total;
        priv->job.info.fileRemaining = priv->job.status.disk_remaining;
        priv->job.info.fileProcessed = priv->job.status.disk_transferred;

        priv->job.info.memTotal = priv->job.status.ram_total;
        priv->job.info.memRemaining = priv->job.status.ram_remaining;
        priv->job.info.memProcessed = priv->job.status.ram_transferred;

        priv->job.info.dataTotal =
            priv->job.status.ram_total + priv->job.status.disk_total;
        priv->job.info.dataRemaining =
            priv->job.status.ram_remaining + priv->job.status.disk_remaining;
        priv->job.info.dataProcessed =
            priv->job.status.ram_transferred +
            priv->job.status.disk_transferred;
1760 1761 1762 1763 1764

        ret = 0;
        break;

    case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
1765
        priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
1766 1767 1768 1769
        ret = 0;
        break;

    case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
1770
        priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
1771 1772
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("%s: %s"), job, _("unexpectedly failed"));
1773 1774 1775
        break;

    case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
1776
        priv->job.info.type = VIR_DOMAIN_JOB_CANCELLED;
1777 1778
        virReportError(VIR_ERR_OPERATION_ABORTED,
                       _("%s: %s"), job, _("canceled by client"));
1779 1780 1781 1782 1783 1784 1785
        break;
    }

    return ret;
}


1786
static int
1787
qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, virDomainObjPtr vm,
1788
                               enum qemuDomainAsyncJob asyncJob,
1789
                               virConnectPtr dconn, bool abort_on_error)
1790
{
1791
    qemuDomainObjPrivatePtr priv = vm->privateData;
1792
    const char *job;
1793
    int pauseReason;
1794

1795 1796
    switch (priv->job.asyncJob) {
    case QEMU_ASYNC_JOB_MIGRATION_OUT:
1797 1798
        job = _("migration job");
        break;
1799
    case QEMU_ASYNC_JOB_SAVE:
1800 1801
        job = _("domain save job");
        break;
1802
    case QEMU_ASYNC_JOB_DUMP:
1803 1804 1805 1806 1807
        job = _("domain core dump job");
        break;
    default:
        job = _("job");
    }
1808

1809
    priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
1810

1811
    while (priv->job.info.type == VIR_DOMAIN_JOB_UNBOUNDED) {
1812 1813 1814
        /* Poll every 50ms for progress & to allow cancellation */
        struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };

1815
        /* cancel migration if disk I/O error is emitted while migrating */
1816
        if (abort_on_error &&
1817 1818 1819 1820
            virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
            pauseReason == VIR_DOMAIN_PAUSED_IOERROR)
            goto cancel;

1821
        if (qemuMigrationUpdateJobStatus(driver, vm, job, asyncJob) < 0)
1822 1823
            goto cleanup;

1824
        if (dconn && virConnectIsAlive(dconn) <= 0) {
1825 1826
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("Lost connection to destination host"));
1827 1828 1829
            goto cleanup;
        }

1830
        virObjectUnlock(vm);
1831 1832 1833

        nanosleep(&ts, NULL);

1834
        virObjectLock(vm);
1835 1836
    }

1837
 cleanup:
1838
    if (priv->job.info.type == VIR_DOMAIN_JOB_COMPLETED)
1839 1840 1841
        return 0;
    else
        return -1;
1842

1843
 cancel:
1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
    if (virDomainObjIsActive(vm)) {
        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           priv->job.asyncJob) == 0) {
            qemuMonitorMigrateCancel(priv->mon);
            qemuDomainObjExitMonitor(driver, vm);
        }
    }

    priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
    virReportError(VIR_ERR_OPERATION_FAILED,
                   _("%s: %s"), job, _("failed due to I/O error"));
    return -1;
1856 1857 1858
}


1859
static int
1860
qemuDomainMigrateGraphicsRelocate(virQEMUDriverPtr driver,
1861
                                  virDomainObjPtr vm,
1862 1863
                                  qemuMigrationCookiePtr cookie,
                                  const char *graphicsuri)
1864 1865
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
1866 1867
    int ret = -1;
    const char *listenAddress = NULL;
1868
    virSocketAddr addr;
1869 1870 1871 1872 1873
    virURIPtr uri = NULL;
    int type = -1;
    int port = -1;
    int tlsPort = -1;
    const char *tlsSubject = NULL;
1874

1875
    if (!cookie || (!cookie->graphics && !graphicsuri))
1876 1877
        return 0;

1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896
    if (graphicsuri && !(uri = virURIParse(graphicsuri)))
        goto cleanup;

    if (cookie->graphics) {
        type = cookie->graphics->type;

        listenAddress = cookie->graphics->listen;

        if (!listenAddress ||
            (virSocketAddrParse(&addr, listenAddress, AF_UNSPEC) > 0 &&
             virSocketAddrIsWildcard(&addr)))
            listenAddress = cookie->remoteHostname;

        port = cookie->graphics->port;
        tlsPort = cookie->graphics->tlsPort;
        tlsSubject = cookie->graphics->tlsSubject;
    }

    if (uri) {
1897
        size_t i;
1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924

        if ((type = virDomainGraphicsTypeFromString(uri->scheme)) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unknown graphics type %s"), uri->scheme);
            goto cleanup;
        }

        if (uri->server)
            listenAddress = uri->server;
        if (uri->port > 0)
            port = uri->port;

        for (i = 0; i < uri->paramsCount; i++) {
            virURIParamPtr param = uri->params + i;

            if (STRCASEEQ(param->name, "tlsPort")) {
                if (virStrToLong_i(param->value, NULL, 10, &tlsPort) < 0) {
                    virReportError(VIR_ERR_INVALID_ARG,
                                   _("invalid tlsPort number: %s"),
                                   param->value);
                    goto cleanup;
                }
            } else if (STRCASEEQ(param->name, "tlsSubject")) {
                tlsSubject = param->value;
            }
        }
    }
1925 1926 1927 1928

    /* QEMU doesn't support VNC relocation yet, so
     * skip it to avoid generating an error
     */
1929 1930 1931 1932
    if (type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
        ret = 0;
        goto cleanup;
    }
1933

1934 1935 1936 1937
    if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                       QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
        ret = qemuMonitorGraphicsRelocate(priv->mon, type, listenAddress,
                                          port, tlsPort, tlsSubject);
1938
        qemuDomainObjExitMonitor(driver, vm);
1939
    }
1940

1941
 cleanup:
1942
    virURIFree(uri);
1943 1944 1945 1946
    return ret;
}


1947
static int
1948
qemuDomainMigrateOPDRelocate(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
1949 1950 1951
                             virDomainObjPtr vm,
                             qemuMigrationCookiePtr cookie)
{
1952 1953
    virDomainNetDefPtr netptr;
    int ret = -1;
1954
    size_t i;
1955 1956 1957 1958 1959 1960 1961 1962

    for (i = 0; i < cookie->network->nnets; i++) {
        netptr = vm->def->nets[i];

        switch (cookie->network->net[i].vporttype) {
        case VIR_NETDEV_VPORT_PROFILE_NONE:
        case VIR_NETDEV_VPORT_PROFILE_8021QBG:
        case VIR_NETDEV_VPORT_PROFILE_8021QBH:
1963
           break;
1964
        case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
1965 1966 1967 1968 1969 1970 1971 1972
            if (virNetDevOpenvswitchSetMigrateData(cookie->network->net[i].portdata,
                                                   netptr->ifname) != 0) {
                virReportSystemError(VIR_ERR_INTERNAL_ERROR,
                                     _("Unable to run command to set OVS port data for "
                                     "interface %s"), netptr->ifname);
                goto cleanup;
            }
            break;
1973 1974 1975 1976 1977
        default:
            break;
        }
    }

1978
    ret = 0;
1979
 cleanup:
1980 1981 1982 1983
    return ret;
}


1984 1985 1986 1987 1988 1989
/* This is called for outgoing non-p2p migrations when a connection to the
 * client which initiated the migration was closed but we were waiting for it
 * to follow up with the next phase, that is, in between
 * qemuDomainMigrateBegin3 and qemuDomainMigratePerform3 or
 * qemuDomainMigratePerform3 and qemuDomainMigrateConfirm3.
 */
1990 1991 1992 1993
static virDomainObjPtr
qemuMigrationCleanup(virDomainObjPtr vm,
                     virConnectPtr conn,
                     void *opaque)
1994
{
1995
    virQEMUDriverPtr driver = opaque;
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
    qemuDomainObjPrivatePtr priv = vm->privateData;

    VIR_DEBUG("vm=%s, conn=%p, asyncJob=%s, phase=%s",
              vm->def->name, conn,
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
              qemuDomainAsyncJobPhaseToString(priv->job.asyncJob,
                                              priv->job.phase));

    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT))
        goto cleanup;

    VIR_DEBUG("The connection which started outgoing migration of domain %s"
              " was closed; canceling the migration",
              vm->def->name);

    switch ((enum qemuMigrationJobPhase) priv->job.phase) {
    case QEMU_MIGRATION_PHASE_BEGIN3:
        /* just forget we were about to migrate */
        qemuDomainObjDiscardAsyncJob(driver, vm);
        break;

    case QEMU_MIGRATION_PHASE_PERFORM3_DONE:
        VIR_WARN("Migration of domain %s finished but we don't know if the"
                 " domain was successfully started on destination or not",
                 vm->def->name);
        /* clear the job and let higher levels decide what to do */
        qemuDomainObjDiscardAsyncJob(driver, vm);
        break;

    case QEMU_MIGRATION_PHASE_PERFORM3:
        /* cannot be seen without an active migration API; unreachable */
    case QEMU_MIGRATION_PHASE_CONFIRM3:
    case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED:
        /* all done; unreachable */
    case QEMU_MIGRATION_PHASE_PREPARE:
    case QEMU_MIGRATION_PHASE_FINISH2:
    case QEMU_MIGRATION_PHASE_FINISH3:
        /* incoming migration; unreachable */
    case QEMU_MIGRATION_PHASE_PERFORM2:
        /* single phase outgoing migration; unreachable */
    case QEMU_MIGRATION_PHASE_NONE:
    case QEMU_MIGRATION_PHASE_LAST:
        /* unreachable */
        ;
    }

2042
 cleanup:
2043 2044 2045
    return vm;
}

2046

2047
/* The caller is supposed to lock the vm and start a migration job. */
2048 2049
static char
*qemuMigrationBeginPhase(virQEMUDriverPtr driver,
2050
                         virDomainObjPtr vm,
2051
                         const char *xmlin,
2052
                         const char *dname,
2053
                         char **cookieout,
2054 2055
                         int *cookieoutlen,
                         unsigned long flags)
2056 2057 2058
{
    char *rv = NULL;
    qemuMigrationCookiePtr mig = NULL;
2059
    virDomainDefPtr def = NULL;
2060
    qemuDomainObjPrivatePtr priv = vm->privateData;
2061
    virCapsPtr caps = NULL;
2062
    unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE;
2063
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
2064

2065
    VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s,"
2066
              " cookieout=%p, cookieoutlen=%p, flags=%lx",
2067
              driver, vm, NULLSTR(xmlin), NULLSTR(dname),
2068
              cookieout, cookieoutlen, flags);
2069

2070 2071 2072
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

2073 2074 2075 2076 2077 2078
    /* Only set the phase if we are inside QEMU_ASYNC_JOB_MIGRATION_OUT.
     * Otherwise we will start the async job later in the perform phase losing
     * change protection.
     */
    if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT)
        qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_BEGIN3);
2079

2080
    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
2081 2082
        goto cleanup;

2083 2084 2085
    if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
        goto cleanup;

2086
    if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
2087
        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR)) {
2088
        /* TODO support NBD for TUNNELLED migration */
2089
        if (flags & VIR_MIGRATE_TUNNELLED) {
2090 2091 2092 2093
            VIR_WARN("NBD in tunnelled migration is currently not supported");
        } else {
            cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
            priv->nbdPort = 0;
2094 2095 2096
        }
    }

2097
    if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0)))
2098 2099 2100 2101
        goto cleanup;

    if (qemuMigrationBakeCookie(mig, driver, vm,
                                cookieout, cookieoutlen,
2102
                                cookieFlags) < 0)
2103 2104
        goto cleanup;

L
liguang 已提交
2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126
    if (flags & VIR_MIGRATE_OFFLINE) {
        if (flags & (VIR_MIGRATE_NON_SHARED_DISK |
                     VIR_MIGRATE_NON_SHARED_INC)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("offline migration cannot handle "
                             "non-shared storage"));
            goto cleanup;
        }
        if (!(flags & VIR_MIGRATE_PERSIST_DEST)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("offline migration must be specified with "
                             "the persistent flag set"));
            goto cleanup;
        }
        if (flags & VIR_MIGRATE_TUNNELLED) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("tunnelled offline migration does not "
                             "make sense"));
            goto cleanup;
        }
    }

2127
    if (xmlin) {
2128
        if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt,
M
Matthias Bolte 已提交
2129
                                            QEMU_EXPECTED_VIRT_TYPES,
2130 2131 2132
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

2133
        if (!qemuDomainDefCheckABIStability(driver, vm->def, def))
2134 2135
            goto cleanup;

2136
        rv = qemuDomainDefFormatLive(driver, def, false, true);
2137
    } else {
2138
        rv = qemuDomainDefFormatLive(driver, vm->def, false, true);
2139
    }
2140

2141
 cleanup:
2142
    qemuMigrationCookieFree(mig);
2143
    virObjectUnref(caps);
2144
    virDomainDefFree(def);
2145 2146 2147
    return rv;
}

2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170
char *
qemuMigrationBegin(virConnectPtr conn,
                   virDomainObjPtr vm,
                   const char *xmlin,
                   const char *dname,
                   char **cookieout,
                   int *cookieoutlen,
                   unsigned long flags)
{
    virQEMUDriverPtr driver = conn->privateData;
    char *xml = NULL;
    enum qemuDomainAsyncJob asyncJob;

    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            goto cleanup;
        asyncJob = QEMU_ASYNC_JOB_MIGRATION_OUT;
    } else {
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
            goto cleanup;
        asyncJob = QEMU_ASYNC_JOB_NONE;
    }

2171 2172
    qemuMigrationStoreDomainState(vm);

2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195
    if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto endjob;
    }

    /* Check if there is any ejected media.
     * We don't want to require them on the destination.
     */
    if (!(flags & VIR_MIGRATE_OFFLINE) &&
        qemuDomainCheckEjectableMedia(driver, vm, asyncJob) < 0)
        goto endjob;

    if (!(xml = qemuMigrationBeginPhase(driver, vm, xmlin, dname,
                                        cookieout, cookieoutlen,
                                        flags)))
        goto endjob;

    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        /* We keep the job active across API calls until the confirm() call.
         * This prevents any other APIs being invoked while migration is taking
         * place.
         */
2196 2197
        if (virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
                                 qemuMigrationCleanup) < 0)
2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210
            goto endjob;
        if (qemuMigrationJobContinue(vm) == 0) {
            vm = NULL;
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("domain disappeared"));
            VIR_FREE(xml);
            if (cookieout)
                VIR_FREE(*cookieout);
        }
    } else {
        goto endjob;
    }

2211
 cleanup:
2212 2213 2214 2215
    if (vm)
        virObjectUnlock(vm);
    return xml;

2216
 endjob:
2217 2218 2219 2220
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobFinish(driver, vm) == 0)
            vm = NULL;
    } else {
E
Eric Blake 已提交
2221
        if (!qemuDomainObjEndJob(driver, vm))
2222 2223 2224 2225 2226
            vm = NULL;
    }
    goto cleanup;
}

2227

2228 2229
/* Prepare is the first step, and it runs on the destination host.
 */
2230

2231
static void
2232
qemuMigrationPrepareCleanup(virQEMUDriverPtr driver,
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242
                            virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;

    VIR_DEBUG("driver=%p, vm=%s, job=%s, asyncJob=%s",
              driver,
              vm->def->name,
              qemuDomainJobTypeToString(priv->job.active),
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob));

2243 2244 2245
    virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
    priv->migrationPort = 0;

2246 2247 2248 2249 2250
    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
        return;
    qemuDomainObjDiscardAsyncJob(driver, vm);
}

2251
static int
2252
qemuMigrationPrepareAny(virQEMUDriverPtr driver,
2253 2254 2255 2256 2257
                        virConnectPtr dconn,
                        const char *cookiein,
                        int cookieinlen,
                        char **cookieout,
                        int *cookieoutlen,
2258
                        virDomainDefPtr *def,
2259
                        const char *origname,
L
liguang 已提交
2260
                        virStreamPtr st,
2261 2262
                        unsigned short port,
                        bool autoPort,
2263
                        const char *listenAddress,
L
liguang 已提交
2264
                        unsigned long flags)
2265 2266
{
    virDomainObjPtr vm = NULL;
2267
    virObjectEventPtr event = NULL;
2268
    int ret = -1;
2269
    int dataFD[2] = { -1, -1 };
2270
    qemuDomainObjPrivatePtr priv = NULL;
J
Jiri Denemark 已提交
2271
    unsigned long long now;
2272
    qemuMigrationCookiePtr mig = NULL;
2273
    bool tunnel = !!st;
J
Jiri Denemark 已提交
2274
    char *xmlout = NULL;
L
liguang 已提交
2275
    unsigned int cookieFlags;
2276
    virCapsPtr caps = NULL;
J
Ján Tomko 已提交
2277
    char *migrateFrom = NULL;
2278
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
2279
    bool taint_hook = false;
2280

2281
    if (virTimeMillisNow(&now) < 0)
2282 2283
        return -1;

L
liguang 已提交
2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305
    if (flags & VIR_MIGRATE_OFFLINE) {
        if (flags & (VIR_MIGRATE_NON_SHARED_DISK |
                     VIR_MIGRATE_NON_SHARED_INC)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("offline migration cannot handle "
                             "non-shared storage"));
            goto cleanup;
        }
        if (!(flags & VIR_MIGRATE_PERSIST_DEST)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("offline migration must be specified with "
                             "the persistent flag set"));
            goto cleanup;
        }
        if (tunnel) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("tunnelled offline migration does not "
                             "make sense"));
            goto cleanup;
        }
    }

2306 2307 2308
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

2309
    if (!qemuMigrationIsAllowed(driver, NULL, *def, true, abort_on_error))
2310 2311
        goto cleanup;

J
Jiri Denemark 已提交
2312 2313 2314 2315 2316
    /* Let migration hook filter domain XML */
    if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
        char *xml;
        int hookret;

2317
        if (!(xml = qemuDomainDefFormatXML(driver, *def,
2318 2319
                                           VIR_DOMAIN_XML_SECURE |
                                           VIR_DOMAIN_XML_MIGRATABLE)))
J
Jiri Denemark 已提交
2320 2321
            goto cleanup;

2322
        hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, (*def)->name,
J
Jiri Denemark 已提交
2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336
                              VIR_HOOK_QEMU_OP_MIGRATE, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, &xmlout);
        VIR_FREE(xml);

        if (hookret < 0) {
            goto cleanup;
        } else if (hookret == 0) {
            if (!*xmlout) {
                VIR_DEBUG("Migrate hook filter returned nothing; using the"
                          " original XML");
            } else {
                virDomainDefPtr newdef;

                VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
2337
                newdef = virDomainDefParseString(xmlout, caps, driver->xmlopt,
J
Jiri Denemark 已提交
2338 2339 2340 2341 2342
                                                 QEMU_EXPECTED_VIRT_TYPES,
                                                 VIR_DOMAIN_XML_INACTIVE);
                if (!newdef)
                    goto cleanup;

2343
                if (!qemuDomainDefCheckABIStability(driver, *def, newdef)) {
J
Jiri Denemark 已提交
2344 2345 2346 2347
                    virDomainDefFree(newdef);
                    goto cleanup;
                }

2348 2349
                virDomainDefFree(*def);
                *def = newdef;
2350 2351 2352 2353
                /* We should taint the domain here. However, @vm and therefore
                 * privateData too are still NULL, so just notice the fact and
                 * taint it later. */
                taint_hook = true;
J
Jiri Denemark 已提交
2354 2355 2356 2357
            }
        }
    }

J
Ján Tomko 已提交
2358 2359 2360 2361
    if (tunnel) {
        /* QEMU will be started with -incoming stdio
         * (which qemu_command might convert to exec:cat or fd:n)
         */
2362
        if (VIR_STRDUP(migrateFrom, "stdio") < 0)
J
Ján Tomko 已提交
2363 2364
            goto cleanup;
    } else {
2365 2366 2367 2368
        virSocketAddr listenAddressSocket;
        bool encloseAddress = false;
        bool hostIPv6Capable = false;
        bool qemuIPv6Capable = false;
J
Ján Tomko 已提交
2369 2370 2371 2372 2373
        virQEMUCapsPtr qemuCaps = NULL;
        struct addrinfo *info = NULL;
        struct addrinfo hints = { .ai_flags = AI_ADDRCONFIG,
                                  .ai_socktype = SOCK_STREAM };

2374 2375 2376 2377
        if (getaddrinfo("::", NULL, &hints, &info) == 0) {
            freeaddrinfo(info);
            hostIPv6Capable = true;
        }
J
Ján Tomko 已提交
2378
        if (!(qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
2379
                                                    (*def)->emulator)))
J
Ján Tomko 已提交
2380 2381
            goto cleanup;

2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408
        qemuIPv6Capable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_IPV6_MIGRATION);
        virObjectUnref(qemuCaps);

        if (listenAddress) {
            if (virSocketAddrIsNumeric(listenAddress)) {
                /* listenAddress is numeric IPv4 or IPv6 */
                if (virSocketAddrParse(&listenAddressSocket, listenAddress, AF_UNSPEC) < 0)
                    goto cleanup;

                /* address parsed successfully */
                if (VIR_SOCKET_ADDR_IS_FAMILY(&listenAddressSocket, AF_INET6)) {
                    if (!qemuIPv6Capable) {
                        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                                       _("qemu isn't capable of IPv6"));
                        goto cleanup;
                    }
                    if (!hostIPv6Capable) {
                        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                                       _("host isn't capable of IPv6"));
                        goto cleanup;
                    }
                    /* IPv6 address must be escaped in brackets on the cmd line */
                    encloseAddress = true;
                }
            } else {
                /* listenAddress is a hostname */
            }
J
Ján Tomko 已提交
2409
        } else {
2410 2411 2412 2413 2414
            /* Listen on :: instead of 0.0.0.0 if QEMU understands it
             * and there is at least one IPv6 address configured
             */
            listenAddress = qemuIPv6Capable && hostIPv6Capable ?
                encloseAddress = true, "::" : "0.0.0.0";
J
Ján Tomko 已提交
2415 2416
        }

2417 2418
        /* QEMU will be started with -incoming [<IPv6 addr>]:port,
         * -incoming <IPv4 addr>:port or -incoming <hostname>:port
J
Ján Tomko 已提交
2419
         */
2420 2421 2422 2423
        if ((encloseAddress &&
             virAsprintf(&migrateFrom, "tcp:[%s]:%d", listenAddress, port) < 0) ||
            (!encloseAddress &&
             virAsprintf(&migrateFrom, "tcp:%s:%d", listenAddress, port) < 0))
J
Ján Tomko 已提交
2424 2425 2426
            goto cleanup;
    }

2427
    if (!(vm = virDomainObjListAdd(driver->domains, *def,
2428
                                   driver->xmlopt,
2429 2430 2431
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
2432
        goto cleanup;
2433

2434
    *def = NULL;
2435
    priv = vm->privateData;
2436 2437
    if (VIR_STRDUP(priv->origname, origname) < 0)
        goto cleanup;
2438

2439 2440 2441 2442 2443
    if (taint_hook) {
        /* Domain XML has been altered by a hook script. */
        priv->hookRun = true;
    }

2444
    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
2445 2446
                                       QEMU_MIGRATION_COOKIE_LOCKSTATE |
                                       QEMU_MIGRATION_COOKIE_NBD)))
2447 2448
        goto cleanup;

2449
    if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
2450
        goto cleanup;
2451
    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PREPARE);
2452 2453 2454 2455

    /* Domain starts inactive, even if the domain XML had an id field. */
    vm->def->id = -1;

L
liguang 已提交
2456 2457 2458
    if (flags & VIR_MIGRATE_OFFLINE)
        goto done;

2459 2460
    if (tunnel &&
        (pipe(dataFD) < 0 || virSetCloseExec(dataFD[1]) < 0)) {
2461 2462
        virReportSystemError(errno, "%s",
                             _("cannot create pipe for tunnelled migration"));
2463 2464 2465 2466
        goto endjob;
    }

    /* Start the QEMU daemon, with the same command-line arguments plus
2467
     * -incoming $migrateFrom
2468
     */
2469 2470 2471
    if (qemuProcessStart(dconn, driver, vm, migrateFrom, dataFD[0], NULL, NULL,
                         VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START,
                         VIR_QEMU_PROCESS_START_PAUSED |
2472
                         VIR_QEMU_PROCESS_START_AUTODESTROY) < 0) {
2473
        virDomainAuditStart(vm, "migrated", false);
2474 2475 2476
        goto endjob;
    }

2477 2478 2479 2480
    if (tunnel) {
        if (virFDStreamOpen(st, dataFD[1]) < 0) {
            virReportSystemError(errno, "%s",
                                 _("cannot pass pipe for tunnelled migration"));
2481
            goto stop;
2482
        }
2483
        dataFD[1] = -1; /* 'st' owns the FD now & will close it */
2484 2485
    }

2486 2487 2488 2489 2490
    if (flags & VIR_MIGRATE_COMPRESSED &&
        qemuMigrationSetCompression(driver, vm,
                                    QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
        goto stop;

2491 2492 2493 2494 2495 2496 2497 2498
    if (mig->lockState) {
        VIR_DEBUG("Received lockstate %s", mig->lockState);
        VIR_FREE(priv->lockState);
        priv->lockState = mig->lockState;
        mig->lockState = NULL;
    } else {
        VIR_DEBUG("Received no lockstate");
    }
2499

2500
 done:
L
liguang 已提交
2501 2502 2503 2504 2505
    if (flags & VIR_MIGRATE_OFFLINE)
        cookieFlags = 0;
    else
        cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS;

2506 2507 2508
    if (mig->nbd &&
        flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER)) {
2509
        if (qemuMigrationStartNBDServer(driver, vm, listenAddress) < 0) {
2510 2511
            /* error already reported */
            goto endjob;
2512
        }
2513
        cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
2514 2515 2516 2517
    }

    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout,
                                cookieoutlen, cookieFlags) < 0) {
2518 2519 2520 2521 2522 2523 2524
        /* We could tear down the whole guest here, but
         * cookie data is (so far) non-critical, so that
         * seems a little harsh. We'll just warn for now.
         */
        VIR_WARN("Unable to encode migration cookie");
    }

2525 2526 2527
    if (qemuDomainCleanupAdd(vm, qemuMigrationPrepareCleanup) < 0)
        goto endjob;

L
liguang 已提交
2528 2529
    if (!(flags & VIR_MIGRATE_OFFLINE)) {
        virDomainAuditStart(vm, "migrated", true);
2530
        event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
2531 2532 2533
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_MIGRATED);
    }
2534

2535 2536 2537 2538
    /* We keep the job active across API calls until the finish() call.
     * This prevents any other APIs being invoked while incoming
     * migration is taking place.
     */
2539
    if (!qemuMigrationJobContinue(vm)) {
2540
        vm = NULL;
2541 2542
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("domain disappeared"));
2543
        goto cleanup;
2544
    }
2545

2546 2547
    if (autoPort)
        priv->migrationPort = port;
2548
    ret = 0;
2549

2550
 cleanup:
J
Ján Tomko 已提交
2551
    VIR_FREE(migrateFrom);
J
Jiri Denemark 已提交
2552
    VIR_FREE(xmlout);
2553 2554
    VIR_FORCE_CLOSE(dataFD[0]);
    VIR_FORCE_CLOSE(dataFD[1]);
2555
    if (vm) {
2556
        if (ret < 0) {
2557 2558 2559
            virPortAllocatorRelease(driver->remotePorts, priv->nbdPort);
            priv->nbdPort = 0;
        }
2560 2561 2562 2563
        if (ret >= 0 || vm->persistent)
            virObjectUnlock(vm);
        else
            qemuDomainRemoveInactive(driver, vm);
2564
    }
2565 2566
    if (event)
        qemuDomainEventQueue(driver, event);
2567
    qemuMigrationCookieFree(mig);
2568
    virObjectUnref(caps);
2569
    return ret;
2570

2571
 stop:
2572 2573 2574
    virDomainAuditStart(vm, "migrated", false);
    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0);

2575
 endjob:
2576
    if (!qemuMigrationJobFinish(driver, vm)) {
2577 2578 2579
        vm = NULL;
    }
    goto cleanup;
2580 2581 2582
}


2583 2584 2585 2586 2587
/*
 * This version starts an empty VM listening on a localhost TCP port, and
 * sets up the corresponding virStream to handle the incoming data.
 */
int
2588
qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
2589 2590 2591 2592 2593 2594
                           virConnectPtr dconn,
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
                           virStreamPtr st,
2595
                           virDomainDefPtr *def,
2596
                           const char *origname,
L
liguang 已提交
2597
                           unsigned long flags)
2598 2599 2600 2601
{
    int ret;

    VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
2602
              "cookieout=%p, cookieoutlen=%p, st=%p, def=%p, "
2603
              "origname=%s, flags=%lx",
2604
              driver, dconn, NULLSTR(cookiein), cookieinlen,
2605
              cookieout, cookieoutlen, st, *def, origname, flags);
2606

2607 2608 2609 2610 2611 2612
    if (st == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("tunnelled migration requested but NULL stream passed"));
        return -1;
    }

2613
    ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
2614
                                  cookieout, cookieoutlen, def, origname,
2615
                                  st, 0, false, NULL, flags);
2616 2617 2618 2619
    return ret;
}


2620
int
2621
qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
2622
                           virConnectPtr dconn,
2623 2624 2625 2626
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
2627 2628
                           const char *uri_in,
                           char **uri_out,
2629
                           virDomainDefPtr *def,
2630
                           const char *origname,
2631
                           const char *listenAddress,
L
liguang 已提交
2632
                           unsigned long flags)
2633
{
2634 2635
    unsigned short port = 0;
    bool autoPort = true;
2636 2637
    char *hostname = NULL;
    const char *p;
J
Ján Tomko 已提交
2638
    char *uri_str = NULL;
2639
    int ret = -1;
2640
    virURIPtr uri = NULL;
2641
    bool well_formed_uri = true;
J
Jiri Denemark 已提交
2642

2643 2644
    VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
              "cookieout=%p, cookieoutlen=%p, uri_in=%s, uri_out=%p, "
2645
              "def=%p, origname=%s, listenAddress=%s, flags=%lx",
2646 2647
              driver, dconn, NULLSTR(cookiein), cookieinlen,
              cookieout, cookieoutlen, NULLSTR(uri_in), uri_out,
2648
              *def, origname, NULLSTR(listenAddress), flags);
2649

2650 2651
    *uri_out = NULL;

2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662
    /* The URI passed in may be NULL or a string "tcp://somehostname:port".
     *
     * If the URI passed in is NULL then we allocate a port number
     * from our pool of port numbers and return a URI of
     * "tcp://ourhostname:port".
     *
     * If the URI passed in is not NULL then we try to parse out the
     * port number and use that (note that the hostname is assumed
     * to be a correct hostname which refers to the target machine).
     */
    if (uri_in == NULL) {
2663
        if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
2664
            goto cleanup;
2665

2666
        if ((hostname = virGetHostname()) == NULL)
2667 2668 2669
            goto cleanup;

        if (STRPREFIX(hostname, "localhost")) {
2670 2671 2672
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("hostname on destination resolved to localhost,"
                             " but migration requires an FQDN"));
2673 2674 2675 2676 2677
            goto cleanup;
        }

        /* XXX this really should have been a properly well-formed
         * URI, but we can't add in tcp:// now without breaking
2678
         * compatibility with old targets. We at least make the
2679 2680 2681
         * new targets accept both syntaxes though.
         */
        /* Caller frees */
2682
        if (virAsprintf(uri_out, "tcp:%s:%d", hostname, port) < 0)
2683 2684 2685 2686 2687 2688
            goto cleanup;
    } else {
        /* Check the URI starts with "tcp:".  We will escape the
         * URI when passing it to the qemu monitor, so bad
         * characters in hostname part don't matter.
         */
J
Ján Tomko 已提交
2689
        if (!(p = STRSKIP(uri_in, "tcp:"))) {
2690 2691 2692
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("only tcp URIs are supported for KVM/QEMU"
                             " migrations"));
2693 2694 2695
            goto cleanup;
        }

J
Ján Tomko 已提交
2696 2697
        /* Convert uri_in to well-formed URI with // after tcp: */
        if (!(STRPREFIX(uri_in, "tcp://"))) {
2698
            well_formed_uri = false;
2699
            if (virAsprintf(&uri_str, "tcp://%s", p) < 0)
J
Ján Tomko 已提交
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718
                goto cleanup;
        }

        uri = virURIParse(uri_str ? uri_str : uri_in);
        VIR_FREE(uri_str);

        if (uri == NULL) {
            virReportError(VIR_ERR_INVALID_ARG, _("unable to parse URI: %s"),
                           uri_in);
            goto cleanup;
        }

        if (uri->server == NULL) {
            virReportError(VIR_ERR_INVALID_ARG, _("missing host in migration"
                                                  " URI: %s"), uri_in);
            goto cleanup;
        }

        if (uri->port == 0) {
2719
            if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
2720
                goto cleanup;
2721

2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732
            if (well_formed_uri) {
                uri->port = port;

                /* Caller frees */
                if (!(*uri_out = virURIFormat(uri)))
                    goto cleanup;
            } else {
                /* Caller frees */
                if (virAsprintf(uri_out, "%s:%d", uri_in, port) < 0)
                    goto cleanup;
            }
2733 2734

        } else {
2735 2736
            port = uri->port;
            autoPort = false;
2737 2738 2739 2740 2741 2742
        }
    }

    if (*uri_out)
        VIR_DEBUG("Generated uri_out=%s", *uri_out);

2743
    ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
2744
                                  cookieout, cookieoutlen, def, origname,
2745
                                  NULL, port, autoPort, listenAddress, flags);
2746
 cleanup:
2747
    virURIFree(uri);
2748
    VIR_FREE(hostname);
2749
    if (ret != 0) {
2750
        VIR_FREE(*uri_out);
2751 2752 2753
        if (autoPort)
            virPortAllocatorRelease(driver->migrationPorts, port);
    }
2754 2755 2756 2757
    return ret;
}


2758 2759 2760
virDomainDefPtr
qemuMigrationPrepareDef(virQEMUDriverPtr driver,
                        const char *dom_xml,
2761 2762
                        const char *dname,
                        char **origname)
2763 2764 2765
{
    virCapsPtr caps = NULL;
    virDomainDefPtr def;
2766
    char *name = NULL;
2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782

    if (!dom_xml) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("no domain XML passed"));
        return NULL;
    }

    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        return NULL;

    if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt,
                                        QEMU_EXPECTED_VIRT_TYPES,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

    if (dname) {
2783
        name = def->name;
2784 2785 2786 2787 2788 2789
        if (VIR_STRDUP(def->name, dname) < 0) {
            virDomainDefFree(def);
            def = NULL;
        }
    }

2790
 cleanup:
2791
    virObjectUnref(caps);
2792 2793 2794 2795
    if (def && origname)
        *origname = name;
    else
        VIR_FREE(name);
2796 2797 2798 2799
    return def;
}


2800 2801 2802 2803 2804 2805 2806 2807 2808 2809
static int
qemuMigrationConfirmPhase(virQEMUDriverPtr driver,
                          virConnectPtr conn,
                          virDomainObjPtr vm,
                          const char *cookiein,
                          int cookieinlen,
                          unsigned int flags,
                          int retcode)
{
    qemuMigrationCookiePtr mig;
2810
    virObjectEventPtr event = NULL;
2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843
    int rv = -1;
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);

    VIR_DEBUG("driver=%p, conn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
              "flags=%x, retcode=%d",
              driver, conn, vm, NULLSTR(cookiein), cookieinlen,
              flags, retcode);

    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);

    qemuMigrationJobSetPhase(driver, vm,
                             retcode == 0
                             ? QEMU_MIGRATION_PHASE_CONFIRM3
                             : QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED);

    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0)))
        goto cleanup;

    if (flags & VIR_MIGRATE_OFFLINE)
        goto done;

    /* Did the migration go as planned?  If yes, kill off the
     * domain object, but if no, resume CPUs
     */
    if (retcode == 0) {
        /* If guest uses SPICE and supports seamless migration we have to hold
         * up domain shutdown until SPICE server transfers its data */
        qemuMigrationWaitForSpice(driver, vm);

        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED,
                        VIR_QEMU_PROCESS_STOP_MIGRATED);
        virDomainAuditStop(vm, "migrated");

2844
        event = virDomainEventLifecycleNewFromObj(vm,
2845 2846 2847 2848 2849 2850 2851
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
    } else {

        /* cancel any outstanding NBD jobs */
        qemuMigrationCancelDriveMirror(mig, driver, vm);

2852 2853 2854 2855
        if (qemuMigrationRestoreDomainState(conn, vm)) {
            event = virDomainEventLifecycleNewFromObj(vm,
                                                      VIR_DOMAIN_EVENT_RESUMED,
                                                      VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
2856 2857 2858 2859 2860 2861 2862 2863
        }

        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
            VIR_WARN("Failed to save status on vm %s", vm->def->name);
            goto cleanup;
        }
    }

2864
 done:
2865 2866 2867
    qemuMigrationCookieFree(mig);
    rv = 0;

2868
 cleanup:
2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898
    if (event)
        qemuDomainEventQueue(driver, event);
    virObjectUnref(cfg);
    return rv;
}

int
qemuMigrationConfirm(virConnectPtr conn,
                     virDomainObjPtr vm,
                     const char *cookiein,
                     int cookieinlen,
                     unsigned int flags,
                     int cancelled)
{
    virQEMUDriverPtr driver = conn->privateData;
    enum qemuMigrationJobPhase phase;
    virQEMUDriverConfigPtr cfg = NULL;
    int ret = -1;

    cfg = virQEMUDriverGetConfig(driver);

    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT))
        goto cleanup;

    if (cancelled)
        phase = QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED;
    else
        phase = QEMU_MIGRATION_PHASE_CONFIRM3;

    qemuMigrationJobStartPhase(driver, vm, phase);
2899 2900
    virCloseCallbacksUnset(driver->closeCallbacks, vm,
                           qemuMigrationCleanup);
2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915

    ret = qemuMigrationConfirmPhase(driver, conn, vm,
                                    cookiein, cookieinlen,
                                    flags, cancelled);

    if (qemuMigrationJobFinish(driver, vm) == 0) {
        vm = NULL;
    } else if (!virDomainObjIsActive(vm) &&
               (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) {
        if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
            virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
        qemuDomainRemoveInactive(driver, vm);
        vm = NULL;
    }

2916
 cleanup:
2917 2918 2919 2920 2921 2922 2923
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(cfg);
    return ret;
}


2924 2925
enum qemuMigrationDestinationType {
    MIGRATION_DEST_HOST,
2926
    MIGRATION_DEST_CONNECT_HOST,
2927
    MIGRATION_DEST_UNIX,
2928
    MIGRATION_DEST_FD,
2929
};
2930

2931 2932 2933 2934
enum qemuMigrationForwardType {
    MIGRATION_FWD_DIRECT,
    MIGRATION_FWD_STREAM,
};
2935

2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946
typedef struct _qemuMigrationSpec qemuMigrationSpec;
typedef qemuMigrationSpec *qemuMigrationSpecPtr;
struct _qemuMigrationSpec {
    enum qemuMigrationDestinationType destType;
    union {
        struct {
            const char *name;
            int port;
        } host;

        struct {
2947
            char *file;
2948 2949
            int sock;
        } unix_socket;
2950 2951 2952 2953 2954

        struct {
            int qemu;
            int local;
        } fd;
2955 2956 2957 2958 2959 2960 2961
    } dest;

    enum qemuMigrationForwardType fwdType;
    union {
        virStreamPtr stream;
    } fwd;
};
2962 2963 2964

#define TUNNEL_SEND_BUF_SIZE 65536

2965 2966 2967 2968 2969 2970 2971
typedef struct _qemuMigrationIOThread qemuMigrationIOThread;
typedef qemuMigrationIOThread *qemuMigrationIOThreadPtr;
struct _qemuMigrationIOThread {
    virThread thread;
    virStreamPtr st;
    int sock;
    virError err;
2972 2973
    int wakeupRecvFD;
    int wakeupSendFD;
2974 2975 2976
};

static void qemuMigrationIOFunc(void *arg)
2977
{
2978
    qemuMigrationIOThreadPtr data = arg;
2979 2980 2981 2982 2983 2984 2985
    char *buffer = NULL;
    struct pollfd fds[2];
    int timeout = -1;
    virErrorPtr err = NULL;

    VIR_DEBUG("Running migration tunnel; stream=%p, sock=%d",
              data->st, data->sock);
2986

2987
    if (VIR_ALLOC_N(buffer, TUNNEL_SEND_BUF_SIZE) < 0)
2988
        goto abrt;
2989

2990 2991 2992
    fds[0].fd = data->sock;
    fds[1].fd = data->wakeupRecvFD;

2993
    for (;;) {
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003
        int ret;

        fds[0].events = fds[1].events = POLLIN;
        fds[0].revents = fds[1].revents = 0;

        ret = poll(fds, ARRAY_CARDINALITY(fds), timeout);

        if (ret < 0) {
            if (errno == EAGAIN || errno == EINTR)
                continue;
3004
            virReportSystemError(errno, "%s",
3005 3006
                                 _("poll failed in migration tunnel"));
            goto abrt;
3007
        }
3008 3009 3010 3011 3012 3013 3014

        if (ret == 0) {
            /* We were asked to gracefully stop but reading would block. This
             * can only happen if qemu told us migration finished but didn't
             * close the migration fd. We handle this in the same way as EOF.
             */
            VIR_DEBUG("QEMU forgot to close migration fd");
3015
            break;
3016
        }
3017

3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033
        if (fds[1].revents & (POLLIN | POLLERR | POLLHUP)) {
            char stop = 0;

            if (saferead(data->wakeupRecvFD, &stop, 1) != 1) {
                virReportSystemError(errno, "%s",
                                     _("failed to read from wakeup fd"));
                goto abrt;
            }

            VIR_DEBUG("Migration tunnel was asked to %s",
                      stop ? "abort" : "finish");
            if (stop) {
                goto abrt;
            } else {
                timeout = 0;
            }
3034 3035
        }

3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052
        if (fds[0].revents & (POLLIN | POLLERR | POLLHUP)) {
            int nbytes;

            nbytes = saferead(data->sock, buffer, TUNNEL_SEND_BUF_SIZE);
            if (nbytes > 0) {
                if (virStreamSend(data->st, buffer, nbytes) < 0)
                    goto error;
            } else if (nbytes < 0) {
                virReportSystemError(errno, "%s",
                        _("tunnelled migration failed to read from qemu"));
                goto abrt;
            } else {
                /* EOF; get out of here */
                break;
            }
        }
    }
3053

3054 3055
    if (virStreamFinish(data->st) < 0)
        goto error;
3056

3057 3058
    VIR_FREE(buffer);

3059 3060
    return;

3061
 abrt:
3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072
    err = virSaveLastError();
    if (err && err->code == VIR_ERR_OK) {
        virFreeError(err);
        err = NULL;
    }
    virStreamAbort(data->st);
    if (err) {
        virSetError(err);
        virFreeError(err);
    }

3073
 error:
3074 3075
    virCopyLastError(&data->err);
    virResetLastError();
3076
    VIR_FREE(buffer);
3077 3078 3079 3080 3081 3082 3083
}


static qemuMigrationIOThreadPtr
qemuMigrationStartTunnel(virStreamPtr st,
                         int sock)
{
3084 3085
    qemuMigrationIOThreadPtr io = NULL;
    int wakeupFD[2] = { -1, -1 };
3086

3087 3088 3089 3090
    if (pipe2(wakeupFD, O_CLOEXEC) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to make pipe"));
        goto error;
3091 3092
    }

3093
    if (VIR_ALLOC(io) < 0)
3094
        goto error;
3095

3096 3097
    io->st = st;
    io->sock = sock;
3098 3099
    io->wakeupRecvFD = wakeupFD[0];
    io->wakeupSendFD = wakeupFD[1];
3100 3101 3102 3103 3104 3105

    if (virThreadCreate(&io->thread, true,
                        qemuMigrationIOFunc,
                        io) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to create migration thread"));
3106
        goto error;
3107 3108 3109
    }

    return io;
3110

3111
 error:
3112 3113 3114 3115
    VIR_FORCE_CLOSE(wakeupFD[0]);
    VIR_FORCE_CLOSE(wakeupFD[1]);
    VIR_FREE(io);
    return NULL;
3116 3117 3118
}

static int
3119
qemuMigrationStopTunnel(qemuMigrationIOThreadPtr io, bool error)
3120 3121
{
    int rv = -1;
3122 3123 3124 3125 3126 3127 3128 3129 3130
    char stop = error ? 1 : 0;

    /* make sure the thread finishes its job and is joinable */
    if (safewrite(io->wakeupSendFD, &stop, 1) != 1) {
        virReportSystemError(errno, "%s",
                             _("failed to wakeup migration tunnel"));
        goto cleanup;
    }

3131 3132 3133 3134
    virThreadJoin(&io->thread);

    /* Forward error from the IO thread, to this thread */
    if (io->err.code != VIR_ERR_OK) {
3135 3136 3137 3138
        if (error)
            rv = 0;
        else
            virSetError(&io->err);
3139 3140 3141 3142 3143 3144
        virResetError(&io->err);
        goto cleanup;
    }

    rv = 0;

3145
 cleanup:
3146 3147
    VIR_FORCE_CLOSE(io->wakeupSendFD);
    VIR_FORCE_CLOSE(io->wakeupRecvFD);
3148 3149
    VIR_FREE(io);
    return rv;
3150 3151
}

3152
static int
3153
qemuMigrationConnect(virQEMUDriverPtr driver,
3154 3155 3156 3157 3158 3159 3160 3161 3162
                     virDomainObjPtr vm,
                     qemuMigrationSpecPtr spec)
{
    virNetSocketPtr sock;
    const char *host;
    char *port = NULL;
    int ret = -1;

    host = spec->dest.host.name;
3163
    if (virAsprintf(&port, "%d", spec->dest.host.port) < 0)
3164 3165 3166 3167 3168 3169 3170 3171 3172
        return -1;

    spec->destType = MIGRATION_DEST_FD;
    spec->dest.fd.qemu = -1;

    if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0)
        goto cleanup;
    if (virNetSocketNewConnectTCP(host, port, &sock) == 0) {
        spec->dest.fd.qemu = virNetSocketDupFD(sock, true);
3173
        virObjectUnref(sock);
3174 3175 3176 3177 3178
    }
    if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0 ||
        spec->dest.fd.qemu == -1)
        goto cleanup;

3179 3180 3181 3182 3183 3184 3185
    /* Migration expects a blocking FD */
    if (virSetBlocking(spec->dest.fd.qemu, true) < 0) {
        virReportSystemError(errno, _("Unable to set FD %d blocking"),
                             spec->dest.fd.qemu);
        goto cleanup;
    }

3186 3187
    ret = 0;

3188
 cleanup:
3189 3190 3191 3192 3193 3194
    VIR_FREE(port);
    if (ret < 0)
        VIR_FORCE_CLOSE(spec->dest.fd.qemu);
    return ret;
}

3195
static int
3196
qemuMigrationRun(virQEMUDriverPtr driver,
3197 3198 3199 3200 3201 3202 3203
                 virDomainObjPtr vm,
                 const char *cookiein,
                 int cookieinlen,
                 char **cookieout,
                 int *cookieoutlen,
                 unsigned long flags,
                 unsigned long resource,
3204
                 qemuMigrationSpecPtr spec,
3205 3206
                 virConnectPtr dconn,
                 const char *graphicsuri)
3207
{
3208
    int ret = -1;
3209 3210
    unsigned int migrate_flags = QEMU_MONITOR_MIGRATE_BACKGROUND;
    qemuDomainObjPrivatePtr priv = vm->privateData;
3211
    qemuMigrationCookiePtr mig = NULL;
3212
    qemuMigrationIOThreadPtr iothread = NULL;
3213
    int fd = -1;
3214
    unsigned long migrate_speed = resource ? resource : priv->migMaxBandwidth;
3215
    virErrorPtr orig_err = NULL;
3216
    unsigned int cookieFlags = 0;
3217
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
3218 3219 3220

    VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
              "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
3221
              "spec=%p (dest=%d, fwd=%d), dconn=%p, graphicsuri=%s",
3222 3223
              driver, vm, NULLSTR(cookiein), cookieinlen,
              cookieout, cookieoutlen, flags, resource,
3224 3225
              spec, spec->destType, spec->fwdType, dconn,
              NULLSTR(graphicsuri));
3226

3227 3228 3229 3230 3231 3232 3233 3234 3235 3236
    if (flags & VIR_MIGRATE_NON_SHARED_DISK) {
        migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
        cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
    }

    if (flags & VIR_MIGRATE_NON_SHARED_INC) {
        migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC;
        cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
    }

3237 3238
    if (virLockManagerPluginUsesState(driver->lockManager) &&
        !cookieout) {
3239 3240 3241 3242
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Migration with lock driver %s requires"
                         " cookie support"),
                       virLockManagerPluginGetName(driver->lockManager));
3243 3244 3245
        return -1;
    }

3246 3247 3248
    mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
                                 cookieFlags | QEMU_MIGRATION_COOKIE_GRAPHICS);
    if (!mig)
3249 3250
        goto cleanup;

3251
    if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig, graphicsuri) < 0)
3252 3253
        VIR_WARN("unable to provide data for graphics client relocation");

3254 3255 3256 3257 3258 3259 3260
    /* this will update migrate_flags on success */
    if (qemuMigrationDriveMirror(driver, vm, mig, spec->dest.host.name,
                                 migrate_speed, &migrate_flags) < 0) {
        /* error reported by helper func */
        goto cleanup;
    }

3261
    /* Before EnterMonitor, since qemuMigrationSetOffline already does that */
3262 3263 3264 3265 3266 3267
    if (!(flags & VIR_MIGRATE_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
        if (qemuMigrationSetOffline(driver, vm) < 0)
            goto cleanup;
    }

3268 3269 3270 3271 3272
    if (flags & VIR_MIGRATE_COMPRESSED &&
        qemuMigrationSetCompression(driver, vm,
                                    QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
        goto cleanup;

3273 3274 3275 3276 3277
    if (flags & VIR_MIGRATE_AUTO_CONVERGE &&
        qemuMigrationSetAutoConverge(driver, vm,
                                     QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
        goto cleanup;

3278 3279
    if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                       QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
3280 3281
        goto cleanup;

3282 3283 3284 3285
    if (priv->job.asyncAbort) {
        /* explicitly do this *after* we entered the monitor,
         * as this is a critical section so we are guaranteed
         * priv->job.asyncAbort will not change */
3286
        qemuDomainObjExitMonitor(driver, vm);
3287 3288 3289 3290 3291 3292
        virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
                       qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
                       _("canceled by client"));
        goto cleanup;
    }

3293
    if (qemuMonitorSetMigrationSpeed(priv->mon, migrate_speed) < 0) {
3294
        qemuDomainObjExitMonitor(driver, vm);
3295 3296
        goto cleanup;
    }
3297

3298 3299
    /* connect to the destination qemu if needed */
    if (spec->destType == MIGRATION_DEST_CONNECT_HOST &&
3300
        qemuMigrationConnect(driver, vm, spec) < 0) {
3301
        qemuDomainObjExitMonitor(driver, vm);
3302
        goto cleanup;
3303
    }
3304

3305 3306 3307 3308 3309 3310 3311
    switch (spec->destType) {
    case MIGRATION_DEST_HOST:
        ret = qemuMonitorMigrateToHost(priv->mon, migrate_flags,
                                       spec->dest.host.name,
                                       spec->dest.host.port);
        break;

3312 3313 3314 3315
    case MIGRATION_DEST_CONNECT_HOST:
        /* handled above and transformed into MIGRATION_DEST_FD */
        break;

3316
    case MIGRATION_DEST_UNIX:
3317
        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX)) {
3318 3319 3320 3321 3322 3323 3324 3325 3326
            ret = qemuMonitorMigrateToUnix(priv->mon, migrate_flags,
                                           spec->dest.unix_socket.file);
        } else {
            const char *args[] = {
                "nc", "-U", spec->dest.unix_socket.file, NULL
            };
            ret = qemuMonitorMigrateToCommand(priv->mon, migrate_flags, args);
        }
        break;
3327 3328

    case MIGRATION_DEST_FD:
3329
        if (spec->fwdType != MIGRATION_FWD_DIRECT) {
3330
            fd = spec->dest.fd.local;
3331 3332
            spec->dest.fd.local = -1;
        }
3333 3334 3335 3336
        ret = qemuMonitorMigrateToFd(priv->mon, migrate_flags,
                                     spec->dest.fd.qemu);
        VIR_FORCE_CLOSE(spec->dest.fd.qemu);
        break;
3337
    }
3338
    qemuDomainObjExitMonitor(driver, vm);
3339
    if (ret < 0)
3340 3341
        goto cleanup;
    ret = -1;
3342 3343

    if (!virDomainObjIsActive(vm)) {
3344 3345
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("guest unexpectedly quit"));
3346 3347 3348 3349 3350 3351
        goto cleanup;
    }

    /* From this point onwards we *must* call cancel to abort the
     * migration on source if anything goes wrong */

3352 3353 3354 3355 3356 3357 3358 3359
    if (spec->destType == MIGRATION_DEST_UNIX) {
        /* It is also possible that the migrate didn't fail initially, but
         * rather failed later on.  Check its status before waiting for a
         * connection from qemu which may never be initiated.
         */
        if (qemuMigrationUpdateJobStatus(driver, vm, _("migration job"),
                                         QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            goto cancel;
3360

3361 3362 3363 3364 3365 3366 3367
        while ((fd = accept(spec->dest.unix_socket.sock, NULL, NULL)) < 0) {
            if (errno == EAGAIN || errno == EINTR)
                continue;
            virReportSystemError(errno, "%s",
                                 _("failed to accept connection from qemu"));
            goto cancel;
        }
3368 3369
    }

3370 3371
    if (spec->fwdType != MIGRATION_FWD_DIRECT &&
        !(iothread = qemuMigrationStartTunnel(spec->fwd.stream, fd)))
3372 3373
        goto cancel;

3374
    if (qemuMigrationWaitForCompletion(driver, vm,
3375
                                       QEMU_ASYNC_JOB_MIGRATION_OUT,
3376
                                       dconn, abort_on_error) < 0)
3377
        goto cleanup;
3378

3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391
    /* When migration completed, QEMU will have paused the
     * CPUs for us, but unless we're using the JSON monitor
     * we won't have been notified of this, so might still
     * think we're running. For v2 protocol this doesn't
     * matter because we'll kill the VM soon, but for v3
     * this is important because we stay paused until the
     * confirm3 step, but need to release the lock state
     */
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
        if (qemuMigrationSetOffline(driver, vm) < 0)
            goto cleanup;
    }

3392
    ret = 0;
3393

3394
 cleanup:
3395 3396 3397
    if (ret < 0 && !orig_err)
        orig_err = virSaveLastError();

3398 3399 3400
    /* cancel any outstanding NBD jobs */
    qemuMigrationCancelDriveMirror(mig, driver, vm);

3401
    if (spec->fwdType != MIGRATION_FWD_DIRECT) {
3402
        if (iothread && qemuMigrationStopTunnel(iothread, ret < 0) < 0)
3403
            ret = -1;
3404
        VIR_FORCE_CLOSE(fd);
3405
    }
3406

3407 3408 3409
    cookieFlags |= QEMU_MIGRATION_COOKIE_NETWORK;
    if (flags & VIR_MIGRATE_PERSIST_DEST)
        cookieFlags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
3410
    if (ret == 0 &&
3411 3412
        qemuMigrationBakeCookie(mig, driver, vm, cookieout,
                                cookieoutlen, cookieFlags) < 0) {
3413
        VIR_WARN("Unable to encode migration cookie");
3414
    }
3415

3416 3417
    qemuMigrationCookieFree(mig);

3418 3419 3420 3421 3422
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }

3423 3424
    return ret;

3425
 cancel:
3426 3427
    orig_err = virSaveLastError();

3428
    if (virDomainObjIsActive(vm)) {
3429 3430
        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
3431
            qemuMonitorMigrateCancel(priv->mon);
3432
            qemuDomainObjExitMonitor(driver, vm);
3433
        }
3434
    }
3435 3436 3437 3438 3439 3440
    goto cleanup;
}

/* Perform migration using QEMU's native TCP migrate support,
 * not encrypted obviously
 */
3441
static int doNativeMigrate(virQEMUDriverPtr driver,
3442 3443 3444 3445 3446 3447 3448
                           virDomainObjPtr vm,
                           const char *uri,
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
                           unsigned long flags,
3449
                           unsigned long resource,
3450 3451
                           virConnectPtr dconn,
                           const char *graphicsuri)
3452
{
3453
    qemuDomainObjPrivatePtr priv = vm->privateData;
M
Martin Kletzander 已提交
3454
    virURIPtr uribits = NULL;
3455
    int ret = -1;
3456 3457 3458
    qemuMigrationSpec spec;

    VIR_DEBUG("driver=%p, vm=%p, uri=%s, cookiein=%s, cookieinlen=%d, "
3459 3460
              "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
              "graphicsuri=%s",
3461
              driver, vm, uri, NULLSTR(cookiein), cookieinlen,
3462 3463
              cookieout, cookieoutlen, flags, resource,
              NULLSTR(graphicsuri));
3464 3465

    if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) {
3466
        char *tmp;
3467
        /* HACK: source host generates bogus URIs, so fix them up */
3468
        if (virAsprintf(&tmp, "tcp://%s", uri + strlen("tcp:")) < 0)
3469
            return -1;
M
Martin Kletzander 已提交
3470
        uribits = virURIParse(tmp);
3471
        VIR_FREE(tmp);
3472
    } else {
M
Martin Kletzander 已提交
3473
        uribits = virURIParse(uri);
3474
    }
3475
    if (!uribits)
3476 3477
        return -1;

3478
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD))
3479 3480
        spec.destType = MIGRATION_DEST_CONNECT_HOST;
    else
3481
        spec.destType = MIGRATION_DEST_HOST;
3482 3483 3484
    spec.dest.host.name = uribits->server;
    spec.dest.host.port = uribits->port;
    spec.fwdType = MIGRATION_FWD_DIRECT;
3485

3486
    ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
3487 3488
                           cookieoutlen, flags, resource, &spec, dconn,
                           graphicsuri);
3489 3490 3491 3492

    if (spec.destType == MIGRATION_DEST_FD)
        VIR_FORCE_CLOSE(spec.dest.fd.qemu);

3493
    virURIFree(uribits);
3494 3495 3496 3497 3498

    return ret;
}


3499
static int doTunnelMigrate(virQEMUDriverPtr driver,
3500 3501 3502 3503 3504 3505 3506
                           virDomainObjPtr vm,
                           virStreamPtr st,
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
                           unsigned long flags,
3507
                           unsigned long resource,
3508 3509
                           virConnectPtr dconn,
                           const char *graphicsuri)
3510 3511
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
3512
    virNetSocketPtr sock = NULL;
3513 3514
    int ret = -1;
    qemuMigrationSpec spec;
3515
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3516 3517

    VIR_DEBUG("driver=%p, vm=%p, st=%p, cookiein=%s, cookieinlen=%d, "
3518 3519
              "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
              "graphicsuri=%s",
3520
              driver, vm, st, NULLSTR(cookiein), cookieinlen,
3521 3522
              cookieout, cookieoutlen, flags, resource,
              NULLSTR(graphicsuri));
3523

3524 3525 3526
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
        !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX) &&
        !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) {
3527 3528
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Source qemu is too old to support tunnelled migration"));
3529
        virObjectUnref(cfg);
3530
        return -1;
3531 3532 3533 3534 3535
    }

    spec.fwdType = MIGRATION_FWD_STREAM;
    spec.fwd.stream = st;

3536
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD)) {
3537 3538 3539 3540 3541 3542
        int fds[2];

        spec.destType = MIGRATION_DEST_FD;
        spec.dest.fd.qemu = -1;
        spec.dest.fd.local = -1;

3543
        if (pipe2(fds, O_CLOEXEC) == 0) {
3544 3545 3546 3547
            spec.dest.fd.qemu = fds[1];
            spec.dest.fd.local = fds[0];
        }
        if (spec.dest.fd.qemu == -1 ||
3548
            virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
3549
                                              spec.dest.fd.qemu) < 0) {
3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560
            virReportSystemError(errno, "%s",
                        _("cannot create pipe for tunnelled migration"));
            goto cleanup;
        }
    } else {
        spec.destType = MIGRATION_DEST_UNIX;
        spec.dest.unix_socket.sock = -1;
        spec.dest.unix_socket.file = NULL;

        if (virAsprintf(&spec.dest.unix_socket.file,
                        "%s/qemu.tunnelmigrate.src.%s",
3561
                        cfg->libDir, vm->def->name) < 0)
3562 3563 3564
            goto cleanup;

        if (virNetSocketNewListenUNIX(spec.dest.unix_socket.file, 0700,
3565
                                      cfg->user, cfg->group,
3566 3567 3568 3569 3570 3571 3572
                                      &sock) < 0 ||
            virNetSocketListen(sock, 1) < 0)
            goto cleanup;

        spec.dest.unix_socket.sock = virNetSocketGetFD(sock);
    }

3573
    ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
3574 3575
                           cookieoutlen, flags, resource, &spec, dconn,
                           graphicsuri);
3576

3577
 cleanup:
3578 3579 3580 3581
    if (spec.destType == MIGRATION_DEST_FD) {
        VIR_FORCE_CLOSE(spec.dest.fd.qemu);
        VIR_FORCE_CLOSE(spec.dest.fd.local);
    } else {
3582
        virObjectUnref(sock);
3583 3584
        VIR_FREE(spec.dest.unix_socket.file);
    }
3585

3586
    virObjectUnref(cfg);
3587 3588 3589 3590
    return ret;
}


3591 3592 3593 3594
/* This is essentially a re-impl of virDomainMigrateVersion2
 * from libvirt.c, but running in source libvirtd context,
 * instead of client app context & also adding in tunnel
 * handling */
3595
static int doPeer2PeerMigrate2(virQEMUDriverPtr driver,
3596
                               virConnectPtr sconn ATTRIBUTE_UNUSED,
3597 3598
                               virConnectPtr dconn,
                               virDomainObjPtr vm,
3599
                               const char *dconnuri,
3600 3601 3602
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
3603 3604 3605
{
    virDomainPtr ddomain = NULL;
    char *uri_out = NULL;
3606
    char *cookie = NULL;
3607 3608 3609
    char *dom_xml = NULL;
    int cookielen = 0, ret;
    virErrorPtr orig_err = NULL;
3610
    bool cancelled;
3611
    virStreamPtr st = NULL;
3612
    unsigned long destflags;
3613

3614
    VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, vm=%p, dconnuri=%s, "
3615
              "flags=%lx, dname=%s, resource=%lu",
3616 3617
              driver, sconn, dconn, vm, NULLSTR(dconnuri),
              flags, NULLSTR(dname), resource);
3618

3619 3620 3621 3622 3623
    /* In version 2 of the protocol, the prepare step is slightly
     * different.  We fetch the domain XML of the source domain
     * and pass it to Prepare2.
     */
    if (!(dom_xml = qemuDomainFormatXML(driver, vm,
3624 3625
                                        QEMU_DOMAIN_FORMAT_LIVE_FLAGS |
                                        VIR_DOMAIN_XML_MIGRATABLE)))
3626 3627 3628 3629 3630
        return -1;

    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
        flags |= VIR_MIGRATE_PAUSED;

3631 3632
    destflags = flags & ~(VIR_MIGRATE_ABORT_ON_ERROR |
                          VIR_MIGRATE_AUTO_CONVERGE);
3633

3634 3635 3636 3637 3638 3639 3640 3641 3642 3643
    VIR_DEBUG("Prepare2 %p", dconn);
    if (flags & VIR_MIGRATE_TUNNELLED) {
        /*
         * Tunnelled Migrate Version 2 does not support cookies
         * due to missing parameters in the prepareTunnel() API.
         */

        if (!(st = virStreamNew(dconn, 0)))
            goto cleanup;

3644
        qemuDomainObjEnterRemote(vm);
3645
        ret = dconn->driver->domainMigratePrepareTunnel
3646
            (dconn, st, destflags, dname, resource, dom_xml);
3647
        qemuDomainObjExitRemote(vm);
3648
    } else {
3649
        qemuDomainObjEnterRemote(vm);
3650 3651
        ret = dconn->driver->domainMigratePrepare2
            (dconn, &cookie, &cookielen, NULL, &uri_out,
3652
             destflags, dname, resource, dom_xml);
3653
        qemuDomainObjExitRemote(vm);
3654 3655 3656
    }
    VIR_FREE(dom_xml);
    if (ret == -1)
3657 3658 3659
        goto cleanup;

    /* the domain may have shutdown or crashed while we had the locks dropped
3660
     * in qemuDomainObjEnterRemote, so check again
3661 3662
     */
    if (!virDomainObjIsActive(vm)) {
3663 3664
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("guest unexpectedly quit"));
3665 3666 3667
        goto cleanup;
    }

3668 3669
    if (!(flags & VIR_MIGRATE_TUNNELLED) &&
        (uri_out == NULL)) {
3670 3671
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("domainMigratePrepare2 did not set uri"));
3672
        cancelled = true;
3673
        orig_err = virSaveLastError();
3674
        goto finish;
3675 3676
    }

3677 3678 3679 3680
    /* Perform the migration.  The driver isn't supposed to return
     * until the migration is complete.
     */
    VIR_DEBUG("Perform %p", sconn);
3681
    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
3682
    if (flags & VIR_MIGRATE_TUNNELLED)
3683 3684
        ret = doTunnelMigrate(driver, vm, st,
                              NULL, 0, NULL, NULL,
3685
                              flags, resource, dconn, NULL);
3686 3687 3688 3689
    else
        ret = doNativeMigrate(driver, vm, uri_out,
                              cookie, cookielen,
                              NULL, NULL, /* No out cookie with v2 migration */
3690
                              flags, resource, dconn, NULL);
3691 3692 3693 3694

    /* Perform failed. Make sure Finish doesn't overwrite the error */
    if (ret < 0)
        orig_err = virSaveLastError();
3695

3696 3697 3698
    /* If Perform returns < 0, then we need to cancel the VM
     * startup on the destination
     */
3699
    cancelled = ret < 0;
3700

3701
 finish:
3702 3703 3704 3705
    /* In version 2 of the migration protocol, we pass the
     * status code from the sender to the destination host,
     * so it can do any cleanup if the migration failed.
     */
3706
    dname = dname ? dname : vm->def->name;
3707
    VIR_DEBUG("Finish2 %p ret=%d", dconn, ret);
3708
    qemuDomainObjEnterRemote(vm);
3709
    ddomain = dconn->driver->domainMigrateFinish2
3710
        (dconn, dname, cookie, cookielen,
3711
         uri_out ? uri_out : dconnuri, destflags, cancelled);
3712
    qemuDomainObjExitRemote(vm);
3713 3714
    if (cancelled && ddomain)
        VIR_ERROR(_("finish step ignored that migration was cancelled"));
3715

3716
 cleanup:
3717
    if (ddomain) {
3718
        virObjectUnref(ddomain);
3719 3720 3721 3722
        ret = 0;
    } else {
        ret = -1;
    }
3723

3724
    virObjectUnref(st);
3725 3726 3727 3728 3729 3730

    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
    VIR_FREE(uri_out);
3731
    VIR_FREE(cookie);
3732 3733

    return ret;
3734 3735 3736
}


3737 3738 3739 3740
/* This is essentially a re-impl of virDomainMigrateVersion3
 * from libvirt.c, but running in source libvirtd context,
 * instead of client app context & also adding in tunnel
 * handling */
3741 3742 3743 3744 3745 3746 3747 3748 3749
static int
doPeer2PeerMigrate3(virQEMUDriverPtr driver,
                    virConnectPtr sconn,
                    virConnectPtr dconn,
                    const char *dconnuri,
                    virDomainObjPtr vm,
                    const char *xmlin,
                    const char *dname,
                    const char *uri,
3750
                    const char *graphicsuri,
3751
                    const char *listenAddress,
3752 3753 3754
                    unsigned long long bandwidth,
                    bool useParams,
                    unsigned long flags)
3755 3756 3757 3758 3759 3760 3761 3762 3763 3764
{
    virDomainPtr ddomain = NULL;
    char *uri_out = NULL;
    char *cookiein = NULL;
    char *cookieout = NULL;
    char *dom_xml = NULL;
    int cookieinlen = 0;
    int cookieoutlen = 0;
    int ret = -1;
    virErrorPtr orig_err = NULL;
3765
    bool cancelled = true;
3766
    virStreamPtr st = NULL;
3767
    unsigned long destflags;
3768 3769 3770 3771 3772
    virTypedParameterPtr params = NULL;
    int nparams = 0;
    int maxparams = 0;

    VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, dconnuri=%s, vm=%p, xmlin=%s, "
3773 3774
              "dname=%s, uri=%s, graphicsuri=%s, listenAddress=%s, "
              "bandwidth=%llu, useParams=%d, flags=%lx",
3775
              driver, sconn, dconn, NULLSTR(dconnuri), vm, NULLSTR(xmlin),
3776 3777
              NULLSTR(dname), NULLSTR(uri), NULLSTR(graphicsuri),
              NULLSTR(listenAddress), bandwidth, useParams, flags);
3778

3779 3780 3781 3782 3783
    /* Unlike the virDomainMigrateVersion3 counterpart, we don't need
     * to worry about auto-setting the VIR_MIGRATE_CHANGE_PROTECTION
     * bit here, because we are already running inside the context of
     * a single job.  */

3784 3785
    dom_xml = qemuMigrationBeginPhase(driver, vm, xmlin, dname,
                                      &cookieout, &cookieoutlen, flags);
3786 3787 3788
    if (!dom_xml)
        goto cleanup;

3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808
    if (useParams) {
        if (virTypedParamsAddString(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_DEST_XML, dom_xml) < 0)
            goto cleanup;

        if (dname &&
            virTypedParamsAddString(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_DEST_NAME, dname) < 0)
            goto cleanup;

        if (uri &&
            virTypedParamsAddString(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_URI, uri) < 0)
            goto cleanup;

        if (bandwidth &&
            virTypedParamsAddULLong(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_BANDWIDTH,
                                    bandwidth) < 0)
            goto cleanup;
3809 3810 3811 3812 3813 3814

        if (graphicsuri &&
            virTypedParamsAddString(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_GRAPHICS_URI,
                                    graphicsuri) < 0)
            goto cleanup;
3815 3816 3817 3818 3819
        if (listenAddress &&
            virTypedParamsAddString(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
                                    listenAddress) < 0)
            goto cleanup;
3820 3821
    }

3822 3823 3824
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
        flags |= VIR_MIGRATE_PAUSED;

3825 3826
    destflags = flags & ~(VIR_MIGRATE_ABORT_ON_ERROR |
                          VIR_MIGRATE_AUTO_CONVERGE);
3827

3828 3829 3830 3831 3832 3833 3834 3835 3836
    VIR_DEBUG("Prepare3 %p", dconn);
    cookiein = cookieout;
    cookieinlen = cookieoutlen;
    cookieout = NULL;
    cookieoutlen = 0;
    if (flags & VIR_MIGRATE_TUNNELLED) {
        if (!(st = virStreamNew(dconn, 0)))
            goto cleanup;

3837
        qemuDomainObjEnterRemote(vm);
3838 3839 3840 3841 3842 3843 3844 3845 3846
        if (useParams) {
            ret = dconn->driver->domainMigratePrepareTunnel3Params
                (dconn, st, params, nparams, cookiein, cookieinlen,
                 &cookieout, &cookieoutlen, destflags);
        } else {
            ret = dconn->driver->domainMigratePrepareTunnel3
                (dconn, st, cookiein, cookieinlen, &cookieout, &cookieoutlen,
                 destflags, dname, bandwidth, dom_xml);
        }
3847
        qemuDomainObjExitRemote(vm);
3848
    } else {
3849
        qemuDomainObjEnterRemote(vm);
3850 3851 3852 3853 3854 3855 3856 3857 3858
        if (useParams) {
            ret = dconn->driver->domainMigratePrepare3Params
                (dconn, params, nparams, cookiein, cookieinlen,
                 &cookieout, &cookieoutlen, &uri_out, destflags);
        } else {
            ret = dconn->driver->domainMigratePrepare3
                (dconn, cookiein, cookieinlen, &cookieout, &cookieoutlen,
                 uri, &uri_out, destflags, dname, bandwidth, dom_xml);
        }
3859
        qemuDomainObjExitRemote(vm);
3860 3861 3862 3863 3864
    }
    VIR_FREE(dom_xml);
    if (ret == -1)
        goto cleanup;

L
liguang 已提交
3865 3866 3867 3868
    if (flags & VIR_MIGRATE_OFFLINE) {
        VIR_DEBUG("Offline migration, skipping Perform phase");
        VIR_FREE(cookieout);
        cookieoutlen = 0;
3869
        cancelled = false;
L
liguang 已提交
3870 3871 3872
        goto finish;
    }

3873 3874 3875 3876
    if (uri_out) {
        uri = uri_out;
        if (useParams &&
            virTypedParamsReplaceString(&params, &nparams,
3877 3878
                                        VIR_MIGRATE_PARAM_URI, uri_out) < 0) {
            orig_err = virSaveLastError();
3879
            goto finish;
3880
        }
3881
    } else if (!uri && !(flags & VIR_MIGRATE_TUNNELLED)) {
3882 3883
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("domainMigratePrepare3 did not set uri"));
3884
        orig_err = virSaveLastError();
3885 3886 3887 3888 3889 3890 3891 3892
        goto finish;
    }

    /* Perform the migration.  The driver isn't supposed to return
     * until the migration is complete. The src VM should remain
     * running, but in paused state until the destination can
     * confirm migration completion.
     */
3893
    VIR_DEBUG("Perform3 %p uri=%s", sconn, NULLSTR(uri));
3894
    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM3);
3895 3896 3897 3898 3899
    VIR_FREE(cookiein);
    cookiein = cookieout;
    cookieinlen = cookieoutlen;
    cookieout = NULL;
    cookieoutlen = 0;
3900
    if (flags & VIR_MIGRATE_TUNNELLED) {
3901 3902 3903
        ret = doTunnelMigrate(driver, vm, st,
                              cookiein, cookieinlen,
                              &cookieout, &cookieoutlen,
3904
                              flags, bandwidth, dconn, graphicsuri);
3905 3906
    } else {
        ret = doNativeMigrate(driver, vm, uri,
3907 3908
                              cookiein, cookieinlen,
                              &cookieout, &cookieoutlen,
3909
                              flags, bandwidth, dconn, graphicsuri);
3910
    }
3911 3912

    /* Perform failed. Make sure Finish doesn't overwrite the error */
3913
    if (ret < 0) {
3914
        orig_err = virSaveLastError();
3915 3916 3917 3918
    } else {
        qemuMigrationJobSetPhase(driver, vm,
                                 QEMU_MIGRATION_PHASE_PERFORM3_DONE);
    }
3919 3920 3921 3922

    /* If Perform returns < 0, then we need to cancel the VM
     * startup on the destination
     */
3923
    cancelled = ret < 0;
3924

3925
 finish:
3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937
    /*
     * The status code from the source is passed to the destination.
     * The dest can cleanup in the source indicated it failed to
     * send all migration data. Returns NULL for ddomain if
     * the dest was unable to complete migration.
     */
    VIR_DEBUG("Finish3 %p ret=%d", dconn, ret);
    VIR_FREE(cookiein);
    cookiein = cookieout;
    cookieinlen = cookieoutlen;
    cookieout = NULL;
    cookieoutlen = 0;
3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960

    if (useParams) {
        if (virTypedParamsGetString(params, nparams,
                                    VIR_MIGRATE_PARAM_DEST_NAME, NULL) <= 0 &&
            virTypedParamsReplaceString(&params, &nparams,
                                        VIR_MIGRATE_PARAM_DEST_NAME,
                                        vm->def->name) < 0) {
            ddomain = NULL;
        } else {
            qemuDomainObjEnterRemote(vm);
            ddomain = dconn->driver->domainMigrateFinish3Params
                (dconn, params, nparams, cookiein, cookieinlen,
                 &cookieout, &cookieoutlen, destflags, cancelled);
            qemuDomainObjExitRemote(vm);
        }
    } else {
        dname = dname ? dname : vm->def->name;
        qemuDomainObjEnterRemote(vm);
        ddomain = dconn->driver->domainMigrateFinish3
            (dconn, dname, cookiein, cookieinlen, &cookieout, &cookieoutlen,
             dconnuri, uri, destflags, cancelled);
        qemuDomainObjExitRemote(vm);
    }
3961 3962
    if (cancelled && ddomain)
        VIR_ERROR(_("finish step ignored that migration was cancelled"));
3963

3964 3965 3966 3967 3968 3969 3970
    /* If ddomain is NULL, then we were unable to start
     * the guest on the target, and must restart on the
     * source. There is a small chance that the ddomain
     * is NULL due to an RPC failure, in which case
     * ddomain could in fact be running on the dest.
     * The lock manager plugins should take care of
     * safety in this scenario.
3971
     */
3972
    cancelled = ddomain == NULL;
3973

3974 3975 3976 3977 3978 3979
    /* If finish3 set an error, and we don't have an earlier
     * one we need to preserve it in case confirm3 overwrites
     */
    if (!orig_err)
        orig_err = virSaveLastError();

3980 3981 3982 3983
    /*
     * If cancelled, then src VM will be restarted, else
     * it will be killed
     */
3984
    VIR_DEBUG("Confirm3 %p cancelled=%d vm=%p", sconn, cancelled, vm);
3985 3986 3987 3988 3989
    VIR_FREE(cookiein);
    cookiein = cookieout;
    cookieinlen = cookieoutlen;
    cookieout = NULL;
    cookieoutlen = 0;
3990 3991 3992
    ret = qemuMigrationConfirmPhase(driver, sconn, vm,
                                    cookiein, cookieinlen,
                                    flags, cancelled);
3993 3994 3995 3996
    /* If Confirm3 returns -1, there's nothing more we can
     * do, but fortunately worst case is that there is a
     * domain left in 'paused' state on source.
     */
3997 3998 3999
    if (ret < 0)
        VIR_WARN("Guest %s probably left in 'paused' state on source",
                 vm->def->name);
4000 4001 4002

 cleanup:
    if (ddomain) {
4003
        virObjectUnref(ddomain);
4004 4005 4006 4007 4008
        ret = 0;
    } else {
        ret = -1;
    }

4009
    virObjectUnref(st);
4010 4011 4012 4013 4014 4015 4016 4017

    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
    VIR_FREE(uri_out);
    VIR_FREE(cookiein);
    VIR_FREE(cookieout);
4018
    virTypedParamsFree(params, nparams);
4019 4020 4021 4022
    return ret;
}


4023
static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
4024
                              virConnectPtr sconn,
4025
                              virDomainObjPtr vm,
4026
                              const char *xmlin,
4027
                              const char *dconnuri,
4028
                              const char *uri,
4029
                              const char *graphicsuri,
4030
                              const char *listenAddress,
4031 4032
                              unsigned long flags,
                              const char *dname,
4033 4034
                              unsigned long resource,
                              bool *v3proto)
4035 4036 4037 4038
{
    int ret = -1;
    virConnectPtr dconn = NULL;
    bool p2p;
4039
    virErrorPtr orig_err = NULL;
4040
    bool offline = false;
4041
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4042
    bool useParams;
4043

4044
    VIR_DEBUG("driver=%p, sconn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
4045 4046
              "uri=%s, graphicsuri=%s, listenAddress=%s, flags=%lx, "
              "dname=%s, resource=%lu",
4047
              driver, sconn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
4048 4049
              NULLSTR(uri), NULLSTR(graphicsuri), NULLSTR(listenAddress),
              flags, NULLSTR(dname), resource);
4050 4051 4052 4053 4054

    /* the order of operations is important here; we make sure the
     * destination side is completely setup before we touch the source
     */

4055
    qemuDomainObjEnterRemote(vm);
4056
    dconn = virConnectOpen(dconnuri);
4057
    qemuDomainObjExitRemote(vm);
4058
    if (dconn == NULL) {
4059
        virReportError(VIR_ERR_OPERATION_FAILED,
4060 4061
                       _("Failed to connect to remote libvirt URI %s: %s"),
                       dconnuri, virGetLastErrorMessage());
4062
        virObjectUnref(cfg);
4063 4064 4065
        return -1;
    }

4066 4067
    if (virConnectSetKeepAlive(dconn, cfg->keepAliveInterval,
                               cfg->keepAliveCount) < 0)
4068 4069
        goto cleanup;

4070
    qemuDomainObjEnterRemote(vm);
4071 4072
    p2p = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                   VIR_DRV_FEATURE_MIGRATION_P2P);
4073
        /* v3proto reflects whether the caller used Perform3, but with
4074
         * p2p migrate, regardless of whether Perform2 or Perform3
4075 4076 4077 4078
         * were used, we decide protocol based on what target supports
         */
    *v3proto = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                        VIR_DRV_FEATURE_MIGRATION_V3);
4079 4080
    useParams = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                         VIR_DRV_FEATURE_MIGRATION_PARAMS);
L
liguang 已提交
4081 4082 4083
    if (flags & VIR_MIGRATE_OFFLINE)
        offline = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                           VIR_DRV_FEATURE_MIGRATION_OFFLINE);
4084
    qemuDomainObjExitRemote(vm);
4085

4086
    if (!p2p) {
4087 4088
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Destination libvirt does not support peer-to-peer migration protocol"));
4089 4090 4091
        goto cleanup;
    }

4092 4093
    /* Only xmlin, dname, uri, and bandwidth parameters can be used with
     * old-style APIs. */
4094
    if (!useParams && graphicsuri) {
4095 4096 4097 4098 4099 4100
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Migration APIs with extensible parameters are not "
                         "supported but extended parameters were passed"));
        goto cleanup;
    }

L
liguang 已提交
4101 4102 4103 4104 4105 4106 4107
    if (flags & VIR_MIGRATE_OFFLINE && !offline) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("offline migration is not supported by "
                         "the destination host"));
        goto cleanup;
    }

4108
    /* domain may have been stopped while we were talking to remote daemon */
L
liguang 已提交
4109
    if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
4110 4111
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("guest unexpectedly quit"));
4112 4113 4114
        goto cleanup;
    }

4115 4116 4117 4118 4119 4120 4121
    /* Change protection is only required on the source side (us), and
     * only for v3 migration when begin and perform are separate jobs.
     * But peer-2-peer is already a single job, and we still want to
     * talk to older destinations that would reject the flag.
     * Therefore it is safe to clear the bit here.  */
    flags &= ~VIR_MIGRATE_CHANGE_PROTECTION;

4122 4123
    if (*v3proto) {
        ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin,
4124 4125
                                  dname, uri, graphicsuri, listenAddress,
                                  resource, useParams, flags);
4126
    } else {
4127
        ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
4128
                                  dconnuri, flags, dname, resource);
4129
    }
4130

4131
 cleanup:
4132
    orig_err = virSaveLastError();
4133
    qemuDomainObjEnterRemote(vm);
4134
    virObjectUnref(dconn);
4135
    qemuDomainObjExitRemote(vm);
4136 4137 4138 4139
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
4140
    virObjectUnref(cfg);
4141 4142 4143 4144
    return ret;
}


4145 4146 4147 4148 4149 4150
/*
 * This implements perform part of the migration protocol when migration job
 * does not need to be active across several APIs, i.e., peer2peer migration or
 * perform phase of v2 non-peer2peer migration.
 */
static int
4151
qemuMigrationPerformJob(virQEMUDriverPtr driver,
4152 4153 4154 4155 4156
                        virConnectPtr conn,
                        virDomainObjPtr vm,
                        const char *xmlin,
                        const char *dconnuri,
                        const char *uri,
4157
                        const char *graphicsuri,
4158
                        const char *listenAddress,
4159
                        const char *cookiein,
4160 4161 4162 4163 4164 4165 4166
                        int cookieinlen,
                        char **cookieout,
                        int *cookieoutlen,
                        unsigned long flags,
                        const char *dname,
                        unsigned long resource,
                        bool v3proto)
4167
{
4168
    virObjectEventPtr event = NULL;
4169
    int ret = -1;
4170
    virErrorPtr orig_err = NULL;
4171
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4172
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
4173

4174
    if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
4175 4176
        goto cleanup;

L
liguang 已提交
4177
    if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
4178 4179
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
4180 4181 4182
        goto endjob;
    }

4183
    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
4184
        goto endjob;
4185

4186
    if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
4187
        goto endjob;
4188

4189
    qemuMigrationStoreDomainState(vm);
4190 4191

    if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
4192
        ret = doPeer2PeerMigrate(driver, conn, vm, xmlin,
4193 4194
                                 dconnuri, uri, graphicsuri, listenAddress,
                                 flags, dname, resource, &v3proto);
4195
    } else {
4196 4197 4198
        qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
        ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
                              cookieout, cookieoutlen,
4199
                              flags, resource, NULL, NULL);
4200
    }
4201 4202
    if (ret < 0)
        goto endjob;
4203

4204 4205 4206 4207
    /*
     * In v3 protocol, the source VM is not killed off until the
     * confirm step.
     */
4208
    if (!v3proto) {
4209 4210
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED,
                        VIR_QEMU_PROCESS_STOP_MIGRATED);
4211
        virDomainAuditStop(vm, "migrated");
4212
        event = virDomainEventLifecycleNewFromObj(vm,
4213 4214
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
4215 4216
    }

4217
 endjob:
4218 4219 4220
    if (ret < 0)
        orig_err = virSaveLastError();

4221
    if (qemuMigrationRestoreDomainState(conn, vm)) {
4222
        event = virDomainEventLifecycleNewFromObj(vm,
4223 4224 4225
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
    }
4226

4227
    if (!qemuMigrationJobFinish(driver, vm)) {
4228 4229 4230 4231 4232
        vm = NULL;
    } else if (!virDomainObjIsActive(vm) &&
               (!vm->persistent ||
                (ret == 0 && (flags & VIR_MIGRATE_UNDEFINE_SOURCE)))) {
        if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
4233
            virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
4234
        qemuDomainRemoveInactive(driver, vm);
4235 4236 4237
        vm = NULL;
    }

4238 4239 4240 4241 4242
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }

4243
 cleanup:
4244
    if (vm)
4245
        virObjectUnlock(vm);
4246 4247
    if (event)
        qemuDomainEventQueue(driver, event);
4248
    virObjectUnref(cfg);
4249 4250 4251 4252 4253 4254 4255
    return ret;
}

/*
 * This implements perform phase of v3 migration protocol.
 */
static int
4256
qemuMigrationPerformPhase(virQEMUDriverPtr driver,
4257 4258 4259
                          virConnectPtr conn,
                          virDomainObjPtr vm,
                          const char *uri,
4260
                          const char *graphicsuri,
4261 4262 4263 4264 4265 4266 4267
                          const char *cookiein,
                          int cookieinlen,
                          char **cookieout,
                          int *cookieoutlen,
                          unsigned long flags,
                          unsigned long resource)
{
4268
    virObjectEventPtr event = NULL;
4269
    int ret = -1;
4270
    bool hasrefs;
4271 4272 4273 4274 4275 4276 4277 4278 4279 4280

    /* If we didn't start the job in the begin phase, start it now. */
    if (!(flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            goto cleanup;
    } else if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT)) {
        goto cleanup;
    }

    qemuMigrationJobStartPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM3);
4281 4282
    virCloseCallbacksUnset(driver->closeCallbacks, vm,
                           qemuMigrationCleanup);
4283 4284 4285

    ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
                          cookieout, cookieoutlen,
4286
                          flags, resource, NULL, graphicsuri);
4287

4288 4289 4290 4291 4292
    if (ret < 0) {
        if (qemuMigrationRestoreDomainState(conn, vm)) {
            event = virDomainEventLifecycleNewFromObj(vm,
                                                      VIR_DOMAIN_EVENT_RESUMED,
                                                      VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
4293
        }
4294
        goto endjob;
4295
    }
4296 4297 4298

    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM3_DONE);

4299 4300
    if (virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
                             qemuMigrationCleanup) < 0)
4301 4302
        goto endjob;

4303
 endjob:
4304
    if (ret < 0)
4305
        hasrefs = qemuMigrationJobFinish(driver, vm);
4306
    else
4307 4308
        hasrefs = qemuMigrationJobContinue(vm);
    if (!hasrefs) {
4309 4310
        vm = NULL;
    } else if (!virDomainObjIsActive(vm) && !vm->persistent) {
4311
        qemuDomainRemoveInactive(driver, vm);
4312
        vm = NULL;
4313
    }
4314

4315
 cleanup:
4316
    if (vm)
4317
        virObjectUnlock(vm);
4318 4319 4320 4321 4322
    if (event)
        qemuDomainEventQueue(driver, event);
    return ret;
}

4323
int
4324
qemuMigrationPerform(virQEMUDriverPtr driver,
4325 4326 4327 4328 4329
                     virConnectPtr conn,
                     virDomainObjPtr vm,
                     const char *xmlin,
                     const char *dconnuri,
                     const char *uri,
4330
                     const char *graphicsuri,
4331
                     const char *listenAddress,
4332 4333 4334 4335 4336 4337 4338 4339 4340 4341
                     const char *cookiein,
                     int cookieinlen,
                     char **cookieout,
                     int *cookieoutlen,
                     unsigned long flags,
                     const char *dname,
                     unsigned long resource,
                     bool v3proto)
{
    VIR_DEBUG("driver=%p, conn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
4342
              "uri=%s, graphicsuri=%s, listenAddress=%s"
4343 4344
              "cookiein=%s, cookieinlen=%d, cookieout=%p, cookieoutlen=%p, "
              "flags=%lx, dname=%s, resource=%lu, v3proto=%d",
4345
              driver, conn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
4346
              NULLSTR(uri), NULLSTR(graphicsuri), NULLSTR(listenAddress),
4347 4348
              NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen,
              flags, NULLSTR(dname), resource, v3proto);
4349 4350 4351

    if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
        if (cookieinlen) {
4352 4353
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("received unexpected cookie with P2P migration"));
4354 4355 4356 4357
            return -1;
        }

        return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri, uri,
4358 4359
                                       graphicsuri, listenAddress,
                                       cookiein, cookieinlen,
4360 4361
                                       cookieout, cookieoutlen,
                                       flags, dname, resource, v3proto);
4362 4363
    } else {
        if (dconnuri) {
4364 4365
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Unexpected dconnuri parameter with non-peer2peer migration"));
4366 4367 4368 4369 4370
            return -1;
        }

        if (v3proto) {
            return qemuMigrationPerformPhase(driver, conn, vm, uri,
4371
                                             graphicsuri,
4372 4373
                                             cookiein, cookieinlen,
                                             cookieout, cookieoutlen,
4374
                                             flags, resource);
4375 4376
        } else {
            return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri,
4377
                                           uri, graphicsuri, listenAddress,
4378
                                           cookiein, cookieinlen,
4379 4380 4381 4382 4383
                                           cookieout, cookieoutlen, flags,
                                           dname, resource, v3proto);
        }
    }
}
4384

4385
static int
4386 4387
qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def)
{
4388
    size_t i;
4389 4390 4391 4392 4393
    int last_good_net = -1;
    virDomainNetDefPtr net;

    for (i = 0; i < def->nnets; i++) {
        net = def->nets[i];
4394
        if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
4395
            if (virNetDevVPortProfileAssociate(net->ifname,
4396
                                               virDomainNetGetActualVirtPortProfile(net),
4397
                                               &net->mac,
4398
                                               virDomainNetGetActualDirectDev(net),
4399
                                               -1,
4400
                                               def->uuid,
4401 4402
                                               VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH,
                                               false) < 0) {
4403 4404 4405
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("Port profile Associate failed for %s"),
                               net->ifname);
4406
                goto err_exit;
4407 4408
            }
            VIR_DEBUG("Port profile Associate succeeded for %s", net->ifname);
4409

4410
            if (virNetDevMacVLanVPortProfileRegisterCallback(net->ifname, &net->mac,
4411 4412 4413 4414
                                                             virDomainNetGetActualDirectDev(net), def->uuid,
                                                             virDomainNetGetActualVirtPortProfile(net),
                                                             VIR_NETDEV_VPORT_PROFILE_OP_CREATE))
                goto err_exit;
4415 4416 4417 4418
        }
        last_good_net = i;
    }

4419
    return 0;
4420

4421
 err_exit:
4422
    for (i = 0; last_good_net != -1 && i < last_good_net; i++) {
4423
        net = def->nets[i];
4424
        if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
4425
            ignore_value(virNetDevVPortProfileDisassociate(net->ifname,
4426
                                                           virDomainNetGetActualVirtPortProfile(net),
4427
                                                           &net->mac,
4428
                                                           virDomainNetGetActualDirectDev(net),
4429
                                                           -1,
4430
                                                           VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH));
4431 4432
        }
    }
4433
    return -1;
4434 4435 4436 4437
}


virDomainPtr
4438
qemuMigrationFinish(virQEMUDriverPtr driver,
4439 4440
                    virConnectPtr dconn,
                    virDomainObjPtr vm,
4441 4442 4443 4444
                    const char *cookiein,
                    int cookieinlen,
                    char **cookieout,
                    int *cookieoutlen,
4445
                    unsigned long flags,
4446 4447
                    int retcode,
                    bool v3proto)
4448 4449
{
    virDomainPtr dom = NULL;
4450
    virObjectEventPtr event = NULL;
4451
    bool newVM = true;
4452
    qemuMigrationCookiePtr mig = NULL;
4453
    virErrorPtr orig_err = NULL;
4454
    int cookie_flags = 0;
J
Jiri Denemark 已提交
4455
    qemuDomainObjPrivatePtr priv = vm->privateData;
4456
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4457
    virCapsPtr caps = NULL;
4458
    unsigned short port;
4459

4460
    VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
4461
              "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
4462 4463
              driver, dconn, vm, NULLSTR(cookiein), cookieinlen,
              cookieout, cookieoutlen, flags, retcode);
4464

4465 4466 4467
    port = priv->migrationPort;
    priv->migrationPort = 0;

4468 4469 4470
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

4471
    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
4472 4473
        goto cleanup;

4474 4475 4476
    qemuMigrationJobStartPhase(driver, vm,
                               v3proto ? QEMU_MIGRATION_PHASE_FINISH3
                                       : QEMU_MIGRATION_PHASE_FINISH2);
4477

4478 4479
    qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);

4480
    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK;
4481 4482 4483 4484 4485
    if (flags & VIR_MIGRATE_PERSIST_DEST)
        cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;

    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein,
                                       cookieinlen, cookie_flags)))
4486
        goto endjob;
4487 4488 4489 4490 4491

    /* Did the migration go as planned?  If yes, return the domain
     * object, but if no, clean up the empty qemu process.
     */
    if (retcode == 0) {
L
liguang 已提交
4492
        if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
4493 4494
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
4495
            goto endjob;
4496 4497
        }

L
liguang 已提交
4498 4499 4500 4501 4502
        if (!(flags & VIR_MIGRATE_OFFLINE)) {
            if (qemuMigrationVPAssociatePortProfiles(vm->def) < 0) {
                qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
                                VIR_QEMU_PROCESS_STOP_MIGRATED);
                virDomainAuditStop(vm, "failed");
4503
                event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
4504 4505 4506 4507 4508 4509 4510
                                                 VIR_DOMAIN_EVENT_STOPPED,
                                                 VIR_DOMAIN_EVENT_STOPPED_FAILED);
                goto endjob;
            }
            if (mig->network)
                if (qemuDomainMigrateOPDRelocate(driver, vm, mig) < 0)
                    VIR_WARN("unable to provide network data for relocation");
4511
        }
4512

4513 4514
        qemuMigrationStopNBDServer(driver, vm, mig);

4515
        if (flags & VIR_MIGRATE_PERSIST_DEST) {
4516
            virDomainDefPtr vmdef;
4517
            if (vm->persistent)
4518
                newVM = false;
4519
            vm->persistent = 1;
4520 4521 4522
            if (mig->persistent)
                vm->newDef = vmdef = mig->persistent;
            else
4523
                vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm);
4524
            if (!vmdef || virDomainSaveConfig(cfg->configDir, vmdef) < 0) {
4525 4526 4527 4528 4529 4530 4531 4532 4533
                /* Hmpf.  Migration was successful, but making it persistent
                 * was not.  If we report successful, then when this domain
                 * shuts down, management tools are in for a surprise.  On the
                 * other hand, if we report failure, then the management tools
                 * might try to restart the domain on the source side, even
                 * though the domain is actually running on the destination.
                 * Return a NULL dom pointer, and hope that this is a rare
                 * situation and management tools are smart.
                 */
4534 4535

                /*
4536 4537
                 * However, in v3 protocol, the source VM is still available
                 * to restart during confirm() step, so we kill it off now.
4538 4539
                 */
                if (v3proto) {
L
liguang 已提交
4540 4541 4542 4543 4544
                    if (!(flags & VIR_MIGRATE_OFFLINE)) {
                        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
                                        VIR_QEMU_PROCESS_STOP_MIGRATED);
                        virDomainAuditStop(vm, "failed");
                    }
4545 4546
                    if (newVM)
                        vm->persistent = 0;
4547
                }
A
Alex Jia 已提交
4548
                if (!vmdef)
4549 4550
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("can't get vmdef"));
4551 4552 4553
                goto endjob;
            }

4554
            event = virDomainEventLifecycleNewFromObj(vm,
4555 4556 4557 4558 4559 4560 4561 4562 4563
                                             VIR_DOMAIN_EVENT_DEFINED,
                                             newVM ?
                                             VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                             VIR_DOMAIN_EVENT_DEFINED_UPDATED);
            if (event)
                qemuDomainEventQueue(driver, event);
            event = NULL;
        }

L
liguang 已提交
4564
        if (!(flags & VIR_MIGRATE_PAUSED) && !(flags & VIR_MIGRATE_OFFLINE)) {
4565 4566 4567 4568
            /* run 'cont' on the destination, which allows migration on qemu
             * >= 0.10.6 to work properly.  This isn't strictly necessary on
             * older qemu's, but it also doesn't hurt anything there
             */
J
Jiri Denemark 已提交
4569
            if (qemuProcessStartCPUs(driver, vm, dconn,
4570 4571
                                     VIR_DOMAIN_RUNNING_MIGRATED,
                                     QEMU_ASYNC_JOB_MIGRATION_IN) < 0) {
4572
                if (virGetLastError() == NULL)
4573 4574
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("resume operation failed"));
4575 4576 4577 4578 4579
                /* Need to save the current error, in case shutting
                 * down the process overwrites it
                 */
                orig_err = virSaveLastError();

4580 4581 4582 4583 4584 4585 4586 4587 4588
                /*
                 * In v3 protocol, the source VM is still available to
                 * restart during confirm() step, so we kill it off
                 * now.
                 * In v2 protocol, the source is dead, so we leave
                 * target in paused state, in case admin can fix
                 * things up
                 */
                if (v3proto) {
4589 4590
                    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
                                    VIR_QEMU_PROCESS_STOP_MIGRATED);
4591
                    virDomainAuditStop(vm, "failed");
4592
                    event = virDomainEventLifecycleNewFromObj(vm,
4593 4594 4595
                                                     VIR_DOMAIN_EVENT_STOPPED,
                                                     VIR_DOMAIN_EVENT_STOPPED_FAILED);
                }
4596 4597 4598 4599
                goto endjob;
            }
        }

4600
        dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
4601

L
liguang 已提交
4602
        if (!(flags & VIR_MIGRATE_OFFLINE)) {
4603
            event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
4604 4605 4606 4607 4608 4609 4610
                                             VIR_DOMAIN_EVENT_RESUMED,
                                             VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
            if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
                virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
                                     VIR_DOMAIN_PAUSED_USER);
                if (event)
                    qemuDomainEventQueue(driver, event);
4611
                event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
4612 4613 4614
                                                 VIR_DOMAIN_EVENT_SUSPENDED,
                                                 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
            }
4615
        }
L
liguang 已提交
4616 4617

        if (virDomainObjIsActive(vm) &&
4618
            virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
4619 4620 4621
            VIR_WARN("Failed to save status on vm %s", vm->def->name);
            goto endjob;
        }
4622 4623 4624

        /* Guest is successfully running, so cancel previous auto destroy */
        qemuProcessAutoDestroyRemove(driver, vm);
L
liguang 已提交
4625
    } else if (!(flags & VIR_MIGRATE_OFFLINE)) {
4626 4627
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
                        VIR_QEMU_PROCESS_STOP_MIGRATED);
4628
        virDomainAuditStop(vm, "failed");
4629
        event = virDomainEventLifecycleNewFromObj(vm,
4630 4631 4632 4633
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
    }

4634 4635 4636
    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
        VIR_WARN("Unable to encode migration cookie");

4637
 endjob:
E
Eric Blake 已提交
4638 4639 4640
    if (qemuMigrationJobFinish(driver, vm) == 0) {
        vm = NULL;
    } else if (!vm->persistent && !virDomainObjIsActive(vm)) {
4641
        qemuDomainRemoveInactive(driver, vm);
E
Eric Blake 已提交
4642
        vm = NULL;
4643
    }
4644

4645
 cleanup:
4646
    virPortAllocatorRelease(driver->migrationPorts, port);
J
Jiri Denemark 已提交
4647 4648
    if (vm) {
        VIR_FREE(priv->origname);
4649
        virObjectUnlock(vm);
J
Jiri Denemark 已提交
4650
    }
4651 4652
    if (event)
        qemuDomainEventQueue(driver, event);
4653
    qemuMigrationCookieFree(mig);
4654 4655 4656 4657
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
4658
    virObjectUnref(caps);
4659
    virObjectUnref(cfg);
4660 4661
    return dom;
}
4662

4663

4664
/* Helper function called while vm is active.  */
4665
int
4666
qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
4667 4668
                    int fd, off_t offset, const char *path,
                    const char *compressor,
E
Eric Blake 已提交
4669
                    bool bypassSecurityDriver,
4670
                    enum qemuDomainAsyncJob asyncJob)
4671 4672 4673
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int rc;
4674
    int ret = -1;
4675
    bool restoreLabel = false;
4676 4677
    virCommandPtr cmd = NULL;
    int pipeFD[2] = { -1, -1 };
4678
    unsigned long saveMigBandwidth = priv->migMaxBandwidth;
4679
    char *errbuf = NULL;
4680 4681 4682 4683 4684

    /* Increase migration bandwidth to unlimited since target is a file.
     * Failure to change migration speed is not fatal. */
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
        qemuMonitorSetMigrationSpeed(priv->mon,
4685 4686
                                     QEMU_DOMAIN_MIG_BANDWIDTH_MAX);
        priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
4687
        qemuDomainObjExitMonitor(driver, vm);
4688
    }
4689

4690
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
4691
        (!compressor || pipe(pipeFD) == 0)) {
4692
        /* All right! We can use fd migration, which means that qemu
4693 4694 4695
         * doesn't have to open() the file, so while we still have to
         * grant SELinux access, we can do it on fd and avoid cleanup
         * later, as well as skip futzing with cgroup.  */
4696
        if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
4697
                                              compressor ? pipeFD[1] : fd) < 0)
4698
            goto cleanup;
4699 4700 4701
        bypassSecurityDriver = true;
    } else {
        /* Phooey - we have to fall back on exec migration, where qemu
E
Eric Blake 已提交
4702 4703
         * has to popen() the file by name, and block devices have to be
         * given cgroup ACL permission.  We might also stumble on
4704 4705
         * a race present in some qemu versions where it does a wait()
         * that botches pclose.  */
4706 4707
        if (virCgroupHasController(priv->cgroup,
                                   VIR_CGROUP_CONTROLLER_DEVICES)) {
4708 4709 4710 4711
            int rv = virCgroupAllowDevicePath(priv->cgroup, path,
                                              VIR_CGROUP_DEVICE_RW);
            virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path, "rw", rv == 0);
            if (rv == 1) {
E
Eric Blake 已提交
4712
                /* path was not a device, no further need for cgroup */
4713
            } else if (rv < 0) {
4714 4715
                goto cleanup;
            }
4716
        }
4717 4718
        if ((!bypassSecurityDriver) &&
            virSecurityManagerSetSavedStateLabel(driver->securityManager,
4719
                                                 vm->def, path) < 0)
4720
            goto cleanup;
4721
        restoreLabel = true;
4722 4723
    }

4724
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
4725 4726
        goto cleanup;

4727 4728 4729
    if (!compressor) {
        const char *args[] = { "cat", NULL };

4730
        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746
            priv->monConfig->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
            rc = qemuMonitorMigrateToFd(priv->mon,
                                        QEMU_MONITOR_MIGRATE_BACKGROUND,
                                        fd);
        } else {
            rc = qemuMonitorMigrateToFile(priv->mon,
                                          QEMU_MONITOR_MIGRATE_BACKGROUND,
                                          args, path, offset);
        }
    } else {
        const char *prog = compressor;
        const char *args[] = {
            prog,
            "-c",
            NULL
        };
4747 4748 4749 4750
        if (pipeFD[0] != -1) {
            cmd = virCommandNewArgs(args);
            virCommandSetInputFD(cmd, pipeFD[0]);
            virCommandSetOutputFD(cmd, &fd);
4751 4752
            virCommandSetErrorBuffer(cmd, &errbuf);
            virCommandDoAsyncIO(cmd);
4753 4754 4755
            if (virSetCloseExec(pipeFD[1]) < 0) {
                virReportSystemError(errno, "%s",
                                     _("Unable to set cloexec flag"));
4756
                qemuDomainObjExitMonitor(driver, vm);
4757 4758 4759
                goto cleanup;
            }
            if (virCommandRunAsync(cmd, NULL) < 0) {
4760
                qemuDomainObjExitMonitor(driver, vm);
4761 4762 4763 4764 4765 4766 4767
                goto cleanup;
            }
            rc = qemuMonitorMigrateToFd(priv->mon,
                                        QEMU_MONITOR_MIGRATE_BACKGROUND,
                                        pipeFD[1]);
            if (VIR_CLOSE(pipeFD[0]) < 0 ||
                VIR_CLOSE(pipeFD[1]) < 0)
4768
                VIR_WARN("failed to close intermediate pipe");
4769 4770 4771 4772 4773
        } else {
            rc = qemuMonitorMigrateToFile(priv->mon,
                                          QEMU_MONITOR_MIGRATE_BACKGROUND,
                                          args, path, offset);
        }
4774
    }
4775
    qemuDomainObjExitMonitor(driver, vm);
4776 4777 4778 4779

    if (rc < 0)
        goto cleanup;

4780
    rc = qemuMigrationWaitForCompletion(driver, vm, asyncJob, NULL, false);
4781 4782 4783 4784

    if (rc < 0)
        goto cleanup;

4785 4786 4787
    if (cmd && virCommandWait(cmd, NULL) < 0)
        goto cleanup;

4788 4789
    ret = 0;

4790
 cleanup:
4791 4792 4793 4794
    /* Restore max migration bandwidth */
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
        qemuMonitorSetMigrationSpeed(priv->mon, saveMigBandwidth);
        priv->migMaxBandwidth = saveMigBandwidth;
4795
        qemuDomainObjExitMonitor(driver, vm);
4796 4797
    }

4798 4799
    VIR_FORCE_CLOSE(pipeFD[0]);
    VIR_FORCE_CLOSE(pipeFD[1]);
4800 4801 4802 4803 4804
    if (cmd) {
        VIR_DEBUG("Compression binary stderr: %s", NULLSTR(errbuf));
        VIR_FREE(errbuf);
        virCommandFree(cmd);
    }
4805 4806
    if (restoreLabel && (!bypassSecurityDriver) &&
        virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
4807
                                                 vm->def, path) < 0)
4808 4809
        VIR_WARN("failed to restore save state label on %s", path);

4810 4811
    if (virCgroupHasController(priv->cgroup,
                               VIR_CGROUP_CONTROLLER_DEVICES)) {
4812 4813 4814
        int rv = virCgroupDenyDevicePath(priv->cgroup, path,
                                         VIR_CGROUP_DEVICE_RWM);
        virDomainAuditCgroupPath(vm, priv->cgroup, "deny", path, "rwm", rv == 0);
4815 4816 4817
    }
    return ret;
}
4818 4819

int
4820
qemuMigrationJobStart(virQEMUDriverPtr driver,
4821 4822 4823 4824 4825
                      virDomainObjPtr vm,
                      enum qemuDomainAsyncJob job)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;

4826
    if (qemuDomainObjBeginAsyncJob(driver, vm, job) < 0)
4827 4828
        return -1;

4829
    if (job == QEMU_ASYNC_JOB_MIGRATION_IN) {
4830
        qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE);
4831 4832
    } else {
        qemuDomainObjSetAsyncJobMask(vm, DEFAULT_JOB_MASK |
4833
                                     JOB_MASK(QEMU_JOB_SUSPEND) |
4834 4835
                                     JOB_MASK(QEMU_JOB_MIGRATION_OP));
    }
4836 4837 4838 4839 4840 4841 4842

    priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;

    return 0;
}

void
4843
qemuMigrationJobSetPhase(virQEMUDriverPtr driver,
4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859
                         virDomainObjPtr vm,
                         enum qemuMigrationJobPhase phase)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;

    if (phase < priv->job.phase) {
        VIR_ERROR(_("migration protocol going backwards %s => %s"),
                  qemuMigrationJobPhaseTypeToString(priv->job.phase),
                  qemuMigrationJobPhaseTypeToString(phase));
        return;
    }

    qemuDomainObjSetJobPhase(driver, vm, phase);
}

void
4860
qemuMigrationJobStartPhase(virQEMUDriverPtr driver,
4861 4862 4863
                           virDomainObjPtr vm,
                           enum qemuMigrationJobPhase phase)
{
4864
    virObjectRef(vm);
4865 4866 4867
    qemuMigrationJobSetPhase(driver, vm, phase);
}

4868
bool
4869 4870
qemuMigrationJobContinue(virDomainObjPtr vm)
{
4871
    qemuDomainObjReleaseAsyncJob(vm);
4872
    return virObjectUnref(vm);
4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888
}

bool
qemuMigrationJobIsActive(virDomainObjPtr vm,
                         enum qemuDomainAsyncJob job)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;

    if (priv->job.asyncJob != job) {
        const char *msg;

        if (job == QEMU_ASYNC_JOB_MIGRATION_IN)
            msg = _("domain '%s' is not processing incoming migration");
        else
            msg = _("domain '%s' is not being migrated");

4889
        virReportError(VIR_ERR_OPERATION_INVALID, msg, vm->def->name);
4890 4891 4892 4893 4894
        return false;
    }
    return true;
}

4895
bool
4896
qemuMigrationJobFinish(virQEMUDriverPtr driver, virDomainObjPtr vm)
4897 4898 4899
{
    return qemuDomainObjEndAsyncJob(driver, vm);
}