qemu_conf.c 219.5 KB
Newer Older
D
Daniel P. Berrange 已提交
1
/*
2
 * qemu_conf.c: QEMU configuration management
D
Daniel P. Berrange 已提交
3
 *
4
 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
D
Daniel P. Berrange 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * 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
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

24
#include <config.h>
25

D
Daniel P. Berrange 已提交
26 27 28 29 30
#include <dirent.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
31
#include <stdlib.h>
D
Daniel P. Berrange 已提交
32 33 34
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
35
#include <sys/wait.h>
36
#include <arpa/inet.h>
37
#include <sys/utsname.h>
38
#include <mntent.h>
D
Daniel P. Berrange 已提交
39

40
#include "c-ctype.h"
41
#include "virterror_internal.h"
42
#include "qemu_conf.h"
43
#include "qemu_bridge_filter.h"
44
#include "uuid.h"
45
#include "buf.h"
D
Daniel P. Berrange 已提交
46
#include "conf.h"
47
#include "util.h"
48
#include "memory.h"
J
Jim Meyering 已提交
49
#include "verify.h"
50 51
#include "datatypes.h"
#include "xml.h"
52
#include "nodeinfo.h"
53
#include "logging.h"
54
#include "network.h"
55
#include "macvtap.h"
56
#include "cpu/cpu.h"
57
#include "domain_nwfilter.h"
58
#include "files.h"
59
#include "configmake.h"
60

61 62
#define VIR_FROM_THIS VIR_FROM_QEMU

63 64 65 66 67 68
VIR_ENUM_DECL(virDomainDiskQEMUBus)
VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
              "ide",
              "floppy",
              "scsi",
              "virtio",
69
              "xen",
70
              "usb",
71 72
              "uml",
              "sata")
73

74

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
VIR_ENUM_DECL(qemuDiskCacheV1)
VIR_ENUM_DECL(qemuDiskCacheV2)

VIR_ENUM_IMPL(qemuDiskCacheV1, VIR_DOMAIN_DISK_CACHE_LAST,
              "default",
              "off",
              "off", /* writethrough not supported, so for safety, disable */
              "on"); /* Old 'on' was equivalent to 'writeback' */

VIR_ENUM_IMPL(qemuDiskCacheV2, VIR_DOMAIN_DISK_CACHE_LAST,
              "default",
              "none",
              "writethrough",
              "writeback");

90 91 92 93 94 95
VIR_ENUM_DECL(qemuVideo)

VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
              "std",
              "cirrus",
              "vmware",
96
              "", /* no arg needed for xen */
97
              "", /* don't support vbox */
98
              "qxl");
99

D
Daniel P. Berrange 已提交
100 101 102 103
int qemudLoadDriverConfig(struct qemud_driver *driver,
                          const char *filename) {
    virConfPtr conf;
    virConfValuePtr p;
104 105
    char *user;
    char *group;
106
    int i;
D
Daniel P. Berrange 已提交
107

108 109
    /* Setup critical defaults */
    driver->dynamicOwnership = 1;
110
    driver->clearEmulatorCapabilities = 1;
111

112
    if (!(driver->vncListen = strdup("127.0.0.1"))) {
113
        virReportOOMError();
114 115
        return -1;
    }
116
    if (!(driver->vncTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-vnc"))) {
117
        virReportOOMError();
D
Daniel P. Berrange 已提交
118 119 120
        return -1;
    }

121 122 123 124
    if (!(driver->spiceListen = strdup("127.0.0.1"))) {
        virReportOOMError();
        return -1;
    }
125 126
    if (!(driver->spiceTLSx509certdir
          = strdup(SYSCONFDIR "/pki/libvirt-spice"))) {
127 128 129 130
        virReportOOMError();
        return -1;
    }

131
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
132 133 134 135 136 137
    /* For privileged driver, try and find hugepage mount automatically.
     * Non-privileged driver requires admin to create a dir for the
     * user, chown it, and then let user configure it manually */
    if (driver->privileged &&
        !(driver->hugetlbfs_mount = virFileFindMountPoint("hugetlbfs"))) {
        if (errno != ENOENT) {
138
            virReportSystemError(errno, "%s",
139 140 141 142 143 144 145
                                 _("unable to find hugetlbfs mountpoint"));
            return -1;
        }
    }
#endif


D
Daniel P. Berrange 已提交
146 147 148
    /* Just check the file is readable before opening it, otherwise
     * libvirt emits an error.
     */
149 150 151 152
    if (access (filename, R_OK) == -1) {
        VIR_INFO("Could not read qemu config file %s", filename);
        return 0;
    }
D
Daniel P. Berrange 已提交
153

154
    conf = virConfReadFile (filename, 0);
155 156 157
    if (!conf) {
        return -1;
    }
D
Daniel P. Berrange 已提交
158 159 160


#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) {               \
161
        qemuReportError(VIR_ERR_INTERNAL_ERROR,                         \
162 163
                        "%s: %s: expected type " #typ,                  \
                        filename, (name));                              \
D
Daniel P. Berrange 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
        virConfFree(conf);                                              \
        return -1;                                                      \
    }

    p = virConfGetValue (conf, "vnc_tls");
    CHECK_TYPE ("vnc_tls", VIR_CONF_LONG);
    if (p) driver->vncTLS = p->l;

    p = virConfGetValue (conf, "vnc_tls_x509_verify");
    CHECK_TYPE ("vnc_tls_x509_verify", VIR_CONF_LONG);
    if (p) driver->vncTLSx509verify = p->l;

    p = virConfGetValue (conf, "vnc_tls_x509_cert_dir");
    CHECK_TYPE ("vnc_tls_x509_cert_dir", VIR_CONF_STRING);
    if (p && p->str) {
179
        VIR_FREE(driver->vncTLSx509certdir);
D
Daniel P. Berrange 已提交
180
        if (!(driver->vncTLSx509certdir = strdup(p->str))) {
181
            virReportOOMError();
D
Daniel P. Berrange 已提交
182 183 184 185 186 187 188 189
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "vnc_listen");
    CHECK_TYPE ("vnc_listen", VIR_CONF_STRING);
    if (p && p->str) {
J
Jim Meyering 已提交
190
        VIR_FREE(driver->vncListen);
191
        if (!(driver->vncListen = strdup(p->str))) {
192
            virReportOOMError();
193 194 195
            virConfFree(conf);
            return -1;
        }
D
Daniel P. Berrange 已提交
196 197
    }

198 199 200 201 202
    p = virConfGetValue (conf, "vnc_password");
    CHECK_TYPE ("vnc_password", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->vncPassword);
        if (!(driver->vncPassword = strdup(p->str))) {
203
            virReportOOMError();
204 205 206 207 208
            virConfFree(conf);
            return -1;
        }
    }

209
    p = virConfGetValue (conf, "security_driver");
J
Jim Meyering 已提交
210
    CHECK_TYPE ("security_driver", VIR_CONF_STRING);
211 212
    if (p && p->str) {
        if (!(driver->securityDriverName = strdup(p->str))) {
213
            virReportOOMError();
214 215 216 217 218
            virConfFree(conf);
            return -1;
        }
    }

219 220 221 222 223 224 225 226 227
    p = virConfGetValue (conf, "vnc_sasl");
    CHECK_TYPE ("vnc_sasl", VIR_CONF_LONG);
    if (p) driver->vncSASL = p->l;

    p = virConfGetValue (conf, "vnc_sasl_dir");
    CHECK_TYPE ("vnc_sasl_dir", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->vncSASLdir);
        if (!(driver->vncSASLdir = strdup(p->str))) {
228
            virReportOOMError();
229 230 231 232 233
            virConfFree(conf);
            return -1;
        }
    }

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
    p = virConfGetValue (conf, "spice_tls");
    CHECK_TYPE ("spice_tls", VIR_CONF_LONG);
    if (p) driver->spiceTLS = p->l;

    p = virConfGetValue (conf, "spice_tls_x509_cert_dir");
    CHECK_TYPE ("spice_tls_x509_cert_dir", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->spiceTLSx509certdir);
        if (!(driver->spiceTLSx509certdir = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "spice_listen");
    CHECK_TYPE ("spice_listen", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->spiceListen);
        if (!(driver->spiceListen = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "spice_password");
    CHECK_TYPE ("spice_password", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->spicePassword);
        if (!(driver->spicePassword = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

271 272 273
    p = virConfGetValue (conf, "user");
    CHECK_TYPE ("user", VIR_CONF_STRING);
    if (!(user = strdup(p && p->str ? p->str : QEMU_USER))) {
274
        virReportOOMError();
275 276 277
        virConfFree(conf);
        return -1;
    }
278
    if (virGetUserID(user, &driver->user) < 0) {
279 280 281 282 283 284
        VIR_FREE(user);
        virConfFree(conf);
        return -1;
    }
    VIR_FREE(user);

285

286 287 288
    p = virConfGetValue (conf, "group");
    CHECK_TYPE ("group", VIR_CONF_STRING);
    if (!(group = strdup(p && p->str ? p->str : QEMU_GROUP))) {
289
        virReportOOMError();
290 291 292
        virConfFree(conf);
        return -1;
    }
293
    if (virGetGroupID(group, &driver->group) < 0) {
294 295 296 297 298 299
        VIR_FREE(group);
        virConfFree(conf);
        return -1;
    }
    VIR_FREE(group);

300 301 302 303 304 305

    p = virConfGetValue (conf, "dynamic_ownership");
    CHECK_TYPE ("dynamic_ownership", VIR_CONF_LONG);
    if (p) driver->dynamicOwnership = p->l;


306 307 308 309 310 311 312
    p = virConfGetValue (conf, "cgroup_controllers");
    CHECK_TYPE ("cgroup_controllers", VIR_CONF_LIST);
    if (p) {
        virConfValuePtr pp;
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            int ctl;
            if (pp->type != VIR_CONF_STRING) {
313
                VIR_ERROR0(_("cgroup_controllers must be a list of strings"));
314 315 316 317 318
                virConfFree(conf);
                return -1;
            }
            ctl = virCgroupControllerTypeFromString(pp->str);
            if (ctl < 0) {
319
                VIR_ERROR(_("Unknown cgroup controller '%s'"), pp->str);
320 321 322 323 324 325 326 327
                virConfFree(conf);
                return -1;
            }
            driver->cgroupControllers |= (1 << ctl);
        }
    } else {
        driver->cgroupControllers =
            (1 << VIR_CGROUP_CONTROLLER_CPU) |
328 329
            (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
            (1 << VIR_CGROUP_CONTROLLER_MEMORY);
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    }
    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
        if (driver->cgroupControllers & (1 << i)) {
            VIR_INFO("Configured cgroup controller '%s'",
                     virCgroupControllerTypeToString(i));
        }
    }

    p = virConfGetValue (conf, "cgroup_device_acl");
    CHECK_TYPE ("cgroup_device_acl", VIR_CONF_LIST);
    if (p) {
        int len = 0;
        virConfValuePtr pp;
        for (pp = p->list; pp; pp = pp->next)
            len++;
        if (VIR_ALLOC_N(driver->cgroupDeviceACL, 1+len) < 0) {
346
            virReportOOMError();
347 348 349 350 351
            virConfFree(conf);
            return -1;
        }
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
352
                VIR_ERROR0(_("cgroup_device_acl must be a list of strings"));
353 354 355 356 357
                virConfFree(conf);
                return -1;
            }
            driver->cgroupDeviceACL[i] = strdup (pp->str);
            if (driver->cgroupDeviceACL[i] == NULL) {
358
                virReportOOMError();
359 360 361 362 363 364 365 366
                virConfFree(conf);
                return -1;
            }

        }
        driver->cgroupDeviceACL[i] = NULL;
    }

367 368 369 370 371
    p = virConfGetValue (conf, "save_image_format");
    CHECK_TYPE ("save_image_format", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->saveImageFormat);
        if (!(driver->saveImageFormat = strdup(p->str))) {
372
            virReportOOMError();
373 374 375 376 377
            virConfFree(conf);
            return -1;
        }
    }

378 379 380 381 382 383 384 385 386 387 388
    p = virConfGetValue (conf, "dump_image_format");
    CHECK_TYPE ("dump_image_format", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->dumpImageFormat);
        if (!(driver->dumpImageFormat = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

389 390 391 392 393
     p = virConfGetValue (conf, "hugetlbfs_mount");
     CHECK_TYPE ("hugetlbfs_mount", VIR_CONF_STRING);
     if (p && p->str) {
         VIR_FREE(driver->hugetlbfs_mount);
         if (!(driver->hugetlbfs_mount = strdup(p->str))) {
394
             virReportOOMError();
395 396 397 398 399
             virConfFree(conf);
             return -1;
         }
     }

400 401
    p = virConfGetValue (conf, "mac_filter");
    CHECK_TYPE ("mac_filter", VIR_CONF_LONG);
402
    if (p && p->l) {
403 404 405
        driver->macFilter = p->l;
        if (!(driver->ebtables = ebtablesContextNew("qemu"))) {
            driver->macFilter = 0;
406
            virReportSystemError(errno,
S
Stefan Berger 已提交
407
                                 _("failed to enable mac filter in '%s'"),
408 409 410 411
                                 __FILE__);
        }

        if ((errno = networkDisableAllFrames(driver))) {
412
            virReportSystemError(errno,
413 414 415 416 417
                         _("failed to add rule to drop all frames in '%s'"),
                                 __FILE__);
        }
    }

418 419 420 421
    p = virConfGetValue (conf, "relaxed_acs_check");
    CHECK_TYPE ("relaxed_acs_check", VIR_CONF_LONG);
    if (p) driver->relaxedACS = p->l;

422 423 424 425
    p = virConfGetValue (conf, "vnc_allow_host_audio");
    CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG);
    if (p) driver->vncAllowHostAudio = p->l;

426 427 428 429
    p = virConfGetValue (conf, "clear_emulator_capabilities");
    CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG);
    if (p) driver->clearEmulatorCapabilities = p->l;

430 431 432 433
    p = virConfGetValue (conf, "allow_disk_format_probing");
    CHECK_TYPE ("allow_disk_format_probing", VIR_CONF_LONG);
    if (p) driver->allowDiskFormatProbing = p->l;

434 435 436 437
    p = virConfGetValue (conf, "set_process_name");
    CHECK_TYPE ("set_process_name", VIR_CONF_LONG);
    if (p) driver->setProcessName = p->l;

D
Daniel P. Berrange 已提交
438 439 440 441
    virConfFree (conf);
    return 0;
}

442 443 444 445 446 447 448 449 450
struct qemu_feature_flags {
    const char *name;
    const int default_on;
    const int toggle;
};

struct qemu_arch_info {
    const char *arch;
    int wordsize;
M
Mark McLoughlin 已提交
451
    const char *machine;
452
    const char *binary;
453
    const char *altbinary;
454 455
    const struct qemu_feature_flags *flags;
    int nflags;
D
Daniel P. Berrange 已提交
456 457
};

458
/* Feature flags for the architecture info */
J
Jim Meyering 已提交
459
static const struct qemu_feature_flags const arch_info_i686_flags [] = {
460 461
    { "pae",  1, 0 },
    { "nonpae",  1, 0 },
462 463 464 465
    { "acpi", 1, 1 },
    { "apic", 1, 0 },
};

J
Jim Meyering 已提交
466
static const struct qemu_feature_flags const arch_info_x86_64_flags [] = {
467 468 469 470
    { "acpi", 1, 1 },
    { "apic", 1, 0 },
};

D
Daniel P. Berrange 已提交
471
/* The archicture tables for supported QEMU archs */
472
static const struct qemu_arch_info const arch_info_hvm[] = {
473 474 475
    {  "i686",   32, NULL, "qemu",
       "qemu-system-x86_64", arch_info_i686_flags, 4 },
    {  "x86_64", 64, NULL, "qemu-system-x86_64",
M
Mark McLoughlin 已提交
476
       NULL, arch_info_x86_64_flags, 2 },
477 478 479 480 481
    {  "arm",    32, NULL, "qemu-system-arm",    NULL, NULL, 0 },
    {  "mips",   32, NULL, "qemu-system-mips",   NULL, NULL, 0 },
    {  "mipsel", 32, NULL, "qemu-system-mipsel", NULL, NULL, 0 },
    {  "sparc",  32, NULL, "qemu-system-sparc",  NULL, NULL, 0 },
    {  "ppc",    32, NULL, "qemu-system-ppc",    NULL, NULL, 0 },
D
Dustin Xiong 已提交
482
    {  "itanium", 64, NULL, "qemu-system-ia64",  NULL, NULL, 0 },
483
    {  "s390x",  64, NULL, "qemu-system-s390x",  NULL, NULL, 0 },
D
Daniel P. Berrange 已提交
484 485
};

486
static const struct qemu_arch_info const arch_info_xen[] = {
487 488
    {  "i686",   32, "xenner", "xenner", NULL, arch_info_i686_flags, 4 },
    {  "x86_64", 64, "xenner", "xenner", NULL, arch_info_x86_64_flags, 2 },
489
};
D
Daniel P. Berrange 已提交
490

M
Mark McLoughlin 已提交
491 492

/* Format is:
493
 * <machine> <desc> [(default)|(alias of <canonical>)]
M
Mark McLoughlin 已提交
494 495 496
 */
static int
qemudParseMachineTypesStr(const char *output,
497
                          virCapsGuestMachinePtr **machines,
M
Mark McLoughlin 已提交
498 499 500 501
                          int *nmachines)
{
    const char *p = output;
    const char *next;
502 503
    virCapsGuestMachinePtr *list = NULL;
    int nitems = 0;
M
Mark McLoughlin 已提交
504 505 506

    do {
        const char *t;
507
        virCapsGuestMachinePtr machine;
M
Mark McLoughlin 已提交
508 509 510 511 512 513 514 515 516 517

        if ((next = strchr(p, '\n')))
            ++next;

        if (STRPREFIX(p, "Supported machines are:"))
            continue;

        if (!(t = strchr(p, ' ')) || (next && t >= next))
            continue;

518
        if (VIR_ALLOC(machine) < 0)
519
            goto no_memory;
M
Mark McLoughlin 已提交
520

521 522
        if (!(machine->name = strndup(p, t - p))) {
            VIR_FREE(machine);
523
            goto no_memory;
524 525
        }

M
Mark McLoughlin 已提交
526
        if (VIR_REALLOC_N(list, nitems + 1) < 0) {
527
            VIR_FREE(machine->name);
M
Mark McLoughlin 已提交
528
            VIR_FREE(machine);
529
            goto no_memory;
M
Mark McLoughlin 已提交
530 531 532 533 534 535 536 537 538 539 540
        }

        p = t;
        if (!(t = strstr(p, "(default)")) || (next && t >= next)) {
            list[nitems++] = machine;
        } else {
            /* put the default first in the list */
            memmove(list + 1, list, sizeof(*list) * nitems);
            list[0] = machine;
            nitems++;
        }
541 542 543 544 545 546 547

        if ((t = strstr(p, "(alias of ")) && (!next || t < next)) {
            p = t + strlen("(alias of ");
            if (!(t = strchr(p, ')')) || (next && t >= next))
                continue;

            if (!(machine->canonical = strndup(p, t - p)))
548
                goto no_memory;
549
        }
M
Mark McLoughlin 已提交
550 551 552 553 554 555 556
    } while ((p = next));

    *machines = list;
    *nmachines = nitems;

    return 0;

557
  no_memory:
558
    virReportOOMError();
559
    virCapabilitiesFreeMachines(list, nitems);
M
Mark McLoughlin 已提交
560 561 562
    return -1;
}

563
int
M
Mark McLoughlin 已提交
564
qemudProbeMachineTypes(const char *binary,
565
                       virCapsGuestMachinePtr **machines,
M
Mark McLoughlin 已提交
566 567 568 569 570 571 572 573 574 575
                       int *nmachines)
{
    const char *const qemuarg[] = { binary, "-M", "?", NULL };
    const char *const qemuenv[] = { "LC_ALL=C", NULL };
    char *output;
    enum { MAX_MACHINES_OUTPUT_SIZE = 1024*4 };
    pid_t child;
    int newstdout = -1, len;
    int ret = -1, status;

576
    if (virExec(qemuarg, qemuenv, NULL,
M
Mark McLoughlin 已提交
577 578 579 580 581
                &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
        return -1;

    len = virFileReadLimFD(newstdout, MAX_MACHINES_OUTPUT_SIZE, &output);
    if (len < 0) {
582
        virReportSystemError(errno, "%s",
M
Mark McLoughlin 已提交
583 584 585 586 587 588 589 590 591 592 593 594
                             _("Unable to read 'qemu -M ?' output"));
        goto cleanup;
    }

    if (qemudParseMachineTypesStr(output, machines, nmachines) < 0)
        goto cleanup2;

    ret = 0;

cleanup2:
    VIR_FREE(output);
cleanup:
595
    if (VIR_CLOSE(newstdout) < 0)
M
Mark McLoughlin 已提交
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
        ret = -1;

rewait:
    if (waitpid(child, &status, 0) != child) {
        if (errno == EINTR)
            goto rewait;

        VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
                  WEXITSTATUS(status), (unsigned long)child);
        ret = -1;
    }
    /* Check & log unexpected exit status, but don't fail,
     * as there's really no need to throw an error if we did
     * actually read a valid version number above */
    if (WEXITSTATUS(status) != 0) {
611
        VIR_WARN("Unexpected exit status '%d', qemu probably failed",
M
Mark McLoughlin 已提交
612 613 614 615 616 617
                 WEXITSTATUS(status));
    }

    return ret;
}

M
Mark McLoughlin 已提交
618 619 620 621 622 623 624 625 626 627
static int
qemudGetOldMachinesFromInfo(virCapsGuestDomainInfoPtr info,
                            const char *emulator,
                            time_t emulator_mtime,
                            virCapsGuestMachinePtr **machines,
                            int *nmachines)
{
    virCapsGuestMachinePtr *list;
    int i;

628 629 630
    if (!info->nmachines)
        return 0;

M
Mark McLoughlin 已提交
631 632 633 634 635 636 637 638 639
    if (!info->emulator || !STREQ(emulator, info->emulator))
        return 0;

    if (emulator_mtime != info->emulator_mtime) {
        VIR_DEBUG("mtime on %s has changed, refreshing machine types",
                  info->emulator);
        return 0;
    }

640
    if (VIR_ALLOC_N(list, info->nmachines) < 0) {
641
        virReportOOMError();
M
Mark McLoughlin 已提交
642
        return 0;
643
    }
M
Mark McLoughlin 已提交
644 645 646

    for (i = 0; i < info->nmachines; i++) {
        if (VIR_ALLOC(list[i]) < 0) {
647
            goto no_memory;
M
Mark McLoughlin 已提交
648 649 650
        }
        if (info->machines[i]->name &&
            !(list[i]->name = strdup(info->machines[i]->name))) {
651
            goto no_memory;
M
Mark McLoughlin 已提交
652 653 654
        }
        if (info->machines[i]->canonical &&
            !(list[i]->canonical = strdup(info->machines[i]->canonical))) {
655
            goto no_memory;
M
Mark McLoughlin 已提交
656 657 658 659 660 661 662
        }
    }

    *machines = list;
    *nmachines = info->nmachines;

    return 1;
663 664

  no_memory:
665
    virReportOOMError();
666 667
    virCapabilitiesFreeMachines(list, info->nmachines);
    return 0;
M
Mark McLoughlin 已提交
668 669
}

670 671 672 673 674 675 676 677 678 679 680 681 682 683
static int
qemudGetOldMachines(const char *ostype,
                    const char *arch,
                    int wordsize,
                    const char *emulator,
                    time_t emulator_mtime,
                    virCapsPtr old_caps,
                    virCapsGuestMachinePtr **machines,
                    int *nmachines)
{
    int i;

    for (i = 0; i < old_caps->nguests; i++) {
        virCapsGuestPtr guest = old_caps->guests[i];
684
        int j;
685 686 687

        if (!STREQ(ostype, guest->ostype) ||
            !STREQ(arch, guest->arch.name) ||
M
Mark McLoughlin 已提交
688
            wordsize != guest->arch.wordsize)
689 690
            continue;

691 692 693 694 695 696 697 698 699
        for (j = 0; j < guest->arch.ndomains; j++) {
            virCapsGuestDomainPtr dom = guest->arch.domains[j];

            if (qemudGetOldMachinesFromInfo(&dom->info,
                                            emulator, emulator_mtime,
                                            machines, nmachines))
                return 1;
        }

M
Mark McLoughlin 已提交
700 701 702 703
        if (qemudGetOldMachinesFromInfo(&guest->arch.defaultInfo,
                                        emulator, emulator_mtime,
                                        machines, nmachines))
            return 1;
704 705 706 707 708
    }

    return 0;
}

709 710 711 712 713 714 715

typedef int
(*qemudParseCPUModels)(const char *output,
                       unsigned int *retcount,
                       const char ***retcpus);

/* Format:
J
Jiri Denemark 已提交
716 717 718
 *      <arch> <model>
 * qemu-0.13 encloses some model names in []:
 *      <arch> [<model>]
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
 */
static int
qemudParseX86Models(const char *output,
                    unsigned int *retcount,
                    const char ***retcpus)
{
    const char *p = output;
    const char *next;
    unsigned int count = 0;
    const char **cpus = NULL;
    int i;

    do {
        const char *t;

        if ((next = strchr(p, '\n')))
            next++;

        if (!(t = strchr(p, ' ')) || (next && t >= next))
            continue;

        if (!STRPREFIX(p, "x86"))
            continue;

        p = t;
        while (*p == ' ')
            p++;

        if (*p == '\0' || *p == '\n')
            continue;

        if (retcpus) {
J
Jiri Denemark 已提交
751 752
            unsigned int len;

753 754 755 756
            if (VIR_REALLOC_N(cpus, count + 1) < 0)
                goto error;

            if (next)
J
Jiri Denemark 已提交
757
                len = next - p - 1;
758
            else
J
Jiri Denemark 已提交
759 760 761 762 763 764
                len = strlen(p);

            if (len > 2 && *p == '[' && p[len - 1] == ']') {
                p++;
                len -= 2;
            }
765

J
Jiri Denemark 已提交
766
            if (!(cpus[count] = strndup(p, len)))
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
                goto error;
        }
        count++;
    } while ((p = next));

    if (retcount)
        *retcount = count;
    if (retcpus)
        *retcpus = cpus;

    return 0;

error:
    if (cpus) {
        for (i = 0; i < count; i++)
            VIR_FREE(cpus[i]);
    }
    VIR_FREE(cpus);

    return -1;
}


int
qemudProbeCPUModels(const char *qemu,
792
                    unsigned long long qemuCmdFlags,
793 794 795 796
                    const char *arch,
                    unsigned int *count,
                    const char ***cpus)
{
797 798 799 800 801 802
    const char *const qemuarg[] = {
        qemu,
        "-cpu", "?",
        (qemuCmdFlags & QEMUD_CMD_FLAG_NODEFCONFIG) ? "-nodefconfig" : NULL,
        NULL
    };
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
    const char *const qemuenv[] = { "LC_ALL=C", NULL };
    enum { MAX_MACHINES_OUTPUT_SIZE = 1024*4 };
    char *output = NULL;
    int newstdout = -1;
    int ret = -1;
    pid_t child;
    int status;
    int len;
    qemudParseCPUModels parse;

    if (count)
        *count = 0;
    if (cpus)
        *cpus = NULL;

    if (STREQ(arch, "i686") || STREQ(arch, "x86_64"))
        parse = qemudParseX86Models;
    else {
821
        VIR_DEBUG("don't know how to parse %s CPU models", arch);
822 823 824
        return 0;
    }

825
    if (virExec(qemuarg, qemuenv, NULL,
826 827 828 829 830
                &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
        return -1;

    len = virFileReadLimFD(newstdout, MAX_MACHINES_OUTPUT_SIZE, &output);
    if (len < 0) {
831
        virReportSystemError(errno, "%s",
832 833 834 835 836
                             _("Unable to read QEMU supported CPU models"));
        goto cleanup;
    }

    if (parse(output, count, cpus) < 0) {
837
        virReportOOMError();
838 839 840 841 842 843 844
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FREE(output);
845
    if (VIR_CLOSE(newstdout) < 0)
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
        ret = -1;

rewait:
    if (waitpid(child, &status, 0) != child) {
        if (errno == EINTR)
            goto rewait;

        VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
                  WEXITSTATUS(status), (unsigned long)child);
        ret = -1;
    }
    /* Check & log unexpected exit status, but don't fail,
     * as there's really no need to throw an error if we did
     * actually read a valid version number above */
    if (WEXITSTATUS(status) != 0) {
861
        VIR_WARN("Unexpected exit status '%d', qemu probably failed",
862 863 864 865 866 867 868
                 WEXITSTATUS(status));
    }

    return ret;
}


869 870
static int
qemudCapsInitGuest(virCapsPtr caps,
871
                   virCapsPtr old_caps,
872 873 874 875
                   const char *hostmachine,
                   const struct qemu_arch_info *info,
                   int hvm) {
    virCapsGuestPtr guest;
876 877 878
    int i;
    int haskvm = 0;
    int haskqemu = 0;
879 880
    char *kvmbin = NULL;
    char *binary = NULL;
881
    time_t binary_mtime;
882
    virCapsGuestMachinePtr *machines = NULL;
M
Mark McLoughlin 已提交
883
    int nmachines = 0;
884
    struct stat st;
885
    unsigned int ncpus;
886
    int ret = -1;
887

888 889 890
    /* Check for existance of base emulator, or alternate base
     * which can be used with magic cpu choice
     */
891 892 893 894 895 896 897 898 899
    binary = virFindFileInPath(info->binary);

    if (binary == NULL || access(binary, X_OK) != 0) {
        VIR_FREE(binary);
        binary = virFindFileInPath(info->altbinary);

        if (binary != NULL && access(binary, X_OK) != 0)
            VIR_FREE(binary);
    }
900

901 902 903 904 905 906 907 908
    /* Can use acceleration for KVM/KQEMU if
     *  - host & guest arches match
     * Or
     *  - hostarch is x86_64 and guest arch is i686
     * The latter simply needs "-cpu qemu32"
     */
    if (STREQ(info->arch, hostmachine) ||
        (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) {
909
        if (access("/dev/kvm", F_OK) == 0) {
910 911
            const char *const kvmbins[] = { "/usr/libexec/qemu-kvm", /* RHEL */
                                            "qemu-kvm", /* Fedora */
912 913 914 915 916 917 918 919 920
                                            "kvm" }; /* Upstream .spec */

            for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) {
                kvmbin = virFindFileInPath(kvmbins[i]);

                if (kvmbin == NULL || access(kvmbin, X_OK) != 0) {
                    VIR_FREE(kvmbin);
                    continue;
                }
921

922
                haskvm = 1;
923 924
                if (!binary)
                    binary = kvmbin;
925

926 927 928
                break;
            }
        }
929 930 931

        if (access("/dev/kqemu", F_OK) == 0)
            haskqemu = 1;
932 933
    }

934
    if (!binary)
935
        return 0;
D
Daniel P. Berrange 已提交
936

937 938 939 940
    if (stat(binary, &st) == 0) {
        binary_mtime = st.st_mtime;
    } else {
        char ebuf[1024];
941
        VIR_WARN("Failed to stat %s, most peculiar : %s",
942 943 944 945
                 binary, virStrerror(errno, ebuf, sizeof(ebuf)));
        binary_mtime = 0;
    }

M
Mark McLoughlin 已提交
946
    if (info->machine) {
947 948
        virCapsGuestMachinePtr machine;

949
        if (VIR_ALLOC(machine) < 0) {
950
            goto no_memory;
951
        }
M
Mark McLoughlin 已提交
952

953 954
        if (!(machine->name = strdup(info->machine))) {
            VIR_FREE(machine);
955
            goto no_memory;
956
        }
M
Mark McLoughlin 已提交
957

M
Matthias Bolte 已提交
958 959
        nmachines = 1;

M
Mark McLoughlin 已提交
960
        if (VIR_ALLOC_N(machines, nmachines) < 0) {
961
            VIR_FREE(machine->name);
M
Mark McLoughlin 已提交
962
            VIR_FREE(machine);
963
            goto no_memory;
M
Mark McLoughlin 已提交
964 965 966
        }

        machines[0] = machine;
967 968 969 970 971 972 973 974
    } else {
        int probe = 1;
        if (old_caps && binary_mtime)
            probe = !qemudGetOldMachines(hvm ? "hvm" : "xen", info->arch,
                                         info->wordsize, binary, binary_mtime,
                                         old_caps, &machines, &nmachines);
        if (probe &&
            qemudProbeMachineTypes(binary, &machines, &nmachines) < 0)
975
            goto error;
976
    }
M
Mark McLoughlin 已提交
977

978 979
    /* We register kvm as the base emulator too, since we can
     * just give -no-kvm to disable acceleration if required */
980 981 982 983
    if ((guest = virCapabilitiesAddGuest(caps,
                                         hvm ? "hvm" : "xen",
                                         info->arch,
                                         info->wordsize,
984
                                         binary,
985
                                         NULL,
M
Mark McLoughlin 已提交
986
                                         nmachines,
987 988 989 990 991
                                         machines)) == NULL)
        goto error;

    machines = NULL;
    nmachines = 0;
M
Mark McLoughlin 已提交
992

993 994
    guest->arch.defaultInfo.emulator_mtime = binary_mtime;

995
    if (caps->host.cpu &&
996
        qemudProbeCPUModels(binary, 0, info->arch, &ncpus, NULL) == 0 &&
997 998
        ncpus > 0 &&
        !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0))
999
        goto error;
1000

1001
    if (hvm) {
1002
        if (virCapabilitiesAddGuestDomain(guest,
1003 1004 1005 1006 1007
                                          "qemu",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
1008
            goto error;
D
Daniel P. Berrange 已提交
1009

1010 1011 1012 1013 1014 1015 1016
        if (haskqemu &&
            virCapabilitiesAddGuestDomain(guest,
                                          "kqemu",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
1017
            goto error;
1018

1019 1020 1021 1022 1023 1024 1025
        if (haskvm) {
            virCapsGuestDomainPtr dom;

            if (stat(kvmbin, &st) == 0) {
                binary_mtime = st.st_mtime;
            } else {
                char ebuf[1024];
1026
                VIR_WARN("Failed to stat %s, most peculiar : %s",
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
                         binary, virStrerror(errno, ebuf, sizeof(ebuf)));
                binary_mtime = 0;
            }

            if (!STREQ(binary, kvmbin)) {
                int probe = 1;
                if (old_caps && binary_mtime)
                    probe = !qemudGetOldMachines("hvm", info->arch, info->wordsize,
                                                 kvmbin, binary_mtime,
                                                 old_caps, &machines, &nmachines);
                if (probe &&
                    qemudProbeMachineTypes(kvmbin, &machines, &nmachines) < 0)
1039
                    goto error;
1040 1041 1042 1043 1044 1045 1046 1047
            }

            if ((dom = virCapabilitiesAddGuestDomain(guest,
                                                     "kvm",
                                                     kvmbin,
                                                     NULL,
                                                     nmachines,
                                                     machines)) == NULL) {
1048
                goto error;
1049 1050
            }

1051 1052 1053
            machines = NULL;
            nmachines = 0;

1054 1055
            dom->info.emulator_mtime = binary_mtime;
        }
1056 1057 1058 1059 1060 1061 1062
    } else {
        if (virCapabilitiesAddGuestDomain(guest,
                                          "kvm",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
1063
            goto error;
1064
    }
D
Daniel P. Berrange 已提交
1065

1066 1067 1068 1069 1070 1071
    if (info->nflags) {
        for (i = 0 ; i < info->nflags ; i++) {
            if (virCapabilitiesAddGuestFeature(guest,
                                               info->flags[i].name,
                                               info->flags[i].default_on,
                                               info->flags[i].toggle) == NULL)
1072
                goto error;
D
Daniel P. Berrange 已提交
1073 1074 1075
        }
    }

1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
    ret = 0;

cleanup:
    if (binary == kvmbin) {
        /* don't double free */
        VIR_FREE(binary);
    } else {
        VIR_FREE(binary);
        VIR_FREE(kvmbin);
    }

    return ret;

no_memory:
1090
    virReportOOMError();
1091 1092 1093 1094 1095

error:
    virCapabilitiesFreeMachines(machines, nmachines);

    goto cleanup;
D
Daniel P. Berrange 已提交
1096 1097
}

1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109

static int
qemudCapsInitCPU(virCapsPtr caps,
                 const char *arch)
{
    virCPUDefPtr cpu = NULL;
    union cpuData *data = NULL;
    virNodeInfo nodeinfo;
    int ret = -1;

    if (VIR_ALLOC(cpu) < 0
        || !(cpu->arch = strdup(arch))) {
1110
        virReportOOMError();
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
        goto error;
    }

    if (nodeGetInfo(NULL, &nodeinfo))
        goto error;

    cpu->type = VIR_CPU_TYPE_HOST;
    cpu->sockets = nodeinfo.sockets;
    cpu->cores = nodeinfo.cores;
    cpu->threads = nodeinfo.threads;

1122
    if (!(data = cpuNodeData(arch))
1123
        || cpuDecode(cpu, data, NULL, 0, NULL) < 0)
1124 1125 1126 1127 1128 1129 1130
        goto error;

    caps->host.cpu = cpu;

    ret = 0;

cleanup:
1131
    cpuDataFree(arch, data);
1132 1133 1134 1135 1136 1137 1138 1139 1140

    return ret;

error:
    virCPUDefFree(cpu);
    goto cleanup;
}


1141
virCapsPtr qemudCapsInit(virCapsPtr old_caps) {
1142 1143 1144
    struct utsname utsname;
    virCapsPtr caps;
    int i;
1145
    char *xenner = NULL;
D
Daniel P. Berrange 已提交
1146

1147 1148 1149 1150
    /* Really, this never fails - look at the man-page. */
    uname (&utsname);

    if ((caps = virCapabilitiesNew(utsname.machine,
1151
                                   1, 1)) == NULL)
1152 1153
        goto no_memory;

1154 1155 1156
    /* Using KVM's mac prefix for QEMU too */
    virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x52, 0x54, 0x00 });

1157 1158 1159 1160 1161 1162 1163 1164
    /* Some machines have problematic NUMA toplogy causing
     * unexpected failures. We don't want to break the QEMU
     * driver in this scenario, so log errors & carry on
     */
    if (nodeCapsInitNUMA(caps) < 0) {
        virCapabilitiesFreeNUMAInfo(caps);
        VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
    }
1165

1166 1167 1168 1169 1170 1171 1172 1173 1174
    if (old_caps == NULL || old_caps->host.cpu == NULL) {
        if (qemudCapsInitCPU(caps, utsname.machine) < 0)
            VIR_WARN0("Failed to get host CPU");
    }
    else {
        caps->host.cpu = old_caps->host.cpu;
        old_caps->host.cpu = NULL;
    }

1175 1176 1177
    virCapabilitiesAddHostMigrateTransport(caps,
                                           "tcp");

1178
    /* First the pure HVM guests */
J
Jim Meyering 已提交
1179
    for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++)
1180
        if (qemudCapsInitGuest(caps, old_caps,
1181 1182 1183 1184
                               utsname.machine,
                               &arch_info_hvm[i], 1) < 0)
            goto no_memory;

1185
    /* Then possibly the Xen paravirt guests (ie Xenner */
1186 1187 1188
    xenner = virFindFileInPath("xenner");

    if (xenner != NULL && access(xenner, X_OK) == 0 &&
1189
        access("/dev/kvm", F_OK) == 0) {
J
Jim Meyering 已提交
1190
        for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_xen) ; i++)
1191 1192 1193 1194
            /* Allow Xen 32-on-32, 32-on-64 and 64-on-64 */
            if (STREQ(arch_info_xen[i].arch, utsname.machine) ||
                (STREQ(utsname.machine, "x86_64") &&
                 STREQ(arch_info_xen[i].arch, "i686"))) {
1195
                if (qemudCapsInitGuest(caps, old_caps,
1196 1197 1198 1199
                                       utsname.machine,
                                       &arch_info_xen[i], 0) < 0)
                    goto no_memory;
            }
D
Daniel P. Berrange 已提交
1200 1201
    }

1202 1203
    VIR_FREE(xenner);

1204 1205 1206
    /* QEMU Requires an emulator in the XML */
    virCapabilitiesSetEmulatorRequired(caps);

1207 1208
    caps->defaultConsoleTargetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;

1209 1210 1211
    return caps;

 no_memory:
1212
    VIR_FREE(xenner);
1213 1214
    virCapabilitiesFree(caps);
    return NULL;
D
Daniel P. Berrange 已提交
1215 1216
}

1217 1218 1219 1220
static unsigned long long qemudComputeCmdFlags(const char *help,
                                               unsigned int version,
                                               unsigned int is_kvm,
                                               unsigned int kvm_version)
M
Mark McLoughlin 已提交
1221
{
1222
    unsigned long long flags = 0;
1223
    const char *p;
1224 1225 1226

    if (strstr(help, "-no-kqemu"))
        flags |= QEMUD_CMD_FLAG_KQEMU;
1227 1228
    if (strstr(help, "-enable-kqemu"))
        flags |= QEMUD_CMD_FLAG_ENABLE_KQEMU;
1229 1230
    if (strstr(help, "-no-kvm"))
        flags |= QEMUD_CMD_FLAG_KVM;
1231 1232
    if (strstr(help, "-enable-kvm"))
        flags |= QEMUD_CMD_FLAG_ENABLE_KVM;
1233 1234
    if (strstr(help, "-no-reboot"))
        flags |= QEMUD_CMD_FLAG_NO_REBOOT;
1235
    if (strstr(help, "-name")) {
1236
        flags |= QEMUD_CMD_FLAG_NAME;
1237 1238 1239
        if (strstr(help, ",process="))
            flags |= QEMUD_CMD_FLAG_NAME_PROCESS;
    }
1240 1241
    if (strstr(help, "-uuid"))
        flags |= QEMUD_CMD_FLAG_UUID;
1242 1243 1244
    if (strstr(help, "-xen-domid"))
        flags |= QEMUD_CMD_FLAG_XEN_DOMID;
    else if (strstr(help, "-domid"))
1245
        flags |= QEMUD_CMD_FLAG_DOMID;
1246
    if (strstr(help, "-drive")) {
1247
        flags |= QEMUD_CMD_FLAG_DRIVE;
1248 1249
        if (strstr(help, "cache=") &&
            !strstr(help, "cache=on|off"))
1250
            flags |= QEMUD_CMD_FLAG_DRIVE_CACHE_V2;
1251 1252
        if (strstr(help, "format="))
            flags |= QEMUD_CMD_FLAG_DRIVE_FORMAT;
1253 1254
        if (strstr(help, "readonly="))
            flags |= QEMUD_CMD_FLAG_DRIVE_READONLY;
1255
    }
1256 1257 1258
    if ((p = strstr(help, "-vga")) && !strstr(help, "-std-vga")) {
        const char *nl = strstr(p, "\n");

1259
        flags |= QEMUD_CMD_FLAG_VGA;
1260

1261
        if (strstr(p, "|qxl"))
1262
            flags |= QEMUD_CMD_FLAG_VGA_QXL;
1263 1264
        if ((p = strstr(p, "|none")) && p < nl)
            flags |= QEMUD_CMD_FLAG_VGA_NONE;
1265
    }
1266 1267
    if (strstr(help, "-spice"))
        flags |= QEMUD_CMD_FLAG_SPICE;
1268 1269
    if (strstr(help, "boot=on"))
        flags |= QEMUD_CMD_FLAG_DRIVE_BOOT;
1270 1271
    if (strstr(help, "serial=s"))
        flags |= QEMUD_CMD_FLAG_DRIVE_SERIAL;
1272 1273
    if (strstr(help, "-pcidevice"))
        flags |= QEMUD_CMD_FLAG_PCIDEVICE;
1274 1275
    if (strstr(help, "-mem-path"))
        flags |= QEMUD_CMD_FLAG_MEM_PATH;
1276 1277
    if (strstr(help, "-chardev"))
        flags |= QEMUD_CMD_FLAG_CHARDEV;
1278 1279
    if (strstr(help, "-balloon"))
        flags |= QEMUD_CMD_FLAG_BALLOON;
1280
    if (strstr(help, "-device")) {
1281
        flags |= QEMUD_CMD_FLAG_DEVICE;
1282 1283 1284 1285 1286 1287
        /*
         * When -device was introduced, qemu already supported drive's
         * readonly option but didn't advertise that.
         */
        flags |= QEMUD_CMD_FLAG_DRIVE_READONLY;
    }
1288 1289
    if (strstr(help, "-nodefconfig"))
        flags |= QEMUD_CMD_FLAG_NODEFCONFIG;
1290 1291 1292
    /* The trailing ' ' is important to avoid a bogus match */
    if (strstr(help, "-rtc "))
        flags |= QEMUD_CMD_FLAG_RTC;
1293 1294 1295 1296 1297 1298 1299 1300 1301
    /* to wit */
    if (strstr(help, "-rtc-td-hack"))
        flags |= QEMUD_CMD_FLAG_RTC_TD_HACK;
    if (strstr(help, "-no-hpet"))
        flags |= QEMUD_CMD_FLAG_NO_HPET;
    if (strstr(help, "-no-kvm-pit-reinjection"))
        flags |= QEMUD_CMD_FLAG_NO_KVM_PIT;
    if (strstr(help, "-tdf"))
        flags |= QEMUD_CMD_FLAG_TDF;
D
Daniel P. Berrange 已提交
1302 1303
    if (strstr(help, "-enable-nesting"))
        flags |= QEMUD_CMD_FLAG_NESTING;
1304 1305
    if (strstr(help, ",menu=on"))
        flags |= QEMUD_CMD_FLAG_BOOT_MENU;
1306 1307
    if (strstr(help, "-fsdev"))
        flags |= QEMUD_CMD_FLAG_FSDEV;
1308 1309
    if (strstr(help, "-smbios type"))
        flags |= QEMUD_CMD_FLAG_SMBIOS_TYPE;
1310

1311 1312 1313 1314 1315 1316 1317
    if (strstr(help, "-netdev")) {
        /* Disable -netdev on 0.12 since although it exists,
         * the corresponding netdev_add/remove monitor commands
         * do not, and we need them to be able todo hotplug */
        if (version >= 13000)
            flags |= QEMUD_CMD_FLAG_NETDEV;
    }
1318

1319 1320
    if (strstr(help, "-sdl"))
        flags |= QEMUD_CMD_FLAG_SDL;
1321 1322 1323 1324
    if (strstr(help, "cores=") &&
        strstr(help, "threads=") &&
        strstr(help, "sockets="))
        flags |= QEMUD_CMD_FLAG_SMP_TOPOLOGY;
1325

1326 1327
    if (version >= 9000)
        flags |= QEMUD_CMD_FLAG_VNC_COLON;
M
Mark McLoughlin 已提交
1328 1329

    if (is_kvm && (version >= 10000 || kvm_version >= 74))
1330
        flags |= QEMUD_CMD_FLAG_VNET_HDR;
1331

1332 1333 1334 1335
    if (is_kvm && strstr(help, ",vhost=")) {
        flags |= QEMUD_CMD_FLAG_VNET_HOST;
    }

1336 1337
    /*
     * Handling of -incoming arg with varying features
1338 1339
     *  -incoming tcp    (kvm >= 79, qemu >= 0.10.0)
     *  -incoming exec   (kvm >= 80, qemu >= 0.10.0)
1340 1341 1342 1343 1344 1345
     *  -incoming stdio  (all earlier kvm)
     *
     * NB, there was a pre-kvm-79 'tcp' support, but it
     * was broken, because it blocked the monitor console
     * while waiting for data, so pretend it doesn't exist
     */
M
Mark McLoughlin 已提交
1346 1347 1348
    if (version >= 10000) {
        flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
        flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
1349 1350
        if (version >= 12000)
            flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX;
M
Mark McLoughlin 已提交
1351
    } else if (kvm_version >= 79) {
1352 1353 1354 1355 1356 1357 1358
        flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
        if (kvm_version >= 80)
            flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
    } else if (kvm_version > 0) {
        flags |= QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO;
    }

1359 1360 1361
    if (version >= 10000)
        flags |= QEMUD_CMD_FLAG_0_10;

1362 1363 1364 1365 1366 1367 1368
    /* While JSON mode was available in 0.12.0, it was too
     * incomplete to contemplate using. The 0.13.0 release
     * is good enough to use, even though it lacks one or
     * two features. The benefits of JSON mode now outweigh
     * the downside.
     */
     if (version >= 13000)
1369
        flags |= QEMUD_CMD_FLAG_MONITOR_JSON;
D
Daniel P. Berrange 已提交
1370

M
Mark McLoughlin 已提交
1371 1372 1373 1374 1375
    return flags;
}

/* We parse the output of 'qemu -help' to get the QEMU
 * version number. The first bit is easy, just parse
1376 1377 1378
 * 'QEMU PC emulator version x.y.z'
 * or
 * 'QEMU emulator version x.y.z'.
M
Mark McLoughlin 已提交
1379
 *
M
Mark McLoughlin 已提交
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
 * With qemu-kvm, however, that is followed by a string
 * in parenthesis as follows:
 *  - qemu-kvm-x.y.z in stable releases
 *  - kvm-XX for kvm versions up to kvm-85
 *  - qemu-kvm-devel-XX for kvm version kvm-86 and later
 *
 * For qemu-kvm versions before 0.10.z, we need to detect
 * the KVM version number for some features. With 0.10.z
 * and later, we just need the QEMU version number and
 * whether it is KVM QEMU or mainline QEMU.
M
Mark McLoughlin 已提交
1390
 */
1391 1392
#define QEMU_VERSION_STR_1  "QEMU emulator version"
#define QEMU_VERSION_STR_2  "QEMU PC emulator version"
M
Mark McLoughlin 已提交
1393
#define QEMU_KVM_VER_PREFIX "(qemu-kvm-"
M
Mark McLoughlin 已提交
1394 1395 1396 1397
#define KVM_VER_PREFIX      "(kvm-"

#define SKIP_BLANKS(p) do { while ((*(p) == ' ') || (*(p) == '\t')) (p)++; } while (0)

1398 1399
int qemudParseHelpStr(const char *qemu,
                      const char *help,
1400
                      unsigned long long *flags,
1401 1402 1403
                      unsigned int *version,
                      unsigned int *is_kvm,
                      unsigned int *kvm_version)
M
Mark McLoughlin 已提交
1404 1405 1406 1407
{
    unsigned major, minor, micro;
    const char *p = help;

M
Mark McLoughlin 已提交
1408
    *flags = *version = *is_kvm = *kvm_version = 0;
M
Mark McLoughlin 已提交
1409

1410 1411 1412 1413 1414
    if (STRPREFIX(p, QEMU_VERSION_STR_1))
        p += strlen(QEMU_VERSION_STR_1);
    else if (STRPREFIX(p, QEMU_VERSION_STR_2))
        p += strlen(QEMU_VERSION_STR_2);
    else
M
Mark McLoughlin 已提交
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
        goto fail;

    SKIP_BLANKS(p);

    major = virParseNumber(&p);
    if (major == -1 || *p != '.')
        goto fail;

    ++p;

    minor = virParseNumber(&p);
1426
    if (minor == -1 || *p != '.')
M
Mark McLoughlin 已提交
1427 1428 1429 1430 1431
        goto fail;

    ++p;

    micro = virParseNumber(&p);
1432
    if (micro == -1)
M
Mark McLoughlin 已提交
1433 1434 1435 1436
        goto fail;

    SKIP_BLANKS(p);

M
Mark McLoughlin 已提交
1437 1438 1439 1440
    if (STRPREFIX(p, QEMU_KVM_VER_PREFIX)) {
        *is_kvm = 1;
        p += strlen(QEMU_KVM_VER_PREFIX);
    } else if (STRPREFIX(p, KVM_VER_PREFIX)) {
M
Mark McLoughlin 已提交
1441 1442
        int ret;

M
Mark McLoughlin 已提交
1443
        *is_kvm = 1;
M
Mark McLoughlin 已提交
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
        p += strlen(KVM_VER_PREFIX);

        ret = virParseNumber(&p);
        if (ret == -1)
            goto fail;

        *kvm_version = ret;
    }

    *version = (major * 1000 * 1000) + (minor * 1000) + micro;

M
Mark McLoughlin 已提交
1455
    *flags = qemudComputeCmdFlags(help, *version, *is_kvm, *kvm_version);
M
Mark McLoughlin 已提交
1456

1457 1458
    VIR_DEBUG("Version %u.%u.%u, cooked version %u, flags 0x%llx",
              major, minor, micro, *version, *flags);
M
Mark McLoughlin 已提交
1459
    if (*kvm_version)
1460
        VIR_DEBUG("KVM version %d detected", *kvm_version);
M
Mark McLoughlin 已提交
1461
    else if (*is_kvm)
1462
        VIR_DEBUG("qemu-kvm version %u.%u.%u detected", major, minor, micro);
M
Mark McLoughlin 已提交
1463 1464 1465 1466 1467 1468 1469 1470

    return 0;

fail:
    p = strchr(help, '\n');
    if (p)
        p = strndup(help, p - help);

1471
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
1472 1473
                    _("cannot parse %s version number in '%s'"),
                    qemu, p ? p : help);
M
Mark McLoughlin 已提交
1474 1475 1476 1477 1478 1479

    VIR_FREE(p);

    return -1;
}

1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
static void qemudParsePCIDeviceStrs(const char *qemu, unsigned long long *flags)
{
    const char *const qemuarg[] = { qemu, "-device", "pci-assign,?", NULL };
    const char *const qemuenv[] = { "LC_ALL=C", NULL };
    pid_t child;
    int status;
    int newstderr = -1;

    if (virExec(qemuarg, qemuenv, NULL,
                &child, -1, NULL, &newstderr, VIR_EXEC_CLEAR_CAPS) < 0)
        return;

    char *pciassign = NULL;
    enum { MAX_PCI_OUTPUT_SIZE = 1024*4 };
    int len = virFileReadLimFD(newstderr, MAX_PCI_OUTPUT_SIZE, &pciassign);
    if (len < 0) {
        virReportSystemError(errno,
                             _("Unable to read %s pci-assign device output"),
                             qemu);
        goto cleanup;
    }

    if (strstr(pciassign, "pci-assign.configfd"))
        *flags |= QEMUD_CMD_FLAG_PCI_CONFIGFD;

cleanup:
    VIR_FREE(pciassign);
1507
    VIR_FORCE_CLOSE(newstderr);
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
rewait:
    if (waitpid(child, &status, 0) != child) {
        if (errno == EINTR)
            goto rewait;

        VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
                  WEXITSTATUS(status), (unsigned long)child);
    }
    if (WEXITSTATUS(status) != 0) {
        VIR_WARN("Unexpected exit status '%d', qemu probably failed",
                 WEXITSTATUS(status));
    }
}

M
Mark McLoughlin 已提交
1522 1523
int qemudExtractVersionInfo(const char *qemu,
                            unsigned int *retversion,
1524
                            unsigned long long *retflags) {
M
Mark McLoughlin 已提交
1525 1526 1527 1528 1529
    const char *const qemuarg[] = { qemu, "-help", NULL };
    const char *const qemuenv[] = { "LC_ALL=C", NULL };
    pid_t child;
    int newstdout = -1;
    int ret = -1, status;
M
Mark McLoughlin 已提交
1530
    unsigned int version, is_kvm, kvm_version;
1531
    unsigned long long flags = 0;
M
Mark McLoughlin 已提交
1532 1533 1534 1535 1536 1537

    if (retflags)
        *retflags = 0;
    if (retversion)
        *retversion = 0;

E
Eric Blake 已提交
1538 1539 1540 1541 1542 1543 1544 1545 1546
    /* Make sure the binary we are about to try exec'ing exists.
     * Technically we could catch the exec() failure, but that's
     * in a sub-process so it's hard to feed back a useful error.
     */
    if (access(qemu, X_OK) < 0) {
        virReportSystemError(errno, _("Cannot find QEMU binary %s"), qemu);
        return -1;
    }

1547
    if (virExec(qemuarg, qemuenv, NULL,
1548
                &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
M
Mark McLoughlin 已提交
1549 1550 1551 1552 1553 1554
        return -1;

    char *help = NULL;
    enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
    int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
    if (len < 0) {
1555 1556
        virReportSystemError(errno,
                             _("Unable to read %s help output"), qemu);
M
Mark McLoughlin 已提交
1557 1558 1559
        goto cleanup2;
    }

1560 1561
    if (qemudParseHelpStr(qemu, help, &flags,
                          &version, &is_kvm, &kvm_version) == -1)
M
Mark McLoughlin 已提交
1562 1563
        goto cleanup2;

1564 1565 1566
    if (flags & QEMUD_CMD_FLAG_DEVICE)
        qemudParsePCIDeviceStrs(qemu, &flags);

1567 1568 1569 1570
    if (retversion)
        *retversion = version;
    if (retflags)
        *retflags = flags;
1571

1572
    ret = 0;
1573

1574
cleanup2:
1575
    VIR_FREE(help);
1576
    if (VIR_CLOSE(newstdout) < 0)
1577
        ret = -1;
1578

1579 1580 1581 1582 1583
rewait:
    if (waitpid(child, &status, 0) != child) {
        if (errno == EINTR)
            goto rewait;

1584 1585
        VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
                  WEXITSTATUS(status), (unsigned long)child);
1586 1587 1588 1589 1590 1591
        ret = -1;
    }
    /* Check & log unexpected exit status, but don't fail,
     * as there's really no need to throw an error if we did
     * actually read a valid version number above */
    if (WEXITSTATUS(status) != 0) {
1592
        VIR_WARN("Unexpected exit status '%d', qemu probably failed",
1593
                 WEXITSTATUS(status));
1594
    }
1595 1596

    return ret;
1597 1598
}

1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
static void
uname_normalize (struct utsname *ut)
{
    uname(ut);

    /* Map i386, i486, i586 to i686.  */
    if (ut->machine[0] == 'i' &&
        ut->machine[1] != '\0' &&
        ut->machine[2] == '8' &&
        ut->machine[3] == '6' &&
        ut->machine[4] == '\0')
        ut->machine[1] = '6';
}

1613
int qemudExtractVersion(struct qemud_driver *driver) {
1614
    const char *binary;
1615
    struct stat sb;
1616
    struct utsname ut;
1617

1618
    if (driver->qemuVersion > 0)
1619 1620
        return 0;

1621
    uname_normalize(&ut);
1622 1623
    if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
                                                      "hvm",
1624
                                                      ut.machine,
1625 1626 1627
                                                      "qemu")) == NULL) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot find suitable emulator for %s"), ut.machine);
1628
        return -1;
1629
    }
1630

1631
    if (stat(binary, &sb) < 0) {
1632
        virReportSystemError(errno,
C
Cole Robinson 已提交
1633
                             _("Cannot find QEMU binary %s"), binary);
1634
        return -1;
1635 1636
    }

1637
    if (qemudExtractVersionInfo(binary, &driver->qemuVersion, NULL) < 0) {
1638 1639
        return -1;
    }
D
Daniel P. Berrange 已提交
1640

1641
    return 0;
D
Daniel P. Berrange 已提交
1642 1643
}

1644 1645 1646
/**
 * qemudPhysIfaceConnect:
 * @conn: pointer to virConnect object
1647
 * @driver: pointer to the qemud_driver
1648
 * @net: pointer to he VM's interface description with direct device type
1649 1650
 * @qemuCmdFlags: flags for qemu
 * @vmuuid: The UUID of the VM (needed by 802.1Qbh)
1651 1652 1653 1654 1655
 *
 * Returns a filedescriptor on success or -1 in case of error.
 */
int
qemudPhysIfaceConnect(virConnectPtr conn,
S
Stefan Berger 已提交
1656
                      struct qemud_driver *driver,
1657
                      virDomainNetDefPtr net,
1658
                      unsigned long long qemuCmdFlags,
1659 1660
                      const unsigned char *vmuuid,
                      enum virVMOperationType vmop)
1661 1662 1663 1664
{
    int rc;
#if WITH_MACVTAP
    char *res_ifname = NULL;
1665
    int vnet_hdr = 0;
S
Stefan Berger 已提交
1666
    int err;
1667 1668 1669 1670

    if (qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HDR &&
        net->model && STREQ(net->model, "virtio"))
        vnet_hdr = 1;
1671

1672 1673
    rc = openMacvtapTap(net->ifname, net->mac, net->data.direct.linkdev,
                        net->data.direct.mode, vnet_hdr, vmuuid,
1674 1675
                        &net->data.direct.virtPortProfile, &res_ifname,
                        vmop);
1676 1677 1678 1679
    if (rc >= 0) {
        VIR_FREE(net->ifname);
        net->ifname = res_ifname;
    }
S
Stefan Berger 已提交
1680 1681 1682 1683 1684 1685 1686 1687

    if (rc >=0 && driver->macFilter) {
        if ((err = networkAllowMacOnPort(driver, net->ifname, net->mac))) {
            virReportSystemError(err,
                 _("failed to add ebtables rule to allow MAC address on  '%s'"),
                                 net->ifname);
        }
    }
S
Stefan Berger 已提交
1688 1689 1690

    if (rc >= 0) {
        if ((net->filter) && (net->ifname)) {
1691
            err = virDomainConfNWFilterInstantiate(conn, net);
S
Stefan Berger 已提交
1692
            if (err) {
1693
                VIR_FORCE_CLOSE(rc);
1694
                delMacvtap(net->ifname, net->mac, net->data.direct.linkdev,
1695
                           &net->data.direct.virtPortProfile);
1696
                VIR_FREE(net->ifname);
S
Stefan Berger 已提交
1697 1698 1699
            }
        }
    }
1700 1701 1702
#else
    (void)conn;
    (void)net;
1703
    (void)qemuCmdFlags;
S
Stefan Berger 已提交
1704
    (void)driver;
1705
    (void)vmuuid;
1706
    (void)vmop;
1707 1708 1709 1710 1711 1712 1713
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("No support for macvtap device"));
    rc = -1;
#endif
    return rc;
}

D
Daniel P. Berrange 已提交
1714

1715
int
1716 1717
qemudNetworkIfaceConnect(virConnectPtr conn,
                         struct qemud_driver *driver,
1718
                         virDomainNetDefPtr net,
1719
                         unsigned long long qemuCmdFlags)
1720
{
R
Ryota Ozaki 已提交
1721
    char *brname = NULL;
1722 1723
    int err;
    int tapfd = -1;
1724
    int vnet_hdr = 0;
1725
    int template_ifname = 0;
1726
    unsigned char tapmac[VIR_MAC_BUFLEN];
1727

1728
    if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
1729 1730
        int active, fail = 0;
        virErrorPtr errobj;
1731
        virNetworkPtr network = virNetworkLookupByName(conn,
1732
                                                       net->data.network.name);
1733 1734 1735
        if (!network)
            return -1;

1736 1737 1738
        active = virNetworkIsActive(network);
        if (active != 1) {
            fail = 1;
1739

1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753
            if (active == 0)
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("Network '%s' is not active."),
                                net->data.network.name);
        }

        if (!fail) {
            brname = virNetworkGetBridgeName(network);
            if (brname == NULL)
                fail = 1;
        }

        /* Make sure any above failure is preserved */
        errobj = virSaveLastError();
1754
        virNetworkFree(network);
1755 1756
        virSetError(errobj);
        virFreeError(errobj);
1757

1758
        if (fail)
1759
            return -1;
1760

1761
    } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
1762
        if (!(brname = strdup(net->data.bridge.brname))) {
1763
            virReportOOMError();
1764 1765
            return -1;
        }
1766
    } else {
1767 1768
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Network type %d is not supported"), net->type);
1769
        return -1;
1770 1771
    }

1772
    if (!driver->brctl && (err = brInit(&driver->brctl))) {
1773
        virReportSystemError(err, "%s",
1774
                             _("cannot initialize bridge support"));
R
Ryota Ozaki 已提交
1775
        goto cleanup;
1776 1777
    }

1778 1779 1780 1781 1782
    if (!net->ifname ||
        STRPREFIX(net->ifname, "vnet") ||
        strchr(net->ifname, '%')) {
        VIR_FREE(net->ifname);
        if (!(net->ifname = strdup("vnet%d"))) {
1783
            virReportOOMError();
R
Ryota Ozaki 已提交
1784
            goto cleanup;
1785
        }
1786 1787
        /* avoid exposing vnet%d in dumpxml or error outputs */
        template_ifname = 1;
1788 1789
    }

1790 1791 1792 1793
    if (qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HDR &&
        net->model && STREQ(net->model, "virtio"))
        vnet_hdr = 1;

1794 1795 1796 1797 1798 1799 1800 1801
    memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
    tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
    if ((err = brAddTap(driver->brctl,
                        brname,
                        &net->ifname,
                        tapmac,
                        vnet_hdr,
                        &tapfd))) {
D
Doug Goldstein 已提交
1802
        if (err == ENOTSUP) {
1803
            /* In this particular case, give a better diagnostic. */
1804 1805 1806
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Failed to add tap interface to bridge. "
                              "%s is not a bridge device"), brname);
1807 1808 1809 1810 1811 1812 1813
        } else if (err == ENOENT) {
            /* When the tun drive is missing, give a better message. */
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("Failed to add tap interface to bridge. "
                              "Your kernel is missing the 'tun' module or "
                              "CONFIG_TUN, or you need to add the "
                              "/dev/net/tun device node."));
1814
        } else if (template_ifname) {
1815
            virReportSystemError(err,
1816 1817
                                 _("Failed to add tap interface to bridge '%s'"),
                                 brname);
1818
        } else {
1819
            virReportSystemError(err,
1820 1821
                                 _("Failed to add tap interface '%s' to bridge '%s'"),
                                 net->ifname, brname);
1822
        }
1823 1824
        if (template_ifname)
            VIR_FREE(net->ifname);
R
Ryota Ozaki 已提交
1825
        tapfd = -1;
1826 1827
    }

1828
    if (driver->macFilter) {
1829 1830
        if ((err = networkAllowMacOnPort(driver, net->ifname, net->mac))) {
            virReportSystemError(err,
1831 1832 1833 1834 1835
                 _("failed to add ebtables rule to allow MAC address on  '%s'"),
                                 net->ifname);
        }
    }

S
Stefan Berger 已提交
1836 1837
    if (tapfd >= 0) {
        if ((net->filter) && (net->ifname)) {
1838
            err = virDomainConfNWFilterInstantiate(conn, net);
1839 1840
            if (err)
                VIR_FORCE_CLOSE(tapfd);
S
Stefan Berger 已提交
1841 1842 1843
        }
    }

R
Ryota Ozaki 已提交
1844 1845 1846
cleanup:
    VIR_FREE(brname);

1847
    return tapfd;
1848 1849
}

1850

1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
int
qemudOpenVhostNet(virDomainNetDefPtr net,
                  unsigned long long qemuCmdFlags)
{

    /* If qemu supports vhost-net mode (including the -netdev command
     * option), the nic model is virtio, and we can open
     * /dev/vhost_net, assume that vhost-net mode is available and
     * return the fd to /dev/vhost_net. Otherwise, return -1.
     */

    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HOST &&
          qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV &&
          qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE &&
          net->model && STREQ(net->model, "virtio")))
        return -1;

    return open("/dev/vhost-net", O_RDWR, 0);
}


1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893
static int qemuDomainDeviceAliasIndex(virDomainDeviceInfoPtr info,
                                      const char *prefix)
{
    int idx;

    if (!info->alias)
        return -1;
    if (!STRPREFIX(info->alias, prefix))
        return -1;

    if (virStrToLong_i(info->alias + strlen(prefix), NULL, 10, &idx) < 0)
        return -1;

    return idx;
}


int qemuDomainNetVLAN(virDomainNetDefPtr def)
{
    return qemuDomainDeviceAliasIndex(&def->info, "net");
}

1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906

/* Names used before -drive existed */
static int qemuAssignDeviceDiskAliasLegacy(virDomainDiskDefPtr disk)
{
    char *devname;

    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
        STREQ(disk->dst, "hdc"))
        devname = strdup("cdrom");
    else
        devname = strdup(disk->dst);

    if (!devname) {
1907
        virReportOOMError();
1908 1909 1910 1911 1912 1913 1914 1915
        return -1;
    }

    disk->info.alias = devname;
    return 0;
}


1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
                               unsigned long long qemudCmdFlags)
{
    char *ret;

    if (qemudCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (virAsprintf(&ret, "%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) {
            virReportOOMError();
            return NULL;
        }
    } else {
        if (!(ret = strdup(disk->info.alias))) {
            virReportOOMError();
            return NULL;
        }
    }
    return ret;
}


1936 1937 1938 1939 1940 1941 1942 1943
/* Names used before -drive supported the id= option */
static int qemuAssignDeviceDiskAliasFixed(virDomainDiskDefPtr disk)
{
    int busid, devid;
    int ret;
    char *devname;

    if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) {
1944 1945 1946
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot convert disk '%s' to bus/device index"),
                        disk->dst);
1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972
        return -1;
    }

    switch (disk->bus) {
    case VIR_DOMAIN_DISK_BUS_IDE:
        if (disk->device== VIR_DOMAIN_DISK_DEVICE_DISK)
            ret = virAsprintf(&devname, "ide%d-hd%d", busid, devid);
        else
            ret = virAsprintf(&devname, "ide%d-cd%d", busid, devid);
        break;
    case VIR_DOMAIN_DISK_BUS_SCSI:
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
            ret = virAsprintf(&devname, "scsi%d-hd%d", busid, devid);
        else
            ret = virAsprintf(&devname, "scsi%d-cd%d", busid, devid);
        break;
    case VIR_DOMAIN_DISK_BUS_FDC:
        ret = virAsprintf(&devname, "floppy%d", devid);
        break;
    case VIR_DOMAIN_DISK_BUS_VIRTIO:
        ret = virAsprintf(&devname, "virtio%d", devid);
        break;
    case VIR_DOMAIN_DISK_BUS_XEN:
        ret = virAsprintf(&devname, "xenblk%d", devid);
        break;
    default:
1973
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1974 1975
                        _("Unsupported disk name mapping for bus '%s'"),
                        virDomainDiskBusTypeToString(disk->bus));
1976 1977 1978 1979
        return -1;
    }

    if (ret == -1) {
1980
        virReportOOMError();
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
        return -1;
    }

    disk->info.alias = devname;

    return 0;
}


/* Our custom -drive naming scheme used with id= */
static int qemuAssignDeviceDiskAliasCustom(virDomainDiskDefPtr disk)
{
    const char *prefix = virDomainDiskBusTypeToString(disk->bus);
    if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
        if (virAsprintf(&disk->info.alias, "%s%d-%d-%d", prefix,
                        disk->info.addr.drive.controller,
                        disk->info.addr.drive.bus,
                        disk->info.addr.drive.unit) < 0)
            goto no_memory;
    } else {
        int idx = virDiskNameToIndex(disk->dst);
        if (virAsprintf(&disk->info.alias, "%s-disk%d", prefix, idx) < 0)
            goto no_memory;
    }

    return 0;

no_memory:
2009
    virReportOOMError();
2010 2011 2012 2013
    return -1;
}


2014
int
2015
qemuAssignDeviceDiskAlias(virDomainDiskDefPtr def, unsigned long long qemuCmdFlags)
2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
{
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
        if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
            return qemuAssignDeviceDiskAliasCustom(def);
        else
            return qemuAssignDeviceDiskAliasFixed(def);
    } else {
        return qemuAssignDeviceDiskAliasLegacy(def);
    }
}


int
qemuAssignDeviceNetAlias(virDomainDefPtr def, virDomainNetDefPtr net, int idx)
{
    if (idx == -1) {
        int i;
        idx = 0;
        for (i = 0 ; i < def->nnets ; i++) {
            int thisidx;
            if ((thisidx = qemuDomainDeviceAliasIndex(&def->nets[i]->info, "net")) < 0) {
2037 2038
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("Unable to determine device index for network device"));
2039 2040 2041 2042 2043 2044 2045 2046
                return -1;
            }
            if (thisidx >= idx)
                idx = thisidx + 1;
        }
    }

    if (virAsprintf(&net->info.alias, "net%d", idx) < 0) {
2047
        virReportOOMError();
2048 2049 2050 2051 2052 2053
        return -1;
    }

    return 0;
}

2054 2055 2056 2057 2058 2059 2060 2061 2062 2063

int
qemuAssignDeviceHostdevAlias(virDomainDefPtr def, virDomainHostdevDefPtr hostdev, int idx)
{
    if (idx == -1) {
        int i;
        idx = 0;
        for (i = 0 ; i < def->nhostdevs ; i++) {
            int thisidx;
            if ((thisidx = qemuDomainDeviceAliasIndex(&def->hostdevs[i]->info, "hostdev")) < 0) {
2064 2065
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("Unable to determine device index for hostdevwork device"));
2066 2067 2068 2069 2070 2071 2072 2073
                return -1;
            }
            if (thisidx >= idx)
                idx = thisidx + 1;
        }
    }

    if (virAsprintf(&hostdev->info.alias, "hostdev%d", idx) < 0) {
2074
        virReportOOMError();
2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088
        return -1;
    }

    return 0;
}


int
qemuAssignDeviceControllerAlias(virDomainControllerDefPtr controller)
{
    const char *prefix = virDomainControllerTypeToString(controller->type);

    if (virAsprintf(&controller->info.alias,  "%s%d", prefix,
                    controller->idx) < 0) {
2089
        virReportOOMError();
2090 2091 2092 2093 2094 2095 2096
        return -1;
    }

    return 0;
}


2097
static int
2098
qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long qemuCmdFlags)
2099 2100 2101 2102
{
    int i;

    for (i = 0; i < def->ndisks ; i++) {
2103 2104
        if (qemuAssignDeviceDiskAlias(def->disks[i], qemuCmdFlags) < 0)
            return -1;
2105
    }
2106 2107 2108 2109 2110 2111
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NET_NAME) ||
        (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
        for (i = 0; i < def->nnets ; i++) {
            if (qemuAssignDeviceNetAlias(def, def->nets[i], i) < 0)
                return -1;
        }
2112 2113
    }

2114 2115 2116
    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
        return 0;

2117 2118 2119 2120
    for (i = 0; i < def->nfss ; i++) {
        if (virAsprintf(&def->fss[i]->info.alias, "fs%d", i) < 0)
            goto no_memory;
    }
2121 2122 2123 2124 2125
    for (i = 0; i < def->nsounds ; i++) {
        if (virAsprintf(&def->sounds[i]->info.alias, "sound%d", i) < 0)
            goto no_memory;
    }
    for (i = 0; i < def->nhostdevs ; i++) {
2126 2127
        if (qemuAssignDeviceHostdevAlias(def, def->hostdevs[i], i) < 0)
            return -1;
2128 2129 2130 2131 2132 2133
    }
    for (i = 0; i < def->nvideos ; i++) {
        if (virAsprintf(&def->videos[i]->info.alias, "video%d", i) < 0)
            goto no_memory;
    }
    for (i = 0; i < def->ncontrollers ; i++) {
2134 2135
        if (qemuAssignDeviceControllerAlias(def->controllers[i]) < 0)
            return -1;
2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152
    }
    for (i = 0; i < def->ninputs ; i++) {
        if (virAsprintf(&def->inputs[i]->info.alias, "input%d", i) < 0)
            goto no_memory;
    }
    for (i = 0; i < def->nparallels ; i++) {
        if (virAsprintf(&def->parallels[i]->info.alias, "parallel%d", i) < 0)
            goto no_memory;
    }
    for (i = 0; i < def->nserials ; i++) {
        if (virAsprintf(&def->serials[i]->info.alias, "serial%d", i) < 0)
            goto no_memory;
    }
    for (i = 0; i < def->nchannels ; i++) {
        if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0)
            goto no_memory;
    }
C
Cole Robinson 已提交
2153 2154 2155 2156
    if (def->console) {
        if (virAsprintf(&def->console->info.alias, "console%d", i) < 0)
            goto no_memory;
    }
2157 2158 2159 2160
    if (def->watchdog) {
        if (virAsprintf(&def->watchdog->info.alias, "watchdog%d", 0) < 0)
            goto no_memory;
    }
2161 2162 2163 2164
    if (def->memballoon) {
        if (virAsprintf(&def->memballoon->info.alias, "balloon%d", 0) < 0)
            goto no_memory;
    }
2165 2166 2167 2168

    return 0;

    no_memory:
2169
    virReportOOMError();
2170 2171 2172 2173
    return -1;
}


2174 2175 2176 2177 2178 2179 2180 2181
#define QEMU_PCI_ADDRESS_LAST_SLOT 31
struct _qemuDomainPCIAddressSet {
    virHashTablePtr used;
    int nextslot;
};


static char *qemuPCIAddressAsString(virDomainDeviceInfoPtr dev)
D
Daniel P. Berrange 已提交
2182
{
2183 2184
    char *addr;

2185 2186
    if (dev->addr.pci.domain != 0 ||
        dev->addr.pci.bus != 0) {
2187 2188
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("Only PCI domain 0 and bus 0 are available"));
2189 2190 2191
        return NULL;
    }

2192 2193 2194 2195
    if (virAsprintf(&addr, "%d:%d:%d",
                    dev->addr.pci.domain,
                    dev->addr.pci.bus,
                    dev->addr.pci.slot) < 0) {
2196
        virReportOOMError();
2197 2198 2199
        return NULL;
    }
    return addr;
D
Daniel P. Berrange 已提交
2200 2201
}

2202 2203 2204 2205 2206 2207 2208 2209 2210

static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
                                 virDomainDeviceInfoPtr dev,
                                 void *opaque)
{
    qemuDomainPCIAddressSetPtr addrs = opaque;

    if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
        char *addr = qemuPCIAddressAsString(dev);
2211 2212
        if (!addr)
            return -1;
2213

2214 2215
        VIR_DEBUG("Remembering PCI addr %s", addr);

2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241
        if (virHashAddEntry(addrs->used, addr, addr) < 0) {
            VIR_FREE(addr);
            return -1;
        }
    }

    return 0;
}


qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def)
{
    qemuDomainPCIAddressSetPtr addrs;

    if (VIR_ALLOC(addrs) < 0)
        goto no_memory;

    if (!(addrs->used = virHashCreate(10)))
        goto no_memory;

    if (virDomainDeviceInfoIterate(def, qemuCollectPCIAddress, addrs) < 0)
        goto error;

    return addrs;

no_memory:
2242
    virReportOOMError();
2243 2244 2245 2246 2247
error:
    qemuDomainPCIAddressSetFree(addrs);
    return NULL;
}

2248 2249
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
                                    virDomainDeviceInfoPtr dev)
2250 2251 2252
{
    char *addr;

2253
    addr = qemuPCIAddressAsString(dev);
2254 2255 2256
    if (!addr)
        return -1;

2257 2258
    VIR_DEBUG("Reserving PCI addr %s", addr);

2259
    if (virHashLookup(addrs->used, addr)) {
2260 2261
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unable to reserve PCI address %s"), addr);
2262 2263 2264 2265 2266 2267 2268 2269 2270
        VIR_FREE(addr);
        return -1;
    }

    if (virHashAddEntry(addrs->used, addr, addr)) {
        VIR_FREE(addr);
        return -1;
    }

J
Jiri Denemark 已提交
2271
    if (dev->addr.pci.slot > addrs->nextslot) {
2272
        addrs->nextslot = dev->addr.pci.slot + 1;
J
Jiri Denemark 已提交
2273 2274 2275
        if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
            addrs->nextslot = 0;
    }
2276

2277 2278 2279
    return 0;
}

2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302
int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
                                    int slot)
{
    virDomainDeviceInfo dev;

    dev.addr.pci.domain = 0;
    dev.addr.pci.bus = 0;
    dev.addr.pci.slot = slot;

    return qemuDomainPCIAddressReserveAddr(addrs, &dev);
}


int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
                                    virDomainDeviceInfoPtr dev)
{
    int ret = 0;
    if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
        ret = qemuDomainPCIAddressReserveAddr(addrs, dev);
    else
        ret = qemuDomainPCIAddressSetNextAddr(addrs, dev);
    return ret;
}
2303 2304 2305 2306 2307 2308 2309

static void qemuDomainPCIAddressSetFreeEntry(void *payload, const char *name ATTRIBUTE_UNUSED)
{
    VIR_FREE(payload);
}


2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327
int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
                                    virDomainDeviceInfoPtr dev)
{
    char *addr;
    int ret;

    addr = qemuPCIAddressAsString(dev);
    if (!addr)
        return -1;

    ret = virHashRemoveEntry(addrs->used, addr, qemuDomainPCIAddressSetFreeEntry);

    VIR_FREE(addr);

    return ret;
}


2328 2329 2330 2331 2332 2333
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
{
    if (!addrs)
        return;

    virHashFree(addrs->used, qemuDomainPCIAddressSetFreeEntry);
2334
    VIR_FREE(addrs);
2335 2336 2337 2338 2339
}


int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
                                    virDomainDeviceInfoPtr dev)
D
Daniel P. Berrange 已提交
2340 2341
{
    int i;
J
Jiri Denemark 已提交
2342
    int iteration;
2343

J
Jiri Denemark 已提交
2344 2345
    for (i = addrs->nextslot, iteration = 0;
         iteration <= QEMU_PCI_ADDRESS_LAST_SLOT; i++, iteration++) {
2346 2347 2348
        virDomainDeviceInfo maybe;
        char *addr;

J
Jiri Denemark 已提交
2349 2350
        if (QEMU_PCI_ADDRESS_LAST_SLOT < i)
            i = 0;
2351 2352 2353 2354 2355
        memset(&maybe, 0, sizeof(maybe));
        maybe.addr.pci.domain = 0;
        maybe.addr.pci.bus = 0;
        maybe.addr.pci.slot = i;

2356 2357
        if (!(addr = qemuPCIAddressAsString(&maybe)))
            return -1;
2358 2359

        if (virHashLookup(addrs->used, addr)) {
J
Jiri Denemark 已提交
2360
            VIR_DEBUG("PCI addr %s already in use", addr);
2361 2362 2363 2364
            VIR_FREE(addr);
            continue;
        }

J
Jiri Denemark 已提交
2365 2366
        VIR_DEBUG("Allocating PCI addr %s", addr);

2367 2368 2369 2370 2371 2372
        if (virHashAddEntry(addrs->used, addr, addr) < 0) {
            VIR_FREE(addr);
            return -1;
        }

        dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
J
Jiri Denemark 已提交
2373
        dev->addr.pci = maybe.addr.pci;
2374 2375

        addrs->nextslot = i + 1;
J
Jiri Denemark 已提交
2376 2377
        if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
            addrs->nextslot = 0;
2378 2379 2380 2381

        return 0;
    }

2382 2383
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("No more available PCI addresses"));
2384 2385 2386
    return -1;
}

2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412
/*
 * This assigns static PCI slots to all configured devices.
 * The ordering here is chosen to match the ordering used
 * with old QEMU < 0.12, so that if a user updates a QEMU
 * host from old QEMU to QEMU >= 0.12, their guests should
 * get PCI addresses in the same order as before.
 *
 * NB, if they previously hotplugged devices then all bets
 * are off. Hotplug for old QEMU was unfixably broken wrt
 * to stable PCI addressing.
 *
 * Order is:
 *
 *  - Host bridge (slot 0)
 *  - PIIX3 ISA bridge, IDE controller, something else unknown, USB controller (slot 1)
 *  - Video (slot 2)
 *
 * Incrementally assign slots from 3 onwards:
 *
 *  - Net
 *  - Sound
 *  - SCSI controllers
 *  - VirtIO block
 *  - VirtIO balloon
 *  - Host device passthrough
 *  - Watchdog
2413 2414 2415 2416 2417
 *
 * Prior to this function being invoked, qemuCollectPCIAddress() will have
 * added all existing PCI addresses from the 'def' to 'addrs'. Thus this
 * function must only try to reserve addresses if info.type == NONE and
 * skip over info.type == PCI
2418
 */
2419 2420 2421 2422
int
qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
{
    int i;
2423
    bool reservedIDE = false;
2424 2425

    /* Host bridge */
2426
    if (qemuDomainPCIAddressReserveSlot(addrs, 0) < 0)
2427
        goto error;
2428

2429
    /* Verify that first IDE controller (if any) is on the PIIX3, fn 1 */
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
    for (i = 0; i < def->ncontrollers ; i++) {
        /* First IDE controller lives on the PIIX3 at slot=1, function=1 */
        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
            def->controllers[i]->idx == 0) {
            if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
                if (def->controllers[i]->info.addr.pci.domain != 0 ||
                    def->controllers[i]->info.addr.pci.bus != 0 ||
                    def->controllers[i]->info.addr.pci.slot != 1 ||
                    def->controllers[i]->info.addr.pci.function != 1) {
                    qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                    _("Primary IDE controller must have PCI address 0:0:1.1"));
                    goto error;
                }
2443 2444 2445
                /* If TYPE==PCI, then then qemuCollectPCIAddress() function
                 * has already reserved the address, so we must skip */
                reservedIDE = true;
2446 2447 2448 2449 2450 2451 2452 2453 2454
            } else {
                def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
                def->controllers[i]->info.addr.pci.domain = 0;
                def->controllers[i]->info.addr.pci.bus = 0;
                def->controllers[i]->info.addr.pci.slot = 1;
                def->controllers[i]->info.addr.pci.function = 1;
            }
        }
    }
2455

2456 2457 2458 2459 2460 2461 2462
    /* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller)
     * hardcoded slot=1, multifunction device
     */
    if (!reservedIDE &&
        qemuDomainPCIAddressReserveSlot(addrs, 1) < 0)
        goto error;

2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483
    /* First VGA is hardcoded slot=2 */
    if (def->nvideos > 0) {
        if (def->videos[0]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
            if (def->videos[0]->info.addr.pci.domain != 0 ||
                def->videos[0]->info.addr.pci.bus != 0 ||
                def->videos[0]->info.addr.pci.slot != 2 ||
                def->videos[0]->info.addr.pci.function != 0) {
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("Primary video card must have PCI address 0:0:2.0"));
                goto error;
            }
        } else {
            def->videos[0]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
            def->videos[0]->info.addr.pci.domain = 0;
            def->videos[0]->info.addr.pci.bus = 0;
            def->videos[0]->info.addr.pci.slot = 2;
            def->videos[0]->info.addr.pci.function = 0;
            if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0)
                goto error;
        }
    }
2484 2485 2486 2487 2488 2489 2490 2491 2492
    for (i = 0; i < def->nfss ; i++) {
        if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
            continue;

        /* Only support VirtIO-9p-pci so far. If that changes,
         * we might need to skip devices here */
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->fss[i]->info) < 0)
            goto error;
    }
2493

2494
    /* Network interfaces */
D
Daniel P. Berrange 已提交
2495 2496 2497
    for (i = 0; i < def->nnets ; i++) {
        if (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
            continue;
2498 2499
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->nets[i]->info) < 0)
            goto error;
D
Daniel P. Berrange 已提交
2500 2501
    }

2502
    /* Sound cards */
D
Daniel P. Berrange 已提交
2503 2504 2505 2506 2507 2508 2509 2510
    for (i = 0; i < def->nsounds ; i++) {
        if (def->sounds[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
            continue;
        /* Skip ISA sound card, and PCSPK */
        if (def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_SB16 ||
            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK)
            continue;

2511 2512
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->sounds[i]->info) < 0)
            goto error;
D
Daniel P. Berrange 已提交
2513 2514
    }

2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546
    /* Disk controllers (SCSI only for now) */
    for (i = 0; i < def->ncontrollers ; i++) {
        /* FDC lives behind the ISA bridge */
        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC)
            continue;

        /* First IDE controller lives on the PIIX3 at slot=1, function=1,
           dealt with earlier on*/
        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
            def->controllers[i]->idx == 0)
            continue;

        if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
            continue;
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0)
            goto error;
    }

    /* Disks (VirtIO only for now */
    for (i = 0; i < def->ndisks ; i++) {
        if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
            continue;

        /* Only VirtIO disks use PCI addrs */
        if (def->disks[i]->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
            continue;

        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->disks[i]->info) < 0)
            goto error;
    }

    /* Host PCI devices */
D
Daniel P. Berrange 已提交
2547 2548 2549 2550 2551 2552 2553
    for (i = 0; i < def->nhostdevs ; i++) {
        if (def->hostdevs[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
            continue;
        if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
            def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

2554 2555
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->hostdevs[i]->info) < 0)
            goto error;
D
Daniel P. Berrange 已提交
2556
    }
2557 2558 2559 2560 2561 2562

    /* VirtIO balloon */
    if (def->memballoon &&
        def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
        def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->memballoon->info) < 0)
2563
            goto error;
D
Daniel P. Berrange 已提交
2564 2565
    }

2566 2567 2568 2569 2570 2571
    /* A watchdog */
    if (def->watchdog &&
        def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->watchdog->info) < 0)
            goto error;
    }
2572

2573 2574 2575
    /* Further non-primary video cards */
    for (i = 1; i < def->nvideos ; i++) {
        if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
2576
            continue;
2577
        if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[i]->info) < 0)
2578
            goto error;
D
Daniel P. Berrange 已提交
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591
    }
    for (i = 0; i < def->ninputs ; i++) {
        /* Nada - none are PCI based (yet) */
    }
    for (i = 0; i < def->nparallels ; i++) {
        /* Nada - none are PCI based (yet) */
    }
    for (i = 0; i < def->nserials ; i++) {
        /* Nada - none are PCI based (yet) */
    }
    for (i = 0; i < def->nchannels ; i++) {
        /* Nada - none are PCI based (yet) */
    }
2592 2593 2594 2595 2596

    return 0;

error:
    return -1;
D
Daniel P. Berrange 已提交
2597 2598 2599
}


D
Daniel P. Berrange 已提交
2600 2601 2602 2603 2604 2605
static int
qemuBuildDeviceAddressStr(virBufferPtr buf,
                          virDomainDeviceInfoPtr info)
{
    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
        if (info->addr.pci.domain != 0) {
2606 2607
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("Only PCI device addresses with domain=0 are supported"));
D
Daniel P. Berrange 已提交
2608 2609 2610
            return -1;
        }
        if (info->addr.pci.bus != 0) {
2611 2612
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("Only PCI device addresses with bus=0 are supported"));
D
Daniel P. Berrange 已提交
2613 2614 2615
            return -1;
        }
        if (info->addr.pci.function != 0) {
2616 2617
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("Only PCI device addresses with function=0 are supported"));
D
Daniel P. Berrange 已提交
2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631
            return -1;
        }

        /* XXX
         * When QEMU grows support for > 1 PCI bus, then pci.0 changes
         * to pci.1, pci.2, etc
         * When QEMU grows support for > 1 PCI domain, then pci.0 change
         * to pciNN.0  where NN is the domain number
         */
        virBufferVSprintf(buf, ",bus=pci.0,addr=0x%x", info->addr.pci.slot);
    }
    return 0;
}

2632

2633 2634 2635 2636
#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"

static int
2637
qemuSafeSerialParamValue(const char *value)
2638 2639
{
    if (strspn(value, QEMU_SERIAL_PARAM_ACCEPTED_CHARS) != strlen (value)) {
2640 2641 2642
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("driver serial '%s' contains unsafe characters"),
                        value);
2643 2644 2645 2646 2647 2648 2649 2650 2651 2652
        return -1;
    }

    return 0;
}


char *
qemuBuildDriveStr(virDomainDiskDefPtr disk,
                  int bootable,
2653
                  unsigned long long qemuCmdFlags)
2654 2655 2656 2657
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;
    const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
    int idx = virDiskNameToIndex(disk->dst);
2658
    int busid = -1, unitid = -1;
2659 2660

    if (idx < 0) {
2661 2662
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unsupported disk type '%s'"), disk->dst);
2663 2664 2665
        goto error;
    }

2666 2667 2668
    switch (disk->bus) {
    case VIR_DOMAIN_DISK_BUS_SCSI:
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
2669 2670
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("unexpected address type for scsi disk"));
2671 2672 2673 2674 2675 2676 2677
            goto error;
        }

        /* Setting bus= attr for SCSI drives, causes a controller
         * to be created. Yes this is slightly odd. It is not possible
         * to have > 1 bus on a SCSI controller (yet). */
        if (disk->info.addr.drive.bus != 0) {
2678 2679
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("SCSI controller only supports 1 bus"));
2680 2681 2682 2683 2684 2685 2686 2687
            goto error;
        }
        busid = disk->info.addr.drive.controller;
        unitid = disk->info.addr.drive.unit;
        break;

    case VIR_DOMAIN_DISK_BUS_IDE:
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
2688 2689
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("unexpected address type for ide disk"));
2690 2691 2692 2693
            goto error;
        }
        /* We can only have 1 IDE controller (currently) */
        if (disk->info.addr.drive.controller != 0) {
2694 2695
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Only 1 %s controller is supported"), bus);
2696 2697 2698 2699 2700 2701 2702 2703
            goto error;
        }
        busid = disk->info.addr.drive.bus;
        unitid = disk->info.addr.drive.unit;
        break;

    case VIR_DOMAIN_DISK_BUS_FDC:
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
2704 2705
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("unexpected address type for fdc disk"));
2706 2707 2708 2709
            goto error;
        }
        /* We can only have 1 FDC controller (currently) */
        if (disk->info.addr.drive.controller != 0) {
2710 2711
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Only 1 %s controller is supported"), bus);
2712 2713 2714 2715
            goto error;
        }
        /* We can only have 1 FDC bus (currently) */
        if (disk->info.addr.drive.bus != 0) {
2716 2717
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Only 1 %s bus is supported"), bus);
2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733
            goto error;
        }
        unitid = disk->info.addr.drive.unit;

        break;

    case VIR_DOMAIN_DISK_BUS_VIRTIO:
        /* Each virtio drive is a separate PCI device, no unit/busid or index */
        idx = -1;
        break;

    case VIR_DOMAIN_DISK_BUS_XEN:
        /* Xen has no address type currently, so assign based on index */
        break;
    }

2734 2735 2736 2737 2738
    if (disk->src) {
        if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
            /* QEMU only supports magic FAT format for now */
            if (disk->driverType &&
                STRNEQ(disk->driverType, "fat")) {
2739 2740 2741
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unsupported disk driver type for '%s'"),
                                disk->driverType);
2742 2743 2744
                goto error;
            }
            if (!disk->readonly) {
2745 2746
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("cannot create virtual FAT disks in read-write mode"));
2747 2748 2749 2750 2751 2752 2753 2754 2755 2756
                goto error;
            }
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
                virBufferVSprintf(&opt, "file=fat:floppy:%s,", disk->src);
            else
                virBufferVSprintf(&opt, "file=fat:%s,", disk->src);
        } else {
            virBufferVSprintf(&opt, "file=%s,", disk->src);
        }
    }
2757 2758 2759 2760 2761
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
        virBufferAddLit(&opt, "if=none");
    else
        virBufferVSprintf(&opt, "if=%s", bus);

2762 2763
    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
        virBufferAddLit(&opt, ",media=cdrom");
2764 2765

    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
2766
        virBufferVSprintf(&opt, ",id=%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias);
2767
    } else {
2768 2769 2770 2771 2772 2773 2774 2775 2776
        if (busid == -1 && unitid == -1) {
            if (idx != -1)
                virBufferVSprintf(&opt, ",index=%d", idx);
        } else {
            if (busid != -1)
                virBufferVSprintf(&opt, ",bus=%d", busid);
            if (unitid != -1)
                virBufferVSprintf(&opt, ",unit=%d", unitid);
        }
2777
    }
2778
    if (bootable &&
2779 2780
        disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
        disk->bus != VIR_DOMAIN_DISK_BUS_IDE)
2781
        virBufferAddLit(&opt, ",boot=on");
2782
    if (disk->readonly &&
2783
        qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_READONLY)
2784
        virBufferAddLit(&opt, ",readonly=on");
2785
    if (disk->driverType && *disk->driverType != '\0' &&
2786 2787 2788 2789 2790
        disk->type != VIR_DOMAIN_DISK_TYPE_DIR &&
        qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_FORMAT)
        virBufferVSprintf(&opt, ",format=%s", disk->driverType);
    if (disk->serial &&
        (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_SERIAL)) {
2791
        if (qemuSafeSerialParamValue(disk->serial) < 0)
2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806
            goto error;
        virBufferVSprintf(&opt, ",serial=%s", disk->serial);
    }

    if (disk->cachemode) {
        const char *mode =
            (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_CACHE_V2) ?
            qemuDiskCacheV2TypeToString(disk->cachemode) :
            qemuDiskCacheV1TypeToString(disk->cachemode);

        virBufferVSprintf(&opt, ",cache=%s", mode);
    } else if (disk->shared && !disk->readonly) {
        virBufferAddLit(&opt, ",cache=off");
    }

2807 2808 2809 2810 2811 2812 2813 2814
    if (qemuCmdFlags & QEMUD_CMD_FLAG_MONITOR_JSON) {
        if (disk->error_policy) {
            virBufferVSprintf(&opt, ",werror=%s,rerror=%s",
                              virDomainDiskErrorPolicyTypeToString(disk->error_policy),
                              virDomainDiskErrorPolicyTypeToString(disk->error_policy));
        }
    }

2815
    if (virBufferError(&opt)) {
2816
        virReportOOMError();
2817 2818 2819 2820 2821 2822 2823 2824 2825 2826
        goto error;
    }

    return virBufferContentAndReset(&opt);

error:
    virBufferFreeAndReset(&opt);
    return NULL;
}

2827 2828

char *
2829
qemuBuildDriveDevStr(virDomainDiskDefPtr disk)
2830 2831 2832 2833 2834 2835
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;
    const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
    int idx = virDiskNameToIndex(disk->dst);

    if (idx < 0) {
2836 2837
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unsupported disk type '%s'"), disk->dst);
2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858
        goto error;
    }

    switch (disk->bus) {
    case VIR_DOMAIN_DISK_BUS_IDE:
        virBufferAddLit(&opt, "ide-drive");
        virBufferVSprintf(&opt, ",bus=ide.%d,unit=%d",
                          disk->info.addr.drive.bus,
                          disk->info.addr.drive.unit);
        break;
    case VIR_DOMAIN_DISK_BUS_SCSI:
        virBufferAddLit(&opt, "scsi-disk");
        virBufferVSprintf(&opt, ",bus=scsi%d.%d,scsi-id=%d",
                          disk->info.addr.drive.controller,
                          disk->info.addr.drive.bus,
                          disk->info.addr.drive.unit);
        break;
    case VIR_DOMAIN_DISK_BUS_VIRTIO:
        virBufferAddLit(&opt, "virtio-blk-pci");
        qemuBuildDeviceAddressStr(&opt, &disk->info);
        break;
2859 2860 2861
    case VIR_DOMAIN_DISK_BUS_USB:
        virBufferAddLit(&opt, "usb-storage");
        break;
2862
    default:
2863 2864
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unsupported disk bus '%s' with device setup"), bus);
2865 2866
        goto error;
    }
2867
    virBufferVSprintf(&opt, ",drive=%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias);
2868 2869
    virBufferVSprintf(&opt, ",id=%s", disk->info.alias);

2870
    if (virBufferError(&opt)) {
2871
        virReportOOMError();
2872 2873 2874 2875
        goto error;
    }

    return virBufferContentAndReset(&opt);
2876 2877 2878

error:
    virBufferFreeAndReset(&opt);
2879
    return NULL;
2880 2881 2882
}


2883 2884 2885 2886 2887 2888 2889
char *qemuBuildFSStr(virDomainFSDefPtr fs,
                     unsigned long long qemuCmdFlags ATTRIBUTE_UNUSED)
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;

    if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2890
                        _("only supports mount filesystem type"));
2891 2892 2893
        goto error;
    }

2894 2895 2896 2897 2898 2899 2900 2901
    virBufferAddLit(&opt, "local");
    if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_MAPPED) {
        virBufferAddLit(&opt, ",security_model=mapped");
    } else if(fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
        virBufferAddLit(&opt, ",security_model=passthrough");
    } else if(fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_SQUASH) {
        virBufferAddLit(&opt, ",security_model=none");
    }
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947
    virBufferVSprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
    virBufferVSprintf(&opt, ",path=%s", fs->src);

    if (virBufferError(&opt)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&opt);

error:
    virBufferFreeAndReset(&opt);
    return NULL;
}


char *
qemuBuildFSDevStr(virDomainFSDefPtr fs)
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;

    if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("can only passthrough directories"));
        goto error;
    }

    virBufferAddLit(&opt, "virtio-9p-pci");
    virBufferVSprintf(&opt, ",id=%s", fs->info.alias);
    virBufferVSprintf(&opt, ",fsdev=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
    virBufferVSprintf(&opt, ",mount_tag=%s", fs->dst);
    qemuBuildDeviceAddressStr(&opt, &fs->info);

    if (virBufferError(&opt)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&opt);

error:
    virBufferFreeAndReset(&opt);
    return NULL;
}


2948
char *
2949 2950 2951 2952 2953 2954 2955 2956 2957 2958
qemuBuildControllerDevStr(virDomainControllerDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    switch (def->type) {
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
        virBufferAddLit(&buf, "lsi");
        virBufferVSprintf(&buf, ",id=scsi%d", def->idx);
        break;

2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976
    case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
        if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
            virBufferAddLit(&buf, "virtio-serial-pci");
        } else {
            virBufferAddLit(&buf, "virtio-serial");
        }
        virBufferVSprintf(&buf, ",id=" QEMU_VIRTIO_SERIAL_PREFIX "%d",
                          def->idx);
        if (def->opts.vioserial.ports != -1) {
            virBufferVSprintf(&buf, ",max_ports=%d",
                              def->opts.vioserial.ports);
        }
        if (def->opts.vioserial.vectors != -1) {
            virBufferVSprintf(&buf, ",vectors=%d",
                              def->opts.vioserial.vectors);
        }
        break;

2977
    /* We always get an IDE controller, whether we want it or not. */
2978 2979 2980 2981 2982 2983 2984 2985
    case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
    default:
        goto error;
    }

    if (qemuBuildDeviceAddressStr(&buf, &def->info) < 0)
        goto error;

2986
    if (virBufferError(&buf)) {
2987
        virReportOOMError();
2988
        goto error;
2989
    }
2990 2991 2992 2993 2994 2995 2996 2997

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}

2998

2999
char *
3000
qemuBuildNicStr(virDomainNetDefPtr net,
3001
                const char *prefix,
3002
                int vlan)
3003
{
3004 3005
    char *str;
    if (virAsprintf(&str,
3006
                    "%smacaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s%s%s%s",
3007 3008 3009 3010 3011 3012
                    prefix ? prefix : "",
                    net->mac[0], net->mac[1],
                    net->mac[2], net->mac[3],
                    net->mac[4], net->mac[5],
                    vlan,
                    (net->model ? ",model=" : ""),
3013
                    (net->model ? net->model : ""),
D
Daniel P. Berrange 已提交
3014 3015
                    (net->info.alias ? ",name=" : ""),
                    (net->info.alias ? net->info.alias : "")) < 0) {
3016
        virReportOOMError();
3017
        return NULL;
3018 3019
    }

3020
    return str;
3021
}
3022

3023 3024

char *
3025
qemuBuildNicDevStr(virDomainNetDefPtr net, int vlan)
3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    const char *nic;

    if (!net->model) {
        nic = "rtl8139";
    } else if (STREQ(net->model, "virtio")) {
        nic = "virtio-net-pci";
    } else {
        nic = net->model;
    }

3038
    virBufferAdd(&buf, nic, strlen(nic));
3039 3040
    if (vlan == -1)
        virBufferVSprintf(&buf, ",netdev=host%s", net->info.alias);
3041
    else
3042
        virBufferVSprintf(&buf, ",vlan=%d", vlan);
3043 3044 3045 3046 3047 3048 3049 3050 3051
    virBufferVSprintf(&buf, ",id=%s", net->info.alias);
    virBufferVSprintf(&buf, ",mac=%02x:%02x:%02x:%02x:%02x:%02x",
                      net->mac[0], net->mac[1],
                      net->mac[2], net->mac[3],
                      net->mac[4], net->mac[5]);
    if (qemuBuildDeviceAddressStr(&buf, &net->info) < 0)
        goto error;

    if (virBufferError(&buf)) {
3052
        virReportOOMError();
3053 3054 3055 3056 3057 3058 3059 3060 3061 3062
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}

3063 3064

char *
3065
qemuBuildHostNetStr(virDomainNetDefPtr net,
3066 3067
                    char type_sep,
                    int vlan,
3068 3069
                    const char *tapfd,
                    const char *vhostfd)
3070
{
3071
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3072

3073 3074 3075
    switch (net->type) {
    case VIR_DOMAIN_NET_TYPE_NETWORK:
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
3076
    case VIR_DOMAIN_NET_TYPE_DIRECT:
3077 3078 3079
        virBufferAddLit(&buf, "tap");
        virBufferVSprintf(&buf, "%cfd=%s", type_sep, tapfd);
        type_sep = ',';
3080 3081 3082
        break;

    case VIR_DOMAIN_NET_TYPE_ETHERNET:
3083 3084 3085 3086 3087 3088 3089 3090 3091
        virBufferAddLit(&buf, "tap");
        if (net->ifname) {
            virBufferVSprintf(&buf, "%cifname=%s", type_sep, net->ifname);
            type_sep = ',';
        }
        if (net->data.ethernet.script) {
            virBufferVSprintf(&buf, "%cscript=%s", type_sep,
                              net->data.ethernet.script);
            type_sep = ',';
3092 3093 3094 3095 3096 3097
        }
        break;

    case VIR_DOMAIN_NET_TYPE_CLIENT:
    case VIR_DOMAIN_NET_TYPE_SERVER:
    case VIR_DOMAIN_NET_TYPE_MCAST:
3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117
        virBufferAddLit(&buf, "socket");
        switch (net->type) {
        case VIR_DOMAIN_NET_TYPE_CLIENT:
            virBufferVSprintf(&buf, "%cconnect=%s:%d",
                              type_sep,
                              net->data.socket.address,
                              net->data.socket.port);
            break;
        case VIR_DOMAIN_NET_TYPE_SERVER:
            virBufferVSprintf(&buf, "%clisten=%s:%d",
                              type_sep,
                              net->data.socket.address,
                              net->data.socket.port);
            break;
        case VIR_DOMAIN_NET_TYPE_MCAST:
            virBufferVSprintf(&buf, "%cmcast=%s:%d",
                              type_sep,
                              net->data.socket.address,
                              net->data.socket.port);
            break;
S
Stefan Berger 已提交
3118 3119 3120 3121 3122 3123 3124 3125
        case VIR_DOMAIN_NET_TYPE_USER:
        case VIR_DOMAIN_NET_TYPE_ETHERNET:
        case VIR_DOMAIN_NET_TYPE_NETWORK:
        case VIR_DOMAIN_NET_TYPE_BRIDGE:
        case VIR_DOMAIN_NET_TYPE_INTERNAL:
        case VIR_DOMAIN_NET_TYPE_DIRECT:
        case VIR_DOMAIN_NET_TYPE_LAST:
            break;
3126
        }
3127
        type_sep = ',';
3128 3129 3130 3131
        break;

    case VIR_DOMAIN_NET_TYPE_USER:
    default:
3132
        virBufferAddLit(&buf, "user");
3133 3134 3135
        break;
    }

3136 3137 3138 3139 3140 3141 3142 3143 3144
    if (vlan >= 0) {
        virBufferVSprintf(&buf, "%cvlan=%d", type_sep, vlan);
        if (net->info.alias)
            virBufferVSprintf(&buf, ",name=host%s",
                              net->info.alias);
    } else {
        virBufferVSprintf(&buf, "%cid=host%s",
                          type_sep, net->info.alias);
    }
3145

3146 3147 3148 3149
    if (vhostfd && *vhostfd) {
        virBufferVSprintf(&buf, ",vhost=on,vhostfd=%s", vhostfd);
    }

3150 3151
    if (virBufferError(&buf)) {
        virBufferFreeAndReset(&buf);
3152
        virReportOOMError();
3153
        return NULL;
3154 3155
    }

3156
    return virBufferContentAndReset(&buf);
3157 3158 3159
}


3160 3161
char *
qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev)
D
Daniel P. Berrange 已提交
3162 3163 3164 3165 3166
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    const char *model = virDomainWatchdogModelTypeToString(dev->model);
    if (!model) {
3167 3168
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("missing watchdog model"));
D
Daniel P. Berrange 已提交
3169 3170 3171 3172 3173 3174 3175 3176 3177
        goto error;
    }

    virBufferVSprintf(&buf, "%s", model);
    virBufferVSprintf(&buf, ",id=%s", dev->info.alias);
    if (qemuBuildDeviceAddressStr(&buf, &dev->info) < 0)
        goto error;

    if (virBufferError(&buf)) {
3178
        virReportOOMError();
D
Daniel P. Berrange 已提交
3179 3180 3181 3182 3183 3184 3185 3186 3187 3188
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}

3189

3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212
char *
qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virBufferAddLit(&buf, "virtio-balloon-pci");
    virBufferVSprintf(&buf, ",id=%s", dev->info.alias);
    if (qemuBuildDeviceAddressStr(&buf, &dev->info) < 0)
        goto error;

    if (virBufferError(&buf)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


3213 3214
char *
qemuBuildUSBInputDevStr(virDomainInputDefPtr dev)
3215 3216 3217 3218 3219 3220 3221 3222 3223
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virBufferVSprintf(&buf, "%s",
                      dev->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
                      "usb-mouse" : "usb-tablet");
    virBufferVSprintf(&buf, ",id=%s", dev->info.alias);

    if (virBufferError(&buf)) {
3224
        virReportOOMError();
3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


3236
char *
3237 3238 3239 3240 3241 3242
qemuBuildSoundDevStr(virDomainSoundDefPtr sound)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    const char *model = virDomainSoundModelTypeToString(sound->model);

    if (!model) {
3243 3244
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("invalid sound model"));
3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259
        goto error;
    }

    /* Hack for 2 wierdly unusal devices name in QEMU */
    if (STREQ(model, "es1370"))
        model = "ES1370";
    else if (STREQ(model, "ac97"))
        model = "AC97";

    virBufferVSprintf(&buf, "%s", model);
    virBufferVSprintf(&buf, ",id=%s", sound->info.alias);
    if (qemuBuildDeviceAddressStr(&buf, &sound->info) < 0)
        goto error;

    if (virBufferError(&buf)) {
3260
        virReportOOMError();
3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301
static char *
qemuBuildVideoDevStr(virDomainVideoDefPtr video)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    const char *model = qemuVideoTypeToString(video->type);

    if (!model) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("invalid video model"));
        goto error;
    }

    virBufferVSprintf(&buf, "%s", model);
    virBufferVSprintf(&buf, ",id=%s", video->info.alias);
    if (qemuBuildDeviceAddressStr(&buf, &video->info) < 0)
        goto error;

    if (virBufferError(&buf)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326
int
qemudOpenPCIConfig(virDomainHostdevDefPtr dev)
{
    char *path = NULL;
    int configfd = -1;

    if (virAsprintf(&path, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/config",
                    dev->source.subsys.u.pci.domain,
                    dev->source.subsys.u.pci.bus,
                    dev->source.subsys.u.pci.slot,
                    dev->source.subsys.u.pci.function) < 0) {
        virReportOOMError();
        return -1;
    }

    configfd = open(path, O_RDWR, 0);

    if (configfd < 0)
        virReportSystemError(errno, _("Failed opening %s"), path);

    VIR_FREE(path);

    return configfd;
}

3327
char *
3328
qemuBuildPCIHostdevDevStr(virDomainHostdevDefPtr dev, const char *configfd)
3329 3330 3331 3332 3333 3334 3335 3336 3337
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virBufferAddLit(&buf, "pci-assign");
    virBufferVSprintf(&buf, ",host=%.2x:%.2x.%.1x",
                      dev->source.subsys.u.pci.bus,
                      dev->source.subsys.u.pci.slot,
                      dev->source.subsys.u.pci.function);
    virBufferVSprintf(&buf, ",id=%s", dev->info.alias);
3338 3339
    if (configfd && *configfd)
        virBufferVSprintf(&buf, ",configfd=%s", configfd);
3340 3341 3342 3343
    if (qemuBuildDeviceAddressStr(&buf, &dev->info) < 0)
        goto error;

    if (virBufferError(&buf)) {
3344
        virReportOOMError();
3345 3346 3347 3348 3349 3350 3351 3352 3353 3354
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}

3355

3356 3357 3358 3359 3360 3361 3362 3363 3364
char *
qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev)
{
    char *ret = NULL;

    if (virAsprintf(&ret, "host=%.2x:%.2x.%.1x",
                    dev->source.subsys.u.pci.bus,
                    dev->source.subsys.u.pci.slot,
                    dev->source.subsys.u.pci.function) < 0)
3365
        virReportOOMError();
3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377

    return ret;
}


char *
qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev)
{
    char *ret = NULL;

    if (!dev->source.subsys.u.usb.bus &&
        !dev->source.subsys.u.usb.device) {
3378 3379
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("USB host device is missing bus/device information"));
3380 3381 3382
        return NULL;
    }

3383
    if (virAsprintf(&ret, "usb-host,hostbus=%d,hostaddr=%d,id=%s",
3384 3385 3386
                    dev->source.subsys.u.usb.bus,
                    dev->source.subsys.u.usb.device,
                    dev->info.alias) < 0)
3387
        virReportOOMError();
3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399

    return ret;
}


char *
qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev)
{
    char *ret = NULL;

    if (!dev->source.subsys.u.usb.bus &&
        !dev->source.subsys.u.usb.device) {
3400 3401
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("USB host device is missing bus/device information"));
3402 3403 3404
        return NULL;
    }

3405
    if (virAsprintf(&ret, "host:%d.%d",
3406 3407
                    dev->source.subsys.u.usb.bus,
                    dev->source.subsys.u.usb.device) < 0)
3408
        virReportOOMError();
3409 3410 3411 3412 3413 3414

    return ret;
}



3415
/* This function outputs a -chardev command line option which describes only the
3416
 * host side of the character device */
3417 3418
char *
qemuBuildChrChardevStr(virDomainChrDefPtr dev)
3419
{
3420
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3421
    bool telnet;
3422

3423 3424
    switch(dev->type) {
    case VIR_DOMAIN_CHR_TYPE_NULL:
3425
        virBufferVSprintf(&buf, "null,id=%s", dev->info.alias);
3426 3427 3428
        break;

    case VIR_DOMAIN_CHR_TYPE_VC:
3429
        virBufferVSprintf(&buf, "vc,id=%s", dev->info.alias);
3430 3431 3432
        break;

    case VIR_DOMAIN_CHR_TYPE_PTY:
3433
        virBufferVSprintf(&buf, "pty,id=%s", dev->info.alias);
3434 3435 3436
        break;

    case VIR_DOMAIN_CHR_TYPE_DEV:
3437
        virBufferVSprintf(&buf, "tty,id=%s,path=%s", dev->info.alias, dev->data.file.path);
3438 3439 3440
        break;

    case VIR_DOMAIN_CHR_TYPE_FILE:
3441
        virBufferVSprintf(&buf, "file,id=%s,path=%s", dev->info.alias, dev->data.file.path);
3442 3443 3444
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
3445
        virBufferVSprintf(&buf, "pipe,id=%s,path=%s", dev->info.alias, dev->data.file.path);
3446 3447 3448
        break;

    case VIR_DOMAIN_CHR_TYPE_STDIO:
3449
        virBufferVSprintf(&buf, "stdio,id=%s", dev->info.alias);
3450 3451 3452
        break;

    case VIR_DOMAIN_CHR_TYPE_UDP:
3453
        virBufferVSprintf(&buf,
3454
                          "udp,id=%s,host=%s,port=%s,localaddr=%s,localport=%s",
3455
                          dev->info.alias,
3456 3457 3458 3459 3460 3461 3462 3463
                          dev->data.udp.connectHost,
                          dev->data.udp.connectService,
                          dev->data.udp.bindHost,
                          dev->data.udp.bindService);
        break;

    case VIR_DOMAIN_CHR_TYPE_TCP:
        telnet = dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
3464
        virBufferVSprintf(&buf,
3465
                          "socket,id=%s,host=%s,port=%s%s%s",
3466
                          dev->info.alias,
3467 3468 3469 3470 3471 3472 3473
                          dev->data.tcp.host,
                          dev->data.tcp.service,
                          telnet ? ",telnet" : "",
                          dev->data.tcp.listen ? ",server,nowait" : "");
        break;

    case VIR_DOMAIN_CHR_TYPE_UNIX:
3474
        virBufferVSprintf(&buf,
3475
                          "socket,id=%s,path=%s%s",
3476
                          dev->info.alias,
3477 3478 3479 3480
                          dev->data.nix.path,
                          dev->data.nix.listen ? ",server,nowait" : "");
        break;
    }
3481 3482

    if (virBufferError(&buf)) {
3483
        virReportOOMError();
3484 3485 3486 3487 3488 3489 3490 3491
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
3492 3493
}

3494 3495 3496

char *
qemuBuildChrArgStr(virDomainChrDefPtr dev, const char *prefix)
3497
{
3498 3499 3500 3501 3502
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (prefix)
        virBufferAdd(&buf, prefix, strlen(prefix));

3503 3504
    switch (dev->type) {
    case VIR_DOMAIN_CHR_TYPE_NULL:
3505
        virBufferAddLit(&buf, "null");
3506 3507
        break;

3508
    case VIR_DOMAIN_CHR_TYPE_VC:
3509
        virBufferAddLit(&buf, "vc");
3510 3511
        break;

3512
    case VIR_DOMAIN_CHR_TYPE_PTY:
3513
        virBufferAddLit(&buf, "pty");
3514 3515
        break;

3516
    case VIR_DOMAIN_CHR_TYPE_DEV:
3517
        virBufferStrcat(&buf, dev->data.file.path, NULL);
3518 3519
        break;

3520
    case VIR_DOMAIN_CHR_TYPE_FILE:
3521
        virBufferVSprintf(&buf, "file:%s", dev->data.file.path);
3522 3523
        break;

3524
    case VIR_DOMAIN_CHR_TYPE_PIPE:
3525
        virBufferVSprintf(&buf, "pipe:%s", dev->data.file.path);
3526 3527
        break;

3528
    case VIR_DOMAIN_CHR_TYPE_STDIO:
3529
        virBufferAddLit(&buf, "stdio");
3530 3531
        break;

3532
    case VIR_DOMAIN_CHR_TYPE_UDP:
3533
        virBufferVSprintf(&buf, "udp:%s:%s@%s:%s",
3534 3535 3536 3537
                          dev->data.udp.connectHost,
                          dev->data.udp.connectService,
                          dev->data.udp.bindHost,
                          dev->data.udp.bindService);
3538 3539
        break;

3540
    case VIR_DOMAIN_CHR_TYPE_TCP:
3541
        if (dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET) {
3542
            virBufferVSprintf(&buf, "telnet:%s:%s%s",
3543 3544 3545
                              dev->data.tcp.host,
                              dev->data.tcp.service,
                              dev->data.tcp.listen ? ",server,nowait" : "");
3546
        } else {
3547
            virBufferVSprintf(&buf, "tcp:%s:%s%s",
3548 3549 3550
                              dev->data.tcp.host,
                              dev->data.tcp.service,
                              dev->data.tcp.listen ? ",server,nowait" : "");
3551
        }
3552 3553
        break;

3554
    case VIR_DOMAIN_CHR_TYPE_UNIX:
3555
        virBufferVSprintf(&buf, "unix:%s%s",
3556 3557
                          dev->data.nix.path,
                          dev->data.nix.listen ? ",server,nowait" : "");
3558 3559
        break;
    }
3560 3561

    if (virBufferError(&buf)) {
3562
        virReportOOMError();
3563 3564 3565 3566 3567 3568 3569 3570
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
3571 3572
}

3573

3574 3575 3576 3577
char *
qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
C
Cole Robinson 已提交
3578 3579 3580 3581
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE)
        virBufferAddLit(&buf, "virtconsole");
    else
        virBufferAddLit(&buf, "virtserialport");
3582 3583 3584 3585 3586 3587 3588

    if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
        /* Check it's a virtio-serial address */
        if (dev->info.type !=
            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL)
        {
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
L
Laine Stump 已提交
3589
                            "%s", _("virtio serial device has invalid address type"));
3590 3591 3592 3593 3594 3595 3596
            goto error;
        }

        virBufferVSprintf(&buf,
                          ",bus=" QEMU_VIRTIO_SERIAL_PREFIX "%d.%d",
                          dev->info.addr.vioserial.controller,
                          dev->info.addr.vioserial.bus);
3597 3598 3599
        virBufferVSprintf(&buf,
                          ",nr=%d",
                          dev->info.addr.vioserial.port);
3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617
    }

    virBufferVSprintf(&buf, ",chardev=%s", dev->info.alias);
    if (dev->target.name) {
        virBufferVSprintf(&buf, ",name=%s", dev->target.name);
    }
    if (virBufferError(&buf)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}

3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629
static char *qemuBuildSmbiosBiosStr(virSysinfoDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if ((def->bios_vendor == NULL) && (def->bios_version == NULL) &&
        (def->bios_date == NULL) && (def->bios_release == NULL))
        return(NULL);

    virBufferAddLit(&buf, "type=0");

    /* 0:Vendor */
    if (def->bios_vendor)
3630
        virBufferVSprintf(&buf, ",vendor=%s", def->bios_vendor);
3631 3632
    /* 0:BIOS Version */
    if (def->bios_version)
3633
        virBufferVSprintf(&buf, ",version=%s", def->bios_version);
3634 3635
    /* 0:BIOS Release Date */
    if (def->bios_date)
3636
        virBufferVSprintf(&buf, ",date=%s", def->bios_date);
3637 3638
    /* 0:System BIOS Major Release and 0:System BIOS Minor Release */
    if (def->bios_release)
3639
        virBufferVSprintf(&buf, ",release=%s", def->bios_release);
3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652

    if (virBufferError(&buf)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return(NULL);
}

3653
static char *qemuBuildSmbiosSystemStr(virSysinfoDefPtr def, bool skip_uuid)
3654 3655 3656 3657
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if ((def->system_manufacturer == NULL) && (def->system_sku == NULL) &&
3658 3659 3660 3661
        (def->system_product == NULL) && (def->system_version == NULL) &&
        (def->system_serial == NULL) && (def->system_family == NULL) &&
        (def->system_uuid == NULL || skip_uuid))
        return NULL;
3662 3663 3664 3665 3666

    virBufferAddLit(&buf, "type=1");

    /* 1:Manufacturer */
    if (def->system_manufacturer)
3667
        virBufferVSprintf(&buf, ",manufacturer=%s",
3668 3669 3670
                          def->system_manufacturer);
     /* 1:Product Name */
    if (def->system_product)
3671
        virBufferVSprintf(&buf, ",product=%s", def->system_product);
3672 3673
    /* 1:Version */
    if (def->system_version)
3674
        virBufferVSprintf(&buf, ",version=%s", def->system_version);
3675 3676
    /* 1:Serial Number */
    if (def->system_serial)
3677
        virBufferVSprintf(&buf, ",serial=%s", def->system_serial);
3678
    /* 1:UUID */
3679
    if (def->system_uuid && !skip_uuid)
3680
        virBufferVSprintf(&buf, ",uuid=%s", def->system_uuid);
3681 3682
    /* 1:SKU Number */
    if (def->system_sku)
3683
        virBufferVSprintf(&buf, ",sku=%s", def->system_sku);
E
Eric Blake 已提交
3684 3685 3686
    /* 1:Family */
    if (def->system_family)
        virBufferVSprintf(&buf, ",family=%s", def->system_family);
3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698

    if (virBufferError(&buf)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return(NULL);
}
3699

3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710
static char *
qemuBuildClockArgStr(virDomainClockDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    switch (def->offset) {
    case VIR_DOMAIN_CLOCK_OFFSET_UTC:
        virBufferAddLit(&buf, "base=utc");
        break;

    case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
3711
    case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
3712 3713 3714 3715 3716 3717 3718 3719 3720 3721
        virBufferAddLit(&buf, "base=localtime");
        break;

    case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: {
        time_t now = time(NULL);
        struct tm nowbits;

        now += def->data.adjustment;
        gmtime_r(&now, &nowbits);

3722
        virBufferVSprintf(&buf, "base=%d-%02d-%02dT%02d:%02d:%02d",
3723
                          nowbits.tm_year + 1900,
3724
                          nowbits.tm_mon + 1,
3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737
                          nowbits.tm_mday,
                          nowbits.tm_hour,
                          nowbits.tm_min,
                          nowbits.tm_sec);
    }   break;

    default:
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("unsupported clock offset '%s'"),
                        virDomainClockOffsetTypeToString(def->offset));
        goto error;
    }

3738 3739 3740 3741
    /* Look for an 'rtc' timer element, and add in appropriate clock= and driftfix= */
    int i;
    for (i = 0; i < def->ntimers; i++) {
        if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) {
3742 3743 3744 3745 3746 3747 3748 3749 3750
            switch (def->timers[i]->track) {
            case -1: /* unspecified - use hypervisor default */
                break;
            case VIR_DOMAIN_TIMER_TRACK_BOOT:
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                _("unsupported rtc timer track '%s'"),
                                virDomainTimerTrackTypeToString(def->timers[i]->track));
                goto error;
            case VIR_DOMAIN_TIMER_TRACK_GUEST:
3751
                virBufferAddLit(&buf, ",clock=vm");
3752 3753 3754 3755
                break;
            case VIR_DOMAIN_TIMER_TRACK_WALL:
                virBufferAddLit(&buf, ",clock=host");
                break;
3756
            }
3757

3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778
            switch (def->timers[i]->tickpolicy) {
            case -1:
            case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
                /* This is the default - missed ticks delivered when
                   next scheduled, at normal rate */
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
                /* deliver ticks at a faster rate until caught up */
                virBufferAddLit(&buf, ",driftfix=slew");
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
            case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                _("unsupported rtc timer tickpolicy '%s'"),
                                virDomainTimerTickpolicyTypeToString(def->timers[i]->tickpolicy));
                goto error;
            }
            break; /* no need to check other timers - there is only one rtc */
        }
    }

3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791
    if (virBufferError(&buf)) {
        virReportOOMError();
        goto error;
    }

    return virBufferContentAndReset(&buf);

error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


3792
static int
3793
qemuBuildCpuArgStr(const struct qemud_driver *driver,
3794 3795
                   const virDomainDefPtr def,
                   const char *emulator,
3796
                   unsigned long long qemuCmdFlags,
3797
                   const struct utsname *ut,
D
Daniel P. Berrange 已提交
3798 3799
                   char **opt,
                   bool *hasHwVirt)
3800 3801 3802
{
    const virCPUDefPtr host = driver->caps->host.cpu;
    virCPUDefPtr guest = NULL;
3803
    unsigned int ncpus = 0;
3804 3805 3806 3807 3808 3809
    const char **cpus = NULL;
    union cpuData *data = NULL;
    int ret = -1;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    int i;

D
Daniel P. Berrange 已提交
3810 3811
    *hasHwVirt = false;

3812
    if (def->cpu && def->cpu->model) {
3813 3814
        if (qemudProbeCPUModels(emulator, qemuCmdFlags, ut->machine,
                                &ncpus, &cpus) < 0)
3815 3816 3817
            goto cleanup;

        if (!ncpus || !host) {
3818
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3819 3820 3821 3822
                            _("CPU specification not supported by hypervisor"));
            goto cleanup;
        }
    }
3823

3824
    if (ncpus > 0 && host) {
3825
        virCPUCompareResult cmp;
3826
        const char *preferred;
D
Daniel P. Berrange 已提交
3827
        int hasSVM;
3828

3829
        cmp = cpuGuestData(host, def->cpu, &data);
3830 3831
        switch (cmp) {
        case VIR_CPU_COMPARE_INCOMPATIBLE:
3832 3833
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("guest CPU is not compatible with host CPU"));
3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844
            /* fall through */
        case VIR_CPU_COMPARE_ERROR:
            goto cleanup;

        default:
            break;
        }

        if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(ut->machine)))
            goto no_memory;

3845 3846 3847 3848 3849
        if (def->cpu->match == VIR_CPU_MATCH_MINIMUM)
            preferred = host->model;
        else
            preferred = def->cpu->model;

3850
        guest->type = VIR_CPU_TYPE_GUEST;
3851
        if (cpuDecode(guest, data, cpus, ncpus, preferred) < 0)
3852 3853
            goto cleanup;

D
Daniel P. Berrange 已提交
3854 3855 3856 3857 3858 3859 3860 3861
        /* Only 'svm' requires --enable-nesting. The nested
         * 'vmx' patches now simply hook off the CPU features
         */
        hasSVM = cpuHasFeature(guest->arch, data, "svm");
        if (hasSVM < 0)
            goto cleanup;
        *hasHwVirt = hasSVM > 0 ? true : false;

3862
        virBufferVSprintf(&buf, "%s", guest->model);
3863 3864 3865 3866 3867 3868 3869 3870 3871
        for (i = 0; i < guest->nfeatures; i++) {
            char sign;
            if (guest->features[i].policy == VIR_CPU_FEATURE_DISABLE)
                sign = '-';
            else
                sign = '+';

            virBufferVSprintf(&buf, ",%c%s", sign, guest->features[i].name);
        }
3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901
    }
    else {
        /*
         * Need to force a 32-bit guest CPU type if
         *
         *  1. guest OS is i686
         *  2. host OS is x86_64
         *  3. emulator is qemu-kvm or kvm
         *
         * Or
         *
         *  1. guest OS is i686
         *  2. emulator is qemu-system-x86_64
         */
        if (STREQ(def->os.arch, "i686") &&
            ((STREQ(ut->machine, "x86_64") &&
              strstr(emulator, "kvm")) ||
             strstr(emulator, "x86_64")))
            virBufferAddLit(&buf, "qemu32");
    }

    if (virBufferError(&buf))
        goto no_memory;

    *opt = virBufferContentAndReset(&buf);

    ret = 0;

cleanup:
    virCPUDefFree(guest);
3902
    cpuDataFree(ut->machine, data);
3903 3904 3905 3906 3907 3908 3909 3910 3911 3912

    if (cpus) {
        for (i = 0; i < ncpus; i++)
            VIR_FREE(cpus[i]);
        VIR_FREE(cpus);
    }

    return ret;

no_memory:
3913
    virReportOOMError();
3914 3915 3916
    goto cleanup;
}

3917
static char *
3918
qemuBuildSmpArgStr(const virDomainDefPtr def,
3919
                   unsigned long long qemuCmdFlags)
3920 3921 3922
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

E
Eric Blake 已提交
3923
    virBufferVSprintf(&buf, "%u", def->vcpus);
3924 3925

    if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) {
3926 3927
        if (def->vcpus != def->maxvcpus)
            virBufferVSprintf(&buf, ",maxcpus=%u", def->maxvcpus);
3928 3929 3930 3931 3932 3933 3934 3935
        /* sockets, cores, and threads are either all zero
         * or all non-zero, thus checking one of them is enough */
        if (def->cpu && def->cpu->sockets) {
            virBufferVSprintf(&buf, ",sockets=%u", def->cpu->sockets);
            virBufferVSprintf(&buf, ",cores=%u", def->cpu->cores);
            virBufferVSprintf(&buf, ",threads=%u", def->cpu->threads);
        }
        else {
E
Eric Blake 已提交
3936
            virBufferVSprintf(&buf, ",sockets=%u", def->maxvcpus);
3937 3938 3939
            virBufferVSprintf(&buf, ",cores=%u", 1);
            virBufferVSprintf(&buf, ",threads=%u", 1);
        }
3940
    } else if (def->vcpus != def->maxvcpus) {
E
Eric Blake 已提交
3941
        virBufferFreeAndReset(&buf);
3942
        /* FIXME - consider hot-unplugging cpus after boot for older qemu */
E
Eric Blake 已提交
3943 3944
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("setting current vcpu count less than maximum is "
3945
                          "not supported with this QEMU binary"));
E
Eric Blake 已提交
3946 3947
        return NULL;
    }
3948 3949 3950

    if (virBufferError(&buf)) {
        virBufferFreeAndReset(&buf);
3951
        virReportOOMError();
3952 3953 3954 3955 3956 3957
        return NULL;
    }

    return virBufferContentAndReset(&buf);
}

3958

D
Daniel P. Berrange 已提交
3959 3960 3961
/*
 * Constructs a argv suitable for launching qemu with config defined
 * for a given virtual machine.
3962 3963 3964
 *
 * XXX 'conn' is only required to resolve network -> bridge name
 * figure out how to remove this requirement some day
D
Daniel P. Berrange 已提交
3965
 */
E
Eric Blake 已提交
3966 3967 3968 3969 3970 3971 3972 3973 3974 3975
virCommandPtr
qemudBuildCommandLine(virConnectPtr conn,
                      struct qemud_driver *driver,
                      virDomainDefPtr def,
                      virDomainChrDefPtr monitor_chr,
                      bool monitor_json,
                      unsigned long long qemuCmdFlags,
                      const char *migrateFrom,
                      virDomainSnapshotObjPtr current_snapshot,
                      enum virVMOperationType vmop)
C
Chris Lalancette 已提交
3976
{
3977
    int i;
3978
    char boot[VIR_DOMAIN_BOOT_LAST+1];
3979 3980
    struct utsname ut;
    int disableKQEMU = 0;
3981
    int enableKQEMU = 0;
3982
    int disableKVM = 0;
3983
    int enableKVM = 0;
3984
    const char *emulator;
3985
    char uuid[VIR_UUID_STRING_BUFLEN];
3986
    char *cpu;
3987
    char *smp;
S
Stefan Berger 已提交
3988
    int last_good_net = -1;
D
Daniel P. Berrange 已提交
3989
    bool hasHwVirt = false;
E
Eric Blake 已提交
3990
    virCommandPtr cmd;
D
Daniel P. Berrange 已提交
3991

3992
    uname_normalize(&ut);
3993

3994
    if (qemuAssignDeviceAliases(def, qemuCmdFlags) < 0)
E
Eric Blake 已提交
3995
        return NULL;
3996

3997
    virUUIDFormat(def->uuid, uuid);
3998

3999 4000 4001 4002 4003 4004
    /* Migration is very annoying due to wildly varying syntax & capabilities
     * over time of KVM / QEMU codebases
     */
    if (migrateFrom) {
        if (STRPREFIX(migrateFrom, "tcp")) {
            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP)) {
4005
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4006
                                "%s", _("TCP migration is not supported with this QEMU binary"));
E
Eric Blake 已提交
4007
                return NULL;
4008 4009 4010 4011 4012
            }
        } else if (STREQ(migrateFrom, "stdio")) {
            if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) {
                migrateFrom = "exec:cat";
            } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO)) {
4013
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4014
                                "%s", _("STDIO migration is not supported with this QEMU binary"));
E
Eric Blake 已提交
4015
                return NULL;
4016 4017 4018
            }
        } else if (STRPREFIX(migrateFrom, "exec")) {
            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)) {
4019
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4020
                                "%s", _("STDIO migration is not supported with this QEMU binary"));
E
Eric Blake 已提交
4021
                return NULL;
4022 4023 4024 4025
            }
        }
    }

4026
    emulator = def->emulator;
4027

4028 4029 4030
    /*
     * do not use boot=on for drives when not using KVM since this
     * is not supported at all in upstream QEmu.
4031 4032
     */
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_KVM) &&
4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043
        (def->virtType == VIR_DOMAIN_VIRT_QEMU) &&
        (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT))
        qemuCmdFlags -= QEMUD_CMD_FLAG_DRIVE_BOOT;

    switch (def->virtType) {
    case VIR_DOMAIN_VIRT_QEMU:
        if (qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU)
            disableKQEMU = 1;
        if (qemuCmdFlags & QEMUD_CMD_FLAG_KVM)
            disableKVM = 1;
        break;
4044

4045 4046 4047
    case VIR_DOMAIN_VIRT_KQEMU:
        if (qemuCmdFlags & QEMUD_CMD_FLAG_KVM)
            disableKVM = 1;
4048

4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080
        if (qemuCmdFlags & QEMUD_CMD_FLAG_ENABLE_KQEMU) {
            enableKQEMU = 1;
        } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU)) {
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("the QEMU binary %s does not support kqemu"),
                            emulator);
        }
        break;

    case VIR_DOMAIN_VIRT_KVM:
        if (qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU)
            disableKQEMU = 1;

        if (qemuCmdFlags & QEMUD_CMD_FLAG_ENABLE_KVM) {
            enableKVM = 1;
        } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_KVM)) {
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("the QEMU binary %s does not support kvm"),
                            emulator);
        }
        break;

    case VIR_DOMAIN_VIRT_XEN:
        /* XXX better check for xenner */
        break;

    default:
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("the QEMU binary %s does not support %s"),
                        emulator, virDomainVirtTypeToString(def->virtType));
        break;
    }
4081

E
Eric Blake 已提交
4082
    cmd = virCommandNewArgList(emulator, "-S", NULL);
4083

E
Eric Blake 已提交
4084
    virCommandAddEnvPassCommon(cmd);
4085 4086 4087 4088 4089

    /* This should *never* be NULL, since we always provide
     * a machine in the capabilities data for QEMU. So this
     * check is just here as a safety in case the unexpected
     * happens */
E
Eric Blake 已提交
4090 4091
    if (def->os.machine)
        virCommandAddArgList(cmd, "-M", def->os.machine, NULL);
4092

D
Daniel P. Berrange 已提交
4093 4094
    if (qemuBuildCpuArgStr(driver, def, emulator, qemuCmdFlags,
                           &ut, &cpu, &hasHwVirt) < 0)
4095 4096
        goto error;

4097
    if (cpu) {
E
Eric Blake 已提交
4098
        virCommandAddArgList(cmd, "-cpu", cpu, NULL);
4099
        VIR_FREE(cpu);
D
Daniel P. Berrange 已提交
4100 4101 4102

        if ((qemuCmdFlags & QEMUD_CMD_FLAG_NESTING) &&
            hasHwVirt)
E
Eric Blake 已提交
4103
            virCommandAddArg(cmd, "-enable-nesting");
4104
    }
4105

4106
    if (disableKQEMU)
E
Eric Blake 已提交
4107 4108 4109
        virCommandAddArg(cmd, "-no-kqemu");
    else if (enableKQEMU)
        virCommandAddArgList(cmd, "-enable-kqemu", "-kernel-kqemu", NULL);
4110
    if (disableKVM)
E
Eric Blake 已提交
4111
        virCommandAddArg(cmd, "-no-kvm");
4112
    if (enableKVM)
E
Eric Blake 已提交
4113 4114 4115 4116 4117 4118 4119 4120
        virCommandAddArg(cmd, "-enable-kvm");

    /* Set '-m MB' based on maxmem, because the lower 'memory' limit
     * is set post-startup using the balloon driver. If balloon driver
     * is not supported, then they're out of luck anyway
     */
    virCommandAddArg(cmd, "-m");
    virCommandAddArgFormat(cmd, "%lu", def->mem.max_balloon / 1024);
4121
    if (def->mem.hugepage_backed) {
4122
        if (!driver->hugetlbfs_mount) {
4123 4124
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("hugetlbfs filesystem is not mounted"));
4125 4126 4127
            goto error;
        }
        if (!driver->hugepage_path) {
4128 4129
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("hugepages are disabled by administrator config"));
4130 4131 4132
            goto error;
        }
        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MEM_PATH)) {
4133 4134 4135
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("hugepage backing not supported by '%s'"),
                            def->emulator);
4136 4137
            goto error;
        }
E
Eric Blake 已提交
4138 4139
        virCommandAddArgList(cmd, "-mem-prealloc", "-mem-path",
                             driver->hugepage_path, NULL);
4140
    }
4141

E
Eric Blake 已提交
4142
    virCommandAddArg(cmd, "-smp");
4143
    if (!(smp = qemuBuildSmpArgStr(def, qemuCmdFlags)))
4144
        goto error;
E
Eric Blake 已提交
4145 4146
    virCommandAddArg(cmd, smp);
    VIR_FREE(smp);
D
Daniel P. Berrange 已提交
4147

4148
    if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
E
Eric Blake 已提交
4149
        virCommandAddArg(cmd, "-name");
4150 4151
        if (driver->setProcessName &&
            (qemuCmdFlags & QEMUD_CMD_FLAG_NAME_PROCESS)) {
E
Eric Blake 已提交
4152 4153
            virCommandAddArgFormat(cmd, "%s,process=qemu:%s",
                                   def->name, def->name);
4154
        } else {
E
Eric Blake 已提交
4155
            virCommandAddArg(cmd, def->name);
4156
        }
4157
    }
E
Eric Blake 已提交
4158 4159
    if (qemuCmdFlags & QEMUD_CMD_FLAG_UUID)
        virCommandAddArgList(cmd, "-uuid", uuid, NULL);
4160 4161 4162 4163
    if (def->virtType == VIR_DOMAIN_VIRT_XEN ||
        STREQ(def->os.type, "xen") ||
        STREQ(def->os.type, "linux")) {
        if (qemuCmdFlags & QEMUD_CMD_FLAG_DOMID) {
E
Eric Blake 已提交
4164 4165
            virCommandAddArg(cmd, "-domid");
            virCommandAddArgFormat(cmd, "%d", def->id);
4166
        } else if (qemuCmdFlags & QEMUD_CMD_FLAG_XEN_DOMID) {
E
Eric Blake 已提交
4167 4168 4169
            virCommandAddArg(cmd, "-xen-attach");
            virCommandAddArg(cmd, "-xen-domid");
            virCommandAddArgFormat(cmd, "%d", def->id);
4170
        } else {
4171 4172 4173
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("qemu emulator '%s' does not support xen"),
                            def->emulator);
4174 4175
            goto error;
        }
4176 4177 4178 4179 4180
    }

    if ((def->os.smbios_mode != VIR_DOMAIN_SMBIOS_NONE) &&
        (def->os.smbios_mode != VIR_DOMAIN_SMBIOS_EMULATE)) {
        virSysinfoDefPtr source = NULL;
4181
        bool skip_uuid = false;
4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192

        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_SMBIOS_TYPE)) {
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                    _("the QEMU binary %s does not support smbios settings"),
                            emulator);
            goto error;
        }

        /* should we really error out or just warn in those cases ? */
        if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_HOST) {
            if (driver->hostsysinfo == NULL) {
4193
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
4194 4195 4196 4197
                            _("Host SMBIOS information is not available"));
                goto error;
            }
            source = driver->hostsysinfo;
4198 4199
            /* Host and guest uuid must differ, by definition of UUID. */
            skip_uuid = true;
4200 4201 4202 4203 4204 4205 4206 4207
        } else if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_SYSINFO) {
            if (def->sysinfo == NULL) {
                qemuReportError(VIR_ERR_XML_ERROR,
                            _("Domain '%s' sysinfo are not available"),
                               def->name);
                goto error;
            }
            source = def->sysinfo;
4208
            /* domain_conf guaranteed that system_uuid matches guest uuid. */
4209 4210 4211 4212 4213 4214
        }
        if (source != NULL) {
            char *smbioscmd;

            smbioscmd = qemuBuildSmbiosBiosStr(source);
            if (smbioscmd != NULL) {
E
Eric Blake 已提交
4215 4216
                virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
                VIR_FREE(smbioscmd);
4217
            }
4218
            smbioscmd = qemuBuildSmbiosSystemStr(source, skip_uuid);
4219
            if (smbioscmd != NULL) {
E
Eric Blake 已提交
4220 4221
                virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
                VIR_FREE(smbioscmd);
4222 4223
            }
        }
4224 4225
    }

4226 4227 4228 4229 4230 4231 4232
    /*
     * NB, -nographic *MUST* come before any serial, or monitor
     * or parallel port flags due to QEMU craziness, where it
     * decides to change the serial port & monitor to be on stdout
     * if you ask for nographic. So we have to make sure we override
     * these defaults ourselves...
     */
4233
    if (!def->graphics)
E
Eric Blake 已提交
4234
        virCommandAddArg(cmd, "-nographic");
4235

4236
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
4237
        if (qemuCmdFlags & QEMUD_CMD_FLAG_NODEFCONFIG)
E
Eric Blake 已提交
4238 4239 4240 4241
            virCommandAddArg(cmd,
                             "-nodefconfig"); /* Disable global config files */
        virCommandAddArg(cmd,
                         "-nodefaults");  /* Disable default guest devices */
4242
    }
4243

4244
    if (monitor_chr) {
4245
        char *chrdev;
4246 4247 4248
        /* Use -chardev if it's available */
        if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) {

E
Eric Blake 已提交
4249
            virCommandAddArg(cmd, "-chardev");
4250 4251
            if (!(chrdev = qemuBuildChrChardevStr(monitor_chr)))
                goto error;
E
Eric Blake 已提交
4252 4253
            virCommandAddArg(cmd, chrdev);
            VIR_FREE(chrdev);
4254

E
Eric Blake 已提交
4255 4256 4257
            virCommandAddArg(cmd, "-mon");
            virCommandAddArgFormat(cmd, "chardev=monitor,mode=%s",
                                   monitor_json ? "control" : "readline");
4258
        } else {
4259
            const char *prefix = NULL;
4260
            if (monitor_json)
4261
                prefix = "control,";
4262

E
Eric Blake 已提交
4263
            virCommandAddArg(cmd, "-monitor");
4264 4265
            if (!(chrdev = qemuBuildChrArgStr(monitor_chr, prefix)))
                goto error;
E
Eric Blake 已提交
4266 4267
            virCommandAddArg(cmd, chrdev);
            VIR_FREE(chrdev);
4268
        }
4269
    }
D
Daniel P. Berrange 已提交
4270

4271 4272
    if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC) {
        const char *rtcopt;
E
Eric Blake 已提交
4273
        virCommandAddArg(cmd, "-rtc");
4274 4275
        if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
            goto error;
E
Eric Blake 已提交
4276 4277
        virCommandAddArg(cmd, rtcopt);
        VIR_FREE(rtcopt);
4278 4279 4280
    } else {
        switch (def->clock.offset) {
        case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
4281
        case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
E
Eric Blake 已提交
4282
            virCommandAddArg(cmd, "-localtime");
4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294
            break;

        case VIR_DOMAIN_CLOCK_OFFSET_UTC:
            /* Nothing, its the default */
            break;

        default:
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("unsupported clock offset '%s'"),
                            virDomainClockOffsetTypeToString(def->clock.offset));
            goto error;
        }
4295
    }
4296 4297
    if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE &&
        def->clock.data.timezone) {
E
Eric Blake 已提交
4298
        virCommandAddEnvPair(cmd, "TZ", def->clock.data.timezone);
4299
    }
4300

4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321
    for (i = 0; i < def->clock.ntimers; i++) {
        switch (def->clock.timers[i]->name) {
        default:
        case VIR_DOMAIN_TIMER_NAME_PLATFORM:
        case VIR_DOMAIN_TIMER_NAME_TSC:
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("unsupported timer type (name) '%s'"),
                            virDomainTimerNameTypeToString(def->clock.timers[i]->name));
            goto error;

        case VIR_DOMAIN_TIMER_NAME_RTC:
            /* This has already been taken care of (in qemuBuildClockArgStr)
               if QEMUD_CMD_FLAG_RTC is set (mutually exclusive with
               QEMUD_FLAG_RTC_TD_HACK) */
            if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC_TD_HACK) {
                switch (def->clock.timers[i]->tickpolicy) {
                case -1:
                case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
                    /* the default - do nothing */
                    break;
                case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
E
Eric Blake 已提交
4322
                    virCommandAddArg(cmd, "-rtc-td-hack");
4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350
                    break;
                case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
                case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
                    qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                    _("unsupported rtc tickpolicy '%s'"),
                                    virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
                goto error;
                }
            } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_RTC)
                       && (def->clock.timers[i]->tickpolicy
                           != VIR_DOMAIN_TIMER_TICKPOLICY_DELAY)
                       && (def->clock.timers[i]->tickpolicy != -1)) {
                /* a non-default rtc policy was given, but there is no
                   way to implement it in this version of qemu */
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                _("unsupported rtc tickpolicy '%s'"),
                                virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
                goto error;
            }
            break;

        case VIR_DOMAIN_TIMER_NAME_PIT:
            switch (def->clock.timers[i]->tickpolicy) {
            case -1:
            case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
                /* delay is the default if we don't have kernel
                   (-no-kvm-pit), otherwise, the default is catchup. */
                if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT)
E
Eric Blake 已提交
4351
                    virCommandAddArg(cmd, "-no-kvm-pit-reinjection");
4352 4353 4354 4355 4356 4357
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
                if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT) {
                    /* do nothing - this is default for kvm-pit */
                } else if (qemuCmdFlags & QEMUD_CMD_FLAG_TDF) {
                    /* -tdf switches to 'catchup' with userspace pit. */
E
Eric Blake 已提交
4358
                    virCommandAddArg(cmd, "-tdf");
4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386
                } else {
                    /* can't catchup if we have neither pit mode */
                    qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                    _("unsupported pit tickpolicy '%s'"),
                                    virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
                    goto error;
                }
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
            case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
                /* no way to support these modes for pit in qemu */
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                _("unsupported pit tickpolicy '%s'"),
                                virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
                goto error;
            }
            break;

        case VIR_DOMAIN_TIMER_NAME_HPET:
            /* the only meaningful attribute for hpet is "present". If
             * present is -1, that means it wasn't specified, and
             * should be left at the default for the
             * hypervisor. "default" when -no-hpet exists is "yes",
             * and when -no-hpet doesn't exist is "no". "confusing"?
             * "yes"! */

            if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_HPET) {
                if (def->clock.timers[i]->present == 0)
E
Eric Blake 已提交
4387
                    virCommandAddArg(cmd, "-no-hpet");
4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399
            } else {
                /* no hpet timer available. The only possible action
                   is to raise an error if present="yes" */
                if (def->clock.timers[i]->present == 1) {
                    qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                    "%s", _("pit timer is not supported"));
                }
            }
            break;
        }
    }

4400
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
4401
        def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
E
Eric Blake 已提交
4402
        virCommandAddArg(cmd, "-no-reboot");
D
Daniel P. Berrange 已提交
4403

4404
    if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
E
Eric Blake 已提交
4405
        virCommandAddArg(cmd, "-no-acpi");
D
Daniel P. Berrange 已提交
4406

4407 4408 4409
    if (!def->os.bootloader) {
        for (i = 0 ; i < def->os.nBootDevs ; i++) {
            switch (def->os.bootDevs[i]) {
4410
            case VIR_DOMAIN_BOOT_CDROM:
D
Daniel P. Berrange 已提交
4411 4412
                boot[i] = 'd';
                break;
4413
            case VIR_DOMAIN_BOOT_FLOPPY:
D
Daniel P. Berrange 已提交
4414 4415
                boot[i] = 'a';
                break;
4416
            case VIR_DOMAIN_BOOT_DISK:
D
Daniel P. Berrange 已提交
4417 4418
                boot[i] = 'c';
                break;
4419
            case VIR_DOMAIN_BOOT_NET:
D
Daniel P. Berrange 已提交
4420 4421 4422 4423 4424 4425 4426
                boot[i] = 'n';
                break;
            default:
                boot[i] = 'c';
                break;
            }
        }
4427
        if (def->os.nBootDevs) {
4428
            virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
E
Eric Blake 已提交
4429 4430
            char *bootstr;
            virCommandAddArg(cmd, "-boot");
4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448

            boot[def->os.nBootDevs] = '\0';

            if (qemuCmdFlags & QEMUD_CMD_FLAG_BOOT_MENU &&
                def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
                if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_ENABLED)
                    virBufferVSprintf(&boot_buf, "order=%s,menu=on", boot);
                else if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_DISABLED)
                    virBufferVSprintf(&boot_buf, "order=%s,menu=off", boot);
            } else {
                virBufferVSprintf(&boot_buf, "%s", boot);
            }

            if (virBufferError(&boot_buf)) {
                virReportOOMError();
                goto error;
            }

E
Eric Blake 已提交
4449 4450 4451
            bootstr = virBufferContentAndReset(&boot_buf);
            virCommandAddArg(cmd, bootstr);
            VIR_FREE(bootstr);
4452
        }
D
Daniel P. Berrange 已提交
4453

E
Eric Blake 已提交
4454 4455 4456 4457 4458 4459
        if (def->os.kernel)
            virCommandAddArgList(cmd, "-kernel", def->os.kernel, NULL);
        if (def->os.initrd)
            virCommandAddArgList(cmd, "-initrd", def->os.initrd, NULL);
        if (def->os.cmdline)
            virCommandAddArgList(cmd, "-append", def->os.cmdline, NULL);
D
Daniel P. Berrange 已提交
4460
    } else {
E
Eric Blake 已提交
4461
        virCommandAddArgList(cmd, "-bootloader", def->os.bootloader, NULL);
D
Daniel P. Berrange 已提交
4462 4463
    }

4464 4465
    for (i = 0 ; i < def->ndisks ; i++) {
        virDomainDiskDefPtr disk = def->disks[i];
4466 4467 4468

        if (disk->driverName != NULL &&
            !STREQ(disk->driverName, "qemu")) {
4469 4470 4471
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("unsupported driver name '%s' for disk '%s'"),
                            disk->driverName, disk->src);
4472 4473 4474 4475
            goto error;
        }
    }

4476 4477
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        for (i = 0 ; i < def->ncontrollers ; i++) {
4478 4479 4480 4481 4482 4483 4484
            virDomainControllerDefPtr cont = def->controllers[i];

            /* We don't add an explicit IDE or FD controller because the
             * provided PIIX4 device already includes one. It isn't possible to
             * remove the PIIX4. */
            if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE ||
                cont->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC)
4485 4486
                continue;

4487 4488
            /* QEMU doesn't implement a SATA driver */
            if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA) {
4489
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4490
                                "%s", _("SATA is not supported with this QEMU binary"));
4491 4492 4493
                goto error;
            }

E
Eric Blake 已提交
4494
            virCommandAddArg(cmd, "-device");
4495

4496 4497
            char *devstr;
            if (!(devstr = qemuBuildControllerDevStr(def->controllers[i])))
4498 4499
                goto no_memory;

E
Eric Blake 已提交
4500 4501
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
4502 4503 4504
        }
    }

4505
    /* If QEMU supports -drive param instead of old -hda, -hdb, -cdrom .. */
4506
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
4507 4508 4509
        int bootCD = 0, bootFloppy = 0, bootDisk = 0;

        /* If QEMU supports boot=on for -drive param... */
4510
        if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
4511 4512
            for (i = 0 ; i < def->os.nBootDevs ; i++) {
                switch (def->os.bootDevs[i]) {
4513
                case VIR_DOMAIN_BOOT_CDROM:
4514 4515
                    bootCD = 1;
                    break;
4516
                case VIR_DOMAIN_BOOT_FLOPPY:
4517 4518
                    bootFloppy = 1;
                    break;
4519
                case VIR_DOMAIN_BOOT_DISK:
4520 4521 4522
                    bootDisk = 1;
                    break;
                }
4523
            }
4524
        }
D
Daniel P. Berrange 已提交
4525

4526
        for (i = 0 ; i < def->ndisks ; i++) {
4527
            char *optstr;
4528
            int bootable = 0;
4529
            virDomainDiskDefPtr disk = def->disks[i];
4530
            int withDeviceArg = 0;
D
Daniel P. Berrange 已提交
4531

4532 4533 4534 4535
            /* Unless we have -device, then USB disks need special
               handling */
            if ((disk->bus == VIR_DOMAIN_DISK_BUS_USB) &&
                !(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
4536
                if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
E
Eric Blake 已提交
4537 4538
                    virCommandAddArg(cmd, "-usbdevice");
                    virCommandAddArgFormat(cmd, "disk:%s", disk->src);
4539
                } else {
4540
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
E
Eric Blake 已提交
4541 4542
                                    _("unsupported usb disk type for '%s'"),
                                    disk->src);
4543 4544 4545 4546 4547
                    goto error;
                }
                continue;
            }

4548
            switch (disk->device) {
4549
            case VIR_DOMAIN_DISK_DEVICE_CDROM:
4550 4551 4552
                bootable = bootCD;
                bootCD = 0;
                break;
4553
            case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
4554 4555 4556
                bootable = bootFloppy;
                bootFloppy = 0;
                break;
4557
            case VIR_DOMAIN_DISK_DEVICE_DISK:
4558 4559 4560 4561 4562
                bootable = bootDisk;
                bootDisk = 0;
                break;
            }

E
Eric Blake 已提交
4563
            virCommandAddArg(cmd, "-drive");
4564

E
Eric Blake 已提交
4565 4566
            /* Unfortunately it is not possible to use
               -device for floppies, or Xen paravirt
4567 4568 4569 4570 4571 4572 4573 4574 4575
               devices. Fortunately, those don't need
               static PCI addresses, so we don't really
               care that we can't use -device */
            if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
                (disk->bus != VIR_DOMAIN_DISK_BUS_XEN))
                withDeviceArg = 1;
            if (!(optstr = qemuBuildDriveStr(disk, bootable,
                                             (withDeviceArg ? qemuCmdFlags :
                                              (qemuCmdFlags & ~QEMUD_CMD_FLAG_DEVICE)))))
4576
                goto error;
E
Eric Blake 已提交
4577 4578
            virCommandAddArg(cmd, optstr);
            VIR_FREE(optstr);
4579 4580 4581

            if (withDeviceArg) {
                if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC) {
E
Eric Blake 已提交
4582 4583 4584 4585 4586
                    virCommandAddArg(cmd, "-global");
                    virCommandAddArgFormat(cmd, "isa-fdc.drive%c=drive-%s",
                                           disk->info.addr.drive.unit
                                           ? 'B' : 'A',
                                           disk->info.alias);
4587
                } else {
E
Eric Blake 已提交
4588
                    virCommandAddArg(cmd, "-device");
4589

4590
                    if (!(optstr = qemuBuildDriveDevStr(disk)))
4591
                        goto error;
E
Eric Blake 已提交
4592 4593
                    virCommandAddArg(cmd, optstr);
                    VIR_FREE(optstr);
4594 4595
                }
            }
4596 4597
        }
    } else {
4598
        for (i = 0 ; i < def->ndisks ; i++) {
4599 4600
            char dev[NAME_MAX];
            char file[PATH_MAX];
4601
            virDomainDiskDefPtr disk = def->disks[i];
4602

4603 4604
            if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
                if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
E
Eric Blake 已提交
4605 4606
                    virCommandAddArg(cmd, "-usbdevice");
                    virCommandAddArgFormat(cmd, "disk:%s", disk->src);
4607
                } else {
4608
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
E
Eric Blake 已提交
4609 4610
                                    _("unsupported usb disk type for '%s'"),
                                    disk->src);
4611 4612 4613 4614 4615
                    goto error;
                }
                continue;
            }

4616
            if (STREQ(disk->dst, "hdc") &&
4617 4618
                disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
                if (disk->src) {
4619 4620 4621 4622 4623 4624 4625 4626 4627
                    snprintf(dev, NAME_MAX, "-%s", "cdrom");
                } else {
                    continue;
                }
            } else {
                if (STRPREFIX(disk->dst, "hd") ||
                    STRPREFIX(disk->dst, "fd")) {
                    snprintf(dev, NAME_MAX, "-%s", disk->dst);
                } else {
4628 4629
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("unsupported disk type '%s'"), disk->dst);
4630 4631 4632 4633
                    goto error;
                }
            }

4634 4635 4636 4637
            if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
                /* QEMU only supports magic FAT format for now */
                if (disk->driverType &&
                    STRNEQ(disk->driverType, "fat")) {
4638 4639 4640
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("unsupported disk driver type for '%s'"),
                                    disk->driverType);
4641 4642 4643
                    goto error;
                }
                if (!disk->readonly) {
4644 4645
                    qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                    _("cannot create virtual FAT disks in read-write mode"));
4646 4647 4648 4649 4650 4651 4652 4653 4654
                    goto error;
                }
                if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
                    snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src);
                else
                    snprintf(file, PATH_MAX, "fat:%s", disk->src);
            } else {
                snprintf(file, PATH_MAX, "%s", disk->src);
            }
4655

E
Eric Blake 已提交
4656
            virCommandAddArgList(cmd, dev, file, NULL);
4657
        }
D
Daniel P. Berrange 已提交
4658 4659
    }

4660 4661 4662 4663 4664
    if (qemuCmdFlags & QEMUD_CMD_FLAG_FSDEV) {
        for (i = 0 ; i < def->nfss ; i++) {
            char *optstr;
            virDomainFSDefPtr fs = def->fss[i];

E
Eric Blake 已提交
4665
            virCommandAddArg(cmd, "-fsdev");
4666 4667
            if (!(optstr = qemuBuildFSStr(fs, qemuCmdFlags)))
                goto error;
E
Eric Blake 已提交
4668 4669
            virCommandAddArg(cmd, optstr);
            VIR_FREE(optstr);
4670

E
Eric Blake 已提交
4671
            virCommandAddArg(cmd, "-device");
4672 4673
            if (!(optstr = qemuBuildFSDevStr(fs)))
                goto error;
E
Eric Blake 已提交
4674 4675
            virCommandAddArg(cmd, optstr);
            VIR_FREE(optstr);
4676 4677 4678 4679 4680 4681 4682 4683 4684
        }
    } else {
        if (def->nfss) {
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("filesystem passthrough not supported by this QEMU"));
            goto error;
        }
    }

4685
    if (!def->nnets) {
4686
        /* If we have -device, then we set -nodefault already */
E
Eric Blake 已提交
4687 4688
        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
            virCommandAddArgList(cmd, "-net", "none", NULL);
D
Daniel P. Berrange 已提交
4689
    } else {
4690 4691
        for (i = 0 ; i < def->nnets ; i++) {
            virDomainNetDefPtr net = def->nets[i];
4692
            char *nic, *host;
4693
            char tapfd_name[50];
4694
            char vhostfd_name[50] = "";
4695
            int vlan;
4696

4697 4698 4699
            /* VLANs are not used with -netdev, so don't record them */
            if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
                (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
4700
                vlan = -1;
4701
            else
4702
                vlan = i;
4703

4704 4705
            if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
                net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
E
Eric Blake 已提交
4706 4707
                int tapfd = qemudNetworkIfaceConnect(conn, driver, net,
                                                     qemuCmdFlags);
4708 4709
                if (tapfd < 0)
                    goto error;
4710

4711
                last_good_net = i;
E
Eric Blake 已提交
4712
                virCommandTransferFD(cmd, tapfd);
4713

E
Eric Blake 已提交
4714 4715
                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
                             tapfd) >= sizeof(tapfd_name))
4716 4717
                    goto no_memory;
            } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
S
Stefan Berger 已提交
4718
                int tapfd = qemudPhysIfaceConnect(conn, driver, net,
4719
                                                  qemuCmdFlags,
4720 4721
                                                  def->uuid,
                                                  vmop);
4722 4723 4724
                if (tapfd < 0)
                    goto error;

4725
                last_good_net = i;
E
Eric Blake 已提交
4726
                virCommandTransferFD(cmd, tapfd);
4727

E
Eric Blake 已提交
4728 4729
                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
                             tapfd) >= sizeof(tapfd_name))
4730
                    goto no_memory;
4731
            }
D
Daniel P. Berrange 已提交
4732

4733 4734 4735 4736 4737 4738 4739
            if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
                net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
                net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
                /* Attempt to use vhost-net mode for these types of
                   network device */
                int vhostfd = qemudOpenVhostNet(net, qemuCmdFlags);
                if (vhostfd >= 0) {
E
Eric Blake 已提交
4740
                    virCommandTransferFD(cmd, vhostfd);
4741

E
Eric Blake 已提交
4742 4743
                    if (snprintf(vhostfd_name, sizeof(vhostfd_name), "%d",
                                 vhostfd) >= sizeof(vhostfd_name))
4744 4745 4746
                        goto no_memory;
                }
            }
4747 4748 4749 4750 4751 4752 4753 4754 4755 4756
            /* Possible combinations:
             *
             *  1. Old way:   -net nic,model=e1000,vlan=1 -net tap,vlan=1
             *  2. Semi-new:  -device e1000,vlan=1        -net tap,vlan=1
             *  3. Best way:  -netdev type=tap,id=netdev1 -device e1000,id=netdev1
             *
             * NB, no support for -netdev without use of -device
             */
            if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
                (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
E
Eric Blake 已提交
4757
                virCommandAddArg(cmd, "-netdev");
4758 4759
                if (!(host = qemuBuildHostNetStr(net, ',', vlan,
                                                 tapfd_name, vhostfd_name)))
4760
                    goto error;
E
Eric Blake 已提交
4761 4762
                virCommandAddArg(cmd, host);
                VIR_FREE(host);
4763 4764
            }
            if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
E
Eric Blake 已提交
4765
                virCommandAddArg(cmd, "-device");
4766
                if (!(nic = qemuBuildNicDevStr(net, vlan)))
4767
                    goto error;
E
Eric Blake 已提交
4768 4769
                virCommandAddArg(cmd, nic);
                VIR_FREE(nic);
4770
            } else {
E
Eric Blake 已提交
4771
                virCommandAddArg(cmd, "-net");
4772
                if (!(nic = qemuBuildNicStr(net, "nic,", vlan)))
4773
                    goto error;
E
Eric Blake 已提交
4774 4775
                virCommandAddArg(cmd, nic);
                VIR_FREE(nic);
4776 4777 4778
            }
            if (!((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
                  (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))) {
E
Eric Blake 已提交
4779
                virCommandAddArg(cmd, "-net");
4780 4781
                if (!(host = qemuBuildHostNetStr(net, ',', vlan,
                                                 tapfd_name, vhostfd_name)))
4782
                    goto error;
E
Eric Blake 已提交
4783 4784
                virCommandAddArg(cmd, host);
                VIR_FREE(host);
4785
            }
D
Daniel P. Berrange 已提交
4786 4787 4788
        }
    }

4789
    if (!def->nserials) {
4790
        /* If we have -device, then we set -nodefault already */
E
Eric Blake 已提交
4791 4792
        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
            virCommandAddArgList(cmd, "-serial", "none", NULL);
4793
    } else {
4794 4795
        for (i = 0 ; i < def->nserials ; i++) {
            virDomainChrDefPtr serial = def->serials[i];
4796
            char *devstr;
4797

4798 4799 4800
            /* Use -chardev with -device if they are available */
            if ((qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) &&
                (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
E
Eric Blake 已提交
4801
                virCommandAddArg(cmd, "-chardev");
4802 4803
                if (!(devstr = qemuBuildChrChardevStr(serial)))
                    goto error;
E
Eric Blake 已提交
4804 4805
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
4806

E
Eric Blake 已提交
4807 4808 4809
                virCommandAddArg(cmd, "-device");
                virCommandAddArgFormat(cmd, "isa-serial,chardev=%s",
                                       serial->info.alias);
4810
            } else {
E
Eric Blake 已提交
4811
                virCommandAddArg(cmd, "-serial");
4812 4813
                if (!(devstr = qemuBuildChrArgStr(serial, NULL)))
                    goto error;
E
Eric Blake 已提交
4814 4815
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
4816
            }
4817 4818 4819
        }
    }

4820
    if (!def->nparallels) {
4821
        /* If we have -device, then we set -nodefault already */
E
Eric Blake 已提交
4822 4823
        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
            virCommandAddArgList(cmd, "-parallel", "none", NULL);
4824
    } else {
4825 4826
        for (i = 0 ; i < def->nparallels ; i++) {
            virDomainChrDefPtr parallel = def->parallels[i];
4827
            char *devstr;
4828

4829 4830 4831
            /* Use -chardev with -device if they are available */
            if ((qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) &&
                (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
E
Eric Blake 已提交
4832
                virCommandAddArg(cmd, "-chardev");
4833 4834
                if (!(devstr = qemuBuildChrChardevStr(parallel)))
                    goto error;
E
Eric Blake 已提交
4835 4836
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
4837

E
Eric Blake 已提交
4838 4839 4840
                virCommandAddArg(cmd, "-device");
                virCommandAddArgFormat(cmd, "isa-parallel,chardev=%s",
                                       parallel->info.alias);
4841
            } else {
E
Eric Blake 已提交
4842
                virCommandAddArg(cmd, "-parallel");
4843 4844
                if (!(devstr = qemuBuildChrArgStr(parallel, NULL)))
                      goto error;
E
Eric Blake 已提交
4845 4846
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
4847
            }
4848 4849 4850
        }
    }

4851 4852
    for (i = 0 ; i < def->nchannels ; i++) {
        virDomainChrDefPtr channel = def->channels[i];
4853
        char *devstr;
4854

4855 4856
        switch(channel->targetType) {
        case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
4857 4858
            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) ||
                !(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
4859
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4860
                                "%s", _("guestfwd requires QEMU to support -chardev & -device"));
4861 4862 4863
                goto error;
            }

E
Eric Blake 已提交
4864
            virCommandAddArg(cmd, "-chardev");
4865 4866
            if (!(devstr = qemuBuildChrChardevStr(channel)))
                goto error;
E
Eric Blake 已提交
4867 4868
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
4869

4870
            char *addr = virSocketFormatAddr(channel->target.addr);
4871 4872
            if (!addr)
                goto error;
M
Matthew Booth 已提交
4873 4874
            int port = virSocketGetPort(channel->target.addr);

E
Eric Blake 已提交
4875 4876 4877 4878 4879
            virCommandAddArg(cmd, "-netdev");
            virCommandAddArgFormat(cmd,
                                   "user,guestfwd=tcp:%s:%i,chardev=%s,id=user-%s",
                                   addr, port, channel->info.alias,
                                   channel->info.alias);
4880
            VIR_FREE(addr);
4881 4882
            break;

4883
        case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
4884
            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
4885
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
4886 4887 4888 4889
                    _("virtio channel requires QEMU to support -device"));
                goto error;
            }

E
Eric Blake 已提交
4890
            virCommandAddArg(cmd, "-chardev");
4891 4892
            if (!(devstr = qemuBuildChrChardevStr(channel)))
                goto error;
E
Eric Blake 已提交
4893 4894
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
4895

E
Eric Blake 已提交
4896
            virCommandAddArg(cmd, "-device");
4897 4898
            if (!(devstr = qemuBuildVirtioSerialPortDevStr(channel)))
                goto error;
E
Eric Blake 已提交
4899 4900
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
4901
            break;
4902 4903 4904
        }
    }

C
Cole Robinson 已提交
4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917
    /* Explicit console devices */
    if (def->console) {
        virDomainChrDefPtr console = def->console;
        char *devstr;

        switch(console->targetType) {
        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
                qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
                    _("virtio channel requires QEMU to support -device"));
                goto error;
            }

E
Eric Blake 已提交
4918
            virCommandAddArg(cmd, "-chardev");
C
Cole Robinson 已提交
4919 4920
            if (!(devstr = qemuBuildChrChardevStr(console)))
                goto error;
E
Eric Blake 已提交
4921 4922
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
C
Cole Robinson 已提交
4923

E
Eric Blake 已提交
4924
            virCommandAddArg(cmd, "-device");
C
Cole Robinson 已提交
4925 4926
            if (!(devstr = qemuBuildVirtioSerialPortDevStr(console)))
                goto error;
E
Eric Blake 已提交
4927 4928
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
C
Cole Robinson 已提交
4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941
            break;

        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
            break;

        default:
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("unsupported console target type %s"),
                            NULLSTR(virDomainChrConsoleTargetTypeToString(console->targetType)));
            goto error;
        }
    }

E
Eric Blake 已提交
4942
    virCommandAddArg(cmd, "-usb");
4943 4944
    for (i = 0 ; i < def->ninputs ; i++) {
        virDomainInputDefPtr input = def->inputs[i];
4945

4946
        if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
4947 4948
            if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
                char *optstr;
E
Eric Blake 已提交
4949
                virCommandAddArg(cmd, "-device");
4950 4951
                if (!(optstr = qemuBuildUSBInputDevStr(input)))
                    goto error;
E
Eric Blake 已提交
4952 4953
                virCommandAddArg(cmd, optstr);
                VIR_FREE(optstr);
4954
            } else {
E
Eric Blake 已提交
4955 4956 4957
                virCommandAddArgList(cmd, "-usbdevice",
                                     input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE
                                     ? "mouse" : "tablet", NULL);
4958
            }
4959 4960 4961
        }
    }

4962 4963 4964 4965 4966 4967
    if (def->ngraphics > 1) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("only 1 graphics device is supported"));
        goto error;
    }

4968 4969
    if ((def->ngraphics == 1) &&
        def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
4970 4971
        virBuffer opt = VIR_BUFFER_INITIALIZER;
        char *optstr;
D
Daniel P. Berrange 已提交
4972

4973
        if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
4974 4975
            if (def->graphics[0]->data.vnc.listenAddr)
                virBufferAdd(&opt, def->graphics[0]->data.vnc.listenAddr, -1);
4976 4977 4978 4979
            else if (driver->vncListen)
                virBufferAdd(&opt, driver->vncListen, -1);

            virBufferVSprintf(&opt, ":%d",
4980
                              def->graphics[0]->data.vnc.port - 5900);
4981

4982
            if (def->graphics[0]->data.vnc.auth.passwd ||
4983 4984 4985
                driver->vncPassword)
                virBufferAddLit(&opt, ",password");

D
Daniel P. Berrange 已提交
4986
            if (driver->vncTLS) {
4987
                virBufferAddLit(&opt, ",tls");
D
Daniel P. Berrange 已提交
4988
                if (driver->vncTLSx509verify) {
4989 4990
                    virBufferVSprintf(&opt, ",x509verify=%s",
                                      driver->vncTLSx509certdir);
D
Daniel P. Berrange 已提交
4991
                } else {
4992 4993
                    virBufferVSprintf(&opt, ",x509=%s",
                                      driver->vncTLSx509certdir);
D
Daniel P. Berrange 已提交
4994 4995
                }
            }
4996 4997 4998 4999 5000

            if (driver->vncSASL) {
                virBufferAddLit(&opt, ",sasl");

                if (driver->vncSASLdir)
E
Eric Blake 已提交
5001 5002
                    virCommandAddEnvPair(cmd, "SASL_CONF_DIR",
                                         driver->vncSASLdir);
5003 5004 5005

                /* TODO: Support ACLs later */
            }
D
Daniel P. Berrange 已提交
5006
        } else {
5007
            virBufferVSprintf(&opt, "%d",
5008
                              def->graphics[0]->data.vnc.port - 5900);
D
Daniel P. Berrange 已提交
5009
        }
5010 5011
        if (virBufferError(&opt)) {
            virBufferFreeAndReset(&opt);
5012
            goto no_memory;
5013
        }
5014 5015

        optstr = virBufferContentAndReset(&opt);
5016

E
Eric Blake 已提交
5017 5018
        virCommandAddArgList(cmd, "-vnc", optstr, NULL);
        VIR_FREE(optstr);
5019
        if (def->graphics[0]->data.vnc.keymap) {
E
Eric Blake 已提交
5020 5021
            virCommandAddArgList(cmd, "-k", def->graphics[0]->data.vnc.keymap,
                                 NULL);
5022
        }
5023

5024 5025 5026
        /* Unless user requested it, set the audio backend to none, to
         * prevent it opening the host OS audio devices, since that causes
         * security issues and might not work when using VNC.
5027
         */
5028
        if (driver->vncAllowHostAudio) {
E
Eric Blake 已提交
5029
            virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
5030
        } else {
E
Eric Blake 已提交
5031
            virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
5032
        }
5033 5034
    } else if ((def->ngraphics == 1) &&
               def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
E
Eric Blake 已提交
5035 5036 5037 5038 5039 5040
        if (def->graphics[0]->data.sdl.xauth)
            virCommandAddEnvPair(cmd, "XAUTHORITY",
                                 def->graphics[0]->data.sdl.xauth);
        if (def->graphics[0]->data.sdl.display)
            virCommandAddEnvPair(cmd, "DISPLAY",
                                 def->graphics[0]->data.sdl.display);
5041
        if (def->graphics[0]->data.sdl.fullscreen)
E
Eric Blake 已提交
5042
            virCommandAddArg(cmd, "-full-screen");
5043 5044 5045 5046 5047

        /* If using SDL for video, then we should just let it
         * use QEMU's host audio drivers, possibly SDL too
         * User can set these two before starting libvirtd
         */
E
Eric Blake 已提交
5048 5049
        virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
        virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");
5050 5051 5052 5053 5054

        /* New QEMU has this flag to let us explicitly ask for
         * SDL graphics. This is better than relying on the
         * default, since the default changes :-( */
        if (qemuCmdFlags & QEMUD_CMD_FLAG_SDL)
E
Eric Blake 已提交
5055
            virCommandAddArg(cmd, "-sdl");
5056

5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069
    } else if ((def->ngraphics == 1) &&
               def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
        virBuffer opt = VIR_BUFFER_INITIALIZER;
        char *optstr;

        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_SPICE)) {
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("spice graphics are not supported with this QEMU"));
            goto error;
        }

        virBufferVSprintf(&opt, "port=%u", def->graphics[0]->data.spice.port);

5070
        if (driver->spiceTLS && def->graphics[0]->data.spice.tlsPort != -1)
5071 5072 5073 5074
            virBufferVSprintf(&opt, ",tls-port=%u", def->graphics[0]->data.spice.tlsPort);

        if (def->graphics[0]->data.spice.listenAddr)
            virBufferVSprintf(&opt, ",addr=%s", def->graphics[0]->data.spice.listenAddr);
5075 5076 5077 5078 5079 5080
        else if (driver->spiceListen)
            virBufferVSprintf(&opt, ",addr=%s", driver->spiceListen);

        /* In the password case we set it via monitor command, to avoid
         * making it visible on CLI, so there's no use of password=XXX
         * in this bit of the code */
5081
        if (!def->graphics[0]->data.spice.auth.passwd &&
5082 5083 5084 5085 5086 5087 5088
            !driver->spicePassword)
            virBufferAddLit(&opt, ",disable-ticketing");

        if (driver->spiceTLS)
            virBufferVSprintf(&opt, ",x509-dir=%s",
                              driver->spiceTLSx509certdir);

5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101
        for (i = 0 ; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST ; i++) {
            int mode = def->graphics[0]->data.spice.channels[i];
            switch (mode) {
            case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
                virBufferVSprintf(&opt, ",tls-channel=%s",
                                  virDomainGraphicsSpiceChannelNameTypeToString(i));
                break;
            case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
                virBufferVSprintf(&opt, ",plaintext-channel=%s",
                                  virDomainGraphicsSpiceChannelNameTypeToString(i));
                break;
            }
        }
5102 5103 5104 5105 5106 5107

        if (virBufferError(&opt))
            goto no_memory;

        optstr = virBufferContentAndReset(&opt);

E
Eric Blake 已提交
5108 5109 5110 5111 5112
        virCommandAddArgList(cmd, "-spice", optstr, NULL);
        VIR_FREE(optstr);
        if (def->graphics[0]->data.spice.keymap)
            virCommandAddArgList(cmd, "-k",
                                 def->graphics[0]->data.spice.keymap, NULL);
5113 5114 5115
        /* SPICE includes native support for tunnelling audio, so we
         * set the audio backend to point at SPICE's own driver
         */
E
Eric Blake 已提交
5116
        virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=spice");
5117

5118 5119 5120 5121 5122
    } else if ((def->ngraphics == 1)) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    _("unsupported graphics type '%s'"),
                    virDomainGraphicsTypeToString(def->graphics[0]->type));
        goto error;
D
Daniel P. Berrange 已提交
5123 5124
    }

5125
    if (def->nvideos > 0) {
5126 5127 5128 5129
        if (qemuCmdFlags & QEMUD_CMD_FLAG_VGA) {
            if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_XEN) {
                /* nothing - vga has no effect on Xen pvfb */
            } else {
5130 5131 5132 5133 5134 5135 5136
                if ((def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_QXL) &&
                    !(qemuCmdFlags & QEMUD_CMD_FLAG_VGA_QXL)) {
                    qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                    _("This QEMU does not support QXL graphics adapters"));
                    goto error;
                }

5137
                const char *vgastr = qemuVideoTypeToString(def->videos[0]->type);
5138
                if (!vgastr || STREQ(vgastr, "")) {
5139
                    qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5140 5141
                                    _("video type %s is not supported with QEMU"),
                                    virDomainVideoTypeToString(def->videos[0]->type));
5142 5143 5144
                    goto error;
                }

E
Eric Blake 已提交
5145
                virCommandAddArgList(cmd, "-vga", vgastr, NULL);
5146 5147 5148 5149 5150
            }
        } else {

            switch (def->videos[0]->type) {
            case VIR_DOMAIN_VIDEO_TYPE_VGA:
E
Eric Blake 已提交
5151
                virCommandAddArg(cmd, "-std-vga");
5152 5153 5154
                break;

            case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
E
Eric Blake 已提交
5155
                virCommandAddArg(cmd, "-vmwarevga");
5156 5157 5158 5159 5160 5161 5162 5163
                break;

            case VIR_DOMAIN_VIDEO_TYPE_XEN:
            case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
                /* No special args - this is the default */
                break;

            default:
5164 5165
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                _("video type %s is not supported with this QEMU"),
5166
                                virDomainVideoTypeToString(def->videos[0]->type));
5167 5168 5169
                goto error;
            }
        }
5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181

        if (def->nvideos > 1) {
            if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
                for (i = 1 ; i < def->nvideos ; i++) {
                    char *str;
                    if (def->videos[i]->type != VIR_DOMAIN_VIDEO_TYPE_QXL) {
                        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                        _("video type %s is only valid as primary video card"),
                                        virDomainVideoTypeToString(def->videos[0]->type));
                        goto error;
                    }

E
Eric Blake 已提交
5182
                    virCommandAddArg(cmd, "-device");
5183 5184 5185 5186

                    if (!(str = qemuBuildVideoDevStr(def->videos[i])))
                        goto error;

E
Eric Blake 已提交
5187 5188
                    virCommandAddArg(cmd, str);
                    VIR_FREE(str);
5189 5190 5191 5192 5193 5194 5195 5196
                }
            } else {
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                "%s", _("only one video card is currently supported"));
                goto error;
            }
        }

5197 5198 5199
    } else {
        /* If we have -device, then we set -nodefault already */
        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
5200 5201
            (qemuCmdFlags & QEMUD_CMD_FLAG_VGA) &&
            (qemuCmdFlags & QEMUD_CMD_FLAG_VGA_NONE))
E
Eric Blake 已提交
5202
            virCommandAddArgList(cmd, "-vga", "none", NULL);
5203 5204
    }

D
Daniel Veillard 已提交
5205
    /* Add sound hardware */
5206
    if (def->nsounds) {
5207 5208 5209 5210 5211 5212 5213 5214 5215
        if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
            for (i = 0 ; i < def->nsounds ; i++) {
                virDomainSoundDefPtr sound = def->sounds[i];
                char *str = NULL;

                /* Sadly pcspk device doesn't use -device syntax. Fortunately
                 * we don't need to set any PCI address on it, so we don't
                 * mind too much */
                if (sound->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) {
E
Eric Blake 已提交
5216
                    virCommandAddArgList(cmd, "-soundhw", "pcspk", NULL);
5217
                } else {
E
Eric Blake 已提交
5218
                    virCommandAddArg(cmd, "-device");
D
Daniel Veillard 已提交
5219

5220 5221 5222
                    if (!(str = qemuBuildSoundDevStr(sound)))
                        goto error;

E
Eric Blake 已提交
5223 5224
                    virCommandAddArg(cmd, str);
                    VIR_FREE(str);
5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237
                }
            }
        } else {
            int size = 100;
            char *modstr;
            if (VIR_ALLOC_N(modstr, size+1) < 0)
                goto no_memory;

            for (i = 0 ; i < def->nsounds && size > 0 ; i++) {
                virDomainSoundDefPtr sound = def->sounds[i];
                const char *model = virDomainSoundModelTypeToString(sound->model);
                if (!model) {
                    VIR_FREE(modstr);
5238 5239
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("invalid sound model"));
5240 5241 5242 5243 5244 5245
                    goto error;
                }
                strncat(modstr, model, size);
                size -= strlen(model);
                if (i < (def->nsounds - 1))
                    strncat(modstr, ",", size--);
D
Daniel Veillard 已提交
5246
            }
E
Eric Blake 已提交
5247 5248
            virCommandAddArgList(cmd, "-soundhw", modstr, NULL);
            VIR_FREE(modstr);
D
Daniel Veillard 已提交
5249 5250 5251
        }
    }

R
Richard Jones 已提交
5252 5253 5254
    /* Add watchdog hardware */
    if (def->watchdog) {
        virDomainWatchdogDefPtr watchdog = def->watchdog;
D
Daniel P. Berrange 已提交
5255 5256 5257
        char *optstr;

        if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
E
Eric Blake 已提交
5258
            virCommandAddArg(cmd, "-device");
D
Daniel P. Berrange 已提交
5259 5260 5261 5262 5263

            optstr = qemuBuildWatchdogDevStr(watchdog);
            if (!optstr)
                goto error;
        } else {
E
Eric Blake 已提交
5264
            virCommandAddArg(cmd, "-watchdog");
D
Daniel P. Berrange 已提交
5265 5266 5267

            const char *model = virDomainWatchdogModelTypeToString(watchdog->model);
            if (!model) {
5268 5269
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("missing watchdog model"));
D
Daniel P. Berrange 已提交
5270 5271 5272 5273 5274
                goto error;
            }

            if (!(optstr = strdup(model)))
                goto no_memory;
R
Richard Jones 已提交
5275
        }
E
Eric Blake 已提交
5276 5277
        virCommandAddArg(cmd, optstr);
        VIR_FREE(optstr);
R
Richard Jones 已提交
5278 5279 5280

        const char *action = virDomainWatchdogActionTypeToString(watchdog->action);
        if (!action) {
5281 5282
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("invalid watchdog action"));
R
Richard Jones 已提交
5283 5284
            goto error;
        }
E
Eric Blake 已提交
5285
        virCommandAddArgList(cmd, "-watchdog-action", action, NULL);
R
Richard Jones 已提交
5286 5287
    }

5288
    /* Add host passthrough hardware */
5289 5290
    for (i = 0 ; i < def->nhostdevs ; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];
5291
        char *devstr;
5292

5293
        /* USB */
5294 5295 5296
        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {

5297
            if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
E
Eric Blake 已提交
5298
                virCommandAddArg(cmd, "-device");
5299 5300
                if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev)))
                    goto error;
E
Eric Blake 已提交
5301 5302
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
5303
            } else {
E
Eric Blake 已提交
5304
                virCommandAddArg(cmd, "-usbdevice");
5305 5306
                if (!(devstr = qemuBuildUSBHostdevUsbDevStr(hostdev)))
                    goto error;
E
Eric Blake 已提交
5307 5308
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
5309 5310
            }
        }
5311 5312 5313 5314

        /* PCI */
        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
5315
            if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
5316 5317 5318 5319 5320 5321
                char *configfd_name = NULL;
                if (qemuCmdFlags & QEMUD_CMD_FLAG_PCI_CONFIGFD) {
                    int configfd = qemudOpenPCIConfig(hostdev);

                    if (configfd >= 0) {
                        if (virAsprintf(&configfd_name, "%d", configfd) < 0) {
5322
                            VIR_FORCE_CLOSE(configfd);
5323 5324 5325 5326
                            virReportOOMError();
                            goto no_memory;
                        }

E
Eric Blake 已提交
5327
                        virCommandTransferFD(cmd, configfd);
5328 5329
                    }
                }
E
Eric Blake 已提交
5330
                virCommandAddArg(cmd, "-device");
5331 5332 5333
                devstr = qemuBuildPCIHostdevDevStr(hostdev, configfd_name);
                VIR_FREE(configfd_name);
                if (!devstr)
5334
                    goto error;
E
Eric Blake 已提交
5335 5336
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
5337
            } else if (qemuCmdFlags & QEMUD_CMD_FLAG_PCIDEVICE) {
E
Eric Blake 已提交
5338
                virCommandAddArg(cmd, "-pcidevice");
5339 5340
                if (!(devstr = qemuBuildPCIHostdevPCIDevStr(hostdev)))
                    goto error;
E
Eric Blake 已提交
5341 5342
                virCommandAddArg(cmd, devstr);
                VIR_FREE(devstr);
5343
            } else {
5344
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5345
                                _("PCI device assignment is not supported by this version of qemu"));
5346 5347
                goto error;
            }
5348
        }
5349 5350
    }

E
Eric Blake 已提交
5351 5352
    if (migrateFrom)
        virCommandAddArgList(cmd, "-incoming", migrateFrom, NULL);
5353

5354 5355
    /* QEMU changed its default behavior to not include the virtio balloon
     * device.  Explicitly request it to ensure it will be present.
5356 5357 5358
     *
     * NB: Earlier we declared that VirtIO balloon will always be in
     * slot 0x3 on bus 0x0
5359
     */
5360 5361
    if ((def->memballoon) &&
        (def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE)) {
5362 5363 5364 5365 5366 5367 5368 5369
        if (def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO) {
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("Memory balloon device type '%s' is not supported by this version of qemu"),
                            virDomainMemballoonModelTypeToString(def->memballoon->model));
            goto error;
        }
        if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
            char *optstr;
E
Eric Blake 已提交
5370
            virCommandAddArg(cmd, "-device");
5371 5372 5373 5374

            optstr = qemuBuildMemballoonDevStr(def->memballoon);
            if (!optstr)
                goto error;
E
Eric Blake 已提交
5375 5376
            virCommandAddArg(cmd, optstr);
            VIR_FREE(optstr);
5377
        } else if (qemuCmdFlags & QEMUD_CMD_FLAG_BALLOON) {
E
Eric Blake 已提交
5378
            virCommandAddArgList(cmd, "-balloon", "virtio", NULL);
5379
        }
5380 5381
    }

E
Eric Blake 已提交
5382 5383 5384
    if (current_snapshot && current_snapshot->def->active)
        virCommandAddArgList(cmd, "-loadvm", current_snapshot->def->name,
                             NULL);
C
Chris Lalancette 已提交
5385

5386
    if (def->namespaceData) {
E
Eric Blake 已提交
5387
        qemuDomainCmdlineDefPtr qemucmd;
5388

E
Eric Blake 已提交
5389 5390 5391 5392 5393 5394 5395 5396
        qemucmd = def->namespaceData;
        for (i = 0; i < qemucmd->num_args; i++)
            virCommandAddArg(cmd, qemucmd->args[i]);
        for (i = 0; i < qemucmd->num_env; i++)
            virCommandAddEnvPair(cmd, qemucmd->env_name[i],
                                 qemucmd->env_value[i]
                                 ? qemucmd->env_value[i] : "");
    }
D
Daniel P. Berrange 已提交
5397

E
Eric Blake 已提交
5398
    return cmd;
D
Daniel P. Berrange 已提交
5399 5400

 no_memory:
5401
    virReportOOMError();
5402
 error:
5403
    for (i = 0; i <= last_good_net; i++)
5404
        virDomainConfNWFilterTeardown(def->nets[i]);
E
Eric Blake 已提交
5405 5406
    virCommandFree(cmd);
    return NULL;
D
Daniel P. Berrange 已提交
5407
}
5408 5409


5410 5411
/*
 * This method takes a string representing a QEMU command line ARGV set
C
Chris Lalancette 已提交
5412
 * optionally prefixed by a list of environment variables. It then tries
5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431
 * to split it up into a NULL terminated list of env & argv, splitting
 * on space
 */
static int qemuStringToArgvEnv(const char *args,
                               const char ***retenv,
                               const char ***retargv)
{
    char **arglist = NULL;
    int argcount = 0;
    int argalloc = 0;
    int envend;
    int i;
    const char *curr = args;
    const char **progenv = NULL;
    const char **progargv = NULL;

    /* Iterate over string, splitting on sequences of ' ' */
    while (curr && *curr != '\0') {
        char *arg;
5432 5433 5434 5435 5436 5437 5438 5439 5440 5441
        const char *next;
        if (*curr == '\'') {
            curr++;
            next = strchr(curr, '\'');
        } else if (*curr == '"') {
            curr++;
            next = strchr(curr, '"');
        } else {
            next = strchr(curr, ' ');
        }
5442 5443 5444
        if (!next)
            next = strchr(curr, '\n');

5445
        if (next) {
5446
            arg = strndup(curr, next-curr);
5447 5448 5449 5450
            if (*next == '\'' ||
                *next == '"')
                next++;
        } else {
5451
            arg = strdup(curr);
5452
        }
5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472

        if (!arg)
            goto no_memory;

        if (argalloc == argcount) {
            if (VIR_REALLOC_N(arglist, argalloc+10) < 0) {
                VIR_FREE(arg);
                goto no_memory;
            }
            argalloc+=10;
        }

        arglist[argcount++] = arg;

        while (next && c_isspace(*next))
            next++;

        curr = next;
    }

5473
    /* Iterate over list of args, finding first arg not containing
5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485
     * the '=' character (eg, skip over env vars FOO=bar) */
    for (envend = 0 ; ((envend < argcount) &&
                       (strchr(arglist[envend], '=') != NULL));
         envend++)
        ; /* nada */

    /* Copy the list of env vars */
    if (envend > 0) {
        if (VIR_REALLOC_N(progenv, envend+1) < 0)
            goto no_memory;
        for (i = 0 ; i < envend ; i++) {
            progenv[i] = arglist[i];
D
Daniel P. Berrange 已提交
5486
            arglist[i] = NULL;
5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511
        }
        progenv[i] = NULL;
    }

    /* Copy the list of argv */
    if (VIR_REALLOC_N(progargv, argcount-envend + 1) < 0)
        goto no_memory;
    for (i = envend ; i < argcount ; i++)
        progargv[i-envend] = arglist[i];
    progargv[i-envend] = NULL;

    VIR_FREE(arglist);

    *retenv = progenv;
    *retargv = progargv;

    return 0;

no_memory:
    for (i = 0 ; progenv && progenv[i] ; i++)
        VIR_FREE(progenv[i]);
    VIR_FREE(progenv);
    for (i = 0 ; i < argcount ; i++)
        VIR_FREE(arglist[i]);
    VIR_FREE(arglist);
5512
    virReportOOMError();
5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525
    return -1;
}


/*
 * Search for a named env variable, and return the value part
 */
static const char *qemuFindEnv(const char **progenv,
                               const char *name)
{
    int i;
    int len = strlen(name);

5526
    for (i = 0 ; progenv && progenv[i] ; i++) {
5527 5528 5529 5530 5531 5532 5533 5534 5535 5536
        if (STREQLEN(progenv[i], name, len) &&
            progenv[i][len] == '=')
            return progenv[i] + len + 1;
    }
    return NULL;
}

/*
 * Takes a string containing a set of key=value,key=value,key...
 * parameters and splits them up, returning two arrays with
5537 5538 5539
 * the individual keys and values. If allowEmptyValue is nonzero,
 * the "=value" part is optional and if a key with no value is found,
 * NULL is be placed into corresponding place in retvalues.
5540
 */
5541 5542 5543 5544 5545
int
qemuParseKeywords(const char *str,
                  char ***retkeywords,
                  char ***retvalues,
                  int allowEmptyValue)
5546 5547 5548 5549 5550 5551
{
    int keywordCount = 0;
    int keywordAlloc = 0;
    char **keywords = NULL;
    char **values = NULL;
    const char *start = str;
5552
    const char *end;
5553 5554 5555 5556
    int i;

    *retkeywords = NULL;
    *retvalues = NULL;
5557
    end = start + strlen(str);
5558 5559 5560 5561 5562

    while (start) {
        const char *separator;
        const char *endmark;
        char *keyword;
5563
        char *value = NULL;
5564

5565 5566 5567 5568 5569 5570 5571
        if (!(endmark = strchr(start, ',')))
            endmark = end;
        if (!(separator = strchr(start, '=')))
            separator = end;

        if (separator >= endmark) {
            if (!allowEmptyValue) {
5572 5573
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("malformed keyword arguments in '%s'"), str);
5574 5575 5576
                goto error;
            }
            separator = endmark;
5577
        }
5578

5579 5580 5581
        if (!(keyword = strndup(start, separator - start)))
            goto no_memory;

5582 5583 5584 5585 5586 5587
        if (separator < endmark) {
            separator++;
            if (!(value = strndup(separator, endmark - separator))) {
                VIR_FREE(keyword);
                goto no_memory;
            }
5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603
        }

        if (keywordAlloc == keywordCount) {
            if (VIR_REALLOC_N(keywords, keywordAlloc + 10) < 0 ||
                VIR_REALLOC_N(values, keywordAlloc + 10) < 0) {
                VIR_FREE(keyword);
                VIR_FREE(value);
                goto no_memory;
            }
            keywordAlloc += 10;
        }

        keywords[keywordCount] = keyword;
        values[keywordCount] = value;
        keywordCount++;

5604
        start = endmark < end ? endmark + 1 : NULL;
5605 5606 5607 5608 5609 5610 5611 5612
    }

    *retkeywords = keywords;
    *retvalues = values;

    return keywordCount;

no_memory:
5613
    virReportOOMError();
5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631
error:
    for (i = 0 ; i < keywordCount ; i++) {
        VIR_FREE(keywords[i]);
        VIR_FREE(values[i]);
    }
    VIR_FREE(keywords);
    VIR_FREE(values);
    return -1;
}

/*
 * Tries to parse new style QEMU -drive  args.
 *
 * eg -drive file=/dev/HostVG/VirtData1,if=ide,index=1
 *
 * Will fail if not using the 'index' keyword
 */
static virDomainDiskDefPtr
5632 5633
qemuParseCommandLineDisk(virCapsPtr caps,
                         const char *val,
5634
                         int nvirtiodisk)
5635 5636 5637 5638 5639 5640 5641
{
    virDomainDiskDefPtr def = NULL;
    char **keywords;
    char **values;
    int nkeywords;
    int i;
    int idx = -1;
5642 5643
    int busid = -1;
    int unitid = -1;
5644

5645 5646 5647
    if ((nkeywords = qemuParseKeywords(val,
                                       &keywords,
                                       &values, 0)) < 0)
5648 5649 5650
        return NULL;

    if (VIR_ALLOC(def) < 0) {
5651
        virReportOOMError();
5652 5653 5654 5655 5656
        goto cleanup;
    }

    def->bus = VIR_DOMAIN_DISK_BUS_IDE;
    def->device = VIR_DOMAIN_DISK_DEVICE_DISK;
5657
    def->type = VIR_DOMAIN_DISK_TYPE_FILE;
5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690

    for (i = 0 ; i < nkeywords ; i++) {
        if (STREQ(keywords[i], "file")) {
            if (values[i] && STRNEQ(values[i], "")) {
                def->src = values[i];
                values[i] = NULL;
                if (STRPREFIX(def->src, "/dev/"))
                    def->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
                else
                    def->type = VIR_DOMAIN_DISK_TYPE_FILE;
            } else {
                def->type = VIR_DOMAIN_DISK_TYPE_FILE;
            }
        } else if (STREQ(keywords[i], "if")) {
            if (STREQ(values[i], "ide"))
                def->bus = VIR_DOMAIN_DISK_BUS_IDE;
            else if (STREQ(values[i], "scsi"))
                def->bus = VIR_DOMAIN_DISK_BUS_SCSI;
            else if (STREQ(values[i], "virtio"))
                def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO;
            else if (STREQ(values[i], "xen"))
                def->bus = VIR_DOMAIN_DISK_BUS_XEN;
        } else if (STREQ(keywords[i], "media")) {
            if (STREQ(values[i], "cdrom")) {
                def->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
                def->readonly = 1;
            } else if (STREQ(values[i], "floppy"))
                def->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
        } else if (STREQ(keywords[i], "format")) {
            def->driverName = strdup("qemu");
            if (!def->driverName) {
                virDomainDiskDefFree(def);
                def = NULL;
5691
                virReportOOMError();
5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704
                goto cleanup;
            }
            def->driverType = values[i];
            values[i] = NULL;
        } else if (STREQ(keywords[i], "cache")) {
            if (STREQ(values[i], "off") ||
                STREQ(values[i], "none"))
                def->cachemode = VIR_DOMAIN_DISK_CACHE_DISABLE;
            else if (STREQ(values[i], "writeback") ||
                     STREQ(values[i], "on"))
                def->cachemode = VIR_DOMAIN_DISK_CACHE_WRITEBACK;
            else if (STREQ(values[i], "writethrough"))
                def->cachemode = VIR_DOMAIN_DISK_CACHE_WRITETHRU;
5705 5706 5707 5708 5709 5710
        } else if (STREQ(keywords[i], "werror") ||
                   STREQ(keywords[i], "rerror")) {
            if (STREQ(values[i], "stop"))
                def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_STOP;
            else if (STREQ(values[i], "ignore"))
                def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE;
5711 5712
            else if (STREQ(values[i], "enospace"))
                def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE;
5713 5714 5715 5716
        } else if (STREQ(keywords[i], "index")) {
            if (virStrToLong_i(values[i], NULL, 10, &idx) < 0) {
                virDomainDiskDefFree(def);
                def = NULL;
5717 5718
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot parse drive index '%s'"), val);
5719 5720
                goto cleanup;
            }
5721 5722 5723 5724
        } else if (STREQ(keywords[i], "bus")) {
            if (virStrToLong_i(values[i], NULL, 10, &busid) < 0) {
                virDomainDiskDefFree(def);
                def = NULL;
5725 5726
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot parse drive bus '%s'"), val);
5727 5728 5729 5730 5731 5732
                goto cleanup;
            }
        } else if (STREQ(keywords[i], "unit")) {
            if (virStrToLong_i(values[i], NULL, 10, &unitid) < 0) {
                virDomainDiskDefFree(def);
                def = NULL;
5733 5734
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot parse drive unit '%s'"), val);
5735 5736
                goto cleanup;
            }
5737 5738 5739
        } else if (STREQ(keywords[i], "readonly")) {
            if ((values[i] == NULL) || STREQ(values[i], "on"))
                def->readonly = 1;
5740 5741 5742 5743 5744
        }
    }

    if (!def->src &&
        def->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
5745 5746
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("missing file parameter in drive '%s'"), val);
5747 5748 5749 5750
        virDomainDiskDefFree(def);
        def = NULL;
        goto cleanup;
    }
5751 5752 5753 5754 5755 5756 5757
    if (idx == -1 &&
        def->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)
        idx = nvirtiodisk;

    if (idx == -1 &&
        unitid == -1 &&
        busid == -1) {
5758 5759
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("missing index/unit/bus parameter in drive '%s'"), val);
5760 5761 5762 5763 5764
        virDomainDiskDefFree(def);
        def = NULL;
        goto cleanup;
    }

5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782
    if (idx == -1) {
        if (unitid == -1)
            unitid = 0;
        if (busid == -1)
            busid = 0;
        switch (def->bus) {
        case VIR_DOMAIN_DISK_BUS_IDE:
            idx = (busid * 2) + unitid;
            break;
        case VIR_DOMAIN_DISK_BUS_SCSI:
            idx = (busid * 7) + unitid;
            break;
        default:
            idx = unitid;
            break;
        }
    }

5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797
    if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) {
        def->dst = strdup("hda");
    } else if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
        def->dst = strdup("sda");
    } else if (def->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
        def->dst = strdup("vda");
    } else if (def->bus == VIR_DOMAIN_DISK_BUS_XEN) {
        def->dst = strdup("xvda");
    } else {
        def->dst = strdup("hda");
    }

    if (!def->dst) {
        virDomainDiskDefFree(def);
        def = NULL;
5798
        virReportOOMError();
5799 5800 5801 5802 5803 5804 5805
        goto cleanup;
    }
    if (STREQ(def->dst, "xvda"))
        def->dst[3] = 'a' + idx;
    else
        def->dst[2] = 'a' + idx;

5806
    if (virDomainDiskDefAssignAddress(caps, def) < 0) {
5807 5808 5809 5810 5811 5812
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("invalid device name '%s'"), def->dst);
        virDomainDiskDefFree(def);
        def = NULL;
        /* fall through to "cleanup" */
    }
5813

5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827
cleanup:
    for (i = 0 ; i < nkeywords ; i++) {
        VIR_FREE(keywords[i]);
        VIR_FREE(values[i]);
    }
    VIR_FREE(keywords);
    VIR_FREE(values);
    return def;
}

/*
 * Tries to find a NIC definition matching a vlan we want
 */
static const char *
5828
qemuFindNICForVLAN(int nnics,
5829 5830 5831 5832 5833 5834 5835 5836
                   const char **nics,
                   int wantvlan)
{
    int i;
    for (i = 0 ; i < nnics ; i++) {
        int gotvlan;
        const char *tmp = strstr(nics[i], "vlan=");
        char *end;
5837 5838 5839 5840
        if (!tmp)
            continue;

        tmp += strlen("vlan=");
5841 5842

        if (virStrToLong_i(tmp, &end, 10, &gotvlan) < 0) {
5843 5844
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot parse NIC vlan in '%s'"), nics[i]);
5845 5846 5847 5848 5849 5850 5851
            return NULL;
        }

        if (gotvlan == wantvlan)
            return nics[i];
    }

5852 5853 5854
    if (wantvlan == 0 && nnics > 0)
        return nics[0];

5855 5856
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    _("cannot find NIC definition for vlan %d"), wantvlan);
5857 5858 5859 5860 5861 5862 5863 5864 5865 5866
    return NULL;
}


/*
 * Tries to parse a QEMU -net backend argument. Gets given
 * a list of all known -net frontend arguments to try and
 * match up against. Horribly complicated stuff
 */
static virDomainNetDefPtr
5867
qemuParseCommandLineNet(virCapsPtr caps,
5868 5869 5870 5871 5872
                        const char *val,
                        int nnics,
                        const char **nics)
{
    virDomainNetDefPtr def = NULL;
5873 5874
    char **keywords = NULL;
    char **values = NULL;
5875 5876 5877 5878
    int nkeywords;
    const char *nic;
    int wantvlan = 0;
    const char *tmp;
5879
    int genmac = 1;
5880 5881 5882 5883
    int i;

    tmp = strchr(val, ',');

5884
    if (tmp) {
5885 5886 5887
        if ((nkeywords = qemuParseKeywords(tmp+1,
                                           &keywords,
                                           &values, 0)) < 0)
5888 5889 5890 5891
            return NULL;
    } else {
        nkeywords = 0;
    }
5892 5893

    if (VIR_ALLOC(def) < 0) {
5894
        virReportOOMError();
5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911
        goto cleanup;
    }

    /* 'tap' could turn into libvirt type=ethernet, type=bridge or
     * type=network, but we can't tell, so use the generic config */
    if (STRPREFIX(val, "tap,"))
        def->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
    else if (STRPREFIX(val, "socket"))
        def->type = VIR_DOMAIN_NET_TYPE_CLIENT;
    else if (STRPREFIX(val, "user"))
        def->type = VIR_DOMAIN_NET_TYPE_USER;
    else
        def->type = VIR_DOMAIN_NET_TYPE_ETHERNET;

    for (i = 0 ; i < nkeywords ; i++) {
        if (STREQ(keywords[i], "vlan")) {
            if (virStrToLong_i(values[i], NULL, 10, &wantvlan) < 0) {
5912 5913
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot parse vlan in '%s'"), val);
5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933
                virDomainNetDefFree(def);
                def = NULL;
                goto cleanup;
            }
        } else if (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
                   STREQ(keywords[i], "script") && STRNEQ(values[i], "")) {
            def->data.ethernet.script = values[i];
            values[i] = NULL;
        } else if (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
                   STREQ(keywords[i], "ifname")) {
            def->ifname = values[i];
            values[i] = NULL;
        }
    }


    /* Done parsing the nic backend. Now to try and find corresponding
     * frontend, based off vlan number. NB this assumes a 1-1 mapping
     */

5934
    nic = qemuFindNICForVLAN(nnics, nics, wantvlan);
5935 5936 5937 5938 5939 5940
    if (!nic) {
        virDomainNetDefFree(def);
        def = NULL;
        goto cleanup;
    }

5941
    if (!STRPREFIX(nic, "nic")) {
5942 5943
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot parse NIC definition '%s'"), nic);
5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955
        virDomainNetDefFree(def);
        def = NULL;
        goto cleanup;
    }

    for (i = 0 ; i < nkeywords ; i++) {
        VIR_FREE(keywords[i]);
        VIR_FREE(values[i]);
    }
    VIR_FREE(keywords);
    VIR_FREE(values);

5956
    if (STRPREFIX(nic, "nic,")) {
5957 5958 5959
        if ((nkeywords = qemuParseKeywords(nic + strlen("nic,"),
                                           &keywords,
                                           &values, 0)) < 0) {
5960 5961 5962 5963 5964 5965
            virDomainNetDefFree(def);
            def = NULL;
            goto cleanup;
        }
    } else {
        nkeywords = 0;
5966 5967 5968 5969
    }

    for (i = 0 ; i < nkeywords ; i++) {
        if (STREQ(keywords[i], "macaddr")) {
5970
            genmac = 0;
5971
            if (virParseMacAddr(values[i], def->mac) < 0) {
5972 5973 5974
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unable to parse mac address '%s'"),
                                values[i]);
5975 5976 5977 5978
                virDomainNetDefFree(def);
                def = NULL;
                goto cleanup;
            }
5979 5980 5981 5982 5983 5984
        } else if (STREQ(keywords[i], "model")) {
            def->model = values[i];
            values[i] = NULL;
        }
    }

5985 5986 5987
    if (genmac)
        virCapabilitiesGenerateMac(caps, def->mac);

5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002
cleanup:
    for (i = 0 ; i < nkeywords ; i++) {
        VIR_FREE(keywords[i]);
        VIR_FREE(values[i]);
    }
    VIR_FREE(keywords);
    VIR_FREE(values);
    return def;
}


/*
 * Tries to parse a QEMU PCI device
 */
static virDomainHostdevDefPtr
6003
qemuParseCommandLinePCI(const char *val)
6004 6005 6006 6007 6008 6009 6010
{
    virDomainHostdevDefPtr def = NULL;
    int bus = 0, slot = 0, func = 0;
    const char *start;
    char *end;

    if (!STRPREFIX(val, "host=")) {
6011 6012
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown PCI device syntax '%s'"), val);
6013 6014 6015 6016 6017
        VIR_FREE(def);
        goto cleanup;
    }

    start = val + strlen("host=");
6018
    if (virStrToLong_i(start, &end, 16, &bus) < 0 || *end != ':') {
6019 6020
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot extract PCI device bus '%s'"), val);
6021 6022 6023 6024
        VIR_FREE(def);
        goto cleanup;
    }
    start = end + 1;
6025
    if (virStrToLong_i(start, &end, 16, &slot) < 0 || *end != '.') {
6026 6027
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot extract PCI device slot '%s'"), val);
6028 6029 6030 6031 6032
        VIR_FREE(def);
        goto cleanup;
    }
    start = end + 1;
    if (virStrToLong_i(start, NULL, 16, &func) < 0) {
6033 6034
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot extract PCI device function '%s'"), val);
6035 6036 6037 6038 6039
        VIR_FREE(def);
        goto cleanup;
    }

    if (VIR_ALLOC(def) < 0) {
6040
        virReportOOMError();
6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059
        goto cleanup;
    }

    def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
    def->managed = 1;
    def->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
    def->source.subsys.u.pci.bus = bus;
    def->source.subsys.u.pci.slot = slot;
    def->source.subsys.u.pci.function = func;

cleanup:
    return def;
}


/*
 * Tries to parse a QEMU USB device
 */
static virDomainHostdevDefPtr
6060
qemuParseCommandLineUSB(const char *val)
6061 6062 6063 6064 6065 6066 6067
{
    virDomainHostdevDefPtr def = NULL;
    int first = 0, second = 0;
    const char *start;
    char *end;

    if (!STRPREFIX(val, "host:")) {
6068
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
6069
                        _("unknown USB device syntax '%s'"), val);
6070 6071 6072 6073 6074 6075
        VIR_FREE(def);
        goto cleanup;
    }

    start = val + strlen("host:");
    if (strchr(start, ':')) {
6076
        if (virStrToLong_i(start, &end, 16, &first) < 0 || *end != ':') {
6077 6078
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot extract USB device vendor '%s'"), val);
6079 6080 6081 6082 6083
            VIR_FREE(def);
            goto cleanup;
        }
        start = end + 1;
        if (virStrToLong_i(start, NULL, 16, &second) < 0) {
6084
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6085
                            _("cannot extract USB device product '%s'"), val);
6086 6087 6088 6089
            VIR_FREE(def);
            goto cleanup;
        }
    } else {
6090
        if (virStrToLong_i(start, &end, 10, &first) < 0 || *end != '.') {
6091
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6092
                             _("cannot extract USB device bus '%s'"), val);
6093 6094 6095 6096 6097
            VIR_FREE(def);
            goto cleanup;
        }
        start = end + 1;
        if (virStrToLong_i(start, NULL, 10, &second) < 0) {
6098
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6099
                            _("cannot extract USB device address '%s'"), val);
6100 6101 6102 6103 6104 6105
            VIR_FREE(def);
            goto cleanup;
        }
    }

    if (VIR_ALLOC(def) < 0) {
6106
        virReportOOMError();
6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129
        goto cleanup;
    }

    def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
    def->managed = 0;
    def->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB;
    if (*end == '.') {
        def->source.subsys.u.usb.bus = first;
        def->source.subsys.u.usb.device = second;
    } else {
        def->source.subsys.u.usb.vendor = first;
        def->source.subsys.u.usb.product = second;
    }

cleanup:
    return def;
}


/*
 * Tries to parse a QEMU serial/parallel device
 */
static virDomainChrDefPtr
6130
qemuParseCommandLineChr(const char *val)
6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166
{
    virDomainChrDefPtr def;

    if (VIR_ALLOC(def) < 0)
        goto no_memory;

    if (STREQ(val, "null")) {
        def->type = VIR_DOMAIN_CHR_TYPE_NULL;
    } else if (STREQ(val, "vc")) {
        def->type = VIR_DOMAIN_CHR_TYPE_VC;
    } else if (STREQ(val, "pty")) {
        def->type = VIR_DOMAIN_CHR_TYPE_PTY;
    } else if (STRPREFIX(val, "file:")) {
        def->type = VIR_DOMAIN_CHR_TYPE_FILE;
        def->data.file.path = strdup(val+strlen("file:"));
        if (!def->data.file.path)
            goto no_memory;
    } else if (STRPREFIX(val, "pipe:")) {
        def->type = VIR_DOMAIN_CHR_TYPE_PIPE;
        def->data.file.path = strdup(val+strlen("pipe:"));
        if (!def->data.file.path)
            goto no_memory;
    } else if (STREQ(val, "stdio")) {
        def->type = VIR_DOMAIN_CHR_TYPE_STDIO;
    } else if (STRPREFIX(val, "udp:")) {
        const char *svc1, *host2, *svc2;
        def->type = VIR_DOMAIN_CHR_TYPE_UDP;
        val += strlen("udp:");
        svc1 = strchr(val, ':');
        host2 = svc1 ? strchr(svc1, '@') : NULL;
        svc2 = host2 ? strchr(host2, ':') : NULL;

        if (svc1)
            def->data.udp.connectHost = strndup(val, svc1-val);
        else
            def->data.udp.connectHost = strdup(val);
6167 6168 6169 6170

        if (!def->data.udp.connectHost)
            goto no_memory;

6171 6172 6173 6174 6175 6176
        if (svc1) {
            svc1++;
            if (host2)
                def->data.udp.connectService = strndup(svc1, host2-svc1);
            else
                def->data.udp.connectService = strdup(svc1);
6177 6178 6179

            if (!def->data.udp.connectService)
                goto no_memory;
6180 6181 6182 6183 6184 6185 6186 6187
        }

        if (host2) {
            host2++;
            if (svc2)
                def->data.udp.bindHost = strndup(host2, svc2-host2);
            else
                def->data.udp.bindHost = strdup(host2);
6188 6189 6190

            if (!def->data.udp.bindHost)
                goto no_memory;
6191 6192 6193 6194
        }
        if (svc2) {
            svc2++;
            def->data.udp.bindService = strdup(svc2);
6195 6196
            if (!def->data.udp.bindService)
                goto no_memory;
6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209
        }
    } else if (STRPREFIX(val, "tcp:") ||
               STRPREFIX(val, "telnet:")) {
        const char *opt, *svc;
        def->type = VIR_DOMAIN_CHR_TYPE_TCP;
        if (STRPREFIX(val, "tcp:")) {
            val += strlen("tcp:");
        } else {
            val += strlen("telnet:");
            def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
        }
        svc = strchr(val, ':');
        if (!svc) {
6210 6211
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find port number in character device %s"), val);
6212 6213 6214 6215 6216 6217 6218
            goto error;
        }
        opt = strchr(svc, ',');
        if (opt && strstr(opt, "server"))
            def->data.tcp.listen = 1;

        def->data.tcp.host = strndup(val, svc-val);
6219 6220
        if (!def->data.tcp.host)
            goto no_memory;
6221 6222 6223 6224 6225 6226
        svc++;
        if (opt) {
            def->data.tcp.service = strndup(svc, opt-svc);
        } else {
            def->data.tcp.service = strdup(svc);
        }
6227 6228
        if (!def->data.tcp.service)
            goto no_memory;
6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249
    } else if (STRPREFIX(val, "unix:")) {
        const char *opt;
        val += strlen("unix:");
        opt = strchr(val, ',');
        def->type = VIR_DOMAIN_CHR_TYPE_UNIX;
        if (opt) {
            if (strstr(opt, "listen"))
                def->data.nix.listen = 1;
            def->data.nix.path = strndup(val, opt-val);
        } else {
            def->data.nix.path = strdup(val);
        }
        if (!def->data.nix.path)
            goto no_memory;

    } else if (STRPREFIX(val, "/dev")) {
        def->type = VIR_DOMAIN_CHR_TYPE_DEV;
        def->data.file.path = strdup(val);
        if (!def->data.file.path)
            goto no_memory;
    } else {
6250 6251
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown character device syntax %s"), val);
6252 6253 6254 6255 6256 6257
        goto error;
    }

    return def;

no_memory:
6258
    virReportOOMError();
6259 6260 6261 6262 6263
error:
    virDomainChrDefFree(def);
    return NULL;
}

6264

6265
static virCPUDefPtr
6266
qemuInitGuestCPU(virDomainDefPtr dom)
6267 6268 6269 6270 6271
{
    if (!dom->cpu) {
        virCPUDefPtr cpu;

        if (VIR_ALLOC(cpu) < 0) {
6272
            virReportOOMError();
6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284
            return NULL;
        }

        cpu->type = VIR_CPU_TYPE_GUEST;
        cpu->match = VIR_CPU_MATCH_EXACT;
        dom->cpu = cpu;
    }

    return dom->cpu;
}


6285
static int
6286
qemuParseCommandLineCPU(virDomainDefPtr dom,
6287 6288 6289 6290 6291 6292
                        const char *val)
{
    virCPUDefPtr cpu;
    const char *p = val;
    const char *next;

6293
    if (!(cpu = qemuInitGuestCPU(dom)))
6294
        goto error;
6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330

    do {
        if (*p == '\0' || *p == ',')
            goto syntax;

        if ((next = strchr(p, ',')))
            next++;

        if (!cpu->model) {
            if (next)
                cpu->model = strndup(p, next - p - 1);
            else
                cpu->model = strdup(p);

            if (!cpu->model)
                goto no_memory;
        }
        else if (*p == '+' || *p == '-') {
            char *feature;
            int policy;
            int ret;

            if (*p == '+')
                policy = VIR_CPU_FEATURE_REQUIRE;
            else
                policy = VIR_CPU_FEATURE_DISABLE;

            p++;
            if (*p == '\0' || *p == ',')
                goto syntax;

            if (next)
                feature = strndup(p, next - p - 1);
            else
                feature = strdup(p);

6331
            ret = virCPUDefAddFeature(cpu, feature, policy);
6332 6333 6334 6335 6336 6337 6338 6339 6340
            VIR_FREE(feature);
            if (ret < 0)
                goto error;
        }
    } while ((p = next));

    return 0;

syntax:
6341 6342
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    _("unknown CPU syntax '%s'"), val);
6343 6344 6345
    goto error;

no_memory:
6346
    virReportOOMError();
6347 6348 6349 6350 6351
error:
    return -1;
}


6352
static int
6353
qemuParseCommandLineSmp(virDomainDefPtr dom,
6354 6355 6356 6357 6358
                        const char *val)
{
    unsigned int sockets = 0;
    unsigned int cores = 0;
    unsigned int threads = 0;
6359
    unsigned int maxcpus = 0;
6360 6361 6362 6363 6364 6365 6366 6367
    int i;
    int nkws;
    char **kws;
    char **vals;
    int n;
    char *end;
    int ret;

6368
    nkws = qemuParseKeywords(val, &kws, &vals, 1);
6369 6370 6371 6372 6373 6374
    if (nkws < 0)
        return -1;

    for (i = 0; i < nkws; i++) {
        if (vals[i] == NULL) {
            if (i > 0 ||
6375
                virStrToLong_i(kws[i], &end, 10, &n) < 0 || *end != '\0')
6376 6377 6378
                goto syntax;
            dom->vcpus = n;
        } else {
6379
            if (virStrToLong_i(vals[i], &end, 10, &n) < 0 || *end != '\0')
6380 6381 6382 6383 6384 6385 6386
                goto syntax;
            if (STREQ(kws[i], "sockets"))
                sockets = n;
            else if (STREQ(kws[i], "cores"))
                cores = n;
            else if (STREQ(kws[i], "threads"))
                threads = n;
6387 6388
            else if (STREQ(kws[i], "maxcpus"))
                maxcpus = n;
6389 6390 6391 6392 6393
            else
                goto syntax;
        }
    }

6394
    dom->maxvcpus = maxcpus ? maxcpus : dom->vcpus;
E
Eric Blake 已提交
6395

6396 6397 6398
    if (sockets && cores && threads) {
        virCPUDefPtr cpu;

6399
        if (!(cpu = qemuInitGuestCPU(dom)))
6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419
            goto error;
        cpu->sockets = sockets;
        cpu->cores = cores;
        cpu->threads = threads;
    } else if (sockets || cores || threads)
        goto syntax;

    ret = 0;

cleanup:
    for (i = 0; i < nkws; i++) {
        VIR_FREE(kws[i]);
        VIR_FREE(vals[i]);
    }
    VIR_FREE(kws);
    VIR_FREE(vals);

    return ret;

syntax:
6420 6421
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    _("cannot parse CPU topology '%s'"), val);
6422 6423 6424 6425 6426 6427
error:
    ret = -1;
    goto cleanup;
}


6428 6429 6430 6431 6432
/*
 * Analyse the env and argv settings and reconstruct a
 * virDomainDefPtr representing these settings as closely
 * as is practical. This is not an exact science....
 */
6433
virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
6434 6435 6436 6437 6438 6439 6440 6441 6442 6443
                                     const char **progenv,
                                     const char **progargv)
{
    virDomainDefPtr def;
    int i;
    int nographics = 0;
    int fullscreen = 0;
    char *path;
    int nnics = 0;
    const char **nics = NULL;
6444
    int video = VIR_DOMAIN_VIDEO_TYPE_CIRRUS;
6445
    int nvirtiodisk = 0;
6446
    qemuDomainCmdlineDefPtr cmd;
6447 6448

    if (!progargv[0]) {
6449 6450
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no emulator path found"));
6451 6452 6453 6454 6455 6456
        return NULL;
    }

    if (VIR_ALLOC(def) < 0)
        goto no_memory;

6457 6458 6459 6460
    /* allocate the cmdlinedef up-front; if it's unused, we'll free it later */
    if (VIR_ALLOC(cmd) < 0)
        goto no_memory;

6461 6462
    virUUIDGenerate(def->uuid);

6463
    def->id = -1;
6464
    def->mem.cur_balloon = def->mem.max_balloon = 64 * 1024;
E
Eric Blake 已提交
6465
    def->maxvcpus = 1;
6466
    def->vcpus = 1;
6467
    def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506
    def->features = (1 << VIR_DOMAIN_FEATURE_ACPI)
        /*| (1 << VIR_DOMAIN_FEATURE_APIC)*/;
    def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
    def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
    def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
    def->virtType = VIR_DOMAIN_VIRT_QEMU;
    if (!(def->emulator = strdup(progargv[0])))
        goto no_memory;

    if (strstr(def->emulator, "kvm")) {
        def->virtType = VIR_DOMAIN_VIRT_KVM;
        def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
    }


    if (strstr(def->emulator, "xenner")) {
        def->virtType = VIR_DOMAIN_VIRT_KVM;
        def->os.type = strdup("xen");
    } else {
        def->os.type = strdup("hvm");
    }
    if (!def->os.type)
        goto no_memory;

    if (STRPREFIX(def->emulator, "qemu"))
        path = def->emulator;
    else
        path = strstr(def->emulator, "qemu");
    if (path &&
        STRPREFIX(path, "qemu-system-"))
        def->os.arch = strdup(path + strlen("qemu-system-"));
    else
        def->os.arch = strdup("i686");
    if (!def->os.arch)
        goto no_memory;

#define WANT_VALUE()                                                   \
    const char *val = progargv[++i];                                   \
    if (!val) {                                                        \
6507 6508
        qemuReportError(VIR_ERR_INTERNAL_ERROR,                        \
                        _("missing value for %s argument"), arg);      \
6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551
        goto error;                                                    \
    }

    /* One initial loop to get list of NICs, so we
     * can correlate them later */
    for (i = 1 ; progargv[i] ; i++) {
        const char *arg = progargv[i];
        /* Make sure we have a single - for all options to
           simplify next logic */
        if (STRPREFIX(arg, "--"))
            arg++;

        if (STREQ(arg, "-net")) {
            WANT_VALUE();
            if (STRPREFIX(val, "nic")) {
                if (VIR_REALLOC_N(nics, nnics+1) < 0)
                    goto no_memory;
                nics[nnics++] = val;
            }
        }
    }

    /* Now the real processing loop */
    for (i = 1 ; progargv[i] ; i++) {
        const char *arg = progargv[i];
        /* Make sure we have a single - for all options to
           simplify next logic */
        if (STRPREFIX(arg, "--"))
            arg++;

        if (STREQ(arg, "-vnc")) {
            virDomainGraphicsDefPtr vnc;
            char *tmp;
            WANT_VALUE();
            if (VIR_ALLOC(vnc) < 0)
                goto no_memory;
            vnc->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;

            tmp = strchr(val, ':');
            if (tmp) {
                char *opts;
                if (virStrToLong_i(tmp+1, &opts, 10, &vnc->data.vnc.port) < 0) {
                    VIR_FREE(vnc);
6552 6553
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,             \
                                    _("cannot parse VNC port '%s'"), tmp+1);
6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575
                    goto error;
                }
                vnc->data.vnc.listenAddr = strndup(val, tmp-val);
                if (!vnc->data.vnc.listenAddr) {
                    VIR_FREE(vnc);
                    goto no_memory;
                }
                vnc->data.vnc.port += 5900;
                vnc->data.vnc.autoport = 0;
            } else {
                vnc->data.vnc.autoport = 1;
            }

            if (VIR_REALLOC_N(def->graphics, def->ngraphics+1) < 0) {
                virDomainGraphicsDefFree(vnc);
                goto no_memory;
            }
            def->graphics[def->ngraphics++] = vnc;
        } else if (STREQ(arg, "-m")) {
            int mem;
            WANT_VALUE();
            if (virStrToLong_i(val, NULL, 10, &mem) < 0) {
6576 6577
                qemuReportError(VIR_ERR_INTERNAL_ERROR, \
                                _("cannot parse memory level '%s'"), val);
6578 6579
                goto error;
            }
6580
            def->mem.cur_balloon = def->mem.max_balloon = mem * 1024;
6581 6582
        } else if (STREQ(arg, "-smp")) {
            WANT_VALUE();
6583
            if (qemuParseCommandLineSmp(def, val) < 0)
6584 6585 6586 6587
                goto error;
        } else if (STREQ(arg, "-uuid")) {
            WANT_VALUE();
            if (virUUIDParse(val, def->uuid) < 0) {
6588 6589
                qemuReportError(VIR_ERR_INTERNAL_ERROR, \
                                _("cannot parse UUID '%s'"), val);
6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628
                goto error;
            }
        } else if (STRPREFIX(arg, "-hd") ||
                   STRPREFIX(arg, "-sd") ||
                   STRPREFIX(arg, "-fd") ||
                   STREQ(arg, "-cdrom")) {
            WANT_VALUE();
            virDomainDiskDefPtr disk;
            if (VIR_ALLOC(disk) < 0)
                goto no_memory;

            if (STRPREFIX(val, "/dev/"))
                disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
            else
                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
            if (STREQ(arg, "-cdrom")) {
                disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
                disk->dst = strdup("hdc");
                disk->readonly = 1;
            } else {
                if (STRPREFIX(arg, "-fd")) {
                    disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
                    disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
                } else {
                    disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
                    if (STRPREFIX(arg, "-hd"))
                        disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
                    else
                        disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
                }
                disk->dst = strdup(arg + 1);
            }
            disk->src = strdup(val);
            if (!disk->src ||
                !disk->dst) {
                virDomainDiskDefFree(disk);
                goto no_memory;
            }

6629
            if (virDomainDiskDefAssignAddress(caps, disk) < 0)
6630
                goto error;
6631

6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647
            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
                virDomainDiskDefFree(disk);
                goto no_memory;
            }
            def->disks[def->ndisks++] = disk;
        } else if (STREQ(arg, "-no-acpi")) {
            def->features &= ~(1 << VIR_DOMAIN_FEATURE_ACPI);
        } else if (STREQ(arg, "-no-reboot")) {
            def->onReboot = VIR_DOMAIN_LIFECYCLE_DESTROY;
        } else if (STREQ(arg, "-no-kvm")) {
            def->virtType = VIR_DOMAIN_VIRT_QEMU;
        } else if (STREQ(arg, "-nographic")) {
            nographics = 1;
        } else if (STREQ(arg, "-full-screen")) {
            fullscreen = 1;
        } else if (STREQ(arg, "-localtime")) {
6648
            def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672
        } else if (STREQ(arg, "-kernel")) {
            WANT_VALUE();
            if (!(def->os.kernel = strdup(val)))
                goto no_memory;
        } else if (STREQ(arg, "-initrd")) {
            WANT_VALUE();
            if (!(def->os.initrd = strdup(val)))
                goto no_memory;
        } else if (STREQ(arg, "-append")) {
            WANT_VALUE();
            if (!(def->os.cmdline = strdup(val)))
                goto no_memory;
        } else if (STREQ(arg, "-boot")) {
            int n, b = 0;
            WANT_VALUE();
            for (n = 0 ; val[n] && b < VIR_DOMAIN_BOOT_LAST ; n++) {
                if (val[n] == 'a')
                    def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_FLOPPY;
                else if (val[n] == 'c')
                    def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_DISK;
                else if (val[n] == 'd')
                    def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM;
                else if (val[n] == 'n')
                    def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET;
6673 6674
                else if (val[n] == ',')
                    break;
6675 6676
            }
            def->os.nBootDevs = b;
6677 6678 6679

            if (strstr(val, "menu=on"))
                def->os.bootmenu = 1;
6680
        } else if (STREQ(arg, "-name")) {
6681
            char *process;
6682
            WANT_VALUE();
6683 6684 6685 6686 6687 6688 6689 6690
            process = strstr(val, ",process=");
            if (process == NULL) {
                if (!(def->name = strdup(val)))
                    goto no_memory;
            } else {
                if (!(def->name = strndup(val, process - val)))
                    goto no_memory;
            }
6691 6692 6693 6694 6695 6696 6697 6698
        } else if (STREQ(arg, "-M")) {
            WANT_VALUE();
            if (!(def->os.machine = strdup(val)))
                goto no_memory;
        } else if (STREQ(arg, "-serial")) {
            WANT_VALUE();
            if (STRNEQ(val, "none")) {
                virDomainChrDefPtr chr;
6699
                if (!(chr = qemuParseCommandLineChr(val)))
6700 6701 6702 6703 6704
                    goto error;
                if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
                    virDomainChrDefFree(chr);
                    goto no_memory;
                }
6705
                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
6706
                chr->target.port = def->nserials;
6707 6708 6709 6710 6711 6712
                def->serials[def->nserials++] = chr;
            }
        } else if (STREQ(arg, "-parallel")) {
            WANT_VALUE();
            if (STRNEQ(val, "none")) {
                virDomainChrDefPtr chr;
6713
                if (!(chr = qemuParseCommandLineChr(val)))
6714 6715 6716 6717 6718
                    goto error;
                if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
                    virDomainChrDefFree(chr);
                    goto no_memory;
                }
6719
                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
6720
                chr->target.port = def->nparallels;
6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765
                def->parallels[def->nparallels++] = chr;
            }
        } else if (STREQ(arg, "-usbdevice")) {
            WANT_VALUE();
            if (STREQ(val, "tablet") ||
                STREQ(val, "mouse")) {
                virDomainInputDefPtr input;
                if (VIR_ALLOC(input) < 0)
                    goto no_memory;
                input->bus = VIR_DOMAIN_INPUT_BUS_USB;
                if (STREQ(val, "tablet"))
                    input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
                else
                    input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
                if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
                    virDomainInputDefFree(input);
                    goto no_memory;
                }
                def->inputs[def->ninputs++] = input;
            } else if (STRPREFIX(val, "disk:")) {
                virDomainDiskDefPtr disk;
                if (VIR_ALLOC(disk) < 0)
                    goto no_memory;
                disk->src = strdup(val + strlen("disk:"));
                if (!disk->src) {
                    virDomainDiskDefFree(disk);
                    goto no_memory;
                }
                if (STRPREFIX(disk->src, "/dev/"))
                    disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
                else
                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
                disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
                disk->bus = VIR_DOMAIN_DISK_BUS_USB;
                if (!(disk->dst = strdup("sda"))) {
                    virDomainDiskDefFree(disk);
                    goto no_memory;
                }
                if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
                    virDomainDiskDefFree(disk);
                    goto no_memory;
                }
                def->disks[def->ndisks++] = disk;
            } else {
                virDomainHostdevDefPtr hostdev;
6766
                if (!(hostdev = qemuParseCommandLineUSB(val)))
6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777
                    goto error;
                if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
                    virDomainHostdevDefFree(hostdev);
                    goto no_memory;
                }
                def->hostdevs[def->nhostdevs++] = hostdev;
            }
        } else if (STREQ(arg, "-net")) {
            WANT_VALUE();
            if (!STRPREFIX(val, "nic") && STRNEQ(val, "none")) {
                virDomainNetDefPtr net;
6778
                if (!(net = qemuParseCommandLineNet(caps, val, nnics, nics)))
6779 6780 6781 6782 6783 6784 6785 6786 6787 6788
                    goto error;
                if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0) {
                    virDomainNetDefFree(net);
                    goto no_memory;
                }
                def->nets[def->nnets++] = net;
            }
        } else if (STREQ(arg, "-drive")) {
            virDomainDiskDefPtr disk;
            WANT_VALUE();
6789
            if (!(disk = qemuParseCommandLineDisk(caps, val, nvirtiodisk)))
6790 6791 6792 6793 6794 6795
                goto error;
            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
                virDomainDiskDefFree(disk);
                goto no_memory;
            }
            def->disks[def->ndisks++] = disk;
6796 6797 6798

            if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)
                nvirtiodisk++;
6799 6800 6801
        } else if (STREQ(arg, "-pcidevice")) {
            virDomainHostdevDefPtr hostdev;
            WANT_VALUE();
6802
            if (!(hostdev = qemuParseCommandLinePCI(val)))
6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839
                goto error;
            if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
                virDomainHostdevDefFree(hostdev);
                goto no_memory;
            }
            def->hostdevs[def->nhostdevs++] = hostdev;
        } else if (STREQ(arg, "-soundhw")) {
            const char *start;
            WANT_VALUE();
            start = val;
            while (start) {
                const char *tmp = strchr(start, ',');
                int type = -1;
                if (STRPREFIX(start, "pcspk")) {
                    type = VIR_DOMAIN_SOUND_MODEL_PCSPK;
                } else if (STRPREFIX(start, "sb16")) {
                    type = VIR_DOMAIN_SOUND_MODEL_SB16;
                } else if (STRPREFIX(start, "es1370")) {
                    type = VIR_DOMAIN_SOUND_MODEL_ES1370;
                } else if (STRPREFIX(start, "ac97")) {
                    type = VIR_DOMAIN_SOUND_MODEL_AC97;
                }

                if (type != -1) {
                    virDomainSoundDefPtr snd;
                    if (VIR_ALLOC(snd) < 0)
                        goto no_memory;
                    snd->model = type;
                    if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
                        VIR_FREE(snd);
                        goto no_memory;
                    }
                    def->sounds[def->nsounds++] = snd;
                }

                start = tmp ? tmp + 1 : NULL;
            }
R
Richard Jones 已提交
6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857
        } else if (STREQ(arg, "-watchdog")) {
            WANT_VALUE();
            int model = virDomainWatchdogModelTypeFromString (val);

            if (model != -1) {
                virDomainWatchdogDefPtr wd;
                if (VIR_ALLOC(wd) < 0)
                    goto no_memory;
                wd->model = model;
                wd->action = VIR_DOMAIN_WATCHDOG_ACTION_RESET;
                def->watchdog = wd;
            }
        } else if (STREQ(arg, "-watchdog-action") && def->watchdog) {
            WANT_VALUE();
            int action = virDomainWatchdogActionTypeFromString (val);

            if (action != -1)
                def->watchdog->action = action;
6858 6859 6860 6861 6862
        } else if (STREQ(arg, "-bootloader")) {
            WANT_VALUE();
            def->os.bootloader = strdup(val);
            if (!def->os.bootloader)
                goto no_memory;
6863 6864 6865 6866 6867 6868
        } else if (STREQ(arg, "-vmwarevga")) {
            video = VIR_DOMAIN_VIDEO_TYPE_VMVGA;
        } else if (STREQ(arg, "-std-vga")) {
            video = VIR_DOMAIN_VIDEO_TYPE_VGA;
        } else if (STREQ(arg, "-vga")) {
            WANT_VALUE();
6869 6870 6871
            if (STRNEQ(val, "none")) {
                video = qemuVideoTypeFromString(val);
                if (video < 0) {
6872 6873
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("unknown video adapter type '%s'"), val);
6874 6875
                    goto error;
                }
6876
            }
6877 6878
        } else if (STREQ(arg, "-cpu")) {
            WANT_VALUE();
6879
            if (qemuParseCommandLineCPU(def, val) < 0)
6880
                goto error;
6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897
        } else if (STREQ(arg, "-domid")) {
            WANT_VALUE();
            /* ignore, generted on the fly */
        } else if (STREQ(arg, "-usb")) {
            /* ignore, always added by libvirt */
        } else if (STREQ(arg, "-pidfile")) {
            WANT_VALUE();
            /* ignore, used by libvirt as needed */
        } else if (STREQ(arg, "-incoming")) {
            WANT_VALUE();
            /* ignore, used via restore/migrate APIs */
        } else if (STREQ(arg, "-monitor")) {
            WANT_VALUE();
            /* ignore, used internally by libvirt */
        } else if (STREQ(arg, "-S")) {
            /* ignore, always added by libvirt */
        } else {
6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908
            /* something we can't yet parse.  Add it to the qemu namespace
             * cmdline/environment advanced options and hope for the best
             */
            VIR_WARN("unknown QEMU argument '%s', adding to the qemu namespace",
                     arg);
            if (VIR_REALLOC_N(cmd->args, cmd->num_args+1) < 0)
                goto no_memory;
            cmd->args[cmd->num_args] = strdup(arg);
            if (cmd->args[cmd->num_args] == NULL)
                goto no_memory;
            cmd->num_args++;
6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939
        }
    }

#undef WANT_VALUE

    if (!nographics && def->ngraphics == 0) {
        virDomainGraphicsDefPtr sdl;
        const char *display = qemuFindEnv(progenv, "DISPLAY");
        const char *xauth = qemuFindEnv(progenv, "XAUTHORITY");
        if (VIR_ALLOC(sdl) < 0)
            goto no_memory;
        sdl->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
        sdl->data.sdl.fullscreen = fullscreen;
        if (display &&
            !(sdl->data.sdl.display = strdup(display))) {
            VIR_FREE(sdl);
            goto no_memory;
        }
        if (xauth &&
            !(sdl->data.sdl.xauth = strdup(xauth))) {
            VIR_FREE(sdl);
            goto no_memory;
        }

        if (VIR_REALLOC_N(def->graphics, def->ngraphics+1) < 0) {
            virDomainGraphicsDefFree(sdl);
            goto no_memory;
        }
        def->graphics[def->ngraphics++] = sdl;
    }

6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957
    if (def->ngraphics) {
        virDomainVideoDefPtr vid;
        if (VIR_ALLOC(vid) < 0)
            goto no_memory;
        if (def->virtType == VIR_DOMAIN_VIRT_XEN)
            vid->type = VIR_DOMAIN_VIDEO_TYPE_XEN;
        else
            vid->type = video;
        vid->vram = virDomainVideoDefaultRAM(def, vid->type);
        vid->heads = 1;

        if (VIR_REALLOC_N(def->videos, def->nvideos+1) < 0) {
            virDomainVideoDefFree(vid);
            goto no_memory;
        }
        def->videos[def->nvideos++] = vid;
    }

6958 6959 6960
    /*
     * having a balloon is the default, define one with type="none" to avoid it
     */
6961 6962 6963 6964 6965 6966 6967 6968 6969
    if (!def->memballoon) {
        virDomainMemballoonDefPtr memballoon;
        if (VIR_ALLOC(memballoon) < 0)
            goto no_memory;
        memballoon->model = VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO;

        def->memballoon = memballoon;
    }

6970 6971 6972 6973 6974 6975 6976
    VIR_FREE(nics);

    if (!def->name) {
        if (!(def->name = strdup("unnamed")))
            goto no_memory;
    }

6977
    if (virDomainDefAddImplicitControllers(def) < 0)
6978 6979
        goto error;

6980 6981 6982 6983 6984 6985 6986
    if (cmd->num_args || cmd->num_env) {
        def->ns = caps->ns;
        def->namespaceData = cmd;
    }
    else
        VIR_FREE(cmd);

6987 6988 6989
    return def;

no_memory:
6990
    virReportOOMError();
6991
error:
6992
    VIR_FREE(cmd);
6993 6994 6995 6996 6997 6998
    virDomainDefFree(def);
    VIR_FREE(nics);
    return NULL;
}


6999
virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
7000 7001 7002 7003 7004 7005 7006 7007 7008 7009
                                           const char *args)
{
    const char **progenv = NULL;
    const char **progargv = NULL;
    virDomainDefPtr def = NULL;
    int i;

    if (qemuStringToArgvEnv(args, &progenv, &progargv) < 0)
        goto cleanup;

7010
    def = qemuParseCommandLine(caps, progenv, progargv);
7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022

cleanup:
    for (i = 0 ; progargv && progargv[i] ; i++)
        VIR_FREE(progargv[i]);
    VIR_FREE(progargv);

    for (i = 0 ; progenv && progenv[i] ; i++)
        VIR_FREE(progenv[i]);
    VIR_FREE(progenv);

    return def;
}