Esempio n. 1
0
static int virNetSocketForkDaemon(const char *binary)
{
    int ret;
    virCommandPtr cmd = virCommandNewArgList(binary,
                                             "--timeout=30",
                                             NULL);

    virCommandAddEnvPassCommon(cmd);
    virCommandClearCaps(cmd);
    virCommandDaemonize(cmd);
    ret = virCommandRun(cmd, NULL);
    virCommandFree(cmd);
    return ret;
}
Esempio n. 2
0
int
qemuCapsProbeCPUModels(const char *qemu,
                       virBitmapPtr qemuCaps,
                       const char *arch,
                       unsigned int *count,
                       const char ***cpus)
{
    char *output = NULL;
    int ret = -1;
    qemuCapsParseCPUModels parse;
    virCommandPtr cmd;

    if (count)
        *count = 0;
    if (cpus)
        *cpus = NULL;

    if (STREQ(arch, "i686") || STREQ(arch, "x86_64"))
        parse = qemuCapsParseX86Models;
    else if (STREQ(arch, "ppc64"))
        parse = qemuCapsParsePPCModels;
    else {
        VIR_DEBUG("don't know how to parse %s CPU models", arch);
        return 0;
    }

    cmd = virCommandNewArgList(qemu, "-cpu", "?", NULL);
    if (qemuCapsGet(qemuCaps, QEMU_CAPS_NODEFCONFIG))
        virCommandAddArg(cmd, "-nodefconfig");
    virCommandAddEnvPassCommon(cmd);
    virCommandSetOutputBuffer(cmd, &output);
    virCommandClearCaps(cmd);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if (parse(output, count, cpus) < 0)
        goto cleanup;

    ret = 0;

cleanup:
    VIR_FREE(output);
    virCommandFree(cmd);

    return ret;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
/**
 * 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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
/*
 * 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;
}
Esempio n. 7
0
/*
 * qemuTPMEmulatorRunSetup
 *
 * @storagepath: path to the directory for TPM state
 * @vmname: the name of the VM
 * @vmuuid: the UUID of the VM
 * @privileged: whether we are running in privileged mode
 * @swtpm_user: The userid to switch to when setting up the TPM;
 *              typically this should be the uid of 'tss' or 'root'
 * @swtpm_group: The group id to switch to
 * @logfile: The file to write the log into; it must be writable
 *           for the user given by userid or 'tss'
 * @tpmversion: The version of the TPM, either a TPM 1.2 or TPM 2
 *
 * Setup the external swtpm by creating endorsement key and
 * certificates for it.
 */
static int
qemuTPMEmulatorRunSetup(const char *storagepath,
                        const char *vmname,
                        const unsigned char *vmuuid,
                        bool privileged,
                        uid_t swtpm_user,
                        gid_t swtpm_group,
                        const char *logfile,
                        const virDomainTPMVersion tpmversion)
{
    virCommandPtr cmd = NULL;
    int exitstatus;
    int ret = -1;
    char uuid[VIR_UUID_STRING_BUFLEN];
    char *vmid = NULL;

    if (!privileged && tpmversion == VIR_DOMAIN_TPM_VERSION_1_2)
        return virFileWriteStr(logfile,
                               _("Did not create EK and certificates since "
                                 "this requires privileged mode for a "
                                 "TPM 1.2\n"), 0600);

    cmd = virCommandNew(swtpm_setup);
    if (!cmd)
        goto cleanup;

    virUUIDFormat(vmuuid, uuid);
    if (virAsprintf(&vmid, "%s:%s", vmname, uuid) < 0)
        goto cleanup;

    virCommandSetUID(cmd, swtpm_user);
    virCommandSetGID(cmd, swtpm_group);

    switch (tpmversion) {
    case VIR_DOMAIN_TPM_VERSION_1_2:
        break;
    case VIR_DOMAIN_TPM_VERSION_2_0:
        virCommandAddArgList(cmd, "--tpm2", NULL);
        break;
    case VIR_DOMAIN_TPM_VERSION_DEFAULT:
    case VIR_DOMAIN_TPM_VERSION_LAST:
        break;
    }


    virCommandAddArgList(cmd,
                         "--tpm-state", storagepath,
                         "--vmid", vmid,
                         "--logfile", logfile,
                         "--createek",
                         "--create-ek-cert",
                         "--create-platform-cert",
                         "--lock-nvram",
                         "--not-overwrite",
                         NULL);

    virCommandClearCaps(cmd);

    if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not run '%s'. exitstatus: %d; "
                         "Check error log '%s' for details."),
                          swtpm_setup, exitstatus, logfile);
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(vmid);
    virCommandFree(cmd);

    return ret;
}