qemu_conf.c 38.9 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;
D
Daniel P. Berrange 已提交
229 230
    int i;

231 232 233 234 235 236 237 238 239
    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 已提交
240

241 242 243 244 245 246 247 248 249 250
    if (hvm) {
        /* Check for existance of base emulator */
        if (access(info->binary, X_OK) == 0 &&
            virCapabilitiesAddGuestDomain(guest,
                                          "qemu",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            return -1;
D
Daniel P. Berrange 已提交
251

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
        /* If guest & host match, then we can accelerate */
        if (STREQ(info->arch, hostmachine)) {
            if (access("/dev/kqemu", F_OK) == 0 &&
                virCapabilitiesAddGuestDomain(guest,
                                              "kqemu",
                                              NULL,
                                              NULL,
                                              0,
                                              NULL) == NULL)
                return -1;

            if (access("/dev/kvm", F_OK) == 0 &&
                virCapabilitiesAddGuestDomain(guest,
                                              "kvm",
                                              "/usr/bin/qemu-kvm",
                                              NULL,
                                              0,
                                              NULL) == NULL)
                return -1;
        }
    } else {
        if (virCapabilitiesAddGuestDomain(guest,
                                          "kvm",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            return -1;
    }
D
Daniel P. Berrange 已提交
281

282 283 284 285 286 287 288
    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 已提交
289 290 291
        }
    }

292
    return 0;
D
Daniel P. Berrange 已提交
293 294
}

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
#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

354 355 356 357
virCapsPtr qemudCapsInit(void) {
    struct utsname utsname;
    virCapsPtr caps;
    int i;
D
Daniel P. Berrange 已提交
358

359 360 361 362 363 364 365
    /* Really, this never fails - look at the man-page. */
    uname (&utsname);

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

366 367 368
    if (qemudCapsInitNUMA(caps) < 0)
        goto no_memory;

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
    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 已提交
387 388
    }

389 390 391 392 393
    return caps;

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

396

397 398 399 400 401
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 };
402
    pid_t child;
403
    int newstdout = -1;
404
    int ret = -1, status;
405 406 407 408 409 410 411 412 413 414 415 416
    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;
417

418 419 420 421 422
    char *help = NULL;
    enum { MAX_HELP_OUTPUT_SIZE = 8192 };
    int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
    if (len < 0)
        goto cleanup2;
423

424 425 426
    if (sscanf(help, "QEMU PC emulator version %u.%u.%u",
               &major, &minor, &micro) != 3) {
        goto cleanup2;
427 428
    }

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

431 432 433 434 435 436 437 438 439 440 441 442
    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;
443

444 445 446 447
    if (retversion)
        *retversion = version;
    if (retflags)
        *retflags = flags;
448

449
    ret = 0;
450

451 452
    qemudDebug("Version %d %d %d  Cooked version: %d, with flags ? %d",
               major, minor, micro, version, flags);
453

454
cleanup2:
455
    VIR_FREE(help);
456 457
    if (close(newstdout) < 0)
        ret = -1;
458

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
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));
476
    }
477 478

    return ret;
479 480
}

481
int qemudExtractVersion(virConnectPtr conn,
482 483
                        struct qemud_driver *driver) {
    const char *binary;
484
    struct stat sb;
485

486
    if (driver->qemuVersion > 0)
487 488
        return 0;

489 490
    if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
                                                      "hvm",
491 492 493
                                                      "i686",
                                                      "qemu")) == NULL)
        return -1;
494

495 496 497 498 499
    if (stat(binary, &sb) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Cannot find QEMU binary %s: %s"), binary,
                         strerror(errno));
        return -1;
500 501
    }

502
    if (qemudExtractVersionInfo(binary, &driver->qemuVersion, NULL) < 0) {
503 504
        return -1;
    }
D
Daniel P. Berrange 已提交
505

506
    return 0;
D
Daniel P. Berrange 已提交
507 508 509
}


510
static char *
511 512
qemudNetworkIfaceConnect(virConnectPtr conn,
                         struct qemud_driver *driver,
513 514 515
                         int **tapfds,
                         int *ntapfds,
                         virDomainNetDefPtr net,
516
                         int vlan)
517
{
518
    virNetworkObjPtr network = NULL;
519
    char *brname;
520 521 522 523 524
    char tapfdstr[4+3+32+7];
    char *retval = NULL;
    int err;
    int tapfd = -1;

525 526
    if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
        if (!(network = virNetworkFindByName(driver->networks, net->data.network.name))) {
527
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
528
                             _("Network '%s' not found"),
529
                             net->data.network.name);
530
            goto error;
531
        } else if (network->def->bridge == NULL) {
532
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
533
                             _("Network '%s' not active"),
534
                             net->data.network.name);
535 536
            goto error;
        }
537
        brname = network->def->bridge;
538 539
    } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
        brname = net->data.bridge.brname;
540
    } else {
541
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
542
                         _("Network type %d is not supported"), net->type);
543 544 545
        goto error;
    }

546 547 548 549 550 551 552 553 554 555
    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;
        }
    }

556
    if (!driver->brctl && (err = brInit(&driver->brctl))) {
557
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
558 559
                         _("cannot initialize bridge support: %s"),
                         strerror(err));
560 561 562
        goto error;
    }

563
    if ((err = brAddTap(driver->brctl, brname,
564
                        &net->ifname, &tapfd))) {
565 566 567 568 569 570 571 572 573
        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"),
574
                             net->ifname, brname, strerror(err));
575
        }
576 577 578
        goto error;
    }

579 580
    snprintf(tapfdstr, sizeof(tapfdstr),
             "tap,fd=%d,script=,vlan=%d,ifname=%s",
581
             tapfd, vlan, net->ifname);
582 583 584 585

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

586
    if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0)
587 588
        goto no_memory;

589
    (*tapfds)[(*ntapfds)++] = tapfd;
590 591 592 593

    return retval;

 no_memory:
594 595
    qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
                     "%s", _("failed to allocate space for tapfds string"));
596
 error:
597
    VIR_FREE(retval);
598 599 600 601 602
    if (tapfd != -1)
        close(tapfd);
    return NULL;
}

603
static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
604 605 606
                                          char *buf,
                                          int buflen)
{
607 608
    switch (dev->type) {
    case VIR_DOMAIN_CHR_TYPE_NULL:
609 610 611 612
        strncpy(buf, "null", buflen);
        buf[buflen-1] = '\0';
        break;

613
    case VIR_DOMAIN_CHR_TYPE_VC:
614 615 616 617
        strncpy(buf, "vc", buflen);
        buf[buflen-1] = '\0';
        break;

618
    case VIR_DOMAIN_CHR_TYPE_PTY:
619 620 621 622
        strncpy(buf, "pty", buflen);
        buf[buflen-1] = '\0';
        break;

623
    case VIR_DOMAIN_CHR_TYPE_DEV:
624
        if (snprintf(buf, buflen, "%s",
625
                     dev->data.file.path) >= buflen)
626 627 628
            return -1;
        break;

629
    case VIR_DOMAIN_CHR_TYPE_FILE:
630
        if (snprintf(buf, buflen, "file:%s",
631
                     dev->data.file.path) >= buflen)
632 633 634
            return -1;
        break;

635
    case VIR_DOMAIN_CHR_TYPE_PIPE:
636
        if (snprintf(buf, buflen, "pipe:%s",
637
                     dev->data.file.path) >= buflen)
638 639 640
            return -1;
        break;

641
    case VIR_DOMAIN_CHR_TYPE_STDIO:
642 643 644 645
        strncpy(buf, "stdio", buflen);
        buf[buflen-1] = '\0';
        break;

646
    case VIR_DOMAIN_CHR_TYPE_UDP:
647
        if (snprintf(buf, buflen, "udp:%s:%s@%s:%s",
648 649 650 651
                     dev->data.udp.connectHost,
                     dev->data.udp.connectService,
                     dev->data.udp.bindHost,
                     dev->data.udp.bindService) >= buflen)
652 653 654
            return -1;
        break;

655
    case VIR_DOMAIN_CHR_TYPE_TCP:
656 657 658 659 660 661 662 663 664 665 666 667 668
        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;
        }
669 670
        break;

671
    case VIR_DOMAIN_CHR_TYPE_UNIX:
672
        if (snprintf(buf, buflen, "unix:%s%s",
673 674
                     dev->data.nix.path,
                     dev->data.nix.listen ? ",listen" : "") >= buflen)
675 676 677 678 679 680 681
            return -1;
        break;
    }

    return 0;
}

D
Daniel P. Berrange 已提交
682 683 684 685
/*
 * Constructs a argv suitable for launching qemu with config defined
 * for a given virtual machine.
 */
686 687
int qemudBuildCommandLine(virConnectPtr conn,
                          struct qemud_driver *driver,
688
                          virDomainObjPtr vm,
689
                          unsigned int qemuCmdFlags,
690
                          const char ***retargv,
691 692 693
                          int **tapfds,
                          int *ntapfds,
                          const char *migrateFrom) {
694
    int i;
D
Daniel P. Berrange 已提交
695 696
    char memory[50];
    char vcpus[50];
697 698 699 700 701
    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;
702
    virDomainHostdevDefPtr hostdev = vm->def->hostdevs;
703 704
    virDomainChrDefPtr serial = vm->def->serials;
    virDomainChrDefPtr parallel = vm->def->parallels;
705 706
    struct utsname ut;
    int disableKQEMU = 0;
707
    int qargc = 0, qarga = 0;
708
    const char **qargv = NULL;
D
Daniel P. Berrange 已提交
709

710 711
    uname(&ut);

D
Daniel P. Berrange 已提交
712
    /* Nasty hack make i?86 look like i686 to simplify next comparison */
713 714 715 716
    if (ut.machine[0] == 'i' &&
        ut.machine[2] == '8' &&
        ut.machine[3] == '6' &&
        !ut.machine[4])
D
Daniel P. Berrange 已提交
717
        ut.machine[1] = '6';
718 719 720 721 722 723

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

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
#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 已提交
750

751 752 753 754
#define ADD_USBDISK(thisarg)                                            \
    do {                                                                \
        ADD_ARG_LIT("-usbdevice");                                      \
        ADD_ARG_SPACE;                                                  \
755
        if ((asprintf((char **)&(qargv[qargc++]), "disk:%s", thisarg)) == -1) {    \
756 757 758 759 760
            qargv[qargc-1] = NULL;                                      \
            goto no_memory;                                             \
        }                                                               \
    } while (0)

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

764

765
    ADD_ARG_LIT(vm->def->emulator);
766 767 768 769 770 771 772 773 774
    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 已提交
775

776
    if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
777 778
        ADD_ARG_LIT("-name");
        ADD_ARG_LIT(vm->def->name);
779
    }
780 781 782 783 784 785 786
    /*
     * 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...
     */
787
    if (!vm->def->graphics)
788
        ADD_ARG_LIT("-nographic");
789

790 791
    ADD_ARG_LIT("-monitor");
    ADD_ARG_LIT("pty");
D
Daniel P. Berrange 已提交
792

793 794
    if (vm->def->localtime)
        ADD_ARG_LIT("-localtime");
795

796 797
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
        vm->def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
798
        ADD_ARG_LIT("-no-reboot");
D
Daniel P. Berrange 已提交
799

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

803
    if (!vm->def->os.bootloader) {
D
Daniel P. Berrange 已提交
804 805
        for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
            switch (vm->def->os.bootDevs[i]) {
806
            case VIR_DOMAIN_BOOT_CDROM:
D
Daniel P. Berrange 已提交
807 808
                boot[i] = 'd';
                break;
809
            case VIR_DOMAIN_BOOT_FLOPPY:
D
Daniel P. Berrange 已提交
810 811
                boot[i] = 'a';
                break;
812
            case VIR_DOMAIN_BOOT_DISK:
D
Daniel P. Berrange 已提交
813 814
                boot[i] = 'c';
                break;
815
            case VIR_DOMAIN_BOOT_NET:
D
Daniel P. Berrange 已提交
816 817 818 819 820 821 822 823
                boot[i] = 'n';
                break;
            default:
                boot[i] = 'c';
                break;
            }
        }
        boot[vm->def->os.nBootDevs] = '\0';
824 825
        ADD_ARG_LIT("-boot");
        ADD_ARG_LIT(boot);
D
Daniel P. Berrange 已提交
826

827
        if (vm->def->os.kernel) {
828 829
            ADD_ARG_LIT("-kernel");
            ADD_ARG_LIT(vm->def->os.kernel);
D
Daniel P. Berrange 已提交
830
        }
831
        if (vm->def->os.initrd) {
832 833
            ADD_ARG_LIT("-initrd");
            ADD_ARG_LIT(vm->def->os.initrd);
D
Daniel P. Berrange 已提交
834
        }
835
        if (vm->def->os.cmdline) {
836 837
            ADD_ARG_LIT("-append");
            ADD_ARG_LIT(vm->def->os.cmdline);
D
Daniel P. Berrange 已提交
838 839
        }
    } else {
840 841
        ADD_ARG_LIT("-bootloader");
        ADD_ARG_LIT(vm->def->os.bootloader);
D
Daniel P. Berrange 已提交
842 843
    }

844
    /* If QEMU supports -drive param instead of old -hda, -hdb, -cdrom .. */
845
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
846 847 848
        int bootCD = 0, bootFloppy = 0, bootDisk = 0;

        /* If QEMU supports boot=on for -drive param... */
849
        if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
850 851
            for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
                switch (vm->def->os.bootDevs[i]) {
852
                case VIR_DOMAIN_BOOT_CDROM:
853 854
                    bootCD = 1;
                    break;
855
                case VIR_DOMAIN_BOOT_FLOPPY:
856 857
                    bootFloppy = 1;
                    break;
858
                case VIR_DOMAIN_BOOT_DISK:
859 860 861
                    bootDisk = 1;
                    break;
                }
862
            }
863
        }
D
Daniel P. Berrange 已提交
864

865 866 867 868 869
        while (disk) {
            char opt[PATH_MAX];
            const char *media = NULL;
            int bootable = 0;
            int idx = virDiskNameToIndex(disk->dst);
870
            const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
D
Daniel P. Berrange 已提交
871

872 873 874 875 876 877 878 879 880 881 882 883
            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;
            }

884 885 886 887 888 889 890
            if (idx < 0) {
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 _("unsupported disk type '%s'"), disk->dst);
                goto error;
            }

            switch (disk->device) {
891
            case VIR_DOMAIN_DISK_DEVICE_CDROM:
892 893
                bootable = bootCD;
                bootCD = 0;
894
                media = "media=cdrom,";
895
                break;
896
            case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
897 898 899
                bootable = bootFloppy;
                bootFloppy = 0;
                break;
900
            case VIR_DOMAIN_DISK_DEVICE_DISK:
901 902 903 904 905 906
                bootable = bootDisk;
                bootDisk = 0;
                break;
            }

            snprintf(opt, PATH_MAX, "file=%s,if=%s,%sindex=%d%s",
907
                     disk->src ? disk->src : "", bus,
908 909
                     media ? media : "",
                     idx,
910 911
                     bootable &&
                     disk->device == VIR_DOMAIN_DISK_DEVICE_DISK
912
                     ? ",boot=on" : "");
913

914 915
            ADD_ARG_LIT("-drive");
            ADD_ARG_LIT(opt);
916 917 918 919 920 921 922
            disk = disk->next;
        }
    } else {
        while (disk) {
            char dev[NAME_MAX];
            char file[PATH_MAX];

923 924 925 926 927 928 929 930 931 932 933 934
            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;
            }

935
            if (STREQ(disk->dst, "hdc") &&
936 937
                disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
                if (disk->src) {
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955
                    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);

956 957
            ADD_ARG_LIT(dev);
            ADD_ARG_LIT(file);
958 959 960

            disk = disk->next;
        }
D
Daniel P. Berrange 已提交
961 962 963
    }

    if (!net) {
964 965
        ADD_ARG_LIT("-net");
        ADD_ARG_LIT("none");
D
Daniel P. Berrange 已提交
966
    } else {
967
        int vlan = 0;
D
Daniel P. Berrange 已提交
968
        while (net) {
969
            char nic[100];
970

971 972
            if (snprintf(nic, sizeof(nic),
                         "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s%s",
973 974 975
                         net->mac[0], net->mac[1],
                         net->mac[2], net->mac[3],
                         net->mac[4], net->mac[5],
976
                         vlan,
977 978
                         (net->model ? ",model=" : ""),
                         (net->model ? net->model : "")) >= sizeof(nic))
979
                goto error;
D
Daniel P. Berrange 已提交
980

981 982 983
            ADD_ARG_LIT("-net");
            ADD_ARG_LIT(nic);
            ADD_ARG_LIT("-net");
984

985
            switch (net->type) {
986 987
            case VIR_DOMAIN_NET_TYPE_NETWORK:
            case VIR_DOMAIN_NET_TYPE_BRIDGE:
988
                {
989 990 991
                    char *tap = qemudNetworkIfaceConnect(conn, driver,
                                                         tapfds, ntapfds,
                                                         net, vlan);
992 993 994 995 996
                    if (tap == NULL)
                        goto error;
                    ADD_ARG(tap);
                    break;
                }
997

998
            case VIR_DOMAIN_NET_TYPE_ETHERNET:
999 1000 1001
                {
                    char arg[PATH_MAX];
                    if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d",
1002 1003
                                 net->ifname,
                                 net->data.ethernet.script,
1004 1005 1006
                                 vlan) >= (PATH_MAX-1))
                        goto error;

1007
                    ADD_ARG_LIT(arg);
1008 1009 1010
                }
                break;

1011 1012 1013
            case VIR_DOMAIN_NET_TYPE_CLIENT:
            case VIR_DOMAIN_NET_TYPE_SERVER:
            case VIR_DOMAIN_NET_TYPE_MCAST:
1014 1015 1016 1017
                {
                    char arg[PATH_MAX];
                    const char *mode = NULL;
                    switch (net->type) {
1018
                    case VIR_DOMAIN_NET_TYPE_CLIENT:
1019 1020
                        mode = "connect";
                        break;
1021
                    case VIR_DOMAIN_NET_TYPE_SERVER:
1022 1023
                        mode = "listen";
                        break;
1024
                    case VIR_DOMAIN_NET_TYPE_MCAST:
1025 1026 1027 1028 1029
                        mode = "mcast";
                        break;
                    }
                    if (snprintf(arg, PATH_MAX-1, "socket,%s=%s:%d,vlan=%d",
                                 mode,
1030 1031
                                 net->data.socket.address,
                                 net->data.socket.port,
1032 1033 1034
                                 vlan) >= (PATH_MAX-1))
                        goto error;

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

1039
            case VIR_DOMAIN_NET_TYPE_USER:
1040 1041 1042 1043 1044 1045
            default:
                {
                    char arg[PATH_MAX];
                    if (snprintf(arg, PATH_MAX-1, "user,vlan=%d", vlan) >= (PATH_MAX-1))
                        goto error;

1046
                    ADD_ARG_LIT(arg);
1047
                }
1048
            }
D
Daniel P. Berrange 已提交
1049 1050

            net = net->next;
1051
            vlan++;
D
Daniel P. Berrange 已提交
1052 1053 1054
        }
    }

1055
    if (!serial) {
1056 1057
        ADD_ARG_LIT("-serial");
        ADD_ARG_LIT("none");
1058 1059 1060 1061 1062 1063 1064
    } else {
        while (serial) {
            char buf[4096];

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

1065 1066
            ADD_ARG_LIT("-serial");
            ADD_ARG_LIT(buf);
1067 1068 1069 1070 1071 1072

            serial = serial->next;
        }
    }

    if (!parallel) {
1073 1074
        ADD_ARG_LIT("-parallel");
        ADD_ARG_LIT("none");
1075 1076 1077 1078 1079 1080 1081
    } else {
        while (parallel) {
            char buf[4096];

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

1082 1083
            ADD_ARG_LIT("-parallel");
            ADD_ARG_LIT(buf);
1084 1085 1086 1087 1088

            parallel = parallel->next;
        }
    }

1089
    ADD_ARG_LIT("-usb");
1090
    while (input) {
1091
        if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
1092
            ADD_ARG_LIT("-usbdevice");
1093
            ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
1094 1095 1096 1097 1098
        }

        input = input->next;
    }

1099 1100
    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
D
Daniel P. Berrange 已提交
1101
        char vncdisplay[PATH_MAX];
1102
        int ret;
D
Daniel P. Berrange 已提交
1103

1104
        if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
D
Daniel P. Berrange 已提交
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
            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 已提交
1118 1119 1120
                           (vm->def->graphics->data.vnc.listenAddr ?
                            vm->def->graphics->data.vnc.listenAddr :
                            (driver->vncListen ? driver->vncListen : "")),
1121
                           vm->def->graphics->data.vnc.port - 5900,
D
Daniel P. Berrange 已提交
1122 1123
                           options);
        } else {
1124
            ret = snprintf(vncdisplay, sizeof(vncdisplay), "%d",
1125
                           vm->def->graphics->data.vnc.port - 5900);
D
Daniel P. Berrange 已提交
1126
        }
1127
        if (ret < 0 || ret >= (int)sizeof(vncdisplay))
1128 1129
            goto error;

1130 1131
        ADD_ARG_LIT("-vnc");
        ADD_ARG_LIT(vncdisplay);
1132
        if (vm->def->graphics->data.vnc.keymap) {
1133
            ADD_ARG_LIT("-k");
1134
            ADD_ARG_LIT(vm->def->graphics->data.vnc.keymap);
1135
        }
1136 1137
    } else if (vm->def->graphics &&
               vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
D
Daniel P. Berrange 已提交
1138 1139 1140
        /* SDL is the default. no args needed */
    }

D
Daniel Veillard 已提交
1141 1142 1143
    /* Add sound hardware */
    if (sound) {
        int size = 100;
1144 1145
        char *modstr;
        if (VIR_ALLOC_N(modstr, size+1) < 0)
D
Daniel Veillard 已提交
1146 1147 1148
            goto no_memory;

        while(sound && size > 0) {
1149
            const char *model = virDomainSoundModelTypeToString(sound->model);
D
Daniel Veillard 已提交
1150
            if (!model) {
1151
                VIR_FREE(modstr);
1152 1153 1154
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("invalid sound model"));
                goto error;
D
Daniel Veillard 已提交
1155 1156 1157 1158 1159 1160 1161
            }
            strncat(modstr, model, size);
            size -= strlen(model);
            sound = sound->next;
            if (sound)
               strncat(modstr, ",", size--);
        }
1162 1163
        ADD_ARG_LIT("-soundhw");
        ADD_ARG(modstr);
D
Daniel Veillard 已提交
1164 1165
    }

1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
    /* 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;
    }

1194
    if (migrateFrom) {
1195
        ADD_ARG_LIT("-incoming");
1196
        ADD_ARG_LIT(migrateFrom);
1197 1198
    }

1199
    ADD_ARG(NULL);
D
Daniel P. Berrange 已提交
1200

1201
    *retargv = qargv;
D
Daniel P. Berrange 已提交
1202 1203 1204
    return 0;

 no_memory:
1205 1206
    qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
                     "%s", _("failed to allocate space for argv string"));
1207
 error:
1208 1209 1210 1211 1212 1213
    if (tapfds &&
        *tapfds) {
        for (i = 0; ntapfds; i++)
            close((*tapfds)[i]);
        VIR_FREE(*tapfds);
        *ntapfds = 0;
1214
    }
1215 1216
    if (qargv) {
        for (i = 0 ; i < qargc ; i++)
1217 1218
            VIR_FREE((qargv)[i]);
        VIR_FREE(qargv);
D
Daniel P. Berrange 已提交
1219 1220
    }
    return -1;
1221 1222 1223 1224

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