diff --git a/README.md b/README.md index a4a7215..b08a701 100644 --- a/README.md +++ b/README.md @@ -354,24 +354,6 @@ Examples $ vng --vsock-connect ``` - - Connect to a remote shell with proper dimensions, env vars, and using 'Fish': -``` - # Start the vng instance with vsock support: - $ vng --vsock "${PWD}/console.sh" - - # In a separate terminal run the following commands: - $ read -r rows columns <<< "$(stty size)" - $ cat <<-EOF > console.sh - #! /bin/bash - stty rows ${rows} columns ${columns} - cd "\${virtme_chdir}" - HOME=${HOME} - fish # use use zsh, tmux, byobu, screen, etc. - EOF - $ chmod +x console.sh - $ vng --vsock-connect -``` - - Run virtme-ng inside a docker container: ``` $ docker run -it --privileged ubuntu:23.10 /bin/bash diff --git a/virtme/commands/run.py b/virtme/commands/run.py index 0b2cbd1..1bb8239 100644 --- a/virtme/commands/run.py +++ b/virtme/commands/run.py @@ -133,13 +133,16 @@ def make_parser() -> argparse.ArgumentParser: g.add_argument( "--vsock", action="store", - default=None, - help="Enable a VSock to communicate from the host to the device and " - + "execute the specified command.", + nargs="?", + metavar="COMMAND", + const="", + help="Enable a VSock to communicate from the host to the device. " + + "An argument can be optionally specified to start a different command.", ) g.add_argument( "--vsock-cid", action="store", + metavar="CID", type=int, default=3, help="CID for the VSock.", @@ -866,7 +869,27 @@ def is_subpath(path, potential_parent): def do_it() -> int: args = _ARGPARSER.parse_args() + vsock_script_path = os.path.join(tempfile.gettempdir(), "virtme-vsock", + f"{args.vsock_cid}.sh") + if args.vsock_connect: + # Note: we could accept arguments passed to --vsock-connect to run a + # specific command, and return, without requiring an interactive tty. + try: + (cols, rows) = os.get_terminal_size() + except OSError: + cols, rows = (80, 24) + + with open(vsock_script_path, 'w', encoding="utf-8") as file: + print(( + '#! /bin/bash\n' + f'stty rows {rows} cols {cols} iutf8 echo\n' + 'HOME=$(getent passwd ${virtme_user:-root} | cut -d: -f6)\n' + 'cd ${virtme_chdir:+"${virtme_chdir}"}\n' + 'exec su ${virtme_user:-root}' + ), file=file) + os.chmod(vsock_script_path, 0o755) + tty = os.ttyname(sys.stdin.fileno()) command = ['socat', f'file:{tty},raw,echo=0', f'VSOCK-CONNECT:{args.vsock_cid}:1024'] @@ -1409,8 +1432,34 @@ def get_net_mac(index): ] ) - if args.vsock: - kernelargs.extend([f"virtme.vsockexec=`{args.vsock}`"]) + def cleanup_vsock_script(): + os.unlink(vsock_script_path) + + if args.vsock is not None: + if os.path.exists(vsock_script_path): + arg_fail("vsock: '%s' file exists: " % vsock_script_path + + "another VM is running with the same --vsock-cid? " + + "If not, remove this file.") + + # create an empty file that can be populated later on + vsock_script_dir = os.path.dirname(vsock_script_path) + os.makedirs(vsock_script_dir, exist_ok=True) + open(vsock_script_path, 'w', encoding="utf-8").close() + atexit.register(cleanup_vsock_script) + + if args.vsock: + vsock_exec = args.vsock + else: + vsock_exec = vsock_script_path + if args.root != "/": + virtfs_config = VirtFSConfig( + path=vsock_script_dir, + mount_tag="virtme.vsockmount", + ) + export_virtfs(qemu, arch, qemuargs, virtfs_config) + kernelargs.append("virtme_vsockmount=%s" % vsock_script_dir) + + kernelargs.extend([f"virtme.vsockexec=`{vsock_exec}`"]) qemuargs.extend(["-device", "vhost-vsock-pci,guest-cid=%d" % args.vsock_cid]) if args.pwd: diff --git a/virtme/guest/virtme-init b/virtme/guest/virtme-init index 2681ad7..45eeaf2 100755 --- a/virtme/guest/virtme-init +++ b/virtme/guest/virtme-init @@ -277,6 +277,10 @@ fi vsock_exec=$(sed -ne "s/.*virtme.vsockexec=\`\(.*\)\`.*/\1/p" /proc/cmdline) if [[ -n "${vsock_exec}" ]]; then + if [[ -n "${virtme_vsockmount}" ]]; then + mkdir -p "${virtme_vsockmount}" + mount -t 9p -o version=9p2000.L,trans=virtio,access=any "virtme.vsockmount" "${virtme_vsockmount}" + fi socat "VSOCK-LISTEN:1024,reuseaddr,fork" \ "EXEC:\"${vsock_exec}\",pty,stderr,setsid,sigint,sane,echo=0" & fi diff --git a/virtme_ng/run.py b/virtme_ng/run.py index 48744a8..2c5aa7f 100644 --- a/virtme_ng/run.py +++ b/virtme_ng/run.py @@ -362,15 +362,17 @@ def make_parser(): parser.add_argument( "--vsock", action="store", - const="bash -i", nargs="?", + metavar="COMMAND", + const="", help="Enable a VSock to communicate from the host to the device. " - + "An argument can be optionally specified to start a different shell.", + + "An argument can be optionally specified to start a different command.", ) parser.add_argument( "--vsock-cid", action="store", + metavar="CID", type=int, help="CID for the VSock.", ) diff --git a/virtme_ng_init b/virtme_ng_init index c43ba1c..c12db88 160000 --- a/virtme_ng_init +++ b/virtme_ng_init @@ -1 +1 @@ -Subproject commit c43ba1ca5d91953a723eb1d6d0f7b4b88da327ca +Subproject commit c12db8879ab4583b8aa80664f1c5fd17d309b36e