Beispiel #1
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;
}
Beispiel #2
0
char *
virISCSIGetSession(const char *devpath,
                   bool probe)
{
    /*
     * # iscsiadm --mode session
     * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b
     * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a
     *
     * Pull out 2nd and 4th fields
     */
    const char *regexes[] = {
        "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+).*$"
    };
    int vars[] = {
        2,
    };
    struct virISCSISessionData cbdata = {
        .session = NULL,
        .devpath = devpath,
    };
    char *error = NULL;
    int exitstatus = 0;

    virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode",
                                             "session", NULL);
    virCommandSetErrorBuffer(cmd, &error);

    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virISCSIExtractSession,
                           &cbdata, NULL, &exitstatus) < 0)
        goto cleanup;

    if (cbdata.session == NULL && !probe)
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find iscsiadm session: %s"),
                       NULLSTR(error));

 cleanup:
    VIR_FREE(error);
    virCommandFree(cmd);
    return cbdata.session;
}
Beispiel #3
0
static int virNetSocketForkDaemon(const char *binary)
{
    int ret;
    virCommandPtr cmd = virCommandNewArgList(binary,
                                             "--timeout=30",
                                             NULL);

    virCommandAddEnvPassCommon(cmd);
    virCommandAddEnvPass(cmd, "XDG_CACHE_HOME");
    virCommandAddEnvPass(cmd, "XDG_CONFIG_HOME");
    virCommandAddEnvPass(cmd, "XDG_RUNTIME_DIR");
    virCommandClearCaps(cmd);
    virCommandDaemonize(cmd);
    ret = virCommandRun(cmd, NULL);
    virCommandFree(cmd);
    return ret;
}
Beispiel #4
0
/**
 * @conn connection to report errors against
 * @pool storage pool to unmount
 *
 * Ensure that a FS storage pool is not mounted on its target location.
 * If already unmounted, this is a no-op
 *
 * Returns 0 if successfully unmounted, -1 on error
 */
static int
virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
    virCommandPtr cmd = NULL;
    int ret = -1;
    int rc;

    if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
        if (pool->def->source.nhost != 1) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Expected exactly 1 host for the storage pool"));
            return -1;
        }
        if (pool->def->source.hosts[0].name == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("missing source host"));
            return -1;
        }
        if (pool->def->source.dir == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("missing source dir"));
            return -1;
        }
    } else {
        if (pool->def->source.ndevice != 1) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("missing source device"));
            return -1;
        }
    }

    /* Short-circuit if already unmounted */
    if ((rc = virStorageBackendFileSystemIsMounted(pool)) != 1)
        return rc;

    cmd = virCommandNewArgList(UMOUNT,
                               pool->def->target.path,
                               NULL);

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

    ret = 0;
cleanup:
    virCommandFree(cmd);
    return ret;
}
static int
virStorageBackendSheepdogRefreshAllVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                                       virStoragePoolObjPtr pool)
{
    int ret = -1;
    char *output = NULL;
    char **lines = NULL;
    char **cells = NULL;
    size_t i;

    virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "list", "-r", NULL);
    virStorageBackendSheepdogAddHostArg(cmd, pool);
    virCommandSetOutputBuffer(cmd, &output);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    lines = virStringSplit(output, "\n", 0);
    if (lines == NULL)
        goto cleanup;

    for (i = 0; lines[i]; i++) {
        const char *line = lines[i];
        if (line == NULL)
            break;

        cells = virStringSplit(line, " ", 0);

        if (cells != NULL && virStringListLength(cells) > 2) {
            if (virStorageBackendSheepdogAddVolume(conn, pool, cells[1]) < 0)
                goto cleanup;
        }

        virStringFreeList(cells);
        cells = NULL;
    }

    ret = 0;

 cleanup:
    virCommandFree(cmd);
    virStringFreeList(lines);
    virStringFreeList(cells);
    VIR_FREE(output);
    return ret;
}
static char *
virStorageBackendISCSISession(virStoragePoolObjPtr pool,
                              int probe)
{
    /*
     * # iscsiadm --mode session
     * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b
     * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a
     *
     * Pull out 2nd and 4th fields
     */
    const char *regexes[] = {
        "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+)\\s*$"
    };
    int vars[] = {
        2,
    };
    char *session = NULL;

    virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "session", NULL);

    /* Note that we ignore the exitstatus.  Older versions of iscsiadm tools
     * returned an exit status of > 0, even if they succeeded.  We will just
     * rely on whether session got filled in properly.
     */
    if (virStorageBackendRunProgRegex(pool,
                                      cmd,
                                      1,
                                      regexes,
                                      vars,
                                      virStorageBackendISCSIExtractSession,
                                      &session, NULL) < 0)
        goto cleanup;

    if (session == NULL &&
        !probe) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot find session"));
        goto cleanup;
    }

cleanup:
    virCommandFree(cmd);
    return session;
}
Beispiel #7
0
/* 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;
}
Beispiel #8
0
static int
virConnectAuthGainPolkit(const char *privilege)
{
    virCommandPtr cmd;
    int ret = -1;

    if (geteuid() == 0)
        return 0;

    cmd = virCommandNewArgList(POLKIT_AUTH, "--obtain", privilege, NULL);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    virCommandFree(cmd);
    return ret;
}
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;

}
Beispiel #10
0
static int
virStorageBackendSheepdogRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                     virStoragePoolObjPtr pool)
{
    int ret;
    char *output = NULL;
    virCommandPtr cmd;

    cmd = virCommandNewArgList(COLLIE, "node", "info", "-r", NULL);
    virStorageBackendSheepdogAddHostArg(cmd, pool);
    virCommandSetOutputBuffer(cmd, &output);
    ret = virCommandRun(cmd, NULL);
    if (ret == 0)
        ret = virStorageBackendSheepdogParseNodeInfo(pool->def, output);

    virCommandFree(cmd);
    VIR_FREE(output);
    return ret;
}
Beispiel #11
0
static int openvzListDomains(virConnectPtr conn ATTRIBUTE_UNUSED,
                             int *ids, int nids) {
    int got = 0;
    int veid;
    int outfd = -1;
    int rc = -1;
    int ret;
    char buf[32];
    char *endptr;
    virCommandPtr cmd = virCommandNewArgList(VZLIST, "-ovpsid", "-H" , NULL);

    virCommandSetOutputFD(cmd, &outfd);
    if (virCommandRunAsync(cmd, NULL) < 0)
        goto cleanup;

    while (got < nids) {
        ret = openvz_readline(outfd, buf, 32);
        if (!ret)
            break;
        if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) {
            openvzError(VIR_ERR_INTERNAL_ERROR,
                        _("Could not parse VPS ID %s"), buf);
            continue;
        }
        ids[got] = veid;
        got ++;
    }

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

    if (VIR_CLOSE(outfd) < 0) {
        virReportSystemError(errno, "%s", _("failed to close file"));
        goto cleanup;
    }

    rc = got;
cleanup:
    VIR_FORCE_CLOSE(outfd);
    virCommandFree(cmd);
    return rc;
}
/*
 * @sourceList: Pointer to a storage pool source list
 *
 * Use the pvs command to fill the list of pv_name and vg_name associated
 * into the passed sourceList.
 *
 * Returns 0 if successful, -1 and sets error on failure
 */
static int
virStorageBackendLogicalGetPoolSources(virStoragePoolSourceListPtr sourceList)
{
    /*
     * # pvs --noheadings -o pv_name,vg_name
     *   /dev/sdb
     *   /dev/sdc VolGroup00
     */
    const char *regexes[] = {
        "^\\s*(\\S+)\\s+(\\S+)\\s*$"
    };
    int vars[] = {
        2
    };
    virCommandPtr cmd;
    int ret = -1;

    /*
     * NOTE: ignoring errors here; this is just to "touch" any logical volumes
     * that might be hanging around, so if this fails for some reason, the
     * worst that happens is that scanning doesn't pick everything up
     */
    cmd = virCommandNew(VGSCAN);
    if (virCommandRun(cmd, NULL) < 0)
        VIR_WARN("Failure when running vgscan to refresh physical volumes");
    virCommandFree(cmd);

    cmd = virCommandNewArgList(PVS,
                               "--noheadings",
                               "-o", "pv_name,vg_name",
                               NULL);
    if (virCommandRunRegex(cmd, 1, regexes, vars,
                           virStorageBackendLogicalFindPoolSourcesFunc,
                           sourceList, "pvs") < 0)
        goto cleanup;
    ret = 0;

 cleanup:
    virCommandFree(cmd);
    return ret;
}
static char *
virStorageBackendISCSISession(virStoragePoolObjPtr pool,
                              bool probe)
{
    /*
     * # iscsiadm --mode session
     * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b
     * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a
     *
     * Pull out 2nd and 4th fields
     */
    const char *regexes[] = {
        "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+).*$"
    };
    int vars[] = {
        2,
    };
    char *session = NULL;

    virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "session", NULL);

    if (virStorageBackendRunProgRegex(pool,
                                      cmd,
                                      1,
                                      regexes,
                                      vars,
                                      virStorageBackendISCSIExtractSession,
                                      &session, NULL) < 0)
        goto cleanup;

    if (session == NULL &&
        !probe) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot find session"));
        goto cleanup;
    }

cleanup:
    virCommandFree(cmd);
    return session;
}
Beispiel #14
0
static int
openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason)
{
    virCommandPtr cmd;
    char *outbuf;
    char *line;
    int state;
    int ret = -1;

    cmd = virCommandNewArgList(VZLIST, vm->def->name, "-ostatus", "-H", NULL);
    virCommandSetOutputBuffer(cmd, &outbuf);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if ((line = strchr(outbuf, '\n')) == NULL) {
        openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("Failed to parse vzlist output"));
        goto cleanup;
    }
    *line++ = '\0';

    state = virDomainObjGetState(vm, reason);

    if (STREQ(outbuf, "running")) {
        /* There is no way to detect whether a domain is paused or not
         * with vzlist */
        if (state == VIR_DOMAIN_PAUSED)
            *status = state;
        else
            *status = VIR_DOMAIN_RUNNING;
    } else {
        *status = VIR_DOMAIN_SHUTOFF;
    }

    ret = 0;

cleanup:
    virCommandFree(cmd);
    VIR_FREE(outbuf);
    return ret;
}
Beispiel #15
0
/*
 * load (add) a profile. Will create one if necessary
 */
static int
load_profile(virSecurityManagerPtr mgr,
             const char *profile,
             virDomainDefPtr def,
             const char *fn,
             bool append)
{
    int rc = -1;
    bool create = true;
    char *xml = NULL;
    virCommandPtr cmd = NULL;
    const char *probe = virSecurityManagerGetAllowDiskFormatProbing(mgr)
        ? "1" : "0";

    xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE);
    if (!xml)
        goto cleanup;

    if (profile_status_file(profile) >= 0)
        create = false;

    cmd = virCommandNewArgList(VIRT_AA_HELPER, "-p", probe,
                               create ? "-c" : "-r",
                               "-u", profile, NULL);
    if (!create && fn) {
        if (append) {
            virCommandAddArgList(cmd, "-F", fn, NULL);
        } else {
            virCommandAddArgList(cmd, "-f", fn, NULL);
        }
    }

    virCommandSetInputBuffer(cmd, xml);
    rc = virCommandRun(cmd, NULL);

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

    return rc;
}
Beispiel #16
0
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;
}
Beispiel #18
0
static int
virStorageBackendZFSDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED,
                               virStoragePoolObjPtr pool,
                               unsigned int flags)
{
    virCommandPtr cmd = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

    cmd = virCommandNewArgList(ZPOOL, "destroy",
                               pool->def->source.name, NULL);

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

    ret = 0;

 cleanup:
    virCommandFree(cmd);
    return ret;
}
static int
virStorageBackendFileSystemNetFindNFSPoolSources(virNetfsDiscoverState *state)
{
    int ret = -1;

    /*
     *  # showmount --no-headers -e HOSTNAME
     *  /tmp   *
     *  /A dir demo1.foo.bar,demo2.foo.bar
     *
     * Extract directory name (including possible interior spaces ...).
     */

    const char *regexes[] = {
        "^(/.*\\S) +\\S+$"
    };
    int vars[] = {
        1
    };

    virCommandPtr cmd = NULL;

    cmd = virCommandNewArgList(SHOWMOUNT,
                               "--no-headers",
                               "--exports",
                               state->host,
                               NULL);

    if (virCommandRunRegex(cmd, 1, regexes, vars,
                           virStorageBackendFileSystemNetFindPoolSourcesFunc,
                           state, NULL) < 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;
    virCommandPtr destroy_cmd = virCommandNewArgList(ZFS, "destroy", NULL);

    virCheckFlags(0, -1);

    virCommandAddArgFormat(destroy_cmd, "%s/%s",
                           pool->def->source.name, vol->name);

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

    ret = 0;
 cleanup:
    virCommandFree(destroy_cmd);
    return ret;
}
Beispiel #21
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;
}
Beispiel #22
0
static int
openvzExtractVersionInfo(const char *cmdstr, int *retversion)
{
    int ret = -1;
    unsigned long version;
    char *help = NULL;
    char *tmp;
    virCommandPtr cmd = virCommandNewArgList(cmdstr, "--help", NULL);

    if (retversion)
        *retversion = 0;

    virCommandAddEnvString(cmd, "LC_ALL=C");
    virCommandSetOutputBuffer(cmd, &help);

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

    tmp = help;

    /* expected format: vzctl version <major>.<minor>.<micro> */
    if ((tmp = STRSKIP(tmp, "vzctl version ")) == NULL)
        goto cleanup;

    if (virParseVersionString(tmp, &version, true) < 0)
        goto cleanup;

    if (retversion)
        *retversion = version;

    ret = 0;

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

    return ret;
}
Beispiel #23
0
static int
virStorageBackendSheepdogRefreshVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                                    virStoragePoolObjPtr pool,
                                    virStorageVolDefPtr vol)
{
    int ret;
    char *output = NULL;

    virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "list", vol->name, "-r", NULL);
    virStorageBackendSheepdogAddHostArg(cmd, pool);
    virCommandSetOutputBuffer(cmd, &output);
    ret = virCommandRun(cmd, NULL);

    if (ret < 0)
        goto cleanup;

    if ((ret = virStorageBackendSheepdogParseVdiList(vol, output)) < 0)
        goto cleanup;

    vol->type = VIR_STORAGE_VOL_NETWORK;

    VIR_FREE(vol->key);
    if (virAsprintf(&vol->key, "%s/%s",
                    pool->def->source.name, vol->name) == -1) {
        virReportOOMError();
        goto cleanup;
    }

    VIR_FREE(vol->target.path);
    if (!(vol->target.path = strdup(vol->name))) {
        virReportOOMError();
        goto cleanup;
    }

cleanup:
    virCommandFree(cmd);
    return ret;
}
Beispiel #24
0
int
vmwareExtractVersion(struct vmware_driver *driver)
{
    unsigned long version = 0;
    char *tmp;
    int ret = -1;
    virCommandPtr cmd;
    char * outbuf = NULL;
    const char * bin = (driver->type == TYPE_PLAYER) ? "vmplayer" : "vmware";
    const char * pattern = (driver->type == TYPE_PLAYER) ?
                "VMware Player " : "VMware Workstation ";

    cmd = virCommandNewArgList(bin, "-v", NULL);
    virCommandSetOutputBuffer(cmd, &outbuf);

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

    if ((tmp = STRSKIP(outbuf, pattern)) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse %s version"), bin);
        goto cleanup;
    }

    if (virParseVersionString(tmp, &version, false) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("version parsing error"));
        goto cleanup;
    }

    driver->version = version;
    ret = 0;

cleanup:
    virCommandFree(cmd);
    VIR_FREE(outbuf);
    return ret;
}
static int
virStorageBackendVzPoolStart(virStoragePoolObjPtr pool)
{
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    VIR_AUTOFREE(char *) grp_name = NULL;
    VIR_AUTOFREE(char *) usr_name = NULL;
    VIR_AUTOFREE(char *) mode = NULL;
    VIR_AUTOPTR(virCommand) cmd = NULL;

    /* Check the permissions */
    if (def->target.perms.mode == (mode_t)-1)
        def->target.perms.mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE;
    if (def->target.perms.uid == (uid_t)-1)
        def->target.perms.uid = geteuid();
    if (def->target.perms.gid == (gid_t)-1)
        def->target.perms.gid = getegid();

    /* Convert ids to names because vstorage uses names */

    if (!(grp_name = virGetGroupName(def->target.perms.gid)))
        return -1;

    if (!(usr_name = virGetUserName(def->target.perms.uid)))
        return -1;

    if (virAsprintf(&mode, "%o", def->target.perms.mode) < 0)
        return -1;

    cmd = virCommandNewArgList(VSTORAGE_MOUNT,
                               "-c", def->source.name,
                               def->target.path,
                               "-m", mode,
                               "-g", grp_name, "-u", usr_name,
                               NULL);

    return virCommandRun(cmd, NULL);
}
static void
testCleanupImages(void)
{
    virCommandPtr cmd;

    VIR_FREE(qemuimg);
    VIR_FREE(absraw);
    VIR_FREE(canonraw);
    VIR_FREE(absqcow2);
    VIR_FREE(canonqcow2);
    VIR_FREE(abswrap);
    VIR_FREE(absqed);
    VIR_FREE(abslink2);

    if (chdir(abs_builddir) < 0) {
        fprintf(stderr, "unable to return to correct directory, refusing to "
                "clean up %s\n", datadir);
        return;
    }

    cmd = virCommandNewArgList("rm", "-rf", datadir, NULL);
    ignore_value(virCommandRun(cmd, NULL));
    virCommandFree(cmd);
}
Beispiel #27
0
static char *
virStorageBackendSCSISerial(const char *dev)
{
    char *serial = NULL;
#ifdef HAVE_UDEV
    virCommandPtr cmd = virCommandNewArgList(
        "/lib/udev/scsi_id",
        "--replace-whitespace",
        "--whitelisted",
        "--device", dev,
        NULL
        );

    /* Run the program and capture its output */
    virCommandSetOutputBuffer(cmd, &serial);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;
#endif

    if (serial && STRNEQ(serial, "")) {
        char *nl = strchr(serial, '\n');
        if (nl)
            *nl = '\0';
    } else {
        VIR_FREE(serial);
        if (!(serial = strdup(dev)))
            virReportOOMError();
    }

#ifdef HAVE_UDEV
cleanup:
    virCommandFree(cmd);
#endif

    return serial;
}
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;
}
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;
}
static int
mymain(void)
{
    int ret;
    virCommandPtr cmd = NULL;

    /* Prep some files with qemu-img; if that is not found on PATH, or
     * if it lacks support for qcow2 and qed, skip this test.  */
    if ((ret = testPrepImages()) != 0)
        return ret;

#define TEST_ONE_CHAIN(id, start, format, chain, flags)              \
    do {                                                             \
        struct testChainData data = {                                \
            start, format, chain, ARRAY_CARDINALITY(chain), flags,   \
        };                                                           \
        if (virtTestRun("Storage backing chain " id, 1,              \
                        testStorageChain, &data) < 0)                \
            ret = -1;                                                \
    } while (0)

#define TEST_CHAIN(id, relstart, absstart, format, chain1, flags1,   \
                   chain2, flags2, chain3, flags3, chain4, flags4)   \
    do {                                                             \
        TEST_ONE_CHAIN(#id "a", relstart, format, chain1, flags1);   \
        TEST_ONE_CHAIN(#id "b", relstart, format, chain2, flags2);   \
        TEST_ONE_CHAIN(#id "c", absstart, format, chain3, flags3);   \
        TEST_ONE_CHAIN(#id "d", absstart, format, chain4, flags4);   \
    } while (0)

    /* Expected details about files in chains */
    const testFileData raw = {
        NULL, NULL, NULL, VIR_STORAGE_FILE_NONE, false, 0, false,
    };
    const testFileData qcow2_relback_relstart = {
        canonraw, "raw", ".", VIR_STORAGE_FILE_RAW, true, 1024, false,
    };
    const testFileData qcow2_relback_absstart = {
        canonraw, "raw", datadir, VIR_STORAGE_FILE_RAW, true, 1024, false,
    };
    const testFileData qcow2_absback = {
        canonraw, absraw, datadir, VIR_STORAGE_FILE_RAW, true, 1024, false,
    };
    const testFileData qcow2_as_probe = {
        canonraw, absraw, datadir, VIR_STORAGE_FILE_AUTO, true, 1024, false,
    };
    const testFileData qcow2_bogus = {
        NULL, datadir "/bogus", datadir, VIR_STORAGE_FILE_NONE,
        false, 1024, false,
    };
    const testFileData qcow2_protocol = {
        "nbd:example.org:6000", NULL, NULL, VIR_STORAGE_FILE_RAW,
        false, 1024, false,
    };
    const testFileData wrap = {
        canonqcow2, absqcow2, datadir, VIR_STORAGE_FILE_QCOW2,
        true, 1024, false,
    };
    const testFileData wrap_as_raw = {
        canonqcow2, absqcow2, datadir, VIR_STORAGE_FILE_RAW,
        true, 1024, false,
    };
    const testFileData wrap_as_probe = {
        canonqcow2, absqcow2, datadir, VIR_STORAGE_FILE_AUTO,
        true, 1024, false,
    };
    const testFileData qed = {
        canonraw, absraw, datadir, VIR_STORAGE_FILE_RAW,
        true, 1024, false,
    };
    const testFileData link1_rel = {
        canonraw, "../raw", "sub/../sub/..", VIR_STORAGE_FILE_RAW,
        true, 1024, false,
    };
    const testFileData link1_abs = {
        canonraw, "../raw", datadir "/sub/../sub/..", VIR_STORAGE_FILE_RAW,
        true, 1024, false,
    };
    const testFileData link2_rel = {
        canonqcow2, "../sub/link1", "sub/../sub", VIR_STORAGE_FILE_QCOW2,
        true, 1024, false,
    };
    const testFileData link2_abs = {
        canonqcow2, "../sub/link1", datadir "/sub/../sub",
        VIR_STORAGE_FILE_QCOW2, true, 1024, false,
    };

    /* The actual tests, in several groups. */

    /* Missing file */
    const testFileData chain0[] = { };
    TEST_ONE_CHAIN("0", "bogus", VIR_STORAGE_FILE_RAW, chain0, EXP_FAIL);

    /* Raw image, whether with right format or no specified format */
    const testFileData chain1[] = { raw };
    TEST_CHAIN(1, "raw", absraw, VIR_STORAGE_FILE_RAW,
               chain1, EXP_PASS,
               chain1, ALLOW_PROBE | EXP_PASS,
               chain1, EXP_PASS,
               chain1, ALLOW_PROBE | EXP_PASS);
    TEST_CHAIN(2, "raw", absraw, VIR_STORAGE_FILE_AUTO,
               chain1, EXP_PASS,
               chain1, ALLOW_PROBE | EXP_PASS,
               chain1, EXP_PASS,
               chain1, ALLOW_PROBE | EXP_PASS);

    /* Qcow2 file with relative raw backing, format provided */
    const testFileData chain3a[] = { qcow2_relback_relstart, raw };
    const testFileData chain3c[] = { qcow2_relback_absstart, raw };
    const testFileData chain4a[] = { raw };
    TEST_CHAIN(3, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
               chain3a, EXP_PASS,
               chain3a, ALLOW_PROBE | EXP_PASS,
               chain3c, EXP_PASS,
               chain3c, ALLOW_PROBE | EXP_PASS);
    TEST_CHAIN(4, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO,
               chain4a, EXP_PASS,
               chain3a, ALLOW_PROBE | EXP_PASS,
               chain4a, EXP_PASS,
               chain3c, ALLOW_PROBE | EXP_PASS);

    /* Rewrite qcow2 file to use absolute backing name */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "raw", "-b", absraw, "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Qcow2 file with raw as absolute backing, backing format provided */
    const testFileData chain5[] = { qcow2_absback, raw };
    const testFileData chain6[] = { raw };
    TEST_CHAIN(5, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
               chain5, EXP_PASS,
               chain5, ALLOW_PROBE | EXP_PASS,
               chain5, EXP_PASS,
               chain5, ALLOW_PROBE | EXP_PASS);
    TEST_CHAIN(6, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO,
               chain6, EXP_PASS,
               chain5, ALLOW_PROBE | EXP_PASS,
               chain6, EXP_PASS,
               chain5, ALLOW_PROBE | EXP_PASS);

    /* Wrapped file access */
    const testFileData chain7[] = { wrap, qcow2_absback, raw };
    TEST_CHAIN(7, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2,
               chain7, EXP_PASS,
               chain7, ALLOW_PROBE | EXP_PASS,
               chain7, EXP_PASS,
               chain7, ALLOW_PROBE | EXP_PASS);

    /* Rewrite qcow2 and wrap file to omit backing file type */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-b", absraw, "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-b", absqcow2, "wrap", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Qcow2 file with raw as absolute backing, backing format omitted */
    const testFileData chain8a[] = { wrap_as_raw, raw };
    const testFileData chain8b[] = { wrap_as_probe, qcow2_as_probe, raw };
    TEST_CHAIN(8, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2,
               chain8a, EXP_PASS,
               chain8b, ALLOW_PROBE | EXP_PASS,
               chain8a, EXP_PASS,
               chain8b, ALLOW_PROBE | EXP_PASS);

    /* Rewrite qcow2 to a missing backing file, with backing type */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", datadir "/bogus",
                               "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Qcow2 file with missing backing file but specified type */
    const testFileData chain9[] = { qcow2_bogus };
    TEST_CHAIN(9, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
               chain9, EXP_WARN,
               chain9, ALLOW_PROBE | EXP_WARN,
               chain9, EXP_WARN,
               chain9, ALLOW_PROBE | EXP_WARN);

    /* Rewrite qcow2 to a missing backing file, without backing type */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-b", datadir "/bogus", "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Qcow2 file with missing backing file and no specified type */
    const testFileData chain10[] = { qcow2_bogus };
    TEST_CHAIN(10, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
               chain10, EXP_WARN,
               chain10, ALLOW_PROBE | EXP_WARN,
               chain10, EXP_WARN,
               chain10, ALLOW_PROBE | EXP_WARN);

    /* Rewrite qcow2 to use an nbd: protocol as backend */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "raw", "-b", "nbd:example.org:6000",
                               "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Qcow2 file with backing protocol instead of file */
    const testFileData chain11[] = { qcow2_protocol };
    TEST_CHAIN(11, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
               chain11, EXP_PASS,
               chain11, ALLOW_PROBE | EXP_PASS,
               chain11, EXP_PASS,
               chain11, ALLOW_PROBE | EXP_PASS);

    /* qed file */
    const testFileData chain12a[] = { raw };
    const testFileData chain12b[] = { qed, raw };
    TEST_CHAIN(12, "qed", absqed, VIR_STORAGE_FILE_AUTO,
               chain12a, EXP_PASS,
               chain12b, ALLOW_PROBE | EXP_PASS,
               chain12a, EXP_PASS,
               chain12b, ALLOW_PROBE | EXP_PASS);

    /* Rewrite qcow2 and wrap file to use backing names relative to a
     * symlink from a different directory */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "raw", "-b", "../raw", "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", "../sub/link1", "wrap",
                               NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Behavior of symlinks to qcow2 with relative backing files */
    const testFileData chain13a[] = { link2_rel, link1_rel, raw };
    const testFileData chain13c[] = { link2_abs, link1_abs, raw };
    TEST_CHAIN(13, "sub/link2", abslink2, VIR_STORAGE_FILE_QCOW2,
               chain13a, EXP_PASS,
               chain13a, ALLOW_PROBE | EXP_PASS,
               chain13c, EXP_PASS,
               chain13c, ALLOW_PROBE | EXP_PASS);

    /* Final cleanup */
    testCleanupImages();
    virCommandFree(cmd);

    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}