[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 12/15] libxl: introduce libxl_retrieve_domain_configuration
Introduce a new public API to return domain configuration. This returned configuration can be used to rebuild a domain. Note that this configuration only describes the configuration necessary to reproduce the guest visible state and does not necessarily include specific decisions made by the toolstack regarding its current incarnation (e.g. disk backend) unless they were specified by the application when the domain was created. With this approach we can preserve what user has provided in the original configuration as well as valuable information from xenstore. Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx> --- change in v3: correct target memory calculation --- tools/libxl/libxl.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl.h | 16 +++++ 2 files changed, 210 insertions(+) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index e2a956c..2e8ea72 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -6119,6 +6119,200 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src) for (i = 0; i < 6; i++) (*dst)[i] = (*src)[i]; } + +int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid, + libxl_domain_config *d_config) +{ + GC_INIT(ctx); + int rc; + libxl__carefd *lock = NULL; + + CTX_LOCK; + + lock = libxl__lock_domain_userdata(gc, domid); + if (!lock) { + rc = ERROR_LOCK_FAIL; + goto out; + } + + rc = libxl__get_domain_configuration(gc, domid, d_config); + if (rc) { + LOG(ERROR, "fail to get domain configuration for domain %d", domid); + rc = ERROR_FAIL; + goto out; + } + + /* Domain name */ + { + char *domname; + domname = libxl_domid_to_name(ctx, domid); + if (!domname) { + LOG(ERROR, "fail to get domain name for domain %d", domid); + goto out; + } + free(d_config->c_info.name); + d_config->c_info.name = domname; /* steals allocation */ + } + + /* Domain UUID */ + { + libxl_dominfo info; + rc = libxl_domain_info(ctx, &info, domid); + if (rc) { + LOG(ERROR, "fail to get domain info for domain %d", domid); + goto out; + } + libxl_uuid_copy(ctx, &d_config->c_info.uuid, &info.uuid); + } + + /* Memory limits: + * + * Currently there are three memory limits: + * 1. "target" in xenstore (originally memory= in config file) + * 2. "static-max" in xenstore (originally maxmem= in config file) + * 3. "max_memkb" in hypervisor + * + * The third one is not visible and currently managed by + * toolstack. In order to rebuild a domain we only need to have + * "target" and "static-max". + */ + { + uint32_t memory; + + /* "target" */ + rc = libxl__get_memory_target(gc, domid, &memory, true); + if (rc) { + LOG(ERROR, "fail to get memory target for domain %d", domid); + goto out; + } + /* Target memory in xenstore is different from what user has + * asked for. The difference is video_memkb. See + * libxl_set_memory_target. + */ + d_config->b_info.target_memkb = memory + d_config->b_info.video_memkb; + + /* "static-max" */ + rc = libxl__get_memory_target(gc, domid, &memory, false); + if (rc) { + LOG(ERROR, "fail to get memory static-max for domain %d", domid); + goto out; + } + d_config->b_info.max_memkb = memory; + } + + /* Devices: disk, nic, vtpm, pcidev etc. */ + + /* The MERGE macro implements following logic: + * 0. retrieve JSON (done by now) + * 1. retrieve list of device from xenstore + * 2. use xenstore entries as primary reference and compare JSON + * entries with them. + * a. if a device is present in xenstore and in JSON, merge the + * two views. + * b. if a device is not present in xenstore but in JSON, delete + * it from the result. + * c. it's impossible to have an entry present in xenstore but + * not in JSON, because we maintain an invariant that every + * entry in xenstore must have a corresponding entry in JSON. + * 3. "merge" operates on "src" and "dst". "src" points to the + * entry retrieved from xenstore while "dst" points to the entry + * retrieve from JSON. + */ +#define MERGE(type, ptr, compare, merge) \ + do { \ + libxl_device_##type *p = NULL; \ + int i, j, num; \ + \ + p = libxl_device_##type##_list(CTX, domid, &num); \ + if (p == NULL) { \ + LOG(DEBUG, \ + "no %s from xenstore for domain %d", \ + #type, domid); \ + } \ + \ + for (i = 0; i < d_config->num_##ptr; i++) { \ + libxl_device_##type *q = &d_config->ptr[i]; \ + for (j = 0; j < num; j++) { \ + if (compare(&p[j], q)) \ + break; \ + } \ + \ + if (j < num) { /* found in xenstore */ \ + libxl_device_##type *dst, *src; \ + dst = q; \ + src = &p[j]; \ + merge; \ + } else { /* not found in xenstore */ \ + LOG(WARN, \ + "Device present in JSON but not in xenstore, ignored"); \ + \ + libxl_device_##type##_dispose(q); \ + \ + for (j = i; j < d_config->num_##ptr - 1; j++) \ + memcpy(&d_config->ptr[j], &d_config->ptr[j+1], \ + sizeof(libxl_device_##type)); \ + \ + d_config->ptr = \ + libxl__realloc(NOGC, d_config->ptr, \ + sizeof(libxl_device_##type) * \ + (d_config->num_##ptr - 1)); \ + \ + /* rewind counters */ \ + d_config->num_##ptr--; \ + i--; \ + } \ + } \ + \ + for (i = 0; i < num; i++) \ + libxl_device_##type##_dispose(&p[i]); \ + free(p); \ + } while (0); + + MERGE(nic, nics, COMPARE_DEVID, { + libxl__update_config_nic(gc, dst, src); + }); + + MERGE(vtpm, vtpms, COMPARE_DEVID, { + libxl__update_config_vtpm(gc, dst, src); + }); + + MERGE(pci, pcidevs, COMPARE_PCI, {}); + + /* Take care of removable device. We maintain invariant in the + * insert / remove operation so that: + * 1. if xenstore is "empty" while JSON is not, the result + * is "empty" + * 2. if xenstore has a different media than JSON, use the + * one in JSON + * 3. if xenstore and JSON have the same media, well, you + * know the answer :-) + * + * Currently there is only one removable device -- CDROM. + * Look for libxl_cdrom_insert for reference. + */ + MERGE(disk, disks, COMPARE_DISK, { + if (src->removable) { + if (!src->pdev_path || *src->pdev_path == '\0') { + /* 1, use "empty" */ + free(dst->pdev_path); + dst->pdev_path = libxl__strdup(NOGC, ""); + dst->format = LIBXL_DISK_FORMAT_EMPTY; + } else { + /* 2 and 3, use JSON, no need to touch anything */ + ; + } + } + }); + +#undef MERGE + +out: + if (lock) libxl__unlock_domain_userdata(lock); + CTX_UNLOCK; + GC_FREE; + return rc; +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index dab3a67..7243023 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -368,6 +368,14 @@ typedef struct libxl__ctx libxl_ctx; #endif #endif +/* LIBXL_HAVE_RETRIEVE_DOMAIN_CONFIGURATION + * + * If this is defined we have libxl_retrieve_domain_configuration which + * returns the current configuration of a domain, which can be used to + * rebuild a domain. + */ +#define LIBXL_HAVE_RETRIEVE_DOMAIN_CONFIGURATION 1 + /* * LIBXL_HAVE_BUILDINFO_VCPU_AFFINITY_ARRAYS * @@ -865,6 +873,14 @@ int static inline libxl_domain_create_restore_0x040200( void libxl_domain_config_init(libxl_domain_config *d_config); void libxl_domain_config_dispose(libxl_domain_config *d_config); +/* + * Retrieve domain configuration and filled it in d_config. The + * returned configuration can be used to rebuild a domain. It only + * works with DomU. + */ +int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid, + libxl_domain_config *d_config); + int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags, /* LIBXL_SUSPEND_* */ const libxl_asyncop_how *ao_how) -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |