[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC 38/38] tools: introduce hyperlaunch domain late init
The late domain init helper is a helper tool for late setup of Xenstore for a domain that was created by the hypervisor using hyperlaunch. Signed-off-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx> --- .gitignore | 1 + tools/helpers/Makefile | 12 + tools/helpers/late-init-domains.c | 364 ++++++++++++++++++++++++++++++ tools/helpers/late-init-domains.h | 18 ++ tools/helpers/xs-helpers.c | 117 ++++++++++ tools/helpers/xs-helpers.h | 26 +++ 6 files changed, 538 insertions(+) create mode 100644 tools/helpers/late-init-domains.c create mode 100644 tools/helpers/late-init-domains.h create mode 100644 tools/helpers/xs-helpers.c create mode 100644 tools/helpers/xs-helpers.h diff --git a/.gitignore b/.gitignore index 53f5df000383..7b0c390dbe0d 100644 --- a/.gitignore +++ b/.gitignore @@ -122,6 +122,7 @@ tools/flask/utils/flask-label-pci tools/helpers/init-dom0less tools/helpers/init-xenstore-domain tools/helpers/xen-init-dom0 +tools/helpers/late-init-domains tools/hotplug/common/hotplugpath.sh tools/hotplug/FreeBSD/rc.d/xencommons tools/hotplug/FreeBSD/rc.d/xendriverdomain diff --git a/tools/helpers/Makefile b/tools/helpers/Makefile index 09590eb5b6f0..26fa079e8b1f 100644 --- a/tools/helpers/Makefile +++ b/tools/helpers/Makefile @@ -14,6 +14,7 @@ ifeq ($(CONFIG_ARM),y) TARGETS += init-dom0less endif endif +TARGETS += late-init-domains XEN_INIT_DOM0_OBJS = xen-init-dom0.o init-dom-json.o $(XEN_INIT_DOM0_OBJS): CFLAGS += $(CFLAGS_libxentoollog) @@ -39,6 +40,14 @@ $(INIT_DOM0LESS_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(INIT_DOM0LESS_OBJS): CFLAGS += $(CFLAGS_libxenevtchn) init-dom0less: LDLIBS += $(call xenlibs-ldlibs,ctrl evtchn toollog store light guest foreignmemory) +LATE_INIT_DOMAINS_OBJS = late-init-domains.o xs-helpers.o init-dom-json.o +$(LATE_INIT_DOMAINS_OBJS): CFLAGS += $(CFLAGS_libxentoollog) +$(LATE_INIT_DOMAINS_OBJS): CFLAGS += $(CFLAGS_libxenguest) +$(LATE_INIT_DOMAINS_OBJS): CFLAGS += $(CFLAGS_libxenlight) +$(LATE_INIT_DOMAINS_OBJS): CFLAGS += $(CFLAGS_libxenctrl) +$(LATE_INIT_DOMAINS_OBJS): CFLAGS += $(CFLAGS_libxenstore) +late-init-domains: LDLIBS += $(call xenlibs-ldlibs,ctrl toollog store light guest) + .PHONY: all all: $(TARGETS) @@ -51,6 +60,9 @@ init-xenstore-domain: $(INIT_XENSTORE_DOMAIN_OBJS) init-dom0less: $(INIT_DOM0LESS_OBJS) $(CC) $(LDFLAGS) -o $@ $(INIT_DOM0LESS_OBJS) $(LDLIBS) $(APPEND_LDFLAGS) +late-init-domains: $(LATE_INIT_DOMAINS_OBJS) + $(CC) $(LDFLAGS) -o $@ $(LATE_INIT_DOMAINS_OBJS) $(LDLIBS) $(APPEND_LDFLAGS) + .PHONY: install install: all $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN) diff --git a/tools/helpers/late-init-domains.c b/tools/helpers/late-init-domains.c new file mode 100644 index 000000000000..06911d2e93d1 --- /dev/null +++ b/tools/helpers/late-init-domains.c @@ -0,0 +1,364 @@ + +#include <errno.h> +#include <getopt.h> +#include <inttypes.h> +#include <libxl.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <xenctrl.h> +#include <xenguest.h> +#include <xenstore.h> +#include <xentoollog.h> +#include <xen/io/xenbus.h> + +#include "init-dom-json.h" +#include "late-init-domains.h" +#include "xs-helpers.h" + +static struct option options[] = { + { "console", 0, NULL, 'c' }, + { "xenstore", 1, NULL, 'x' }, + { "force", 0, NULL, 'f' }, + { "verbose", 0, NULL, 'v' }, + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 } +}; + +static void usage(void) +{ + fprintf(stderr, +"Usage:\n" +"\n" +"late-init-domains <options>\n" +"\n" +"where options may include:\n" +"\n" +" --console <con domid> configure the console\n" +" --xenstore <xs domid> domain id of the xenstore domain\n" +" --force force domain introduction even if xenstore entries exist\n" +" -v[v[v]] verbosity constructing xenstore tree\n" +" --help help message\n"); +} + +#define XS_DOM_PERM(x, d, k, v) \ + ret = do_xs_write_dom_with_perm(x, d, k, v, perms, num_perms); \ + if ( ret != 0 ) return ret \ + +#define XS_DIR_PERM(x, p, k, v) \ + ret = do_xs_write_dir_node_with_perm(x, p, k, v, perms, num_perms); \ + if ( ret != 0 ) return ret \ + +static int pages_from_hvm_params( + struct xc_interface_core *xch, libxl_dominfo *info, + struct system_pages *pgs) +{ + int ret; + domid_t domid = info->domid; + + ret = xc_hvm_param_get(xch, domid, HVM_PARAM_STORE_EVTCHN, + &pgs->store.evtchn); + if (ret != 0) { + fprintf(stderr, "err: failed to get dom%d store evtchn\n", domid); + return ret; + } + + ret = xc_hvm_param_get(xch, domid, HVM_PARAM_STORE_PFN, + &pgs->store.pfn); + if (ret < 0) { + fprintf(stderr, "err: failed to get dom%d store pfn\n", domid); + return ret; + } + + if ( pgs->console.enabled ) + { + ret = xc_hvm_param_get(xch, domid, HVM_PARAM_CONSOLE_EVTCHN, + &pgs->console.evtchn); + if (ret != 0) { + fprintf(stderr, "warn: console for dom%d not configured\n", domid); + pgs->console.evtchn = pgs->console.pfn = 0; + return 0; + } + + ret = xc_hvm_param_get(xch, domid, HVM_PARAM_CONSOLE_PFN, + &pgs->console.pfn); + if (ret < 0) { + fprintf(stderr, "warn: console for dom%d not configured\n", domid); + pgs->console.evtchn = pgs->console.pfn = 0; + return 0; + } + } + + return 0; +} + +static int create_xs_entries( + struct xs_handle *xsh, struct system_pages *pgs, libxl_dominfo *di) +{ + char path[128], value[16]; + struct xs_permissions perms[2] = { + {.id = pgs->store.be_domid, .perms = XS_PERM_NONE}, + {.id = di->domid, .perms = XS_PERM_READ}, + }; + uint32_t num_perms = (sizeof(perms) / sizeof((perms)[0])); + int ret = 0; + + while ( do_xs_start_transaction(xsh) == 0 ) + { + XS_DOM_PERM(xsh, di->domid, "", ""); + + snprintf(value, 16, "%d", di->domid); + XS_DOM_PERM(xsh, di->domid, "domid", value); + + XS_DOM_PERM(xsh, di->domid, "memory", ""); + snprintf(value, 16, "%" PRIu64, di->current_memkb); + XS_DOM_PERM(xsh, di->domid, "memory/target", value); + + snprintf(value, 16, "%" PRIu64, di->max_memkb); + XS_DOM_PERM(xsh, di->domid, "memory/static-max", value); + + XS_DOM_PERM(xsh, di->domid, "store", ""); + snprintf(value, 16, "%" PRIu64, pgs->store.evtchn); + XS_DOM_PERM(xsh, di->domid, "store/port", value); + + snprintf(value, 16, "%" PRIu64, pgs->store.pfn); + XS_DOM_PERM(xsh, di->domid, "store/ring-ref", value); + + if ( pgs->console.enabled && pgs->console.evtchn ) + { + char be_path[64], fe_path[64]; + + snprintf(fe_path, 64, "/local/domain/%d/console", di->domid); + snprintf(be_path, 64, "/local/domain/%d/backend/console/%d/0", + pgs->console.be_domid, di->domid); + + /* Backend entries */ + XS_DIR_PERM(xsh, be_path, "", ""); + snprintf(value, 16, "%d", di->domid); + XS_DIR_PERM(xsh, be_path, "frontend-id", value); + XS_DIR_PERM(xsh, be_path, "frontend", fe_path); + XS_DIR_PERM(xsh, be_path, "online", "1"); + XS_DIR_PERM(xsh, be_path, "protocol", "vt100"); + + snprintf(value, 16, "%d", XenbusStateInitialising); + XS_DIR_PERM(xsh, be_path, "state", value); + + /* Frontend entries */ + XS_DOM_PERM(xsh, di->domid, "console", ""); + snprintf(value, 16, "%d", pgs->console.be_domid); + XS_DIR_PERM(xsh, fe_path, "backend", be_path); + XS_DIR_PERM(xsh, fe_path, "backend-id", value); + XS_DIR_PERM(xsh, fe_path, "limit", "1048576"); + XS_DIR_PERM(xsh, fe_path, "type", "xenconsoled"); + XS_DIR_PERM(xsh, fe_path, "output", "pty"); + XS_DIR_PERM(xsh, fe_path, "tty", ""); + + snprintf(value, 16, "%" PRIu64, pgs->console.evtchn); + XS_DIR_PERM(xsh, fe_path, "port", value); + + snprintf(value, 16, "%" PRIu64, pgs->console.pfn); + XS_DIR_PERM(xsh, fe_path, "ring-ref", value); + + } + + snprintf(path, 128, "/libxl/%u", di->domid); + switch ( di->domain_type ) + { + case LIBXL_DOMAIN_TYPE_PV: + XS_DIR_PERM(xsh, path, "type", "pv"); + break; + case LIBXL_DOMAIN_TYPE_PVH: + XS_DIR_PERM(xsh, path, "type", "pvh"); + break; + case LIBXL_DOMAIN_TYPE_HVM: + XS_DIR_PERM(xsh, path, "type", "hvm"); + break; + default: + break; + } + + ret = do_xs_end_transaction(xsh); + switch ( ret ) + { + case 0: + break; /* proceed to loop break */ + case -EAGAIN: + continue; /* try again */ + default: + return ret; /* failed */ + } + + break; + } + + return ret; +} + +static bool init_domain( + struct xc_interface_core *xch, struct xs_handle *xsh, + struct system_pages *pgs, libxl_dominfo *di) +{ + xen_pfn_t con_pfn = 0L; + /*xc_dom_gnttab_seed will do nothing if front == back */ + uint32_t con_domid = di->domid; + bool is_hvm = (di->domain_type == LIBXL_DOMAIN_TYPE_HVM || + di->domain_type == LIBXL_DOMAIN_TYPE_PVH); + int ret; + + if ( (ret = pages_from_hvm_params(xch, di, pgs)) != 0 ) + { + fprintf(stderr, "error(%d): unable to fetch dom%d system pages\n", ret, + di->domid); + return false; + } + + if ( pgs->console.enabled && pgs->console.evtchn ) + { + con_domid = pgs->console.be_domid; + con_pfn = pgs->console.pfn; + } + + ret = xc_dom_gnttab_seed(xch, di->domid, is_hvm, con_pfn, + pgs->store.pfn, con_domid, pgs->store.be_domid); + if ( ret != 0 ) + { + fprintf(stderr, "error (%d) setting up grant tables for dom%d\n", + ret, di->domid); + return false; + } + + libxl_uuid_generate(&di->uuid); + xc_domain_sethandle(xch, di->domid, + libxl_uuid_bytearray(&di->uuid)); + + if ( (ret = gen_stub_json_config(di->domid, &di->uuid)) != 0 ) + fprintf(stderr, "warn(%d): unable generate dom%d json stub\n", ret, + di->domid); + + if ( (ret = create_xs_entries(xsh, pgs, di)) != 0 ) + { + fprintf(stderr, "error(%d): unable create dom%d xenstore entries\n", + ret, di->domid); + return false; + } + + if ( !xs_introduce_domain(xsh, di->domid, pgs->store.pfn, + pgs->store.evtchn) ) + { + fprintf(stderr, "error introducing dom%d\n", di->domid); + return false; + } + + return true; +} + +int main(int argc, char** argv) +{ + int opt, ret, i, nb_vm = 0, count = 0; + bool force = false; + struct xs_handle *xsh = NULL; + struct xc_interface_core *xch = NULL; + xentoollog_level minmsglevel = XTL_PROGRESS; + xentoollog_logger *logger = NULL; + libxl_dominfo *info = NULL; + libxl_ctx *ctx; + struct system_pages pages = { {0} }; + + while ( (opt = getopt_long(argc, argv, "c:x:fv", options, NULL)) != -1 ) + { + switch ( opt ) + { + case 'c': + pages.console.be_domid = strtol(optarg, NULL, 10); + pages.console.enabled = true; + break; + case 'x': + pages.store.be_domid = strtol(optarg, NULL, 10); + break; + case 'f': + force = true; + break; + case 'v': + if ( minmsglevel > 1 ) + minmsglevel--; + break; + case 'h': + usage(); + return 0; + default: + usage(); + return 2; + } + } + + if ( optind != argc ) + { + usage(); + return 1; + } + + logger = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, + minmsglevel, 0); + + xsh = xs_open(0); + xch = xc_interface_open(0, 0, 0); + if ( xsh == NULL || xch == NULL ) + { + fprintf(stderr, "error: unable to connect to xs and/or xc interface\n"); + ret = 1; + goto out; + } + + ret = libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, NULL); + if (ret) { + fprintf(stderr, "cannot init xl context\n"); + goto out; + } + + info = libxl_list_domain(ctx, &nb_vm); + if (!info) { + fprintf(stderr, "libxl_list_vm failed.\n"); + ret = 1; + goto out; + } + + for (i = 0; i < nb_vm; i++) { + domid_t domid = info[i].domid; + + /* Don't need to check for Dom0 */ + if (!domid) + continue; + + if ( xs_is_domain_introduced(xsh, domid) ) + { + if ( !force ) + continue; + + fprintf(stderr, "warning: re-introducting domain %d\n", domid); + } + + if ( init_domain(xch, xsh, &pages, &info[i]) ) + count++; + } + + printf("initialized %d out of %d domains\n", count, nb_vm); + + ret = 0; + +out: + if ( info ) + libxl_dominfo_list_free(info, nb_vm); + + if ( xsh ) + xs_close(xsh); + + if ( xch ) + xc_interface_close(xch); + + if ( logger ) + xtl_logger_destroy(logger); + + return ret; +} diff --git a/tools/helpers/late-init-domains.h b/tools/helpers/late-init-domains.h new file mode 100644 index 000000000000..8d071ef82ea0 --- /dev/null +++ b/tools/helpers/late-init-domains.h @@ -0,0 +1,18 @@ +#ifndef __LATE_INIT_PV_H +#define __LATE_INIT_PV_H + +struct system_pages { + struct { + uint16_t be_domid; + uint64_t evtchn; + uint64_t pfn; + } store; + struct { + bool enabled; + uint16_t be_domid; + uint64_t evtchn; + uint64_t pfn; + } console; +}; + +#endif diff --git a/tools/helpers/xs-helpers.c b/tools/helpers/xs-helpers.c new file mode 100644 index 000000000000..a4d2bebbbd54 --- /dev/null +++ b/tools/helpers/xs-helpers.c @@ -0,0 +1,117 @@ + +#include <err.h> +#include <stdio.h> +#include <string.h> +#include <xenstore.h> + +#define MAX_XS_PAATH 100 + +static xs_transaction_t t_id = XBT_NULL; + +int do_xs_start_transaction(struct xs_handle *xsh) +{ + t_id = xs_transaction_start(xsh); + if (t_id == XBT_NULL) + return -errno; + + return 0; +} + +int do_xs_end_transaction(struct xs_handle *xsh) +{ + if ( t_id == XBT_NULL ) + return -EINVAL; + + if (!xs_transaction_end(xsh, t_id, false)) + return -errno; + + return 0; +} + +int do_xs_write(struct xs_handle *xsh, char *path, char *val) +{ + if ( !xs_write(xsh, t_id, path, val, strlen(val)) ) + { + fprintf(stderr, "failed write: %s\n", path); + return -errno; + } + + return 0; +} + +int do_xs_perms( + struct xs_handle *xsh, char *path, struct xs_permissions *perms, + uint32_t num_perms) +{ + if ( !xs_set_permissions(xsh, t_id, path, perms, num_perms) ) + { + fprintf(stderr, "failed set perm: %s\n", path); + return -errno; + } + + return 0; +} + +int do_xs_write_dir_node_with_perm( + struct xs_handle *xsh, char *dir, char *node, char *val, + struct xs_permissions *perms, uint32_t num_perms) +{ + char full_path[MAX_XS_PAATH]; + int ret = 0; + + /* + * mainly for creating a value holding node, but + * also support creating directory nodes. + */ + if ( strlen(node) != 0 ) + snprintf(full_path, MAX_XS_PAATH, "%s/%s", dir, node); + else + snprintf(full_path, MAX_XS_PAATH, "%s", dir); + + ret = do_xs_write(xsh, full_path, val); + if ( ret < 0 ) + return ret; + + if ( perms != NULL && num_perms > 0 ) + ret = do_xs_perms(xsh, full_path, perms, num_perms); + + return ret; +} + +int do_xs_write_dir_node( + struct xs_handle *xsh, char *dir, char *node, char *val) +{ + return do_xs_write_dir_node_with_perm(xsh, dir, node, val, NULL, 0); +} + +int do_xs_write_dom_with_perm( + struct xs_handle *xsh, uint32_t domid, char *path, char *val, + struct xs_permissions *perms, uint32_t num_perms) +{ + char full_path[MAX_XS_PAATH]; + int ret = 0; + + /* + * mainly for creating a value holding node, but + * also support creating directory nodes. + */ + if ( strlen(path) != 0 ) + snprintf(full_path, MAX_XS_PAATH, "/local/domain/%d/%s", domid, path); + else + snprintf(full_path, MAX_XS_PAATH, "/local/domain/%d", domid); + + ret = do_xs_write(xsh, full_path, val); + if ( ret < 0 ) + return ret; + + if ( perms != NULL && num_perms > 0 ) + ret = do_xs_perms(xsh, full_path, perms, num_perms); + + return ret; +} + +int do_xs_write_dom( + struct xs_handle *xsh, uint32_t domid, char *path, char *val) +{ + return do_xs_write_dom_with_perm(xsh, domid, path, val, NULL, 0); +} diff --git a/tools/helpers/xs-helpers.h b/tools/helpers/xs-helpers.h new file mode 100644 index 000000000000..89585637d4bb --- /dev/null +++ b/tools/helpers/xs-helpers.h @@ -0,0 +1,26 @@ +#ifndef __XS_HELPERS_H +#define __XS_HELPERS_H + +#include <xenstore.h> + +int do_xs_start_transaction(struct xs_handle *xsh); +int do_xs_end_transaction(struct xs_handle *xsh); + +int do_xs_write(struct xs_handle *xsh, char *path, char *val); +int do_xs_perms( + struct xs_handle *xsh, char *path, struct xs_permissions *perms, + uint32_t num_perms); + +int do_xs_write_dir_node_with_perm( + struct xs_handle *xsh, char *dir, char *node, char *val, + struct xs_permissions *perms, uint32_t num_perms); +int do_xs_write_dir_node( + struct xs_handle *xsh, char *dir, char *node, char *val); + +int do_xs_write_dom_with_perm( + struct xs_handle *xsh, uint32_t domid, char *path, char *val, + struct xs_permissions *perms, uint32_t num_perms); +int do_xs_write_dom( + struct xs_handle *xsh, uint32_t domid, char *path, char *val); + +#endif -- 2.30.2
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |