/* Collect information about VCPUs */ static int xenstat_collect_vcpus(xenstat_node * node) { unsigned int i, vcpu, inc_index; /* Fill in VCPU information */ for (i = 0; i < node->num_domains; i+=inc_index) { inc_index = 1; /* default is to increment to next domain */ node->domains[i].vcpus = malloc(node->domains[i].num_vcpus * sizeof(xenstat_vcpu)); if (node->domains[i].vcpus == NULL) return 0; for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) { /* FIXME: need to be using a more efficient mechanism*/ xc_vcpuinfo_t info; if (xc_vcpu_getinfo(node->handle->xc_handle, node->domains[i].id, vcpu, &info) != 0) { if (errno == ENOMEM) { /* fatal error */ return 0; } else { /* domain is in transition - remove from list */ xenstat_prune_domain(node, i); /* remember not to increment index! */ inc_index = 0; break; } } else { node->domains[i].vcpus[vcpu].online = info.online; node->domains[i].vcpus[vcpu].ns = info.cpu_time; } } } return 1; }
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; } }