Signed-off-by: juergen.gross@xxxxxxxxxxxxxx diff -r 12322ad00ea2 tools/libxl/libxl.c --- a/tools/libxl/libxl.c Thu Aug 05 11:23:10 2010 +0200 +++ b/tools/libxl/libxl.c Wed Aug 11 09:45:54 2010 +0200 @@ -526,16 +526,27 @@ libxl_poolinfo * libxl_list_pool(libxl_c libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool) { libxl_poolinfo *ptr; - int i; + int i, m; xc_cpupoolinfo_t *info; - int size = 256; + int size; uint32_t poolid; + libxl_physinfo physinfo; + int mapsize; + uint64_t *cpumap; - ptr = calloc(size, sizeof(libxl_poolinfo)); + if (libxl_get_physinfo(ctx, &physinfo) != 0) { + XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting phys info"); + return NULL; + } + mapsize = (physinfo.max_phys_cpus + 63) / 64; + size = physinfo.max_phys_cpus + 32; + + ptr = calloc(size, sizeof(libxl_poolinfo) + mapsize * sizeof(*cpumap)); if (!ptr) { XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "allocating cpupool info"); return NULL; } + cpumap = (uint64_t *)(ptr + size); poolid = 0; for (i = 0; i < size; i++) { @@ -543,6 +554,13 @@ libxl_poolinfo * libxl_list_pool(libxl_c if (info == NULL) break; ptr[i].poolid = info->cpupool_id; + ptr[i].sched_id = info->sched_id; + ptr[i].n_dom = info->n_dom; + ptr[i].cpumap_size = info->cpumap_size; + ptr[i].cpumap = cpumap; + for (m = 0; m < mapsize; m++) + cpumap[m] = info->cpumap[m]; + cpumap += mapsize; poolid = info->cpupool_id + 1; free(info); } @@ -3000,3 +3018,158 @@ int libxl_file_reference_unmap(libxl_ctx return ret == 0 ? 0 : ERROR_FAIL; } + +int libxl_get_freecpus(libxl_ctx *ctx, int *n_cpus, uint64_t **cpumap) +{ + libxl_physinfo info; + int mapsize; + + if (libxl_get_physinfo(ctx, &info) != 0) + return ERROR_FAIL; + + mapsize = (info.max_phys_cpus + 63) / 64; + *cpumap = calloc(mapsize, sizeof(**cpumap)); + if (!*cpumap) + return ERROR_NOMEM; + + if (xc_cpupool_freeinfo(ctx->xch, *cpumap, info.max_phys_cpus)) { + free(*cpumap); + *cpumap = NULL; + return ERROR_FAIL; + } + + *n_cpus = info.max_phys_cpus; + return 0; +} + +int libxl_create_cpupool(libxl_ctx *ctx, const char *name, int schedid, + uint64_t *cpumap, int n_cpus, libxl_uuid *uuid, + uint32_t *poolid) +{ + int rc; + int i; + xs_transaction_t t; + char *uuid_string; + + uuid_string = libxl_uuid2string(ctx, *uuid); + if (!uuid_string) + return ERROR_NOMEM; + + rc = xc_cpupool_create(ctx->xch, poolid, schedid); + if (rc) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, + "Could not create cpupool"); + return ERROR_FAIL; + } + + for (i = 0; i < n_cpus; i++) + if (cpumap[i / 64] & (1L << (i % 64))) { + rc = xc_cpupool_addcpu(ctx->xch, *poolid, i); + if (rc) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, + "Error moving cpu to cpupool"); + return ERROR_FAIL; + } + } + + for (;;) { + t = xs_transaction_start(ctx->xsh); + + xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/pool/%d", *poolid)); + xs_write(ctx->xsh, t, libxl_sprintf(ctx, "/local/pool/%d/uuid", *poolid), + uuid_string, strlen(uuid_string)); + xs_write(ctx->xsh, t, libxl_sprintf(ctx, "/local/pool/%d/name", *poolid), + name, strlen(name)); + + if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) + return 0; + } +} + +int libxl_destroy_cpupool(libxl_ctx *ctx, uint32_t poolid) +{ + int rc, i; + xc_cpupoolinfo_t *info; + xs_transaction_t t; + + info = xc_cpupool_getinfo(ctx->xch, poolid); + if (info == NULL) + return ERROR_NOMEM; + + rc = ERROR_INVAL; + if ((info->cpupool_id != poolid) || (info->n_dom)) + goto out; + + for (i = 0; i < info->cpumap_size; i++) + if (info->cpumap[i / 64] & (1L << (i % 64))) { + rc = xc_cpupool_removecpu(ctx->xch, poolid, i); + if (rc) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, + "Error removing cpu from cpupool"); + rc = ERROR_FAIL; + goto out; + } + } + + rc = xc_cpupool_destroy(ctx->xch, poolid); + if (rc) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Could not destroy cpupool"); + rc = ERROR_FAIL; + goto out; + } + + for (;;) { + t = xs_transaction_start(ctx->xsh); + + xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "/local/pool/%d", poolid)); + + if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) + break; + } + + rc = 0; + +out: + free(info); + + return rc; +} + +int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu) +{ + int rc; + + rc = xc_cpupool_addcpu(ctx->xch, poolid, cpu); + if (rc) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, + "Error moving cpu to cpupool"); + return ERROR_FAIL; + } + return 0; +} + +int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu) +{ + int rc; + + rc = xc_cpupool_removecpu(ctx->xch, poolid, cpu); + if (rc) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, + "Error removing cpu from cpupool"); + return ERROR_FAIL; + } + return 0; +} + +int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid) +{ + int rc; + + rc = xc_cpupool_movedomain(ctx->xch, poolid, domid); + if (rc) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, + "Error moving domain to cpupool"); + return ERROR_FAIL; + } + return 0; +} diff -r 12322ad00ea2 tools/libxl/libxl.h --- a/tools/libxl/libxl.h Thu Aug 05 11:23:10 2010 +0200 +++ b/tools/libxl/libxl.h Wed Aug 11 09:45:54 2010 +0200 @@ -51,6 +51,10 @@ typedef struct { typedef struct { uint32_t poolid; + uint32_t sched_id; + uint32_t n_dom; + uint32_t cpumap_size; + uint64_t *cpumap; } libxl_poolinfo; typedef struct { @@ -666,6 +670,15 @@ int libxl_device_net2_del(libxl_ctx *ctx int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait); +int libxl_get_freecpus(libxl_ctx *ctx, int *n_cpus, uint64_t **cpumap); +int libxl_create_cpupool(libxl_ctx *ctx, const char *name, int schedid, + uint64_t *cpumap, int n_cpus, libxl_uuid *uuid, + uint32_t *poolid); +int libxl_destroy_cpupool(libxl_ctx *ctx, uint32_t poolid); +int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu); +int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu); +int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid); + /* common paths */ const char *libxl_sbindir_path(void); const char *libxl_bindir_path(void); diff -r 12322ad00ea2 tools/libxl/libxl_utils.c --- a/tools/libxl/libxl_utils.c Thu Aug 05 11:23:10 2010 +0200 +++ b/tools/libxl/libxl_utils.c Wed Aug 11 09:45:54 2010 +0200 @@ -31,6 +31,17 @@ #include "libxl_utils.h" #include "libxl_internal.h" +struct schedid_name { + char *name; + int id; +}; + +static struct schedid_name schedid_name[] = { + { "credit", XEN_SCHEDULER_CREDIT }, + { "sedf", XEN_SCHEDULER_SEDF }, + { "credit2", XEN_SCHEDULER_CREDIT2 }, + { NULL, -1 } +}; unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, unsigned int smp_cpus) { @@ -116,6 +127,28 @@ int libxl_name_to_poolid(libxl_ctx *ctx, } } return -1; +} + +int libxl_name_to_schedid(libxl_ctx *ctx, const char *name) +{ + int i; + + for (i = 0; schedid_name[i].name != NULL; i++) + if (strcmp(name, schedid_name[i].name) == 0) + return schedid_name[i].id; + + return -1; +} + +char *libxl_schedid_to_name(libxl_ctx *ctx, int schedid) +{ + int i; + + for (i = 0; schedid_name[i].name != NULL; i++) + if (schedid_name[i].id == schedid) + return schedid_name[i].name; + + return "unknown"; } int libxl_get_stubdom_id(libxl_ctx *ctx, int guest_domid) diff -r 12322ad00ea2 tools/libxl/libxl_utils.h --- a/tools/libxl/libxl_utils.h Thu Aug 05 11:23:10 2010 +0200 +++ b/tools/libxl/libxl_utils.h Wed Aug 11 09:45:54 2010 +0200 @@ -23,6 +23,8 @@ char *libxl_domid_to_name(libxl_ctx *ctx char *libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid); int libxl_name_to_poolid(libxl_ctx *ctx, const char *name, uint32_t *poolid); char *libxl_poolid_to_name(libxl_ctx *ctx, uint32_t poolid); +int libxl_name_to_schedid(libxl_ctx *ctx, const char *name); +char *libxl_schedid_to_name(libxl_ctx *ctx, int schedid); int libxl_get_stubdom_id(libxl_ctx *ctx, int guest_domid); int libxl_is_stubdom(libxl_ctx *ctx, uint32_t domid, uint32_t *target_domid); int libxl_create_logfile(libxl_ctx *ctx, char *name, char **full_name); diff -r 12322ad00ea2 tools/libxl/xl.h --- a/tools/libxl/xl.h Thu Aug 05 11:23:10 2010 +0200 +++ b/tools/libxl/xl.h Wed Aug 11 09:45:54 2010 +0200 @@ -79,6 +79,12 @@ int main_network2attach(int argc, char * int main_network2attach(int argc, char **argv); int main_network2list(int argc, char **argv); int main_network2detach(int argc, char **argv); +int main_poolcreate(int argc, char **argv); +int main_poollist(int argc, char **argv); +int main_pooldestroy(int argc, char **argv); +int main_poolcpuadd(int argc, char **argv); +int main_poolcpuremove(int argc, char **argv); +int main_poolmigrate(int argc, char **argv); void help(char *command); diff -r 12322ad00ea2 tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c Thu Aug 05 11:23:10 2010 +0200 +++ b/tools/libxl/xl_cmdimpl.c Wed Aug 11 09:45:54 2010 +0200 @@ -396,7 +396,7 @@ static void printf_info(int domid, (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], (c_info->uuid)[7], (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], (c_info->uuid)[11], (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], (c_info->uuid)[15]); - printf("\t(cpupool %s (%d))\n", c_info->poolname, c_info->poolid); + printf("\t(pool_name %s)\n", c_info->poolname); if (c_info->xsdata) printf("\t(xsdata contains data)\n"); else @@ -3468,10 +3468,7 @@ static void output_xeninfo(void) printf("xen_minor : %d\n", info->xen_version_minor); printf("xen_extra : %s\n", info->xen_version_extra); printf("xen_caps : %s\n", info->capabilities); - printf("xen_scheduler : %s\n", - sched_id == XEN_SCHEDULER_SEDF ? "sedf" : - sched_id == XEN_SCHEDULER_CREDIT ? "credit" : - sched_id == XEN_SCHEDULER_CREDIT2 ? "credit2" : "unknown"); + printf("xen_scheduler : %s\n", libxl_schedid_to_name(&ctx, sched_id)); printf("xen_pagesize : %lu\n", info->pagesize); printf("platform_params : virt_start=0x%lx\n", info->virt_start); printf("xen_changeset : %s\n", info->changeset); @@ -3502,6 +3499,8 @@ static void output_physinfo(void) libxl_physinfo info; const libxl_version_info *vinfo; unsigned int i; + uint64_t *cpumap; + int n_cpus, n = 0; if (libxl_get_physinfo(&ctx, &info) != 0) { fprintf(stderr, "libxl_physinfo failed.\n"); @@ -3528,6 +3527,13 @@ static void output_physinfo(void) printf("total_memory : %"PRIu64"\n", info.total_pages / i); printf("free_memory : %"PRIu64"\n", info.free_pages / i); } + if (!libxl_get_freecpus(&ctx, &n_cpus, &cpumap)) { + for (i = 0; i < n_cpus; i++) + if (cpumap[i / 64] & ((uint64_t)1 << (i % 64))) + n++; + printf("free_cpus : %d\n", n); + free(cpumap); + } return; } @@ -4928,3 +4934,444 @@ int main_tmem_freeable(int argc, char ** printf("%d\n", mb); return 0; } + +int main_poolcreate(int argc, char **argv) +{ + char *filename = NULL; + char *p, extra_config[1024]; + int dryrun = 0; + int opt; + int option_index = 0; + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"defconfig", 1, 0, 'f'}, + {"dryrun", 0, 0, 'n'}, + {0, 0, 0, 0} + }; + int ret; + void *config_data = 0; + int config_len = 0; + XLU_Config *config; + const char *buf; + char *name, *sched; + uint32_t poolid; + int schedid = -1; + XLU_ConfigList *cpus; + int max_cpus, n_cpus, i, n; + uint64_t *freemap = NULL; + uint64_t *cpumap = NULL; + libxl_uuid uuid; + + while (1) { + opt = getopt_long(argc, argv, "hnf:", long_options, &option_index); + if (opt == -1) + break; + + switch (opt) { + case 'f': + filename = optarg; + break; + case 'h': + help("pool-create"); + return 0; + case 'n': + dryrun = 1; + break; + default: + fprintf(stderr, "option not supported\n"); + break; + } + } + + memset(extra_config, 0, sizeof(extra_config)); + while (optind < argc) { + if ((p = strchr(argv[optind], '='))) { + if (strlen(extra_config) + 1 < sizeof(extra_config)) { + if (strlen(extra_config)) + strcat(extra_config, "\n"); + strcat(extra_config, argv[optind]); + } + } else if (!filename) { + filename = argv[optind]; + } else { + help("pool-create"); + return -ERROR_FAIL; + } + optind++; + } + + if (!filename) { + help("pool-create"); + return -ERROR_FAIL; + } + + if (libxl_read_file_contents(&ctx, filename, &config_data, &config_len)) { + fprintf(stderr, "Failed to read config file: %s: %s\n", + filename, strerror(errno)); + return -ERROR_FAIL; + } + if (strlen(extra_config)) { + if (config_len > INT_MAX - (strlen(extra_config) + 2)) { + fprintf(stderr, "Failed to attach extra configration\n"); + return -ERROR_FAIL; + } + config_data = realloc(config_data, + config_len + strlen(extra_config) + 2); + if (!config_data) { + fprintf(stderr, "Failed to realloc config_data\n"); + return -ERROR_FAIL; + } + strcat(config_data, "\n"); + strcat(config_data, extra_config); + strcat(config_data, "\n"); + config_len += (strlen(extra_config) + 2); + } + + config = xlu_cfg_init(stderr, filename); + if (!config) { + fprintf(stderr, "Failed to allocate for configuration\n"); + return -ERROR_FAIL; + } + + ret = xlu_cfg_readdata(config, config_data, config_len); + if (ret) { + fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret)); + return -ERROR_FAIL; + } + + if (!xlu_cfg_get_string (config, "name", &buf)) + name = strdup(buf); + else + name = basename(filename); + if (!libxl_name_to_poolid(&ctx, name, &poolid)) { + fprintf(stderr, "Pool name \"%s\" already exists\n", name); + return -ERROR_FAIL; + } + + if (!xlu_cfg_get_string (config, "sched", &buf)) { + if ((schedid = libxl_name_to_schedid(&ctx, buf)) < 0) { + fprintf(stderr, "Unknown scheduler\n"); + return -ERROR_FAIL; + } + } else { + if ((schedid = libxl_get_sched_id(&ctx)) < 0) { + fprintf(stderr, "get_sched_id sysctl failed.\n"); + return -ERROR_FAIL; + } + } + sched = libxl_schedid_to_name(&ctx, schedid); + + if (libxl_get_freecpus(&ctx, &max_cpus, &freemap)) { + fprintf(stderr, "libxl_get_freecpus failed\n"); + return -ERROR_FAIL; + } + cpumap = calloc((max_cpus + 63) / 64, sizeof (*cpumap)); + if (!cpumap) { + fprintf(stderr, "Failed to allocate cpumap\n"); + return -ERROR_FAIL; + } + if (!xlu_cfg_get_list(config, "cpus", &cpus, 0)) { + n_cpus = 0; + while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) { + i = atoi(buf); + if ((i < 0) || (i >= max_cpus) || + !(freemap[i / 64] & (1L << (i % 64)))) { + fprintf(stderr, "cpu %d illegal or not free\n", i); + return -ERROR_FAIL; + } + cpumap[i / 64] |= 1L << (i % 64); + n_cpus++; + } + } else { + n_cpus = 1; + n = 0; + for (i = 0; i < max_cpus; i++) + if (freemap[i / 64] & (1L << (i % 64))) { + n++; + cpumap[i / 64] = 1L << (i % 64); + break; + } + if (n != n_cpus) { + fprintf(stderr, "no free cpu found\n"); + return -ERROR_FAIL; + } + } + + random_uuid(&uuid); + + printf("Using config file \"%s\"\n", filename); + printf("pool name: %s\n", name); + printf("scheduler: %s\n", sched); + printf("number of cpus: %d\n", n_cpus); + + if (dryrun) + return 0; + + poolid = 0; + if (libxl_create_cpupool(&ctx, name, schedid, cpumap, max_cpus, &uuid, + &poolid)) { + fprintf(stderr, "error on creating cpupool\n"); + return -ERROR_FAIL; + } + + return 0; +} + +int main_poollist(int argc, char **argv) +{ + int opt; + int option_index = 0; + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"long", 0, 0, 'l'}, + {"cpus", 0, 0, 'c'}, + {0, 0, 0, 0} + }; + int opt_long = 0; + int opt_cpus = 0; + char *pool = NULL; + libxl_poolinfo *poolinfo; + int n_pools, p, c, n; + uint32_t poolid; + char *name; + + while (1) { + opt = getopt_long(argc, argv, "hlc", long_options, &option_index); + if (opt == -1) + break; + + switch (opt) { + case 'h': + help("pool-create"); + return 0; + case 'l': + opt_long = 1; + break; + case 'c': + opt_cpus = 1; + break; + default: + fprintf(stderr, "option not supported\n"); + break; + } + } + + if ((optind + 1) < argc) { + help("pool-list"); + return -ERROR_FAIL; + } + if (optind < argc) { + pool = argv[optind]; + if (libxl_name_to_poolid(&ctx, pool, &poolid)) { + fprintf(stderr, "Pool \'%s\' does not exist\n", pool); + return -ERROR_FAIL; + } + } + + poolinfo = libxl_list_pool(&ctx, &n_pools); + if (!poolinfo) { + fprintf(stderr, "error getting cpupool info\n"); + return -ERROR_NOMEM; + } + + if (!opt_long) { + printf("%-19s", "Name"); + if (opt_cpus) + printf("CPU list\n"); + else + printf("CPUs Sched Active Domain count\n"); + } + + for (p = 0; p < n_pools; p++) { + if (pool && (poolinfo[p].poolid != poolid)) + continue; + name = libxl_poolid_to_name(&ctx, poolinfo[p].poolid); + if (!name) { + fprintf(stderr, "error getting cpupool info\n"); + return -ERROR_NOMEM; + } + if (opt_long) { + return -ERROR_NI; + } else { + printf("%-19s", name); + n = 0; + for (c = 0; c < poolinfo[p].cpumap_size; c++) + if (poolinfo[p].cpumap[c / 64] & (1L << (c % 64))) { + if (n && opt_cpus) printf(","); + if (opt_cpus) printf("%d", c); + n++; + } + if (!opt_cpus) { + printf("%3d %9s y %4d", n, + libxl_schedid_to_name(&ctx, poolinfo[p].sched_id), + poolinfo[p].n_dom); + } + printf("\n"); + } + } + + return 0; +} + +int main_pooldestroy(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-destroy"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + pool = argv[optind]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-destroy"); + return -ERROR_FAIL; + } + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_destroy_cpupool(&ctx, poolid); +} + +int main_poolcpuadd(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + int cpu; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-cpu-add"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + pool = argv[optind++]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-cpu-add"); + return -ERROR_FAIL; + } + + if (!argv[optind]) { + fprintf(stderr, "no cpu specified\n"); + help("pool-cpu-add"); + return -ERROR_FAIL; + } + cpu = atoi(argv[optind]); + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_cpupool_cpuadd(&ctx, poolid, cpu); +} + +int main_poolcpuremove(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + int cpu; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-cpu-remove"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + pool = argv[optind++]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-cpu-remove"); + return -ERROR_FAIL; + } + + if (!argv[optind]) { + fprintf(stderr, "no cpu specified\n"); + help("pool-cpu-remove"); + return -ERROR_FAIL; + } + cpu = atoi(argv[optind]); + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_cpupool_cpuremove(&ctx, poolid, cpu); +} + +int main_poolmigrate(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + char *dom; + uint32_t domid; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-migrate"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + dom = argv[optind++]; + if (!dom) { + fprintf(stderr, "no domain specified\n"); + help("pool-migrate"); + return -ERROR_FAIL; + } + + pool = argv[optind++]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-migrate"); + return -ERROR_FAIL; + } + + if (domain_qualifier_to_domid(dom, &domid, NULL) || + !libxl_domid_to_name(&ctx, domid)) { + fprintf(stderr, "unknown domain \'%s\'\n", dom); + return -ERROR_FAIL; + } + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_cpupool_movedomain(&ctx, poolid, domid); +} diff -r 12322ad00ea2 tools/libxl/xl_cmdtable.c --- a/tools/libxl/xl_cmdtable.c Thu Aug 05 11:23:10 2010 +0200 +++ b/tools/libxl/xl_cmdtable.c Wed Aug 11 09:45:54 2010 +0200 @@ -336,6 +336,41 @@ struct cmd_spec cmd_table[] = { "destroy a domain's version 2 virtual network device", " ", }, + { "pool-create", + &main_poolcreate, + "Create a CPU pool based an ConfigFile", + "[options] [vars]", + "-h, --help Print this help.\n" + "-f=FILE, --defconfig=FILE Use the given configuration file.\n" + "-n, --dryrun Dry run - prints the resulting configuration." + }, + { "pool-list", + &main_poollist, + "List CPU pools on host", + "[-l|--long] [-c|--cpus] []", + "-l, --long Output all CPU pool details.\n" + "-c, --cpus Output list of CPUs used by a pool" + }, + { "pool-destroy", + &main_pooldestroy, + "Deactivates a CPU pool", + "", + }, + { "pool-cpu-add", + &main_poolcpuadd, + "Adds a CPU to a CPU pool", + " ", + }, + { "pool-cpu-remove", + &main_poolcpuremove, + "Removes a CPU from a CPU pool", + " ", + }, + { "pool-migrate", + &main_poolmigrate, + "Moves a domain into a CPU pool", + " ", + }, }; int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);