Пример #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;
}
Пример #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;
}
Пример #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;
}
Пример #4
0
/*
 * 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;
}
Пример #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;
}
Пример #6
0
/**
 * virHookCall:
 * @driver: the driver number (from virHookDriver enum)
 * @id: an id for the object '-' if non available for example on daemon hooks
 * @op: the operation on the id e.g. VIR_HOOK_QEMU_OP_START
 * @sub_op: a sub_operation, currently unused
 * @extra: optional string information
 * @input: extra input given to the script on stdin
 * @output: optional address of variable to store malloced result buffer
 *
 * Implement a hook call, where the external script for the driver is
 * called with the given information. This is a synchronous call, we wait for
 * execution completion. If @output is non-NULL, *output is guaranteed to be
 * allocated after successful virHookCall, and is best-effort allocated after
 * failed virHookCall; the caller is responsible for freeing *output.
 *
 * Returns: 0 if the execution succeeded, 1 if the script was not found or
 *          invalid parameters, and -1 if script returned an error
 */
int
virHookCall(int driver,
            const char *id,
            int op,
            int sub_op,
            const char *extra,
            const char *input,
            char **output)
{
    int ret;
    int exitstatus;
    char *path;
    virCommandPtr cmd;
    const char *drvstr;
    const char *opstr;
    const char *subopstr;

    if (output)
        *output = NULL;

    if ((driver < VIR_HOOK_DRIVER_DAEMON) ||
        (driver >= VIR_HOOK_DRIVER_LAST))
        return 1;

    /*
     * We cache the availability of the script to minimize impact at
     * runtime if no script is defined, this is being reset on SIGHUP
     */
    if ((virHooksFound == -1) ||
        ((driver == VIR_HOOK_DRIVER_DAEMON) &&
         (op == VIR_HOOK_DAEMON_OP_RELOAD ||
         op == VIR_HOOK_DAEMON_OP_SHUTDOWN)))
        virHookInitialize();

    if ((virHooksFound & (1 << driver)) == 0)
        return 1;

    drvstr = virHookDriverTypeToString(driver);

    opstr = NULL;
    switch (driver) {
        case VIR_HOOK_DRIVER_DAEMON:
            opstr = virHookDaemonOpTypeToString(op);
            break;
        case VIR_HOOK_DRIVER_QEMU:
            opstr = virHookQemuOpTypeToString(op);
            break;
        case VIR_HOOK_DRIVER_LXC:
            opstr = virHookLxcOpTypeToString(op);
            break;
    }
    if (opstr == NULL) {
        virHookReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Hook for %s, failed to find operation #%d"),
                           drvstr, op);
        return 1;
    }
    subopstr = virHookSubopTypeToString(sub_op);
    if (subopstr == NULL)
        subopstr = "-";
    if (extra == NULL)
        extra = "-";

    ret = virBuildPath(&path, LIBVIRT_HOOK_DIR, drvstr);
    if ((ret < 0) || (path == NULL)) {
        virHookReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to build path for %s hook"),
                           drvstr);
        return -1;
    }

    cmd = virCommandNewArgList(path, id, opstr, subopstr, extra, NULL);

    virCommandAddEnvPassCommon(cmd);

    if (input)
        virCommandSetInputBuffer(cmd, input);
    if (output)
        virCommandSetOutputBuffer(cmd, output);

    ret = virCommandRun(cmd, &exitstatus);
    if (ret == 0 && exitstatus != 0) {
        virHookReportError(VIR_ERR_HOOK_SCRIPT_FAILED,
                           _("Hook script %s %s failed with error code %d"),
                           path, drvstr, exitstatus);
        ret = -1;
    }

    virCommandFree(cmd);

    VIR_FREE(path);

    return ret;
}
Пример #7
0
/**
 * virHookCall:
 * @driver: the driver number (from virHookDriver enum)
 * @id: an id for the object '-' if non available for example on daemon hooks
 * @op: the operation on the id e.g. VIR_HOOK_QEMU_OP_START
 * @sub_op: a sub_operation, currently unused
 * @extra: optional string information
 * @input: extra input given to the script on stdin
 * @output: optional address of variable to store malloced result buffer
 *
 * Implement a hook call, where the external script for the driver is
 * called with the given information. This is a synchronous call, we wait for
 * execution completion. If @output is non-NULL, *output is guaranteed to be
 * allocated after successful virHookCall, and is best-effort allocated after
 * failed virHookCall; the caller is responsible for freeing *output.
 *
 * Returns: 0 if the execution succeeded, 1 if the script was not found or
 *          invalid parameters, and -1 if script returned an error
 */
int
virHookCall(int driver,
            const char *id,
            int op,
            int sub_op,
            const char *extra,
            const char *input,
            char **output)
{
    int ret;
    char *path;
    virCommandPtr cmd;
    const char *drvstr;
    const char *opstr;
    const char *subopstr;

    if (output)
        *output = NULL;

    if ((driver < VIR_HOOK_DRIVER_DAEMON) ||
        (driver >= VIR_HOOK_DRIVER_LAST))
        return 1;

    /*
     * We cache the availability of the script to minimize impact at
     * runtime if no script is defined, this is being reset on SIGHUP
     */
    if ((virHooksFound == -1) ||
        ((driver == VIR_HOOK_DRIVER_DAEMON) &&
         (op == VIR_HOOK_DAEMON_OP_RELOAD ||
         op == VIR_HOOK_DAEMON_OP_SHUTDOWN)))
        virHookInitialize();

    if ((virHooksFound & (1 << driver)) == 0)
        return 1;

    drvstr = virHookDriverTypeToString(driver);

    opstr = NULL;
    switch (driver) {
        case VIR_HOOK_DRIVER_DAEMON:
            opstr = virHookDaemonOpTypeToString(op);
            break;
        case VIR_HOOK_DRIVER_QEMU:
            opstr = virHookQemuOpTypeToString(op);
            break;
        case VIR_HOOK_DRIVER_LXC:
            opstr = virHookLxcOpTypeToString(op);
            break;
        case VIR_HOOK_DRIVER_NETWORK:
            opstr = virHookNetworkOpTypeToString(op);
    }
    if (opstr == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Hook for %s, failed to find operation #%d"),
                       drvstr, op);
        return 1;
    }
    subopstr = virHookSubopTypeToString(sub_op);
    if (subopstr == NULL)
        subopstr = "-";
    if (extra == NULL)
        extra = "-";

    if (virBuildPath(&path, LIBVIRT_HOOK_DIR, drvstr) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to build path for %s hook"),
                       drvstr);
        return -1;
    }

    VIR_DEBUG("Calling hook opstr=%s subopstr=%s extra=%s",
              opstr, subopstr, extra);

    cmd = virCommandNewArgList(path, id, opstr, subopstr, extra, NULL);

    virCommandAddEnvPassCommon(cmd);

    if (input)
        virCommandSetInputBuffer(cmd, input);
    if (output)
        virCommandSetOutputBuffer(cmd, output);

    ret = virCommandRun(cmd, NULL);
    if (ret < 0) {
        /* Convert INTERNAL_ERROR into known error.  */
        virErrorPtr err = virGetLastError();
        virReportError(VIR_ERR_HOOK_SCRIPT_FAILED, "%s",
                       err ? err->message : _("unknown error"));
    }

    virCommandFree(cmd);

    VIR_FREE(path);

    return ret;
}