qemu_domain.c 80.9 KB
Newer Older
1
/*
2
 * qemu_domain.c: QEMU domain private state
3
 *
4
 * Copyright (C) 2006-2014 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26 27
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include "qemu_domain.h"
#include "qemu_command.h"
28
#include "qemu_capabilities.h"
29
#include "qemu_migration.h"
30
#include "viralloc.h"
31
#include "virlog.h"
32
#include "virerror.h"
33
#include "c-ctype.h"
34
#include "cpu/cpu.h"
35
#include "viruuid.h"
E
Eric Blake 已提交
36
#include "virfile.h"
37
#include "domain_addr.h"
38
#include "domain_event.h"
39
#include "virtime.h"
40
#include "virstoragefile.h"
41
#include "virstring.h"
42

43 44
#include "storage/storage_driver.h"

45
#include <sys/time.h>
46
#include <fcntl.h>
47

48 49 50 51
#include <libxml/xpathInternals.h>

#define VIR_FROM_THIS VIR_FROM_QEMU

52 53
VIR_LOG_INIT("qemu.qemu_domain");

54 55
#define QEMU_NAMESPACE_HREF "http://libvirt.org/schemas/domain/qemu/1.0"

56 57 58 59 60 61
VIR_ENUM_IMPL(qemuDomainJob, QEMU_JOB_LAST,
              "none",
              "query",
              "destroy",
              "suspend",
              "modify",
62
              "abort",
63
              "migration operation",
64 65 66 67 68 69 70 71 72 73
              "none",   /* async job is never stored in job.active */
              "async nested",
);

VIR_ENUM_IMPL(qemuDomainAsyncJob, QEMU_ASYNC_JOB_LAST,
              "none",
              "migration out",
              "migration in",
              "save",
              "dump",
74
              "snapshot",
75 76
);

77

J
Jiri Denemark 已提交
78
const char *
79
qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job,
J
Jiri Denemark 已提交
80 81 82 83 84
                                int phase ATTRIBUTE_UNUSED)
{
    switch (job) {
    case QEMU_ASYNC_JOB_MIGRATION_OUT:
    case QEMU_ASYNC_JOB_MIGRATION_IN:
85 86
        return qemuMigrationJobPhaseTypeToString(phase);

J
Jiri Denemark 已提交
87 88
    case QEMU_ASYNC_JOB_SAVE:
    case QEMU_ASYNC_JOB_DUMP:
89
    case QEMU_ASYNC_JOB_SNAPSHOT:
J
Jiri Denemark 已提交
90 91 92 93 94 95 96 97 98
    case QEMU_ASYNC_JOB_NONE:
    case QEMU_ASYNC_JOB_LAST:
        ; /* fall through */
    }

    return "none";
}

int
99
qemuDomainAsyncJobPhaseFromString(qemuDomainAsyncJob job,
J
Jiri Denemark 已提交
100 101 102 103 104 105 106 107
                                  const char *phase)
{
    if (!phase)
        return 0;

    switch (job) {
    case QEMU_ASYNC_JOB_MIGRATION_OUT:
    case QEMU_ASYNC_JOB_MIGRATION_IN:
108 109
        return qemuMigrationJobPhaseTypeFromString(phase);

J
Jiri Denemark 已提交
110 111
    case QEMU_ASYNC_JOB_SAVE:
    case QEMU_ASYNC_JOB_DUMP:
112
    case QEMU_ASYNC_JOB_SNAPSHOT:
J
Jiri Denemark 已提交
113 114 115 116 117 118 119 120 121 122 123
    case QEMU_ASYNC_JOB_NONE:
    case QEMU_ASYNC_JOB_LAST:
        ; /* fall through */
    }

    if (STREQ(phase, "none"))
        return 0;
    else
        return -1;
}

124

125
void qemuDomainEventQueue(virQEMUDriverPtr driver,
126
                          virObjectEventPtr event)
127
{
128
    virObjectEventStateQueue(driver->domainEventState, event);
129 130 131
}


132 133 134 135 136 137 138 139
static int
qemuDomainObjInitJob(qemuDomainObjPrivatePtr priv)
{
    memset(&priv->job, 0, sizeof(priv->job));

    if (virCondInit(&priv->job.cond) < 0)
        return -1;

140
    if (virCondInit(&priv->job.asyncCond) < 0) {
141
        virCondDestroy(&priv->job.cond);
142 143 144
        return -1;
    }

145 146 147 148 149 150 151 152 153
    return 0;
}

static void
qemuDomainObjResetJob(qemuDomainObjPrivatePtr priv)
{
    struct qemuDomainJobObj *job = &priv->job;

    job->active = QEMU_JOB_NONE;
154
    job->owner = 0;
155 156 157 158 159 160 161 162
}

static void
qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
{
    struct qemuDomainJobObj *job = &priv->job;

    job->asyncJob = QEMU_ASYNC_JOB_NONE;
163
    job->asyncOwner = 0;
J
Jiri Denemark 已提交
164
    job->phase = 0;
165
    job->mask = QEMU_JOB_DEFAULT_MASK;
166
    job->dump_memory_only = false;
167
    job->asyncAbort = false;
J
Jiri Denemark 已提交
168
    VIR_FREE(job->current);
169 170
}

171 172 173 174 175 176 177 178
void
qemuDomainObjRestoreJob(virDomainObjPtr obj,
                        struct qemuDomainJobObj *job)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    memset(job, 0, sizeof(*job));
    job->active = priv->job.active;
179
    job->owner = priv->job.owner;
180
    job->asyncJob = priv->job.asyncJob;
181
    job->asyncOwner = priv->job.asyncOwner;
J
Jiri Denemark 已提交
182
    job->phase = priv->job.phase;
183 184 185 186 187

    qemuDomainObjResetJob(priv);
    qemuDomainObjResetAsyncJob(priv);
}

188 189 190 191 192
void
qemuDomainObjTransferJob(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

193
    VIR_DEBUG("Changing job owner from %llu to %llu",
194 195 196 197
              priv->job.owner, virThreadSelfID());
    priv->job.owner = virThreadSelfID();
}

198 199 200
static void
qemuDomainObjFreeJob(qemuDomainObjPrivatePtr priv)
{
J
Jiri Denemark 已提交
201
    VIR_FREE(priv->job.current);
202
    VIR_FREE(priv->job.completed);
203 204
    virCondDestroy(&priv->job.cond);
    virCondDestroy(&priv->job.asyncCond);
205 206
}

207
static bool
208
qemuDomainTrackJob(qemuDomainJob job)
209 210 211 212
{
    return (QEMU_DOMAIN_TRACK_JOBS & JOB_MASK(job)) != 0;
}

213

J
Jiri Denemark 已提交
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
int
qemuDomainJobInfoUpdateTime(qemuDomainJobInfoPtr jobInfo)
{
    unsigned long long now;

    if (!jobInfo->started)
        return 0;

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

    jobInfo->timeElapsed = now - jobInfo->started;
    return 0;
}

int
qemuDomainJobInfoToInfo(qemuDomainJobInfoPtr jobInfo,
                        virDomainJobInfoPtr info)
{
    info->timeElapsed = jobInfo->timeElapsed;
    info->timeRemaining = jobInfo->timeRemaining;

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

    info->fileTotal = jobInfo->status.disk_total;
    info->fileRemaining = jobInfo->status.disk_remaining;
    info->fileProcessed = jobInfo->status.disk_transferred;

    info->dataTotal = info->memTotal + info->fileTotal;
    info->dataRemaining = info->memRemaining + info->fileRemaining;
    info->dataProcessed = info->memProcessed + info->fileProcessed;

    return 0;
}

int
qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo,
                          int *type,
                          virTypedParameterPtr *params,
                          int *nparams)
{
    qemuMonitorMigrationStatus *status = &jobInfo->status;
    virTypedParameterPtr par = NULL;
    int maxpar = 0;
    int npar = 0;

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_TIME_ELAPSED,
                                jobInfo->timeElapsed) < 0)
        goto error;

    if (jobInfo->type == VIR_DOMAIN_JOB_BOUNDED &&
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_TIME_REMAINING,
                                jobInfo->timeRemaining) < 0)
        goto error;

    if (status->downtime_set &&
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DOWNTIME,
                                status->downtime) < 0)
        goto error;

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DATA_TOTAL,
                                status->ram_total +
                                status->disk_total) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DATA_PROCESSED,
                                status->ram_transferred +
                                status->disk_transferred) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DATA_REMAINING,
                                status->ram_remaining +
                                status->disk_remaining) < 0)
        goto error;

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_MEMORY_TOTAL,
                                status->ram_total) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_MEMORY_PROCESSED,
                                status->ram_transferred) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_MEMORY_REMAINING,
                                status->ram_remaining) < 0)
        goto error;

    if (status->ram_duplicate_set) {
        if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_MEMORY_CONSTANT,
                                    status->ram_duplicate) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_MEMORY_NORMAL,
                                    status->ram_normal) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES,
                                    status->ram_normal_bytes) < 0)
            goto error;
    }

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DISK_TOTAL,
                                status->disk_total) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DISK_PROCESSED,
                                status->disk_transferred) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DISK_REMAINING,
                                status->disk_remaining) < 0)
        goto error;

    if (status->xbzrle_set) {
        if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_CACHE,
                                    status->xbzrle_cache_size) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_BYTES,
                                    status->xbzrle_bytes) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_PAGES,
                                    status->xbzrle_pages) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES,
                                    status->xbzrle_cache_miss) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW,
                                    status->xbzrle_overflow) < 0)
            goto error;
    }

    *type = jobInfo->type;
    *params = par;
    *nparams = npar;
    return 0;

 error:
    virTypedParamsFree(par, npar);
    return -1;
}


358 359
static void *
qemuDomainObjPrivateAlloc(void)
360 361 362 363 364 365
{
    qemuDomainObjPrivatePtr priv;

    if (VIR_ALLOC(priv) < 0)
        return NULL;

366 367 368
    if (qemuDomainObjInitJob(priv) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to init qemu driver mutexes"));
369
        goto error;
370
    }
371

372 373 374
    if (virCondInit(&priv->unplugFinished) < 0)
        goto error;

375
    if (!(priv->devs = virChrdevAlloc()))
376 377
        goto error;

378
    priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
379

380
    return priv;
381

382
 error:
383 384
    VIR_FREE(priv);
    return NULL;
385 386
}

387 388
static void
qemuDomainObjPrivateFree(void *data)
389 390 391
{
    qemuDomainObjPrivatePtr priv = data;

392
    virObjectUnref(priv->qemuCaps);
393

394
    virCgroupFree(&priv->cgroup);
395
    virDomainPCIAddressSetFree(priv->pciaddrs);
J
Ján Tomko 已提交
396
    virDomainCCWAddressSetFree(priv->ccwaddrs);
397
    virDomainChrSourceDefFree(priv->monConfig);
398
    qemuDomainObjFreeJob(priv);
399
    VIR_FREE(priv->vcpupids);
400
    VIR_FREE(priv->lockState);
J
Jiri Denemark 已提交
401
    VIR_FREE(priv->origname);
402

403
    virCondDestroy(&priv->unplugFinished);
404
    virChrdevFree(priv->devs);
405

406 407
    /* This should never be non-NULL if we get here, but just in case... */
    if (priv->mon) {
408
        VIR_ERROR(_("Unexpected QEMU monitor still active during domain deletion"));
409 410
        qemuMonitorClose(priv->mon);
    }
D
Daniel P. Berrange 已提交
411 412 413 414
    if (priv->agent) {
        VIR_ERROR(_("Unexpected QEMU agent still active during domain deletion"));
        qemuAgentClose(priv->agent);
    }
415
    VIR_FREE(priv->cleanupCallbacks);
416 417 418 419
    VIR_FREE(priv);
}


420 421
static int
qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
422 423 424
{
    qemuDomainObjPrivatePtr priv = data;
    const char *monitorpath;
425
    qemuDomainJob job;
426 427 428

    /* priv->monitor_chr is set only for qemu */
    if (priv->monConfig) {
429
        switch (priv->monConfig->type) {
430
        case VIR_DOMAIN_CHR_TYPE_UNIX:
431
            monitorpath = priv->monConfig->data.nix.path;
432 433 434
            break;
        default:
        case VIR_DOMAIN_CHR_TYPE_PTY:
435
            monitorpath = priv->monConfig->data.file.path;
436 437 438
            break;
        }

439
        virBufferEscapeString(buf, "<monitor path='%s'", monitorpath);
440 441
        if (priv->monJSON)
            virBufferAddLit(buf, " json='1'");
442
        virBufferAsprintf(buf, " type='%s'/>\n",
443
                          virDomainChrTypeToString(priv->monConfig->type));
444 445 446 447
    }


    if (priv->nvcpupids) {
448
        size_t i;
449 450
        virBufferAddLit(buf, "<vcpus>\n");
        virBufferAdjustIndent(buf, 2);
451
        for (i = 0; i < priv->nvcpupids; i++) {
452
            virBufferAsprintf(buf, "<vcpu pid='%d'/>\n", priv->vcpupids[i]);
453
        }
454 455
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</vcpus>\n");
456 457
    }

458
    if (priv->qemuCaps) {
459
        size_t i;
460 461
        virBufferAddLit(buf, "<qemuCaps>\n");
        virBufferAdjustIndent(buf, 2);
462
        for (i = 0; i < QEMU_CAPS_LAST; i++) {
463
            if (virQEMUCapsGet(priv->qemuCaps, i)) {
464
                virBufferAsprintf(buf, "<flag name='%s'/>\n",
465
                                  virQEMUCapsTypeToString(i));
466 467
            }
        }
468 469
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</qemuCaps>\n");
470 471
    }

472
    if (priv->lockState)
473
        virBufferAsprintf(buf, "<lockstate>%s</lockstate>\n", priv->lockState);
474

475 476 477 478
    job = priv->job.active;
    if (!qemuDomainTrackJob(job))
        priv->job.active = QEMU_JOB_NONE;

479
    if (priv->job.active || priv->job.asyncJob) {
480
        virBufferAsprintf(buf, "<job type='%s' async='%s'",
481 482
                          qemuDomainJobTypeToString(priv->job.active),
                          qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
J
Jiri Denemark 已提交
483 484 485 486 487 488
        if (priv->job.phase) {
            virBufferAsprintf(buf, " phase='%s'",
                              qemuDomainAsyncJobPhaseToString(
                                    priv->job.asyncJob, priv->job.phase));
        }
        virBufferAddLit(buf, "/>\n");
489
    }
490
    priv->job.active = job;
491

492
    if (priv->fakeReboot)
493
        virBufferAddLit(buf, "<fakereboot/>\n");
494

495 496
    if (priv->qemuDevices && *priv->qemuDevices) {
        char **tmp = priv->qemuDevices;
497 498
        virBufferAddLit(buf, "<devices>\n");
        virBufferAdjustIndent(buf, 2);
499
        while (*tmp) {
500
            virBufferAsprintf(buf, "<device alias='%s'/>\n", *tmp);
501 502
            tmp++;
        }
503 504
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</devices>\n");
505 506
    }

507 508 509
    if (priv->quiesced)
        virBufferAddLit(buf, "<quiesced/>\n");

510 511 512
    return 0;
}

513 514
static int
qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
515 516 517 518
{
    qemuDomainObjPrivatePtr priv = data;
    char *monitorpath;
    char *tmp;
519 520
    int n;
    size_t i;
521
    xmlNodePtr *nodes = NULL;
522
    virQEMUCapsPtr qemuCaps = NULL;
523

524
    if (VIR_ALLOC(priv->monConfig) < 0)
525 526 527 528
        goto error;

    if (!(monitorpath =
          virXPathString("string(./monitor[1]/@path)", ctxt))) {
529 530
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no monitor path"));
531 532 533 534 535
        goto error;
    }

    tmp = virXPathString("string(./monitor[1]/@type)", ctxt);
    if (tmp)
536
        priv->monConfig->type = virDomainChrTypeFromString(tmp);
537
    else
538
        priv->monConfig->type = VIR_DOMAIN_CHR_TYPE_PTY;
539 540
    VIR_FREE(tmp);

E
Eric Blake 已提交
541 542
    priv->monJSON = virXPathBoolean("count(./monitor[@json = '1']) > 0",
                                    ctxt) > 0;
543

544
    switch (priv->monConfig->type) {
545
    case VIR_DOMAIN_CHR_TYPE_PTY:
546
        priv->monConfig->data.file.path = monitorpath;
547 548
        break;
    case VIR_DOMAIN_CHR_TYPE_UNIX:
549
        priv->monConfig->data.nix.path = monitorpath;
550 551 552
        break;
    default:
        VIR_FREE(monitorpath);
553 554 555
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported monitor type '%s'"),
                       virDomainChrTypeToString(priv->monConfig->type));
556 557 558 559 560 561 562 563
        goto error;
    }

    n = virXPathNodeSet("./vcpus/vcpu", ctxt, &nodes);
    if (n < 0)
        goto error;
    if (n) {
        priv->nvcpupids = n;
564
        if (VIR_REALLOC_N(priv->vcpupids, priv->nvcpupids) < 0)
565 566
            goto error;

567
        for (i = 0; i < n; i++) {
568 569 570 571 572 573 574 575 576 577 578 579 580
            char *pidstr = virXMLPropString(nodes[i], "pid");
            if (!pidstr)
                goto error;

            if (virStrToLong_i(pidstr, NULL, 10, &(priv->vcpupids[i])) < 0) {
                VIR_FREE(pidstr);
                goto error;
            }
            VIR_FREE(pidstr);
        }
        VIR_FREE(nodes);
    }

581
    if ((n = virXPathNodeSet("./qemuCaps/flag", ctxt, &nodes)) < 0) {
582 583
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("failed to parse qemu capabilities flags"));
584 585 586
        goto error;
    }
    if (n > 0) {
587
        if (!(qemuCaps = virQEMUCapsNew()))
588 589
            goto error;

590
        for (i = 0; i < n; i++) {
591 592
            char *str = virXMLPropString(nodes[i], "name");
            if (str) {
593
                int flag = virQEMUCapsTypeFromString(str);
594
                if (flag < 0) {
595 596
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Unknown qemu capabilities flag %s"), str);
597
                    VIR_FREE(str);
598 599
                    goto error;
                }
600
                VIR_FREE(str);
601
                virQEMUCapsSet(qemuCaps, flag);
602 603 604
            }
        }

605
        priv->qemuCaps = qemuCaps;
606 607 608
    }
    VIR_FREE(nodes);

609
    priv->lockState = virXPathString("string(./lockstate)", ctxt);
610

611 612 613 614
    if ((tmp = virXPathString("string(./job[1]/@type)", ctxt))) {
        int type;

        if ((type = qemuDomainJobTypeFromString(tmp)) < 0) {
615 616
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unknown job type %s"), tmp);
617 618 619 620 621 622 623 624 625 626 627
            VIR_FREE(tmp);
            goto error;
        }
        VIR_FREE(tmp);
        priv->job.active = type;
    }

    if ((tmp = virXPathString("string(./job[1]/@async)", ctxt))) {
        int async;

        if ((async = qemuDomainAsyncJobTypeFromString(tmp)) < 0) {
628 629
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unknown async job type %s"), tmp);
630 631 632 633 634
            VIR_FREE(tmp);
            goto error;
        }
        VIR_FREE(tmp);
        priv->job.asyncJob = async;
J
Jiri Denemark 已提交
635 636 637 638

        if ((tmp = virXPathString("string(./job[1]/@phase)", ctxt))) {
            priv->job.phase = qemuDomainAsyncJobPhaseFromString(async, tmp);
            if (priv->job.phase < 0) {
639 640
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Unknown job phase %s"), tmp);
J
Jiri Denemark 已提交
641 642 643 644 645
                VIR_FREE(tmp);
                goto error;
            }
            VIR_FREE(tmp);
        }
646 647
    }

648 649
    priv->fakeReboot = virXPathBoolean("boolean(./fakereboot)", ctxt) == 1;

650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
    if ((n = virXPathNodeSet("./devices/device", ctxt, &nodes)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to parse qemu device list"));
        goto error;
    }
    if (n > 0) {
        /* NULL-terminated list */
        if (VIR_ALLOC_N(priv->qemuDevices, n + 1) < 0)
            goto error;

        for (i = 0; i < n; i++) {
            priv->qemuDevices[i] = virXMLPropString(nodes[i], "alias");
            if (!priv->qemuDevices[i]) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to parse qemu device list"));
                goto error;
            }
        }
    }
    VIR_FREE(nodes);

671 672
    priv->quiesced = virXPathBoolean("boolean(./quiesced)", ctxt) == 1;

673 674
    return 0;

675
 error:
676
    virDomainChrSourceDefFree(priv->monConfig);
677 678
    priv->monConfig = NULL;
    VIR_FREE(nodes);
679 680
    virStringFreeList(priv->qemuDevices);
    priv->qemuDevices = NULL;
681
    virObjectUnref(qemuCaps);
682 683 684 685
    return -1;
}


686 687 688 689 690 691 692 693
virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = {
    .alloc = qemuDomainObjPrivateAlloc,
    .free = qemuDomainObjPrivateFree,
    .parse = qemuDomainObjPrivateXMLParse,
    .format = qemuDomainObjPrivateXMLFormat,
};


694 695 696 697 698
static void
qemuDomainDefNamespaceFree(void *nsdata)
{
    qemuDomainCmdlineDefPtr cmd = nsdata;

699
    qemuDomainCmdlineDefFree(cmd);
700 701 702
}

static int
P
Philipp Hahn 已提交
703 704
qemuDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
                            xmlNodePtr root ATTRIBUTE_UNUSED,
705 706 707 708
                            xmlXPathContextPtr ctxt,
                            void **data)
{
    qemuDomainCmdlineDefPtr cmd = NULL;
P
Philipp Hahn 已提交
709
    bool uses_qemu_ns = false;
710
    xmlNodePtr *nodes = NULL;
711 712
    int n;
    size_t i;
713

P
Philipp Hahn 已提交
714
    if (xmlXPathRegisterNs(ctxt, BAD_CAST "qemu", BAD_CAST QEMU_NAMESPACE_HREF) < 0) {
715 716 717
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to register xml namespace '%s'"),
                       QEMU_NAMESPACE_HREF);
718 719 720
        return -1;
    }

721
    if (VIR_ALLOC(cmd) < 0)
722 723 724 725 726 727
        return -1;

    /* first handle the extra command-line arguments */
    n = virXPathNodeSet("./qemu:commandline/qemu:arg", ctxt, &nodes);
    if (n < 0)
        goto error;
P
Philipp Hahn 已提交
728
    uses_qemu_ns |= n > 0;
729 730

    if (n && VIR_ALLOC_N(cmd->args, n) < 0)
731
        goto error;
732 733 734 735

    for (i = 0; i < n; i++) {
        cmd->args[cmd->num_args] = virXMLPropString(nodes[i], "value");
        if (cmd->args[cmd->num_args] == NULL) {
736 737
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("No qemu command-line argument specified"));
738 739 740 741 742 743 744 745 746 747 748
            goto error;
        }
        cmd->num_args++;
    }

    VIR_FREE(nodes);

    /* now handle the extra environment variables */
    n = virXPathNodeSet("./qemu:commandline/qemu:env", ctxt, &nodes);
    if (n < 0)
        goto error;
P
Philipp Hahn 已提交
749
    uses_qemu_ns |= n > 0;
750 751

    if (n && VIR_ALLOC_N(cmd->env_name, n) < 0)
752
        goto error;
753 754

    if (n && VIR_ALLOC_N(cmd->env_value, n) < 0)
755
        goto error;
756 757 758 759 760 761

    for (i = 0; i < n; i++) {
        char *tmp;

        tmp = virXMLPropString(nodes[i], "name");
        if (tmp == NULL) {
762 763
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("No qemu environment name specified"));
764 765 766
            goto error;
        }
        if (tmp[0] == '\0') {
767 768
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Empty qemu environment name specified"));
769 770 771
            goto error;
        }
        if (!c_isalpha(tmp[0]) && tmp[0] != '_') {
772 773
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Invalid environment name, it must begin with a letter or underscore"));
774 775 776
            goto error;
        }
        if (strspn(tmp, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_") != strlen(tmp)) {
777 778
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Invalid environment name, it must contain only alphanumerics and underscore"));
779 780 781 782 783 784 785 786 787 788 789 790
            goto error;
        }

        cmd->env_name[cmd->num_env] = tmp;

        cmd->env_value[cmd->num_env] = virXMLPropString(nodes[i], "value");
        /* a NULL value for command is allowed, since it might be empty */
        cmd->num_env++;
    }

    VIR_FREE(nodes);

P
Philipp Hahn 已提交
791 792 793 794
    if (uses_qemu_ns)
        *data = cmd;
    else
        VIR_FREE(cmd);
795 796 797

    return 0;

798
 error:
799 800 801 802 803 804 805 806 807 808
    VIR_FREE(nodes);
    qemuDomainDefNamespaceFree(cmd);
    return -1;
}

static int
qemuDomainDefNamespaceFormatXML(virBufferPtr buf,
                                void *nsdata)
{
    qemuDomainCmdlineDefPtr cmd = nsdata;
809
    size_t i;
810 811 812 813

    if (!cmd->num_args && !cmd->num_env)
        return 0;

814 815 816
    virBufferAddLit(buf, "<qemu:commandline>\n");
    virBufferAdjustIndent(buf, 2);

817
    for (i = 0; i < cmd->num_args; i++)
818
        virBufferEscapeString(buf, "<qemu:arg value='%s'/>\n",
819 820
                              cmd->args[i]);
    for (i = 0; i < cmd->num_env; i++) {
821
        virBufferAsprintf(buf, "<qemu:env name='%s'", cmd->env_name[i]);
822 823 824 825 826
        if (cmd->env_value[i])
            virBufferEscapeString(buf, " value='%s'", cmd->env_value[i]);
        virBufferAddLit(buf, "/>\n");
    }

827 828
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</qemu:commandline>\n");
829 830 831 832 833 834 835 836 837 838
    return 0;
}

static const char *
qemuDomainDefNamespaceHref(void)
{
    return "xmlns:qemu='" QEMU_NAMESPACE_HREF "'";
}


839 840 841 842 843 844
virDomainXMLNamespace virQEMUDriverDomainXMLNamespace = {
    .parse = qemuDomainDefNamespaceParse,
    .free = qemuDomainDefNamespaceFree,
    .format = qemuDomainDefNamespaceFormatXML,
    .href = qemuDomainDefNamespaceHref,
};
845

846

847 848 849 850 851
static int
qemuDomainDefPostParse(virDomainDefPtr def,
                       virCapsPtr caps,
                       void *opaque ATTRIBUTE_UNUSED)
{
852
    bool addDefaultUSB = true;
853
    bool addImplicitSATA = false;
854
    bool addPCIRoot = false;
L
Laine Stump 已提交
855
    bool addPCIeRoot = false;
856
    bool addDefaultMemballoon = true;
857 858
    bool addDefaultUSBKBD = false;
    bool addDefaultUSBMouse = false;
859

860 861 862 863 864
    /* check for emulator and create a default one if needed */
    if (!def->emulator &&
        !(def->emulator = virDomainDefGetDefaultEmulator(def, caps)))
        return -1;

865 866 867 868 869 870
    /* Add implicit PCI root controller if the machine has one */
    switch (def->os.arch) {
    case VIR_ARCH_I686:
    case VIR_ARCH_X86_64:
        if (!def->os.machine)
            break;
L
Laine Stump 已提交
871
        if (STREQ(def->os.machine, "isapc")) {
872
            addDefaultUSB = false;
873
            break;
874
        }
L
Laine Stump 已提交
875 876 877 878
        if (STRPREFIX(def->os.machine, "pc-q35") ||
            STREQ(def->os.machine, "q35")) {
           addPCIeRoot = true;
           addDefaultUSB = false;
879
           addImplicitSATA = true;
L
Laine Stump 已提交
880 881
           break;
        }
882 883
        if (!STRPREFIX(def->os.machine, "pc-0.") &&
            !STRPREFIX(def->os.machine, "pc-1.") &&
884
            !STRPREFIX(def->os.machine, "pc-i440") &&
885 886 887 888 889 890
            !STREQ(def->os.machine, "pc") &&
            !STRPREFIX(def->os.machine, "rhel"))
            break;
        addPCIRoot = true;
        break;

891 892
    case VIR_ARCH_ARMV7L:
       addDefaultUSB = false;
893
       addDefaultMemballoon = false;
894
       break;
895 896 897 898
    case VIR_ARCH_AARCH64:
       addDefaultUSB = false;
       addDefaultMemballoon = false;
       break;
899

900 901 902 903 904 905
    case VIR_ARCH_PPC64:
        addPCIRoot = true;
        addDefaultUSBKBD = true;
        addDefaultUSBMouse = true;
        break;

906 907 908 909 910 911 912 913 914 915 916
    case VIR_ARCH_ALPHA:
    case VIR_ARCH_PPC:
    case VIR_ARCH_PPCEMB:
    case VIR_ARCH_SH4:
    case VIR_ARCH_SH4EB:
        addPCIRoot = true;
        break;
    default:
        break;
    }

917 918 919 920 921
    if (addDefaultUSB &&
        virDomainDefMaybeAddController(
            def, VIR_DOMAIN_CONTROLLER_TYPE_USB, 0, -1) < 0)
        return -1;

922 923 924 925 926
    if (addImplicitSATA &&
        virDomainDefMaybeAddController(
            def, VIR_DOMAIN_CONTROLLER_TYPE_SATA, 0, -1) < 0)
        return -1;

927 928 929 930 931 932
    if (addPCIRoot &&
        virDomainDefMaybeAddController(
            def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
            VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
        return -1;

933 934 935 936 937 938 939 940 941 942 943 944 945 946
    /* When a machine has a pcie-root, make sure that there is always
     * a dmi-to-pci-bridge controller added as bus 1, and a pci-bridge
     * as bus 2, so that standard PCI devices can be connected
     */
    if (addPCIeRoot) {
        if (virDomainDefMaybeAddController(
                def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
                VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0 ||
            virDomainDefMaybeAddController(
                def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1,
                VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE) < 0 ||
            virDomainDefMaybeAddController(
                def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 2,
                VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE) < 0) {
L
Laine Stump 已提交
947
        return -1;
948 949
        }
    }
950

951
    if (addDefaultMemballoon && !def->memballoon) {
952 953 954 955 956 957 958 959
        virDomainMemballoonDefPtr memballoon;
        if (VIR_ALLOC(memballoon) < 0)
            return -1;

        memballoon->model = VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO;
        def->memballoon = memballoon;
    }

960 961 962 963 964 965 966 967 968 969 970 971 972 973
    if (addDefaultUSBKBD &&
        def->ngraphics > 0 &&
        virDomainDefMaybeAddInput(def,
                                  VIR_DOMAIN_INPUT_TYPE_KBD,
                                  VIR_DOMAIN_INPUT_BUS_USB) < 0)
        return -1;

    if (addDefaultUSBMouse &&
        def->ngraphics > 0 &&
        virDomainDefMaybeAddInput(def,
                                  VIR_DOMAIN_INPUT_TYPE_MOUSE,
                                  VIR_DOMAIN_INPUT_BUS_USB) < 0)
        return -1;

974 975 976
    return 0;
}

977
static const char *
978 979
qemuDomainDefaultNetModel(const virDomainDef *def)
{
980 981 982 983
    if (def->os.arch == VIR_ARCH_S390 ||
        def->os.arch == VIR_ARCH_S390X)
        return "virtio";

984 985
    if (def->os.arch == VIR_ARCH_ARMV7L ||
        def->os.arch == VIR_ARCH_AARCH64) {
986 987 988
        if (STREQ(def->os.machine, "versatilepb"))
            return "smc91c111";

989 990 991
        if (STREQ(def->os.machine, "virt"))
            return "virtio";

992 993 994 995 996 997 998
        /* Incomplete. vexpress (and a few others) use this, but not all
         * arm boards */
        return "lan9118";
    }

    return "rtl8139";
}
999

1000 1001
static int
qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
1002
                             const virDomainDef *def,
1003
                             virCapsPtr caps ATTRIBUTE_UNUSED,
1004
                             void *opaque)
1005
{
1006 1007 1008 1009
    int ret = -1;
    virQEMUDriverPtr driver = opaque;
    virQEMUDriverConfigPtr cfg = NULL;

1010
    if (dev->type == VIR_DOMAIN_DEVICE_NET &&
1011 1012
        dev->data.net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
        !dev->data.net->model) {
1013
        if (VIR_STRDUP(dev->data.net->model,
1014
                       qemuDomainDefaultNetModel(def)) < 0)
1015
            goto cleanup;
1016
    }
1017

1018 1019 1020 1021 1022 1023 1024 1025 1026
    /* set default disk types and drivers */
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        virDomainDiskDefPtr disk = dev->data.disk;

        /* both of these require data from the driver config */
        if (driver && (cfg = virQEMUDriverGetConfig(driver))) {
            /* assign default storage format and driver according to config */
            if (cfg->allowDiskFormatProbing) {
                /* default disk format for drives */
1027
                if (virDomainDiskGetFormat(disk) == VIR_STORAGE_FILE_NONE &&
E
Eric Blake 已提交
1028 1029
                    (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_FILE ||
                     virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_BLOCK))
1030
                    virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_AUTO);
1031 1032 1033

                 /* default disk format for mirrored drive */
                if (disk->mirror &&
1034 1035
                    disk->mirror->format == VIR_STORAGE_FILE_NONE)
                    disk->mirror->format = VIR_STORAGE_FILE_AUTO;
1036 1037
            } else {
                /* default driver if probing is forbidden */
1038 1039
                if (!virDomainDiskGetDriver(disk) &&
                    virDomainDiskSetDriver(disk, "qemu") < 0)
1040
                        goto cleanup;
1041 1042

                /* default disk format for drives */
1043
                if (virDomainDiskGetFormat(disk) == VIR_STORAGE_FILE_NONE &&
E
Eric Blake 已提交
1044 1045
                    (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_FILE ||
                     virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_BLOCK))
1046
                    virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
1047 1048 1049

                 /* default disk format for mirrored drive */
                if (disk->mirror &&
1050 1051
                    disk->mirror->format == VIR_STORAGE_FILE_NONE)
                    disk->mirror->format = VIR_STORAGE_FILE_RAW;
1052
            }
1053 1054 1055
        }
    }

1056 1057 1058 1059 1060 1061 1062
    /* set the default console type for S390 arches */
    if (dev->type == VIR_DOMAIN_DEVICE_CHR &&
        dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
        dev->data.chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE &&
        (def->os.arch == VIR_ARCH_S390 || def->os.arch == VIR_ARCH_S390X))
        dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO;

1063 1064 1065 1066 1067 1068 1069 1070
    /* set the default USB model to none for s390 unless an address is found */
    if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER &&
        dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
        dev->data.controller->model == -1 &&
        dev->data.controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
        (def->os.arch == VIR_ARCH_S390 || def->os.arch == VIR_ARCH_S390X))
        dev->data.controller->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE;

1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
    /* auto generate unix socket path */
    if (dev->type == VIR_DOMAIN_DEVICE_CHR &&
        dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
        dev->data.chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
        dev->data.chr->source.type == VIR_DOMAIN_CHR_TYPE_UNIX &&
        !dev->data.chr->source.data.nix.path &&
        (driver && (cfg = virQEMUDriverGetConfig(driver)))) {

        if (virAsprintf(&dev->data.chr->source.data.nix.path,
                        "%s/channel/target/%s.%s",
                        cfg->libDir, def->name,
1082
                        dev->data.chr->target.name) < 0)
1083
            goto cleanup;
1084 1085 1086
        dev->data.chr->source.data.nix.listen = true;
    }

1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
    /* forbid capabilities mode hostdev in this kind of hypervisor */
    if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
        dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev mode 'capabilities' is not "
                         "supported in %s"),
                       virDomainVirtTypeToString(def->virtType));
        goto cleanup;
    }

1097 1098
    ret = 0;

1099
 cleanup:
1100 1101
    virObjectUnref(cfg);
    return ret;
1102 1103 1104 1105 1106
}


virDomainDefParserConfig virQEMUDriverDomainDefParserConfig = {
    .devicesPostParseCallback = qemuDomainDeviceDefPostParse,
1107
    .domainPostParseCallback = qemuDomainDefPostParse,
1108 1109 1110
};


1111
static void
1112
qemuDomainObjSaveJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
1113
{
1114 1115 1116
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);

    if (virDomainObjIsActive(obj)) {
1117
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, obj) < 0)
1118
            VIR_WARN("Failed to save status on vm %s", obj->def->name);
1119
    }
1120

1121
    virObjectUnref(cfg);
1122 1123
}

J
Jiri Denemark 已提交
1124
void
1125
qemuDomainObjSetJobPhase(virQEMUDriverPtr driver,
J
Jiri Denemark 已提交
1126 1127 1128 1129
                         virDomainObjPtr obj,
                         int phase)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
1130
    unsigned long long me = virThreadSelfID();
J
Jiri Denemark 已提交
1131 1132 1133 1134

    if (!priv->job.asyncJob)
        return;

1135 1136 1137 1138 1139
    VIR_DEBUG("Setting '%s' phase to '%s'",
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
              qemuDomainAsyncJobPhaseToString(priv->job.asyncJob, phase));

    if (priv->job.asyncOwner && me != priv->job.asyncOwner) {
1140
        VIR_WARN("'%s' async job is owned by thread %llu",
1141 1142 1143 1144
                 qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
                 priv->job.asyncOwner);
    }

J
Jiri Denemark 已提交
1145
    priv->job.phase = phase;
1146
    priv->job.asyncOwner = me;
J
Jiri Denemark 已提交
1147 1148 1149
    qemuDomainObjSaveJob(driver, obj);
}

1150
void
1151 1152
qemuDomainObjSetAsyncJobMask(virDomainObjPtr obj,
                             unsigned long long allowedJobs)
1153 1154 1155
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

1156 1157 1158 1159 1160 1161 1162
    if (!priv->job.asyncJob)
        return;

    priv->job.mask = allowedJobs | JOB_MASK(QEMU_JOB_DESTROY);
}

void
1163
qemuDomainObjDiscardAsyncJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
1164 1165 1166 1167 1168 1169
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    if (priv->job.active == QEMU_JOB_ASYNC_NESTED)
        qemuDomainObjResetJob(priv);
    qemuDomainObjResetAsyncJob(priv);
1170
    qemuDomainObjSaveJob(driver, obj);
1171 1172
}

1173 1174 1175 1176 1177 1178 1179 1180 1181
void
qemuDomainObjReleaseAsyncJob(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    VIR_DEBUG("Releasing ownership of '%s' async job",
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob));

    if (priv->job.asyncOwner != virThreadSelfID()) {
1182
        VIR_WARN("'%s' async job is owned by thread %llu",
1183 1184 1185 1186 1187 1188
                 qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
                 priv->job.asyncOwner);
    }
    priv->job.asyncOwner = 0;
}

1189
static bool
1190
qemuDomainNestedJobAllowed(qemuDomainObjPrivatePtr priv, qemuDomainJob job)
1191 1192
{
    return !priv->job.asyncJob || (priv->job.mask & JOB_MASK(job)) != 0;
1193 1194
}

1195
bool
1196
qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv, qemuDomainJob job)
1197 1198 1199 1200
{
    return !priv->job.active && qemuDomainNestedJobAllowed(priv, job);
}

1201 1202 1203
/* Give up waiting for mutex after 30 seconds */
#define QEMU_JOB_WAIT_TIME (1000ull * 30)

1204
/*
1205
 * obj must be locked before calling
1206
 */
1207
static int ATTRIBUTE_NONNULL(1)
1208
qemuDomainObjBeginJobInternal(virQEMUDriverPtr driver,
1209
                              virDomainObjPtr obj,
1210 1211
                              qemuDomainJob job,
                              qemuDomainAsyncJob asyncJob)
1212 1213
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
J
Jiri Denemark 已提交
1214
    unsigned long long now;
1215
    unsigned long long then;
1216
    bool nested = job == QEMU_JOB_ASYNC_NESTED;
1217
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
J
Jiri Denemark 已提交
1218
    int ret = -1;
1219

1220 1221 1222 1223 1224 1225
    VIR_DEBUG("Starting %s: %s (async=%s vm=%p name=%s)",
              job == QEMU_JOB_ASYNC ? "async job" : "job",
              qemuDomainJobTypeToString(job),
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
              obj, obj->def->name);

1226 1227
    if (virTimeMillisNow(&now) < 0) {
        virObjectUnref(cfg);
1228
        return -1;
1229 1230
    }

1231
    priv->jobs_queued++;
J
Jiri Denemark 已提交
1232
    then = now + QEMU_JOB_WAIT_TIME;
1233

1234
    virObjectRef(obj);
1235

1236
 retry:
1237 1238
    if (cfg->maxQueuedJobs &&
        priv->jobs_queued > cfg->maxQueuedJobs) {
1239 1240 1241
        goto error;
    }

1242
    while (!nested && !qemuDomainNestedJobAllowed(priv, job)) {
1243
        VIR_DEBUG("Waiting for async job (vm=%p name=%s)", obj, obj->def->name);
1244
        if (virCondWaitUntil(&priv->job.asyncCond, &obj->parent.lock, then) < 0)
1245 1246 1247
            goto error;
    }

1248
    while (priv->job.active) {
1249
        VIR_DEBUG("Waiting for job (vm=%p name=%s)", obj, obj->def->name);
1250
        if (virCondWaitUntil(&priv->job.cond, &obj->parent.lock, then) < 0)
1251
            goto error;
1252
    }
1253 1254 1255

    /* No job is active but a new async job could have been started while obj
     * was unlocked, so we need to recheck it. */
1256
    if (!nested && !qemuDomainNestedJobAllowed(priv, job))
1257 1258
        goto retry;

1259
    qemuDomainObjResetJob(priv);
1260 1261

    if (job != QEMU_JOB_ASYNC) {
1262
        VIR_DEBUG("Started job: %s (async=%s vm=%p name=%s)",
1263
                   qemuDomainJobTypeToString(job),
1264 1265
                  qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
                  obj, obj->def->name);
1266
        priv->job.active = job;
1267
        priv->job.owner = virThreadSelfID();
1268
    } else {
1269 1270 1271
        VIR_DEBUG("Started async job: %s (vm=%p name=%s)",
                  qemuDomainAsyncJobTypeToString(asyncJob),
                  obj, obj->def->name);
1272
        qemuDomainObjResetAsyncJob(priv);
J
Jiri Denemark 已提交
1273 1274
        if (VIR_ALLOC(priv->job.current) < 0)
            goto cleanup;
1275
        priv->job.asyncJob = asyncJob;
1276
        priv->job.asyncOwner = virThreadSelfID();
J
Jiri Denemark 已提交
1277
        priv->job.current->started = now;
1278
    }
1279

1280 1281
    if (qemuDomainTrackJob(job))
        qemuDomainObjSaveJob(driver, obj);
1282

1283
    virObjectUnref(cfg);
1284
    return 0;
1285

1286
 error:
1287
    VIR_WARN("Cannot start job (%s, %s) for domain %s;"
1288
             " current job is (%s, %s) owned by (%llu, %llu)",
1289 1290 1291 1292 1293 1294 1295
             qemuDomainJobTypeToString(job),
             qemuDomainAsyncJobTypeToString(asyncJob),
             obj->def->name,
             qemuDomainJobTypeToString(priv->job.active),
             qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
             priv->job.owner, priv->job.asyncOwner);

1296 1297
    ret = -1;
    if (errno == ETIMEDOUT) {
1298 1299
        virReportError(VIR_ERR_OPERATION_TIMEOUT,
                       "%s", _("cannot acquire state change lock"));
1300 1301 1302
        ret = -2;
    } else if (cfg->maxQueuedJobs &&
               priv->jobs_queued > cfg->maxQueuedJobs) {
1303 1304 1305
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("cannot acquire state change lock "
                               "due to max_queued limit"));
1306 1307
        ret = -2;
    } else {
1308 1309
        virReportSystemError(errno,
                             "%s", _("cannot acquire job mutex"));
1310
    }
J
Jiri Denemark 已提交
1311 1312

 cleanup:
1313
    priv->jobs_queued--;
1314
    virObjectUnref(obj);
1315
    virObjectUnref(cfg);
1316
    return ret;
1317 1318 1319
}

/*
1320
 * obj must be locked before calling
1321 1322 1323 1324 1325 1326 1327
 *
 * This must be called by anything that will change the VM state
 * in any way, or anything that will use the QEMU monitor.
 *
 * Upon successful return, the object will have its ref count increased,
 * successful calls must be followed by EndJob eventually
 */
1328
int qemuDomainObjBeginJob(virQEMUDriverPtr driver,
1329
                          virDomainObjPtr obj,
1330
                          qemuDomainJob job)
1331
{
1332 1333 1334 1335 1336
    if (qemuDomainObjBeginJobInternal(driver, obj, job,
                                      QEMU_ASYNC_JOB_NONE) < 0)
        return -1;
    else
        return 0;
1337 1338
}

1339
int qemuDomainObjBeginAsyncJob(virQEMUDriverPtr driver,
1340
                               virDomainObjPtr obj,
1341
                               qemuDomainAsyncJob asyncJob)
1342
{
1343 1344 1345 1346 1347
    if (qemuDomainObjBeginJobInternal(driver, obj, QEMU_JOB_ASYNC,
                                      asyncJob) < 0)
        return -1;
    else
        return 0;
1348 1349
}

1350
static int ATTRIBUTE_RETURN_CHECK
1351 1352
qemuDomainObjBeginNestedJob(virQEMUDriverPtr driver,
                            virDomainObjPtr obj,
1353
                            qemuDomainAsyncJob asyncJob)
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    if (asyncJob != priv->job.asyncJob) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected async job %d"), asyncJob);
        return -1;
    }

    if (priv->job.asyncOwner != virThreadSelfID()) {
1364
        VIR_WARN("This thread doesn't seem to be the async job owner: %llu",
1365 1366 1367 1368 1369 1370 1371 1372
                 priv->job.asyncOwner);
    }

    return qemuDomainObjBeginJobInternal(driver, obj,
                                         QEMU_JOB_ASYNC_NESTED,
                                         QEMU_ASYNC_JOB_NONE);
}

1373

1374
/*
1375
 * obj must be locked before calling
1376 1377 1378 1379
 *
 * To be called after completing the work associated with the
 * earlier qemuDomainBeginJob() call
 *
1380 1381
 * Returns true if @obj was still referenced, false if it was
 * disposed of.
1382
 */
1383
bool qemuDomainObjEndJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
1384 1385
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
1386
    qemuDomainJob job = priv->job.active;
1387

1388 1389
    priv->jobs_queued--;

1390
    VIR_DEBUG("Stopping job: %s (async=%s vm=%p name=%s)",
1391
              qemuDomainJobTypeToString(job),
1392 1393
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
              obj, obj->def->name);
1394

1395
    qemuDomainObjResetJob(priv);
1396 1397
    if (qemuDomainTrackJob(job))
        qemuDomainObjSaveJob(driver, obj);
1398
    virCondSignal(&priv->job.cond);
1399

1400
    return virObjectUnref(obj);
1401 1402
}

1403
bool
1404
qemuDomainObjEndAsyncJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
1405 1406
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
1407

1408 1409
    priv->jobs_queued--;

1410 1411 1412
    VIR_DEBUG("Stopping async job: %s (vm=%p name=%s)",
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
              obj, obj->def->name);
1413

1414
    qemuDomainObjResetAsyncJob(priv);
1415
    qemuDomainObjSaveJob(driver, obj);
1416 1417
    virCondBroadcast(&priv->job.asyncCond);

1418
    return virObjectUnref(obj);
1419 1420
}

1421 1422 1423 1424 1425
void
qemuDomainObjAbortAsyncJob(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

1426 1427 1428
    VIR_DEBUG("Requesting abort of async job: %s (vm=%p name=%s)",
              qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
              obj, obj->def->name);
1429 1430 1431 1432

    priv->job.asyncAbort = true;
}

1433 1434 1435 1436 1437 1438 1439 1440 1441
/*
 * obj must be locked before calling
 *
 * To be called immediately before any QEMU monitor API call
 * Must have already either called qemuDomainObjBeginJob() and checked
 * that the VM is still active; may not be used for nested async jobs.
 *
 * To be followed with qemuDomainObjExitMonitor() once complete
 */
1442
static int
1443
qemuDomainObjEnterMonitorInternal(virQEMUDriverPtr driver,
1444
                                  virDomainObjPtr obj,
1445
                                  qemuDomainAsyncJob asyncJob)
1446 1447 1448
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

1449
    if (asyncJob != QEMU_ASYNC_JOB_NONE) {
1450 1451 1452
        int ret;
        if ((ret = qemuDomainObjBeginNestedJob(driver, obj, asyncJob)) < 0)
            return ret;
1453
        if (!virDomainObjIsActive(obj)) {
1454 1455
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("domain is no longer running"));
1456 1457
            /* Still referenced by the containing async job.  */
            ignore_value(qemuDomainObjEndJob(driver, obj));
1458 1459
            return -1;
        }
1460 1461 1462
    } else if (priv->job.asyncOwner == virThreadSelfID()) {
        VIR_WARN("This thread seems to be the async job owner; entering"
                 " monitor without asking for a nested job is dangerous");
1463 1464
    }

1465 1466
    VIR_DEBUG("Entering monitor (mon=%p vm=%p name=%s)",
              priv->mon, obj, obj->def->name);
1467
    virObjectLock(priv->mon);
1468
    virObjectRef(priv->mon);
1469
    ignore_value(virTimeMillisNow(&priv->monStart));
1470
    virObjectUnlock(obj);
1471 1472

    return 0;
1473 1474
}

1475
static void ATTRIBUTE_NONNULL(1)
1476
qemuDomainObjExitMonitorInternal(virQEMUDriverPtr driver,
1477
                                 virDomainObjPtr obj)
1478 1479
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
1480
    bool hasRefs;
1481

1482
    hasRefs = virObjectUnref(priv->mon);
1483

1484
    if (hasRefs)
1485
        virObjectUnlock(priv->mon);
1486

1487
    virObjectLock(obj);
1488 1489
    VIR_DEBUG("Exited monitor (mon=%p vm=%p name=%s)",
              priv->mon, obj, obj->def->name);
1490

1491
    priv->monStart = 0;
1492
    if (!hasRefs)
1493
        priv->mon = NULL;
1494

1495 1496 1497 1498 1499
    if (priv->job.active == QEMU_JOB_ASYNC_NESTED) {
        qemuDomainObjResetJob(priv);
        qemuDomainObjSaveJob(driver, obj);
        virCondSignal(&priv->job.cond);

1500
        virObjectUnref(obj);
1501
    }
1502 1503
}

1504
void qemuDomainObjEnterMonitor(virQEMUDriverPtr driver,
1505
                               virDomainObjPtr obj)
1506
{
1507
    ignore_value(qemuDomainObjEnterMonitorInternal(driver, obj,
1508
                                                   QEMU_ASYNC_JOB_NONE));
1509 1510
}

1511
/* obj must NOT be locked before calling
1512 1513 1514
 *
 * Should be paired with an earlier qemuDomainObjEnterMonitor() call
 */
1515
void qemuDomainObjExitMonitor(virQEMUDriverPtr driver,
1516
                              virDomainObjPtr obj)
1517
{
1518
    qemuDomainObjExitMonitorInternal(driver, obj);
1519
}
1520 1521

/*
1522
 * obj must be locked before calling
1523 1524
 *
 * To be called immediately before any QEMU monitor API call.
1525
 * Must have already either called qemuDomainObjBeginJob()
1526 1527 1528 1529 1530
 * and checked that the VM is still active, with asyncJob of
 * QEMU_ASYNC_JOB_NONE; or already called qemuDomainObjBeginAsyncJob,
 * with the same asyncJob.
 *
 * Returns 0 if job was started, in which case this must be followed with
1531 1532 1533
 * qemuDomainObjExitMonitor(); -2 if waiting for the nested job times out;
 * or -1 if the job could not be started (probably because the vm exited
 * in the meantime).
1534 1535
 */
int
1536
qemuDomainObjEnterMonitorAsync(virQEMUDriverPtr driver,
1537
                               virDomainObjPtr obj,
1538
                               qemuDomainAsyncJob asyncJob)
1539
{
1540
    return qemuDomainObjEnterMonitorInternal(driver, obj, asyncJob);
1541 1542
}

D
Daniel P. Berrange 已提交
1543 1544


1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555
/*
 * obj must be locked before calling
 *
 * To be called immediately before any QEMU agent API call.
 * Must have already called qemuDomainObjBeginJob() and checked
 * that the VM is still active.
 *
 * To be followed with qemuDomainObjExitAgent() once complete
 */
void
qemuDomainObjEnterAgent(virDomainObjPtr obj)
D
Daniel P. Berrange 已提交
1556 1557 1558
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

1559 1560
    VIR_DEBUG("Entering agent (agent=%p vm=%p name=%s)",
              priv->agent, obj, obj->def->name);
1561
    virObjectLock(priv->agent);
1562
    virObjectRef(priv->agent);
D
Daniel P. Berrange 已提交
1563
    ignore_value(virTimeMillisNow(&priv->agentStart));
1564
    virObjectUnlock(obj);
D
Daniel P. Berrange 已提交
1565 1566
}

1567 1568 1569 1570 1571 1572 1573

/* obj must NOT be locked before calling
 *
 * Should be paired with an earlier qemuDomainObjEnterAgent() call
 */
void
qemuDomainObjExitAgent(virDomainObjPtr obj)
D
Daniel P. Berrange 已提交
1574 1575
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
1576
    bool hasRefs;
D
Daniel P. Berrange 已提交
1577

1578
    hasRefs = virObjectUnref(priv->agent);
D
Daniel P. Berrange 已提交
1579

1580
    if (hasRefs)
1581
        virObjectUnlock(priv->agent);
D
Daniel P. Berrange 已提交
1582

1583
    virObjectLock(obj);
1584 1585
    VIR_DEBUG("Exited agent (agent=%p vm=%p name=%s)",
              priv->agent, obj, obj->def->name);
D
Daniel P. Berrange 已提交
1586 1587

    priv->agentStart = 0;
1588
    if (!hasRefs)
D
Daniel P. Berrange 已提交
1589 1590 1591
        priv->agent = NULL;
}

1592
void qemuDomainObjEnterRemote(virDomainObjPtr obj)
1593
{
1594 1595
    VIR_DEBUG("Entering remote (vm=%p name=%s)",
              obj, obj->def->name);
1596
    virObjectRef(obj);
1597
    virObjectUnlock(obj);
1598 1599
}

1600
void qemuDomainObjExitRemote(virDomainObjPtr obj)
1601
{
1602
    virObjectLock(obj);
1603 1604
    VIR_DEBUG("Exited remote (vm=%p name=%s)",
              obj, obj->def->name);
1605
    virObjectUnref(obj);
1606
}
1607 1608


1609 1610 1611 1612 1613 1614 1615 1616
virDomainDefPtr
qemuDomainDefCopy(virQEMUDriverPtr driver,
                  virDomainDefPtr src,
                  unsigned int flags)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virDomainDefPtr ret = NULL;
    virCapsPtr caps = NULL;
1617
    char *xml = NULL;
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631

    if (qemuDomainDefFormatBuf(driver, src, flags, &buf) < 0)
        goto cleanup;

    xml = virBufferContentAndReset(&buf);

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

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

1632
 cleanup:
1633 1634 1635 1636 1637
    VIR_FREE(xml);
    virObjectUnref(caps);
    return ret;
}

1638
int
1639
qemuDomainDefFormatBuf(virQEMUDriverPtr driver,
1640 1641 1642
                       virDomainDefPtr def,
                       unsigned int flags,
                       virBuffer *buf)
1643
{
1644
    int ret = -1;
1645
    virCPUDefPtr cpu = NULL;
1646
    virCPUDefPtr def_cpu = def->cpu;
1647 1648
    virDomainControllerDefPtr *controllers = NULL;
    int ncontrollers = 0;
1649 1650 1651 1652
    virCapsPtr caps = NULL;

    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;
1653 1654

    /* Update guest CPU requirements according to host CPU */
1655 1656 1657
    if ((flags & VIR_DOMAIN_XML_UPDATE_CPU) &&
        def_cpu &&
        (def_cpu->mode != VIR_CPU_MODE_CUSTOM || def_cpu->model)) {
1658 1659
        if (!caps->host.cpu ||
            !caps->host.cpu->model) {
1660 1661
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("cannot get host CPU capabilities"));
1662 1663 1664
            goto cleanup;
        }

1665
        if (!(cpu = virCPUDefCopy(def_cpu)) ||
1666
            cpuUpdate(cpu, caps->host.cpu) < 0)
1667 1668 1669 1670
            goto cleanup;
        def->cpu = cpu;
    }

1671
    if ((flags & VIR_DOMAIN_XML_MIGRATABLE)) {
1672
        size_t i;
1673
        int toremove = 0;
1674
        virDomainControllerDefPtr usb = NULL, pci = NULL;
1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692

        /* If only the default USB controller is present, we can remove it
         * and make the XML compatible with older versions of libvirt which
         * didn't support USB controllers in the XML but always added the
         * default one to qemu anyway.
         */
        for (i = 0; i < def->ncontrollers; i++) {
            if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
                if (usb) {
                    usb = NULL;
                    break;
                }
                usb = def->controllers[i];
            }
        }
        if (usb && usb->idx == 0 && usb->model == -1) {
            VIR_DEBUG("Removing default USB controller from domain '%s'"
                      " for migration compatibility", def->name);
1693
            toremove++;
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711
        } else {
            usb = NULL;
        }

        /* Remove the default PCI controller if there is only one present
         * and its model is pci-root */
        for (i = 0; i < def->ncontrollers; i++) {
            if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
                if (pci) {
                    pci = NULL;
                    break;
                }
                pci = def->controllers[i];
            }
        }

        if (pci && pci->idx == 0 &&
            pci->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
L
Laine Stump 已提交
1712
            VIR_DEBUG("Removing default pci-root from domain '%s'"
1713
                      " for migration compatibility", def->name);
1714
            toremove++;
1715 1716 1717 1718
        } else {
            pci = NULL;
        }

1719
        if (toremove) {
1720 1721
            controllers = def->controllers;
            ncontrollers = def->ncontrollers;
1722
            if (VIR_ALLOC_N(def->controllers, ncontrollers - toremove) < 0) {
1723 1724 1725 1726 1727 1728
                controllers = NULL;
                goto cleanup;
            }

            def->ncontrollers = 0;
            for (i = 0; i < ncontrollers; i++) {
1729
                if (controllers[i] != usb && controllers[i] != pci)
1730 1731 1732
                    def->controllers[def->ncontrollers++] = controllers[i];
            }
        }
1733 1734


1735 1736
    }

1737
    ret = virDomainDefFormatInternal(def, flags, buf);
1738

1739
 cleanup:
1740 1741
    def->cpu = def_cpu;
    virCPUDefFree(cpu);
1742 1743 1744 1745 1746
    if (controllers) {
        VIR_FREE(def->controllers);
        def->controllers = controllers;
        def->ncontrollers = ncontrollers;
    }
1747
    virObjectUnref(caps);
1748 1749
    return ret;
}
1750

1751
char *qemuDomainDefFormatXML(virQEMUDriverPtr driver,
1752
                             virDomainDefPtr def,
1753
                             unsigned int flags)
1754 1755 1756
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

1757
    if (qemuDomainDefFormatBuf(driver, def, flags, &buf) < 0) {
1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
        virBufferFreeAndReset(&buf);
        return NULL;
    }

    if (virBufferError(&buf)) {
        virReportOOMError();
        virBufferFreeAndReset(&buf);
        return NULL;
    }

    return virBufferContentAndReset(&buf);
}

1771
char *qemuDomainFormatXML(virQEMUDriverPtr driver,
1772
                          virDomainObjPtr vm,
1773
                          unsigned int flags)
1774 1775 1776 1777 1778 1779 1780 1781
{
    virDomainDefPtr def;

    if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef)
        def = vm->newDef;
    else
        def = vm->def;

1782
    return qemuDomainDefFormatXML(driver, def, flags);
1783 1784
}

1785
char *
1786
qemuDomainDefFormatLive(virQEMUDriverPtr driver,
1787
                        virDomainDefPtr def,
1788 1789
                        bool inactive,
                        bool compatible)
1790 1791 1792 1793 1794
{
    unsigned int flags = QEMU_DOMAIN_FORMAT_LIVE_FLAGS;

    if (inactive)
        flags |= VIR_DOMAIN_XML_INACTIVE;
1795 1796
    if (compatible)
        flags |= VIR_DOMAIN_XML_MIGRATABLE;
1797

1798
    return qemuDomainDefFormatXML(driver, def, flags);
1799 1800
}

1801

1802
void qemuDomainObjTaint(virQEMUDriverPtr driver,
1803
                        virDomainObjPtr obj,
1804
                        virDomainTaintFlags taint,
1805
                        int logFD)
1806
{
1807 1808
    virErrorPtr orig_err = NULL;

1809 1810 1811 1812 1813 1814 1815 1816 1817
    if (virDomainObjTaint(obj, taint)) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(obj->def->uuid, uuidstr);

        VIR_WARN("Domain id=%d name='%s' uuid=%s is tainted: %s",
                 obj->def->id,
                 obj->def->name,
                 uuidstr,
                 virDomainTaintTypeToString(taint));
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831

        /* We don't care about errors logging taint info, so
         * preserve original error, and clear any error that
         * is raised */
        orig_err = virSaveLastError();
        if (qemuDomainAppendLog(driver, obj, logFD,
                                "Domain id=%d is tainted: %s\n",
                                obj->def->id,
                                virDomainTaintTypeToString(taint)) < 0)
            virResetLastError();
        if (orig_err) {
            virSetError(orig_err);
            virFreeError(orig_err);
        }
1832 1833 1834 1835
    }
}


1836
void qemuDomainObjCheckTaint(virQEMUDriverPtr driver,
1837 1838
                             virDomainObjPtr obj,
                             int logFD)
1839
{
1840
    size_t i;
1841
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
1842
    qemuDomainObjPrivatePtr priv = obj->privateData;
1843

1844 1845 1846 1847
    if (cfg->privileged &&
        (!cfg->clearEmulatorCapabilities ||
         cfg->user == 0 ||
         cfg->group == 0))
1848
        qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_HIGH_PRIVILEGES, logFD);
1849

1850 1851 1852
    if (priv->hookRun)
        qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_HOOK, logFD);

1853 1854 1855
    if (obj->def->namespaceData) {
        qemuDomainCmdlineDefPtr qemucmd = obj->def->namespaceData;
        if (qemucmd->num_args || qemucmd->num_env)
1856
            qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_CUSTOM_ARGV, logFD);
1857 1858
    }

1859 1860 1861
    if (obj->def->cpu && obj->def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH)
        qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_HOST_CPU, logFD);

1862
    for (i = 0; i < obj->def->ndisks; i++)
1863
        qemuDomainObjCheckDiskTaint(driver, obj, obj->def->disks[i], logFD);
1864

1865
    for (i = 0; i < obj->def->nnets; i++)
1866
        qemuDomainObjCheckNetTaint(driver, obj, obj->def->nets[i], logFD);
1867 1868

    virObjectUnref(cfg);
1869 1870 1871
}


1872
void qemuDomainObjCheckDiskTaint(virQEMUDriverPtr driver,
1873
                                 virDomainObjPtr obj,
1874 1875
                                 virDomainDiskDefPtr disk,
                                 int logFD)
1876
{
1877
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
1878
    int format = virDomainDiskGetFormat(disk);
1879

1880
    if ((!format || format == VIR_STORAGE_FILE_AUTO) &&
1881
        cfg->allowDiskFormatProbing)
1882
        qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_DISK_PROBING, logFD);
1883

1884
    if (disk->rawio == 1)
1885
        qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_HIGH_PRIVILEGES, logFD);
1886 1887

    virObjectUnref(cfg);
1888 1889 1890
}


1891
void qemuDomainObjCheckNetTaint(virQEMUDriverPtr driver,
1892
                                virDomainObjPtr obj,
1893 1894
                                virDomainNetDefPtr net,
                                int logFD)
1895
{
1896 1897 1898 1899 1900 1901
    /* script is only useful for NET_TYPE_ETHERNET (qemu) and
     * NET_TYPE_BRIDGE (xen), but could be (incorrectly) specified for
     * any interface type. In any case, it's adding user sauce into
     * the soup, so it should taint the domain.
     */
    if (net->script != NULL)
1902
        qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_SHELL_SCRIPTS, logFD);
1903
}
1904 1905 1906


static int
1907
qemuDomainOpenLogHelper(virQEMUDriverConfigPtr cfg,
1908
                        virDomainObjPtr vm,
E
Eric Blake 已提交
1909
                        int oflags,
1910 1911 1912 1913
                        mode_t mode)
{
    char *logfile;
    int fd = -1;
1914
    bool trunc = false;
1915

1916
    if (virAsprintf(&logfile, "%s/%s.log", cfg->logDir, vm->def->name) < 0)
1917 1918
        return -1;

1919 1920 1921 1922 1923 1924 1925 1926 1927
    /* To make SELinux happy we always need to open in append mode.
     * So we fake O_TRUNC by calling ftruncate after open instead
     */
    if (oflags & O_TRUNC) {
        oflags &= ~O_TRUNC;
        oflags |= O_APPEND;
        trunc = true;
    }

E
Eric Blake 已提交
1928
    if ((fd = open(logfile, oflags, mode)) < 0) {
1929 1930 1931 1932 1933 1934 1935
        virReportSystemError(errno, _("failed to create logfile %s"),
                             logfile);
        goto cleanup;
    }
    if (virSetCloseExec(fd) < 0) {
        virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
                             logfile);
1936 1937 1938 1939 1940 1941 1942
        VIR_FORCE_CLOSE(fd);
        goto cleanup;
    }
    if (trunc &&
        ftruncate(fd, 0) < 0) {
        virReportSystemError(errno, _("failed to truncate %s"),
                             logfile);
1943 1944 1945 1946
        VIR_FORCE_CLOSE(fd);
        goto cleanup;
    }

1947
 cleanup:
1948 1949 1950 1951 1952 1953
    VIR_FREE(logfile);
    return fd;
}


int
1954
qemuDomainCreateLog(virQEMUDriverPtr driver, virDomainObjPtr vm,
E
Eric Blake 已提交
1955
                    bool append)
1956
{
1957
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
E
Eric Blake 已提交
1958
    int oflags;
1959
    int ret;
1960

E
Eric Blake 已提交
1961
    oflags = O_CREAT | O_WRONLY;
1962
    /* Only logrotate files in /var/log, so only append if running privileged */
1963
    if (cfg->privileged || append)
E
Eric Blake 已提交
1964
        oflags |= O_APPEND;
1965
    else
E
Eric Blake 已提交
1966
        oflags |= O_TRUNC;
1967

1968 1969 1970
    ret = qemuDomainOpenLogHelper(cfg, vm, oflags, S_IRUSR | S_IWUSR);
    virObjectUnref(cfg);
    return ret;
1971 1972 1973 1974
}


int
1975
qemuDomainOpenLog(virQEMUDriverPtr driver, virDomainObjPtr vm, off_t pos)
1976
{
1977
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
1978 1979 1980 1981
    int fd;
    off_t off;
    int whence;

1982 1983 1984
    fd = qemuDomainOpenLogHelper(cfg, vm, O_RDONLY, 0);
    virObjectUnref(cfg);
    if (fd < 0)
1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
        return -1;

    if (pos < 0) {
        off = 0;
        whence = SEEK_END;
    } else {
        off = pos;
        whence = SEEK_SET;
    }

    if (lseek(fd, off, whence) < 0) {
        if (whence == SEEK_END)
            virReportSystemError(errno,
                                 _("unable to seek to end of log for %s"),
                                 vm->def->name);
        else
            virReportSystemError(errno,
                                 _("unable to seek to %lld from start for %s"),
                                 (long long)off, vm->def->name);
        VIR_FORCE_CLOSE(fd);
    }

    return fd;
}


2011
int qemuDomainAppendLog(virQEMUDriverPtr driver,
2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
                        virDomainObjPtr obj,
                        int logFD,
                        const char *fmt, ...)
{
    int fd = logFD;
    va_list argptr;
    char *message = NULL;
    int ret = -1;

    va_start(argptr, fmt);

    if ((fd == -1) &&
        (fd = qemuDomainCreateLog(driver, obj, true)) < 0)
        goto cleanup;

2027
    if (virVasprintf(&message, fmt, argptr) < 0)
2028 2029 2030 2031 2032 2033 2034 2035 2036
        goto cleanup;
    if (safewrite(fd, message, strlen(message)) < 0) {
        virReportSystemError(errno, _("Unable to write to domain logfile %s"),
                             obj->def->name);
        goto cleanup;
    }

    ret = 0;

2037
 cleanup:
2038 2039 2040 2041 2042
    va_end(argptr);

    if (fd != logFD)
        VIR_FORCE_CLOSE(fd);

O
Osier Yang 已提交
2043
    VIR_FREE(message);
2044 2045
    return ret;
}
2046 2047 2048

/* Locate an appropriate 'qemu-img' binary.  */
const char *
2049
qemuFindQemuImgBinary(virQEMUDriverPtr driver)
2050
{
2051 2052 2053
    if (!driver->qemuImgBinary)
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("unable to find kvm-img or qemu-img"));
2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070

    return driver->qemuImgBinary;
}

int
qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
                                virDomainSnapshotObjPtr snapshot,
                                char *snapshotDir)
{
    char *newxml = NULL;
    int ret = -1;
    char *snapDir = NULL;
    char *snapFile = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    virUUIDFormat(vm->def->uuid, uuidstr);
    newxml = virDomainSnapshotDefFormat(uuidstr, snapshot->def,
2071 2072
                                        QEMU_DOMAIN_FORMAT_LIVE_FLAGS, 1);
    if (newxml == NULL)
2073 2074
        return -1;

2075
    if (virAsprintf(&snapDir, "%s/%s", snapshotDir, vm->def->name) < 0)
2076 2077 2078 2079 2080 2081 2082
        goto cleanup;
    if (virFileMakePath(snapDir) < 0) {
        virReportSystemError(errno, _("cannot create snapshot directory '%s'"),
                             snapDir);
        goto cleanup;
    }

2083
    if (virAsprintf(&snapFile, "%s/%s.xml", snapDir, snapshot->def->name) < 0)
2084 2085
        goto cleanup;

J
Ján Tomko 已提交
2086
    ret = virXMLSaveFile(snapFile, NULL, "snapshot-edit", newxml);
2087

2088
 cleanup:
2089 2090 2091 2092 2093 2094 2095 2096
    VIR_FREE(snapFile);
    VIR_FREE(snapDir);
    VIR_FREE(newxml);
    return ret;
}

/* The domain is expected to be locked and inactive. Return -1 on normal
 * failure, 1 if we skipped a disk due to try_all.  */
2097
static int
2098
qemuDomainSnapshotForEachQcow2Raw(virQEMUDriverPtr driver,
2099 2100 2101 2102 2103
                                  virDomainDefPtr def,
                                  const char *name,
                                  const char *op,
                                  bool try_all,
                                  int ndisks)
2104 2105
{
    const char *qemuimgarg[] = { NULL, "snapshot", NULL, NULL, NULL, NULL };
2106
    size_t i;
2107 2108 2109 2110 2111 2112 2113 2114 2115
    bool skipped = false;

    qemuimgarg[0] = qemuFindQemuImgBinary(driver);
    if (qemuimgarg[0] == NULL) {
        /* qemuFindQemuImgBinary set the error */
        return -1;
    }

    qemuimgarg[2] = op;
2116
    qemuimgarg[3] = name;
2117

2118
    for (i = 0; i < ndisks; i++) {
2119
        /* FIXME: we also need to handle LVM here */
2120
        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
2121 2122 2123
            int format = virDomainDiskGetFormat(def->disks[i]);

            if (format > 0 && format != VIR_STORAGE_FILE_QCOW2) {
2124 2125 2126 2127 2128
                if (try_all) {
                    /* Continue on even in the face of error, since other
                     * disks in this VM may have the same snapshot name.
                     */
                    VIR_WARN("skipping snapshot action on %s",
2129
                             def->disks[i]->dst);
2130 2131
                    skipped = true;
                    continue;
2132 2133 2134 2135 2136
                } else if (STREQ(op, "-c") && i) {
                    /* We must roll back partial creation by deleting
                     * all earlier snapshots.  */
                    qemuDomainSnapshotForEachQcow2Raw(driver, def, name,
                                                      "-d", false, i);
2137
                }
2138 2139 2140 2141
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("Disk device '%s' does not support"
                                 " snapshotting"),
                               def->disks[i]->dst);
2142 2143 2144
                return -1;
            }

2145
            qemuimgarg[4] = virDomainDiskGetSource(def->disks[i]);
2146 2147 2148 2149

            if (virRun(qemuimgarg, NULL) < 0) {
                if (try_all) {
                    VIR_WARN("skipping snapshot action on %s",
2150
                             def->disks[i]->dst);
2151 2152
                    skipped = true;
                    continue;
2153 2154 2155 2156 2157
                } else if (STREQ(op, "-c") && i) {
                    /* We must roll back partial creation by deleting
                     * all earlier snapshots.  */
                    qemuDomainSnapshotForEachQcow2Raw(driver, def, name,
                                                      "-d", false, i);
2158 2159 2160 2161 2162 2163 2164 2165 2166
                }
                return -1;
            }
        }
    }

    return skipped ? 1 : 0;
}

2167 2168 2169
/* The domain is expected to be locked and inactive. Return -1 on normal
 * failure, 1 if we skipped a disk due to try_all.  */
int
2170
qemuDomainSnapshotForEachQcow2(virQEMUDriverPtr driver,
2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186
                               virDomainObjPtr vm,
                               virDomainSnapshotObjPtr snap,
                               const char *op,
                               bool try_all)
{
    /* Prefer action on the disks in use at the time the snapshot was
     * created; but fall back to current definition if dealing with a
     * snapshot created prior to libvirt 0.9.5.  */
    virDomainDefPtr def = snap->def->dom;

    if (!def)
        def = vm->def;
    return qemuDomainSnapshotForEachQcow2Raw(driver, def, snap->def->name,
                                             op, try_all, def->ndisks);
}

2187 2188
/* Discard one snapshot (or its metadata), without reparenting any children.  */
int
2189
qemuDomainSnapshotDiscard(virQEMUDriverPtr driver,
2190 2191 2192 2193 2194 2195 2196 2197 2198
                          virDomainObjPtr vm,
                          virDomainSnapshotObjPtr snap,
                          bool update_current,
                          bool metadata_only)
{
    char *snapFile = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
    virDomainSnapshotObjPtr parentsnap = NULL;
2199
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
2200 2201 2202 2203 2204 2205 2206 2207 2208

    if (!metadata_only) {
        if (!virDomainObjIsActive(vm)) {
            /* Ignore any skipped disks */
            if (qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-d",
                                               true) < 0)
                goto cleanup;
        } else {
            priv = vm->privateData;
2209
            qemuDomainObjEnterMonitor(driver, vm);
2210 2211
            /* we continue on even in the face of error */
            qemuMonitorDeleteSnapshot(priv->mon, snap->def->name);
2212
            qemuDomainObjExitMonitor(driver, vm);
2213 2214 2215
        }
    }

2216
    if (virAsprintf(&snapFile, "%s/%s/%s.xml", cfg->snapshotDir,
2217
                    vm->def->name, snap->def->name) < 0)
2218 2219 2220 2221
        goto cleanup;

    if (snap == vm->current_snapshot) {
        if (update_current && snap->def->parent) {
2222
            parentsnap = virDomainSnapshotFindByName(vm->snapshots,
2223 2224 2225 2226 2227 2228 2229
                                                     snap->def->parent);
            if (!parentsnap) {
                VIR_WARN("missing parent snapshot matching name '%s'",
                         snap->def->parent);
            } else {
                parentsnap->def->current = true;
                if (qemuDomainSnapshotWriteMetadata(vm, parentsnap,
2230
                                                    cfg->snapshotDir) < 0) {
2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242
                    VIR_WARN("failed to set parent snapshot '%s' as current",
                             snap->def->parent);
                    parentsnap->def->current = false;
                    parentsnap = NULL;
                }
            }
        }
        vm->current_snapshot = parentsnap;
    }

    if (unlink(snapFile) < 0)
        VIR_WARN("Failed to unlink %s", snapFile);
2243
    virDomainSnapshotObjListRemove(vm->snapshots, snap);
2244 2245 2246

    ret = 0;

2247
 cleanup:
2248
    VIR_FREE(snapFile);
2249
    virObjectUnref(cfg);
2250 2251 2252 2253 2254 2255 2256 2257 2258
    return ret;
}

/* Hash iterator callback to discard multiple snapshots.  */
void qemuDomainSnapshotDiscardAll(void *payload,
                                  const void *name ATTRIBUTE_UNUSED,
                                  void *data)
{
    virDomainSnapshotObjPtr snap = payload;
2259
    virQEMUSnapRemovePtr curr = data;
2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270
    int err;

    if (snap->def->current)
        curr->current = true;
    err = qemuDomainSnapshotDiscard(curr->driver, curr->vm, snap, false,
                                    curr->metadata_only);
    if (err && !curr->err)
        curr->err = err;
}

int
2271
qemuDomainSnapshotDiscardAllMetadata(virQEMUDriverPtr driver,
2272 2273
                                     virDomainObjPtr vm)
{
2274
    virQEMUSnapRemove rem;
2275 2276 2277 2278 2279

    rem.driver = driver;
    rem.vm = vm;
    rem.metadata_only = true;
    rem.err = 0;
2280 2281
    virDomainSnapshotForEach(vm->snapshots, qemuDomainSnapshotDiscardAll,
                             &rem);
2282 2283 2284 2285 2286

    return rem.err;
}

/*
2287
 * The caller must hold a lock the vm and there must
2288 2289 2290
 * be no remaining references to vm.
 */
void
2291
qemuDomainRemoveInactive(virQEMUDriverPtr driver,
2292 2293
                         virDomainObjPtr vm)
{
2294
    char *snapDir;
2295
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
2296

2297 2298 2299 2300 2301
    /* Remove any snapshot metadata prior to removing the domain */
    if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0) {
        VIR_WARN("unable to remove all snapshots for domain %s",
                 vm->def->name);
    }
2302
    else if (virAsprintf(&snapDir, "%s/%s", cfg->snapshotDir,
2303 2304
                         vm->def->name) < 0) {
        VIR_WARN("unable to remove snapshot directory %s/%s",
2305
                 cfg->snapshotDir, vm->def->name);
2306 2307 2308 2309 2310
    } else {
        if (rmdir(snapDir) < 0 && errno != ENOENT)
            VIR_WARN("unable to remove snapshot directory %s", snapDir);
        VIR_FREE(snapDir);
    }
2311
    virDomainObjListRemove(driver->domains, vm);
2312
    virObjectUnref(cfg);
2313
}
2314 2315

void
2316
qemuDomainSetFakeReboot(virQEMUDriverPtr driver,
2317 2318 2319 2320
                        virDomainObjPtr vm,
                        bool value)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
2321
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
2322 2323

    if (priv->fakeReboot == value)
2324
        goto cleanup;
2325 2326 2327

    priv->fakeReboot = value;

2328
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
2329
        VIR_WARN("Failed to save status on vm %s", vm->def->name);
2330

2331
 cleanup:
2332
    virObjectUnref(cfg);
2333
}
M
Michal Privoznik 已提交
2334

2335 2336 2337
static int
qemuDomainCheckRemoveOptionalDisk(virQEMUDriverPtr driver,
                                  virDomainObjPtr vm,
2338
                                  size_t diskIndex)
2339 2340
{
    char uuid[VIR_UUID_STRING_BUFLEN];
2341
    virObjectEventPtr event = NULL;
2342
    virDomainDiskDefPtr disk = vm->def->disks[diskIndex];
2343
    const char *src = virDomainDiskGetSource(disk);
2344 2345 2346 2347 2348

    virUUIDFormat(vm->def->uuid, uuid);

    VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
              "due to inaccessible source '%s'",
2349
              disk->dst, vm->def->name, uuid, src);
2350 2351 2352 2353

    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
        disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {

2354
        event = virDomainEventDiskChangeNewFromObj(vm, src, NULL,
2355 2356
                                                   disk->info.alias,
                                                   VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
2357
        ignore_value(virDomainDiskSetSource(disk, NULL));
2358
    } else {
2359
        event = virDomainEventDiskChangeNewFromObj(vm, src, NULL,
2360 2361
                                                   disk->info.alias,
                                                   VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START);
2362 2363
        virDomainDiskRemove(vm->def, diskIndex);
        virDomainDiskDefFree(disk);
2364 2365 2366 2367 2368 2369 2370 2371
    }

    if (event)
        qemuDomainEventQueue(driver, event);

    return 0;
}

2372 2373 2374
static int
qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
                                 virDomainObjPtr vm,
2375
                                 size_t diskIndex,
2376 2377 2378
                                 bool cold_boot)
{
    char uuid[VIR_UUID_STRING_BUFLEN];
2379
    int startupPolicy = vm->def->disks[diskIndex]->startupPolicy;
2380
    int device = vm->def->disks[diskIndex]->device;
2381 2382 2383

    virUUIDFormat(vm->def->uuid, uuid);

2384
    switch ((virDomainStartupPolicy) startupPolicy) {
2385
        case VIR_DOMAIN_STARTUP_POLICY_OPTIONAL:
2386 2387 2388 2389 2390 2391 2392
            /* Once started with an optional disk, qemu saves its section
             * in the migration stream, so later, when restoring from it
             * we must make sure the sections match. */
            if (!cold_boot &&
                device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
                device != VIR_DOMAIN_DISK_DEVICE_CDROM)
                goto error;
2393 2394 2395 2396 2397 2398
            break;

        case VIR_DOMAIN_STARTUP_POLICY_MANDATORY:
            goto error;

        case VIR_DOMAIN_STARTUP_POLICY_REQUISITE:
2399
            if (cold_boot)
2400 2401 2402 2403 2404 2405 2406 2407 2408
                goto error;
            break;

        case VIR_DOMAIN_STARTUP_POLICY_DEFAULT:
        case VIR_DOMAIN_STARTUP_POLICY_LAST:
            /* this should never happen */
            break;
    }

2409
    if (qemuDomainCheckRemoveOptionalDisk(driver, vm, diskIndex) < 0)
2410
        goto error;
2411 2412 2413

    return 0;

2414
 error:
2415 2416 2417
    return -1;
}

2418 2419 2420 2421 2422
static int
qemuDiskChainCheckBroken(virDomainDiskDefPtr disk)
{
    char *brokenFile = NULL;

2423
    if (!virDomainDiskGetSource(disk))
2424 2425
        return 0;

2426
    if (virStorageFileChainGetBroken(disk->src, &brokenFile) < 0)
2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439
        return -1;

    if (brokenFile) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Backing file '%s' of image '%s' is missing."),
                       brokenFile, virDomainDiskGetSource(disk));
        VIR_FREE(brokenFile);
        return -1;
    }

    return 0;
}

M
Michal Privoznik 已提交
2440
int
2441
qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
M
Michal Privoznik 已提交
2442
                            virDomainObjPtr vm,
2443
                            bool cold_boot)
M
Michal Privoznik 已提交
2444 2445
{
    int ret = -1;
2446
    size_t i;
M
Michal Privoznik 已提交
2447

2448
    VIR_DEBUG("Checking for disk presence");
2449
    for (i = vm->def->ndisks; i > 0; i--) {
2450 2451
        size_t idx = i - 1;
        virDomainDiskDefPtr disk = vm->def->disks[idx];
2452
        const char *path = virDomainDiskGetSource(disk);
2453
        virStorageFileFormat format = virDomainDiskGetFormat(disk);
2454
        virStorageType type = virStorageSourceGetActualType(disk->src);
M
Michal Privoznik 已提交
2455

2456 2457 2458 2459 2460 2461
        if (!path)
            continue;

        /* There is no need to check the backing chain for disks
         * without backing support, the fact that the file exists is
         * more than enough */
2462 2463
        if (type != VIR_STORAGE_TYPE_NETWORK &&
            format >= VIR_STORAGE_FILE_NONE &&
2464 2465
            format < VIR_STORAGE_FILE_BACKING &&
            virFileExists(path))
M
Michal Privoznik 已提交
2466 2467
            continue;

2468
        if (qemuDomainDetermineDiskChain(driver, vm, disk, false) >= 0 &&
2469
            qemuDiskChainCheckBroken(disk) >= 0)
M
Michal Privoznik 已提交
2470
            continue;
2471

2472
        if (disk->startupPolicy &&
2473
            qemuDomainCheckDiskStartupPolicy(driver, vm, idx,
2474 2475 2476
                                             cold_boot) >= 0) {
            virResetLastError();
            continue;
M
Michal Privoznik 已提交
2477 2478
        }

2479
        goto error;
M
Michal Privoznik 已提交
2480 2481 2482 2483
    }

    ret = 0;

2484
 error:
M
Michal Privoznik 已提交
2485 2486
    return ret;
}
2487 2488 2489 2490 2491 2492 2493 2494 2495 2496

/*
 * The vm must be locked when any of the following cleanup functions is
 * called.
 */
int
qemuDomainCleanupAdd(virDomainObjPtr vm,
                     qemuDomainCleanupCallback cb)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
2497
    size_t i;
2498 2499 2500 2501 2502 2503 2504 2505 2506 2507

    VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb);

    for (i = 0; i < priv->ncleanupCallbacks; i++) {
        if (priv->cleanupCallbacks[i] == cb)
            return 0;
    }

    if (VIR_RESIZE_N(priv->cleanupCallbacks,
                     priv->ncleanupCallbacks_max,
2508
                     priv->ncleanupCallbacks, 1) < 0)
2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519
        return -1;

    priv->cleanupCallbacks[priv->ncleanupCallbacks++] = cb;
    return 0;
}

void
qemuDomainCleanupRemove(virDomainObjPtr vm,
                        qemuDomainCleanupCallback cb)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
2520
    size_t i;
2521 2522 2523 2524

    VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb);

    for (i = 0; i < priv->ncleanupCallbacks; i++) {
2525 2526 2527
        if (priv->cleanupCallbacks[i] == cb)
            VIR_DELETE_ELEMENT_INPLACE(priv->cleanupCallbacks,
                                       i, priv->ncleanupCallbacks);
2528 2529 2530 2531 2532 2533 2534 2535
    }

    VIR_SHRINK_N(priv->cleanupCallbacks,
                 priv->ncleanupCallbacks_max,
                 priv->ncleanupCallbacks_max - priv->ncleanupCallbacks);
}

void
2536
qemuDomainCleanupRun(virQEMUDriverPtr driver,
2537 2538 2539
                     virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
2540
    size_t i;
2541 2542 2543 2544

    VIR_DEBUG("driver=%p, vm=%s", driver, vm->def->name);

    /* run cleanup callbacks in reverse order */
2545 2546
    for (i = 0; i < priv->ncleanupCallbacks; i++) {
        if (priv->cleanupCallbacks[priv->ncleanupCallbacks - (i + 1)])
2547 2548 2549 2550 2551 2552 2553
            priv->cleanupCallbacks[i](driver, vm);
    }

    VIR_FREE(priv->cleanupCallbacks);
    priv->ncleanupCallbacks = 0;
    priv->ncleanupCallbacks_max = 0;
}
2554

2555 2556 2557
static void
qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg,
                      virDomainObjPtr vm,
2558
                      virStorageSourcePtr src,
2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576
                      uid_t *uid, gid_t *gid)
{
    virSecurityLabelDefPtr vmlabel;
    virSecurityDeviceLabelDefPtr disklabel;

    if (uid)
        *uid = -1;
    if (gid)
        *gid = -1;

    if (cfg) {
        if (uid)
            *uid = cfg->user;

        if (gid)
            *gid = cfg->group;
    }

2577 2578
    if (vm && (vmlabel = virDomainDefGetSecurityLabelDef(vm->def, "dac")) &&
        vmlabel->label)
2579 2580
        virParseOwnershipIds(vmlabel->label, uid, gid);

2581
    if ((disklabel = virStorageSourceGetSecurityLabelDef(src, "dac")) &&
2582
        disklabel->label)
2583 2584 2585 2586
        virParseOwnershipIds(disklabel->label, uid, gid);
}


2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609
int
qemuDomainStorageFileInit(virQEMUDriverPtr driver,
                          virDomainObjPtr vm,
                          virStorageSourcePtr src)
{
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
    uid_t uid;
    gid_t gid;
    int ret = -1;

    qemuDomainGetImageIds(cfg, vm, src, &uid, &gid);

    if (virStorageFileInitAs(src, uid, gid) < 0)
        goto cleanup;

    ret = 0;

 cleanup:
    virObjectUnref(cfg);
    return ret;
}


2610
int
2611
qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
2612
                             virDomainObjPtr vm,
2613 2614 2615
                             virDomainDiskDefPtr disk,
                             bool force)
{
2616 2617
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
    int ret = 0;
2618 2619
    uid_t uid;
    gid_t gid;
2620
    int type = virStorageSourceGetActualType(disk->src);
2621

2622
    if (type != VIR_STORAGE_TYPE_NETWORK &&
2623
        !disk->src->path)
2624
        goto cleanup;
2625

2626
    if (disk->src->backingStore) {
2627
        if (force)
2628
            virStorageSourceBackingStoreClear(disk->src);
2629
        else
2630
            goto cleanup;
2631
    }
2632

2633
    qemuDomainGetImageIds(cfg, vm, disk->src, &uid, &gid);
2634

2635
    if (virStorageFileGetMetadata(disk->src,
2636 2637
                                  uid, gid,
                                  cfg->allowDiskFormatProbing) < 0)
2638 2639
        ret = -1;

2640
 cleanup:
2641 2642
    virObjectUnref(cfg);
    return ret;
2643
}
2644

2645 2646
int
qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
2647 2648
                           virDomainObjPtr vm,
                           int asyncJob)
2649 2650 2651 2652 2653 2654 2655
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    char **aliases;

    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
        return 0;

2656 2657
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
        return -1;
2658 2659 2660 2661 2662 2663 2664 2665 2666 2667
    if (qemuMonitorGetDeviceAliases(priv->mon, &aliases) < 0) {
        qemuDomainObjExitMonitor(driver, vm);
        return -1;
    }
    qemuDomainObjExitMonitor(driver, vm);

    virStringFreeList(priv->qemuDevices);
    priv->qemuDevices = aliases;
    return 0;
}
2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684

bool
qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
                               virDomainDefPtr src,
                               virDomainDefPtr dst)
{
    virDomainDefPtr migratableDefSrc = NULL;
    virDomainDefPtr migratableDefDst = NULL;
    const int flags = VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_UPDATE_CPU | VIR_DOMAIN_XML_MIGRATABLE;
    bool ret = false;

    if (!(migratableDefSrc = qemuDomainDefCopy(driver, src, flags)) ||
        !(migratableDefDst = qemuDomainDefCopy(driver, dst, flags)))
        goto cleanup;

    ret = virDomainDefCheckABIStability(migratableDefSrc, migratableDefDst);

2685
 cleanup:
2686 2687 2688 2689
    virDomainDefFree(migratableDefSrc);
    virDomainDefFree(migratableDefDst);
    return ret;
}
2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711

bool
qemuDomainAgentAvailable(qemuDomainObjPrivatePtr priv,
                         bool reportError)
{
    if (priv->agentError) {
        if (reportError) {
            virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                           _("QEMU guest agent is not "
                             "available due to an error"));
        }
        return false;
    }
    if (!priv->agent) {
        if (reportError) {
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("QEMU guest agent is not configured"));
        }
        return false;
    }
    return true;
}