Beispiel #1
0
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;
}
Beispiel #3
0
  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;
	}
      }
Beispiel #4
0
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, &current_target_memkb,
                                           &current_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;
}