static int sched_credit_domain_set(libxl__gc *gc, uint32_t domid, const libxl_domain_sched_params *scinfo) { struct xen_domctl_sched_credit sdom; xc_domaininfo_t domaininfo; int rc; rc = xc_domain_getinfolist(CTX->xch, domid, 1, &domaininfo); if (rc < 0) { LOGED(ERROR, domid, "Getting domain info list"); return ERROR_FAIL; } if (rc != 1 || domaininfo.domain != domid) return ERROR_INVAL; rc = xc_sched_credit_domain_get(CTX->xch, domid, &sdom); if (rc != 0) { LOGED(ERROR, domid, "Getting domain sched credit"); return ERROR_FAIL; } if (scinfo->weight != LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT) { if (scinfo->weight < 1 || scinfo->weight > 65535) { LOGD(ERROR, domid, "Cpu weight out of range, " "valid values are within range from 1 to 65535"); return ERROR_INVAL; } sdom.weight = scinfo->weight; } if (scinfo->cap != LIBXL_DOMAIN_SCHED_PARAM_CAP_DEFAULT) { if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) { LOGD(ERROR, domid, "Cpu cap out of range, " "valid range is from 0 to %d for specified number of vcpus", ((domaininfo.max_vcpu_id + 1) * 100)); return ERROR_INVAL; } sdom.cap = scinfo->cap; } rc = xc_sched_credit_domain_set(CTX->xch, domid, &sdom); if ( rc < 0 ) { LOGED(ERROR, domid, "Setting domain sched credit"); return ERROR_FAIL; } return 0; }
xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags) { #define DOMAIN_CHUNK_SIZE 256 xenstat_node *node; xc_physinfo_t physinfo = { 0 }; xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE]; unsigned int new_domains; unsigned int i; /* Create the node */ node = (xenstat_node *) calloc(1, sizeof(xenstat_node)); if (node == NULL) return NULL; /* Store the handle in the node for later access */ node->handle = handle; /* Get information about the physical system */ if (xc_physinfo(handle->xc_handle, &physinfo) < 0) { free(node); return NULL; } node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL; node->num_cpus = physinfo.nr_cpus; node->tot_mem = ((unsigned long long)physinfo.total_pages) * handle->page_size; node->free_mem = ((unsigned long long)physinfo.free_pages) * handle->page_size; /* malloc(0) is not portable, so allocate a single domain. This will * be resized below. */ node->domains = malloc(sizeof(xenstat_domain)); if (node->domains == NULL) { free(node); return NULL; } node->num_domains = 0; do { xenstat_domain *domain, *tmp; new_domains = xc_domain_getinfolist(handle->xc_handle, node->num_domains, DOMAIN_CHUNK_SIZE, domaininfo); tmp = realloc(node->domains, (node->num_domains + new_domains) * sizeof(xenstat_domain)); if (tmp == NULL) { free(node->domains); free(node); return NULL; } node->domains = tmp; domain = node->domains + node->num_domains; /* zero out newly allocated memory in case error occurs below */ memset(domain, 0, new_domains * sizeof(xenstat_domain)); for (i = 0; i < new_domains; i++) { /* Fill in domain using domaininfo[i] */ domain->id = domaininfo[i].domain; domain->name = xenstat_get_domain_name(handle, domain->id); if (domain->name == NULL) { if (errno == ENOMEM) { /* fatal error */ xenstat_free_node(node); return NULL; } else { /* failed to get name -- this means the domain is being destroyed so simply ignore this entry */ continue; } } domain->state = domaininfo[i].flags; domain->cpu_ns = domaininfo[i].cpu_time; domain->num_vcpus = (domaininfo[i].max_vcpu_id+1); domain->vcpus = NULL; domain->cur_mem = ((unsigned long long)domaininfo[i].tot_pages) * handle->page_size; domain->max_mem = domaininfo[i].max_pages == UINT_MAX ? (unsigned long long)-1 : (unsigned long long)(domaininfo[i].max_pages * handle->page_size); domain->ssid = domaininfo[i].ssidref; domain->num_networks = 0; domain->networks = NULL; domain->num_vbds = 0; domain->vbds = NULL; domain++; node->num_domains++; } } while (new_domains == DOMAIN_CHUNK_SIZE); /* Run all the extra data collectors requested */ node->flags = 0; for (i = 0; i < NUM_COLLECTORS; i++) { if ((flags & collectors[i].flag) == collectors[i].flag) { node->flags |= collectors[i].flag; if(collectors[i].collect(node) == 0) { xenstat_free_node(node); return NULL; } } } return node; }
void agentCB_getCountersVM(void *magic, SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs) { #ifdef HSF_XEN assert(poller->magic); HSP *sp = (HSP *)poller->magic; HSPVMState *state = (HSPVMState *)poller->userData; if(state && xenHandlesOK(sp)) { xc_domaininfo_t domaininfo; int32_t n = xc_domain_getinfolist(sp->xc_handle, state->vm_index, 1, &domaininfo); if(n < 0 || domaininfo.domain != state->domId) { // Assume something changed under our feet. // Request a reload of the VM information and bail. // We'll try again next time. myLog(LOG_INFO, "request for vm_index %u (dom_id=%u) returned %d (with dom_id=%u)", state->vm_index, state->domId, n, domaininfo.domain); sp->refreshVMList = YES; return; } // host ID SFLCounters_sample_element hidElem = { 0 }; memset(&hidElem, 0, sizeof(hidElem)); hidElem.tag = SFLCOUNTERS_HOST_HID; char query[255]; char hname[255]; snprintf(query, sizeof(query), "/local/domain/%u/name", state->domId); char *xshname = (char *)xs_read(sp->xs_handle, XBT_NULL, query, NULL); if(xshname) { // copy the name out here so we can free it straight away strncpy(hname, xshname, 255); free(xshname); hidElem.counterBlock.host_hid.hostname.str = hname; hidElem.counterBlock.host_hid.hostname.len = strlen(hname); memcpy(hidElem.counterBlock.host_hid.uuid, &domaininfo.handle, 16); hidElem.counterBlock.host_hid.machine_type = SFLMT_unknown; hidElem.counterBlock.host_hid.os_name = SFLOS_unknown; //hidElem.counterBlock.host_hid.os_release.str = NULL; //hidElem.counterBlock.host_hid.os_release.len = 0; SFLADD_ELEMENT(cs, &hidElem); } // host parent SFLCounters_sample_element parElem = { 0 }; parElem.tag = SFLCOUNTERS_HOST_PAR; parElem.counterBlock.host_par.dsClass = SFL_DSCLASS_PHYSICAL_ENTITY; parElem.counterBlock.host_par.dsIndex = 1; SFLADD_ELEMENT(cs, &parElem); // VM Net I/O SFLCounters_sample_element nioElem = { 0 }; nioElem.tag = SFLCOUNTERS_HOST_VRT_NIO; char devFilter[20]; snprintf(devFilter, 20, "vif%u.", state->domId); uint32_t network_count = readNioCounters(sp, (SFLHost_nio_counters *)&nioElem.counterBlock.host_vrt_nio, devFilter); if(state->network_count != network_count) { // request a refresh if the number of VIFs changed. Not a perfect test // (e.g. if one was removed and another was added at the same time then // we would miss it). I guess we should keep the whole list of network ids, // or just force a refresh every few minutes? myLog(LOG_INFO, "vif count changed from %u to %u (dom_id=%u). Setting refreshAdaptorList=YES", state->network_count, network_count, state->domId); state->network_count = network_count; sp->refreshAdaptorList = YES; } SFLADD_ELEMENT(cs, &nioElem); // VM cpu counters [ref xenstat.c] SFLCounters_sample_element cpuElem = { 0 }; cpuElem.tag = SFLCOUNTERS_HOST_VRT_CPU; u_int64_t vcpu_ns = 0; for(uint32_t c = 0; c <= domaininfo.max_vcpu_id; c++) { xc_vcpuinfo_t info; if(xc_vcpu_getinfo(sp->xc_handle, state->domId, c, &info) != 0) { // error or domain is in transition. Just bail. myLog(LOG_INFO, "vcpu list in transition (dom_id=%u)", state->domId); return; } else { if(info.online) { vcpu_ns += info.cpu_time; } } } uint32_t st = domaininfo.flags; // first 8 bits (b7-b0) are a mask of flags (see tools/libxc/xen/domctl.h) // next 8 bits (b15-b8) indentify the CPU to which the domain is bound // next 8 bits (b23-b16) indentify the the user-supplied shutdown code cpuElem.counterBlock.host_vrt_cpu.state = SFL_VIR_DOMAIN_NOSTATE; if(st & XEN_DOMINF_shutdown) { cpuElem.counterBlock.host_vrt_cpu.state = SFL_VIR_DOMAIN_SHUTDOWN; if(((st >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) == SHUTDOWN_crash) { cpuElem.counterBlock.host_vrt_cpu.state = SFL_VIR_DOMAIN_CRASHED; } }
int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, int64_t target_memkb, int relative, int enforce) { GC_INIT(ctx); int rc, r, lrc, abort_transaction = 0; uint64_t memorykb, size; uint64_t videoram = 0; uint64_t current_target_memkb = 0, new_target_memkb = 0; uint64_t current_max_memkb = 0; char *memmax, *endptr, *videoram_s = NULL, *target = NULL; char *dompath = libxl__xs_get_dompath(gc, domid); xc_domaininfo_t info; libxl_dominfo ptr; char *uuid; xs_transaction_t t; libxl__domain_userdata_lock *lock; libxl_domain_config d_config; libxl_domain_config_init(&d_config); CTX_LOCK; lock = libxl__lock_domain_userdata(gc, domid); if (!lock) { rc = ERROR_LOCK_FAIL; goto out_no_transaction; } rc = libxl__get_domain_configuration(gc, domid, &d_config); if (rc < 0) { LOGE(ERROR, "unable to retrieve domain configuration"); goto out_no_transaction; } rc = libxl__arch_extra_memory(gc, &d_config.b_info, &size); if (rc < 0) { LOGE(ERROR, "Couldn't get arch extra constant memory size"); goto out_no_transaction; } retry_transaction: t = xs_transaction_start(ctx->xsh); target = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/target", dompath)); if (!target && !domid) { if (!xs_transaction_end(ctx->xsh, t, 1)) { rc = ERROR_FAIL; goto out_no_transaction; } lrc = libxl__fill_dom0_memory_info(gc, ¤t_target_memkb, ¤t_max_memkb); if (lrc < 0) { rc = ERROR_FAIL; goto out_no_transaction; } goto retry_transaction; } else if (!target) { LOGED(ERROR, domid, "Cannot get target memory info from %s/memory/target", dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } else { current_target_memkb = strtoull(target, &endptr, 10); if (*endptr != '\0') { LOGED(ERROR, domid, "Invalid memory target %s from %s/memory/target\n", target, dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } } memmax = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/static-max", dompath)); if (!memmax) { LOGED(ERROR, domid, "Cannot get memory info from %s/memory/static-max", dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } memorykb = strtoull(memmax, &endptr, 10); if (*endptr != '\0') { LOGED(ERROR, domid, "Invalid max memory %s from %s/memory/static-max\n", memmax, dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } videoram_s = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/videoram", dompath)); videoram = videoram_s ? atoi(videoram_s) : 0; if (relative) { if (target_memkb < 0 && llabs(target_memkb) > current_target_memkb) new_target_memkb = 0; else new_target_memkb = current_target_memkb + target_memkb; } else new_target_memkb = target_memkb - videoram; if (new_target_memkb > memorykb) { LOGD(ERROR, domid, "memory_dynamic_max must be less than or equal to" " memory_static_max\n"); abort_transaction = 1; rc = ERROR_INVAL; goto out; } if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) { LOGD(ERROR, domid, "New target %"PRIu64" for dom0 is below the minimum threshold", new_target_memkb); abort_transaction = 1; rc = ERROR_INVAL; goto out; } if (enforce) { memorykb = new_target_memkb + videoram; r = xc_domain_setmaxmem(ctx->xch, domid, memorykb + size); if (r != 0) { LOGED(ERROR, domid, "xc_domain_setmaxmem memkb=%"PRIu64" failed ""rc=%d\n", memorykb + size, r); abort_transaction = 1; rc = ERROR_FAIL; goto out; } } r = xc_domain_set_pod_target(ctx->xch, domid, (new_target_memkb + size) / 4, NULL, NULL, NULL); if (r != 0) { LOGED(ERROR, domid, "xc_domain_set_pod_target memkb=%"PRIu64" failed rc=%d\n", (new_target_memkb + size) / 4, r); abort_transaction = 1; rc = ERROR_FAIL; goto out; } libxl__xs_printf(gc, t, GCSPRINTF("%s/memory/target", dompath), "%"PRIu64, new_target_memkb); r = xc_domain_getinfolist(ctx->xch, domid, 1, &info); if (r != 1 || info.domain != domid) { abort_transaction = 1; rc = ERROR_FAIL; goto out; } libxl_dominfo_init(&ptr); libxl__xcinfo2xlinfo(ctx, &info, &ptr); uuid = libxl__uuid2string(gc, ptr.uuid); libxl__xs_printf(gc, t, GCSPRINTF("/vm/%s/memory", uuid), "%"PRIu64, new_target_memkb / 1024); libxl_dominfo_dispose(&ptr); rc = 0; out: if (!xs_transaction_end(ctx->xsh, t, abort_transaction) && !abort_transaction) if (errno == EAGAIN) goto retry_transaction; out_no_transaction: libxl_domain_config_dispose(&d_config); if (lock) libxl__unlock_domain_userdata(lock); CTX_UNLOCK; GC_FREE; return rc; }