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; }
/* 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; }
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; }
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; }
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; }
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; }
/** * 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; }
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); }
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; }
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); }
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; }
/* 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; }
/* 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; }
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; }
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; }
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"))
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; }
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; }
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; }
/* 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, ¶m->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, ¶m->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, ¶m->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, ¶m->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, ¶m->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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }