* src/qemu/qemu_conf.c (qemudExtractVersionInfo): Check for file
before executing it here, rather than in callers.
(qemudBuildCommandLine): Rewrite with virCommand.
* src/qemu/qemu_conf.h (qemudBuildCommandLine): Update signature.
* src/qemu/qemu_driver.c (qemuAssignPCIAddresses)
(qemudStartVMDaemon, qemuDomainXMLToNative): Adjust callers.
---
v2: new patch, taking most of the ideas from
https://www.redhat.com/archives/libvir-list/2010-November/msg00979.html
but making it better by using virCommand improvements
src/qemu/qemu_conf.c | 710 ++++++++++++++++++----------------------------
src/qemu/qemu_conf.h | 10 +-
src/qemu/qemu_driver.c | 190 +++----------
tests/qemuxml2argvtest.c | 68 +----
4 files changed, 338 insertions(+), 640 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 35caccc..7c0db15 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1530,6 +1530,15 @@ int qemudExtractVersionInfo(const char *qemu,
if (retversion)
*retversion = 0;
+ /* Make sure the binary we are about to try exec'ing exists.
+ * Technically we could catch the exec() failure, but that's
+ * in a sub-process so it's hard to feed back a useful error.
+ */
+ if (access(qemu, X_OK) < 0) {
+ virReportSystemError(errno, _("Cannot find QEMU binary %s"), qemu);
+ return -1;
+ }
+
if (virExec(qemuarg, qemuenv, NULL,
&child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
return -1;
@@ -3942,43 +3951,35 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
* XXX 'conn' is only required to resolve network -> bridge name
* figure out how to remove this requirement some day
*/
-int qemudBuildCommandLine(virConnectPtr conn,
- struct qemud_driver *driver,
- virDomainDefPtr def,
- virDomainChrDefPtr monitor_chr,
- int monitor_json,
- unsigned long long qemuCmdFlags,
- const char ***retargv,
- const char ***retenv,
- int **vmfds,
- int *nvmfds,
- const char *migrateFrom,
- virDomainSnapshotObjPtr current_snapshot)
+virCommandPtr
+qemudBuildCommandLine(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainDefPtr def,
+ virDomainChrDefPtr monitor_chr,
+ bool monitor_json,
+ unsigned long long qemuCmdFlags,
+ const char *migrateFrom,
+ virDomainSnapshotObjPtr current_snapshot)
{
int i;
- char memory[50];
char boot[VIR_DOMAIN_BOOT_LAST+1];
struct utsname ut;
int disableKQEMU = 0;
int enableKQEMU = 0;
int disableKVM = 0;
int enableKVM = 0;
- int qargc = 0, qarga = 0;
- const char **qargv = NULL;
- int qenvc = 0, qenva = 0;
- const char **qenv = NULL;
const char *emulator;
char uuid[VIR_UUID_STRING_BUFLEN];
- char domid[50];
char *cpu;
char *smp;
int last_good_net = -1;
bool hasHwVirt = false;
+ virCommandPtr cmd;
uname_normalize(&ut);
if (qemuAssignDeviceAliases(def, qemuCmdFlags) < 0)
- return -1;
+ return NULL;
virUUIDFormat(def->uuid, uuid);
@@ -3990,7 +3991,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("TCP migration is not supported
with this QEMU binary"));
- return -1;
+ return NULL;
}
} else if (STREQ(migrateFrom, "stdio")) {
if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) {
@@ -3998,13 +3999,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
} else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("STDIO migration is not supported
with this QEMU binary"));
- return -1;
+ return NULL;
}
} else if (STRPREFIX(migrateFrom, "exec")) {
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("STDIO migration is not supported
with this QEMU binary"));
- return -1;
+ return NULL;
}
}
}
@@ -4065,134 +4066,45 @@ int qemudBuildCommandLine(virConnectPtr conn,
break;
}
-#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)
-
-#define ADD_USBDISK(thisarg) \
- do { \
- ADD_ARG_LIT("-usbdevice"); \
- ADD_ARG_SPACE; \
- if ((virAsprintf((char **)&(qargv[qargc++]), \
- "disk:%s", thisarg)) == -1) { \
- goto no_memory; \
- } \
- } while (0)
-
-#define ADD_ENV_SPACE \
- do { \
- if (qenvc == qenva) { \
- qenva += 10; \
- if (VIR_REALLOC_N(qenv, qenva) < 0) \
- goto no_memory; \
- } \
- } while (0)
-
-#define ADD_ENV(thisarg) \
- do { \
- ADD_ENV_SPACE; \
- qenv[qenvc++] = thisarg; \
- } while (0)
-
-#define ADD_ENV_LIT(thisarg) \
- do { \
- ADD_ENV_SPACE; \
- if ((qenv[qenvc++] = strdup(thisarg)) == NULL) \
- goto no_memory; \
- } while (0)
-
-#define ADD_ENV_PAIR(envname, val) \
- do { \
- char *envval; \
- ADD_ENV_SPACE; \
- if (virAsprintf(&envval, "%s=%s", envname, val) < 0)
\
- goto no_memory; \
- qenv[qenvc++] = envval; \
- } while (0)
-
- /* Make sure to unset or set all envvars in qemuxml2argvtest.c that
- * are copied here using this macro, otherwise the test may fail */
-#define ADD_ENV_COPY(envname) \
- do { \
- char *val = getenv(envname); \
- if (val != NULL) { \
- ADD_ENV_PAIR(envname, val); \
- } \
- } while (0)
+ cmd = virCommandNewArgList(emulator, "-S", NULL);
- /* Set '-m MB' based on maxmem, because the lower 'memory' limit
- * is set post-startup using the balloon driver. If balloon driver
- * is not supported, then they're out of luck anyway
- */
- snprintf(memory, sizeof(memory), "%lu", def->mem.max_balloon/1024);
- snprintf(domid, sizeof(domid), "%d", def->id);
-
- ADD_ENV_LIT("LC_ALL=C");
-
- ADD_ENV_COPY("LD_PRELOAD");
- ADD_ENV_COPY("LD_LIBRARY_PATH");
- ADD_ENV_COPY("PATH");
- ADD_ENV_COPY("HOME");
- ADD_ENV_COPY("USER");
- ADD_ENV_COPY("LOGNAME");
- ADD_ENV_COPY("TMPDIR");
-
- ADD_ARG_LIT(emulator);
- ADD_ARG_LIT("-S");
+ virCommandAddEnvPassCommon(cmd);
/* This should *never* be NULL, since we always provide
* a machine in the capabilities data for QEMU. So this
* check is just here as a safety in case the unexpected
* happens */
- if (def->os.machine) {
- ADD_ARG_LIT("-M");
- ADD_ARG_LIT(def->os.machine);
- }
+ if (def->os.machine)
+ virCommandAddArgList(cmd, "-M", def->os.machine, NULL);
if (qemuBuildCpuArgStr(driver, def, emulator, qemuCmdFlags,
&ut, &cpu, &hasHwVirt) < 0)
goto error;
if (cpu) {
- ADD_ARG_LIT("-cpu");
- ADD_ARG_LIT(cpu);
+ virCommandAddArgList(cmd, "-cpu", cpu, NULL);
VIR_FREE(cpu);
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NESTING) &&
hasHwVirt)
- ADD_ARG_LIT("-enable-nesting");
+ virCommandAddArg(cmd, "-enable-nesting");
}
if (disableKQEMU)
- ADD_ARG_LIT("-no-kqemu");
- else if (enableKQEMU) {
- ADD_ARG_LIT("-enable-kqemu");
- ADD_ARG_LIT("-kernel-kqemu");
- }
+ virCommandAddArg(cmd, "-no-kqemu");
+ else if (enableKQEMU)
+ virCommandAddArgList(cmd, "-enable-kqemu", "-kernel-kqemu",
NULL);
if (disableKVM)
- ADD_ARG_LIT("-no-kvm");
+ virCommandAddArg(cmd, "-no-kvm");
if (enableKVM)
- ADD_ARG_LIT("-enable-kvm");
- ADD_ARG_LIT("-m");
- ADD_ARG_LIT(memory);
+ virCommandAddArg(cmd, "-enable-kvm");
+
+ /* Set '-m MB' based on maxmem, because the lower 'memory' limit
+ * is set post-startup using the balloon driver. If balloon driver
+ * is not supported, then they're out of luck anyway
+ */
+ virCommandAddArg(cmd, "-m");
+ virCommandAddArgFormat(cmd, "%lu", def->mem.max_balloon / 1024);
if (def->mem.hugepage_backed) {
if (!driver->hugetlbfs_mount) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -4210,43 +4122,38 @@ int qemudBuildCommandLine(virConnectPtr conn,
def->emulator);
goto error;
}
- ADD_ARG_LIT("-mem-prealloc");
- ADD_ARG_LIT("-mem-path");
- ADD_ARG_LIT(driver->hugepage_path);
+ virCommandAddArgList(cmd, "-mem-prealloc", "-mem-path",
+ driver->hugepage_path, NULL);
}
- ADD_ARG_LIT("-smp");
+ virCommandAddArg(cmd, "-smp");
if (!(smp = qemuBuildSmpArgStr(def, qemuCmdFlags)))
goto error;
- ADD_ARG(smp);
+ virCommandAddArg(cmd, smp);
+ VIR_FREE(smp);
if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
- ADD_ARG_LIT("-name");
+ virCommandAddArg(cmd, "-name");
if (driver->setProcessName &&
(qemuCmdFlags & QEMUD_CMD_FLAG_NAME_PROCESS)) {
- char *name;
- if (virAsprintf(&name, "%s,process=qemu:%s",
- def->name, def->name) < 0)
- goto no_memory;
- ADD_ARG_LIT(name);
+ virCommandAddArgFormat(cmd, "%s,process=qemu:%s",
+ def->name, def->name);
} else {
- ADD_ARG_LIT(def->name);
+ virCommandAddArg(cmd, def->name);
}
}
- if (qemuCmdFlags & QEMUD_CMD_FLAG_UUID) {
- ADD_ARG_LIT("-uuid");
- ADD_ARG_LIT(uuid);
- }
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_UUID)
+ virCommandAddArgList(cmd, "-uuid", uuid, NULL);
if (def->virtType == VIR_DOMAIN_VIRT_XEN ||
STREQ(def->os.type, "xen") ||
STREQ(def->os.type, "linux")) {
if (qemuCmdFlags & QEMUD_CMD_FLAG_DOMID) {
- ADD_ARG_LIT("-domid");
- ADD_ARG_LIT(domid);
+ virCommandAddArg(cmd, "-domid");
+ virCommandAddArgFormat(cmd, "%d", def->id);
} else if (qemuCmdFlags & QEMUD_CMD_FLAG_XEN_DOMID) {
- ADD_ARG_LIT("-xen-attach");
- ADD_ARG_LIT("-xen-domid");
- ADD_ARG_LIT(domid);
+ virCommandAddArg(cmd, "-xen-attach");
+ virCommandAddArg(cmd, "-xen-domid");
+ virCommandAddArgFormat(cmd, "%d", def->id);
} else {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("qemu emulator '%s' does not support
xen"),
@@ -4288,13 +4195,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
smbioscmd = qemuBuildSmbiosBiosStr(source);
if (smbioscmd != NULL) {
- ADD_ARG_LIT("-smbios");
- ADD_ARG(smbioscmd);
+ virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
+ VIR_FREE(smbioscmd);
}
smbioscmd = qemuBuildSmbiosSystemStr(source);
if (smbioscmd != NULL) {
- ADD_ARG_LIT("-smbios");
- ADD_ARG(smbioscmd);
+ virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
+ VIR_FREE(smbioscmd);
}
}
}
@@ -4307,12 +4214,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
* these defaults ourselves...
*/
if (!def->graphics)
- ADD_ARG_LIT("-nographic");
+ virCommandAddArg(cmd, "-nographic");
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
if (qemuCmdFlags & QEMUD_CMD_FLAG_NODEFCONFIG)
- ADD_ARG_LIT("-nodefconfig"); /* Disabling global config files */
- ADD_ARG_LIT("-nodefaults"); /* Disabling default guest devices */
+ virCommandAddArg(cmd,
+ "-nodefconfig"); /* Disable global config files
*/
+ virCommandAddArg(cmd,
+ "-nodefaults"); /* Disable default guest devices */
}
if (monitor_chr) {
@@ -4320,39 +4229,40 @@ int qemudBuildCommandLine(virConnectPtr conn,
/* Use -chardev if it's available */
if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) {
- ADD_ARG_LIT("-chardev");
+ virCommandAddArg(cmd, "-chardev");
if (!(chrdev = qemuBuildChrChardevStr(monitor_chr)))
goto error;
- ADD_ARG(chrdev);
+ virCommandAddArg(cmd, chrdev);
+ VIR_FREE(chrdev);
- ADD_ARG_LIT("-mon");
- if (monitor_json)
- ADD_ARG_LIT("chardev=monitor,mode=control");
- else
- ADD_ARG_LIT("chardev=monitor,mode=readline");
+ virCommandAddArg(cmd, "-mon");
+ virCommandAddArgFormat(cmd, "chardev=monitor,mode=%s",
+ monitor_json ? "control" :
"readline");
} else {
const char *prefix = NULL;
if (monitor_json)
prefix = "control,";
- ADD_ARG_LIT("-monitor");
+ virCommandAddArg(cmd, "-monitor");
if (!(chrdev = qemuBuildChrArgStr(monitor_chr, prefix)))
goto error;
- ADD_ARG(chrdev);
+ virCommandAddArg(cmd, chrdev);
+ VIR_FREE(chrdev);
}
}
if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC) {
const char *rtcopt;
- ADD_ARG_LIT("-rtc");
+ virCommandAddArg(cmd, "-rtc");
if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
goto error;
- ADD_ARG(rtcopt);
+ virCommandAddArg(cmd, rtcopt);
+ VIR_FREE(rtcopt);
} else {
switch (def->clock.offset) {
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
- ADD_ARG_LIT("-localtime");
+ virCommandAddArg(cmd, "-localtime");
break;
case VIR_DOMAIN_CLOCK_OFFSET_UTC:
@@ -4368,7 +4278,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE &&
def->clock.data.timezone) {
- ADD_ENV_PAIR("TZ", def->clock.data.timezone);
+ virCommandAddEnvPair(cmd, "TZ", def->clock.data.timezone);
}
for (i = 0; i < def->clock.ntimers; i++) {
@@ -4392,7 +4302,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
/* the default - do nothing */
break;
case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
- ADD_ARG_LIT("-rtc-td-hack");
+ virCommandAddArg(cmd, "-rtc-td-hack");
break;
case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
@@ -4421,14 +4331,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
/* delay is the default if we don't have kernel
(-no-kvm-pit), otherwise, the default is catchup. */
if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT)
- ADD_ARG_LIT("-no-kvm-pit-reinjection");
+ virCommandAddArg(cmd, "-no-kvm-pit-reinjection");
break;
case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT) {
/* do nothing - this is default for kvm-pit */
} else if (qemuCmdFlags & QEMUD_CMD_FLAG_TDF) {
/* -tdf switches to 'catchup' with userspace pit. */
- ADD_ARG_LIT("-tdf");
+ virCommandAddArg(cmd, "-tdf");
} else {
/* can't catchup if we have neither pit mode */
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -4457,7 +4367,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_HPET) {
if (def->clock.timers[i]->present == 0)
- ADD_ARG_LIT("-no-hpet");
+ virCommandAddArg(cmd, "-no-hpet");
} else {
/* no hpet timer available. The only possible action
is to raise an error if present="yes" */
@@ -4472,10 +4382,10 @@ int qemudBuildCommandLine(virConnectPtr conn,
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
- ADD_ARG_LIT("-no-reboot");
+ virCommandAddArg(cmd, "-no-reboot");
if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
- ADD_ARG_LIT("-no-acpi");
+ virCommandAddArg(cmd, "-no-acpi");
if (!def->os.bootloader) {
for (i = 0 ; i < def->os.nBootDevs ; i++) {
@@ -4499,7 +4409,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
if (def->os.nBootDevs) {
virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
- ADD_ARG_LIT("-boot");
+ char *bootstr;
+ virCommandAddArg(cmd, "-boot");
boot[def->os.nBootDevs] = '\0';
@@ -4518,24 +4429,19 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto error;
}
- ADD_ARG(virBufferContentAndReset(&boot_buf));
+ bootstr = virBufferContentAndReset(&boot_buf);
+ virCommandAddArg(cmd, bootstr);
+ VIR_FREE(bootstr);
}
- if (def->os.kernel) {
- ADD_ARG_LIT("-kernel");
- ADD_ARG_LIT(def->os.kernel);
- }
- if (def->os.initrd) {
- ADD_ARG_LIT("-initrd");
- ADD_ARG_LIT(def->os.initrd);
- }
- if (def->os.cmdline) {
- ADD_ARG_LIT("-append");
- ADD_ARG_LIT(def->os.cmdline);
- }
+ if (def->os.kernel)
+ virCommandAddArgList(cmd, "-kernel", def->os.kernel, NULL);
+ if (def->os.initrd)
+ virCommandAddArgList(cmd, "-initrd", def->os.initrd, NULL);
+ if (def->os.cmdline)
+ virCommandAddArgList(cmd, "-append", def->os.cmdline, NULL);
} else {
- ADD_ARG_LIT("-bootloader");
- ADD_ARG_LIT(def->os.bootloader);
+ virCommandAddArgList(cmd, "-bootloader", def->os.bootloader, NULL);
}
for (i = 0 ; i < def->ndisks ; i++) {
@@ -4568,13 +4474,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto error;
}
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
char *devstr;
if (!(devstr = qemuBuildControllerDevStr(def->controllers[i])))
goto no_memory;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
}
}
@@ -4610,10 +4517,12 @@ int qemudBuildCommandLine(virConnectPtr conn,
if ((disk->bus == VIR_DOMAIN_DISK_BUS_USB) &&
!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
- ADD_USBDISK(disk->src);
+ virCommandAddArg(cmd, "-usbdevice");
+ virCommandAddArgFormat(cmd, "disk:%s", disk->src);
} else {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("unsupported usb disk type for
'%s'"), disk->src);
+ _("unsupported usb disk type for
'%s'"),
+ disk->src);
goto error;
}
continue;
@@ -4634,10 +4543,10 @@ int qemudBuildCommandLine(virConnectPtr conn,
break;
}
- ADD_ARG_LIT("-drive");
+ virCommandAddArg(cmd, "-drive");
- /* Unfortunately it is nt possible to use
- -device for floppys, or Xen paravirt
+ /* Unfortunately it is not possible to use
+ -device for floppies, or Xen paravirt
devices. Fortunately, those don't need
static PCI addresses, so we don't really
care that we can't use -device */
@@ -4648,24 +4557,23 @@ int qemudBuildCommandLine(virConnectPtr conn,
(withDeviceArg ? qemuCmdFlags :
(qemuCmdFlags &
~QEMUD_CMD_FLAG_DEVICE)))))
goto error;
- ADD_ARG(optstr);
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
if (withDeviceArg) {
if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC) {
- char *fdc;
- ADD_ARG_LIT("-global");
-
- if (virAsprintf(&fdc, "isa-fdc.drive%c=drive-%s",
- disk->info.addr.drive.unit ? 'B' :
'A',
- disk->info.alias) < 0)
- goto no_memory;
- ADD_ARG(fdc);
+ virCommandAddArg(cmd, "-global");
+ virCommandAddArgFormat(cmd, "isa-fdc.drive%c=drive-%s",
+ disk->info.addr.drive.unit
+ ? 'B' : 'A',
+ disk->info.alias);
} else {
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(optstr = qemuBuildDriveDevStr(disk)))
goto error;
- ADD_ARG(optstr);
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
}
}
}
@@ -4677,10 +4585,12 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
- ADD_USBDISK(disk->src);
+ virCommandAddArg(cmd, "-usbdevice");
+ virCommandAddArgFormat(cmd, "disk:%s", disk->src);
} else {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("unsupported usb disk type for
'%s'"), disk->src);
+ _("unsupported usb disk type for
'%s'"),
+ disk->src);
goto error;
}
continue;
@@ -4726,8 +4636,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
snprintf(file, PATH_MAX, "%s", disk->src);
}
- ADD_ARG_LIT(dev);
- ADD_ARG_LIT(file);
+ virCommandAddArgList(cmd, dev, file, NULL);
}
}
@@ -4736,15 +4645,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
char *optstr;
virDomainFSDefPtr fs = def->fss[i];
- ADD_ARG_LIT("-fsdev");
+ virCommandAddArg(cmd, "-fsdev");
if (!(optstr = qemuBuildFSStr(fs, qemuCmdFlags)))
goto error;
- ADD_ARG(optstr);
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(optstr = qemuBuildFSDevStr(fs)))
goto error;
- ADD_ARG(optstr);
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
}
} else {
if (def->nfss) {
@@ -4756,10 +4667,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (!def->nnets) {
/* If we have -device, then we set -nodefault already */
- if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
- ADD_ARG_LIT("-net");
- ADD_ARG_LIT("none");
- }
+ if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
+ virCommandAddArgList(cmd, "-net", "none", NULL);
} else {
for (i = 0 ; i < def->nnets ; i++) {
virDomainNetDefPtr net = def->nets[i];
@@ -4777,21 +4686,16 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
- int tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags);
+ int tapfd = qemudNetworkIfaceConnect(conn, driver, net,
+ qemuCmdFlags);
if (tapfd < 0)
goto error;
- if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
- virDomainConfNWFilterTeardown(net);
- VIR_FORCE_CLOSE(tapfd);
- goto no_memory;
- }
-
last_good_net = i;
+ virCommandTransferFD(cmd, tapfd);
- (*vmfds)[(*nvmfds)++] = tapfd;
-
- if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >=
sizeof(tapfd_name))
+ if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
+ tapfd) >= sizeof(tapfd_name))
goto no_memory;
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
int tapfd = qemudPhysIfaceConnect(conn, driver, net,
@@ -4800,17 +4704,11 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (tapfd < 0)
goto error;
- if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
- virDomainConfNWFilterTeardown(net);
- VIR_FORCE_CLOSE(tapfd);
- goto no_memory;
- }
-
last_good_net = i;
+ virCommandTransferFD(cmd, tapfd);
- (*vmfds)[(*nvmfds)++] = tapfd;
-
- if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >=
sizeof(tapfd_name))
+ if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
+ tapfd) >= sizeof(tapfd_name))
goto no_memory;
}
@@ -4821,14 +4719,10 @@ int qemudBuildCommandLine(virConnectPtr conn,
network device */
int vhostfd = qemudOpenVhostNet(net, qemuCmdFlags);
if (vhostfd >= 0) {
- if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
- VIR_FORCE_CLOSE(vhostfd);
- goto no_memory;
- }
+ virCommandTransferFD(cmd, vhostfd);
- (*vmfds)[(*nvmfds)++] = vhostfd;
- if (snprintf(vhostfd_name, sizeof(vhostfd_name), "%d",
vhostfd)
- >= sizeof(vhostfd_name))
+ if (snprintf(vhostfd_name, sizeof(vhostfd_name), "%d",
+ vhostfd) >= sizeof(vhostfd_name))
goto no_memory;
}
}
@@ -4842,40 +4736,42 @@ int qemudBuildCommandLine(virConnectPtr conn,
*/
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
- ADD_ARG_LIT("-netdev");
+ virCommandAddArg(cmd, "-netdev");
if (!(host = qemuBuildHostNetStr(net, ',', vlan,
tapfd_name, vhostfd_name)))
goto error;
- ADD_ARG(host);
+ virCommandAddArg(cmd, host);
+ VIR_FREE(host);
}
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(nic = qemuBuildNicDevStr(net, vlan)))
goto error;
- ADD_ARG(nic);
+ virCommandAddArg(cmd, nic);
+ VIR_FREE(nic);
} else {
- ADD_ARG_LIT("-net");
+ virCommandAddArg(cmd, "-net");
if (!(nic = qemuBuildNicStr(net, "nic,", vlan)))
goto error;
- ADD_ARG(nic);
+ virCommandAddArg(cmd, nic);
+ VIR_FREE(nic);
}
if (!((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))) {
- ADD_ARG_LIT("-net");
+ virCommandAddArg(cmd, "-net");
if (!(host = qemuBuildHostNetStr(net, ',', vlan,
tapfd_name, vhostfd_name)))
goto error;
- ADD_ARG(host);
+ virCommandAddArg(cmd, host);
+ VIR_FREE(host);
}
}
}
if (!def->nserials) {
/* If we have -device, then we set -nodefault already */
- if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
- ADD_ARG_LIT("-serial");
- ADD_ARG_LIT("none");
- }
+ if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
+ virCommandAddArgList(cmd, "-serial", "none", NULL);
} else {
for (i = 0 ; i < def->nserials ; i++) {
virDomainChrDefPtr serial = def->serials[i];
@@ -4884,30 +4780,29 @@ int qemudBuildCommandLine(virConnectPtr conn,
/* Use -chardev with -device if they are available */
if ((qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) &&
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
- ADD_ARG_LIT("-chardev");
+ virCommandAddArg(cmd, "-chardev");
if (!(devstr = qemuBuildChrChardevStr(serial)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
- ADD_ARG_LIT("-device");
- if (virAsprintf(&devstr, "isa-serial,chardev=%s",
serial->info.alias) < 0)
- goto no_memory;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, "-device");
+ virCommandAddArgFormat(cmd, "isa-serial,chardev=%s",
+ serial->info.alias);
} else {
- ADD_ARG_LIT("-serial");
+ virCommandAddArg(cmd, "-serial");
if (!(devstr = qemuBuildChrArgStr(serial, NULL)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
}
}
}
if (!def->nparallels) {
/* If we have -device, then we set -nodefault already */
- if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
- ADD_ARG_LIT("-parallel");
- ADD_ARG_LIT("none");
- }
+ if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
+ virCommandAddArgList(cmd, "-parallel", "none", NULL);
} else {
for (i = 0 ; i < def->nparallels ; i++) {
virDomainChrDefPtr parallel = def->parallels[i];
@@ -4916,20 +4811,21 @@ int qemudBuildCommandLine(virConnectPtr conn,
/* Use -chardev with -device if they are available */
if ((qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) &&
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
- ADD_ARG_LIT("-chardev");
+ virCommandAddArg(cmd, "-chardev");
if (!(devstr = qemuBuildChrChardevStr(parallel)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
- ADD_ARG_LIT("-device");
- if (virAsprintf(&devstr, "isa-parallel,chardev=%s",
parallel->info.alias) < 0)
- goto no_memory;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, "-device");
+ virCommandAddArgFormat(cmd, "isa-parallel,chardev=%s",
+ parallel->info.alias);
} else {
- ADD_ARG_LIT("-parallel");
+ virCommandAddArg(cmd, "-parallel");
if (!(devstr = qemuBuildChrArgStr(parallel, NULL)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
}
}
}
@@ -4947,24 +4843,23 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto error;
}
- ADD_ARG_LIT("-chardev");
+ virCommandAddArg(cmd, "-chardev");
if (!(devstr = qemuBuildChrChardevStr(channel)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
char *addr = virSocketFormatAddr(channel->target.addr);
if (!addr)
goto error;
int port = virSocketGetPort(channel->target.addr);
- ADD_ARG_LIT("-netdev");
- if (virAsprintf(&devstr,
"user,guestfwd=tcp:%s:%i,chardev=%s,id=user-%s",
- addr, port, channel->info.alias, channel->info.alias)
< 0) {
- VIR_FREE(addr);
- goto no_memory;
- }
+ virCommandAddArg(cmd, "-netdev");
+ virCommandAddArgFormat(cmd,
+
"user,guestfwd=tcp:%s:%i,chardev=%s,id=user-%s",
+ addr, port, channel->info.alias,
+ channel->info.alias);
VIR_FREE(addr);
- ADD_ARG(devstr);
break;
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
@@ -4974,15 +4869,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto error;
}
- ADD_ARG_LIT("-chardev");
+ virCommandAddArg(cmd, "-chardev");
if (!(devstr = qemuBuildChrChardevStr(channel)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(devstr = qemuBuildVirtioSerialPortDevStr(channel)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
break;
}
}
@@ -5000,15 +4897,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto error;
}
- ADD_ARG_LIT("-chardev");
+ virCommandAddArg(cmd, "-chardev");
if (!(devstr = qemuBuildChrChardevStr(console)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(devstr = qemuBuildVirtioSerialPortDevStr(console)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
break;
case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
@@ -5022,20 +4921,22 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
}
- ADD_ARG_LIT("-usb");
+ virCommandAddArg(cmd, "-usb");
for (i = 0 ; i < def->ninputs ; i++) {
virDomainInputDefPtr input = def->inputs[i];
if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
char *optstr;
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(optstr = qemuBuildUSBInputDevStr(input)))
goto error;
- ADD_ARG(optstr);
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
} else {
- ADD_ARG_LIT("-usbdevice");
- ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
"mouse" : "tablet");
+ virCommandAddArgList(cmd, "-usbdevice",
+ input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE
+ ? "mouse" : "tablet", NULL);
}
}
}
@@ -5079,7 +4980,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
virBufferAddLit(&opt, ",sasl");
if (driver->vncSASLdir)
- ADD_ENV_PAIR("SASL_CONF_DIR", driver->vncSASLdir);
+ virCommandAddEnvPair(cmd, "SASL_CONF_DIR",
+ driver->vncSASLdir);
/* TODO: Support ACLs later */
}
@@ -5094,11 +4996,11 @@ int qemudBuildCommandLine(virConnectPtr conn,
optstr = virBufferContentAndReset(&opt);
- ADD_ARG_LIT("-vnc");
- ADD_ARG(optstr);
+ virCommandAddArgList(cmd, "-vnc", optstr, NULL);
+ VIR_FREE(optstr);
if (def->graphics[0]->data.vnc.keymap) {
- ADD_ARG_LIT("-k");
- ADD_ARG_LIT(def->graphics[0]->data.vnc.keymap);
+ virCommandAddArgList(cmd, "-k",
def->graphics[0]->data.vnc.keymap,
+ NULL);
}
/* Unless user requested it, set the audio backend to none, to
@@ -5106,45 +5008,33 @@ int qemudBuildCommandLine(virConnectPtr conn,
* security issues and might not work when using VNC.
*/
if (driver->vncAllowHostAudio) {
- ADD_ENV_COPY("QEMU_AUDIO_DRV");
+ virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
} else {
- ADD_ENV_LIT("QEMU_AUDIO_DRV=none");
+ virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
}
} else if ((def->ngraphics == 1) &&
def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
- char *xauth = NULL;
- char *display = NULL;
-
- if (def->graphics[0]->data.sdl.xauth &&
- virAsprintf(&xauth, "XAUTHORITY=%s",
- def->graphics[0]->data.sdl.xauth) < 0)
- goto no_memory;
- if (def->graphics[0]->data.sdl.display &&
- virAsprintf(&display, "DISPLAY=%s",
- def->graphics[0]->data.sdl.display) < 0) {
- VIR_FREE(xauth);
- goto no_memory;
- }
-
- if (xauth)
- ADD_ENV(xauth);
- if (display)
- ADD_ENV(display);
+ if (def->graphics[0]->data.sdl.xauth)
+ virCommandAddEnvPair(cmd, "XAUTHORITY",
+ def->graphics[0]->data.sdl.xauth);
+ if (def->graphics[0]->data.sdl.display)
+ virCommandAddEnvPair(cmd, "DISPLAY",
+ def->graphics[0]->data.sdl.display);
if (def->graphics[0]->data.sdl.fullscreen)
- ADD_ARG_LIT("-full-screen");
+ virCommandAddArg(cmd, "-full-screen");
/* If using SDL for video, then we should just let it
* use QEMU's host audio drivers, possibly SDL too
* User can set these two before starting libvirtd
*/
- ADD_ENV_COPY("QEMU_AUDIO_DRV");
- ADD_ENV_COPY("SDL_AUDIODRIVER");
+ virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
+ virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");
/* New QEMU has this flag to let us explicitly ask for
* SDL graphics. This is better than relying on the
* default, since the default changes :-( */
if (qemuCmdFlags & QEMUD_CMD_FLAG_SDL)
- ADD_ARG_LIT("-sdl");
+ virCommandAddArg(cmd, "-sdl");
} else if ((def->ngraphics == 1) &&
def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
@@ -5197,16 +5087,15 @@ int qemudBuildCommandLine(virConnectPtr conn,
optstr = virBufferContentAndReset(&opt);
- ADD_ARG_LIT("-spice");
- ADD_ARG(optstr);
- if (def->graphics[0]->data.spice.keymap) {
- ADD_ARG_LIT("-k");
- ADD_ARG_LIT(def->graphics[0]->data.spice.keymap);
- }
+ virCommandAddArgList(cmd, "-spice", optstr, NULL);
+ VIR_FREE(optstr);
+ if (def->graphics[0]->data.spice.keymap)
+ virCommandAddArgList(cmd, "-k",
+ def->graphics[0]->data.spice.keymap, NULL);
/* SPICE includes native support for tunnelling audio, so we
* set the audio backend to point at SPICE's own driver
*/
- ADD_ENV_LIT("QEMU_AUDIO_DRV=spice");
+ virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=spice");
} else if ((def->ngraphics == 1)) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -5235,18 +5124,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto error;
}
- ADD_ARG_LIT("-vga");
- ADD_ARG_LIT(vgastr);
+ virCommandAddArgList(cmd, "-vga", vgastr, NULL);
}
} else {
switch (def->videos[0]->type) {
case VIR_DOMAIN_VIDEO_TYPE_VGA:
- ADD_ARG_LIT("-std-vga");
+ virCommandAddArg(cmd, "-std-vga");
break;
case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
- ADD_ARG_LIT("-vmwarevga");
+ virCommandAddArg(cmd, "-vmwarevga");
break;
case VIR_DOMAIN_VIDEO_TYPE_XEN:
@@ -5273,12 +5161,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto error;
}
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(str = qemuBuildVideoDevStr(def->videos[i])))
goto error;
- ADD_ARG(str);
+ virCommandAddArg(cmd, str);
+ VIR_FREE(str);
}
} else {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -5290,10 +5179,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
} else {
/* If we have -device, then we set -nodefault already */
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
- (qemuCmdFlags & QEMUD_CMD_FLAG_VGA)) {
- ADD_ARG_LIT("-vga");
- ADD_ARG_LIT("none");
- }
+ (qemuCmdFlags & QEMUD_CMD_FLAG_VGA))
+ virCommandAddArgList(cmd, "-vga", "none", NULL);
}
/* Add sound hardware */
@@ -5307,15 +5194,15 @@ int qemudBuildCommandLine(virConnectPtr conn,
* we don't need to set any PCI address on it, so we don't
* mind too much */
if (sound->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) {
- ADD_ARG_LIT("-soundhw");
- ADD_ARG_LIT("pcspk");
+ virCommandAddArgList(cmd, "-soundhw", "pcspk",
NULL);
} else {
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(str = qemuBuildSoundDevStr(sound)))
goto error;
- ADD_ARG(str);
+ virCommandAddArg(cmd, str);
+ VIR_FREE(str);
}
}
} else {
@@ -5338,8 +5225,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (i < (def->nsounds - 1))
strncat(modstr, ",", size--);
}
- ADD_ARG_LIT("-soundhw");
- ADD_ARG(modstr);
+ virCommandAddArgList(cmd, "-soundhw", modstr, NULL);
+ VIR_FREE(modstr);
}
}
@@ -5349,13 +5236,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
char *optstr;
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
optstr = qemuBuildWatchdogDevStr(watchdog);
if (!optstr)
goto error;
} else {
- ADD_ARG_LIT("-watchdog");
+ virCommandAddArg(cmd, "-watchdog");
const char *model = virDomainWatchdogModelTypeToString(watchdog->model);
if (!model) {
@@ -5367,7 +5254,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
if (!(optstr = strdup(model)))
goto no_memory;
}
- ADD_ARG(optstr);
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
const char *action = virDomainWatchdogActionTypeToString(watchdog->action);
if (!action) {
@@ -5375,8 +5263,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
"%s", _("invalid watchdog action"));
goto error;
}
- ADD_ARG_LIT("-watchdog-action");
- ADD_ARG_LIT(action);
+ virCommandAddArgList(cmd, "-watchdog-action", action, NULL);
}
/* Add host passthrough hardware */
@@ -5389,15 +5276,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
} else {
- ADD_ARG_LIT("-usbdevice");
+ virCommandAddArg(cmd, "-usbdevice");
if (!(devstr = qemuBuildUSBHostdevUsbDevStr(hostdev)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
}
}
@@ -5416,26 +5305,22 @@ int qemudBuildCommandLine(virConnectPtr conn,
goto no_memory;
}
- if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
- VIR_FREE(configfd_name);
- VIR_FORCE_CLOSE(configfd);
- goto no_memory;
- }
-
- (*vmfds)[(*nvmfds)++] = configfd;
+ virCommandTransferFD(cmd, configfd);
}
}
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
devstr = qemuBuildPCIHostdevDevStr(hostdev, configfd_name);
VIR_FREE(configfd_name);
if (!devstr)
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
} else if (qemuCmdFlags & QEMUD_CMD_FLAG_PCIDEVICE) {
- ADD_ARG_LIT("-pcidevice");
+ virCommandAddArg(cmd, "-pcidevice");
if (!(devstr = qemuBuildPCIHostdevPCIDevStr(hostdev)))
goto error;
- ADD_ARG(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
} else {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("PCI device assignment is not supported by this
version of qemu"));
@@ -5444,10 +5329,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
}
- if (migrateFrom) {
- ADD_ARG_LIT("-incoming");
- ADD_ARG_LIT(migrateFrom);
- }
+ if (migrateFrom)
+ virCommandAddArgList(cmd, "-incoming", migrateFrom, NULL);
/* QEMU changed its default behavior to not include the virtio balloon
* device. Explicitly request it to ensure it will be present.
@@ -5465,76 +5348,43 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
char *optstr;
- ADD_ARG_LIT("-device");
+ virCommandAddArg(cmd, "-device");
optstr = qemuBuildMemballoonDevStr(def->memballoon);
if (!optstr)
goto error;
- ADD_ARG(optstr);
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
} else if (qemuCmdFlags & QEMUD_CMD_FLAG_BALLOON) {
- ADD_ARG_LIT("-balloon");
- ADD_ARG_LIT("virtio");
+ virCommandAddArgList(cmd, "-balloon", "virtio", NULL);
}
}
- if (current_snapshot && current_snapshot->def->active) {
- ADD_ARG_LIT("-loadvm");
- ADD_ARG_LIT(current_snapshot->def->name);
- }
+ if (current_snapshot && current_snapshot->def->active)
+ virCommandAddArgList(cmd, "-loadvm",
current_snapshot->def->name,
+ NULL);
if (def->namespaceData) {
- qemuDomainCmdlineDefPtr cmd;
-
- cmd = def->namespaceData;
- for (i = 0; i < cmd->num_args; i++)
- ADD_ARG_LIT(cmd->args[i]);
- for (i = 0; i < cmd->num_env; i++) {
- if (cmd->env_value[i])
- ADD_ENV_PAIR(cmd->env_name[i], cmd->env_value[i]);
- else
- ADD_ENV_PAIR(cmd->env_name[i], "");
- }
- }
+ qemuDomainCmdlineDefPtr qemucmd;
- ADD_ARG(NULL);
- ADD_ENV(NULL);
+ qemucmd = def->namespaceData;
+ for (i = 0; i < qemucmd->num_args; i++)
+ virCommandAddArg(cmd, qemucmd->args[i]);
+ for (i = 0; i < qemucmd->num_env; i++)
+ virCommandAddEnvPair(cmd, qemucmd->env_name[i],
+ qemucmd->env_value[i]
+ ? qemucmd->env_value[i] : "");
+ }
- *retargv = qargv;
- *retenv = qenv;
- return 0;
+ return cmd;
no_memory:
virReportOOMError();
error:
for (i = 0; i <= last_good_net; i++)
virDomainConfNWFilterTeardown(def->nets[i]);
- if (vmfds &&
- *vmfds) {
- for (i = 0; i < *nvmfds; i++)
- VIR_FORCE_CLOSE((*vmfds)[i]);
- VIR_FREE(*vmfds);
- *nvmfds = 0;
- }
- if (qargv) {
- for (i = 0 ; i < qargc ; i++)
- VIR_FREE((qargv)[i]);
- VIR_FREE(qargv);
- }
- if (qenv) {
- for (i = 0 ; i < qenvc ; i++)
- VIR_FREE((qenv)[i]);
- VIR_FREE(qenv);
- }
- return -1;
-
-#undef ADD_ARG
-#undef ADD_ARG_LIT
-#undef ADD_ARG_SPACE
-#undef ADD_USBDISK
-#undef ADD_ENV
-#undef ADD_ENV_COPY
-#undef ADD_ENV_LIT
-#undef ADD_ENV_SPACE
+ virCommandFree(cmd);
+ return NULL;
}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 790ce98..24df871 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -25,6 +25,7 @@
# define __QEMUD_CONF_H
# include <config.h>
+# include <stdbool.h>
# include "ebtables.h"
# include "internal.h"
@@ -40,6 +41,7 @@
# include "cpu_conf.h"
# include "driver.h"
# include "bitmap.h"
+# include "command.h"
# define qemudDebug(fmt, ...) do {} while(0)
@@ -227,16 +229,12 @@ int qemudParseHelpStr (const char *qemu,
unsigned int *is_kvm,
unsigned int *kvm_version);
-int qemudBuildCommandLine (virConnectPtr conn,
+virCommandPtr qemudBuildCommandLine (virConnectPtr conn,
struct qemud_driver *driver,
virDomainDefPtr def,
virDomainChrDefPtr monitor_chr,
- int monitor_json,
+ bool monitor_json,
unsigned long long qemuCmdFlags,
- const char ***retargv,
- const char ***retenv,
- int **vmfds,
- int *nvmfds,
const char *migrateFrom,
virDomainSnapshotObjPtr current_snapshot)
ATTRIBUTE_NONNULL(1);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f00d8a3..38d7bd2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3018,14 +3018,6 @@ qemuAssignPCIAddresses(virDomainDefPtr def)
int ret = -1;
unsigned long long qemuCmdFlags = 0;
qemuDomainPCIAddressSetPtr addrs = NULL;
- struct stat sb;
-
- if (stat(def->emulator, &sb) < 0) {
- virReportSystemError(errno,
- _("Cannot find QEMU binary %s"),
- def->emulator);
- goto cleanup;
- }
if (qemudExtractVersionInfo(def->emulator,
NULL,
@@ -3865,30 +3857,21 @@ static int qemudStartVMDaemon(virConnectPtr conn,
bool start_paused,
int stdin_fd,
const char *stdin_path) {
- const char **argv = NULL, **tmp;
- const char **progenv = NULL;
- int i, ret, runflags;
- struct stat sb;
- int *vmfds = NULL;
- int nvmfds = 0;
+ int ret;
unsigned long long qemuCmdFlags;
- fd_set keepfd;
- const char *emulator;
- pid_t child;
int pos = -1;
char ebuf[1024];
char *pidfile = NULL;
int logfile = -1;
char *timestamp;
qemuDomainObjPrivatePtr priv = vm->privateData;
+ virCommandPtr cmd = NULL;
struct qemudHookData hookData;
hookData.conn = conn;
hookData.vm = vm;
hookData.driver = driver;
- FD_ZERO(&keepfd);
-
DEBUG0("Beginning VM startup process");
if (virDomainObjIsActive(vm)) {
@@ -3979,21 +3962,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if ((logfile = qemudLogFD(driver, vm->def->name, false)) < 0)
goto cleanup;
- emulator = vm->def->emulator;
-
- /* Make sure the binary we are about to try exec'ing exists.
- * Technically we could catch the exec() failure, but that's
- * in a sub-process so its hard to feed back a useful error
- */
- if (stat(emulator, &sb) < 0) {
- virReportSystemError(errno,
- _("Cannot find QEMU binary %s"),
- emulator);
- goto cleanup;
- }
-
- DEBUG0("Determing emulator version");
- if (qemudExtractVersionInfo(emulator,
+ DEBUG0("Determining emulator version");
+ if (qemudExtractVersionInfo(vm->def->emulator,
NULL,
&qemuCmdFlags) < 0)
goto cleanup;
@@ -4062,10 +4032,10 @@ static int qemudStartVMDaemon(virConnectPtr conn,
DEBUG0("Building emulator command line");
vm->def->id = driver->nextvmid++;
- if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
- priv->monJSON, qemuCmdFlags, &argv, &progenv,
- &vmfds, &nvmfds, migrateFrom,
- vm->current_snapshot) < 0)
+ if (!(cmd = qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
+ priv->monJSON != 0, qemuCmdFlags,
+ migrateFrom,
+ vm->current_snapshot)))
goto cleanup;
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
@@ -4100,50 +4070,28 @@ static int qemudStartVMDaemon(virConnectPtr conn,
VIR_FREE(timestamp);
}
- tmp = progenv;
-
- while (*tmp) {
- if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
- VIR_WARN("Unable to write envv to logfile: %s",
- virStrerror(errno, ebuf, sizeof ebuf));
- if (safewrite(logfile, " ", 1) < 0)
- VIR_WARN("Unable to write envv to logfile: %s",
- virStrerror(errno, ebuf, sizeof ebuf));
- tmp++;
- }
- tmp = argv;
- while (*tmp) {
- if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
- VIR_WARN("Unable to write argv to logfile: %s",
- virStrerror(errno, ebuf, sizeof ebuf));
- if (safewrite(logfile, " ", 1) < 0)
- VIR_WARN("Unable to write argv to logfile: %s",
- virStrerror(errno, ebuf, sizeof ebuf));
- tmp++;
- }
- if (safewrite(logfile, "\n", 1) < 0)
- VIR_WARN("Unable to write argv to logfile: %s",
- virStrerror(errno, ebuf, sizeof ebuf));
+ virCommandWriteArgLog(cmd, logfile);
if ((pos = lseek(logfile, 0, SEEK_END)) < 0)
VIR_WARN("Unable to seek to end of logfile: %s",
virStrerror(errno, ebuf, sizeof ebuf));
- for (i = 0 ; i < nvmfds ; i++)
- FD_SET(vmfds[i], &keepfd);
-
VIR_DEBUG("Clear emulator capabilities: %d",
driver->clearEmulatorCapabilities);
- runflags = VIR_EXEC_NONBLOCK;
- if (driver->clearEmulatorCapabilities) {
- runflags |= VIR_EXEC_CLEAR_CAPS;
- }
-
- ret = virExecDaemonize(argv, progenv, &keepfd, &child,
- stdin_fd, &logfile, &logfile,
- runflags,
- qemudSecurityHook, &hookData,
- pidfile);
+ if (driver->clearEmulatorCapabilities)
+ virCommandClearCaps(cmd);
+
+ VIR_WARN("Executing %s", vm->def->emulator);
+ virCommandSetPreExecHook(cmd, qemudSecurityHook, &hookData);
+ virCommandSetInputFD(cmd, stdin_fd);
+ virCommandSetOutputFD(cmd, &logfile);
+ virCommandSetErrorFD(cmd, &logfile);
+ virCommandNonblockingFDs(cmd);
+ virCommandSetPidFile(cmd, pidfile);
+ virCommandDaemonize(cmd);
+
+ ret = virCommandRun(cmd, NULL);
+ VIR_WARN("Executing done %s", vm->def->emulator);
VIR_FREE(pidfile);
/* wait for qemu process to to show up */
@@ -4153,7 +4101,13 @@ static int qemudStartVMDaemon(virConnectPtr conn,
_("Domain %s didn't show up\n"),
vm->def->name);
ret = -1;
}
+#if 0
} else if (ret == -2) {
+ /*
+ * XXX this is bogus. It isn't safe to set vm->pid = child
+ * because the child no longer exists.
+ */
+
/* The virExec process that launches the daemon failed. Pending on
* when it failed (we can't determine for sure), there may be
* extra info in the domain log (if the hook failed for example).
@@ -4163,30 +4117,16 @@ static int qemudStartVMDaemon(virConnectPtr conn,
*/
vm->pid = child;
ret = 0;
+#endif
}
if (migrateFrom)
start_paused = true;
vm->state = start_paused ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
- for (i = 0 ; argv[i] ; i++)
- VIR_FREE(argv[i]);
- VIR_FREE(argv);
-
- for (i = 0 ; progenv[i] ; i++)
- VIR_FREE(progenv[i]);
- VIR_FREE(progenv);
-
if (ret == -1) /* The VM failed to start; tear filters before taps */
virDomainConfVMNWFilterTeardown(vm);
- if (vmfds) {
- for (i = 0 ; i < nvmfds ; i++) {
- VIR_FORCE_CLOSE(vmfds[i]);
- }
- VIR_FREE(vmfds);
- }
-
if (ret == -1) /* The VM failed to start */
goto cleanup;
@@ -4240,6 +4180,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (virDomainObjSetDefTransient(driver->caps, vm) < 0)
goto cleanup;
+ virCommandFree(cmd);
VIR_FORCE_CLOSE(logfile);
return 0;
@@ -4248,9 +4189,9 @@ cleanup:
/* We jump here if we failed to start the VM for any reason, or
* if we failed to initialize the now running VM. kill it off and
* pretend we never started it */
- qemudShutdownVMDaemon(driver, vm, 0);
-
+ virCommandFree(cmd);
VIR_FORCE_CLOSE(logfile);
+ qemudShutdownVMDaemon(driver, vm, 0);
return -1;
}
@@ -7312,13 +7253,8 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
struct qemud_driver *driver = conn->privateData;
virDomainDefPtr def = NULL;
virDomainChrDef monConfig;
- const char *emulator;
unsigned long long qemuCmdFlags;
- struct stat sb;
- const char **retargv = NULL;
- const char **retenv = NULL;
- const char **tmp;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
+ virCommandPtr cmd = NULL;
char *ret = NULL;
int i;
@@ -7368,70 +7304,26 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
def->graphics[i]->data.vnc.autoport)
def->graphics[i]->data.vnc.port = 5900;
}
- emulator = def->emulator;
-
- /* Make sure the binary we are about to try exec'ing exists.
- * Technically we could catch the exec() failure, but that's
- * in a sub-process so its hard to feed back a useful error
- */
- if (stat(emulator, &sb) < 0) {
- virReportSystemError(errno,
- _("Cannot find QEMU binary %s"),
- emulator);
- goto cleanup;
- }
- if (qemudExtractVersionInfo(emulator,
+ if (qemudExtractVersionInfo(def->emulator,
NULL,
- &qemuCmdFlags) < 0) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("Cannot determine QEMU argv syntax %s"),
- emulator);
+ &qemuCmdFlags) < 0)
goto cleanup;
- }
if (qemuPrepareMonitorChr(driver, &monConfig, def->name) < 0)
goto cleanup;
- if (qemudBuildCommandLine(conn, driver, def,
- &monConfig, 0, qemuCmdFlags,
- &retargv, &retenv,
- NULL, NULL, /* Don't want it to create TAP devices */
- NULL, NULL) < 0) {
- goto cleanup;
- }
-
- tmp = retenv;
- while (*tmp) {
- virBufferAdd(&buf, *tmp, strlen(*tmp));
- virBufferAddLit(&buf, " ");
- tmp++;
- }
- tmp = retargv;
- while (*tmp) {
- virBufferAdd(&buf, *tmp, strlen(*tmp));
- virBufferAddLit(&buf, " ");
- tmp++;
- }
-
- if (virBufferError(&buf)) {
- virBufferFreeAndReset(&buf);
- virReportOOMError();
+ if (!(cmd = qemudBuildCommandLine(conn, driver, def,
+ &monConfig, false, qemuCmdFlags,
+ NULL, NULL)))
goto cleanup;
- }
- ret = virBufferContentAndReset(&buf);
+ ret = virCommandToString(cmd);
cleanup:
qemuDriverUnlock(driver);
- for (tmp = retargv ; tmp && *tmp ; tmp++)
- VIR_FREE(*tmp);
- VIR_FREE(retargv);
-
- for (tmp = retenv ; tmp && *tmp ; tmp++)
- VIR_FREE(*tmp);
- VIR_FREE(retenv);
+ virCommandFree(cmd);
virDomainDefFree(def);
return ret;
}
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index b149ef4..07dde54 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -25,28 +25,30 @@ static struct qemud_driver driver;
# define MAX_FILE 4096
static int testCompareXMLToArgvFiles(const char *xml,
- const char *cmd,
+ const char *cmdline,
unsigned long long extraFlags,
const char *migrateFrom,
bool expectError) {
char argvData[MAX_FILE];
char *expectargv = &(argvData[0]);
+ int len;
char *actualargv = NULL;
- const char **argv = NULL;
- const char **qenv = NULL;
- const char **tmp = NULL;
- int ret = -1, len;
+ int ret = -1;
unsigned long long flags;
virDomainDefPtr vmdef = NULL;
virDomainChrDef monitor_chr;
virConnectPtr conn;
char *log = NULL;
+ virCommandPtr cmd = NULL;
if (!(conn = virGetConnect()))
goto fail;
- if (virtTestLoadFile(cmd, &expectargv, MAX_FILE) < 0)
+ len = virtTestLoadFile(cmdline, &expectargv, MAX_FILE);
+ if (len < 0)
goto fail;
+ if (len && expectargv[len - 1] == '\n')
+ expectargv[len - 1] = '\0';
if (!(vmdef = virDomainDefParseFile(driver.caps, xml,
VIR_DOMAIN_XML_INACTIVE)))
@@ -85,10 +87,9 @@ static int testCompareXMLToArgvFiles(const char *xml,
free(virtTestLogContentAndReset());
- if (qemudBuildCommandLine(conn, &driver,
- vmdef, &monitor_chr, 0, flags,
- &argv, &qenv,
- NULL, NULL, migrateFrom, NULL) < 0)
+ if (!(cmd = qemudBuildCommandLine(conn, &driver,
+ vmdef, &monitor_chr, false, flags,
+ migrateFrom, NULL)))
goto fail;
if ((log = virtTestLogContentAndReset()) == NULL)
@@ -105,36 +106,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
virResetLastError();
}
- len = 1; /* for trailing newline */
- tmp = qenv;
- while (*tmp) {
- len += strlen(*tmp) + 1;
- tmp++;
- }
-
- tmp = argv;
- while (*tmp) {
- len += strlen(*tmp) + 1;
- tmp++;
- }
- if ((actualargv = malloc(sizeof(*actualargv)*len)) == NULL)
+ if (!(actualargv = virCommandToString(cmd)))
goto fail;
- actualargv[0] = '\0';
- tmp = qenv;
- while (*tmp) {
- if (actualargv[0])
- strcat(actualargv, " ");
- strcat(actualargv, *tmp);
- tmp++;
- }
- tmp = argv;
- while (*tmp) {
- if (actualargv[0])
- strcat(actualargv, " ");
- strcat(actualargv, *tmp);
- tmp++;
- }
- strcat(actualargv, "\n");
if (STRNEQ(expectargv, actualargv)) {
virtTestDifference(stderr, expectargv, actualargv);
@@ -146,22 +119,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
fail:
free(log);
free(actualargv);
- if (argv) {
- tmp = argv;
- while (*tmp) {
- free(*(char**)tmp);
- tmp++;
- }
- free(argv);
- }
- if (qenv) {
- tmp = qenv;
- while (*tmp) {
- free(*(char**)tmp);
- tmp++;
- }
- free(qenv);
- }
+ virCommandFree(cmd);
virDomainDefFree(vmdef);
virUnrefConnect(conn);
return ret;
--
1.7.3.2