qemu_conf.c 39.7 KB
Newer Older
D
Daniel P. Berrange 已提交
1 2 3
/*
 * config.c: VM configuration management
 *
4
 * Copyright (C) 2006, 2007, 2008 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 31 32 33
#include <dirent.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
34
#include <sys/wait.h>
35
#include <arpa/inet.h>
36
#include <sys/utsname.h>
D
Daniel P. Berrange 已提交
37

38 39 40 41
#if HAVE_NUMACTL
#include <numa.h>
#endif

42
#include "qemu_conf.h"
43
#include "uuid.h"
44
#include "buf.h"
D
Daniel P. Berrange 已提交
45
#include "conf.h"
46
#include "util.h"
47
#include "memory.h"
J
Jim Meyering 已提交
48
#include "verify.h"
49 50 51 52 53 54 55

VIR_ENUM_DECL(virDomainDiskQEMUBus)
VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
              "ide",
              "floppy",
              "scsi",
              "virtio",
56 57
              "xen",
              "usb")
58

59

60 61
#define qemudLog(level, msg...) fprintf(stderr, msg)

62 63 64 65 66
void qemudReportError(virConnectPtr conn,
                      virDomainPtr dom,
                      virNetworkPtr net,
                      int code, const char *fmt, ...) {
    va_list args;
67
    char errorMessage[1024];
D
Daniel Veillard 已提交
68
    const char *virerr;
69 70 71

    if (fmt) {
        va_start(args, fmt);
72
        vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args);
73 74 75 76
        va_end(args);
    } else {
        errorMessage[0] = '\0';
    }
D
Daniel Veillard 已提交
77

78
    virerr = __virErrorMsg(code, (errorMessage[0] ? errorMessage : NULL));
79
    __virRaiseError(conn, dom, net, VIR_FROM_QEMU, code, VIR_ERR_ERROR,
D
Daniel Veillard 已提交
80
                    virerr, errorMessage, NULL, -1, -1, virerr, errorMessage);
81 82
}

D
Daniel P. Berrange 已提交
83 84 85 86 87 88
int qemudLoadDriverConfig(struct qemud_driver *driver,
                          const char *filename) {
    virConfPtr conf;
    virConfValuePtr p;

    /* Setup 2 critical defaults */
89 90 91 92 93
    if (!(driver->vncListen = strdup("127.0.0.1"))) {
        qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
                         "%s", _("failed to allocate vncListen"));
        return -1;
    }
D
Daniel P. Berrange 已提交
94 95
    if (!(driver->vncTLSx509certdir = strdup(SYSCONF_DIR "/pki/libvirt-vnc"))) {
        qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
96
                         "%s", _("failed to allocate vncTLSx509certdir"));
D
Daniel P. Berrange 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
        return -1;
    }

    /* Just check the file is readable before opening it, otherwise
     * libvirt emits an error.
     */
    if (access (filename, R_OK) == -1) return 0;

    conf = virConfReadFile (filename);
    if (!conf) return 0;


#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) {               \
        qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,      \
                         "remoteReadConfigFile: %s: %s: expected type " #typ "\n", \
                         filename, (name));                             \
        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) {
128
        VIR_FREE(driver->vncTLSx509certdir);
D
Daniel P. Berrange 已提交
129 130
        if (!(driver->vncTLSx509certdir = strdup(p->str))) {
            qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
131
                             "%s", _("failed to allocate vncTLSx509certdir"));
D
Daniel P. Berrange 已提交
132 133 134 135 136 137 138 139
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "vnc_listen");
    CHECK_TYPE ("vnc_listen", VIR_CONF_STRING);
    if (p && p->str) {
140 141 142 143 144 145
        if (!(driver->vncListen = strdup(p->str))) {
            qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
                             "%s", _("failed to allocate vncTLSx509certdir"));
            virConfFree(conf);
            return -1;
        }
D
Daniel P. Berrange 已提交
146 147 148 149 150 151
    }

    virConfFree (conf);
    return 0;
}

D
Daniel P. Berrange 已提交
152 153
/* The list of possible machine types for various architectures,
   as supported by QEMU - taken from 'qemu -M ?' for each arch */
154 155
static const char *const arch_info_hvm_x86_machines[] = {
    "pc", "isapc"
D
Daniel P. Berrange 已提交
156
};
157 158
static const char *const arch_info_hvm_mips_machines[] = {
    "mips"
D
Daniel P. Berrange 已提交
159
};
160 161
static const char *const arch_info_hvm_sparc_machines[] = {
    "sun4m"
D
Daniel P. Berrange 已提交
162
};
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
static const char *const arch_info_hvm_ppc_machines[] = {
    "g3bw", "mac99", "prep"
};

static const char *const arch_info_xen_x86_machines[] = {
    "xenner"
};

struct qemu_feature_flags {
    const char *name;
    const int default_on;
    const int toggle;
};

struct qemu_arch_info {
    const char *arch;
    int wordsize;
    const char *const *machines;
    int nmachines;
    const char *binary;
    const struct qemu_feature_flags *flags;
    int nflags;
D
Daniel P. Berrange 已提交
185 186
};

187
/* Feature flags for the architecture info */
J
Jim Meyering 已提交
188
static const struct qemu_feature_flags const arch_info_i686_flags [] = {
189 190
    { "pae",  1, 0 },
    { "nonpae",  1, 0 },
191 192 193 194
    { "acpi", 1, 1 },
    { "apic", 1, 0 },
};

J
Jim Meyering 已提交
195
static const struct qemu_feature_flags const arch_info_x86_64_flags [] = {
196 197 198 199
    { "acpi", 1, 1 },
    { "apic", 1, 0 },
};

D
Daniel P. Berrange 已提交
200
/* The archicture tables for supported QEMU archs */
201 202 203 204 205 206 207 208 209 210 211 212 213
static const struct qemu_arch_info const arch_info_hvm[] = {
    {  "i686", 32, arch_info_hvm_x86_machines, 2,
       "/usr/bin/qemu", arch_info_i686_flags, 4 },
    {  "x86_64", 64, arch_info_hvm_x86_machines, 2,
       "/usr/bin/qemu-system-x86_64", arch_info_x86_64_flags, 2 },
    {  "mips", 32, arch_info_hvm_mips_machines, 1,
       "/usr/bin/qemu-system-mips", NULL, 0 },
    {  "mipsel", 32, arch_info_hvm_mips_machines, 1,
       "/usr/bin/qemu-system-mipsel", NULL, 0 },
    {  "sparc", 32, arch_info_hvm_sparc_machines, 1,
       "/usr/bin/qemu-system-sparc", NULL, 0 },
    {  "ppc", 32, arch_info_hvm_ppc_machines, 3,
       "/usr/bin/qemu-system-ppc", NULL, 0 },
D
Daniel P. Berrange 已提交
214 215
};

216 217 218 219 220 221
static const struct qemu_arch_info const arch_info_xen[] = {
    {  "i686", 32, arch_info_xen_x86_machines, 1,
       "/usr/bin/xenner", arch_info_i686_flags, 4 },
    {  "x86_64", 64, arch_info_xen_x86_machines, 1,
       "/usr/bin/xenner", arch_info_x86_64_flags, 2 },
};
D
Daniel P. Berrange 已提交
222

223 224 225 226 227 228
static int
qemudCapsInitGuest(virCapsPtr caps,
                   const char *hostmachine,
                   const struct qemu_arch_info *info,
                   int hvm) {
    virCapsGuestPtr guest;
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
    int i, haskvm, hasbase, samearch;
    const char *kvmbin = NULL;

    /* Check for existance of base emulator */
    hasbase = (access(info->binary, X_OK) == 0);

    samearch = STREQ(info->arch, hostmachine);
    if (samearch) {
        const char *const kvmbins[] = { "/usr/bin/qemu-kvm", /* Fedora */
                                        "/usr/bin/kvm" }; /* Upstream .spec */

        for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) {
            if ((haskvm = (access(kvmbins[i], X_OK) == 0))) {
                kvmbin = kvmbins[i];
                break;
            }
        }
    } else {
        haskvm = 0;
    }

    if (!hasbase && !haskvm)
        return 0;
D
Daniel P. Berrange 已提交
252

253 254 255 256 257 258 259 260 261
    if ((guest = virCapabilitiesAddGuest(caps,
                                         hvm ? "hvm" : "xen",
                                         info->arch,
                                         info->wordsize,
                                         info->binary,
                                         NULL,
                                         info->nmachines,
                                         info->machines)) == NULL)
        return -1;
D
Daniel P. Berrange 已提交
262

263
    if (hvm) {
264
        if (hasbase &&
265 266 267 268 269 270 271
            virCapabilitiesAddGuestDomain(guest,
                                          "qemu",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            return -1;
D
Daniel P. Berrange 已提交
272

273
        /* If guest & host match, then we can accelerate */
274
        if (samearch) {
275 276 277 278 279 280 281 282 283 284
            if (access("/dev/kqemu", F_OK) == 0 &&
                virCapabilitiesAddGuestDomain(guest,
                                              "kqemu",
                                              NULL,
                                              NULL,
                                              0,
                                              NULL) == NULL)
                return -1;

            if (access("/dev/kvm", F_OK) == 0 &&
285
                haskvm &&
286 287
                virCapabilitiesAddGuestDomain(guest,
                                              "kvm",
288
                                              kvmbin,
289 290 291 292 293 294 295 296 297 298 299 300 301 302
                                              NULL,
                                              0,
                                              NULL) == NULL)
                return -1;
        }
    } else {
        if (virCapabilitiesAddGuestDomain(guest,
                                          "kvm",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            return -1;
    }
D
Daniel P. Berrange 已提交
303

304 305 306 307 308 309 310
    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)
                return -1;
D
Daniel P. Berrange 已提交
311 312 313
        }
    }

314
    return 0;
D
Daniel P. Berrange 已提交
315 316
}

317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
#if HAVE_NUMACTL
#define MAX_CPUS 4096
#define MAX_CPUS_MASK_SIZE (sizeof(unsigned long))
#define MAX_CPUS_MASK_LEN (MAX_CPUS / MAX_CPUS_MASK_SIZE)
#define MAX_CPUS_MASK_BYTES (MAX_CPUS / 8)

#define MASK_CPU_ISSET(mask, cpu) \
    (((mask)[((cpu) / MAX_CPUS_MASK_SIZE)] >> ((cpu) % MAX_CPUS_MASK_SIZE)) & 1)

static int
qemudCapsInitNUMA(virCapsPtr caps)
{
    int n, i;
    unsigned long *mask = NULL;
    int ncpus;
    int *cpus = NULL;
    int ret = -1;

    if (numa_available() < 0)
        return 0;

    if (VIR_ALLOC_N(mask, MAX_CPUS_MASK_LEN) < 0)
        goto cleanup;

    for (n = 0 ; n <= numa_max_node() ; n++) {
        if (numa_node_to_cpus(n, mask, MAX_CPUS_MASK_BYTES) < 0)
            goto cleanup;

        for (ncpus = 0, i = 0 ; i < MAX_CPUS ; i++)
            if (MASK_CPU_ISSET(mask, i))
                ncpus++;

        if (VIR_ALLOC_N(cpus, ncpus) < 0)
            goto cleanup;

        for (ncpus = 0, i = 0 ; i < MAX_CPUS ; i++)
            if (MASK_CPU_ISSET(mask, i))
                cpus[ncpus++] = i;

        if (virCapabilitiesAddHostNUMACell(caps,
                                           n,
                                           ncpus,
                                           cpus) < 0)
            goto cleanup;

        VIR_FREE(cpus);
    }

    ret = 0;

cleanup:
    VIR_FREE(cpus);
    VIR_FREE(mask);
    return ret;
}
#else
static int qemudCapsInitNUMA(virCapsPtr caps ATTRIBUTE_UNUSED) { return 0; }
#endif

376 377 378 379
virCapsPtr qemudCapsInit(void) {
    struct utsname utsname;
    virCapsPtr caps;
    int i;
D
Daniel P. Berrange 已提交
380

381 382 383 384 385 386 387
    /* Really, this never fails - look at the man-page. */
    uname (&utsname);

    if ((caps = virCapabilitiesNew(utsname.machine,
                                   0, 0)) == NULL)
        goto no_memory;

388 389 390
    if (qemudCapsInitNUMA(caps) < 0)
        goto no_memory;

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
    for (i = 0 ; i < (sizeof(arch_info_hvm)/sizeof(arch_info_hvm[0])) ; i++)
        if (qemudCapsInitGuest(caps,
                               utsname.machine,
                               &arch_info_hvm[i], 1) < 0)
            goto no_memory;

    if (access("/usr/bin/xenner", X_OK) == 0 &&
        access("/dev/kvm", F_OK) == 0) {
        for (i = 0 ; i < (sizeof(arch_info_xen)/sizeof(arch_info_xen[0])) ; i++)
            /* 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"))) {
                if (qemudCapsInitGuest(caps,
                                       utsname.machine,
                                       &arch_info_xen[i], 0) < 0)
                    goto no_memory;
            }
D
Daniel P. Berrange 已提交
409 410
    }

411 412 413 414 415
    return caps;

 no_memory:
    virCapabilitiesFree(caps);
    return NULL;
D
Daniel P. Berrange 已提交
416 417
}

418

419 420 421 422 423
int qemudExtractVersionInfo(const char *qemu,
                            unsigned int *retversion,
                            unsigned int *retflags) {
    const char *const qemuarg[] = { qemu, "-help", NULL };
    const char *const qemuenv[] = { "LC_ALL=C", NULL };
424
    pid_t child;
425
    int newstdout = -1;
426
    int ret = -1, status;
427 428 429 430 431 432 433 434 435 436 437 438
    unsigned int major, minor, micro;
    unsigned int version;
    unsigned int flags = 0;

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

    if (virExec(NULL, qemuarg, qemuenv, NULL,
                &child, -1, &newstdout, NULL, VIR_EXEC_NONE) < 0)
        return -1;
439

440 441 442 443 444
    char *help = NULL;
    enum { MAX_HELP_OUTPUT_SIZE = 8192 };
    int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
    if (len < 0)
        goto cleanup2;
445

446 447 448
    if (sscanf(help, "QEMU PC emulator version %u.%u.%u",
               &major, &minor, &micro) != 3) {
        goto cleanup2;
449 450
    }

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

453 454 455 456 457 458 459 460 461 462 463 464
    if (strstr(help, "-no-kqemu"))
        flags |= QEMUD_CMD_FLAG_KQEMU;
    if (strstr(help, "-no-reboot"))
        flags |= QEMUD_CMD_FLAG_NO_REBOOT;
    if (strstr(help, "-name"))
        flags |= QEMUD_CMD_FLAG_NAME;
    if (strstr(help, "-drive"))
        flags |= QEMUD_CMD_FLAG_DRIVE;
    if (strstr(help, "boot=on"))
        flags |= QEMUD_CMD_FLAG_DRIVE_BOOT;
    if (version >= 9000)
        flags |= QEMUD_CMD_FLAG_VNC_COLON;
465

466 467 468 469
    if (retversion)
        *retversion = version;
    if (retflags)
        *retflags = flags;
470

471
    ret = 0;
472

473 474
    qemudDebug("Version %d %d %d  Cooked version: %d, with flags ? %d",
               major, minor, micro, version, flags);
475

476
cleanup2:
477
    VIR_FREE(help);
478 479
    if (close(newstdout) < 0)
        ret = -1;
480

481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
rewait:
    if (waitpid(child, &status, 0) != child) {
        if (errno == EINTR)
            goto rewait;

        qemudLog(QEMUD_ERR,
                 _("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) {
        qemudLog(QEMUD_WARN,
                 _("Unexpected exit status '%d', qemu probably failed"),
                 WEXITSTATUS(status));
498
    }
499 500

    return ret;
501 502
}

503
int qemudExtractVersion(virConnectPtr conn,
504 505
                        struct qemud_driver *driver) {
    const char *binary;
506
    struct stat sb;
507

508
    if (driver->qemuVersion > 0)
509 510
        return 0;

511 512
    if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
                                                      "hvm",
513 514 515
                                                      "i686",
                                                      "qemu")) == NULL)
        return -1;
516

517 518 519 520 521
    if (stat(binary, &sb) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Cannot find QEMU binary %s: %s"), binary,
                         strerror(errno));
        return -1;
522 523
    }

524
    if (qemudExtractVersionInfo(binary, &driver->qemuVersion, NULL) < 0) {
525 526
        return -1;
    }
D
Daniel P. Berrange 已提交
527

528
    return 0;
D
Daniel P. Berrange 已提交
529 530 531
}


532
static char *
533 534
qemudNetworkIfaceConnect(virConnectPtr conn,
                         struct qemud_driver *driver,
535 536 537
                         int **tapfds,
                         int *ntapfds,
                         virDomainNetDefPtr net,
538
                         int vlan)
539
{
540
    virNetworkObjPtr network = NULL;
541
    char *brname;
542 543 544 545 546
    char tapfdstr[4+3+32+7];
    char *retval = NULL;
    int err;
    int tapfd = -1;

547 548
    if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
        if (!(network = virNetworkFindByName(driver->networks, net->data.network.name))) {
549
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
550
                             _("Network '%s' not found"),
551
                             net->data.network.name);
552
            goto error;
553
        } else if (network->def->bridge == NULL) {
554
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
555
                             _("Network '%s' not active"),
556
                             net->data.network.name);
557 558
            goto error;
        }
559
        brname = network->def->bridge;
560 561
    } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
        brname = net->data.bridge.brname;
562
    } else {
563
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
564
                         _("Network type %d is not supported"), net->type);
565 566 567
        goto error;
    }

568 569 570 571 572 573 574 575 576 577
    if (!net->ifname ||
        STRPREFIX(net->ifname, "vnet") ||
        strchr(net->ifname, '%')) {
        VIR_FREE(net->ifname);
        if (!(net->ifname = strdup("vnet%d"))) {
            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
            goto error;
        }
    }

578
    if (!driver->brctl && (err = brInit(&driver->brctl))) {
579
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
580 581
                         _("cannot initialize bridge support: %s"),
                         strerror(err));
582 583 584
        goto error;
    }

585
    if ((err = brAddTap(driver->brctl, brname,
586
                        &net->ifname, &tapfd))) {
587 588 589 590 591 592 593 594 595
        if (errno == ENOTSUP) {
            /* In this particular case, give a better diagnostic. */
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             _("Failed to add tap interface to bridge. "
                               "%s is not a bridge device"), brname);
        } else {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             _("Failed to add tap interface '%s' "
                               "to bridge '%s' : %s"),
596
                             net->ifname, brname, strerror(err));
597
        }
598 599 600
        goto error;
    }

601 602
    snprintf(tapfdstr, sizeof(tapfdstr),
             "tap,fd=%d,script=,vlan=%d,ifname=%s",
603
             tapfd, vlan, net->ifname);
604 605 606 607

    if (!(retval = strdup(tapfdstr)))
        goto no_memory;

608
    if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0)
609 610
        goto no_memory;

611
    (*tapfds)[(*ntapfds)++] = tapfd;
612 613 614 615

    return retval;

 no_memory:
616 617
    qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
                     "%s", _("failed to allocate space for tapfds string"));
618
 error:
619
    VIR_FREE(retval);
620 621 622 623 624
    if (tapfd != -1)
        close(tapfd);
    return NULL;
}

625
static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
626 627 628
                                          char *buf,
                                          int buflen)
{
629 630
    switch (dev->type) {
    case VIR_DOMAIN_CHR_TYPE_NULL:
631 632 633 634
        strncpy(buf, "null", buflen);
        buf[buflen-1] = '\0';
        break;

635
    case VIR_DOMAIN_CHR_TYPE_VC:
636 637 638 639
        strncpy(buf, "vc", buflen);
        buf[buflen-1] = '\0';
        break;

640
    case VIR_DOMAIN_CHR_TYPE_PTY:
641 642 643 644
        strncpy(buf, "pty", buflen);
        buf[buflen-1] = '\0';
        break;

645
    case VIR_DOMAIN_CHR_TYPE_DEV:
646
        if (snprintf(buf, buflen, "%s",
647
                     dev->data.file.path) >= buflen)
648 649 650
            return -1;
        break;

651
    case VIR_DOMAIN_CHR_TYPE_FILE:
652
        if (snprintf(buf, buflen, "file:%s",
653
                     dev->data.file.path) >= buflen)
654 655 656
            return -1;
        break;

657
    case VIR_DOMAIN_CHR_TYPE_PIPE:
658
        if (snprintf(buf, buflen, "pipe:%s",
659
                     dev->data.file.path) >= buflen)
660 661 662
            return -1;
        break;

663
    case VIR_DOMAIN_CHR_TYPE_STDIO:
664 665 666 667
        strncpy(buf, "stdio", buflen);
        buf[buflen-1] = '\0';
        break;

668
    case VIR_DOMAIN_CHR_TYPE_UDP:
669
        if (snprintf(buf, buflen, "udp:%s:%s@%s:%s",
670 671 672 673
                     dev->data.udp.connectHost,
                     dev->data.udp.connectService,
                     dev->data.udp.bindHost,
                     dev->data.udp.bindService) >= buflen)
674 675 676
            return -1;
        break;

677
    case VIR_DOMAIN_CHR_TYPE_TCP:
678 679 680 681 682 683 684 685 686 687 688 689 690
        if (dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET) {
            if (snprintf(buf, buflen, "telnet:%s:%s%s",
                         dev->data.tcp.host,
                         dev->data.tcp.service,
                         dev->data.tcp.listen ? ",server" : "") >= buflen)
                return -1;
        } else {
            if (snprintf(buf, buflen, "tcp:%s:%s%s",
                         dev->data.tcp.host,
                         dev->data.tcp.service,
                         dev->data.tcp.listen ? ",listen" : "") >= buflen)
                return -1;
        }
691 692
        break;

693
    case VIR_DOMAIN_CHR_TYPE_UNIX:
694
        if (snprintf(buf, buflen, "unix:%s%s",
695 696
                     dev->data.nix.path,
                     dev->data.nix.listen ? ",listen" : "") >= buflen)
697 698 699 700 701 702 703
            return -1;
        break;
    }

    return 0;
}

D
Daniel P. Berrange 已提交
704 705 706 707
/*
 * Constructs a argv suitable for launching qemu with config defined
 * for a given virtual machine.
 */
708 709
int qemudBuildCommandLine(virConnectPtr conn,
                          struct qemud_driver *driver,
710
                          virDomainObjPtr vm,
711
                          unsigned int qemuCmdFlags,
712
                          const char ***retargv,
713 714 715
                          int **tapfds,
                          int *ntapfds,
                          const char *migrateFrom) {
716
    int i;
D
Daniel P. Berrange 已提交
717 718
    char memory[50];
    char vcpus[50];
719 720 721 722 723
    char boot[VIR_DOMAIN_BOOT_LAST];
    virDomainDiskDefPtr disk = vm->def->disks;
    virDomainNetDefPtr net = vm->def->nets;
    virDomainInputDefPtr input = vm->def->inputs;
    virDomainSoundDefPtr sound = vm->def->sounds;
724
    virDomainHostdevDefPtr hostdev = vm->def->hostdevs;
725 726
    virDomainChrDefPtr serial = vm->def->serials;
    virDomainChrDefPtr parallel = vm->def->parallels;
727 728
    struct utsname ut;
    int disableKQEMU = 0;
729
    int qargc = 0, qarga = 0;
730
    const char **qargv = NULL;
731
    const char *emulator;
D
Daniel P. Berrange 已提交
732

733 734
    uname(&ut);

D
Daniel P. Berrange 已提交
735
    /* Nasty hack make i?86 look like i686 to simplify next comparison */
736 737 738 739
    if (ut.machine[0] == 'i' &&
        ut.machine[2] == '8' &&
        ut.machine[3] == '6' &&
        !ut.machine[4])
D
Daniel P. Berrange 已提交
740
        ut.machine[1] = '6';
741 742 743 744 745 746

    /* Need to explicitly disable KQEMU if
     * 1. Arch matches host arch
     * 2. Guest is 'qemu'
     * 3. The qemu binary has the -no-kqemu flag
     */
747
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
748
        STREQ(ut.machine, vm->def->os.arch) &&
749
        vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
750 751
        disableKQEMU = 1;

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
#define ADD_ARG_SPACE                                                   \
    do { \
        if (qargc == qarga) {                                           \
            qarga += 10;                                                \
            if (VIR_REALLOC_N(qargv, qarga) < 0)                        \
                goto no_memory;                                         \
        }                                                               \
    } while (0)

#define ADD_ARG(thisarg)                                                \
    do {                                                                \
        ADD_ARG_SPACE;                                                  \
        qargv[qargc++] = thisarg;                                       \
    } while (0)

#define ADD_ARG_LIT(thisarg)                                            \
    do {                                                                \
        ADD_ARG_SPACE;                                                  \
        if ((qargv[qargc++] = strdup(thisarg)) == NULL)                 \
            goto no_memory;                                             \
    } while (0)
D
Daniel P. Berrange 已提交
773

774 775 776 777
#define ADD_USBDISK(thisarg)                                            \
    do {                                                                \
        ADD_ARG_LIT("-usbdevice");                                      \
        ADD_ARG_SPACE;                                                  \
778
        if ((asprintf((char **)&(qargv[qargc++]), "disk:%s", thisarg)) == -1) {    \
779 780 781 782 783
            qargv[qargc-1] = NULL;                                      \
            goto no_memory;                                             \
        }                                                               \
    } while (0)

784
    snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024);
785
    snprintf(vcpus, sizeof(vcpus), "%lu", vm->def->vcpus);
D
Daniel P. Berrange 已提交
786

787 788 789 790 791
    emulator = vm->def->emulator;
    if (!emulator)
        emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
    if (!emulator)
        return -1;
792

793
    ADD_ARG_LIT(emulator);
794 795 796 797 798 799 800 801 802
    ADD_ARG_LIT("-S");
    ADD_ARG_LIT("-M");
    ADD_ARG_LIT(vm->def->os.machine);
    if (disableKQEMU)
        ADD_ARG_LIT("-no-kqemu");
    ADD_ARG_LIT("-m");
    ADD_ARG_LIT(memory);
    ADD_ARG_LIT("-smp");
    ADD_ARG_LIT(vcpus);
D
Daniel P. Berrange 已提交
803

804
    if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
805 806
        ADD_ARG_LIT("-name");
        ADD_ARG_LIT(vm->def->name);
807
    }
808 809 810 811 812 813 814
    /*
     * 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...
     */
815
    if (!vm->def->graphics)
816
        ADD_ARG_LIT("-nographic");
817

818 819
    ADD_ARG_LIT("-monitor");
    ADD_ARG_LIT("pty");
D
Daniel P. Berrange 已提交
820

821 822
    if (vm->def->localtime)
        ADD_ARG_LIT("-localtime");
823

824 825
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
        vm->def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
826
        ADD_ARG_LIT("-no-reboot");
D
Daniel P. Berrange 已提交
827

828
    if (!(vm->def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
829
        ADD_ARG_LIT("-no-acpi");
D
Daniel P. Berrange 已提交
830

831
    if (!vm->def->os.bootloader) {
D
Daniel P. Berrange 已提交
832 833
        for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
            switch (vm->def->os.bootDevs[i]) {
834
            case VIR_DOMAIN_BOOT_CDROM:
D
Daniel P. Berrange 已提交
835 836
                boot[i] = 'd';
                break;
837
            case VIR_DOMAIN_BOOT_FLOPPY:
D
Daniel P. Berrange 已提交
838 839
                boot[i] = 'a';
                break;
840
            case VIR_DOMAIN_BOOT_DISK:
D
Daniel P. Berrange 已提交
841 842
                boot[i] = 'c';
                break;
843
            case VIR_DOMAIN_BOOT_NET:
D
Daniel P. Berrange 已提交
844 845 846 847 848 849 850 851
                boot[i] = 'n';
                break;
            default:
                boot[i] = 'c';
                break;
            }
        }
        boot[vm->def->os.nBootDevs] = '\0';
852 853
        ADD_ARG_LIT("-boot");
        ADD_ARG_LIT(boot);
D
Daniel P. Berrange 已提交
854

855
        if (vm->def->os.kernel) {
856 857
            ADD_ARG_LIT("-kernel");
            ADD_ARG_LIT(vm->def->os.kernel);
D
Daniel P. Berrange 已提交
858
        }
859
        if (vm->def->os.initrd) {
860 861
            ADD_ARG_LIT("-initrd");
            ADD_ARG_LIT(vm->def->os.initrd);
D
Daniel P. Berrange 已提交
862
        }
863
        if (vm->def->os.cmdline) {
864 865
            ADD_ARG_LIT("-append");
            ADD_ARG_LIT(vm->def->os.cmdline);
D
Daniel P. Berrange 已提交
866 867
        }
    } else {
868 869
        ADD_ARG_LIT("-bootloader");
        ADD_ARG_LIT(vm->def->os.bootloader);
D
Daniel P. Berrange 已提交
870 871
    }

872
    /* If QEMU supports -drive param instead of old -hda, -hdb, -cdrom .. */
873
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
874 875 876
        int bootCD = 0, bootFloppy = 0, bootDisk = 0;

        /* If QEMU supports boot=on for -drive param... */
877
        if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
878 879
            for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
                switch (vm->def->os.bootDevs[i]) {
880
                case VIR_DOMAIN_BOOT_CDROM:
881 882
                    bootCD = 1;
                    break;
883
                case VIR_DOMAIN_BOOT_FLOPPY:
884 885
                    bootFloppy = 1;
                    break;
886
                case VIR_DOMAIN_BOOT_DISK:
887 888 889
                    bootDisk = 1;
                    break;
                }
890
            }
891
        }
D
Daniel P. Berrange 已提交
892

893 894 895 896 897
        while (disk) {
            char opt[PATH_MAX];
            const char *media = NULL;
            int bootable = 0;
            int idx = virDiskNameToIndex(disk->dst);
898
            const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
D
Daniel P. Berrange 已提交
899

900 901 902 903 904 905 906 907 908 909 910 911
            if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
                if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
                    ADD_USBDISK(disk->src);
                } else {
                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                     _("unsupported usb disk type for '%s'"), disk->src);
                    goto error;
                }
                disk = disk->next;
                continue;
            }

912 913 914 915 916 917 918
            if (idx < 0) {
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 _("unsupported disk type '%s'"), disk->dst);
                goto error;
            }

            switch (disk->device) {
919
            case VIR_DOMAIN_DISK_DEVICE_CDROM:
920 921
                bootable = bootCD;
                bootCD = 0;
922
                media = "media=cdrom,";
923
                break;
924
            case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
925 926 927
                bootable = bootFloppy;
                bootFloppy = 0;
                break;
928
            case VIR_DOMAIN_DISK_DEVICE_DISK:
929 930 931 932 933 934
                bootable = bootDisk;
                bootDisk = 0;
                break;
            }

            snprintf(opt, PATH_MAX, "file=%s,if=%s,%sindex=%d%s",
935
                     disk->src ? disk->src : "", bus,
936 937
                     media ? media : "",
                     idx,
938 939
                     bootable &&
                     disk->device == VIR_DOMAIN_DISK_DEVICE_DISK
940
                     ? ",boot=on" : "");
941

942 943
            ADD_ARG_LIT("-drive");
            ADD_ARG_LIT(opt);
944 945 946 947 948 949 950
            disk = disk->next;
        }
    } else {
        while (disk) {
            char dev[NAME_MAX];
            char file[PATH_MAX];

951 952 953 954 955 956 957 958 959 960 961 962
            if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
                if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
                    ADD_USBDISK(disk->src);
                } else {
                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                     _("unsupported usb disk type for '%s'"), disk->src);
                    goto error;
                }
                disk = disk->next;
                continue;
            }

963
            if (STREQ(disk->dst, "hdc") &&
964 965
                disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
                if (disk->src) {
966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
                    snprintf(dev, NAME_MAX, "-%s", "cdrom");
                } else {
                    disk = disk->next;
                    continue;
                }
            } else {
                if (STRPREFIX(disk->dst, "hd") ||
                    STRPREFIX(disk->dst, "fd")) {
                    snprintf(dev, NAME_MAX, "-%s", disk->dst);
                } else {
                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                     _("unsupported disk type '%s'"), disk->dst);
                    goto error;
                }
            }

            snprintf(file, PATH_MAX, "%s", disk->src);

984 985
            ADD_ARG_LIT(dev);
            ADD_ARG_LIT(file);
986 987 988

            disk = disk->next;
        }
D
Daniel P. Berrange 已提交
989 990 991
    }

    if (!net) {
992 993
        ADD_ARG_LIT("-net");
        ADD_ARG_LIT("none");
D
Daniel P. Berrange 已提交
994
    } else {
995
        int vlan = 0;
D
Daniel P. Berrange 已提交
996
        while (net) {
997
            char nic[100];
998

999 1000
            if (snprintf(nic, sizeof(nic),
                         "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s%s",
1001 1002 1003
                         net->mac[0], net->mac[1],
                         net->mac[2], net->mac[3],
                         net->mac[4], net->mac[5],
1004
                         vlan,
1005 1006
                         (net->model ? ",model=" : ""),
                         (net->model ? net->model : "")) >= sizeof(nic))
1007
                goto error;
D
Daniel P. Berrange 已提交
1008

1009 1010 1011
            ADD_ARG_LIT("-net");
            ADD_ARG_LIT(nic);
            ADD_ARG_LIT("-net");
1012

1013
            switch (net->type) {
1014 1015
            case VIR_DOMAIN_NET_TYPE_NETWORK:
            case VIR_DOMAIN_NET_TYPE_BRIDGE:
1016
                {
1017 1018 1019
                    char *tap = qemudNetworkIfaceConnect(conn, driver,
                                                         tapfds, ntapfds,
                                                         net, vlan);
1020 1021 1022 1023 1024
                    if (tap == NULL)
                        goto error;
                    ADD_ARG(tap);
                    break;
                }
1025

1026
            case VIR_DOMAIN_NET_TYPE_ETHERNET:
1027 1028 1029
                {
                    char arg[PATH_MAX];
                    if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d",
1030 1031
                                 net->ifname,
                                 net->data.ethernet.script,
1032 1033 1034
                                 vlan) >= (PATH_MAX-1))
                        goto error;

1035
                    ADD_ARG_LIT(arg);
1036 1037 1038
                }
                break;

1039 1040 1041
            case VIR_DOMAIN_NET_TYPE_CLIENT:
            case VIR_DOMAIN_NET_TYPE_SERVER:
            case VIR_DOMAIN_NET_TYPE_MCAST:
1042 1043 1044 1045
                {
                    char arg[PATH_MAX];
                    const char *mode = NULL;
                    switch (net->type) {
1046
                    case VIR_DOMAIN_NET_TYPE_CLIENT:
1047 1048
                        mode = "connect";
                        break;
1049
                    case VIR_DOMAIN_NET_TYPE_SERVER:
1050 1051
                        mode = "listen";
                        break;
1052
                    case VIR_DOMAIN_NET_TYPE_MCAST:
1053 1054 1055 1056 1057
                        mode = "mcast";
                        break;
                    }
                    if (snprintf(arg, PATH_MAX-1, "socket,%s=%s:%d,vlan=%d",
                                 mode,
1058 1059
                                 net->data.socket.address,
                                 net->data.socket.port,
1060 1061 1062
                                 vlan) >= (PATH_MAX-1))
                        goto error;

1063
                    ADD_ARG_LIT(arg);
1064 1065 1066
                }
                break;

1067
            case VIR_DOMAIN_NET_TYPE_USER:
1068 1069 1070 1071 1072 1073
            default:
                {
                    char arg[PATH_MAX];
                    if (snprintf(arg, PATH_MAX-1, "user,vlan=%d", vlan) >= (PATH_MAX-1))
                        goto error;

1074
                    ADD_ARG_LIT(arg);
1075
                }
1076
            }
D
Daniel P. Berrange 已提交
1077 1078

            net = net->next;
1079
            vlan++;
D
Daniel P. Berrange 已提交
1080 1081 1082
        }
    }

1083
    if (!serial) {
1084 1085
        ADD_ARG_LIT("-serial");
        ADD_ARG_LIT("none");
1086 1087 1088 1089 1090 1091 1092
    } else {
        while (serial) {
            char buf[4096];

            if (qemudBuildCommandLineChrDevStr(serial, buf, sizeof(buf)) < 0)
                goto error;

1093 1094
            ADD_ARG_LIT("-serial");
            ADD_ARG_LIT(buf);
1095 1096 1097 1098 1099 1100

            serial = serial->next;
        }
    }

    if (!parallel) {
1101 1102
        ADD_ARG_LIT("-parallel");
        ADD_ARG_LIT("none");
1103 1104 1105 1106 1107 1108 1109
    } else {
        while (parallel) {
            char buf[4096];

            if (qemudBuildCommandLineChrDevStr(parallel, buf, sizeof(buf)) < 0)
                goto error;

1110 1111
            ADD_ARG_LIT("-parallel");
            ADD_ARG_LIT(buf);
1112 1113 1114 1115 1116

            parallel = parallel->next;
        }
    }

1117
    ADD_ARG_LIT("-usb");
1118
    while (input) {
1119
        if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
1120
            ADD_ARG_LIT("-usbdevice");
1121
            ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
1122 1123 1124 1125 1126
        }

        input = input->next;
    }

1127 1128
    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
D
Daniel P. Berrange 已提交
1129
        char vncdisplay[PATH_MAX];
1130
        int ret;
D
Daniel P. Berrange 已提交
1131

1132
        if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
D
Daniel P. Berrange 已提交
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
            char options[PATH_MAX] = "";
            if (driver->vncTLS) {
                strcat(options, ",tls");
                if (driver->vncTLSx509verify) {
                    strcat(options, ",x509verify=");
                } else {
                    strcat(options, ",x509=");
                }
                strncat(options, driver->vncTLSx509certdir,
                        sizeof(options) - (strlen(driver->vncTLSx509certdir)-1));
                options[sizeof(options)-1] = '\0';
            }
            ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d%s",
D
Daniel P. Berrange 已提交
1146 1147 1148
                           (vm->def->graphics->data.vnc.listenAddr ?
                            vm->def->graphics->data.vnc.listenAddr :
                            (driver->vncListen ? driver->vncListen : "")),
1149
                           vm->def->graphics->data.vnc.port - 5900,
D
Daniel P. Berrange 已提交
1150 1151
                           options);
        } else {
1152
            ret = snprintf(vncdisplay, sizeof(vncdisplay), "%d",
1153
                           vm->def->graphics->data.vnc.port - 5900);
D
Daniel P. Berrange 已提交
1154
        }
1155
        if (ret < 0 || ret >= (int)sizeof(vncdisplay))
1156 1157
            goto error;

1158 1159
        ADD_ARG_LIT("-vnc");
        ADD_ARG_LIT(vncdisplay);
1160
        if (vm->def->graphics->data.vnc.keymap) {
1161
            ADD_ARG_LIT("-k");
1162
            ADD_ARG_LIT(vm->def->graphics->data.vnc.keymap);
1163
        }
1164 1165
    } else if (vm->def->graphics &&
               vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
D
Daniel P. Berrange 已提交
1166 1167 1168
        /* SDL is the default. no args needed */
    }

D
Daniel Veillard 已提交
1169 1170 1171
    /* Add sound hardware */
    if (sound) {
        int size = 100;
1172 1173
        char *modstr;
        if (VIR_ALLOC_N(modstr, size+1) < 0)
D
Daniel Veillard 已提交
1174 1175 1176
            goto no_memory;

        while(sound && size > 0) {
1177
            const char *model = virDomainSoundModelTypeToString(sound->model);
D
Daniel Veillard 已提交
1178
            if (!model) {
1179
                VIR_FREE(modstr);
1180 1181 1182
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("invalid sound model"));
                goto error;
D
Daniel Veillard 已提交
1183 1184 1185 1186 1187 1188 1189
            }
            strncat(modstr, model, size);
            size -= strlen(model);
            sound = sound->next;
            if (sound)
               strncat(modstr, ",", size--);
        }
1190 1191
        ADD_ARG_LIT("-soundhw");
        ADD_ARG(modstr);
D
Daniel Veillard 已提交
1192 1193
    }

1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
    /* Add host passthrough hardware */
    while (hostdev) {
        int ret;
        char* usbdev;

        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
            if(hostdev->source.subsys.usb.vendor) {
                    ret = asprintf(&usbdev, "host:%.4x:%.4x",
                               hostdev->source.subsys.usb.vendor,
                               hostdev->source.subsys.usb.product);

            } else {
                    ret = asprintf(&usbdev, "host:%.3d.%.3d",
                               hostdev->source.subsys.usb.bus,
                               hostdev->source.subsys.usb.device);
            }
            if (ret < 0) {
                usbdev = NULL;
                goto error;
            }
            ADD_ARG_LIT("-usbdevice");
            ADD_ARG_LIT(usbdev);
            VIR_FREE(usbdev);
        }
        hostdev = hostdev->next;
    }

1222
    if (migrateFrom) {
1223
        ADD_ARG_LIT("-incoming");
1224
        ADD_ARG_LIT(migrateFrom);
1225 1226
    }

1227
    ADD_ARG(NULL);
D
Daniel P. Berrange 已提交
1228

1229
    *retargv = qargv;
D
Daniel P. Berrange 已提交
1230 1231 1232
    return 0;

 no_memory:
1233 1234
    qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
                     "%s", _("failed to allocate space for argv string"));
1235
 error:
1236 1237 1238 1239 1240 1241
    if (tapfds &&
        *tapfds) {
        for (i = 0; ntapfds; i++)
            close((*tapfds)[i]);
        VIR_FREE(*tapfds);
        *ntapfds = 0;
1242
    }
1243 1244
    if (qargv) {
        for (i = 0 ; i < qargc ; i++)
1245 1246
            VIR_FREE((qargv)[i]);
        VIR_FREE(qargv);
D
Daniel P. Berrange 已提交
1247 1248
    }
    return -1;
1249 1250 1251 1252

#undef ADD_ARG
#undef ADD_ARG_LIT
#undef ADD_ARG_SPACE
D
Daniel P. Berrange 已提交
1253
}