static void
virDomainCapsCPUModelsDispose(void *obj)
{
    virDomainCapsCPUModelsPtr cpuModels = obj;
    size_t i;

    for (i = 0; i < cpuModels->nmodels; i++) {
        VIR_FREE(cpuModels->models[i].name);
        virStringListFree(cpuModels->models[i].blockers);
    }

    VIR_FREE(cpuModels->models);
}
Exemple #2
0
static int testSplit(const void *args)
{
    const struct testSplitData *data = args;
    char **got;
    size_t ntokens;
    size_t exptokens = 0;
    char **tmp1;
    const char **tmp2;
    int ret = -1;

    if (!(got = virStringSplitCount(data->string, data->delim,
                                    data->max_tokens, &ntokens))) {
        VIR_DEBUG("Got no tokens at all");
        return -1;
    }

    tmp1 = got;
    tmp2 = data->tokens;
    while (*tmp1 && *tmp2) {
        if (STRNEQ(*tmp1, *tmp2)) {
            virFilePrintf(stderr, "Mismatch '%s' vs '%s'\n", *tmp1, *tmp2);
            goto cleanup;
        }
        tmp1++;
        tmp2++;
        exptokens++;
    }
    if (*tmp1) {
        virFilePrintf(stderr, "Too many pieces returned\n");
        goto cleanup;
    }
    if (*tmp2) {
        virFilePrintf(stderr, "Too few pieces returned\n");
        goto cleanup;
    }

    if (ntokens != exptokens) {
        virFilePrintf(stderr,
                      "Returned token count (%zu) doesn't match "
                      "expected count (%zu)",
                      ntokens, exptokens);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    virStringListFree(got);

    return ret;
}
static int
virStorageBackendZFSFindVols(virStoragePoolObjPtr pool,
                             virStorageVolDefPtr vol)
{
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    virCommandPtr cmd = NULL;
    char *volumes_list = NULL;
    char **lines = NULL;
    size_t i;

    /**
     * $ zfs list -Hp -t volume -o name,volsize -r test
     * test/vol1       5368709120
     * test/vol3       1073741824
     * test/vol4       1572864000
     * $
     *
     * Arguments description:
     *  -t volume -- we want to see only volumes
     *  -o name,volsize -- limit output to name and volume size
     *  -r -- we want to see all the childer of our pool
     */
    cmd = virCommandNewArgList(ZFS,
                               "list", "-Hp",
                               "-t", "volume", "-r",
                               "-o", "name,volsize,refreservation",
                               def->source.name,
                               NULL);
    virCommandSetOutputBuffer(cmd, &volumes_list);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if (!(lines = virStringSplit(volumes_list, "\n", 0)))
        goto cleanup;

    for (i = 0; lines[i]; i++) {
        if (STREQ(lines[i], ""))
            continue;

        if (virStorageBackendZFSParseVol(pool, vol, lines[i]) < 0)
            continue;
    }

 cleanup:
    virCommandFree(cmd);
    virStringListFree(lines);
    VIR_FREE(volumes_list);

    return 0;
}
Exemple #4
0
static int testAdd(const void *args)
{
    const struct testJoinData *data = args;
    char **list = NULL;
    char *got = NULL;
    int ret = -1;
    size_t i;

    for (i = 0; data->tokens[i]; i++) {
        char **tmp = virStringListAdd((const char **)list, data->tokens[i]);
        if (!tmp)
            goto cleanup;
        virStringListFree(list);
        list = tmp;
        tmp = NULL;
    }

    if (!list &&
        VIR_ALLOC(list) < 0)
        goto cleanup;

    if (!(got = virStringListJoin((const char **)list, data->delim))) {
        VIR_DEBUG("Got no result");
        goto cleanup;
    }

    if (STRNEQ(got, data->string)) {
        virFilePrintf(stderr, "Mismatch '%s' vs '%s'\n", got, data->string);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    virStringListFree(list);
    VIR_FREE(got);
    return ret;
}
Exemple #5
0
static int
lxcNetworkParseDataIPs(const char *name,
                       virConfValuePtr value,
                       lxcNetworkParseData *parseData)
{
    int family = AF_INET;
    char **ipparts = NULL;
    virNetDevIPAddrPtr ip = NULL;

    if (VIR_ALLOC(ip) < 0)
        return -1;

    if (STREQ(name, "ipv6"))
        family = AF_INET6;

    ipparts = virStringSplit(value->str, "/", 2);
    if (virStringListLength((const char * const *)ipparts) != 2 ||
        virSocketAddrParse(&ip->address, ipparts[0], family) < 0 ||
        virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) {

        virReportError(VIR_ERR_INVALID_ARG,
                       _("Invalid CIDR address: '%s'"), value->str);

        virStringListFree(ipparts);
        VIR_FREE(ip);
        return -1;
    }

    virStringListFree(ipparts);

    if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) {
        VIR_FREE(ip);
        return -1;
    }

    return 0;
}
Exemple #6
0
static bool
cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd)
{
    virNodeDevicePtr dev = NULL;
    bool ret = false;
    const char *device_value = NULL;
    char **arr = NULL;
    int narr;
    virshControlPtr priv = ctl->privData;

    if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0)
        return false;

    if (strchr(device_value, ',')) {
        narr = vshStringToArray(device_value, &arr);
        if (narr != 2) {
            vshError(ctl, _("Malformed device value '%s'"), device_value);
            goto cleanup;
        }

        if (!virValidateWWN(arr[0]) || !virValidateWWN(arr[1]))
            goto cleanup;

        dev = virNodeDeviceLookupSCSIHostByWWN(priv->conn, arr[0], arr[1], 0);
    } else {
        dev = virNodeDeviceLookupByName(priv->conn, device_value);
    }

    if (!dev) {
        vshError(ctl, "%s '%s'", _("Could not find matching device"), device_value);
        goto cleanup;
    }

    if (virNodeDeviceDestroy(dev) == 0) {
        vshPrintExtra(ctl, _("Destroyed node device '%s'\n"), device_value);
    } else {
        vshError(ctl, _("Failed to destroy node device '%s'"), device_value);
        goto cleanup;
    }

    ret = true;
 cleanup:
    virStringListFree(arr);
    if (dev)
        virNodeDeviceFree(dev);
    return ret;
}
Exemple #7
0
static void
lxcSetCapDrop(virDomainDefPtr def, virConfPtr properties)
{
    VIR_AUTOFREE(char *) value = NULL;
    char **toDrop = NULL;
    const char *capString;
    size_t i;

    if (virConfGetValueString(properties, "lxc.cap.drop", &value) > 0)
        toDrop = virStringSplit(value, " ", 0);

    for (i = 0; i < VIR_DOMAIN_CAPS_FEATURE_LAST; i++) {
        capString = virDomainCapsFeatureTypeToString(i);
        if (toDrop != NULL &&
            virStringListHasString((const char **)toDrop, capString))
            def->caps_features[i] = VIR_TRISTATE_SWITCH_OFF;
    }

    def->features[VIR_DOMAIN_FEATURE_CAPABILITIES] = VIR_DOMAIN_CAPABILITIES_POLICY_ALLOW;

    virStringListFree(toDrop);
}
Exemple #8
0
/**
 * virStringSearch:
 * @str: string to search
 * @regexp: POSIX Extended regular expression pattern used for matching
 * @max_matches: maximum number of substrings to return
 * @result: pointer to an array to be filled with NULL terminated list of matches
 *
 * Performs a POSIX extended regex search against a string and return all matching substrings.
 * The @result value should be freed with virStringListFree() when no longer
 * required.
 *
 * @code
 *  char *source = "6853a496-1c10-472e-867a-8244937bd6f0
 *                  773ab075-4cd7-4fc2-8b6e-21c84e9cb391
 *                  bbb3c75c-d60f-43b0-b802-fd56b84a4222
 *                  60c04aa1-0375-4654-8d9f-e149d9885273
 *                  4548d465-9891-4c34-a184-3b1c34a26aa8";
 *  char **matches = NULL;
 *  virStringSearch(source,
 *                  "([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
 *                  3,
 *                  &matches);
 *
 *  // matches[0] == "6853a496-1c10-472e-867a-8244937bd6f0";
 *  // matches[1] == "773ab075-4cd7-4fc2-8b6e-21c84e9cb391";
 *  // matches[2] == "bbb3c75c-d60f-43b0-b802-fd56b84a4222"
 *  // matches[3] == NULL;
 *
 *  virStringListFree(matches);
 * @endcode
 *
 * Returns: -1 on error, or number of matches
 */
ssize_t
virStringSearch(const char *str,
                const char *regexp,
                size_t max_matches,
                char ***matches)
{
    regex_t re;
    regmatch_t rem;
    size_t nmatches = 0;
    ssize_t ret = -1;
    int rv = -1;

    *matches = NULL;

    VIR_DEBUG("search '%s' for '%s'", str, regexp);

    if ((rv = regcomp(&re, regexp, REG_EXTENDED)) != 0) {
        char error[100];
        regerror(rv, &re, error, sizeof(error));
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Error while compiling regular expression '%s': %s"),
                       regexp, error);
        return -1;
    }

    if (re.re_nsub != 1) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Regular expression '%s' must have exactly 1 match group, not %zu"),
                       regexp, re.re_nsub);
        goto cleanup;
    }

    /* '*matches' must always be NULL terminated in every iteration
     * of the loop, so start by allocating 1 element
     */
    if (VIR_EXPAND_N(*matches, nmatches, 1) < 0)
        goto cleanup;

    while ((nmatches - 1) < max_matches) {
        char *match;

        if (regexec(&re, str, 1, &rem, 0) != 0)
            break;

        if (VIR_EXPAND_N(*matches, nmatches, 1) < 0)
            goto cleanup;

        if (VIR_STRNDUP(match, str + rem.rm_so,
                        rem.rm_eo - rem.rm_so) < 0)
            goto cleanup;

        VIR_DEBUG("Got '%s'", match);

        (*matches)[nmatches-2] = match;

        str = str + rem.rm_eo;
    }

    ret = nmatches - 1; /* don't count the trailing null */

 cleanup:
    regfree(&re);
    if (ret < 0) {
        virStringListFree(*matches);
        *matches = NULL;
    }
    return ret;
}
static int
virStorageBackendZFSRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                virStoragePoolObjPtr pool ATTRIBUTE_UNUSED)
{
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    virCommandPtr cmd = NULL;
    char *zpool_props = NULL;
    char **lines = NULL;
    char **tokens = NULL;
    size_t i;

    /**
     * $ zpool get -Hp health,size,free,allocated test
     * test    health  ONLINE  -
     * test    size    199715979264    -
     * test    free    198899976704    -
     * test    allocated       816002560       -
     * $
     *
     * Here we just provide a list of properties we want to see
     */
    cmd = virCommandNewArgList(ZPOOL,
                               "get", "-Hp",
                               "health,size,free,allocated",
                               def->source.name,
                               NULL);
    virCommandSetOutputBuffer(cmd, &zpool_props);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if (!(lines = virStringSplit(zpool_props, "\n", 0)))
        goto cleanup;

    for (i = 0; lines[i]; i++) {
        size_t count;
        char *prop_name;

        if (STREQ(lines[i], ""))
            continue;

        virStringListFree(tokens);
        if (!(tokens = virStringSplitCount(lines[i], "\t", 0, &count)))
            goto cleanup;

        if (count != 4)
            continue;

        prop_name = tokens[1];

        if (STREQ(prop_name, "free") || STREQ(prop_name, "size") ||
            STREQ(prop_name, "allocated")) {
            unsigned long long value;
            if (virStrToLong_ull(tokens[2], NULL, 10, &value) < 0)
                goto cleanup;

            if (STREQ(prop_name, "free"))
                def->available = value;
            else if (STREQ(prop_name, "size"))
                def->capacity = value;
            else if (STREQ(prop_name, "allocated"))
                def->allocation = value;
        }
    }

    /* Obtain a list of volumes */
    if (virStorageBackendZFSFindVols(pool, NULL) < 0)
        goto cleanup;

 cleanup:
    virCommandFree(cmd);
    virStringListFree(lines);
    virStringListFree(tokens);
    VIR_FREE(zpool_props);

    return 0;
}
Exemple #10
0
static int
virStorageBackendZFSParseVol(virStoragePoolObjPtr pool,
                             virStorageVolDefPtr vol,
                             const char *volume_string)
{
    int ret = -1;
    char **tokens;
    size_t count;
    char **name_tokens = NULL;
    char *vol_name;
    bool is_new_vol = false;
    virStorageVolDefPtr volume = NULL;
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);

    if (!(tokens = virStringSplitCount(volume_string, "\t", 0, &count)))
        return -1;

    if (count != 3)
        goto cleanup;

    if (!(name_tokens = virStringSplit(tokens[0], "/", 2)))
        goto cleanup;

    vol_name = name_tokens[1];

    if (vol == NULL)
        volume = virStorageVolDefFindByName(pool, vol_name);
    else
        volume = vol;

    if (volume == NULL) {
        if (VIR_ALLOC(volume) < 0)
            goto cleanup;

        is_new_vol = true;
        volume->type = VIR_STORAGE_VOL_BLOCK;

        if (VIR_STRDUP(volume->name, vol_name) < 0)
            goto cleanup;
    }

    if (!volume->key && VIR_STRDUP(volume->key, tokens[0]) < 0)
        goto cleanup;

    if (volume->target.path == NULL) {
        if (virAsprintf(&volume->target.path, "%s/%s",
                        def->target.path, volume->name) < 0)
            goto cleanup;
    }

    if (virStrToLong_ull(tokens[1], NULL, 10, &volume->target.capacity) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volsize reported"));
        goto cleanup;
    }

    if (virStrToLong_ull(tokens[2], NULL, 10, &volume->target.allocation) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed refreservation reported"));
        goto cleanup;
    }

    if (volume->target.allocation < volume->target.capacity)
        volume->target.sparse = true;

    if (is_new_vol && virStoragePoolObjAddVol(pool, volume) < 0)
        goto cleanup;
    volume = NULL;

    ret = 0;
 cleanup:
    virStringListFree(tokens);
    virStringListFree(name_tokens);
    if (is_new_vol)
        virStorageVolDefFree(volume);
    return ret;
}
Exemple #11
0
static int lxctoolsReadFSConfig(lxctoolsConffilePtr conffile, virDomainDefPtr def)
{

    virDomainFSDefPtr fs = NULL;
    char* item_str = NULL;
    size_t tokencnt;
    char** splitlist = NULL;

    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.rootfs.path")) == NULL || item_str[0] == '\0') {
        VIR_WARN("Could not find key lxc.rootfs.path. Trying legacy key lxc.rootfs.");
        if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.rootfs")) == NULL) {
            VIR_ERROR("Could not find key lxc.rootfs");
            goto error;
        }
    }
    if (item_str[0] == '\0') {
        VIR_ERROR("Domain has no rootfs config-item.");
        goto error;
    }
    if (VIR_ALLOC(fs) < 0) {
        VIR_ERROR("Could not allocate for virDomainFSDefPtr fs.");
        goto error;
    }
    fs->type = VIR_DOMAIN_FS_TYPE_MOUNT;
    if (VIR_ALLOC(fs->src) < 0) {
        VIR_ERROR("Could not allocate for virStorageSourcePtr fs->src.");
        goto error;
    }
    splitlist = virStringSplitCount(item_str, ":", 3, &tokencnt);
    
    // Simple path
    if (tokencnt == 1) {
        fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH;
        if (virAsprintf(&fs->src->path, "dir:%s", splitlist[0]) < 0) {
            VIR_ERROR("Could not print string in fs->src->path.");
            goto error;
        }
    // dir
    } else if (tokencnt == 2 && strcmp(splitlist[0], "dir") == 0) {
        fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH;
        if (virAsprintf(&fs->src->path, "%s:%s", splitlist[0], splitlist[1]) < 0) {
            VIR_ERROR("Could not print string in fs->src->path.");
            goto error;
        }
    // overlay or overlayfs
    } else if (tokencnt == 3 && (strcmp(splitlist[0], "overlay") == 0 || strcmp(splitlist[0], "overlayfs") == 0)) {
        // We could add a new FS type like VIR_DOMAIN_FS_DRIVER_TYPE_OVERLAY, but this requires minor changes in the
        // libvirt interface and the qemu driver.
        // Also, we could either save "lowerdir:upperdir" in fs->src or create additional members to hold each seperately
        // splitlist[0] -> overlayfs/overlay
        // splitlist[1] -> lowerdir path
        // splitlist[2] -> upperdir path
        // For now, this implements overlayfs using VIR_DOMAIN_FS_DRIVER_TYPE_PATH and saving "overlayfs:lowerdir:upperdir"
        // in fs->src, which does not require lxctools external changes, but is a little bit ugly.
        fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH;
        if (virAsprintf(&fs->src->path, "%s:%s:%s", splitlist[0], splitlist[1], splitlist[2]) < 0) {
            VIR_ERROR("Could not print string in fs->src->path.");
            goto error;
        }
    } else {
        VIR_ERROR("Domain rootfs type is currently not supported");
        goto error;
    }
    if (VIR_STRDUP(fs->dst, "/") != 1) {
        VIR_ERROR("Could not duplicate string.");
        goto error;
    }
    if (virDomainFSInsert(def, fs) < 0) {
        VIR_ERROR("Could not insert filesystem desc into domain.");
        goto error;
    }
    fs = NULL;
    VIR_FREE(item_str);
    virStringListFree(splitlist);
    splitlist = NULL;

    if ((splitlist = lxctoolsConffileGetItemlist(conffile, "lxc.mount.entry", &tokencnt)) == NULL) {
        goto error;
    }
    if (splitlist[0] != NULL) {
        size_t param_cnt;
        char** params;
        while (tokencnt-- > 0) {
            params = virStringSplitCount(splitlist[tokencnt], " ", 6, &param_cnt);
            if (param_cnt != 6) {
                VIR_ERROR("The following entry has to few parameters: '%s'", splitlist[tokencnt]);
                goto error;
            }
            if (VIR_ALLOC(fs) < 0) {
                VIR_ERROR("Could not allocate for virDomainFSDefPtr fs.");
                goto error;
            }
            if (strcmp(params[2], "none") == 0 && strstr(params[3],"bind") != NULL) {
                fs->type = VIR_DOMAIN_FS_TYPE_MOUNT;
                fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH;
                if (VIR_ALLOC(fs->src) < 0) {
                    VIR_ERROR("Could not allocate for virStorageSourcePtr fs->src.");
                    goto error;
                }
                if (VIR_STRDUP(fs->src->path, params[0]) < 0) {
                    VIR_ERROR("Could not copy src string.");
                    goto error;
                }
                if (virAsprintf(&fs->dst, "/%s", params[1]) < 0) {
                    VIR_ERROR("Could not copy dst string.");
                    goto error;
                }
                if (strstr(params[3], "ro") != NULL) {
                    fs->readonly = true;
                }
                if (virDomainFSInsert(def, fs) < 0) {
                    VIR_ERROR("Could not insert filesystem desc into domain.");
                    goto error;
                }
                fs = NULL;
            }
            VIR_FREE(fs);
            virStringListFree(params);
        }
        virStringListFree(splitlist);
        splitlist = NULL;
    }
    return 0;

error:
    virStringListFree(splitlist);
    splitlist = NULL;
    VIR_FREE(item_str);
    if (fs)
        VIR_FREE(fs->src);
    VIR_FREE(fs);
    return -1;
}
Exemple #12
0
/**
 * virConfGetValueStringList:
 * @conf: the config object
 * @setting: the config entry name
 * @compatString: true to treat string entry as a 1 element list
 * @value: pointer to hold NULL terminated string list
 *
 * Get the string list value of the config name @setting, storing
 * it in @value. If the config entry is not present, then
 * @value will be unmodified. If @compatString is set to true
 * and the value is present as a string, this will be turned into
 * a 1 element list. The returned @value will be NULL terminated
 * if set.
 *
 * Reports an error if the config entry is set but has
 * an unexpected type.
 *
 * Returns: 1 if the value was present, 0 if missing, -1 on error
 */
int virConfGetValueStringList(virConfPtr conf,
                              const char *setting,
                              bool compatString,
                              char ***values)
{
    virConfValuePtr cval = virConfGetValue(conf, setting);
    size_t len;
    virConfValuePtr eval;

    VIR_DEBUG("Get value string list %p %d",
              cval, cval ? cval->type : VIR_CONF_NONE);

    if (!cval)
        return 0;

    virStringListFree(*values);
    *values = NULL;

    switch (cval->type) {
    case VIR_CONF_LIST:
        /* Calc length and check items */
        for (len = 0, eval = cval->list; eval; len++, eval = eval->next) {
            if (eval->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX,
                               _("%s: expected a string list for '%s' parameter"),
                               conf->filename, setting);
                return -1;
            }
        }

        if (VIR_ALLOC_N(*values, len + 1) < 0)
            return -1;

        for (len = 0, eval = cval->list; eval; len++, eval = eval->next) {
            if (VIR_STRDUP((*values)[len], eval->str) < 0) {
                virStringListFree(*values);
                *values = NULL;
                return -1;
            }
        }
        break;

    case VIR_CONF_STRING:
        if (compatString) {
            if (VIR_ALLOC_N(*values, cval->str ? 2 : 1) < 0)
                return -1;
            if (cval->str &&
                VIR_STRDUP((*values)[0], cval->str) < 0) {
                VIR_FREE(*values);
                return -1;
            }
            break;
        }
        /* fallthrough */

    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       compatString ?
                       _("%s: expected a string or string list for '%s' parameter") :
                       _("%s: expected a string list for '%s' parameter"),
                       conf->filename, setting);
        return -1;
    }

    return 1;
}
Exemple #13
0
static int
lxcBlkioDeviceWalkCallback(const char *name, virConfValuePtr value, void *data)
{
    char **parts = NULL;
    virBlkioDevicePtr device = NULL;
    virDomainDefPtr def = data;
    size_t i = 0;
    char *path = NULL;
    int ret = -1;

    if (!STRPREFIX(name, "lxc.cgroup.blkio.") ||
            STREQ(name, "lxc.cgroup.blkio.weight")|| !value->str)
        return 0;

    if (!(parts = lxcStringSplit(value->str)))
        return -1;

    if (!parts[0] || !parts[1]) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("invalid %s value: '%s'"),
                       name, value->str);
        goto cleanup;
    }

    if (virAsprintf(&path, "/dev/block/%s", parts[0]) < 0)
        goto cleanup;

    /* Do we already have a device definition for this path?
     * Get that device or create a new one */
    for (i = 0; !device && i < def->blkio.ndevices; i++) {
        if (STREQ(def->blkio.devices[i].path, path))
            device = &def->blkio.devices[i];
    }
    if (!device) {
        if (VIR_EXPAND_N(def->blkio.devices, def->blkio.ndevices, 1) < 0)
            goto cleanup;
        device = &def->blkio.devices[def->blkio.ndevices - 1];
        device->path = path;
        path = NULL;
    }

    /* Set the value */
    if (STREQ(name, "lxc.cgroup.blkio.device_weight")) {
        if (virStrToLong_ui(parts[1], NULL, 10, &device->weight) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse device weight: '%s'"), parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.read_bps_device")) {
        if (virStrToLong_ull(parts[1], NULL, 10, &device->rbps) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse read_bps_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.write_bps_device")) {
        if (virStrToLong_ull(parts[1], NULL, 10, &device->wbps) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse write_bps_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.read_iops_device")) {
        if (virStrToLong_ui(parts[1], NULL, 10, &device->riops) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse read_iops_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.write_iops_device")) {
        if (virStrToLong_ui(parts[1], NULL, 10, &device->wiops) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse write_iops_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else {
        VIR_WARN("Unhandled blkio tune config: %s", name);
    }

    ret = 0;

 cleanup:
    virStringListFree(parts);
    VIR_FREE(path);

    return ret;
}
Exemple #14
0
static int
lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
{
    const char *src = NULL;
    char *dst = NULL;
    char **options = virStringSplit(fstab->options, ",", 0);
    bool readonly;
    int type = VIR_DOMAIN_FS_TYPE_MOUNT;
    unsigned long long usage = 0;
    int ret = -1;

    if (!options)
        return -1;

    if (fstab->dst[0] != '/') {
        if (virAsprintf(&dst, "/%s", fstab->dst) < 0)
            goto cleanup;
    } else {
        if (VIR_STRDUP(dst, fstab->dst) < 0)
            goto cleanup;
    }

    /* Check that we don't add basic mounts */
    if (lxcIsBasicMountLocation(dst)) {
        ret = 0;
        goto cleanup;
    }

    if (STREQ(fstab->type, "tmpfs")) {
        char *sizeStr = NULL;
        size_t i;
        type = VIR_DOMAIN_FS_TYPE_RAM;

        for (i = 0; options[i]; i++) {
            if ((sizeStr = STRSKIP(options[i], "size="))) {
                if (lxcConvertSize(sizeStr, &usage) < 0)
                    goto cleanup;
                break;
            }
        }
        if (!sizeStr) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("missing tmpfs size, set the size option"));
            goto cleanup;
        }
    } else {
        src = fstab->src;
    }

    /* Is it a block device that needs special favor? */
    if (STRPREFIX(fstab->src, "/dev/"))
        type = VIR_DOMAIN_FS_TYPE_BLOCK;

    /* Do we have ro in options? */
    readonly = virStringListHasString((const char **)options, "ro");

    if (lxcAddFSDef(def, type, src, dst, readonly, usage) < 0)
        goto cleanup;

    ret = 1;

 cleanup:
    VIR_FREE(dst);
    virStringListFree(options);
    return ret;
}