virCommandPtr virBhyveProcessBuildBhyveCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED, virDomainObjPtr vm) { /* * /usr/sbin/bhyve -c 2 -m 256 -AI -H -P \ * -s 0:0,hostbridge \ * -s 1:0,virtio-net,tap0 \ * -s 2:0,ahci-hd,${IMG} \ * -S 31,uart,stdio \ * vm0 */ virCommandPtr cmd = virCommandNew(BHYVE); /* CPUs */ virCommandAddArg(cmd, "-c"); virCommandAddArgFormat(cmd, "%d", vm->def->vcpus); /* Memory */ virCommandAddArg(cmd, "-m"); virCommandAddArgFormat(cmd, "%llu", VIR_DIV_UP(vm->def->mem.max_balloon, 1024)); /* Options */ if (vm->def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON) virCommandAddArg(cmd, "-A"); /* Create an ACPI table */ if (vm->def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON) virCommandAddArg(cmd, "-I"); /* Present ioapic to the guest */ /* Clarification about -H and -P flags from Peter Grehan: * -H and -P flags force the guest to exit when it executes IA32 HLT and PAUSE * instructions respectively. * * For the HLT exit, bhyve uses that to infer that the guest is idling and can * be put to sleep until an external event arrives. If this option is not used, * the guest will always use 100% of CPU on the host. * * The PAUSE exit is most useful when there are large numbers of guest VMs running, * since it forces the guest to exit when it spins on a lock acquisition. */ virCommandAddArg(cmd, "-H"); /* vmexit from guest on hlt */ virCommandAddArg(cmd, "-P"); /* vmexit from guest on pause */ virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); /* Devices */ if (bhyveBuildNetArgStr(vm->def, cmd) < 0) goto error; if (bhyveBuildDiskArgStr(vm->def, cmd) < 0) goto error; if (bhyveBuildConsoleArgStr(vm->def, cmd) < 0) goto error; virCommandAddArg(cmd, vm->def->name); return cmd; error: virCommandFree(cmd); return NULL; }
static int virStorageBackendZFSCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol) { virCommandPtr cmd = NULL; int ret = -1; vol->type = VIR_STORAGE_VOL_BLOCK; if (vol->target.path != NULL) { /* A target path passed to CreateVol has no meaning */ VIR_FREE(vol->target.path); } if (virAsprintf(&vol->target.path, "%s/%s", pool->def->target.path, vol->name) == -1) return -1; if (VIR_STRDUP(vol->key, vol->target.path) < 0) goto cleanup; /** * $ zfs create -o volmode=dev -V 10240K test/volname * * -o volmode=dev -- we want to get volumes exposed as cdev * devices. If we don't specify that zfs * will lookup vfs.zfs.vol.mode sysctl value * -V -- tells to create a volume with the specified size */ cmd = virCommandNewArgList(ZFS, "create", "-o", "volmode=dev", "-V", NULL); virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity, 1024)); virCommandAddArgFormat(cmd, "%s/%s", pool->def->source.name, vol->name); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virStorageBackendZFSFindVols(pool, vol) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int virStorageBackendZFSDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags) { int ret = -1; virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool); virCommandPtr destroy_cmd = NULL; virCheckFlags(0, -1); destroy_cmd = virCommandNewArgList(ZFS, "destroy", NULL); virCommandAddArgFormat(destroy_cmd, "%s/%s", def->source.name, vol->name); if (virCommandRun(destroy_cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(destroy_cmd); return ret; }
static int bhyveBuildConsoleArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainChrDefPtr chr = NULL; if (!def->nserials) return 0; chr = def->serials[0]; if (chr->source.type != VIR_DOMAIN_CHR_TYPE_NMDM) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only nmdm console types are supported")); return -1; } /* bhyve supports only two ports: com1 and com2 */ if (chr->target.port > 2) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only two serial ports are supported")); return -1; } virCommandAddArgList(cmd, "-s", "1,lpc", NULL); virCommandAddArg(cmd, "-l"); virCommandAddArgFormat(cmd, "com%d,%s", chr->target.port + 1, chr->source.data.file.path); return 0; }
static int virStorageBackendSheepdogCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol) { int ret = -1; if (vol->target.encryption != NULL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Sheepdog does not support encrypted volumes")); return -1; } virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "create", vol->name, NULL); virCommandAddArgFormat(cmd, "%llu", vol->capacity); virStorageBackendSheepdogAddHostArg(cmd, pool); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virStorageBackendSheepdogRefreshVol(conn, pool, vol) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
void virStorageBackendSheepdogAddHostArg(virCommandPtr cmd, virStoragePoolObjPtr pool) { const char *address = "localhost"; int port = 7000; if (pool->def->source.nhost > 0) { if (pool->def->source.hosts[0].name != NULL) address = pool->def->source.hosts[0].name; if (pool->def->source.hosts[0].port) port = pool->def->source.hosts[0].port; } virCommandAddArg(cmd, "-a"); virCommandAddArgFormat(cmd, "%s", address); virCommandAddArg(cmd, "-p"); virCommandAddArgFormat(cmd, "%d", port); }
/* virPolkitAgentCreate: * * Allocate and setup a polkit agent * * Returns a virCommandPtr on success and NULL on failure */ virPolkitAgentPtr virPolkitAgentCreate(void) { virPolkitAgentPtr agent = NULL; int pipe_fd[2] = {-1, -1}; struct pollfd pollfd; int outfd = STDOUT_FILENO; int errfd = STDERR_FILENO; if (!isatty(STDIN_FILENO)) goto error; if (pipe2(pipe_fd, 0) < 0) goto error; if (VIR_ALLOC(agent) < 0) goto error; agent->cmd = virCommandNewArgList(PKTTYAGENT, "--process", NULL); virCommandAddArgFormat(agent->cmd, "%lld", (long long int) getpid()); virCommandAddArg(agent->cmd, "--notify-fd"); virCommandAddArgFormat(agent->cmd, "%d", pipe_fd[1]); virCommandAddArg(agent->cmd, "--fallback"); virCommandSetInputFD(agent->cmd, STDIN_FILENO); virCommandSetOutputFD(agent->cmd, &outfd); virCommandSetErrorFD(agent->cmd, &errfd); virCommandPassFD(agent->cmd, pipe_fd[1], VIR_COMMAND_PASS_FD_CLOSE_PARENT); if (virCommandRunAsync(agent->cmd, NULL) < 0) goto error; pollfd.fd = pipe_fd[0]; pollfd.events = POLLHUP; if (poll(&pollfd, 1, -1) < 0) goto error; return agent; error: VIR_FORCE_CLOSE(pipe_fd[0]); VIR_FORCE_CLOSE(pipe_fd[1]); virPolkitAgentDestroy(agent); return NULL; }
static int bhyveBuildDiskArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainDiskDefPtr disk; const char *bus_type; if (def->ndisks != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one disk defined")); return -1; } disk = def->disks[0]; switch (disk->bus) { case VIR_DOMAIN_DISK_BUS_SATA: bus_type = "ahci-hd"; break; case VIR_DOMAIN_DISK_BUS_VIRTIO: bus_type = "virtio-blk"; break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk bus type")); return -1; } if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk device")); return -1; } if (virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_FILE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk type")); return -1; } virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "2:0,%s,%s", bus_type, virDomainDiskGetSource(disk)); return 0; }
static int virStorageBackendSheepdogResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned long long capacity, unsigned int flags) { virCheckFlags(0, -1); virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "resize", vol->name, NULL); virCommandAddArgFormat(cmd, "%llu", capacity); virStorageBackendSheepdogAddHostArg(cmd, pool); int ret = virCommandRun(cmd, NULL); virCommandFree(cmd); return ret; }
virCommandPtr virBhyveProcessBuildLoadCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED, virDomainObjPtr vm) { virCommandPtr cmd; virDomainDiskDefPtr disk; if (vm->def->ndisks != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one disk defined")); return NULL; } disk = vm->def->disks[0]; if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk device")); return NULL; } if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk type")); return NULL; } cmd = virCommandNew(BHYVELOAD); /* Memory */ virCommandAddArg(cmd, "-m"); virCommandAddArgFormat(cmd, "%llu", VIR_DIV_UP(vm->def->mem.max_balloon, 1024)); /* Image path */ virCommandAddArg(cmd, "-d"); virCommandAddArg(cmd, disk->src); /* VM name */ virCommandAddArg(cmd, vm->def->name); return cmd; }
char * virNumaGetAutoPlacementAdvice(unsigned short vcpus, unsigned long long balloon) { virCommandPtr cmd = NULL; char *output = NULL; cmd = virCommandNewArgList(NUMAD, "-w", NULL); virCommandAddArgFormat(cmd, "%d:%llu", vcpus, VIR_DIV_UP(balloon, 1024)); virCommandSetOutputBuffer(cmd, &output); if (virCommandRun(cmd, NULL) < 0) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to query numad for the " "advisory nodeset")); virCommandFree(cmd); return output; }
/** * virNodeSuspendSetNodeWakeup: * @alarmTime: time in seconds from now, at which the RTC alarm has to be set. * * Set up the RTC alarm to the specified time. * Return 0 on success, -1 on failure. */ static int virNodeSuspendSetNodeWakeup(unsigned long long alarmTime) { virCommandPtr setAlarmCmd; int ret = -1; if (alarmTime <= MIN_TIME_REQ_FOR_SUSPEND) { virNodeSuspendError(VIR_ERR_INVALID_ARG, "%s", _("Suspend duration is too short")); return -1; } setAlarmCmd = virCommandNewArgList("rtcwake", "-m", "no", "-s", NULL); virCommandAddArgFormat(setAlarmCmd, "%lld", alarmTime); if (virCommandRun(setAlarmCmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(setAlarmCmd); return ret; }
static int bhyveBuildDiskArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainDiskDefPtr disk; if (def->ndisks != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one disk defined")); return -1; } disk = def->disks[0]; if (disk->bus != VIR_DOMAIN_DISK_BUS_SATA) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk bus type")); return -1; } if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk device")); return -1; } if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk type")); return -1; } virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "2:0,ahci-hd,%s", disk->src); return 0; }
static int virStorageBackendSheepdogBuildVol(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags) { int ret = -1; virCheckFlags(0, -1); virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "create", vol->name, NULL); virCommandAddArgFormat(cmd, "%llu", vol->target.capacity); virStorageBackendSheepdogAddHostArg(cmd, pool); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virStorageBackendSheepdogRefreshVol(conn, pool, vol) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
/* * Constructs a argv suitable for launching uml with config defined * for a given virtual machine. */ virCommandPtr umlBuildCommandLine(virConnectPtr conn, struct uml_driver *driver, virDomainObjPtr vm) { size_t i, j; virCommandPtr cmd; cmd = virCommandNew(vm->def->os.kernel); virCommandAddEnvPassCommon(cmd); //virCommandAddArgPair(cmd, "con0", "fd:0,fd:1"); virCommandAddArgFormat(cmd, "mem=%lluK", vm->def->mem.cur_balloon); virCommandAddArgPair(cmd, "umid", vm->def->name); virCommandAddArgPair(cmd, "uml_dir", driver->monitorDir); if (vm->def->os.root) virCommandAddArgPair(cmd, "root", vm->def->os.root); for (i = 0; i < vm->def->ndisks; i++) { virDomainDiskDefPtr disk = vm->def->disks[i]; if (!STRPREFIX(disk->dst, "ubd")) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported disk type '%s'"), disk->dst); goto error; } virCommandAddArgPair(cmd, disk->dst, virDomainDiskGetSource(disk)); } for (i = 0; i < vm->def->nnets; i++) { char *ret = umlBuildCommandLineNet(conn, vm->def, vm->def->nets[i], i); if (!ret) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) { virDomainChrDefPtr chr = NULL; char *ret = NULL; for (j = 0; j < vm->def->nconsoles; j++) if (vm->def->consoles[j]->target.port == i) chr = vm->def->consoles[j]; if (chr) ret = umlBuildCommandLineChr(chr, "con", cmd); if (!ret) if (virAsprintf(&ret, "con%zu=none", i) < 0) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) { virDomainChrDefPtr chr = NULL; char *ret = NULL; for (j = 0; j < vm->def->nserials; j++) if (vm->def->serials[j]->target.port == i) chr = vm->def->serials[j]; if (chr) ret = umlBuildCommandLineChr(chr, "ssl", cmd); if (!ret) if (virAsprintf(&ret, "ssl%zu=none", i) < 0) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } if (vm->def->os.cmdline) { char *args, *next_arg; char *cmdline; if (VIR_STRDUP(cmdline, vm->def->os.cmdline) < 0) goto error; args = cmdline; while (*args == ' ') args++; while (*args) { next_arg = umlNextArg(args); virCommandAddArg(cmd, args); args = next_arg; } VIR_FREE(cmdline); } return cmd; error: virCommandFree(cmd); return NULL; }
static virCommandPtr virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, virDomainObjPtr vm, int nveths, char **veths, int *ttyFDs, size_t nttyFDs, int *files, size_t nfiles, int handshakefd) { size_t i; char *filterstr; char *outputstr; virCommandPtr cmd; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); cmd = virCommandNew(vm->def->emulator); /* The controller may call ip command, so we have to retain PATH. */ virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin"); virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d", virLogGetDefaultPriority()); if (virLogGetNbFilters() > 0) { filterstr = virLogGetFilters(); if (!filterstr) { virReportOOMError(); goto cleanup; } virCommandAddEnvPair(cmd, "LIBVIRT_LOG_FILTERS", filterstr); VIR_FREE(filterstr); } if (cfg->log_libvirtd) { if (virLogGetNbOutputs() > 0) { outputstr = virLogGetOutputs(); if (!outputstr) { virReportOOMError(); goto cleanup; } virCommandAddEnvPair(cmd, "LIBVIRT_LOG_OUTPUTS", outputstr); VIR_FREE(outputstr); } } else { virCommandAddEnvFormat(cmd, "LIBVIRT_LOG_OUTPUTS=%d:stderr", virLogGetDefaultPriority()); } virCommandAddArgList(cmd, "--name", vm->def->name, NULL); for (i = 0; i < nttyFDs; i++) { virCommandAddArg(cmd, "--console"); virCommandAddArgFormat(cmd, "%d", ttyFDs[i]); virCommandPassFD(cmd, ttyFDs[i], 0); } for (i = 0; i < nfiles; i++) { virCommandAddArg(cmd, "--passfd"); virCommandAddArgFormat(cmd, "%d", files[i]); virCommandPassFD(cmd, files[i], 0); } virCommandAddArgPair(cmd, "--security", virSecurityManagerGetModel(driver->securityManager)); virCommandAddArg(cmd, "--handshake"); virCommandAddArgFormat(cmd, "%d", handshakefd); virCommandAddArg(cmd, "--background"); for (i = 0; i < nveths; i++) { virCommandAddArgList(cmd, "--veth", veths[i], NULL); } virCommandPassFD(cmd, handshakefd, 0); return cmd; cleanup: virCommandFree(cmd); virObjectUnref(cfg); return NULL; }
/* * qemuTPMEmulatorBuildCommand: * * @tpm: TPM definition * @vmname: The name of the VM * @vmuuid: The UUID of the VM * @privileged: whether we are running in privileged mode * @swtpm_user: The uid for the swtpm to run as (drop privileges to from root) * @swtpm_group: The gid for the swtpm to run as * @swtpmStateDir: the directory where swtpm writes the pid file and creates the * Unix socket * @shortName: the short name of the VM * * Create the virCommand use for starting the emulator * Do some initializations on the way, such as creation of storage * and emulator setup. */ static virCommandPtr qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, const char *vmname, const unsigned char *vmuuid, bool privileged, uid_t swtpm_user, gid_t swtpm_group, const char *swtpmStateDir, const char *shortName) { virCommandPtr cmd = NULL; bool created = false; char *pidfile; if (qemuTPMCreateEmulatorStorage(tpm->data.emulator.storagepath, &created, swtpm_user, swtpm_group) < 0) return NULL; if (created && qemuTPMEmulatorRunSetup(tpm->data.emulator.storagepath, vmname, vmuuid, privileged, swtpm_user, swtpm_group, tpm->data.emulator.logfile, tpm->version) < 0) goto error; unlink(tpm->data.emulator.source.data.nix.path); cmd = virCommandNew(swtpm_path); if (!cmd) goto error; virCommandClearCaps(cmd); virCommandAddArgList(cmd, "socket", "--daemon", "--ctrl", NULL); virCommandAddArgFormat(cmd, "type=unixio,path=%s,mode=0600", tpm->data.emulator.source.data.nix.path); virCommandAddArg(cmd, "--tpmstate"); virCommandAddArgFormat(cmd, "dir=%s,mode=0600", tpm->data.emulator.storagepath); virCommandAddArg(cmd, "--log"); virCommandAddArgFormat(cmd, "file=%s", tpm->data.emulator.logfile); virCommandSetUID(cmd, swtpm_user); virCommandSetGID(cmd, swtpm_group); switch (tpm->version) { case VIR_DOMAIN_TPM_VERSION_1_2: break; case VIR_DOMAIN_TPM_VERSION_2_0: virCommandAddArg(cmd, "--tpm2"); break; case VIR_DOMAIN_TPM_VERSION_DEFAULT: case VIR_DOMAIN_TPM_VERSION_LAST: break; } if (!(pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir, shortName))) goto error; virCommandAddArg(cmd, "--pid"); virCommandAddArgFormat(cmd, "file=%s", pidfile); VIR_FREE(pidfile); return cmd; error: if (created) qemuTPMDeleteEmulatorStorage(tpm); virCommandFree(cmd); return NULL; }
static int bhyveBuildNetArgStr(const virDomainDef *def, virDomainNetDefPtr net, virCommandPtr cmd, bool dryRun) { char macaddr[VIR_MAC_STRING_BUFLEN]; char *realifname = NULL; char *brname = NULL; int actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Network type %d is not supported"), virDomainNetGetActualType(net)); return -1; } if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { VIR_FREE(net->ifname); if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) { VIR_FREE(brname); return -1; } } if (!dryRun) { if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, NULL, NULL, 0, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } realifname = virNetDevTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } VIR_DEBUG("%s -> %s", net->ifname, realifname); /* hack on top of other hack: we need to set * interface to 'UP' again after re-opening to find its * name */ if (virNetDevSetOnline(net->ifname, true) != 0) { VIR_FREE(realifname); VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } } else { if (VIR_STRDUP(realifname, "tap0") < 0) return -1; } virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "%d:0,virtio-net,%s,mac=%s", net->info.addr.pci.slot, realifname, virMacAddrFormat(&net->mac, macaddr)); VIR_FREE(realifname); return 0; }
static int testPrepImages(void) { int ret = EXIT_FAILURE; virCommandPtr cmd = NULL; qemuimg = virFindFileInPath("kvm-img"); if (!qemuimg) qemuimg = virFindFileInPath("qemu-img"); if (!qemuimg) goto skip; if (virAsprintf(&absraw, "%s/raw", datadir) < 0 || virAsprintf(&absqcow2, "%s/qcow2", datadir) < 0 || virAsprintf(&abswrap, "%s/wrap", datadir) < 0 || virAsprintf(&absqed, "%s/qed", datadir) < 0 || virAsprintf(&abslink2, "%s/sub/link2", datadir) < 0) { virReportOOMError(); goto cleanup; } if (virFileMakePath(datadir "/sub") < 0) { fprintf(stderr, "unable to create directory %s\n", datadir "/sub"); goto cleanup; } if (chdir(datadir) < 0) { fprintf(stderr, "unable to test relative backing chains\n"); goto cleanup; } /* I'm lazy enough to use a shell one-liner instead of open/write/close */ virCommandFree(cmd); cmd = virCommandNewArgList("sh", "-c", "printf %1024d 0 > raw", NULL); if (virCommandRun(cmd, NULL) < 0) { fprintf(stderr, "unable to create raw file\n"); goto cleanup; } if (!(canonraw = canonicalize_file_name(absraw))) { virReportOOMError(); goto cleanup; } /* Create a qcow2 wrapping relative raw; later on, we modify its * metadata to test other configurations */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", "-obacking_file=raw,backing_fmt=raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Make sure our later uses of 'qemu-img rebase' will work */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", "raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonqcow2 = canonicalize_file_name(absqcow2))) { virReportOOMError(); goto cleanup; } /* Create a second qcow2 wrapping the first, to be sure that we * can correctly avoid insecure probing. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=qcow2", absqcow2); virCommandAddArg(cmd, "wrap"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Create a qed file. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qed", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=raw", absraw); virCommandAddArg(cmd, "qed"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Create some symlinks in a sub-directory. */ if (symlink("../qcow2", datadir "/sub/link1") < 0 || symlink("../wrap", datadir "/sub/link2") < 0) { fprintf(stderr, "unable to create symlink"); goto cleanup; } ret = 0; cleanup: virCommandFree(cmd); if (ret) testCleanupImages(); return ret; skip: fputs("qemu-img is too old; skipping this test\n", stderr); ret = EXIT_AM_SKIP; goto cleanup; }
/** * virNetDevOpenvswitchAddPort: * @brname: the bridge name * @ifname: the network interface name * @macaddr: the mac address of the virtual interface * @vmuuid: the Domain UUID that has this interface * @ovsport: the ovs specific fields * * Add an interface to the OVS bridge * * Returns 0 in case of success or -1 in case of failure. */ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, const virMacAddr *macaddr, const unsigned char *vmuuid, virNetDevVPortProfilePtr ovsport, virNetDevVlanPtr virtVlan) { int ret = -1; size_t i = 0; virCommandPtr cmd = NULL; char macaddrstr[VIR_MAC_STRING_BUFLEN]; char ifuuidstr[VIR_UUID_STRING_BUFLEN]; char vmuuidstr[VIR_UUID_STRING_BUFLEN]; char *attachedmac_ex_id = NULL; char *ifaceid_ex_id = NULL; char *profile_ex_id = NULL; char *vmid_ex_id = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virMacAddrFormat(macaddr, macaddrstr); virUUIDFormat(ovsport->interfaceID, ifuuidstr); virUUIDFormat(vmuuid, vmuuidstr); if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"", macaddrstr) < 0) goto cleanup; if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"", ifuuidstr) < 0) goto cleanup; if (virAsprintf(&vmid_ex_id, "external-ids:vm-id=\"%s\"", vmuuidstr) < 0) goto cleanup; if (ovsport->profileID[0] != '\0') { if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"", ovsport->profileID) < 0) goto cleanup; } cmd = virCommandNew(OVSVSCTL); virCommandAddArgList(cmd, "--timeout=5", "--", "--if-exists", "del-port", ifname, "--", "add-port", brname, ifname, NULL); if (virtVlan && virtVlan->nTags > 0) { switch (virtVlan->nativeMode) { case VIR_NATIVE_VLAN_MODE_TAGGED: virCommandAddArg(cmd, "vlan_mode=native-tagged"); virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag); break; case VIR_NATIVE_VLAN_MODE_UNTAGGED: virCommandAddArg(cmd, "vlan_mode=native-untagged"); virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag); break; case VIR_NATIVE_VLAN_MODE_DEFAULT: default: break; } if (virtVlan->trunk) { virBufferAddLit(&buf, "trunk="); /* * Trunk ports have at least one VLAN. Do the first one * outside the "for" loop so we can put a "," at the * start of the for loop if there are more than one VLANs * on this trunk port. */ virBufferAsprintf(&buf, "%d", virtVlan->tag[i]); for (i = 1; i < virtVlan->nTags; i++) { virBufferAddLit(&buf, ","); virBufferAsprintf(&buf, "%d", virtVlan->tag[i]); } if (virBufferCheckError(&buf) < 0) goto cleanup; virCommandAddArg(cmd, virBufferCurrentContent(&buf)); } else if (virtVlan->nTags) { virCommandAddArgFormat(cmd, "tag=%d", virtVlan->tag[0]); } } if (ovsport->profileID[0] == '\0') { virCommandAddArgList(cmd, "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, vmid_ex_id, "--", "set", "Interface", ifname, "external-ids:iface-status=active", NULL); } else { virCommandAddArgList(cmd, "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, vmid_ex_id, "--", "set", "Interface", ifname, profile_ex_id, "--", "set", "Interface", ifname, "external-ids:iface-status=active", NULL); } if (virCommandRun(cmd, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to add port %s to OVS bridge %s"), ifname, brname); goto cleanup; } ret = 0; cleanup: virBufferFreeAndReset(&buf); VIR_FREE(attachedmac_ex_id); VIR_FREE(ifaceid_ex_id); VIR_FREE(vmid_ex_id); VIR_FREE(profile_ex_id); virCommandFree(cmd); return ret; }
/* * Add "NAME=VAL" as a single command line argument to the child */ void virCommandAddArgPair(virCommandPtr cmd, const char *name, const char *val) { virCommandAddArgFormat(cmd, "%s=%s", name, val); }
static int testPrepImages(void) { int ret = EXIT_FAILURE; virCommandPtr cmd = NULL; char *buf = NULL; bool compat = false; qemuimg = virFindFileInPath("kvm-img"); if (!qemuimg) qemuimg = virFindFileInPath("qemu-img"); if (!qemuimg) goto skip; /* Clean up from any earlier failed tests */ virFileDeleteTree(datadir); /* See if qemu-img supports '-o compat=xxx'. If so, we force the * use of both v2 and v3 files; if not, it is v2 only but the test * still works. */ cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", "-o?", "/dev/null", NULL); virCommandSetOutputBuffer(cmd, &buf); if (virCommandRun(cmd, NULL) < 0) goto skip; if (strstr(buf, "compat ")) compat = true; VIR_FREE(buf); if (virAsprintf(&absraw, "%s/raw", datadir) < 0 || virAsprintf(&absqcow2, "%s/qcow2", datadir) < 0 || virAsprintf(&abswrap, "%s/wrap", datadir) < 0 || virAsprintf(&absqed, "%s/qed", datadir) < 0 || virAsprintf(&absdir, "%s/dir", datadir) < 0 || virAsprintf(&abslink2, "%s/sub/link2", datadir) < 0) goto cleanup; if (virFileMakePath(datadir "/sub") < 0) { fprintf(stderr, "unable to create directory %s\n", datadir "/sub"); goto cleanup; } if (virFileMakePath(datadir "/dir") < 0) { fprintf(stderr, "unable to create directory %s\n", datadir "/dir"); goto cleanup; } if (!(canondir = canonicalize_file_name(absdir))) { virReportOOMError(); goto cleanup; } if (chdir(datadir) < 0) { fprintf(stderr, "unable to test relative backing chains\n"); goto cleanup; } if (virAsprintf(&buf, "%1024d", 0) < 0 || virFileWriteStr("raw", buf, 0600) < 0) { fprintf(stderr, "unable to create raw file\n"); goto cleanup; } if (!(canonraw = canonicalize_file_name(absraw))) { virReportOOMError(); goto cleanup; } /* Create a qcow2 wrapping relative raw; later on, we modify its * metadata to test other configurations */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL); virCommandAddArgFormat(cmd, "-obacking_file=raw,backing_fmt=raw%s", compat ? ",compat=0.10" : ""); virCommandAddArg(cmd, "qcow2"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Make sure our later uses of 'qemu-img rebase' will work */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", "raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonqcow2 = canonicalize_file_name(absqcow2))) { virReportOOMError(); goto cleanup; } /* Create a second qcow2 wrapping the first, to be sure that we * can correctly avoid insecure probing. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=qcow2%s", absqcow2, compat ? ",compat=1.1" : ""); virCommandAddArg(cmd, "wrap"); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonwrap = canonicalize_file_name(abswrap))) { virReportOOMError(); goto cleanup; } /* Create a qed file. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qed", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=raw", absraw); virCommandAddArg(cmd, "qed"); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonqed = canonicalize_file_name(absqed))) { virReportOOMError(); goto cleanup; } #ifdef HAVE_SYMLINK /* Create some symlinks in a sub-directory. */ if (symlink("../qcow2", datadir "/sub/link1") < 0 || symlink("../wrap", datadir "/sub/link2") < 0) { fprintf(stderr, "unable to create symlink"); goto cleanup; } #endif ret = 0; cleanup: VIR_FREE(buf); virCommandFree(cmd); if (ret) testCleanupImages(); return ret; skip: fputs("qemu-img is too old; skipping this test\n", stderr); ret = EXIT_AM_SKIP; goto cleanup; }
static int virStorageBackendZFSCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol) { virCommandPtr cmd = NULL; int ret = -1; int volmode_needed = -1; if (vol->target.format != VIR_STORAGE_FILE_RAW) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only RAW volumes are supported by this storage pool")); return -1; } if (vol->target.encryption != NULL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("storage pool does not support encrypted " "volumes")); return -1; } vol->type = VIR_STORAGE_VOL_BLOCK; VIR_FREE(vol->target.path); if (virAsprintf(&vol->target.path, "%s/%s", pool->def->target.path, vol->name) == -1) return -1; if (VIR_STRDUP(vol->key, vol->target.path) < 0) goto cleanup; volmode_needed = virStorageBackendZFSVolModeNeeded(); if (volmode_needed < 0) goto cleanup; /** * $ zfs create -o volmode=dev -V 10240K test/volname * * -o volmode=dev -- we want to get volumes exposed as cdev * devices. If we don't specify that zfs * will lookup vfs.zfs.vol.mode sysctl value * -V -- tells to create a volume with the specified size */ cmd = virCommandNewArgList(ZFS, "create", NULL); if (volmode_needed) virCommandAddArgList(cmd, "-o", "volmode=dev", NULL); virCommandAddArg(cmd, "-V"); virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity, 1024)); virCommandAddArgFormat(cmd, "%s/%s", pool->def->source.name, vol->name); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virStorageBackendZFSFindVols(pool, vol) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
/** * qemuCreateInBridgePortWithHelper: * @cfg: the configuration object in which the helper name is looked up * @brname: the bridge name * @ifname: the returned interface name * @macaddr: the returned MAC address * @tapfd: file descriptor return value for the new tap device * @flags: OR of virNetDevTapCreateFlags: * VIR_NETDEV_TAP_CREATE_VNET_HDR * - Enable IFF_VNET_HDR on the tap device * * This function creates a new tap device on a bridge using an external * helper. The final name for the bridge will be stored in @ifname. * * Returns 0 in case of success or -1 on failure */ static int qemuCreateInBridgePortWithHelper(virQEMUDriverConfigPtr cfg, const char *brname, char **ifname, int *tapfd, unsigned int flags) { virCommandPtr cmd; char *errbuf = NULL, *cmdstr = NULL; int pair[2] = { -1, -1 }; if ((flags & ~VIR_NETDEV_TAP_CREATE_VNET_HDR) != VIR_NETDEV_TAP_CREATE_IFUP) return -1; if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) { virReportSystemError(errno, "%s", _("failed to create socket")); return -1; } if (!virFileIsExecutable(cfg->bridgeHelperName)) { virReportSystemError(errno, _("'%s' is not a suitable bridge helper"), cfg->bridgeHelperName); return -1; } cmd = virCommandNew(cfg->bridgeHelperName); if (flags & VIR_NETDEV_TAP_CREATE_VNET_HDR) virCommandAddArgFormat(cmd, "--use-vnet"); virCommandAddArgFormat(cmd, "--br=%s", brname); virCommandAddArgFormat(cmd, "--fd=%d", pair[1]); virCommandSetErrorBuffer(cmd, &errbuf); virCommandDoAsyncIO(cmd); virCommandPassFD(cmd, pair[1], VIR_COMMAND_PASS_FD_CLOSE_PARENT); virCommandClearCaps(cmd); #ifdef CAP_NET_ADMIN virCommandAllowCap(cmd, CAP_NET_ADMIN); #endif if (virCommandRunAsync(cmd, NULL) < 0) { *tapfd = -1; goto cleanup; } do { *tapfd = recvfd(pair[0], 0); } while (*tapfd < 0 && errno == EINTR); if (*tapfd < 0) { char ebuf[1024]; char *errstr = NULL; if (!(cmdstr = virCommandToString(cmd))) goto cleanup; virCommandAbort(cmd); if (errbuf && *errbuf && virAsprintf(&errstr, "\nstderr=%s", errbuf) < 0) goto cleanup; virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: failed to communicate with bridge helper: %s%s"), cmdstr, virStrerror(errno, ebuf, sizeof(ebuf)), errstr ? errstr : ""); VIR_FREE(errstr); goto cleanup; } if (virNetDevTapGetName(*tapfd, ifname) < 0 || virCommandWait(cmd, NULL) < 0) { VIR_FORCE_CLOSE(*tapfd); *tapfd = -1; } cleanup: VIR_FREE(cmdstr); VIR_FREE(errbuf); virCommandFree(cmd); VIR_FORCE_CLOSE(pair[0]); return *tapfd < 0 ? -1 : 0; }
static int bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainNetDefPtr net = NULL; char *brname = NULL; char *realifname = NULL; int *tapfd = NULL; if (def->nnets != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one net defined")); return -1; } net = def->nets[0]; if (net) { int actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Network type %d is not supported"), virDomainNetGetActualType(net)); return -1; } if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { VIR_FREE(net->ifname); if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) { VIR_FREE(brname); return -1; } } if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, tapfd, 1, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } } realifname = virBhyveTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } VIR_DEBUG("%s -> %s", net->ifname, realifname); /* hack on top of other hack: we need to set * interface to 'UP' again after re-opening to find its * name */ if (virNetDevSetOnline(net->ifname, true) != 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "1:0,virtio-net,%s", realifname); return 0; }