Пример #1
0
int
virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
                                      char *output)
{
    /* fields:
     * current/clone/snapshot, name, id, size, used, shared, creation time, vdi id, [tag]
     *
     * example output:
     * s test 1 10 0 0 1336556634 7c2b25
     * s test 2 10 0 0 1336557203 7c2b26
     * = test 3 10 0 0 1336557216 7c2b27
     */

    int id;
    const char *p, *next;

    vol->allocation = vol->capacity = 0;

    p = output;
    do {
        char *end;

        if ((next = strchr(p, '\n')))
            ++next;

        /* ignore snapshots */
        if (*p != '=')
            continue;

        /* skip space */
        if (p + 2 < next)
            p += 2;
        else
            return -1;

        /* skip name */
        while (*p != '\0' && *p != ' ') {
            if (*p == '\\')
                ++p;
            ++p;
        }

        if (virStrToLong_i(p, &end, 10, &id) < 0)
            return -1;

        p = end + 1;

        if (virStrToLong_ull(p, &end, 10, &vol->capacity) < 0)
            return -1;

        p = end + 1;

        if (virStrToLong_ull(p, &end, 10, &vol->allocation) < 0)
            return -1;

        return 0;
    } while ((p = next));

    return -1;
}
Пример #2
0
/* Parse config values of the form barrier:limit into barrier and limit */
static int
openvzParseBarrierLimit(const char* value,
                        unsigned long long *barrier,
                        unsigned long long *limit)
{
    char **tmp = NULL;
    size_t ntmp = 0;
    int ret = -1;

    if (!(tmp = virStringSplitCount(value, ":", 0, &ntmp)))
        goto error;

    if (ntmp != 2)
        goto error;

    if (barrier && virStrToLong_ull(tmp[0], NULL, 10, barrier) < 0)
        goto error;

    if (limit && virStrToLong_ull(tmp[1], NULL, 10, limit) < 0)
        goto error;

    ret = 0;
 error:
    virStringFreeListCount(tmp, ntmp);
    return ret;
}
Пример #3
0
static int
lxcSetCpuTune(virDomainDefPtr def, virConfPtr properties)
{
    VIR_AUTOFREE(char *) value = NULL;

    if (virConfGetValueString(properties, "lxc.cgroup.cpu.shares",
                              &value) > 0) {
        if (virStrToLong_ull(value, NULL, 10, &def->cputune.shares) < 0)
            goto error;
        def->cputune.sharesSpecified = true;
        VIR_FREE(value);
    }

    if (virConfGetValueString(properties, "lxc.cgroup.cpu.cfs_quota_us",
                              &value) > 0) {
        if (virStrToLong_ll(value, NULL, 10, &def->cputune.quota) < 0)
            goto error;
        VIR_FREE(value);
    }

    if (virConfGetValueString(properties, "lxc.cgroup.cpu.cfs_period_us",
                              &value) > 0) {
        if (virStrToLong_ull(value, NULL, 10, &def->cputune.period) < 0)
            goto error;
    }

    return 0;

 error:
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("failed to parse integer: '%s'"), value);
    return -1;
}
Пример #4
0
static int
lxcSetCpuTune(virDomainDefPtr def, virConfPtr properties)
{
    virConfValuePtr value;

    if ((value = virConfGetValue(properties, "lxc.cgroup.cpu.shares")) &&
            value->str) {
        if (virStrToLong_ull(value->str, NULL, 10, &def->cputune.shares) < 0)
            goto error;
        def->cputune.sharesSpecified = true;
    }

    if ((value = virConfGetValue(properties,
                                 "lxc.cgroup.cpu.cfs_quota_us")) &&
            value->str && virStrToLong_ll(value->str, NULL, 10,
                                          &def->cputune.quota) < 0)
        goto error;

    if ((value = virConfGetValue(properties,
                                 "lxc.cgroup.cpu.cfs_period_us")) &&
            value->str && virStrToLong_ull(value->str, NULL, 10,
                                           &def->cputune.period) < 0)
        goto error;

    return 0;

 error:
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("failed to parse integer: '%s'"), value->str);
    return -1;
}
Пример #5
0
static int
virStorageBackendLogicalRefreshPoolFunc(char **const groups,
                                        void *data)
{
    virStoragePoolObjPtr pool = data;
    if (virStrToLong_ull(groups[0], NULL, 10, &pool->def->capacity) < 0)
        return -1;
    if (virStrToLong_ull(groups[1], NULL, 10, &pool->def->available) < 0)
        return -1;
    pool->def->allocation = pool->def->capacity - pool->def->available;

    return 0;
}
Пример #6
0
static int
lxcConvertSize(const char *size, unsigned long long *value)
{
    char *unit = NULL;

    /* Split the string into value and unit */
    if (virStrToLong_ull(size, &unit, 10, value) < 0)
        goto error;

    if (STREQ(unit, "%")) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("can't convert relative size: '%s'"),
                       size);
        return -1;
    } else {
        if (virScaleInteger(value, unit, 1, ULLONG_MAX) < 0)
            goto error;
    }

    return 0;

 error:
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("failed to convert size: '%s'"),
                   size);
    return -1;
}
Пример #7
0
/**
 * virXPathULongLong:
 * @xpath: the XPath string to evaluate
 * @ctxt: an XPath context
 * @value: the returned long long value
 *
 * Convenience function to evaluate an XPath number
 *
 * Returns 0 in case of success in which case @value is set,
 *         or -1 if the XPath evaluation failed or -2 if the
 *         value doesn't have a long format.
 */
int
virXPathULongLong(const char *xpath,
                  xmlXPathContextPtr ctxt,
                  unsigned long long *value)
{
    xmlXPathObjectPtr obj;
    xmlNodePtr relnode;
    int ret = 0;

    if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Invalid parameter to virXPathULong()"));
        return -1;
    }
    relnode = ctxt->node;
    obj = xmlXPathEval(BAD_CAST xpath, ctxt);
    ctxt->node = relnode;
    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
        if (virStrToLong_ull((char *) obj->stringval, NULL, 10, value) < 0)
            ret = -2;
    } else if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
               (!(isnan(obj->floatval)))) {
        *value = (unsigned long long) obj->floatval;
        if (*value != obj->floatval) {
            ret = -2;
        }
    } else {
        ret = -1;
    }

    xmlXPathFreeObject(obj);
    return ret;
}
Пример #8
0
int virJSONValueGetNumberUlong(virJSONValuePtr number, unsigned long long *value)
{
    if (number->type != VIR_JSON_TYPE_NUMBER)
        return -1;

    return virStrToLong_ull(number->data.number, NULL, 10, value);
}
Пример #9
0
int
virStorageBackendSheepdogParseNodeInfo(virStoragePoolDefPtr pool,
                                       char *output)
{
    /* fields:
     * node id/total, size, used, use%, [total vdi size]
     *
     * example output:
     * 0 15245667872 117571104 0%
     * Total 15245667872 117571104 0% 20972341
     */

    const char *p, *next;

    pool->allocation = pool->capacity = pool->available = 0;

    p = output;
    do {
        char *end;

        if ((next = strchr(p, '\n')))
            ++next;
        else
            break;

        if (!STRPREFIX(p, "Total "))
            continue;

        p = p + 6;

        if (virStrToLong_ull(p, &end, 10, &pool->capacity) < 0)
            break;

        if ((p = end + 1) > next)
            break;

        if (virStrToLong_ull(p, &end, 10, &pool->allocation) < 0)
            break;

        pool->available = pool->capacity - pool->allocation;
        return 0;

    } while ((p = next));

    return -1;
}
Пример #10
0
static int
vshVolSize(const char *data, unsigned long long *val)
{
    char *end;
    if (virStrToLong_ull(data, &end, 10, val) < 0)
        return -1;
    return virScaleInteger(val, end, 1, ULLONG_MAX);
}
Пример #11
0
static int
virStorageBackendDiskMakeFreeExtent(virStoragePoolObjPtr pool,
                                    char **const groups)
{
    virStoragePoolSourceDevicePtr dev = &pool->def->source.devices[0];

    if (VIR_REALLOC_N(dev->freeExtents,
                      dev->nfreeExtent + 1) < 0)
        return -1;

    memset(dev->freeExtents +
           dev->nfreeExtent, 0,
           sizeof(dev->freeExtents[0]));

    /* set type of free area */
    if (STREQ(groups[1], "logical")) {
        dev->freeExtents[dev->nfreeExtent].type = VIR_STORAGE_FREE_LOGICAL;
    } else {
        dev->freeExtents[dev->nfreeExtent].type = VIR_STORAGE_FREE_NORMAL;
    }


    if (virStrToLong_ull(groups[3], NULL, 10,
                         &dev->freeExtents[dev->nfreeExtent].start) < 0)
        return -1; /* Don't bother to re-alloc freeExtents - it'll be free'd shortly */

    if (virStrToLong_ull(groups[4], NULL, 10,
                         &dev->freeExtents[dev->nfreeExtent].end) < 0)
        return -1; /* Don't bother to re-alloc freeExtents - it'll be free'd shortly */

    /* first block reported as free, even if it is not */
    if (dev->freeExtents[dev->nfreeExtent].start == 0) {
        dev->freeExtents[dev->nfreeExtent].start = SECTOR_SIZE;
    }

    pool->def->available +=
        (dev->freeExtents[dev->nfreeExtent].end -
         dev->freeExtents[dev->nfreeExtent].start);
    if (dev->freeExtents[dev->nfreeExtent].end > pool->def->capacity)
        pool->def->capacity = dev->freeExtents[dev->nfreeExtent].end;

    dev->nfreeExtent++;

    return 0;
}
Пример #12
0
/* Parse config values of the form barrier:limit into barrier and limit */
static int
openvzParseBarrierLimit(const char* value,
                        unsigned long long *barrier,
                        unsigned long long *limit)
{
    char *token;
    char *saveptr = NULL;
    char *str = strdup(value);

    if (str == NULL) {
        virReportOOMError();
        goto error;
    }

    token = strtok_r(str, ":", &saveptr);
    if (token == NULL) {
        goto error;
    } else {
        if (barrier != NULL) {
            if (virStrToLong_ull(token, NULL, 10, barrier))
                goto error;
        }
    }
    token = strtok_r(NULL, ":", &saveptr);
    if (token == NULL) {
        goto error;
    } else {
        if (limit != NULL) {
            if (virStrToLong_ull(token, NULL, 10, limit))
                goto error;
        }
    }
    return 0;
error:
    VIR_FREE(str);
    return -1;
}
Пример #13
0
/* Parse config values of the form barrier:limit into barrier and limit */
static int
openvzParseBarrierLimit(const char* value,
                        unsigned long long *barrier,
                        unsigned long long *limit)
{
    char *token;
    char *saveptr = NULL;
    char *str;
    int ret = -1;

    if (VIR_STRDUP(str, value) < 0)
        goto error;

    token = strtok_r(str, ":", &saveptr);
    if (token == NULL) {
        goto error;
    } else {
        if (barrier != NULL) {
            if (virStrToLong_ull(token, NULL, 10, barrier))
                goto error;
        }
    }
    token = strtok_r(NULL, ":", &saveptr);
    if (token == NULL) {
        goto error;
    } else {
        if (limit != NULL) {
            if (virStrToLong_ull(token, NULL, 10, limit))
                goto error;
        }
    }
    ret = 0;
 error:
    VIR_FREE(str);
    return ret;
}
Пример #14
0
static int udevStrToLong_ull(char const *s,
                             char **end_ptr,
                             int base,
                             unsigned long long *result)
{
    int ret = 0;

    ret = virStrToLong_ull(s, end_ptr, base, result);
    if (ret != 0) {
        VIR_ERROR(_("Failed to convert '%s' to unsigned long long"), s);
    } else {
        VIR_DEBUG("Converted '%s' to unsigned long %llu", s, *result);
    }

    return ret;
}
Пример #15
0
int virIdentityGetUNIXProcessTime(virIdentityPtr ident,
                                  unsigned long long *timestamp)
{
    const char *processtime;
    if (virIdentityGetAttr(ident,
                           VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME,
                           &processtime) < 0)
        return -1;

    if (!processtime)
        return -1;

    if (virStrToLong_ull(processtime, NULL, 10, timestamp) < 0)
        return -1;

    return 0;
}
Пример #16
0
static int virLXCCgroupGetMemStat(virCgroupPtr cgroup,
                                  virLXCMeminfoPtr meminfo)
{
    int ret = 0;
    FILE *statfd = NULL;
    char *statFile = NULL;
    char *line = NULL;
    size_t n;

    ret = virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY,
                                    "memory.stat", &statFile);
    if (ret != 0) {
        virReportSystemError(-ret, "%s",
                             _("cannot get the path of MEMORY cgroup controller"));
        return ret;
    }

    statfd = fopen(statFile, "r");
    if (statfd == NULL) {
        ret = -errno;
        goto cleanup;
    }

    while (getline(&line, &n, statfd) > 0) {

        char *value = strchr(line, ' ');
        char *nl = value ? strchr(line, '\n') : NULL;
        unsigned long long stat_value;

        if (!value)
            continue;

        if (nl)
            *nl = '\0';

        *value = '\0';

        if (virStrToLong_ull(value + 1, NULL, 10, &stat_value) < 0) {
            ret = -EINVAL;
            goto cleanup;
        }
        if (STREQ(line, "cache"))
            meminfo->cached = stat_value >> 10;
        else if (STREQ(line, "inactive_anon"))
            meminfo->inactive_anon = stat_value >> 10;
        else if (STREQ(line, "active_anon"))
Пример #17
0
static int virCgroupGetValueU64(virCgroupPtr group,
                                int controller,
                                const char *key,
                                unsigned long long int *value)
{
    char *strval = NULL;
    int rc = 0;

    rc = virCgroupGetValueStr(group, controller, key, &strval);
    if (rc != 0)
        goto out;

    if (virStrToLong_ull(strval, NULL, 10, value) < 0)
        rc = -EINVAL;
out:
    VIR_FREE(strval);

    return rc;
}
Пример #18
0
int virIdentityGetUNIXProcessID(virIdentityPtr ident,
                                pid_t *pid)
{
    unsigned long long val;
    const char *processid;

    *pid = 0;
    if (virIdentityGetAttr(ident,
                           VIR_IDENTITY_ATTR_UNIX_PROCESS_ID,
                           &processid) < 0)
        return -1;

    if (!processid)
        return -1;

    if (virStrToLong_ull(processid, NULL, 10, &val) < 0)
        return -1;

    *pid = (pid_t)val;

    return 0;
}
Пример #19
0
int
virNumaSetPagePoolSize(int node,
                       unsigned int page_size,
                       unsigned long long page_count,
                       bool add)
{
    int ret = -1;
    char *nr_path = NULL, *nr_buf =  NULL;
    char *end;
    unsigned long long nr_count;

    if (page_size == virGetSystemPageSizeKB()) {
        /* Special case as kernel handles system pages
         * differently to huge pages. */
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("system pages pool can't be modified"));
        goto cleanup;
    }

    if (virNumaGetHugePageInfoPath(&nr_path, node, page_size, "nr_hugepages") < 0)
        goto cleanup;

    /* Firstly check, if there's anything for us to do */
    if (virFileReadAll(nr_path, 1024, &nr_buf) < 0)
        goto cleanup;

    if (virStrToLong_ull(nr_buf, &end, 10, &nr_count) < 0 ||
            *end != '\n') {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("invalid number '%s' in '%s'"),
                       nr_buf, nr_path);
        goto cleanup;
    }

    if (add) {
        if (!page_count) {
            VIR_DEBUG("Nothing left to do: add = true page_count = 0");
            ret = 0;
            goto cleanup;
        }
        page_count += nr_count;
    } else {
        if (nr_count == page_count) {
            VIR_DEBUG("Nothing left to do: nr_count = page_count = %llu",
                      page_count);
            ret = 0;
            goto cleanup;
        }
    }

    /* Okay, page pool adjustment must be done in two steps. In
     * first we write the desired number into nr_hugepages file.
     * Kernel then starts to allocate the pages (return from
     * write should be postponed until the kernel is finished).
     * However, kernel may have not been successful and reserved
     * all the pages we wanted. So do the second read to check.
     */
    VIR_FREE(nr_buf);
    if (virAsprintf(&nr_buf, "%llu", page_count) < 0)
        goto cleanup;

    if (virFileWriteStr(nr_path, nr_buf, 0) < 0) {
        virReportSystemError(errno,
                             _("Unable to write to: %s"), nr_path);
        goto cleanup;
    }

    /* And now do the check. */

    VIR_FREE(nr_buf);
    if (virFileReadAll(nr_path, 1024, &nr_buf) < 0)
        goto cleanup;

    if (virStrToLong_ull(nr_buf, &end, 10, &nr_count) < 0 ||
            *end != '\n') {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("invalid number '%s' in '%s'"),
                       nr_buf, nr_path);
        goto cleanup;
    }

    if (nr_count != page_count) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("Unable to allocate %llu pages. Allocated only %llu"),
                       page_count, nr_count);
        goto cleanup;
    }

    ret = 0;
cleanup:
    VIR_FREE(nr_buf);
    VIR_FREE(nr_path);
    return ret;
}
static int
virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
                                char **const groups,
                                void *data)
{
    virStorageVolDefPtr vol = NULL;
    unsigned long long offset, size, length;

    /* See if we're only looking for a specific volume */
    if (data != NULL) {
        vol = data;
        if (STRNEQ(vol->name, groups[0]))
            return 0;
    }

    /* Or filling in more data on an existing volume */
    if (vol == NULL)
        vol = virStorageVolDefFindByName(pool, groups[0]);

    /* Or a completely new volume */
    if (vol == NULL) {
        if (VIR_ALLOC(vol) < 0) {
            virReportOOMError();
            return -1;
        }

        vol->type = VIR_STORAGE_VOL_BLOCK;

        if ((vol->name = strdup(groups[0])) == NULL) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }

        if (VIR_REALLOC_N(pool->volumes.objs,
                          pool->volumes.count + 1)) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }
        pool->volumes.objs[pool->volumes.count++] = vol;
    }

    if (vol->target.path == NULL) {
        if (virAsprintf(&vol->target.path, "%s/%s",
                        pool->def->target.path, vol->name) < 0) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }
    }

    if (groups[1] && !STREQ(groups[1], "")) {
        if (virAsprintf(&vol->backingStore.path, "%s/%s",
                        pool->def->target.path, groups[1]) < 0) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }

        vol->backingStore.format = VIR_STORAGE_POOL_LOGICAL_LVM2;
    }

    if (vol->key == NULL &&
        (vol->key = strdup(groups[2])) == NULL) {
        virReportOOMError();
        return -1;
    }

    if (virStorageBackendUpdateVolInfo(vol, 1) < 0)
        return -1;


    /* Finally fill in extents information */
    if (VIR_REALLOC_N(vol->source.extents,
                      vol->source.nextent + 1) < 0) {
        virReportOOMError();
        return -1;
    }

    if ((vol->source.extents[vol->source.nextent].path =
         strdup(groups[3])) == NULL) {
        virReportOOMError();
        return -1;
    }

    if (virStrToLong_ull(groups[4], NULL, 10, &offset) < 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("malformed volume extent offset value"));
        return -1;
    }
    if (virStrToLong_ull(groups[5], NULL, 10, &length) < 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("malformed volume extent length value"));
        return -1;
    }
    if (virStrToLong_ull(groups[6], NULL, 10, &size) < 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("malformed volume extent size value"));
        return -1;
    }

    vol->source.extents[vol->source.nextent].start = offset * size;
    vol->source.extents[vol->source.nextent].end = (offset * size) + length;
    vol->source.nextent++;

    return 0;
}
Пример #21
0
/* Assign name, type, and convert the argument from a const string.
 * In case of a string, the string is copied.
 * Return 0 on success, -1 after an error message on failure.  */
int
virTypedParameterAssignFromStr(virTypedParameterPtr param, const char *name,
                               int type, const char *val)
{
    int ret = -1;

    if (!val) {
        virReportError(VIR_ERR_INVALID_ARG, _("NULL value for field '%s'"),
                       name);
        goto cleanup;
    }

    if (virStrcpyStatic(param->field, name) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, _("Field name '%s' too long"),
                       name);
        goto cleanup;
    }

    param->type = type;
    switch (type) {
    case VIR_TYPED_PARAM_INT:
        if (virStrToLong_i(val, NULL, 10, &param->value.i) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': expected int"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_UINT:
        if (virStrToLong_ui(val, NULL, 10, &param->value.ui) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected unsigned int"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_LLONG:
        if (virStrToLong_ll(val, NULL, 10, &param->value.l) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected long long"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_ULLONG:
        if (virStrToLong_ull(val, NULL, 10, &param->value.ul) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected unsigned long long"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_DOUBLE:
        if (virStrToDouble(val, NULL, &param->value.d) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected double"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_BOOLEAN:
        if (STRCASEEQ(val, "true") || STREQ(val, "1")) {
            param->value.b = true;
        } else if (STRCASEEQ(val, "false") || STREQ(val, "0")) {
            param->value.b = false;
        } else {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid boolean value for field '%s'"), name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_STRING:
        if (VIR_STRDUP(param->value.s, val) < 0)
            goto cleanup;
        break;
    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected type %d for field %s"), type, name);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    return ret;
}
Пример #22
0
static int
virStorageBackendDiskMakeDataVol(virStoragePoolObjPtr pool,
                                 char **const groups,
                                 virStorageVolDefPtr vol)
{
    char *tmp, *devpath;

    if (vol == NULL) {
        if (VIR_ALLOC(vol) < 0) {
            virReportOOMError();
            return -1;
        }

        if (VIR_REALLOC_N(pool->volumes.objs,
                          pool->volumes.count+1) < 0) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }
        pool->volumes.objs[pool->volumes.count++] = vol;

        /* Prepended path will be same for all partitions, so we can
         * strip the path to form a reasonable pool-unique name
         */
        tmp = strrchr(groups[0], '/');
        if ((vol->name = strdup(tmp ? tmp + 1 : groups[0])) == NULL) {
            virReportOOMError();
            return -1;
        }
    }

    if (vol->target.path == NULL) {
        if ((devpath = strdup(groups[0])) == NULL) {
            virReportOOMError();
            return -1;
        }

        /* Now figure out the stable path
         *
         * XXX this method is O(N) because it scans the pool target
         * dir every time its run. Should figure out a more efficient
         * way of doing this...
         */
        vol->target.path = virStorageBackendStablePath(pool, devpath, true);
        VIR_FREE(devpath);
        if (vol->target.path == NULL)
            return -1;
    }

    if (vol->key == NULL) {
        /* XXX base off a unique key of the underlying disk */
        if ((vol->key = strdup(vol->target.path)) == NULL) {
            virReportOOMError();
            return -1;
        }
    }

    if (vol->source.extents == NULL) {
        if (VIR_ALLOC(vol->source.extents) < 0) {
            virReportOOMError();
            return -1;
        }
        vol->source.nextent = 1;

        if (virStrToLong_ull(groups[3], NULL, 10,
                             &vol->source.extents[0].start) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("cannot parse device start location"));
            return -1;
        }

        if (virStrToLong_ull(groups[4], NULL, 10,
                             &vol->source.extents[0].end) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("cannot parse device end location"));
            return -1;
        }

        if ((vol->source.extents[0].path =
             strdup(pool->def->source.devices[0].path)) == NULL) {
            virReportOOMError();
            return -1;
        }
    }

    /* Refresh allocation/capacity/perms */
    if (virStorageBackendUpdateVolInfo(vol, 1) < 0)
        return -1;

    /* set partition type */
    if (STREQ(groups[1], "normal"))
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_PRIMARY;
    else if (STREQ(groups[1], "logical"))
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_LOGICAL;
    else if (STREQ(groups[1], "extended"))
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_EXTENDED;
    else
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_NONE;

    vol->type = VIR_STORAGE_VOL_BLOCK;

    /* The above gets allocation wrong for
     * extended partitions, so overwrite it */
    vol->allocation = vol->capacity =
        (vol->source.extents[0].end - vol->source.extents[0].start);

    if (STRNEQ(groups[2], "metadata"))
        pool->def->allocation += vol->allocation;
    if (vol->source.extents[0].end > pool->def->capacity)
        pool->def->capacity = vol->source.extents[0].end;

    return 0;
}
Пример #23
0
static int
virNetDevBandwidthParseRate(xmlNodePtr node, virNetDevBandwidthRatePtr rate)
{
    int ret = -1;
    char *average = NULL;
    char *peak = NULL;
    char *burst = NULL;
    char *floor = NULL;

    if (!node || !rate) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("invalid argument supplied"));
        return -1;
    }

    average = virXMLPropString(node, "average");
    peak = virXMLPropString(node, "peak");
    burst = virXMLPropString(node, "burst");
    floor = virXMLPropString(node, "floor");

    if (average) {
        if (virStrToLong_ull(average, NULL, 10, &rate->average) < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("could not convert bandwidth average value '%s'"),
                           average);
            goto cleanup;
        }
    } else if (!floor) {
        virReportError(VIR_ERR_XML_DETAIL, "%s",
                       _("Missing mandatory average or floor attributes"));
        goto cleanup;
    }

    if ((peak || burst) && !average) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("'peak' and 'burst' require 'average' attribute"));
        goto cleanup;
    }

    if (peak && virStrToLong_ull(peak, NULL, 10, &rate->peak) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("could not convert bandwidth peak value '%s'"),
                       peak);
        goto cleanup;
    }

    if (burst && virStrToLong_ull(burst, NULL, 10, &rate->burst) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("could not convert bandwidth burst value '%s'"),
                       burst);
        goto cleanup;
    }

    if (floor && virStrToLong_ull(floor, NULL, 10, &rate->floor) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("could not convert bandwidth floor value '%s'"),
                       floor);
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(average);
    VIR_FREE(peak);
    VIR_FREE(burst);
    VIR_FREE(floor);

    return ret;
}
Пример #24
0
static int
virStorageBackendZFSRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                virStoragePoolObjPtr pool ATTRIBUTE_UNUSED)
{
    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",
                               pool->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;

        virStringFreeList(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"))
                pool->def->available = value;
            else if (STREQ(prop_name, "size"))
                pool->def->capacity = value;
            else if (STREQ(prop_name, "allocated"))
                pool->def->allocation = value;
        }
    }

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

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

    return 0;
}
Пример #25
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;

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

    if (count != 2)
        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",
                        pool->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 (is_new_vol &&
        VIR_APPEND_ELEMENT(pool->volumes.objs,
                           pool->volumes.count,
                           volume) < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    virStringFreeList(tokens);
    virStringFreeList(name_tokens);
    if (is_new_vol)
        virStorageVolDefFree(volume);
    return ret;
}
Пример #26
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:
    virStringFreeList(parts);
    VIR_FREE(path);

    return ret;
}
Пример #27
0
static int
virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
                                char **const groups,
                                void *data)
{
    virStorageVolDefPtr vol = NULL;
    bool is_new_vol = false;
    unsigned long long offset, size, length;
    const char *regex_unit = "(\\S+)\\((\\S+)\\)";
    char *regex = NULL;
    regex_t *reg = NULL;
    regmatch_t *vars = NULL;
    char *p = NULL;
    size_t i;
    int err, nextents, nvars, ret = -1;
    const char *attrs = groups[9];

    /* Skip inactive volume */
    if (attrs[4] != 'a')
        return 0;

    /*
     * Skip thin pools(t). These show up in normal lvs output
     * but do not have a corresponding /dev/$vg/$lv device that
     * is created by udev. This breaks assumptions in later code.
     */
    if (attrs[0] == 't')
        return 0;

    /* See if we're only looking for a specific volume */
    if (data != NULL) {
        vol = data;
        if (STRNEQ(vol->name, groups[0]))
            return 0;
    }

    /* Or filling in more data on an existing volume */
    if (vol == NULL)
        vol = virStorageVolDefFindByName(pool, groups[0]);

    /* Or a completely new volume */
    if (vol == NULL) {
        if (VIR_ALLOC(vol) < 0)
            return -1;

        is_new_vol = true;
        vol->type = VIR_STORAGE_VOL_BLOCK;

        if (VIR_STRDUP(vol->name, groups[0]) < 0)
            goto cleanup;

        if (VIR_REALLOC_N(pool->volumes.objs,
                          pool->volumes.count + 1))
            goto cleanup;
    }

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

    /* Skips the backingStore of lv created with "--virtualsize",
     * its original device "/dev/$vgname/$lvname_vorigin" is
     * just for lvm internal use, one should never use it.
     *
     * (lvs outputs "[$lvname_vorigin] for field "origin" if the
     *  lv is created with "--virtualsize").
     */
    if (groups[1] && !STREQ(groups[1], "") && (groups[1][0] != '[')) {
        if (virAsprintf(&vol->backingStore.path, "%s/%s",
                        pool->def->target.path, groups[1]) < 0)
            goto cleanup;

        vol->backingStore.format = VIR_STORAGE_POOL_LOGICAL_LVM2;
    }

    if (!vol->key && VIR_STRDUP(vol->key, groups[2]) < 0)
        goto cleanup;

    if (virStorageBackendUpdateVolInfo(vol, 1) < 0)
        goto cleanup;

    nextents = 1;
    if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) {
        if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent stripes value"));
            goto cleanup;
        }
    }

    /* Finally fill in extents information */
    if (VIR_REALLOC_N(vol->source.extents,
                      vol->source.nextent + nextents) < 0)
        goto cleanup;

    if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent length value"));
        goto cleanup;
    }
    if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent size value"));
        goto cleanup;
    }
    if (virStrToLong_ull(groups[8], NULL, 10, &vol->allocation) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume allocation value"));
        goto cleanup;
    }

    /* Now parse the "devices" field separately */
    if (VIR_STRDUP(regex, regex_unit) < 0)
        goto cleanup;

    for (i = 1; i < nextents; i++) {
        if (VIR_REALLOC_N(regex, strlen(regex) + strlen(regex_unit) + 2) < 0)
            goto cleanup;
        /* "," is the separator of "devices" field */
        strcat(regex, ",");
        strncat(regex, regex_unit, strlen(regex_unit));
    }

    if (VIR_ALLOC(reg) < 0)
        goto cleanup;

    /* Each extent has a "path:offset" pair, and vars[0] will
     * be the whole matched string.
     */
    nvars = (nextents * 2) + 1;
    if (VIR_ALLOC_N(vars, nvars) < 0)
        goto cleanup;

    err = regcomp(reg, regex, REG_EXTENDED);
    if (err != 0) {
        char error[100];
        regerror(err, reg, error, sizeof(error));
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to compile regex %s"),
                       error);
        goto cleanup;
    }

    err = regexec(reg, groups[3], nvars, vars, 0);
    regfree(reg);
    if (err != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("malformed volume extent devices value"));
        goto cleanup;
    }

    p = groups[3];

    /* vars[0] is skipped */
    for (i = 0; i < nextents; i++) {
        size_t j;
        int len;
        char *offset_str = NULL;

        j = (i * 2) + 1;
        len = vars[j].rm_eo - vars[j].rm_so;
        p[vars[j].rm_eo] = '\0';

        if (VIR_STRNDUP(vol->source.extents[vol->source.nextent].path,
                        p + vars[j].rm_so, len) < 0)
            goto cleanup;

        len = vars[j + 1].rm_eo - vars[j + 1].rm_so;
        if (VIR_STRNDUP(offset_str, p + vars[j + 1].rm_so, len) < 0)
            goto cleanup;

        if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent offset value"));
            VIR_FREE(offset_str);
            goto cleanup;
        }

        VIR_FREE(offset_str);

        vol->source.extents[vol->source.nextent].start = offset * size;
        vol->source.extents[vol->source.nextent].end = (offset * size) + length;
        vol->source.nextent++;
    }

    if (is_new_vol)
        pool->volumes.objs[pool->volumes.count++] = vol;

    ret = 0;

cleanup:
    VIR_FREE(regex);
    VIR_FREE(reg);
    VIR_FREE(vars);
    if (is_new_vol && (ret == -1))
        virStorageVolDefFree(vol);
    return ret;
}
Пример #28
0
static qemuMigrationCookieNBDPtr
qemuMigrationCookieNBDXMLParse(xmlXPathContextPtr ctxt)
{
    qemuMigrationCookieNBDPtr ret = NULL;
    char *port = NULL, *capacity = NULL;
    size_t i;
    int n;
    xmlNodePtr *disks = NULL;
    xmlNodePtr save_ctxt = ctxt->node;

    if (VIR_ALLOC(ret) < 0)
        goto error;

    port = virXPathString("string(./nbd/@port)", ctxt);
    if (port && virStrToLong_i(port, NULL, 10, &ret->port) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Malformed nbd port '%s'"),
                       port);
        goto error;
    }

    /* Now check if source sent a list of disks to prealloc. We might be
     * talking to an older server, so it's not an error if the list is
     * missing. */
    if ((n = virXPathNodeSet("./nbd/disk", ctxt, &disks)) > 0) {
        if (VIR_ALLOC_N(ret->disks, n) < 0)
            goto error;
        ret->ndisks = n;

        for (i = 0; i < n; i++) {
            ctxt->node = disks[i];
            VIR_FREE(capacity);

            if (!(ret->disks[i].target = virXPathString("string(./@target)", ctxt))) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Malformed disk target"));
                goto error;
            }

            capacity = virXPathString("string(./@capacity)", ctxt);
            if (!capacity ||
                virStrToLong_ull(capacity, NULL, 10,
                                 &ret->disks[i].capacity) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Malformed disk capacity: '%s'"),
                               NULLSTR(capacity));
                goto error;
            }
        }
    }

 cleanup:
    VIR_FREE(port);
    VIR_FREE(capacity);
    VIR_FREE(disks);
    ctxt->node = save_ctxt;
    return ret;
 error:
    qemuMigrationCookieNBDFree(ret);
    ret = NULL;
    goto cleanup;
}