static bool hasNetfilterTools(void) { return virFileIsExecutable(IPTABLES_PATH) && virFileIsExecutable(IP6TABLES_PATH) && virFileIsExecutable(EBTABLES_PATH); }
/* * qemuTPMEmulatorInit * * Initialize the Emulator functions by searching for necessary * executables that we will use to start and setup the swtpm */ static int qemuTPMEmulatorInit(void) { if (!swtpm_path) { swtpm_path = virFindFileInPath("swtpm"); if (!swtpm_path) { virReportSystemError(ENOENT, "%s", _("Unable to find 'swtpm' binary in $PATH")); return -1; } if (!virFileIsExecutable(swtpm_path)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("TPM emulator %s is not an executable"), swtpm_path); VIR_FREE(swtpm_path); return -1; } } if (!swtpm_setup) { swtpm_setup = virFindFileInPath("swtpm_setup"); if (!swtpm_setup) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not find 'swtpm_setup' in PATH")); return -1; } if (!virFileIsExecutable(swtpm_setup)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("'%s' is not an executable"), swtpm_setup); VIR_FREE(swtpm_setup); return -1; } } if (!swtpm_ioctl) { swtpm_ioctl = virFindFileInPath("swtpm_ioctl"); if (!swtpm_ioctl) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not find swtpm_ioctl in PATH")); return -1; } if (!virFileIsExecutable(swtpm_ioctl)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("swtpm_ioctl program %s is not an executable"), swtpm_ioctl); VIR_FREE(swtpm_ioctl); return -1; } } return 0; }
/** * virHookCheck: * @driver: the driver name "daemon", "qemu", "lxc"... * * Check is there is an installed hook for the given driver, if this * is the case register it. Then subsequent calls to virHookCall * will call the hook if found. * * Returns 1 if found, 0 if not found, and -1 in case of error */ static int virHookCheck(int no, const char *driver) { char *path; int ret; if (driver == NULL) { virHookReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid hook name for #%d"), no); return -1; } ret = virBuildPath(&path, LIBVIRT_HOOK_DIR, driver); if ((ret < 0) || (path == NULL)) { virHookReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to build path for %s hook"), driver); return -1; } if (!virFileExists(path)) { ret = 0; VIR_DEBUG("No hook script %s", path); } else if (!virFileIsExecutable(path)) { ret = 0; VIR_WARN("Non-executable hook script %s", path); } else { ret = 1; VIR_DEBUG("Found hook script %s", path); } VIR_FREE(path); return ret; }
int virBhyveProbeCaps(unsigned int *caps) { char *binary, *help; virCommandPtr cmd = NULL; int ret = 0, exit; binary = virFindFileInPath("bhyve"); if (binary == NULL) goto out; if (!virFileIsExecutable(binary)) goto out; cmd = virCommandNew(binary); virCommandAddArg(cmd, "-h"); virCommandSetErrorBuffer(cmd, &help); if (virCommandRun(cmd, &exit) < 0) { ret = -1; goto out; } if (strstr(help, "-u:") != NULL) *caps |= BHYVE_CAP_RTC_UTC; out: VIR_FREE(help); virCommandFree(cmd); VIR_FREE(binary); return ret; }
int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps) { char *binary, *help; virCommandPtr cmd; int ret, exit; ret = 0; *caps = 0; cmd = NULL; help = NULL; binary = virFindFileInPath("grub-bhyve"); if (binary == NULL) goto out; if (!virFileIsExecutable(binary)) goto out; cmd = virCommandNew(binary); virCommandAddArg(cmd, "--help"); virCommandSetOutputBuffer(cmd, &help); if (virCommandRun(cmd, &exit) < 0) { ret = -1; goto out; } if (strstr(help, "--cons-dev") != NULL) *caps |= BHYVE_GRUB_CAP_CONSDEV; out: VIR_FREE(help); virCommandFree(cmd); VIR_FREE(binary); return ret; }
static const char * virLockManagerLockDaemonFindDaemon(void) { const char *customDaemon = getenv("VIRTLOCKD_PATH"); if (customDaemon) return customDaemon; if (virFileIsExecutable(VIRTLOCKD_PATH)) return VIRTLOCKD_PATH; return NULL; }
int qemuCapsProbeMachineTypes(const char *binary, virCapsGuestMachinePtr **machines, int *nmachines) { char *output; int ret = -1; virCommandPtr cmd; int status; /* 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 (!virFileIsExecutable(binary)) { virReportSystemError(errno, _("Cannot find QEMU binary %s"), binary); return -1; } cmd = virCommandNewArgList(binary, "-M", "?", NULL); virCommandAddEnvPassCommon(cmd); virCommandSetOutputBuffer(cmd, &output); virCommandClearCaps(cmd); /* Ignore failure from older qemu that did not understand '-M ?'. */ if (virCommandRun(cmd, &status) < 0) goto cleanup; if (qemuCapsParseMachineTypesStr(output, machines, nmachines) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(output); 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 qemuCapsInitGuest(virCapsPtr caps, virCapsPtr old_caps, const char *hostmachine, const struct qemu_arch_info *info, int hvm) { virCapsGuestPtr guest; int i; int haskvm = 0; int haskqemu = 0; char *kvmbin = NULL; char *binary = NULL; time_t binary_mtime; virCapsGuestMachinePtr *machines = NULL; int nmachines = 0; struct stat st; unsigned int ncpus; virBitmapPtr qemuCaps = NULL; int ret = -1; /* Check for existance of base emulator, or alternate base * which can be used with magic cpu choice */ binary = virFindFileInPath(info->binary); if (binary == NULL || !virFileIsExecutable(binary)) { VIR_FREE(binary); binary = virFindFileInPath(info->altbinary); } /* Can use acceleration for KVM/KQEMU if * - host & guest arches match * Or * - hostarch is x86_64 and guest arch is i686 * The latter simply needs "-cpu qemu32" */ if (STREQ(info->arch, hostmachine) || (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) { if (access("/dev/kvm", F_OK) == 0) { const char *const kvmbins[] = { "/usr/libexec/qemu-kvm", /* RHEL */ "qemu-kvm", /* Fedora */ "kvm" }; /* Upstream .spec */ for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) { kvmbin = virFindFileInPath(kvmbins[i]); if (!kvmbin) continue; haskvm = 1; if (!binary) binary = kvmbin; break; } } if (access("/dev/kqemu", F_OK) == 0) haskqemu = 1; } if (!binary) return 0; /* Ignore binary if extracting version info fails */ if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0) { ret = 0; goto cleanup; } if (stat(binary, &st) == 0) { binary_mtime = st.st_mtime; } else { char ebuf[1024]; VIR_WARN("Failed to stat %s, most peculiar : %s", binary, virStrerror(errno, ebuf, sizeof(ebuf))); binary_mtime = 0; } if (info->machine) { virCapsGuestMachinePtr machine; if (VIR_ALLOC(machine) < 0) { goto no_memory; } if (!(machine->name = strdup(info->machine))) { VIR_FREE(machine); goto no_memory; } nmachines = 1; if (VIR_ALLOC_N(machines, nmachines) < 0) { VIR_FREE(machine->name); VIR_FREE(machine); goto no_memory; } machines[0] = machine; } else { int probe = 1; if (old_caps && binary_mtime) probe = !qemuCapsGetOldMachines(hvm ? "hvm" : "xen", info->arch, info->wordsize, binary, binary_mtime, old_caps, &machines, &nmachines); if (probe && qemuCapsProbeMachineTypes(binary, &machines, &nmachines) < 0) goto error; } /* We register kvm as the base emulator too, since we can * just give -no-kvm to disable acceleration if required */ if ((guest = virCapabilitiesAddGuest(caps, hvm ? "hvm" : "xen", info->arch, info->wordsize, binary, NULL, nmachines, machines)) == NULL) goto error; machines = NULL; nmachines = 0; guest->arch.defaultInfo.emulator_mtime = binary_mtime; if (caps->host.cpu && qemuCapsProbeCPUModels(binary, NULL, info->arch, &ncpus, NULL) == 0 && ncpus > 0 && !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0)) goto error; if (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) && !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0)) goto error; if (hvm) { if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL) == NULL) goto error; if (haskqemu && virCapabilitiesAddGuestDomain(guest, "kqemu", NULL, NULL, 0, NULL) == NULL) goto error; if (haskvm) { virCapsGuestDomainPtr dom; if (stat(kvmbin, &st) == 0) { binary_mtime = st.st_mtime; } else { char ebuf[1024]; VIR_WARN("Failed to stat %s, most peculiar : %s", binary, virStrerror(errno, ebuf, sizeof(ebuf))); binary_mtime = 0; } if (!STREQ(binary, kvmbin)) { int probe = 1; if (old_caps && binary_mtime) probe = !qemuCapsGetOldMachines("hvm", info->arch, info->wordsize, kvmbin, binary_mtime, old_caps, &machines, &nmachines); if (probe && qemuCapsProbeMachineTypes(kvmbin, &machines, &nmachines) < 0) goto error; } if ((dom = virCapabilitiesAddGuestDomain(guest, "kvm", kvmbin, NULL, nmachines, machines)) == NULL) { goto error; } machines = NULL; nmachines = 0; dom->info.emulator_mtime = binary_mtime; } } else { if (virCapabilitiesAddGuestDomain(guest, "kvm", NULL, NULL, 0, NULL) == NULL) goto error; } 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) goto error; } } ret = 0; cleanup: if (binary == kvmbin) { /* don't double free */ VIR_FREE(binary); } else { VIR_FREE(binary); VIR_FREE(kvmbin); } qemuCapsFree(qemuCaps); return ret; no_memory: virReportOOMError(); error: virCapabilitiesFreeMachines(machines, nmachines); goto cleanup; }
static int dnsmasqCapsRefreshInternal(dnsmasqCapsPtr caps, bool force) { int ret = -1; struct stat sb; virCommandPtr cmd = NULL; char *help = NULL, *version = NULL, *complete = NULL; if (!caps || caps->noRefresh) return 0; if (stat(caps->binaryPath, &sb) < 0) { virReportSystemError(errno, _("Cannot check dnsmasq binary %s"), caps->binaryPath); return -1; } if (!force && caps->mtime == sb.st_mtime) return 0; caps->mtime = sb.st_mtime; /* 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 (!virFileIsExecutable(caps->binaryPath)) { virReportSystemError(errno, _("dnsmasq binary %s is not executable"), caps->binaryPath); goto cleanup; } cmd = virCommandNewArgList(caps->binaryPath, "--version", NULL); virCommandSetOutputBuffer(cmd, &version); virCommandAddEnvPassCommon(cmd); virCommandClearCaps(cmd); if (virCommandRun(cmd, NULL) < 0) { virReportSystemError(errno, _("failed to run '%s --version': %s"), caps->binaryPath, version); goto cleanup; } virCommandFree(cmd); cmd = virCommandNewArgList(caps->binaryPath, "--help", NULL); virCommandSetOutputBuffer(cmd, &help); virCommandAddEnvPassCommon(cmd); virCommandClearCaps(cmd); if (virCommandRun(cmd, NULL) < 0) { virReportSystemError(errno, _("failed to run '%s --help': %s"), caps->binaryPath, help); goto cleanup; } if (virAsprintf(&complete, "%s\n%s", version, help) < 0) goto cleanup; ret = dnsmasqCapsSetFromBuffer(caps, complete); cleanup: virCommandFree(cmd); VIR_FREE(help); VIR_FREE(version); VIR_FREE(complete); return ret; }