[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] libxl: Implement QEMU command line probe
commit 1817e4c3c5e4cf5ad21b76765bb19a23244b9019 Author: Anthony PERARD <anthony.perard@xxxxxxxxxx> AuthorDate: Thu Aug 29 10:00:46 2024 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu Aug 29 10:00:46 2024 +0200 libxl: Implement QEMU command line probe Starting with QEMU 9.0, the option "-chroot", that we use for the "dmrestrict" feature, is removed. We need to find out which to use between "-chroot" and "-run-with chroot=dir". This patch implement the machinery to spawn QEMU, and to run the QMP command "query-command-line-options" but doesn't yet look at the actual result. Whether or not to use "-run-with chroot=dir" will be implemented in a follow up patch. The command line used to spawn the qemu we want to probe is mostly similar to the one we already use for the device model, "-machine none" comes from libvirt. This patch implement the probing on qemu-xen, even if we probably not going to use the result. We could check the feature wanted for the domain being created, but this could get complicated fairly quickly. We already need to check the options "b_info->dm_restrict" for "-chroot" and "state->dm_runas" for "-runas" (which is deprecated). Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> Reviewed-by: Jason Andryuk <jason.andryuk@xxxxxxx> --- tools/libs/light/libxl_dm.c | 207 ++++++++++++++++++++++++++++++++++++-- tools/libs/light/libxl_internal.h | 1 + 2 files changed, 198 insertions(+), 10 deletions(-) diff --git a/tools/libs/light/libxl_dm.c b/tools/libs/light/libxl_dm.c index ff8ddeec9a..46babfed0b 100644 --- a/tools/libs/light/libxl_dm.c +++ b/tools/libs/light/libxl_dm.c @@ -2858,6 +2858,20 @@ static void device_model_qmp_cb(libxl__egc *egc, libxl__ev_qmp *ev, static void device_model_spawn_outcome(libxl__egc *egc, libxl__dm_spawn_state *dmss, int rc); +static void device_model_probe_startup_failed(libxl__egc *egc, + libxl__spawn_state *spawn, int rc); +static void device_model_probe_confirm(libxl__egc *egc, + libxl__spawn_state *spawn, const char *xsdata); +static void device_model_probe_detached(libxl__egc *egc, + libxl__spawn_state *spawn); +static void device_model_probe_cmdline(libxl__egc *egc, + libxl__ev_qmp *qmp, const libxl__json_object *response, int rc); +static void device_model_probe_quit(libxl__egc *egc, + libxl__ev_qmp *qmp, const libxl__json_object *response, int rc); +static void device_model_probe_spawn_outcome(libxl__egc *egc, + libxl__dm_spawn_state *dmss, int rc); +static void device_model_launch(libxl__egc *egc, + libxl__dm_spawn_state *dmss, int rc); static void device_model_postconfig_chardev(libxl__egc *egc, libxl__ev_qmp *qmp, const libxl__json_object *response, int rc); static void device_model_postconfig_vnc(libxl__egc *egc, @@ -2873,25 +2887,18 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) { /* convenience aliases */ const int domid = dmss->guest_domid; - libxl__domain_build_state *const state = dmss->build_state; libxl__spawn_state *const spawn = &dmss->spawn; STATE_AO_GC(dmss->spawn.ao); - libxl_ctx *ctx = CTX; libxl_domain_config *guest_config = dmss->guest_config; const libxl_domain_create_info *c_info = &guest_config->c_info; const libxl_domain_build_info *b_info = &guest_config->b_info; - const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config); - char *path; - int logfile_w, null; int rc; - char **args, **arg, **envs; - xs_transaction_t t; - char *vm_path; - char **pass_stuff; const char *dm; - int dm_state_fd = -1; + int logfile_w = -1, null = -1; + int qmp_probe_fd = -1; + bool probe_spawned = false; dmss_init(dmss); @@ -2904,6 +2911,7 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) rc = ERROR_FAIL; goto out; } + dmss->dm = dm; if (access(dm, X_OK) < 0) { LOGED(ERROR, domid, "device model %s is not executable", dm); rc = ERROR_FAIL; @@ -2911,6 +2919,185 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) } rc = libxl__domain_get_device_model_uid(gc, dmss); + if (rc) + goto out; + + /* probe QEMU's available command line options */ + if (b_info->device_model_version + == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { + + logfile_w = libxl__create_qemu_logfile( + gc, GCSPRINTF("qemu-probe-%s", c_info->name)); + if (logfile_w < 0) { + rc = logfile_w; + goto out; + } + null = open("/dev/null", O_RDONLY); + if (null < 0) { + LOGED(ERROR, domid, "unable to open /dev/null"); + rc = ERROR_FAIL; + goto out; + } + + rc = libxl__pre_open_qmp_socket(gc, domid, &qmp_probe_fd); + if (rc) goto out; + + flexarray_t *dm_args = flexarray_make(gc, 16, 1); + flexarray_vappend(dm_args, dm, + "-S", + "-no-user-config", + "-nodefaults", + "-nographic", + "-machine", "none,accel=xen", + NULL); + flexarray_vappend(dm_args, + "-chardev", + GCSPRINTF("socket,id=libxl-cmd,fd=%d,server=on,wait=off", + qmp_probe_fd), + "-mon", "chardev=libxl-cmd,mode=control", + NULL); + flexarray_append(dm_args, NULL); + char **exec_args = (char **) flexarray_contents(dm_args); + + const char *dom_path = libxl__xs_get_dompath(gc, domid); + + spawn->what = GCSPRINTF("domain %d qemu command line probe", domid); + spawn->xspath = "/dev/null"; /* No path to watch */ + spawn->timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000; + spawn->pidpath = GCSPRINTF("%s/image/device-model-pid", dom_path); + spawn->midproc_cb = libxl__spawn_record_pid; + spawn->confirm_cb = device_model_probe_confirm; + spawn->failure_cb = device_model_probe_startup_failed; + spawn->detached_cb = device_model_probe_detached; + + dmss->qmp.ao = ao; + dmss->qmp.callback = device_model_probe_cmdline; + dmss->qmp.domid = domid; + dmss->qmp.payload_fd = -1; + rc = libxl__ev_qmp_send(egc, &dmss->qmp, "query-command-line-options", NULL); + if (rc) goto out; + + rc = libxl__spawn_spawn(egc, spawn); + if (rc < 0) + goto out; + if (!rc) { /* inner child */ + setsid(); + libxl__exec(gc, null, logfile_w, logfile_w, dm, exec_args, NULL); + } + probe_spawned = true; + } else { + /* Continue with launching DM instead of probing it */ + probe_spawned = false; + } + rc = 0; +out: + if (qmp_probe_fd >= 0) + close(qmp_probe_fd); + if (null >= 0) + close(null); + if (logfile_w >= 0) + close(logfile_w); + if (rc || !probe_spawned) + device_model_launch(egc, dmss, rc); +} + +static void device_model_probe_startup_failed(libxl__egc *egc, + libxl__spawn_state *spawn, int rc) +{ + libxl__dm_spawn_state *dmss = CONTAINER_OF(spawn, *dmss, spawn); + device_model_probe_spawn_outcome(egc, dmss, rc); +} + +static void device_model_probe_confirm(libxl__egc *egc, + libxl__spawn_state *spawn, const char *xsdata) +{ + /* Nothing to do, confirmation is done via QMP instead */ +} + +static void device_model_probe_detached(libxl__egc *egc, + libxl__spawn_state *spawn) +{ + libxl__dm_spawn_state *dmss = CONTAINER_OF(spawn, *dmss, spawn); + device_model_probe_spawn_outcome(egc, dmss, 0); +} + +static void device_model_probe_cmdline(libxl__egc *egc, + libxl__ev_qmp *qmp, const libxl__json_object *response, int rc) +{ + libxl__dm_spawn_state *dmss = CONTAINER_OF(qmp, *dmss, qmp); + + if (rc) + goto out; + + /* + * query-command-line-options response: + * [ { 'option': 'str', 'parameters': [{ 'name': 'str', ... }] } ] + */ + + qmp->callback = device_model_probe_quit; + rc = libxl__ev_qmp_send(egc, qmp, "quit", NULL); + if (rc) goto out; + return; + +out: + libxl__spawn_initiate_failure(egc, &dmss->spawn, rc); +} + +static void device_model_probe_quit(libxl__egc *egc, + libxl__ev_qmp *qmp, const libxl__json_object *response, int rc) +{ + EGC_GC; + libxl__dm_spawn_state *dmss = CONTAINER_OF(qmp, *dmss, qmp); + + libxl__ev_qmp_dispose(gc, qmp); + libxl__spawn_initiate_detach(gc, &dmss->spawn); +} + +static void device_model_probe_spawn_outcome(libxl__egc *egc, + libxl__dm_spawn_state *dmss, int rc) +{ + EGC_GC; + libxl__ev_qmp_dispose(gc, &dmss->qmp); + + /* Ensure our QEMU command line probe is killed. */ + rc = libxl__kill_xs_path(gc, dmss->spawn.pidpath, + "qemu command-line probe"); + if (rc) { + LOGD(WARN, dmss->guest_domid, + "Killing qemu command-line probe pid from path %s", + dmss->spawn.pidpath); + } + + /* + * Ignore all failure from the QEMU command line probe, start the + * device model in any case. + */ + device_model_launch(egc, dmss, 0); +} + +static void device_model_launch(libxl__egc *egc, + libxl__dm_spawn_state *dmss, int rc) +{ + STATE_AO_GC(dmss->spawn.ao); + libxl_ctx *ctx = CTX; + libxl_domain_config *guest_config = dmss->guest_config; + const libxl_domain_create_info *c_info = &guest_config->c_info; + const libxl_domain_build_info *b_info = &guest_config->b_info; + const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config); + char *path; + int logfile_w, null; + char **args, **arg, **envs; + xs_transaction_t t; + char *vm_path; + char **pass_stuff; + int dm_state_fd = -1; + + /* convenience aliases */ + const int domid = dmss->guest_domid; + libxl__domain_build_state *const state = dmss->build_state; + libxl__spawn_state *const spawn = &dmss->spawn; + const char *const dm = dmss->dm; + if (rc) goto out; diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h index 3b58bb2d7f..e99adc56cb 100644 --- a/tools/libs/light/libxl_internal.h +++ b/tools/libs/light/libxl_internal.h @@ -4154,6 +4154,7 @@ struct libxl__dm_spawn_state { libxl__ev_qmp qmp; libxl__ev_time timeout; libxl__dm_resume_state dmrs; + const char *dm; /* filled in by user, must remain valid: */ uint32_t guest_domid; /* domain being served */ libxl_domain_config *guest_config; -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |