qemu_migration.c 162.1 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
        return false;
    }

J
Ján Tomko 已提交
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
    for (i = 0; i < def->cpu->nfeatures; i++) {
        virCPUFeatureDefPtr feature = &def->cpu->features[i];

        if (feature->policy != VIR_CPU_FEATURE_REQUIRE)
            continue;

        /* QEMU blocks migration and save with invariant TSC enabled */
        if (STREQ(feature->name, "invtsc")) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("domain has CPU feature: %s"),
                           feature->name);
            return false;
        }
    }

1531 1532 1533
    return true;
}

1534 1535 1536
static bool
qemuMigrationIsSafe(virDomainDefPtr def)
{
1537
    size_t i;
1538

1539
    for (i = 0; i < def->ndisks; i++) {
1540
        virDomainDiskDefPtr disk = def->disks[i];
1541
        const char *src = virDomainDiskGetSource(disk);
1542

1543 1544
        /* Our code elsewhere guarantees shared disks are either readonly (in
         * which case cache mode doesn't matter) or used with cache=none */
1545
        if (src &&
1546 1547 1548
            !disk->shared &&
            !disk->readonly &&
            disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE) {
1549
            int rc;
1550

E
Eric Blake 已提交
1551
            if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_FILE) {
1552
                if ((rc = virFileIsSharedFS(src)) < 0)
1553 1554
                    return false;
                else if (rc == 0)
1555
                    continue;
1556
                if ((rc = virStorageFileIsClusterFS(src)) < 0)
1557
                    return false;
1558 1559
                else if (rc == 1)
                    continue;
1560 1561
            } else if (disk->src->type == VIR_STORAGE_TYPE_NETWORK &&
                       disk->src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) {
1562
                continue;
1563
            }
1564

1565 1566 1567
            virReportError(VIR_ERR_MIGRATE_UNSAFE, "%s",
                           _("Migration may lead to data corruption if disks"
                             " use cache != none"));
1568 1569 1570 1571 1572 1573 1574
            return false;
        }
    }

    return true;
}

1575 1576 1577 1578
/** qemuMigrationSetOffline
 * Pause domain for non-live migration.
 */
int
1579
qemuMigrationSetOffline(virQEMUDriverPtr driver,
1580 1581 1582
                        virDomainObjPtr vm)
{
    int ret;
1583
    VIR_DEBUG("driver=%p vm=%p", driver, vm);
1584 1585
    ret = qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_MIGRATION,
                              QEMU_ASYNC_JOB_MIGRATION_OUT);
1586
    if (ret == 0) {
1587
        virObjectEventPtr event;
1588

1589
        event = virDomainEventLifecycleNewFromObj(vm,
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }

    return ret;
}


1600 1601 1602
static int
qemuMigrationSetCompression(virQEMUDriverPtr driver,
                            virDomainObjPtr vm,
1603
                            qemuDomainAsyncJob job)
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
{
    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);

1635
 cleanup:
1636 1637 1638 1639
    qemuDomainObjExitMonitor(driver, vm);
    return ret;
}

1640 1641 1642
static int
qemuMigrationSetAutoConverge(virQEMUDriverPtr driver,
                             virDomainObjPtr vm,
1643
                             qemuDomainAsyncJob job)
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
{
    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);

1669
 cleanup:
1670 1671 1672 1673 1674
    qemuDomainObjExitMonitor(driver, vm);
    return ret;
}


1675 1676 1677 1678 1679 1680 1681
static int
qemuMigrationWaitForSpice(virQEMUDriverPtr driver,
                          virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    bool wait_for_spice = false;
    bool spice_migrated = false;
1682
    size_t i = 0;
1683

1684 1685 1686 1687 1688 1689 1690 1691
    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;
            }
        }
    }
1692 1693 1694 1695 1696 1697 1698 1699

    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 };

1700 1701 1702 1703
        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            return -1;

1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
        if (qemuMonitorGetSpiceMigrationStatus(priv->mon,
                                               &spice_migrated) < 0) {
            qemuDomainObjExitMonitor(driver, vm);
            return -1;
        }
        qemuDomainObjExitMonitor(driver, vm);
        virObjectUnlock(vm);
        nanosleep(&ts, NULL);
        virObjectLock(vm);
    }

    return 0;
}
1717

1718
static int
1719
qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
1720
                             virDomainObjPtr vm,
1721
                             const char *job,
1722
                             qemuDomainAsyncJob asyncJob)
1723
{
1724
    qemuDomainObjPrivatePtr priv = vm->privateData;
1725
    int ret;
1726 1727 1728
    qemuMonitorMigrationStatus status;

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

1730 1731
    ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob);
    if (ret < 0) {
1732 1733 1734
        /* Guest already exited or waiting for the job timed out; nothing
         * further to update. */
        return ret;
1735
    }
1736
    ret = qemuMonitorGetMigrationStatus(priv->mon, &status);
1737

1738
    qemuDomainObjExitMonitor(driver, vm);
1739

1740 1741
    priv->job.status = status;

1742
    if (ret < 0 || virTimeMillisNow(&priv->job.info.timeElapsed) < 0)
1743
        return -1;
1744

1745
    priv->job.info.timeElapsed -= priv->job.start;
1746

1747
    ret = -1;
1748
    switch (priv->job.status.status) {
1749
    case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
1750
        priv->job.info.type = VIR_DOMAIN_JOB_NONE;
1751 1752
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("%s: %s"), job, _("is not active"));
1753 1754
        break;

M
Michael Avdienko 已提交
1755 1756 1757 1758
    case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
        ret = 0;
        break;

1759
    case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774
        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;
1775 1776 1777 1778 1779

        ret = 0;
        break;

    case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
1780
        priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
1781 1782 1783 1784
        ret = 0;
        break;

    case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
1785
        priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
1786 1787
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("%s: %s"), job, _("unexpectedly failed"));
1788 1789 1790
        break;

    case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
1791
        priv->job.info.type = VIR_DOMAIN_JOB_CANCELLED;
1792 1793
        virReportError(VIR_ERR_OPERATION_ABORTED,
                       _("%s: %s"), job, _("canceled by client"));
1794 1795 1796 1797 1798 1799 1800
        break;
    }

    return ret;
}


1801 1802 1803
/* Returns 0 on success, -2 when migration needs to be cancelled, or -1 when
 * QEMU reports failed migration.
 */
1804
static int
1805
qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, virDomainObjPtr vm,
1806
                               qemuDomainAsyncJob asyncJob,
1807
                               virConnectPtr dconn, bool abort_on_error)
1808
{
1809
    qemuDomainObjPrivatePtr priv = vm->privateData;
1810
    const char *job;
1811
    int pauseReason;
1812

1813 1814
    switch (priv->job.asyncJob) {
    case QEMU_ASYNC_JOB_MIGRATION_OUT:
1815 1816
        job = _("migration job");
        break;
1817
    case QEMU_ASYNC_JOB_SAVE:
1818 1819
        job = _("domain save job");
        break;
1820
    case QEMU_ASYNC_JOB_DUMP:
1821 1822 1823 1824 1825
        job = _("domain core dump job");
        break;
    default:
        job = _("job");
    }
1826

1827
    priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
1828

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

1833
        if (qemuMigrationUpdateJobStatus(driver, vm, job, asyncJob) == -1)
1834
            break;
1835

1836
        /* cancel migration if disk I/O error is emitted while migrating */
1837
        if (abort_on_error &&
1838
            virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
1839 1840 1841 1842 1843
            pauseReason == VIR_DOMAIN_PAUSED_IOERROR) {
            virReportError(VIR_ERR_OPERATION_FAILED,
                           _("%s: %s"), job, _("failed due to I/O error"));
            break;
        }
1844

1845
        if (dconn && virConnectIsAlive(dconn) <= 0) {
1846 1847
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("Lost connection to destination host"));
1848
            break;
1849 1850
        }

1851
        virObjectUnlock(vm);
1852 1853 1854

        nanosleep(&ts, NULL);

1855
        virObjectLock(vm);
1856 1857
    }

1858
    if (priv->job.info.type == VIR_DOMAIN_JOB_COMPLETED) {
1859
        return 0;
1860 1861 1862 1863 1864 1865 1866
    } else if (priv->job.info.type == VIR_DOMAIN_JOB_UNBOUNDED) {
        /* The migration was aborted by us rather than QEMU itself so let's
         * update the job type and notify the caller to send migrate_cancel.
         */
        priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
        return -2;
    } else {
1867
        return -1;
1868
    }
1869 1870 1871
}


1872
static int
1873
qemuDomainMigrateGraphicsRelocate(virQEMUDriverPtr driver,
1874
                                  virDomainObjPtr vm,
1875 1876
                                  qemuMigrationCookiePtr cookie,
                                  const char *graphicsuri)
1877 1878
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
1879 1880
    int ret = -1;
    const char *listenAddress = NULL;
1881
    virSocketAddr addr;
1882 1883 1884 1885 1886
    virURIPtr uri = NULL;
    int type = -1;
    int port = -1;
    int tlsPort = -1;
    const char *tlsSubject = NULL;
1887

1888
    if (!cookie || (!cookie->graphics && !graphicsuri))
1889 1890
        return 0;

1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909
    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) {
1910
        size_t i;
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937

        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;
            }
        }
    }
1938 1939 1940 1941

    /* QEMU doesn't support VNC relocation yet, so
     * skip it to avoid generating an error
     */
1942 1943 1944 1945
    if (type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
        ret = 0;
        goto cleanup;
    }
1946

1947 1948 1949 1950
    if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                       QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
        ret = qemuMonitorGraphicsRelocate(priv->mon, type, listenAddress,
                                          port, tlsPort, tlsSubject);
1951
        qemuDomainObjExitMonitor(driver, vm);
1952
    }
1953

1954
 cleanup:
1955
    virURIFree(uri);
1956 1957 1958 1959
    return ret;
}


1960
static int
1961
qemuDomainMigrateOPDRelocate(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
1962 1963 1964
                             virDomainObjPtr vm,
                             qemuMigrationCookiePtr cookie)
{
1965 1966
    virDomainNetDefPtr netptr;
    int ret = -1;
1967
    size_t i;
1968 1969 1970 1971 1972 1973 1974 1975

    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:
1976
           break;
1977
        case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
1978 1979 1980 1981 1982 1983 1984 1985
            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;
1986 1987 1988 1989 1990
        default:
            break;
        }
    }

1991
    ret = 0;
1992
 cleanup:
1993 1994 1995 1996
    return ret;
}


1997 1998 1999 2000 2001 2002
/* 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.
 */
2003 2004 2005 2006
static virDomainObjPtr
qemuMigrationCleanup(virDomainObjPtr vm,
                     virConnectPtr conn,
                     void *opaque)
2007
{
2008
    virQEMUDriverPtr driver = opaque;
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
    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);

2024
    switch ((qemuMigrationJobPhase) priv->job.phase) {
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054
    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 */
        ;
    }

2055
 cleanup:
2056 2057 2058
    return vm;
}

2059

2060
/* The caller is supposed to lock the vm and start a migration job. */
2061 2062
static char
*qemuMigrationBeginPhase(virQEMUDriverPtr driver,
2063
                         virDomainObjPtr vm,
2064
                         const char *xmlin,
2065
                         const char *dname,
2066
                         char **cookieout,
2067 2068
                         int *cookieoutlen,
                         unsigned long flags)
2069 2070 2071
{
    char *rv = NULL;
    qemuMigrationCookiePtr mig = NULL;
2072
    virDomainDefPtr def = NULL;
2073
    qemuDomainObjPrivatePtr priv = vm->privateData;
2074
    virCapsPtr caps = NULL;
2075
    unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE;
2076
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
2077

2078
    VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s,"
2079
              " cookieout=%p, cookieoutlen=%p, flags=%lx",
2080
              driver, vm, NULLSTR(xmlin), NULLSTR(dname),
2081
              cookieout, cookieoutlen, flags);
2082

2083 2084 2085
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

2086 2087 2088 2089 2090 2091
    /* 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);
2092

2093
    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
2094 2095
        goto cleanup;

2096 2097 2098
    if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
        goto cleanup;

2099
    if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
2100
        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR)) {
2101
        /* TODO support NBD for TUNNELLED migration */
2102
        if (flags & VIR_MIGRATE_TUNNELLED) {
2103 2104 2105 2106
            VIR_WARN("NBD in tunnelled migration is currently not supported");
        } else {
            cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
            priv->nbdPort = 0;
2107 2108 2109
        }
    }

2110
    if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0)))
2111 2112 2113 2114
        goto cleanup;

    if (qemuMigrationBakeCookie(mig, driver, vm,
                                cookieout, cookieoutlen,
2115
                                cookieFlags) < 0)
2116 2117
        goto cleanup;

L
liguang 已提交
2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139
    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;
        }
    }

2140
    if (xmlin) {
2141
        if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt,
M
Matthias Bolte 已提交
2142
                                            QEMU_EXPECTED_VIRT_TYPES,
2143 2144 2145
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

2146
        if (!qemuDomainDefCheckABIStability(driver, vm->def, def))
2147 2148
            goto cleanup;

2149
        rv = qemuDomainDefFormatLive(driver, def, false, true);
2150
    } else {
2151
        rv = qemuDomainDefFormatLive(driver, vm->def, false, true);
2152
    }
2153

2154
 cleanup:
2155
    qemuMigrationCookieFree(mig);
2156
    virObjectUnref(caps);
2157
    virDomainDefFree(def);
2158 2159 2160
    return rv;
}

2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
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;
2172
    qemuDomainAsyncJob asyncJob;
2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183

    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;
    }

2184 2185
    qemuMigrationStoreDomainState(vm);

2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208
    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.
         */
2209 2210
        if (virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
                                 qemuMigrationCleanup) < 0)
2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223
            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;
    }

2224
 cleanup:
2225 2226 2227 2228
    if (vm)
        virObjectUnlock(vm);
    return xml;

2229
 endjob:
2230 2231 2232 2233
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobFinish(driver, vm) == 0)
            vm = NULL;
    } else {
E
Eric Blake 已提交
2234
        if (!qemuDomainObjEndJob(driver, vm))
2235 2236 2237 2238 2239
            vm = NULL;
    }
    goto cleanup;
}

2240

2241 2242
/* Prepare is the first step, and it runs on the destination host.
 */
2243

2244
static void
2245
qemuMigrationPrepareCleanup(virQEMUDriverPtr driver,
2246 2247 2248 2249 2250 2251 2252 2253 2254 2255
                            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));

2256 2257 2258
    virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
    priv->migrationPort = 0;

2259 2260 2261 2262 2263
    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
        return;
    qemuDomainObjDiscardAsyncJob(driver, vm);
}

2264
static int
2265
qemuMigrationPrepareAny(virQEMUDriverPtr driver,
2266 2267 2268 2269 2270
                        virConnectPtr dconn,
                        const char *cookiein,
                        int cookieinlen,
                        char **cookieout,
                        int *cookieoutlen,
2271
                        virDomainDefPtr *def,
2272
                        const char *origname,
L
liguang 已提交
2273
                        virStreamPtr st,
2274 2275
                        unsigned short port,
                        bool autoPort,
2276
                        const char *listenAddress,
L
liguang 已提交
2277
                        unsigned long flags)
2278 2279
{
    virDomainObjPtr vm = NULL;
2280
    virObjectEventPtr event = NULL;
2281
    int ret = -1;
2282
    int dataFD[2] = { -1, -1 };
2283
    qemuDomainObjPrivatePtr priv = NULL;
J
Jiri Denemark 已提交
2284
    unsigned long long now;
2285
    qemuMigrationCookiePtr mig = NULL;
2286
    bool tunnel = !!st;
J
Jiri Denemark 已提交
2287
    char *xmlout = NULL;
L
liguang 已提交
2288
    unsigned int cookieFlags;
2289
    virCapsPtr caps = NULL;
J
Ján Tomko 已提交
2290
    char *migrateFrom = NULL;
2291
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
2292
    bool taint_hook = false;
2293

2294
    if (virTimeMillisNow(&now) < 0)
2295 2296
        return -1;

L
liguang 已提交
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318
    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;
        }
    }

2319 2320 2321
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

2322
    if (!qemuMigrationIsAllowed(driver, NULL, *def, true, abort_on_error))
2323 2324
        goto cleanup;

J
Jiri Denemark 已提交
2325 2326 2327 2328 2329
    /* Let migration hook filter domain XML */
    if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
        char *xml;
        int hookret;

2330
        if (!(xml = qemuDomainDefFormatXML(driver, *def,
2331 2332
                                           VIR_DOMAIN_XML_SECURE |
                                           VIR_DOMAIN_XML_MIGRATABLE)))
J
Jiri Denemark 已提交
2333 2334
            goto cleanup;

2335
        hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, (*def)->name,
J
Jiri Denemark 已提交
2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349
                              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);
2350
                newdef = virDomainDefParseString(xmlout, caps, driver->xmlopt,
J
Jiri Denemark 已提交
2351 2352 2353 2354 2355
                                                 QEMU_EXPECTED_VIRT_TYPES,
                                                 VIR_DOMAIN_XML_INACTIVE);
                if (!newdef)
                    goto cleanup;

2356
                if (!qemuDomainDefCheckABIStability(driver, *def, newdef)) {
J
Jiri Denemark 已提交
2357 2358 2359 2360
                    virDomainDefFree(newdef);
                    goto cleanup;
                }

2361 2362
                virDomainDefFree(*def);
                *def = newdef;
2363 2364 2365 2366
                /* 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 已提交
2367 2368 2369 2370
            }
        }
    }

J
Ján Tomko 已提交
2371 2372 2373 2374
    if (tunnel) {
        /* QEMU will be started with -incoming stdio
         * (which qemu_command might convert to exec:cat or fd:n)
         */
2375
        if (VIR_STRDUP(migrateFrom, "stdio") < 0)
J
Ján Tomko 已提交
2376 2377
            goto cleanup;
    } else {
2378 2379 2380 2381
        virSocketAddr listenAddressSocket;
        bool encloseAddress = false;
        bool hostIPv6Capable = false;
        bool qemuIPv6Capable = false;
J
Ján Tomko 已提交
2382 2383 2384 2385 2386
        virQEMUCapsPtr qemuCaps = NULL;
        struct addrinfo *info = NULL;
        struct addrinfo hints = { .ai_flags = AI_ADDRCONFIG,
                                  .ai_socktype = SOCK_STREAM };

2387 2388 2389 2390
        if (getaddrinfo("::", NULL, &hints, &info) == 0) {
            freeaddrinfo(info);
            hostIPv6Capable = true;
        }
J
Ján Tomko 已提交
2391
        if (!(qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
2392
                                                    (*def)->emulator)))
J
Ján Tomko 已提交
2393 2394
            goto cleanup;

2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421
        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 已提交
2422
        } else {
2423 2424 2425 2426 2427
            /* 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 已提交
2428 2429
        }

2430 2431
        /* QEMU will be started with -incoming [<IPv6 addr>]:port,
         * -incoming <IPv4 addr>:port or -incoming <hostname>:port
J
Ján Tomko 已提交
2432
         */
2433 2434 2435 2436
        if ((encloseAddress &&
             virAsprintf(&migrateFrom, "tcp:[%s]:%d", listenAddress, port) < 0) ||
            (!encloseAddress &&
             virAsprintf(&migrateFrom, "tcp:%s:%d", listenAddress, port) < 0))
J
Ján Tomko 已提交
2437 2438 2439
            goto cleanup;
    }

2440
    if (!(vm = virDomainObjListAdd(driver->domains, *def,
2441
                                   driver->xmlopt,
2442 2443 2444
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
2445
        goto cleanup;
2446

2447
    *def = NULL;
2448
    priv = vm->privateData;
2449 2450
    if (VIR_STRDUP(priv->origname, origname) < 0)
        goto cleanup;
2451

2452 2453 2454 2455 2456
    if (taint_hook) {
        /* Domain XML has been altered by a hook script. */
        priv->hookRun = true;
    }

2457
    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
2458 2459
                                       QEMU_MIGRATION_COOKIE_LOCKSTATE |
                                       QEMU_MIGRATION_COOKIE_NBD)))
2460 2461
        goto cleanup;

2462
    if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
2463
        goto cleanup;
2464
    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PREPARE);
2465 2466 2467 2468

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

L
liguang 已提交
2469 2470 2471
    if (flags & VIR_MIGRATE_OFFLINE)
        goto done;

2472 2473
    if (tunnel &&
        (pipe(dataFD) < 0 || virSetCloseExec(dataFD[1]) < 0)) {
2474 2475
        virReportSystemError(errno, "%s",
                             _("cannot create pipe for tunnelled migration"));
2476 2477 2478 2479
        goto endjob;
    }

    /* Start the QEMU daemon, with the same command-line arguments plus
2480
     * -incoming $migrateFrom
2481
     */
2482 2483 2484
    if (qemuProcessStart(dconn, driver, vm, migrateFrom, dataFD[0], NULL, NULL,
                         VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START,
                         VIR_QEMU_PROCESS_START_PAUSED |
2485
                         VIR_QEMU_PROCESS_START_AUTODESTROY) < 0) {
2486
        virDomainAuditStart(vm, "migrated", false);
2487 2488 2489
        goto endjob;
    }

2490 2491 2492 2493
    if (tunnel) {
        if (virFDStreamOpen(st, dataFD[1]) < 0) {
            virReportSystemError(errno, "%s",
                                 _("cannot pass pipe for tunnelled migration"));
2494
            goto stop;
2495
        }
2496
        dataFD[1] = -1; /* 'st' owns the FD now & will close it */
2497 2498
    }

2499 2500 2501 2502 2503
    if (flags & VIR_MIGRATE_COMPRESSED &&
        qemuMigrationSetCompression(driver, vm,
                                    QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
        goto stop;

2504 2505 2506 2507 2508 2509 2510 2511
    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");
    }
2512

2513
 done:
L
liguang 已提交
2514 2515 2516 2517 2518
    if (flags & VIR_MIGRATE_OFFLINE)
        cookieFlags = 0;
    else
        cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS;

2519 2520 2521
    if (mig->nbd &&
        flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER)) {
2522
        if (qemuMigrationStartNBDServer(driver, vm, listenAddress) < 0) {
2523 2524
            /* error already reported */
            goto endjob;
2525
        }
2526
        cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
2527 2528 2529 2530
    }

    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout,
                                cookieoutlen, cookieFlags) < 0) {
2531 2532 2533 2534 2535 2536 2537
        /* 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");
    }

2538 2539 2540
    if (qemuDomainCleanupAdd(vm, qemuMigrationPrepareCleanup) < 0)
        goto endjob;

L
liguang 已提交
2541 2542
    if (!(flags & VIR_MIGRATE_OFFLINE)) {
        virDomainAuditStart(vm, "migrated", true);
2543
        event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
2544 2545 2546
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_MIGRATED);
    }
2547

2548 2549 2550 2551
    /* 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.
     */
2552
    if (!qemuMigrationJobContinue(vm)) {
2553
        vm = NULL;
2554 2555
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("domain disappeared"));
2556
        goto cleanup;
2557
    }
2558

2559 2560
    if (autoPort)
        priv->migrationPort = port;
2561
    ret = 0;
2562

2563
 cleanup:
J
Ján Tomko 已提交
2564
    VIR_FREE(migrateFrom);
J
Jiri Denemark 已提交
2565
    VIR_FREE(xmlout);
2566 2567
    VIR_FORCE_CLOSE(dataFD[0]);
    VIR_FORCE_CLOSE(dataFD[1]);
2568
    if (vm) {
2569
        if (ret < 0) {
2570 2571 2572
            virPortAllocatorRelease(driver->remotePorts, priv->nbdPort);
            priv->nbdPort = 0;
        }
2573 2574 2575 2576
        if (ret >= 0 || vm->persistent)
            virObjectUnlock(vm);
        else
            qemuDomainRemoveInactive(driver, vm);
2577
    }
2578 2579
    if (event)
        qemuDomainEventQueue(driver, event);
2580
    qemuMigrationCookieFree(mig);
2581
    virObjectUnref(caps);
2582
    return ret;
2583

2584
 stop:
2585 2586 2587
    virDomainAuditStart(vm, "migrated", false);
    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0);

2588
 endjob:
2589
    if (!qemuMigrationJobFinish(driver, vm)) {
2590 2591 2592
        vm = NULL;
    }
    goto cleanup;
2593 2594 2595
}


2596 2597 2598 2599 2600
/*
 * This version starts an empty VM listening on a localhost TCP port, and
 * sets up the corresponding virStream to handle the incoming data.
 */
int
2601
qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
2602 2603 2604 2605 2606 2607
                           virConnectPtr dconn,
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
                           virStreamPtr st,
2608
                           virDomainDefPtr *def,
2609
                           const char *origname,
L
liguang 已提交
2610
                           unsigned long flags)
2611 2612 2613 2614
{
    int ret;

    VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
2615
              "cookieout=%p, cookieoutlen=%p, st=%p, def=%p, "
2616
              "origname=%s, flags=%lx",
2617
              driver, dconn, NULLSTR(cookiein), cookieinlen,
2618
              cookieout, cookieoutlen, st, *def, origname, flags);
2619

2620 2621 2622 2623 2624 2625
    if (st == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("tunnelled migration requested but NULL stream passed"));
        return -1;
    }

2626
    ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
2627
                                  cookieout, cookieoutlen, def, origname,
2628
                                  st, 0, false, NULL, flags);
2629 2630 2631 2632
    return ret;
}


2633
int
2634
qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
2635
                           virConnectPtr dconn,
2636 2637 2638 2639
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
2640 2641
                           const char *uri_in,
                           char **uri_out,
2642
                           virDomainDefPtr *def,
2643
                           const char *origname,
2644
                           const char *listenAddress,
L
liguang 已提交
2645
                           unsigned long flags)
2646
{
2647 2648
    unsigned short port = 0;
    bool autoPort = true;
2649 2650
    char *hostname = NULL;
    const char *p;
J
Ján Tomko 已提交
2651
    char *uri_str = NULL;
2652
    int ret = -1;
2653
    virURIPtr uri = NULL;
2654
    bool well_formed_uri = true;
2655 2656
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
    const char *migrateHost = cfg->migrateHost;
J
Jiri Denemark 已提交
2657

2658 2659
    VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
              "cookieout=%p, cookieoutlen=%p, uri_in=%s, uri_out=%p, "
2660
              "def=%p, origname=%s, listenAddress=%s, flags=%lx",
2661 2662
              driver, dconn, NULLSTR(cookiein), cookieinlen,
              cookieout, cookieoutlen, NULLSTR(uri_in), uri_out,
2663
              *def, origname, NULLSTR(listenAddress), flags);
2664

2665 2666
    *uri_out = NULL;

2667 2668 2669
    /* 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
2670 2671 2672
     * from our pool of port numbers, and if the migrateHost is configured,
     * we return a URI of "tcp://migrateHost:port", otherwise return a URI
     * of "tcp://ourhostname:port".
2673 2674 2675 2676 2677 2678
     *
     * 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) {
2679
        if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
2680
            goto cleanup;
2681

2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
        if (migrateHost != NULL) {
            if (virSocketAddrIsNumeric(migrateHost) &&
                virSocketAddrParse(NULL, migrateHost, AF_UNSPEC) < 0)
                goto cleanup;

           if (VIR_STRDUP(hostname, migrateHost) < 0)
                goto cleanup;
        } else {
            if ((hostname = virGetHostname()) == NULL)
                goto cleanup;
        }
2693 2694

        if (STRPREFIX(hostname, "localhost")) {
2695 2696 2697
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("hostname on destination resolved to localhost,"
                             " but migration requires an FQDN"));
2698 2699 2700 2701 2702
            goto cleanup;
        }

        /* XXX this really should have been a properly well-formed
         * URI, but we can't add in tcp:// now without breaking
2703
         * compatibility with old targets. We at least make the
2704 2705 2706
         * new targets accept both syntaxes though.
         */
        /* Caller frees */
2707
        if (virAsprintf(uri_out, "tcp:%s:%d", hostname, port) < 0)
2708 2709 2710 2711 2712 2713
            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 已提交
2714
        if (!(p = STRSKIP(uri_in, "tcp:"))) {
2715 2716 2717
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("only tcp URIs are supported for KVM/QEMU"
                             " migrations"));
2718 2719 2720
            goto cleanup;
        }

J
Ján Tomko 已提交
2721 2722
        /* Convert uri_in to well-formed URI with // after tcp: */
        if (!(STRPREFIX(uri_in, "tcp://"))) {
2723
            well_formed_uri = false;
2724
            if (virAsprintf(&uri_str, "tcp://%s", p) < 0)
J
Ján Tomko 已提交
2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743
                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) {
2744
            if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
2745
                goto cleanup;
2746

2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757
            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;
            }
2758 2759

        } else {
2760 2761
            port = uri->port;
            autoPort = false;
2762 2763 2764 2765 2766 2767
        }
    }

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

2768
    ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
2769
                                  cookieout, cookieoutlen, def, origname,
2770
                                  NULL, port, autoPort, listenAddress, flags);
2771
 cleanup:
2772
    virURIFree(uri);
2773
    VIR_FREE(hostname);
2774
    virObjectUnref(cfg);
2775
    if (ret != 0) {
2776
        VIR_FREE(*uri_out);
2777 2778 2779
        if (autoPort)
            virPortAllocatorRelease(driver->migrationPorts, port);
    }
2780 2781 2782 2783
    return ret;
}


2784 2785 2786
virDomainDefPtr
qemuMigrationPrepareDef(virQEMUDriverPtr driver,
                        const char *dom_xml,
2787 2788
                        const char *dname,
                        char **origname)
2789 2790 2791
{
    virCapsPtr caps = NULL;
    virDomainDefPtr def;
2792
    char *name = NULL;
2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808

    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) {
2809
        name = def->name;
2810 2811 2812 2813 2814 2815
        if (VIR_STRDUP(def->name, dname) < 0) {
            virDomainDefFree(def);
            def = NULL;
        }
    }

2816
 cleanup:
2817
    virObjectUnref(caps);
2818 2819 2820 2821
    if (def && origname)
        *origname = name;
    else
        VIR_FREE(name);
2822 2823 2824 2825
    return def;
}


2826 2827 2828 2829 2830 2831 2832 2833 2834 2835
static int
qemuMigrationConfirmPhase(virQEMUDriverPtr driver,
                          virConnectPtr conn,
                          virDomainObjPtr vm,
                          const char *cookiein,
                          int cookieinlen,
                          unsigned int flags,
                          int retcode)
{
    qemuMigrationCookiePtr mig;
2836
    virObjectEventPtr event = NULL;
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869
    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");

2870
        event = virDomainEventLifecycleNewFromObj(vm,
2871 2872 2873 2874 2875 2876 2877
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
    } else {

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

2878 2879 2880 2881
        if (qemuMigrationRestoreDomainState(conn, vm)) {
            event = virDomainEventLifecycleNewFromObj(vm,
                                                      VIR_DOMAIN_EVENT_RESUMED,
                                                      VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
2882 2883 2884 2885 2886 2887 2888 2889
        }

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

2890
 done:
2891 2892 2893
    qemuMigrationCookieFree(mig);
    rv = 0;

2894
 cleanup:
2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909
    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;
2910
    qemuMigrationJobPhase phase;
2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
    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);
2925 2926
    virCloseCallbacksUnset(driver->closeCallbacks, vm,
                           qemuMigrationCleanup);
2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941

    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;
    }

2942
 cleanup:
2943 2944 2945 2946 2947 2948 2949
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(cfg);
    return ret;
}


2950 2951
enum qemuMigrationDestinationType {
    MIGRATION_DEST_HOST,
2952
    MIGRATION_DEST_CONNECT_HOST,
2953
    MIGRATION_DEST_UNIX,
2954
    MIGRATION_DEST_FD,
2955
};
2956

2957 2958 2959 2960
enum qemuMigrationForwardType {
    MIGRATION_FWD_DIRECT,
    MIGRATION_FWD_STREAM,
};
2961

2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972
typedef struct _qemuMigrationSpec qemuMigrationSpec;
typedef qemuMigrationSpec *qemuMigrationSpecPtr;
struct _qemuMigrationSpec {
    enum qemuMigrationDestinationType destType;
    union {
        struct {
            const char *name;
            int port;
        } host;

        struct {
2973
            char *file;
2974 2975
            int sock;
        } unix_socket;
2976 2977 2978 2979 2980

        struct {
            int qemu;
            int local;
        } fd;
2981 2982 2983 2984 2985 2986 2987
    } dest;

    enum qemuMigrationForwardType fwdType;
    union {
        virStreamPtr stream;
    } fwd;
};
2988 2989 2990

#define TUNNEL_SEND_BUF_SIZE 65536

2991 2992 2993 2994 2995 2996 2997
typedef struct _qemuMigrationIOThread qemuMigrationIOThread;
typedef qemuMigrationIOThread *qemuMigrationIOThreadPtr;
struct _qemuMigrationIOThread {
    virThread thread;
    virStreamPtr st;
    int sock;
    virError err;
2998 2999
    int wakeupRecvFD;
    int wakeupSendFD;
3000 3001 3002
};

static void qemuMigrationIOFunc(void *arg)
3003
{
3004
    qemuMigrationIOThreadPtr data = arg;
3005 3006 3007 3008 3009 3010 3011
    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);
3012

3013
    if (VIR_ALLOC_N(buffer, TUNNEL_SEND_BUF_SIZE) < 0)
3014
        goto abrt;
3015

3016 3017 3018
    fds[0].fd = data->sock;
    fds[1].fd = data->wakeupRecvFD;

3019
    for (;;) {
3020 3021 3022 3023 3024 3025 3026 3027 3028 3029
        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;
3030
            virReportSystemError(errno, "%s",
3031 3032
                                 _("poll failed in migration tunnel"));
            goto abrt;
3033
        }
3034 3035 3036 3037 3038 3039 3040

        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");
3041
            break;
3042
        }
3043

3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059
        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;
            }
3060 3061
        }

3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078
        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;
            }
        }
    }
3079

3080 3081
    if (virStreamFinish(data->st) < 0)
        goto error;
3082

3083 3084
    VIR_FREE(buffer);

3085 3086
    return;

3087
 abrt:
3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098
    err = virSaveLastError();
    if (err && err->code == VIR_ERR_OK) {
        virFreeError(err);
        err = NULL;
    }
    virStreamAbort(data->st);
    if (err) {
        virSetError(err);
        virFreeError(err);
    }

3099
 error:
3100 3101
    virCopyLastError(&data->err);
    virResetLastError();
3102
    VIR_FREE(buffer);
3103 3104 3105 3106 3107 3108 3109
}


static qemuMigrationIOThreadPtr
qemuMigrationStartTunnel(virStreamPtr st,
                         int sock)
{
3110 3111
    qemuMigrationIOThreadPtr io = NULL;
    int wakeupFD[2] = { -1, -1 };
3112

3113 3114 3115 3116
    if (pipe2(wakeupFD, O_CLOEXEC) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to make pipe"));
        goto error;
3117 3118
    }

3119
    if (VIR_ALLOC(io) < 0)
3120
        goto error;
3121

3122 3123
    io->st = st;
    io->sock = sock;
3124 3125
    io->wakeupRecvFD = wakeupFD[0];
    io->wakeupSendFD = wakeupFD[1];
3126 3127 3128 3129 3130 3131

    if (virThreadCreate(&io->thread, true,
                        qemuMigrationIOFunc,
                        io) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to create migration thread"));
3132
        goto error;
3133 3134 3135
    }

    return io;
3136

3137
 error:
3138 3139 3140 3141
    VIR_FORCE_CLOSE(wakeupFD[0]);
    VIR_FORCE_CLOSE(wakeupFD[1]);
    VIR_FREE(io);
    return NULL;
3142 3143 3144
}

static int
3145
qemuMigrationStopTunnel(qemuMigrationIOThreadPtr io, bool error)
3146 3147
{
    int rv = -1;
3148 3149 3150 3151 3152 3153 3154 3155 3156
    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;
    }

3157 3158 3159 3160
    virThreadJoin(&io->thread);

    /* Forward error from the IO thread, to this thread */
    if (io->err.code != VIR_ERR_OK) {
3161 3162 3163 3164
        if (error)
            rv = 0;
        else
            virSetError(&io->err);
3165 3166 3167 3168 3169 3170
        virResetError(&io->err);
        goto cleanup;
    }

    rv = 0;

3171
 cleanup:
3172 3173
    VIR_FORCE_CLOSE(io->wakeupSendFD);
    VIR_FORCE_CLOSE(io->wakeupRecvFD);
3174 3175
    VIR_FREE(io);
    return rv;
3176 3177
}

3178
static int
3179
qemuMigrationConnect(virQEMUDriverPtr driver,
3180 3181 3182 3183 3184 3185 3186 3187 3188
                     virDomainObjPtr vm,
                     qemuMigrationSpecPtr spec)
{
    virNetSocketPtr sock;
    const char *host;
    char *port = NULL;
    int ret = -1;

    host = spec->dest.host.name;
3189
    if (virAsprintf(&port, "%d", spec->dest.host.port) < 0)
3190 3191 3192 3193 3194 3195 3196 3197 3198
        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);
3199
        virObjectUnref(sock);
3200 3201 3202 3203 3204
    }
    if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0 ||
        spec->dest.fd.qemu == -1)
        goto cleanup;

3205 3206 3207 3208 3209 3210 3211
    /* 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;
    }

3212 3213
    ret = 0;

3214
 cleanup:
3215 3216 3217 3218 3219 3220
    VIR_FREE(port);
    if (ret < 0)
        VIR_FORCE_CLOSE(spec->dest.fd.qemu);
    return ret;
}

3221
static int
3222
qemuMigrationRun(virQEMUDriverPtr driver,
3223 3224 3225 3226 3227 3228 3229
                 virDomainObjPtr vm,
                 const char *cookiein,
                 int cookieinlen,
                 char **cookieout,
                 int *cookieoutlen,
                 unsigned long flags,
                 unsigned long resource,
3230
                 qemuMigrationSpecPtr spec,
3231 3232
                 virConnectPtr dconn,
                 const char *graphicsuri)
3233
{
3234
    int ret = -1;
3235 3236
    unsigned int migrate_flags = QEMU_MONITOR_MIGRATE_BACKGROUND;
    qemuDomainObjPrivatePtr priv = vm->privateData;
3237
    qemuMigrationCookiePtr mig = NULL;
3238
    qemuMigrationIOThreadPtr iothread = NULL;
3239
    int fd = -1;
3240
    unsigned long migrate_speed = resource ? resource : priv->migMaxBandwidth;
3241
    virErrorPtr orig_err = NULL;
3242
    unsigned int cookieFlags = 0;
3243
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
3244
    int rc;
3245 3246 3247

    VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
              "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
3248
              "spec=%p (dest=%d, fwd=%d), dconn=%p, graphicsuri=%s",
3249 3250
              driver, vm, NULLSTR(cookiein), cookieinlen,
              cookieout, cookieoutlen, flags, resource,
3251 3252
              spec, spec->destType, spec->fwdType, dconn,
              NULLSTR(graphicsuri));
3253

3254 3255 3256 3257 3258 3259 3260 3261 3262 3263
    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;
    }

3264 3265
    if (virLockManagerPluginUsesState(driver->lockManager) &&
        !cookieout) {
3266 3267 3268 3269
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Migration with lock driver %s requires"
                         " cookie support"),
                       virLockManagerPluginGetName(driver->lockManager));
3270 3271 3272
        return -1;
    }

3273 3274 3275
    mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
                                 cookieFlags | QEMU_MIGRATION_COOKIE_GRAPHICS);
    if (!mig)
3276 3277
        goto cleanup;

3278
    if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig, graphicsuri) < 0)
3279 3280
        VIR_WARN("unable to provide data for graphics client relocation");

3281 3282 3283 3284 3285 3286 3287
    /* 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;
    }

3288
    /* Before EnterMonitor, since qemuMigrationSetOffline already does that */
3289 3290 3291 3292 3293 3294
    if (!(flags & VIR_MIGRATE_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
        if (qemuMigrationSetOffline(driver, vm) < 0)
            goto cleanup;
    }

3295 3296 3297 3298 3299
    if (flags & VIR_MIGRATE_COMPRESSED &&
        qemuMigrationSetCompression(driver, vm,
                                    QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
        goto cleanup;

3300 3301 3302 3303 3304
    if (flags & VIR_MIGRATE_AUTO_CONVERGE &&
        qemuMigrationSetAutoConverge(driver, vm,
                                     QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
        goto cleanup;

3305 3306
    if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                       QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
3307 3308
        goto cleanup;

3309 3310 3311 3312
    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 */
3313
        qemuDomainObjExitMonitor(driver, vm);
3314 3315 3316 3317 3318 3319
        virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
                       qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
                       _("canceled by client"));
        goto cleanup;
    }

3320
    if (qemuMonitorSetMigrationSpeed(priv->mon, migrate_speed) < 0) {
3321
        qemuDomainObjExitMonitor(driver, vm);
3322 3323
        goto cleanup;
    }
3324

3325 3326
    /* connect to the destination qemu if needed */
    if (spec->destType == MIGRATION_DEST_CONNECT_HOST &&
3327
        qemuMigrationConnect(driver, vm, spec) < 0) {
3328
        qemuDomainObjExitMonitor(driver, vm);
3329
        goto cleanup;
3330
    }
3331

3332 3333 3334 3335 3336 3337 3338
    switch (spec->destType) {
    case MIGRATION_DEST_HOST:
        ret = qemuMonitorMigrateToHost(priv->mon, migrate_flags,
                                       spec->dest.host.name,
                                       spec->dest.host.port);
        break;

3339 3340 3341 3342
    case MIGRATION_DEST_CONNECT_HOST:
        /* handled above and transformed into MIGRATION_DEST_FD */
        break;

3343
    case MIGRATION_DEST_UNIX:
3344
        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX)) {
3345 3346 3347 3348 3349 3350 3351 3352 3353
            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;
3354 3355

    case MIGRATION_DEST_FD:
3356
        if (spec->fwdType != MIGRATION_FWD_DIRECT) {
3357
            fd = spec->dest.fd.local;
3358 3359
            spec->dest.fd.local = -1;
        }
3360 3361 3362 3363
        ret = qemuMonitorMigrateToFd(priv->mon, migrate_flags,
                                     spec->dest.fd.qemu);
        VIR_FORCE_CLOSE(spec->dest.fd.qemu);
        break;
3364
    }
3365
    qemuDomainObjExitMonitor(driver, vm);
3366
    if (ret < 0)
3367 3368
        goto cleanup;
    ret = -1;
3369 3370

    if (!virDomainObjIsActive(vm)) {
3371 3372
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("guest unexpectedly quit"));
3373 3374 3375 3376 3377 3378
        goto cleanup;
    }

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

3379 3380 3381 3382 3383 3384 3385 3386
    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;
3387

3388 3389 3390 3391 3392 3393 3394
        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;
        }
3395 3396
    }

3397 3398
    if (spec->fwdType != MIGRATION_FWD_DIRECT &&
        !(iothread = qemuMigrationStartTunnel(spec->fwd.stream, fd)))
3399 3400
        goto cancel;

3401 3402 3403 3404 3405 3406
    rc = qemuMigrationWaitForCompletion(driver, vm,
                                        QEMU_ASYNC_JOB_MIGRATION_OUT,
                                        dconn, abort_on_error);
    if (rc == -2)
        goto cancel;
    else if (rc == -1)
3407
        goto cleanup;
3408

3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421
    /* 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;
    }

3422
    ret = 0;
3423

3424
 cleanup:
3425 3426 3427
    if (ret < 0 && !orig_err)
        orig_err = virSaveLastError();

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

3431
    if (spec->fwdType != MIGRATION_FWD_DIRECT) {
3432
        if (iothread && qemuMigrationStopTunnel(iothread, ret < 0) < 0)
3433
            ret = -1;
3434
        VIR_FORCE_CLOSE(fd);
3435
    }
3436

3437 3438 3439
    cookieFlags |= QEMU_MIGRATION_COOKIE_NETWORK;
    if (flags & VIR_MIGRATE_PERSIST_DEST)
        cookieFlags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
3440
    if (ret == 0 &&
3441 3442
        qemuMigrationBakeCookie(mig, driver, vm, cookieout,
                                cookieoutlen, cookieFlags) < 0) {
3443
        VIR_WARN("Unable to encode migration cookie");
3444
    }
3445

3446 3447
    qemuMigrationCookieFree(mig);

3448 3449 3450 3451 3452
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }

3453 3454
    return ret;

3455
 cancel:
3456 3457
    orig_err = virSaveLastError();

3458
    if (virDomainObjIsActive(vm)) {
3459 3460
        if (qemuDomainObjEnterMonitorAsync(driver, vm,
                                           QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
3461
            qemuMonitorMigrateCancel(priv->mon);
3462
            qemuDomainObjExitMonitor(driver, vm);
3463
        }
3464
    }
3465 3466 3467 3468 3469 3470
    goto cleanup;
}

/* Perform migration using QEMU's native TCP migrate support,
 * not encrypted obviously
 */
3471
static int doNativeMigrate(virQEMUDriverPtr driver,
3472 3473 3474 3475 3476 3477 3478
                           virDomainObjPtr vm,
                           const char *uri,
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
                           unsigned long flags,
3479
                           unsigned long resource,
3480 3481
                           virConnectPtr dconn,
                           const char *graphicsuri)
3482
{
3483
    qemuDomainObjPrivatePtr priv = vm->privateData;
M
Martin Kletzander 已提交
3484
    virURIPtr uribits = NULL;
3485
    int ret = -1;
3486 3487 3488
    qemuMigrationSpec spec;

    VIR_DEBUG("driver=%p, vm=%p, uri=%s, cookiein=%s, cookieinlen=%d, "
3489 3490
              "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
              "graphicsuri=%s",
3491
              driver, vm, uri, NULLSTR(cookiein), cookieinlen,
3492 3493
              cookieout, cookieoutlen, flags, resource,
              NULLSTR(graphicsuri));
3494 3495

    if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) {
3496
        char *tmp;
3497
        /* HACK: source host generates bogus URIs, so fix them up */
3498
        if (virAsprintf(&tmp, "tcp://%s", uri + strlen("tcp:")) < 0)
3499
            return -1;
M
Martin Kletzander 已提交
3500
        uribits = virURIParse(tmp);
3501
        VIR_FREE(tmp);
3502
    } else {
M
Martin Kletzander 已提交
3503
        uribits = virURIParse(uri);
3504
    }
3505
    if (!uribits)
3506 3507
        return -1;

3508
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD))
3509 3510
        spec.destType = MIGRATION_DEST_CONNECT_HOST;
    else
3511
        spec.destType = MIGRATION_DEST_HOST;
3512 3513 3514
    spec.dest.host.name = uribits->server;
    spec.dest.host.port = uribits->port;
    spec.fwdType = MIGRATION_FWD_DIRECT;
3515

3516
    ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
3517 3518
                           cookieoutlen, flags, resource, &spec, dconn,
                           graphicsuri);
3519 3520 3521 3522

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

3523
    virURIFree(uribits);
3524 3525 3526 3527 3528

    return ret;
}


3529
static int doTunnelMigrate(virQEMUDriverPtr driver,
3530 3531 3532 3533 3534 3535 3536
                           virDomainObjPtr vm,
                           virStreamPtr st,
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
                           int *cookieoutlen,
                           unsigned long flags,
3537
                           unsigned long resource,
3538 3539
                           virConnectPtr dconn,
                           const char *graphicsuri)
3540 3541
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
3542
    virNetSocketPtr sock = NULL;
3543 3544
    int ret = -1;
    qemuMigrationSpec spec;
3545
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3546 3547

    VIR_DEBUG("driver=%p, vm=%p, st=%p, cookiein=%s, cookieinlen=%d, "
3548 3549
              "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
              "graphicsuri=%s",
3550
              driver, vm, st, NULLSTR(cookiein), cookieinlen,
3551 3552
              cookieout, cookieoutlen, flags, resource,
              NULLSTR(graphicsuri));
3553

3554 3555 3556
    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)) {
3557 3558
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Source qemu is too old to support tunnelled migration"));
3559
        virObjectUnref(cfg);
3560
        return -1;
3561 3562 3563 3564 3565
    }

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

3566
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD)) {
3567 3568 3569 3570 3571 3572
        int fds[2];

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

3573
        if (pipe2(fds, O_CLOEXEC) == 0) {
3574 3575 3576 3577
            spec.dest.fd.qemu = fds[1];
            spec.dest.fd.local = fds[0];
        }
        if (spec.dest.fd.qemu == -1 ||
3578
            virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
3579
                                              spec.dest.fd.qemu) < 0) {
3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590
            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",
3591
                        cfg->libDir, vm->def->name) < 0)
3592 3593 3594
            goto cleanup;

        if (virNetSocketNewListenUNIX(spec.dest.unix_socket.file, 0700,
3595
                                      cfg->user, cfg->group,
3596 3597 3598 3599 3600 3601 3602
                                      &sock) < 0 ||
            virNetSocketListen(sock, 1) < 0)
            goto cleanup;

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

3603
    ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
3604 3605
                           cookieoutlen, flags, resource, &spec, dconn,
                           graphicsuri);
3606

3607
 cleanup:
3608 3609 3610 3611
    if (spec.destType == MIGRATION_DEST_FD) {
        VIR_FORCE_CLOSE(spec.dest.fd.qemu);
        VIR_FORCE_CLOSE(spec.dest.fd.local);
    } else {
3612
        virObjectUnref(sock);
3613 3614
        VIR_FREE(spec.dest.unix_socket.file);
    }
3615

3616
    virObjectUnref(cfg);
3617 3618 3619 3620
    return ret;
}


3621 3622 3623 3624
/* 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 */
3625
static int doPeer2PeerMigrate2(virQEMUDriverPtr driver,
3626
                               virConnectPtr sconn ATTRIBUTE_UNUSED,
3627 3628
                               virConnectPtr dconn,
                               virDomainObjPtr vm,
3629
                               const char *dconnuri,
3630 3631 3632
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
3633 3634 3635
{
    virDomainPtr ddomain = NULL;
    char *uri_out = NULL;
3636
    char *cookie = NULL;
3637 3638 3639
    char *dom_xml = NULL;
    int cookielen = 0, ret;
    virErrorPtr orig_err = NULL;
3640
    bool cancelled;
3641
    virStreamPtr st = NULL;
3642
    unsigned long destflags;
3643

3644
    VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, vm=%p, dconnuri=%s, "
3645
              "flags=%lx, dname=%s, resource=%lu",
3646 3647
              driver, sconn, dconn, vm, NULLSTR(dconnuri),
              flags, NULLSTR(dname), resource);
3648

3649 3650 3651 3652 3653
    /* 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,
3654 3655
                                        QEMU_DOMAIN_FORMAT_LIVE_FLAGS |
                                        VIR_DOMAIN_XML_MIGRATABLE)))
3656 3657 3658 3659 3660
        return -1;

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

3661 3662
    destflags = flags & ~(VIR_MIGRATE_ABORT_ON_ERROR |
                          VIR_MIGRATE_AUTO_CONVERGE);
3663

3664 3665 3666 3667 3668 3669 3670 3671 3672 3673
    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;

3674
        qemuDomainObjEnterRemote(vm);
3675
        ret = dconn->driver->domainMigratePrepareTunnel
3676
            (dconn, st, destflags, dname, resource, dom_xml);
3677
        qemuDomainObjExitRemote(vm);
3678
    } else {
3679
        qemuDomainObjEnterRemote(vm);
3680 3681
        ret = dconn->driver->domainMigratePrepare2
            (dconn, &cookie, &cookielen, NULL, &uri_out,
3682
             destflags, dname, resource, dom_xml);
3683
        qemuDomainObjExitRemote(vm);
3684 3685 3686
    }
    VIR_FREE(dom_xml);
    if (ret == -1)
3687 3688 3689
        goto cleanup;

    /* the domain may have shutdown or crashed while we had the locks dropped
3690
     * in qemuDomainObjEnterRemote, so check again
3691 3692
     */
    if (!virDomainObjIsActive(vm)) {
3693 3694
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("guest unexpectedly quit"));
3695 3696 3697
        goto cleanup;
    }

3698 3699
    if (!(flags & VIR_MIGRATE_TUNNELLED) &&
        (uri_out == NULL)) {
3700 3701
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("domainMigratePrepare2 did not set uri"));
3702
        cancelled = true;
3703
        orig_err = virSaveLastError();
3704
        goto finish;
3705 3706
    }

3707 3708 3709 3710
    /* Perform the migration.  The driver isn't supposed to return
     * until the migration is complete.
     */
    VIR_DEBUG("Perform %p", sconn);
3711
    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
3712
    if (flags & VIR_MIGRATE_TUNNELLED)
3713 3714
        ret = doTunnelMigrate(driver, vm, st,
                              NULL, 0, NULL, NULL,
3715
                              flags, resource, dconn, NULL);
3716 3717 3718 3719
    else
        ret = doNativeMigrate(driver, vm, uri_out,
                              cookie, cookielen,
                              NULL, NULL, /* No out cookie with v2 migration */
3720
                              flags, resource, dconn, NULL);
3721 3722 3723 3724

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

3726 3727 3728
    /* If Perform returns < 0, then we need to cancel the VM
     * startup on the destination
     */
3729
    cancelled = ret < 0;
3730

3731
 finish:
3732 3733 3734 3735
    /* 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.
     */
3736
    dname = dname ? dname : vm->def->name;
3737
    VIR_DEBUG("Finish2 %p ret=%d", dconn, ret);
3738
    qemuDomainObjEnterRemote(vm);
3739
    ddomain = dconn->driver->domainMigrateFinish2
3740
        (dconn, dname, cookie, cookielen,
3741
         uri_out ? uri_out : dconnuri, destflags, cancelled);
3742
    qemuDomainObjExitRemote(vm);
3743 3744
    if (cancelled && ddomain)
        VIR_ERROR(_("finish step ignored that migration was cancelled"));
3745

3746
 cleanup:
3747
    if (ddomain) {
3748
        virObjectUnref(ddomain);
3749 3750 3751 3752
        ret = 0;
    } else {
        ret = -1;
    }
3753

3754
    virObjectUnref(st);
3755 3756 3757 3758 3759 3760

    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
    VIR_FREE(uri_out);
3761
    VIR_FREE(cookie);
3762 3763

    return ret;
3764 3765 3766
}


3767 3768 3769 3770
/* 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 */
3771 3772 3773 3774 3775 3776 3777 3778 3779
static int
doPeer2PeerMigrate3(virQEMUDriverPtr driver,
                    virConnectPtr sconn,
                    virConnectPtr dconn,
                    const char *dconnuri,
                    virDomainObjPtr vm,
                    const char *xmlin,
                    const char *dname,
                    const char *uri,
3780
                    const char *graphicsuri,
3781
                    const char *listenAddress,
3782 3783 3784
                    unsigned long long bandwidth,
                    bool useParams,
                    unsigned long flags)
3785 3786 3787 3788 3789 3790 3791 3792 3793 3794
{
    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;
3795
    bool cancelled = true;
3796
    virStreamPtr st = NULL;
3797
    unsigned long destflags;
3798 3799 3800 3801 3802
    virTypedParameterPtr params = NULL;
    int nparams = 0;
    int maxparams = 0;

    VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, dconnuri=%s, vm=%p, xmlin=%s, "
3803 3804
              "dname=%s, uri=%s, graphicsuri=%s, listenAddress=%s, "
              "bandwidth=%llu, useParams=%d, flags=%lx",
3805
              driver, sconn, dconn, NULLSTR(dconnuri), vm, NULLSTR(xmlin),
3806 3807
              NULLSTR(dname), NULLSTR(uri), NULLSTR(graphicsuri),
              NULLSTR(listenAddress), bandwidth, useParams, flags);
3808

3809 3810 3811 3812 3813
    /* 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.  */

3814 3815
    dom_xml = qemuMigrationBeginPhase(driver, vm, xmlin, dname,
                                      &cookieout, &cookieoutlen, flags);
3816 3817 3818
    if (!dom_xml)
        goto cleanup;

3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838
    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;
3839 3840 3841 3842 3843 3844

        if (graphicsuri &&
            virTypedParamsAddString(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_GRAPHICS_URI,
                                    graphicsuri) < 0)
            goto cleanup;
3845 3846 3847 3848 3849
        if (listenAddress &&
            virTypedParamsAddString(&params, &nparams, &maxparams,
                                    VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
                                    listenAddress) < 0)
            goto cleanup;
3850 3851
    }

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

3855 3856
    destflags = flags & ~(VIR_MIGRATE_ABORT_ON_ERROR |
                          VIR_MIGRATE_AUTO_CONVERGE);
3857

3858 3859 3860 3861 3862 3863 3864 3865 3866
    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;

3867
        qemuDomainObjEnterRemote(vm);
3868 3869 3870 3871 3872 3873 3874 3875 3876
        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);
        }
3877
        qemuDomainObjExitRemote(vm);
3878
    } else {
3879
        qemuDomainObjEnterRemote(vm);
3880 3881 3882 3883 3884 3885 3886 3887 3888
        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);
        }
3889
        qemuDomainObjExitRemote(vm);
3890 3891 3892 3893 3894
    }
    VIR_FREE(dom_xml);
    if (ret == -1)
        goto cleanup;

L
liguang 已提交
3895 3896 3897 3898
    if (flags & VIR_MIGRATE_OFFLINE) {
        VIR_DEBUG("Offline migration, skipping Perform phase");
        VIR_FREE(cookieout);
        cookieoutlen = 0;
3899
        cancelled = false;
L
liguang 已提交
3900 3901 3902
        goto finish;
    }

3903 3904 3905 3906
    if (uri_out) {
        uri = uri_out;
        if (useParams &&
            virTypedParamsReplaceString(&params, &nparams,
3907 3908
                                        VIR_MIGRATE_PARAM_URI, uri_out) < 0) {
            orig_err = virSaveLastError();
3909
            goto finish;
3910
        }
3911
    } else if (!uri && !(flags & VIR_MIGRATE_TUNNELLED)) {
3912 3913
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("domainMigratePrepare3 did not set uri"));
3914
        orig_err = virSaveLastError();
3915 3916 3917 3918 3919 3920 3921 3922
        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.
     */
3923
    VIR_DEBUG("Perform3 %p uri=%s", sconn, NULLSTR(uri));
3924
    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM3);
3925 3926 3927 3928 3929
    VIR_FREE(cookiein);
    cookiein = cookieout;
    cookieinlen = cookieoutlen;
    cookieout = NULL;
    cookieoutlen = 0;
3930
    if (flags & VIR_MIGRATE_TUNNELLED) {
3931 3932 3933
        ret = doTunnelMigrate(driver, vm, st,
                              cookiein, cookieinlen,
                              &cookieout, &cookieoutlen,
3934
                              flags, bandwidth, dconn, graphicsuri);
3935 3936
    } else {
        ret = doNativeMigrate(driver, vm, uri,
3937 3938
                              cookiein, cookieinlen,
                              &cookieout, &cookieoutlen,
3939
                              flags, bandwidth, dconn, graphicsuri);
3940
    }
3941 3942

    /* Perform failed. Make sure Finish doesn't overwrite the error */
3943
    if (ret < 0) {
3944
        orig_err = virSaveLastError();
3945 3946 3947 3948
    } else {
        qemuMigrationJobSetPhase(driver, vm,
                                 QEMU_MIGRATION_PHASE_PERFORM3_DONE);
    }
3949 3950 3951 3952

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

3955
 finish:
3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967
    /*
     * 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;
3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990

    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);
    }
3991 3992
    if (cancelled && ddomain)
        VIR_ERROR(_("finish step ignored that migration was cancelled"));
3993

3994 3995 3996 3997 3998 3999 4000
    /* 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.
4001
     */
4002
    cancelled = ddomain == NULL;
4003

4004 4005 4006 4007 4008 4009
    /* 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();

4010 4011 4012 4013
    /*
     * If cancelled, then src VM will be restarted, else
     * it will be killed
     */
4014
    VIR_DEBUG("Confirm3 %p cancelled=%d vm=%p", sconn, cancelled, vm);
4015 4016 4017 4018 4019
    VIR_FREE(cookiein);
    cookiein = cookieout;
    cookieinlen = cookieoutlen;
    cookieout = NULL;
    cookieoutlen = 0;
4020 4021 4022
    ret = qemuMigrationConfirmPhase(driver, sconn, vm,
                                    cookiein, cookieinlen,
                                    flags, cancelled);
4023 4024 4025 4026
    /* 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.
     */
4027 4028 4029
    if (ret < 0)
        VIR_WARN("Guest %s probably left in 'paused' state on source",
                 vm->def->name);
4030 4031 4032

 cleanup:
    if (ddomain) {
4033
        virObjectUnref(ddomain);
4034 4035 4036 4037 4038
        ret = 0;
    } else {
        ret = -1;
    }

4039
    virObjectUnref(st);
4040 4041 4042 4043 4044 4045 4046 4047

    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
    VIR_FREE(uri_out);
    VIR_FREE(cookiein);
    VIR_FREE(cookieout);
4048
    virTypedParamsFree(params, nparams);
4049 4050 4051 4052
    return ret;
}


4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064
static int virConnectCredType[] = {
    VIR_CRED_AUTHNAME,
    VIR_CRED_PASSPHRASE,
};


static virConnectAuth virConnectAuthConfig = {
    .credtype = virConnectCredType,
    .ncredtype = ARRAY_CARDINALITY(virConnectCredType),
};


4065
static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
4066
                              virConnectPtr sconn,
4067
                              virDomainObjPtr vm,
4068
                              const char *xmlin,
4069
                              const char *dconnuri,
4070
                              const char *uri,
4071
                              const char *graphicsuri,
4072
                              const char *listenAddress,
4073 4074
                              unsigned long flags,
                              const char *dname,
4075 4076
                              unsigned long resource,
                              bool *v3proto)
4077 4078 4079 4080
{
    int ret = -1;
    virConnectPtr dconn = NULL;
    bool p2p;
4081
    virErrorPtr orig_err = NULL;
4082
    bool offline = false;
4083
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4084
    bool useParams;
4085

4086
    VIR_DEBUG("driver=%p, sconn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
4087 4088
              "uri=%s, graphicsuri=%s, listenAddress=%s, flags=%lx, "
              "dname=%s, resource=%lu",
4089
              driver, sconn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
4090 4091
              NULLSTR(uri), NULLSTR(graphicsuri), NULLSTR(listenAddress),
              flags, NULLSTR(dname), resource);
4092 4093 4094 4095 4096

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

4097
    qemuDomainObjEnterRemote(vm);
4098
    dconn = virConnectOpenAuth(dconnuri, &virConnectAuthConfig, 0);
4099
    qemuDomainObjExitRemote(vm);
4100
    if (dconn == NULL) {
4101
        virReportError(VIR_ERR_OPERATION_FAILED,
4102 4103
                       _("Failed to connect to remote libvirt URI %s: %s"),
                       dconnuri, virGetLastErrorMessage());
4104
        virObjectUnref(cfg);
4105 4106 4107
        return -1;
    }

4108 4109
    if (virConnectSetKeepAlive(dconn, cfg->keepAliveInterval,
                               cfg->keepAliveCount) < 0)
4110 4111
        goto cleanup;

4112
    qemuDomainObjEnterRemote(vm);
4113 4114
    p2p = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                   VIR_DRV_FEATURE_MIGRATION_P2P);
4115
        /* v3proto reflects whether the caller used Perform3, but with
4116
         * p2p migrate, regardless of whether Perform2 or Perform3
4117 4118 4119 4120
         * were used, we decide protocol based on what target supports
         */
    *v3proto = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                        VIR_DRV_FEATURE_MIGRATION_V3);
4121 4122
    useParams = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                         VIR_DRV_FEATURE_MIGRATION_PARAMS);
L
liguang 已提交
4123 4124 4125
    if (flags & VIR_MIGRATE_OFFLINE)
        offline = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
                                           VIR_DRV_FEATURE_MIGRATION_OFFLINE);
4126
    qemuDomainObjExitRemote(vm);
4127

4128
    if (!p2p) {
4129 4130
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Destination libvirt does not support peer-to-peer migration protocol"));
4131 4132 4133
        goto cleanup;
    }

4134 4135
    /* Only xmlin, dname, uri, and bandwidth parameters can be used with
     * old-style APIs. */
4136
    if (!useParams && graphicsuri) {
4137 4138 4139 4140 4141 4142
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Migration APIs with extensible parameters are not "
                         "supported but extended parameters were passed"));
        goto cleanup;
    }

L
liguang 已提交
4143 4144 4145 4146 4147 4148 4149
    if (flags & VIR_MIGRATE_OFFLINE && !offline) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("offline migration is not supported by "
                         "the destination host"));
        goto cleanup;
    }

4150
    /* domain may have been stopped while we were talking to remote daemon */
L
liguang 已提交
4151
    if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
4152 4153
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("guest unexpectedly quit"));
4154 4155 4156
        goto cleanup;
    }

4157 4158 4159 4160 4161 4162 4163
    /* 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;

4164 4165
    if (*v3proto) {
        ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin,
4166 4167
                                  dname, uri, graphicsuri, listenAddress,
                                  resource, useParams, flags);
4168
    } else {
4169
        ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
4170
                                  dconnuri, flags, dname, resource);
4171
    }
4172

4173
 cleanup:
4174
    orig_err = virSaveLastError();
4175
    qemuDomainObjEnterRemote(vm);
4176
    virObjectUnref(dconn);
4177
    qemuDomainObjExitRemote(vm);
4178 4179 4180 4181
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
4182
    virObjectUnref(cfg);
4183 4184 4185 4186
    return ret;
}


4187 4188 4189 4190 4191 4192
/*
 * 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
4193
qemuMigrationPerformJob(virQEMUDriverPtr driver,
4194 4195 4196 4197 4198
                        virConnectPtr conn,
                        virDomainObjPtr vm,
                        const char *xmlin,
                        const char *dconnuri,
                        const char *uri,
4199
                        const char *graphicsuri,
4200
                        const char *listenAddress,
4201
                        const char *cookiein,
4202 4203 4204 4205 4206 4207 4208
                        int cookieinlen,
                        char **cookieout,
                        int *cookieoutlen,
                        unsigned long flags,
                        const char *dname,
                        unsigned long resource,
                        bool v3proto)
4209
{
4210
    virObjectEventPtr event = NULL;
4211
    int ret = -1;
4212
    virErrorPtr orig_err = NULL;
4213
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4214
    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
4215

4216
    if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
4217 4218
        goto cleanup;

L
liguang 已提交
4219
    if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
4220 4221
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
4222 4223 4224
        goto endjob;
    }

4225
    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
4226
        goto endjob;
4227

4228
    if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
4229
        goto endjob;
4230

4231
    qemuMigrationStoreDomainState(vm);
4232 4233

    if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
4234
        ret = doPeer2PeerMigrate(driver, conn, vm, xmlin,
4235 4236
                                 dconnuri, uri, graphicsuri, listenAddress,
                                 flags, dname, resource, &v3proto);
4237
    } else {
4238 4239 4240
        qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
        ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
                              cookieout, cookieoutlen,
4241
                              flags, resource, NULL, NULL);
4242
    }
4243 4244
    if (ret < 0)
        goto endjob;
4245

4246 4247 4248 4249
    /*
     * In v3 protocol, the source VM is not killed off until the
     * confirm step.
     */
4250
    if (!v3proto) {
4251 4252
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED,
                        VIR_QEMU_PROCESS_STOP_MIGRATED);
4253
        virDomainAuditStop(vm, "migrated");
4254
        event = virDomainEventLifecycleNewFromObj(vm,
4255 4256
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
4257 4258
    }

4259
 endjob:
4260 4261 4262
    if (ret < 0)
        orig_err = virSaveLastError();

4263
    if (qemuMigrationRestoreDomainState(conn, vm)) {
4264
        event = virDomainEventLifecycleNewFromObj(vm,
4265 4266 4267
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
    }
4268

4269
    if (!qemuMigrationJobFinish(driver, vm)) {
4270 4271 4272 4273 4274
        vm = NULL;
    } else if (!virDomainObjIsActive(vm) &&
               (!vm->persistent ||
                (ret == 0 && (flags & VIR_MIGRATE_UNDEFINE_SOURCE)))) {
        if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
4275
            virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
4276
        qemuDomainRemoveInactive(driver, vm);
4277 4278 4279
        vm = NULL;
    }

4280 4281 4282 4283 4284
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }

4285
 cleanup:
4286
    if (vm)
4287
        virObjectUnlock(vm);
4288 4289
    if (event)
        qemuDomainEventQueue(driver, event);
4290
    virObjectUnref(cfg);
4291 4292 4293 4294 4295 4296 4297
    return ret;
}

/*
 * This implements perform phase of v3 migration protocol.
 */
static int
4298
qemuMigrationPerformPhase(virQEMUDriverPtr driver,
4299 4300 4301
                          virConnectPtr conn,
                          virDomainObjPtr vm,
                          const char *uri,
4302
                          const char *graphicsuri,
4303 4304 4305 4306 4307 4308 4309
                          const char *cookiein,
                          int cookieinlen,
                          char **cookieout,
                          int *cookieoutlen,
                          unsigned long flags,
                          unsigned long resource)
{
4310
    virObjectEventPtr event = NULL;
4311
    int ret = -1;
4312
    bool hasrefs;
4313 4314 4315 4316 4317 4318 4319 4320 4321 4322

    /* 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);
4323 4324
    virCloseCallbacksUnset(driver->closeCallbacks, vm,
                           qemuMigrationCleanup);
4325 4326 4327

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

4330 4331 4332 4333 4334
    if (ret < 0) {
        if (qemuMigrationRestoreDomainState(conn, vm)) {
            event = virDomainEventLifecycleNewFromObj(vm,
                                                      VIR_DOMAIN_EVENT_RESUMED,
                                                      VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
4335
        }
4336
        goto endjob;
4337
    }
4338 4339 4340

    qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM3_DONE);

4341 4342
    if (virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
                             qemuMigrationCleanup) < 0)
4343 4344
        goto endjob;

4345
 endjob:
4346
    if (ret < 0)
4347
        hasrefs = qemuMigrationJobFinish(driver, vm);
4348
    else
4349 4350
        hasrefs = qemuMigrationJobContinue(vm);
    if (!hasrefs) {
4351 4352
        vm = NULL;
    } else if (!virDomainObjIsActive(vm) && !vm->persistent) {
4353
        qemuDomainRemoveInactive(driver, vm);
4354
        vm = NULL;
4355
    }
4356

4357
 cleanup:
4358
    if (vm)
4359
        virObjectUnlock(vm);
4360 4361 4362 4363 4364
    if (event)
        qemuDomainEventQueue(driver, event);
    return ret;
}

4365
int
4366
qemuMigrationPerform(virQEMUDriverPtr driver,
4367 4368 4369 4370 4371
                     virConnectPtr conn,
                     virDomainObjPtr vm,
                     const char *xmlin,
                     const char *dconnuri,
                     const char *uri,
4372
                     const char *graphicsuri,
4373
                     const char *listenAddress,
4374 4375 4376 4377 4378 4379 4380 4381 4382 4383
                     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, "
4384
              "uri=%s, graphicsuri=%s, listenAddress=%s"
4385 4386
              "cookiein=%s, cookieinlen=%d, cookieout=%p, cookieoutlen=%p, "
              "flags=%lx, dname=%s, resource=%lu, v3proto=%d",
4387
              driver, conn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
4388
              NULLSTR(uri), NULLSTR(graphicsuri), NULLSTR(listenAddress),
4389 4390
              NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen,
              flags, NULLSTR(dname), resource, v3proto);
4391 4392 4393

    if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
        if (cookieinlen) {
4394 4395
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("received unexpected cookie with P2P migration"));
4396 4397 4398 4399
            return -1;
        }

        return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri, uri,
4400 4401
                                       graphicsuri, listenAddress,
                                       cookiein, cookieinlen,
4402 4403
                                       cookieout, cookieoutlen,
                                       flags, dname, resource, v3proto);
4404 4405
    } else {
        if (dconnuri) {
4406 4407
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Unexpected dconnuri parameter with non-peer2peer migration"));
4408 4409 4410 4411 4412
            return -1;
        }

        if (v3proto) {
            return qemuMigrationPerformPhase(driver, conn, vm, uri,
4413
                                             graphicsuri,
4414 4415
                                             cookiein, cookieinlen,
                                             cookieout, cookieoutlen,
4416
                                             flags, resource);
4417 4418
        } else {
            return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri,
4419
                                           uri, graphicsuri, listenAddress,
4420
                                           cookiein, cookieinlen,
4421 4422 4423 4424 4425
                                           cookieout, cookieoutlen, flags,
                                           dname, resource, v3proto);
        }
    }
}
4426

4427
static int
4428 4429
qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def)
{
4430
    size_t i;
4431 4432 4433 4434 4435
    int last_good_net = -1;
    virDomainNetDefPtr net;

    for (i = 0; i < def->nnets; i++) {
        net = def->nets[i];
4436
        if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
4437
            if (virNetDevVPortProfileAssociate(net->ifname,
4438
                                               virDomainNetGetActualVirtPortProfile(net),
4439
                                               &net->mac,
4440
                                               virDomainNetGetActualDirectDev(net),
4441
                                               -1,
4442
                                               def->uuid,
4443 4444
                                               VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH,
                                               false) < 0) {
4445 4446 4447
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("Port profile Associate failed for %s"),
                               net->ifname);
4448
                goto err_exit;
4449 4450
            }
            VIR_DEBUG("Port profile Associate succeeded for %s", net->ifname);
4451

4452
            if (virNetDevMacVLanVPortProfileRegisterCallback(net->ifname, &net->mac,
4453 4454 4455 4456
                                                             virDomainNetGetActualDirectDev(net), def->uuid,
                                                             virDomainNetGetActualVirtPortProfile(net),
                                                             VIR_NETDEV_VPORT_PROFILE_OP_CREATE))
                goto err_exit;
4457 4458 4459 4460
        }
        last_good_net = i;
    }

4461
    return 0;
4462

4463
 err_exit:
4464
    for (i = 0; last_good_net != -1 && i < last_good_net; i++) {
4465
        net = def->nets[i];
4466
        if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
4467
            ignore_value(virNetDevVPortProfileDisassociate(net->ifname,
4468
                                                           virDomainNetGetActualVirtPortProfile(net),
4469
                                                           &net->mac,
4470
                                                           virDomainNetGetActualDirectDev(net),
4471
                                                           -1,
4472
                                                           VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH));
4473 4474
        }
    }
4475
    return -1;
4476 4477 4478 4479
}


virDomainPtr
4480
qemuMigrationFinish(virQEMUDriverPtr driver,
4481 4482
                    virConnectPtr dconn,
                    virDomainObjPtr vm,
4483 4484 4485 4486
                    const char *cookiein,
                    int cookieinlen,
                    char **cookieout,
                    int *cookieoutlen,
4487
                    unsigned long flags,
4488 4489
                    int retcode,
                    bool v3proto)
4490 4491
{
    virDomainPtr dom = NULL;
4492
    virObjectEventPtr event = NULL;
4493
    bool newVM = true;
4494
    qemuMigrationCookiePtr mig = NULL;
4495
    virErrorPtr orig_err = NULL;
4496
    int cookie_flags = 0;
J
Jiri Denemark 已提交
4497
    qemuDomainObjPrivatePtr priv = vm->privateData;
4498
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4499
    virCapsPtr caps = NULL;
4500
    unsigned short port;
4501

4502
    VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
4503
              "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
4504 4505
              driver, dconn, vm, NULLSTR(cookiein), cookieinlen,
              cookieout, cookieoutlen, flags, retcode);
4506

4507 4508 4509
    port = priv->migrationPort;
    priv->migrationPort = 0;

4510 4511 4512
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

4513
    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
4514 4515
        goto cleanup;

4516 4517 4518
    qemuMigrationJobStartPhase(driver, vm,
                               v3proto ? QEMU_MIGRATION_PHASE_FINISH3
                                       : QEMU_MIGRATION_PHASE_FINISH2);
4519

4520 4521
    qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);

4522
    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK;
4523 4524 4525 4526 4527
    if (flags & VIR_MIGRATE_PERSIST_DEST)
        cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;

    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein,
                                       cookieinlen, cookie_flags)))
4528
        goto endjob;
4529 4530 4531 4532 4533

    /* 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 已提交
4534
        if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
4535 4536
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
4537
            goto endjob;
4538 4539
        }

L
liguang 已提交
4540 4541 4542 4543 4544
        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");
4545
                event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
4546 4547 4548 4549 4550 4551 4552
                                                 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");
4553
        }
4554

4555 4556
        qemuMigrationStopNBDServer(driver, vm, mig);

4557
        if (flags & VIR_MIGRATE_PERSIST_DEST) {
4558
            virDomainDefPtr vmdef;
4559
            if (vm->persistent)
4560
                newVM = false;
4561
            vm->persistent = 1;
4562 4563 4564
            if (mig->persistent)
                vm->newDef = vmdef = mig->persistent;
            else
4565
                vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm);
4566
            if (!vmdef || virDomainSaveConfig(cfg->configDir, vmdef) < 0) {
4567 4568 4569 4570 4571 4572 4573 4574 4575
                /* 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.
                 */
4576 4577

                /*
4578 4579
                 * However, in v3 protocol, the source VM is still available
                 * to restart during confirm() step, so we kill it off now.
4580 4581
                 */
                if (v3proto) {
L
liguang 已提交
4582 4583 4584 4585 4586
                    if (!(flags & VIR_MIGRATE_OFFLINE)) {
                        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
                                        VIR_QEMU_PROCESS_STOP_MIGRATED);
                        virDomainAuditStop(vm, "failed");
                    }
4587 4588
                    if (newVM)
                        vm->persistent = 0;
4589
                }
A
Alex Jia 已提交
4590
                if (!vmdef)
4591 4592
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("can't get vmdef"));
4593 4594 4595
                goto endjob;
            }

4596
            event = virDomainEventLifecycleNewFromObj(vm,
4597 4598 4599 4600 4601 4602 4603 4604 4605
                                             VIR_DOMAIN_EVENT_DEFINED,
                                             newVM ?
                                             VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                             VIR_DOMAIN_EVENT_DEFINED_UPDATED);
            if (event)
                qemuDomainEventQueue(driver, event);
            event = NULL;
        }

L
liguang 已提交
4606
        if (!(flags & VIR_MIGRATE_PAUSED) && !(flags & VIR_MIGRATE_OFFLINE)) {
4607 4608 4609 4610
            /* 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 已提交
4611
            if (qemuProcessStartCPUs(driver, vm, dconn,
4612 4613
                                     VIR_DOMAIN_RUNNING_MIGRATED,
                                     QEMU_ASYNC_JOB_MIGRATION_IN) < 0) {
4614
                if (virGetLastError() == NULL)
4615 4616
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("resume operation failed"));
4617 4618 4619 4620 4621
                /* Need to save the current error, in case shutting
                 * down the process overwrites it
                 */
                orig_err = virSaveLastError();

4622 4623 4624 4625 4626 4627 4628 4629 4630
                /*
                 * 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) {
4631 4632
                    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
                                    VIR_QEMU_PROCESS_STOP_MIGRATED);
4633
                    virDomainAuditStop(vm, "failed");
4634
                    event = virDomainEventLifecycleNewFromObj(vm,
4635 4636 4637
                                                     VIR_DOMAIN_EVENT_STOPPED,
                                                     VIR_DOMAIN_EVENT_STOPPED_FAILED);
                }
4638 4639 4640 4641
                goto endjob;
            }
        }

4642
        dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
4643

L
liguang 已提交
4644
        if (!(flags & VIR_MIGRATE_OFFLINE)) {
4645
            event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
4646 4647 4648 4649 4650 4651 4652
                                             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);
4653
                event = virDomainEventLifecycleNewFromObj(vm,
L
liguang 已提交
4654 4655 4656
                                                 VIR_DOMAIN_EVENT_SUSPENDED,
                                                 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
            }
4657
        }
L
liguang 已提交
4658 4659

        if (virDomainObjIsActive(vm) &&
4660
            virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
4661 4662 4663
            VIR_WARN("Failed to save status on vm %s", vm->def->name);
            goto endjob;
        }
4664 4665 4666

        /* Guest is successfully running, so cancel previous auto destroy */
        qemuProcessAutoDestroyRemove(driver, vm);
L
liguang 已提交
4667
    } else if (!(flags & VIR_MIGRATE_OFFLINE)) {
4668 4669
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
                        VIR_QEMU_PROCESS_STOP_MIGRATED);
4670
        virDomainAuditStop(vm, "failed");
4671
        event = virDomainEventLifecycleNewFromObj(vm,
4672 4673 4674 4675
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
    }

4676 4677 4678
    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
        VIR_WARN("Unable to encode migration cookie");

4679
 endjob:
E
Eric Blake 已提交
4680 4681 4682
    if (qemuMigrationJobFinish(driver, vm) == 0) {
        vm = NULL;
    } else if (!vm->persistent && !virDomainObjIsActive(vm)) {
4683
        qemuDomainRemoveInactive(driver, vm);
E
Eric Blake 已提交
4684
        vm = NULL;
4685
    }
4686

4687
 cleanup:
4688
    virPortAllocatorRelease(driver->migrationPorts, port);
J
Jiri Denemark 已提交
4689 4690
    if (vm) {
        VIR_FREE(priv->origname);
4691
        virObjectUnlock(vm);
J
Jiri Denemark 已提交
4692
    }
4693 4694
    if (event)
        qemuDomainEventQueue(driver, event);
4695
    qemuMigrationCookieFree(mig);
4696 4697 4698 4699
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
4700
    virObjectUnref(caps);
4701
    virObjectUnref(cfg);
4702 4703
    return dom;
}
4704

4705

4706
/* Helper function called while vm is active.  */
4707
int
4708
qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
4709 4710
                    int fd, off_t offset, const char *path,
                    const char *compressor,
E
Eric Blake 已提交
4711
                    bool bypassSecurityDriver,
4712
                    qemuDomainAsyncJob asyncJob)
4713 4714 4715
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int rc;
4716
    int ret = -1;
4717
    bool restoreLabel = false;
4718 4719
    virCommandPtr cmd = NULL;
    int pipeFD[2] = { -1, -1 };
4720
    unsigned long saveMigBandwidth = priv->migMaxBandwidth;
4721
    char *errbuf = NULL;
4722
    virErrorPtr orig_err = NULL;
4723 4724 4725 4726 4727

    /* 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,
4728 4729
                                     QEMU_DOMAIN_MIG_BANDWIDTH_MAX);
        priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
4730
        qemuDomainObjExitMonitor(driver, vm);
4731
    }
4732

4733
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
4734
        (!compressor || pipe(pipeFD) == 0)) {
4735
        /* All right! We can use fd migration, which means that qemu
4736 4737 4738
         * 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.  */
4739
        if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
4740
                                              compressor ? pipeFD[1] : fd) < 0)
4741
            goto cleanup;
4742 4743 4744
        bypassSecurityDriver = true;
    } else {
        /* Phooey - we have to fall back on exec migration, where qemu
E
Eric Blake 已提交
4745 4746
         * has to popen() the file by name, and block devices have to be
         * given cgroup ACL permission.  We might also stumble on
4747 4748
         * a race present in some qemu versions where it does a wait()
         * that botches pclose.  */
4749 4750
        if (virCgroupHasController(priv->cgroup,
                                   VIR_CGROUP_CONTROLLER_DEVICES)) {
4751 4752 4753 4754
            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 已提交
4755
                /* path was not a device, no further need for cgroup */
4756
            } else if (rv < 0) {
4757 4758
                goto cleanup;
            }
4759
        }
4760 4761
        if ((!bypassSecurityDriver) &&
            virSecurityManagerSetSavedStateLabel(driver->securityManager,
4762
                                                 vm->def, path) < 0)
4763
            goto cleanup;
4764
        restoreLabel = true;
4765 4766
    }

4767
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
4768 4769
        goto cleanup;

4770 4771 4772
    if (!compressor) {
        const char *args[] = { "cat", NULL };

4773
        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789
            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
        };
4790 4791 4792 4793
        if (pipeFD[0] != -1) {
            cmd = virCommandNewArgs(args);
            virCommandSetInputFD(cmd, pipeFD[0]);
            virCommandSetOutputFD(cmd, &fd);
4794 4795
            virCommandSetErrorBuffer(cmd, &errbuf);
            virCommandDoAsyncIO(cmd);
4796 4797 4798
            if (virSetCloseExec(pipeFD[1]) < 0) {
                virReportSystemError(errno, "%s",
                                     _("Unable to set cloexec flag"));
4799
                qemuDomainObjExitMonitor(driver, vm);
4800 4801 4802
                goto cleanup;
            }
            if (virCommandRunAsync(cmd, NULL) < 0) {
4803
                qemuDomainObjExitMonitor(driver, vm);
4804 4805 4806 4807 4808 4809 4810
                goto cleanup;
            }
            rc = qemuMonitorMigrateToFd(priv->mon,
                                        QEMU_MONITOR_MIGRATE_BACKGROUND,
                                        pipeFD[1]);
            if (VIR_CLOSE(pipeFD[0]) < 0 ||
                VIR_CLOSE(pipeFD[1]) < 0)
4811
                VIR_WARN("failed to close intermediate pipe");
4812 4813 4814 4815 4816
        } else {
            rc = qemuMonitorMigrateToFile(priv->mon,
                                          QEMU_MONITOR_MIGRATE_BACKGROUND,
                                          args, path, offset);
        }
4817
    }
4818
    qemuDomainObjExitMonitor(driver, vm);
4819 4820 4821 4822

    if (rc < 0)
        goto cleanup;

4823
    rc = qemuMigrationWaitForCompletion(driver, vm, asyncJob, NULL, false);
4824

4825 4826 4827 4828 4829 4830 4831 4832 4833
    if (rc < 0) {
        if (rc == -2) {
            orig_err = virSaveLastError();
            virCommandAbort(cmd);
            if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
                qemuMonitorMigrateCancel(priv->mon);
                qemuDomainObjExitMonitor(driver, vm);
            }
        }
4834
        goto cleanup;
4835
    }
4836

4837 4838 4839
    if (cmd && virCommandWait(cmd, NULL) < 0)
        goto cleanup;

4840 4841
    ret = 0;

4842
 cleanup:
4843 4844 4845
    if (ret < 0 && !orig_err)
        orig_err = virSaveLastError();

4846 4847 4848 4849
    /* Restore max migration bandwidth */
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
        qemuMonitorSetMigrationSpeed(priv->mon, saveMigBandwidth);
        priv->migMaxBandwidth = saveMigBandwidth;
4850
        qemuDomainObjExitMonitor(driver, vm);
4851 4852
    }

4853 4854
    VIR_FORCE_CLOSE(pipeFD[0]);
    VIR_FORCE_CLOSE(pipeFD[1]);
4855 4856 4857 4858 4859
    if (cmd) {
        VIR_DEBUG("Compression binary stderr: %s", NULLSTR(errbuf));
        VIR_FREE(errbuf);
        virCommandFree(cmd);
    }
4860 4861
    if (restoreLabel && (!bypassSecurityDriver) &&
        virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
4862
                                                 vm->def, path) < 0)
4863 4864
        VIR_WARN("failed to restore save state label on %s", path);

4865 4866
    if (virCgroupHasController(priv->cgroup,
                               VIR_CGROUP_CONTROLLER_DEVICES)) {
4867 4868 4869
        int rv = virCgroupDenyDevicePath(priv->cgroup, path,
                                         VIR_CGROUP_DEVICE_RWM);
        virDomainAuditCgroupPath(vm, priv->cgroup, "deny", path, "rwm", rv == 0);
4870
    }
4871 4872 4873 4874 4875 4876

    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }

4877 4878
    return ret;
}
4879 4880

int
4881
qemuMigrationJobStart(virQEMUDriverPtr driver,
4882
                      virDomainObjPtr vm,
4883
                      qemuDomainAsyncJob job)
4884 4885 4886
{
    qemuDomainObjPrivatePtr priv = vm->privateData;

4887
    if (qemuDomainObjBeginAsyncJob(driver, vm, job) < 0)
4888 4889
        return -1;

4890
    if (job == QEMU_ASYNC_JOB_MIGRATION_IN) {
4891
        qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE);
4892 4893
    } else {
        qemuDomainObjSetAsyncJobMask(vm, DEFAULT_JOB_MASK |
4894
                                     JOB_MASK(QEMU_JOB_SUSPEND) |
4895 4896
                                     JOB_MASK(QEMU_JOB_MIGRATION_OP));
    }
4897 4898 4899 4900 4901 4902 4903

    priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;

    return 0;
}

void
4904
qemuMigrationJobSetPhase(virQEMUDriverPtr driver,
4905
                         virDomainObjPtr vm,
4906
                         qemuMigrationJobPhase phase)
4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920
{
    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
4921
qemuMigrationJobStartPhase(virQEMUDriverPtr driver,
4922
                           virDomainObjPtr vm,
4923
                           qemuMigrationJobPhase phase)
4924
{
4925
    virObjectRef(vm);
4926 4927 4928
    qemuMigrationJobSetPhase(driver, vm, phase);
}

4929
bool
4930 4931
qemuMigrationJobContinue(virDomainObjPtr vm)
{
4932
    qemuDomainObjReleaseAsyncJob(vm);
4933
    return virObjectUnref(vm);
4934 4935 4936 4937
}

bool
qemuMigrationJobIsActive(virDomainObjPtr vm,
4938
                         qemuDomainAsyncJob job)
4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949
{
    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");

4950
        virReportError(VIR_ERR_OPERATION_INVALID, msg, vm->def->name);
4951 4952 4953 4954 4955
        return false;
    }
    return true;
}

4956
bool
4957
qemuMigrationJobFinish(virQEMUDriverPtr driver, virDomainObjPtr vm)
4958 4959 4960
{
    return qemuDomainObjEndAsyncJob(driver, vm);
}