diff --git a/cmd/env b/cmd/env index cb27fc3..08b0fa3 100644 --- a/cmd/env +++ b/cmd/env @@ -52,9 +52,7 @@ _env() { _require_program socat exampledir="${BASEDIR}/examples/vm" - if [[ ! -d ${exampledir} ]]; then - _fatal 1 "Example dir (${exampledir}) not found." - fi + _require_path "${exampledir}" if [ ! -d "${bootstrap_dir}" ]; then if ! mkdir --parent ${verbose} "${bootstrap_dir}"; then diff --git a/cmd/run b/cmd/run index 81b087a..2951f20 100644 --- a/cmd/run +++ b/cmd/run @@ -49,11 +49,7 @@ _run() { while true; do case "$1" in '-k' | '--kernel-dir' ) - local kernel_dir="$2"; shift 2 - - if [[ ! -d "$kernel_dir" ]]; then - _fatal 1 "no such directory: '$kernel_dir'" - fi + local kernel_dir="$2" ; shift 2 ;; '-c' | '--cloud-init' ) @@ -145,8 +141,9 @@ _run() { QEMU_PARAMS+=("-pidfile" "${VMROOT}/run/${VMNAME}/pidfile") if [[ -v kernel_dir ]]; then - qemu_kern_add_custom --kernel-dir "${kernel_dir}" + GUEST_KERNEL_CUSTOM_DIR="${kernel_dir}" fi + qemu_kernel_setup if [[ -v do_background ]]; then QEMU_PARAMS+=("-daemonize") diff --git a/common/rc b/common/rc index 3222a5a..5c1c7f7 100644 --- a/common/rc +++ b/common/rc @@ -130,13 +130,21 @@ _require_program() { } _require_path() { - local rpath="$1"; shift + local rpath="$1" if [[ ! -d "${rpath}" ]]; then _fatal 1 "Path not found (${rpath}). $*" fi } +_require_vars() { + for var in $1; do + if [[ ! -v ${var} ]]; then + _fatal 1 "${FUNCNAME[0]} Missing var ${var}. Missing in ${VMCONFIG}?" + fi + done +} + _is_running() { if [[ -f "${VMRUN}/pidfile" ]]; then return 0 diff --git a/common/shellcheck b/common/shellcheck index 73629e8..c585dfb 100644 --- a/common/shellcheck +++ b/common/shellcheck @@ -6,5 +6,9 @@ # suppress unused global variable warnings _silence_sc2034() { - echo "$QEMU_SYSTEM_BINARY $QEMU_TRACE_EVENTS ${GUEST_KERNEL_CMDLINE[*]} $RESET" > /dev/null + echo "$QEMU_SYSTEM_BINARY \ + $QEMU_TRACE_EVENTS \ + ${GUEST_KERNEL_CMDLINE[*]} \ + $RESET \ + $GUEST_KERNEL_CUSTOM_DIR " > /dev/null } diff --git a/lib/qemu/kern b/lib/qemu/kern index 333f012..6e8dde3 100644 --- a/lib/qemu/kern +++ b/lib/qemu/kern @@ -5,13 +5,7 @@ # Written by Joel Granados _qemu_kern_img_add() { - local cmdline_extra="$1" - - for var in GUEST_BOOT GUEST_BOOT_BASE; do - if [[ ! -v ${var} ]]; then - _fatal 1 "${FUNCNAME[0]} Missing var ${var}. Add it to ${VMCONFIG}" - fi - done + _require_vars "GUEST_BOOT GUEST_BOOT_BASE" if [[ ! -f "${VMROOT}/$GUEST_BOOT" ]]; then if [[ ! -f "${VMROOT}/$GUEST_BOOT_BASE" ]]; then @@ -27,66 +21,33 @@ _qemu_kern_img_add() { GUEST_KERNEL_BOOTDEV="/dev/vda1" fi - local cmdline="root=${GUEST_KERNEL_BOOTDEV} console=${GUEST_KERNEL_CONSOLE} ${cmdline_extra}" - if [[ -v GUEST_KERNEL_APPEND_EXTRA ]]; then - cmdline="$cmdline ${GUEST_KERNEL_APPEND_EXTRA}" - fi - - QEMU_PARAMS+=("-kernel" "${kernel_dir}/${GUEST_KERNEL_IMAGE}") - QEMU_PARAMS+=("-append" "$cmdline") + QEMU_PARAMS+=("-kernel" "${GUEST_KERNEL_CUSTOM_DIR}/${GUEST_KERNEL_IMAGE}") + QEMU_PARAMS+=("-append" \ + "root=${GUEST_KERNEL_BOOTDEV} console=${GUEST_KERNEL_CONSOLE} ${GUEST_KERNEL_APPEND_EXTRA}") } -qemu_kern_add_custom() { - local cmdline_extra="" - local mod_share="9p" - local long="kernel-dir:,cmdline-extra:,mod-share:" - - if ! tmp=$(getopt -o "" --long "$long" -n "${FUNCNAME[0]}" -- "$@"); then - exit 1 - fi - - eval set -- "$tmp" - unset tmp - - while true; do - case "$1" in - '--kernel-dir' ) - local kernel_dir="$2"; shift 2 - ;; - '--cmdline-extra' ) - cmdline_extra="${cmdline_extra} $2"; shift 2 - ;; - 'mod-share' ) - mod_share="$2"; shift 2 - ;; - '--' ) - shift; break - ;; - * ) - _fatal 1 "unknown argument '$1'" - ;; - esac - done - - if [[ ! -v kernel_dir ]]; then - _fatal 1 "${FUNCNAME[0]} Missing required --kernel-dir argument" +qemu_kernel_setup() { + if [[ ! -v GUEST_KERNEL_CUSTOM_DIR ]]; then + # Yes!; Do nothing with image-backed + if [[ -v NIX_STORE_PATH ]]; then + _require_vars "GUEST_KERNEL_IMAGE GUEST_KERNEL_CONSOLE" + qemu_nix_add_noimgnix + fi + return fi - for var in GUEST_KERNEL_IMAGE GUEST_KERNEL_CONSOLE; do - if [[ ! -v ${var} ]]; then - _fatal 1 "${FUNCNAME[0]} Missing var ${var}. Add it to ${VMCONFIG}" - fi - done + _require_path "${GUEST_KERNEL_CUSTOM_DIR}" + _require_vars "GUEST_KERNEL_IMAGE GUEST_KERNEL_CONSOLE" if [[ -v NIX_STORE_PATH ]]; then qemu_nix_add_noimgnix + local mod_share="virtiofs" else - _qemu_kern_img_add "${cmdline_extra}" + _qemu_kern_img_add + local mod_share="9p" fi - local kernel_tag="kernel_dir" - qemu_share_add --shared-dir "${kernel_dir}" \ - --tag "${kernel_tag}" \ + qemu_share_add --shared-dir "${GUEST_KERNEL_CUSTOM_DIR}" \ + --tag "kernel_dir" \ --share-type "${mod_share}" } - diff --git a/lib/qemu/nix b/lib/qemu/nix index 200e1e1..0bddfeb 100644 --- a/lib/qemu/nix +++ b/lib/qemu/nix @@ -7,7 +7,7 @@ _qemu_nix_create_nix_sys () { local dst_path="$1" local flake_attr_path="nixosConfigurations.vm.config.system.build.toplevel" - local flake_dst_dir="${VMSTATE}" + local flake_dst_dir="${VMSTATE}/nixstage" local flake_dst_path="${flake_dst_dir}/flake.nix" : "${NIX_FLAKE_PATH:="${BASEDIR}/contrib/nix/x86_64-noimgnix-base.nix"}" @@ -15,18 +15,13 @@ _qemu_nix_create_nix_sys () { _fatal 1 "${FUNCNAME[0]}: File not found (${NIX_FLAKE_PATH})" fi - if ! cp -f "${NIX_FLAKE_PATH}" "${flake_dst_path}"; then - _fatal 1 "${FUNCNAME[0]}: Error copying \ - src:(${NIX_FLAKE_PATH}) dest:(${flake_dst_path})" - fi + _add_pre_cmd "mkdir -p \"${flake_dst_dir}\"" + _add_pre_cmd "cp -f \"${NIX_FLAKE_PATH}\" \"${flake_dst_path}\"" - local nix_build_cmd="nix build \ + _add_pre_cmd "nix build \ 'path:${flake_dst_dir}#${flake_attr_path}' \ -o \"${dst_path}\" \ --no-write-lock-file" - if ! eval "${nix_build_cmd}"; then - _fatal 1 "${FUNCNAME[0]}: Error running '${nix_build_cmd}'" - fi } _qemu_nix_create_nix_init () { @@ -41,89 +36,55 @@ _qemu_nix_create_nix_init () { local make_path="${state_dir}/Makefile" if [[ ! -f ${make_path} ]]; then - if ! ln -s "${BASEDIR}/contrib/nix/Makefile" "${make_path}"; then - _fatal 1 "${FUNCNAME[0]}: Error creating sym link for ${make_path}" - fi + _add_pre_cmd "ln -s \"${BASEDIR}/contrib/nix/Makefile\" \"${make_path}\"" fi local c_init_path="${state_dir}/vmctl_init.c" if [[ ! -f ${c_init_path} ]]; then - if ! ln -s "${BASEDIR}/contrib/nix/vmctl_init.c" "${c_init_path}"; then - _fatal 1 "${FUNCNAME[0]}: Error creating sym link for ${c_init_path}" - fi + _add_pre_cmd "ln -s \"${BASEDIR}/contrib/nix/vmctl_init.c\" \"${c_init_path}\"" fi if [[ ${NIX_INIT_REBUILD} == "yes" ]]; then - if ! make -C "${state_dir}" clean; then - _fatal 1 "${FUNCNAME[0]}: Error cleaning ${c_init_path}" - fi - fi - if ! make -C "${state_dir}" all; then - _fatal 1 "${FUNCNAME[0]}: Error compiling ${c_init_path}" + _add_pre_cmd "make -C \"${state_dir}\" clean" fi + + _add_pre_cmd "make -C \"${state_dir}\" all" } qemu_nix_add_noimgnix () { _require_program nix _require_path "${NIX_STORE_PATH}" + _require_vars "VMSTATE" - local long="cmd-line-extra:" - - if ! tmp=$(getopt -o "" --long "$long" -n "${FUNCNAME[0]}" -- "$@"); then - exit 1 - fi - - eval set -- "$tmp" - unset tmp - - local cmd_line_extra="" - while true; do - case "$1" in - '--cmd-line-extra' ) - cmd_line_extra="$2"; shift 2 - ;; - '--' ) - shift; break - ;; - * ) - _fatal 1 "unknown argument '$1'" - ;; - esac - done - - if [[ ! -v VMSTATE ]]; then - _fatal 1 "${FUNCNAME[0]}: VMSTATE global var is not set" - fi - - local dst_path="${VMSTATE}/nixsys" + local nixsys_link="${VMSTATE}/nixsys" + local nixsys_path=""; nixsys_path="$(readlink -f "${nixsys_link}")" : "${NIX_SYS_BUILD_FORCE:="no"}" # defaults to "no" if not set - if [[ ${NIX_SYS_BUILD_FORCE} == "yes" || ! -h ${dst_path} ]]; then - _qemu_nix_create_nix_sys "${dst_path}" + if [[ ${NIX_SYS_BUILD_FORCE} == "yes" || ! -h ${nixsys_link} ]]; then + _qemu_nix_create_nix_sys "${nixsys_link}" fi - _qemu_nix_create_nix_init "${VMSTATE}" - qemu_share_add --shared-dir "${NIX_STORE_PATH}" \ --tag "nixstore" \ --share-type "virtiofs" \ --vm-dir "/nix/store" - local nix_init_path="" - nix_init_path="$(readlink "${dst_path}")/init" - local cmd_line="root=/dev/ram0 console=${GUEST_KERNEL_CONSOLE}" - if [[ -v GUEST_KERNEL_APPEND_EXTRA ]]; then - cmd_line="${cmd_line} ${GUEST_KERNEL_APPEND_EXTRA}" + _qemu_nix_create_nix_init "${VMSTATE}" + + if [[ -v GUEST_KERNEL_CUSTOM_DIR ]]; then + QEMU_PARAMS+=("-kernel" "${GUEST_KERNEL_CUSTOM_DIR}/${GUEST_KERNEL_IMAGE}") + QEMU_PARAMS+=("-initrd" "${VMSTATE}/init.img") + else + _fatal 1 "${FUNCNAME[0]}: Running a nixvm without a kernel is unsupported" fi - cmd_line="${cmd_line} ${cmd_line_extra}" - cmd_line="${cmd_line} -- --init-path ${nix_init_path}" + + local cmd_line="root=/dev/ram0 console=${GUEST_KERNEL_CONSOLE}" + cmd_line="${cmd_line} ${GUEST_KERNEL_APPEND_EXTRA}" + cmd_line="${cmd_line} -- --init-path ${nixsys_path}/init" if [[ -v NIX_MOUNTS ]]; then for nmount in "${NIX_MOUNTS[@]}"; do cmd_line="${cmd_line} --mount ${nmount}" done fi - QEMU_PARAMS+=("-kernel" "${kernel_dir}/${GUEST_KERNEL_IMAGE}") QEMU_PARAMS+=("-append" "${cmd_line}") - QEMU_PARAMS+=("-initrd" "${VMSTATE}/init.img") - } diff --git a/lib/qemu/share b/lib/qemu/share index 4cb375f..5d21276 100644 --- a/lib/qemu/share +++ b/lib/qemu/share @@ -6,9 +6,7 @@ _qemu_share_force_memshare() { # memshare for virtiofs https://virtio-fs.gitlab.io/howto-qemu.html - if [[ ! -v GUEST_MEMORY ]]; then - _fatal 1 "${FUNCNAME[0]}: GUEST_MEMORY variable is undefined" - fi + _require_vars "GUEST_MEMORY" if [[ "${QEMU_PARAMS[*]}" != *"memory-backend-file"* ]]; then QEMU_PARAMS+=("-object" "memory-backend-file,id=mem,size=${GUEST_MEMORY},mem-path=/dev/shm,share=on") @@ -79,9 +77,7 @@ qemu_share_add() { _fatal 1 "${FUNCNAME[0]}: missing required '--shared-dir' argument" fi - if [[ ! -d ${shared_dir} ]]; then - _fatal 1 "${FUNCNAME[0]}: ${shared_dir} does not exist" - fi + _require_path "${shared_dir}" if [[ ! -v tag ]]; then _fatal 1 "${FUNCNAME[0]}: missing required '--tag' argument" diff --git a/vmctl b/vmctl index 8b6b94f..262f1b5 100755 --- a/vmctl +++ b/vmctl @@ -73,11 +73,8 @@ _main() { ;; '-b' | '--basedir' ) - if [[ ! -d "$2" ]]; then - _fatal 1 "invalid base directory '$2'" - fi - VMCTL_VMROOT="$2"; shift 2 + _require_path "${VMCTL_VMROOT}" ;; '-h' | '--help' )