diff --git a/Makefile b/Makefile index bb63579..b478ba4 100644 --- a/Makefile +++ b/Makefile @@ -6,5 +6,5 @@ ifndef SHELLCHECK $(error "cannot find shellcheck; install to run check") endif shellcheck -a -x \ - vmctl cmd/* common/* lib/qemu/* + vmctl cmd/* common/* lib/qemu/* lib/cloudinit/* diff --git a/README.md b/README.md index fe391d2..ef0bab9 100644 --- a/README.md +++ b/README.md @@ -163,50 +163,31 @@ This is useful when selftests or modules are needed within the VM. ## Prep boot img -The base configruation `*-base.conf` will look for a base image in -`img/base.qcow2`. You can use [archbase][archbase] to build a lean Arch Linux -base image or grab a QCOW2-based [Ubuntu cloud image][ubuntu-cloud-image] if -that's your vice. +There needs to be a base image in `img/base.qcow2` because the default configs +`*-base.conf` expect it. Use the following command to create a QCOW2-based +[Ubuntu cloud image][ubuntu-cloud-image]: -In the case of a standard "cloud image", you probably want to resize it since -it is usually shrunk to be as small as possible by default. + $ vmctl -c cloudinit.conf run - $ qemu-img resize img/base.qcow2 8G +**Note**: This command will do the following: + 1. Create an ubuntu amd64 plucky image + 2. Resize it to 8G + 3. Add first ~/.ssh/*.pub file for ssh connections + 4. Configure default login:"vmuser" and passwd:"vmuser" + 5. It will do a qemu seed run and then powerdown to set everything up -**Note** The example `nvme.conf` will define `GUEST_BOOT="img/nvme.qcow2"`. -You do not need to provide that image - if it is not there `$GUEST_BOOT` -will be a differential image backed by `img/base.qcow2`. So, if you ever -need to reset to the "base" state, just remove the `img/nvme.qcow2` image. +After running the `cloudinit.conf` configuration, you should see an image in +`img/base.qcow2` which you can run by doing: -[archbase]: https://github.com/OpenMPDK/archbase -[ubuntu-cloud-image]: https://cloud-images.ubuntu.com - -### cloud-init - -If your chosen base image is meant to be configured through [cloud-init][cloud-init], -you can use the included cloud-config helper script to generate a basic -cloud-init seed image: - - $ ./contrib/generate-cloud-config-seed.sh ~/.ssh/id_rsa.pub - -If the image is running freebsd, use the script with `-freebsd` suffix: + $ vmctl -c nvme.conf run -b + $ vmctl -c nvme.conf ssh --wait - $ ./contrib/generate-cloud-config-seed-freebsd.sh ~/.ssh/id_rsa.pub +**Note**: Customize cloudinit.conf if the defaults don't work for you -This will generate a simple cloud-init seed image that will set up the image -with a default `vmuser` account that can be logged into using the given public -key. Place the output image (`seed.img`) in `img/` and pass the `--cloud-init` -(short: `'-c'`) option to `vmctl run` to initialize the image on first boot: - - $ vmctl -c CONFIG run -c - -cloud-init will automatically power off the virtual machine when it has been -configured. - -**Note**: For the cloud-config helper script to work `cloud-utils` is required. - -[cloud-init]: https://cloudinit.readthedocs.io/en/latest/ +**Note** Use [archbase][archbase] to build a lean Arch Linux base image +[archbase]: https://github.com/OpenMPDK/archbase +[ubuntu-cloud-image]: https://cloud-images.ubuntu.com ## License diff --git a/cmd/run b/cmd/run index 2951f20..d6b2aba 100644 --- a/cmd/run +++ b/cmd/run @@ -9,7 +9,7 @@ set -euo pipefail #shellcheck source=common/rc source "${BASEDIR}/common/rc" -for rc in "${BASEDIR}"/lib/qemu/*; do +for rc in "${BASEDIR}"/lib/*/*; do #shellcheck disable=SC1090 source "$rc" done @@ -24,7 +24,6 @@ Options: -k, --kernel-dir DIR directory containing the kernel source. The directory will be made available to the vm as a 9p virtfs with mount tag 'kernel_dir' - -c, --cloud-init use '\${VMIMG}/seed.img' as a cloud-init seed -b, --background start in the background -g, --gdb launch under gdb -p, --perf perf record @@ -36,8 +35,8 @@ Options: event with a '-'" _run() { - local short="k:cd:bnfgpt:h" - local long="kernel-dir:,cloud-init,background,print,reset,gdb,perf,trace:,help" + local short="k:d:bnfgpt:h" + local long="kernel-dir:,background,print,reset,gdb,perf,trace:,help" if ! tmp=$(getopt -o "$short" --long "$long" -n "$BASENAME" -- "$@"); then exit 1 @@ -52,10 +51,6 @@ _run() { local kernel_dir="$2" ; shift 2 ;; - '-c' | '--cloud-init' ) - local do_cloud_init=1; shift - ;; - '-b' | '--background' ) local do_background=1; shift ;; @@ -127,17 +122,6 @@ _run() { truncate -s 0 "${VMLOG}/${logfile}" done - if [[ -v do_cloud_init ]]; then - if [[ ! -f "${VMIMG}/seed.img" ]]; then - _fatal 1 "no such file: '${VMIMG}/seed.img'" - fi - - qemu_drive_add "cloud-init-seed" \ - --file "img/seed.img" \ - --format "raw" \ - --interface "virtio" - fi - QEMU_PARAMS+=("-pidfile" "${VMROOT}/run/${VMNAME}/pidfile") if [[ -v kernel_dir ]]; then diff --git a/contrib/generate-cloud-config-seed-freebsd.sh b/contrib/generate-cloud-config-seed-freebsd.sh deleted file mode 100755 index 2742a38..0000000 --- a/contrib/generate-cloud-config-seed-freebsd.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: GPL-3.0-or-later - -set -euo pipefail - -cat </tmp/cloud-config -#cloud-config -disable_root: false - -users: - - name: vmuser - sudo: ALL=(ALL) NOPASSWD:ALL - lock_passwd: false - plain_text_passwd: 'vmuser' -EOF - -if [[ $# -gt 0 ]]; then - pubkey="$(<"$1")" - cat <>/tmp/cloud-config - ssh_authorized_keys: - - ${pubkey} - - name: root - ssh_authorized_keys: - - ${pubkey} -EOF -fi - -cat <>/tmp/cloud-config -write_files: -- path: /etc/ssh/sshd_config - content: | - PermitRootLogin yes - AuthorizedKeysFile .ssh/authorized_keys - Subsystem sftp /usr/libexec/sftp-server -EOF - -cat <>/tmp/cloud-config - -power_state: - mode: poweroff - condition: True -EOF - -cloud-localds -v seed.img /tmp/cloud-config -rm /tmp/cloud-config diff --git a/contrib/generate-cloud-config-seed.sh b/contrib/generate-cloud-config-seed.sh deleted file mode 100755 index 1db50fd..0000000 --- a/contrib/generate-cloud-config-seed.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: GPL-3.0-or-later - -set -euo pipefail - -cat </tmp/meta-data -instance-id: debian-1 -local-hostname: debian -EOF - -cat </tmp/user-data -#cloud-config -disable_root: false -ssh_pwauth: true -users: - - name: vmuser - sudo: ALL=(ALL) NOPASSWD:ALL - groups: users, admin - home: /home/vmuser - shell: /bin/bash - lock_passwd: false - plain_text_passwd: 'vmuser' -EOF - -if [[ $# -gt 0 ]]; then - pubkey="$(<"$1")" - cat <>/tmp/user-data - ssh_authorized_keys: - - ${pubkey} - - name: root - ssh_authorized_keys: - - ${pubkey} -EOF -fi - -cat <>/tmp/user-data - -write_files: -- path: /etc/systemd/system/mount-shared-kernel-dir.service - content: | - # MIT License - # - # Copyright (c) 2021 Omar Sandoval - # - # Permission is hereby granted, free of charge, to any person obtaining a copy - # of this software and associated documentation files (the "Software"), to deal - # in the Software without restriction, including without limitation the rights - # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - # copies of the Software, and to permit persons to whom the Software is furnished - # to do so, subject to the following conditions: - # - # The above copyright notice and this permission notice shall be included in - # all copies or substantial portions of the Software. - # - # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS - # OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - # - # Cribbed and slightly modified from a systemd unit-file created by Omar - # Sandoval: - # - # https://github.com/osandov/osandov-linux/blob/master/scripts/vm-modules-mounter.service - # - - [Unit] - Description=Mount shared kernel build dir - DefaultDependencies=no - After=systemd-remount-fs.service - Before=local-fs-pre.target systemd-modules-load.service systemd-udevd.service kmod-static-nodes.service umount.target - Conflicts=umount.target - RefuseManualStop=true - ConditionPathExists=!/lib/modules/%v/kernel - - [Install] - WantedBy=local-fs-pre.target - - [Service] - Type=oneshot - RemainAfterExit=yes - ExecStart=mount -t tmpfs -o mode=755,strictatime,x-mount.mkdir,x-initrd.mount tmpfs /lib/modules/%v - ExecStart=mount -t 9p -o trans=virtio,ro,x-mount.mkdir,x-initrd.mount kernel_dir /lib/modules/%v/build - ExecStart=ln -s build/modules.order /lib/modules/%v/modules.order - ExecStart=ln -s build/modules.builtin /lib/modules/%v/modules.builtin - ExecStart=ln -s build /lib/modules/%v/kernel - ExecStart=-depmod %v - ExecStopPost=sh -c 'if mountpoint -q /lib/modules/%v/build; then umount -l /lib/modules/%v/build; fi' - ExecStopPost=sh -c 'if mountpoint -q /lib/modules/%v; then umount -l /lib/modules/%v; fi' - ExecStopPost=find /lib/modules -mindepth 1 -maxdepth 1 -type d -empty -delete - ExecReload=-depmod %v - -runcmd: - - [ systemctl, daemon-reload ] - - [ systemctl, enable, mount-shared-kernel-dir.service ] -EOF - -cat <>/tmp/user-data - -power_state: - mode: poweroff - condition: True -EOF - -#cloud-localds -v seed.img /tmp/cloud-config -mkisofs -output seed.img -volid cidata -joliet -rock /tmp/user-data /tmp/meta-data -rm /tmp/user-data -rm /tmp/meta-data diff --git a/contrib/systemd/mount-shared-kernel-dir.service b/contrib/systemd/mount-shared-kernel-dir.service deleted file mode 100644 index 05ea81c..0000000 --- a/contrib/systemd/mount-shared-kernel-dir.service +++ /dev/null @@ -1,71 +0,0 @@ -# MIT License -# -# Copyright (c) 2021 Omar Sandoval -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is furnished -# to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Cribbed and slightly modified from a systemd unit-file created by Omar -# Sandoval: -# -# https://github.com/osandov/osandov-linux/blob/master/scripts/vm-modules-mounter.service -# -# -# Linux kernel dir mounter service for systemd -# -# This systemd service will try to mount the p9 virtfs made available to the vm -# with the mount tag `kernel_dir` at very early boot. The network file system -# will be made available inside /lib/modules such that kernel modules can be -# loaded. -# -# Copy this file to /etc/systemd/system/mount-shared-kernel-dir.service and run -# -# systemctl daemon-reload -# systemctl enable mount-shared-kernel-dir.service -# -# Then reboot with the vmctl `--kernel-dir` option. -# - -[Unit] -Description=Mount shared kernel build dir -DefaultDependencies=no -After=systemd-remount-fs.service -Before=local-fs-pre.target systemd-modules-load.service systemd-udevd.service kmod-static-nodes.service umount.target -Conflicts=umount.target -RefuseManualStop=true -ConditionPathExists=!/lib/modules/%v/kernel - -[Install] -WantedBy=local-fs-pre.target - -[Service] -Type=oneshot -RemainAfterExit=yes -# Mount with x-initrd.mount so that systemd will ignore these mounts, because -# we want to unmount them ourselves. -ExecStart=/bin/mount -t tmpfs -o mode=755,strictatime,x-mount.mkdir,x-initrd.mount tmpfs /lib/modules/%v -ExecStart=/bin/mount -t 9p -o trans=virtio,ro,x-mount.mkdir,x-initrd.mount kernel_dir /lib/modules/%v/build -ExecStart=/bin/ln -s build/modules.order /lib/modules/%v/modules.order -ExecStart=/bin/ln -s build/modules.builtin /lib/modules/%v/modules.builtin -ExecStart=/bin/ln -s build /lib/modules/%v/kernel -ExecStart=/bin/depmod %v -# Lazy unmount to deal with stuff like udevd which keeps the mount busy. -ExecStopPost=/bin/sh -c 'if mountpoint -q /lib/modules/%v/build; then umount -l /lib/modules/%v/build; fi' -ExecStopPost=/bin/sh -c 'if mountpoint -q /lib/modules/%v; then umount -l /lib/modules/%v; fi' -ExecStopPost=/usr/bin/find /lib/modules -mindepth 1 -maxdepth 1 -type d -empty -delete -ExecReload=/bin/depmod %v - diff --git a/examples/vm/cloudinit.conf b/examples/vm/cloudinit.conf new file mode 100644 index 0000000..272982a --- /dev/null +++ b/examples/vm/cloudinit.conf @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +CLOUDINIT_STAGE_DIR="$(mktemp -d)" +GUEST_BOOT_BASE="${CLOUDINIT_STAGE_DIR}/base.qcow2" +trap 'rm -rfv ${CLOUDINIT_STAGE_DIR}' EXIT + +source "x86_64-q35-base.conf" + +_pre() { + _require_program mkisofs + _require_program wget + _require_vars "GUEST_BOOT" + + local meta_data_file="${CLOUDINIT_STAGE_DIR}/meta-data" + local usr_data_file="${CLOUDINIT_STAGE_DIR}/user-data" + + if [[ -f "img/base.qcow2" ]]; then + _fatal 1 "img/base.qcow2 exist; rename to avoid overwriting" + fi + + cloudinit_get_img --ubuntu-25 \ + --cloud-img-path "${GUEST_BOOT}" \ + --resize-to 8G + + cloudinit_make_seed_img \ + --seed-img-path "${CLOUDINIT_STAGE_DIR}/seed.img" \ + --meta-data-file "${meta_data_file}" \ + --usr-data-file "${usr_data_file}" \ + --usr-name "vmuser" \ + --usr-passwd "vmuser" +} + +_setup_cloudinit() { + _setup_x86_64_q35_base + + QEMU_PARAMS+=("-drive" "id=cloud-init-seed,file=${CLOUDINIT_STAGE_DIR}/seed.img,format=raw,media=cdrom") +} + +_post() { + mkdir -p "img" + mv "${GUEST_BOOT}" "img/base.qcow2" +} diff --git a/examples/vm/nvme-aarch64.conf b/examples/vm/nvme-aarch64.conf index 1a33d93..89df9ee 100644 --- a/examples/vm/nvme-aarch64.conf +++ b/examples/vm/nvme-aarch64.conf @@ -1,6 +1,6 @@ #!/usr/bin/env bash -QEMU_SYSTEM_AARCH64=$(/usr/bin/which qemu-system-aarch64) +QEMU_SYSTEM_AARCH64=$(/usr/bin/env which qemu-system-aarch64) GUEST_BOOT_BASE="img/debian-13-genericcloud-arm64.qcow2" source "aarch64-virt-base.conf" diff --git a/examples/vm/nvme.conf b/examples/vm/nvme.conf index c51db08..9e2a9ae 100644 --- a/examples/vm/nvme.conf +++ b/examples/vm/nvme.conf @@ -1,6 +1,6 @@ #!/usr/bin/env bash -QEMU_SYSTEM_X86_64=$(/usr/bin/which qemu-system-x86_64) +QEMU_SYSTEM_X86_64=$(/usr/bin/env which qemu-system-x86_64) source "x86_64-q35-base.conf" #source "x86_64-q35-noimgnix-base.conf" diff --git a/examples/vm/x86_64-q35-base.conf b/examples/vm/x86_64-q35-base.conf index 16d7c43..c227aa1 100644 --- a/examples/vm/x86_64-q35-base.conf +++ b/examples/vm/x86_64-q35-base.conf @@ -18,8 +18,7 @@ if [[ -f "common.conf" ]]; then source "common.conf" fi -QEMU_SYSTEM_BINARY=${QEMU_SYSTEM_X86_64} - +: "${QEMU_SYSTEM_BINARY:="$(/usr/bin/env which qemu-system-x86_64)"}" : "${GUEST_DISPLAY:="0"}" : "${GUEST_VIOMMU:="1"}" : "${GUEST_VIOMMU_ARGS:="intel-iommu,intremap=on"}" diff --git a/lib/cloudinit/cimgs b/lib/cloudinit/cimgs new file mode 100644 index 0000000..494eefd --- /dev/null +++ b/lib/cloudinit/cimgs @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Written by Joel Granados + +cloudinit_get_img() { + _require_program wget + + local long="ubuntu-25,cloud-img-path:,resize-to:" + + if ! tmp=$(getopt -o "" --long "$long" -n "${FUNCNAME[0]}" -- "$@"); then + exit 1 + fi + + eval set -- "$tmp" + unset tmp + + while true; do + case "$1" in + '--ubuntu-25' ) + local base_url="https://cloud-images.ubuntu.com/releases/plucky/release" + local img_name="ubuntu-25.04-server-cloudimg-amd64.img" + shift + ;; + '--cloud-img-path' ) + local cloud_img_path="$2"; shift 2 + ;; + '--resize-to' ) + local resize_to="$2"; shift 2 + ;; + '--' ) + shift; break + ;; + * ) + _fatal 1 "unknown argument '$1'" + ;; + esac + done + + if [[ ! -v base_url || ! -v img_name ]]; then + _fatal 1 "${FUNCNAME[0]} base_url or img_name are undefined" + fi + + if [[ ! -v cloud_img_path ]]; then + _fatal 1 "${FUNCNAME[0]} missing --cloud-img-path arg" + fi + + if [[ -v resize_to ]]; then + _require_program qemu-img + fi + + wget -O "${cloud_img_path}" "${base_url}/${img_name}" + + if [[ -v resize_to ]]; then + qemu-img resize "${cloud_img_path}" "${resize_to}" + fi +} diff --git a/lib/cloudinit/seedimg b/lib/cloudinit/seedimg new file mode 100644 index 0000000..37c33f3 --- /dev/null +++ b/lib/cloudinit/seedimg @@ -0,0 +1,131 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Written by Joel Granados + +cloudinit_make_userdatafile() { + cloudinit_get_sshkey + _require_vars "CLOUDINIT_SSHKEY" + + cat > "${CLOUDINIT_USR_DATA_FILE}" << EOF +#cloud-config +disable_root: false +ssh_pwauth: false + +users: + - name: ${CLOUDINIT_USR_NAME} + sudo: ['ALL=(ALL) NOPASSWD:ALL'] + groups: users, admin + home: /home/${CLOUDINIT_USR_NAME} + shell: /bin/bash + lock_passwd: false + plain_text_passwd: '${CLOUDINIT_USR_PASSWD}' + ssh_authorized_keys: + - ${CLOUDINIT_SSHKEY} + + - name: root + ssh_authorized_keys: + - ${CLOUDINIT_SSHKEY} + +write_files: +- path: /etc/systemd/system/mount-shared-kernel-dir.service + content: | + # Cribbed and slightly modified from a systemd unit-file created by Omar Sandoval: + # https://github.com/osandov/osandov-linux/blob/master/scripts/vm-modules-mounter.service + + [Unit] + Description=Mount shared kernel build dir + DefaultDependencies=no + After=systemd-remount-fs.service + Before=local-fs-pre.target systemd-modules-load.service systemd-udevd.service kmod-static-nodes.service umount.target + Conflicts=umount.target + RefuseManualStop=true + ConditionPathExists=!/lib/modules/%v/kernel + + [Install] + WantedBy=local-fs-pre.target + + [Service] + Type=oneshot + RemainAfterExit=yes + ExecStart=mount -t tmpfs -o mode=755,strictatime,x-mount.mkdir,x-initrd.mount tmpfs /lib/modules/%v + ExecStart=mount -t 9p -o trans=virtio,ro,x-mount.mkdir,x-initrd.mount kernel_dir /lib/modules/%v/build + ExecStart=ln -s build/modules.order /lib/modules/%v/modules.order + ExecStart=ln -s build/modules.builtin /lib/modules/%v/modules.builtin + ExecStart=ln -s build /lib/modules/%v/kernel + ExecStart=-depmod %v + ExecStopPost=sh -c 'if mountpoint -q /lib/modules/%v/build; then umount -l /lib/modules/%v/build; fi' + ExecStopPost=sh -c 'if mountpoint -q /lib/modules/%v; then umount -l /lib/modules/%v; fi' + ExecStopPost=find /lib/modules -mindepth 1 -maxdepth 1 -type d -empty -delete + ExecReload=-depmod %v + +runcmd: + - [ systemctl, daemon-reload ] + - [ systemctl, enable, mount-shared-kernel-dir.service ] + +power_state: + mode: poweroff + condition: true +EOF +} + +cloudinit_make_metadatafile() { + cat > "${CLOUDINIT_META_DATA_FILE}" << EOF +#cloud-config +#instance-id: vmctl-1 +#local-hostname: vmctl +EOF +} + +cloudinit_make_seed_img() { + _require_program mkisofs + local long="seed-img-path:,meta-data-file:,usr-data-file:,usr-name:,usr-passwd:" + + if ! tmp=$(getopt -o "" --long "$long" -n "${FUNCNAME[0]}" -- "$@"); then + exit 1 + fi + + eval set -- "$tmp" + unset tmp + + CLOUDINIT_USR_NAME="vmuser" + CLOUDINIT_USR_PASSWD="${CLOUDINIT_USR_NAME}" + while true; do + case "$1" in + '--meta-data-file' ) + CLOUDINIT_META_DATA_FILE="$2"; shift 2 + ;; + '--usr-data-file' ) + CLOUDINIT_USR_DATA_FILE="$2"; shift 2 + ;; + '--usr-name' ) + CLOUDINIT_USR_NAME="$2"; shift 2 + ;; + '--usr-passwd' ) + CLOUDINIT_USR_PASSWD="$2"; shift 2; + ;; + '--seed-img-path' ) + local seed_img_path="$2"; shift 2; + ;; + '--' ) + shift; break + ;; + * ) + _fatal 1 "unknown argument '$1'" + ;; + esac + done + + if [[ ! -v seed_img_path ]]; then + _fatal 1 "${FUNCNAME[0]} Missing --seed-img-path arg" + fi + + _require_vars "CLOUDINIT_META_DATA_FILE CLOUDINIT_USR_DATA_FILE" + + cloudinit_make_userdatafile + cloudinit_make_metadatafile + + mkisofs -output "${seed_img_path}" \ + -volid cidata -joliet -rock "${CLOUDINIT_USR_DATA_FILE}" "${CLOUDINIT_META_DATA_FILE}" +} diff --git a/lib/cloudinit/sshkey b/lib/cloudinit/sshkey new file mode 100644 index 0000000..4f1122e --- /dev/null +++ b/lib/cloudinit/sshkey @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Written by Joel Granados + +cloudinit_get_sshkey() { + local long="key-file:" + + if ! tmp=$(getopt -o "" --long "$long" -n "${FUNCNAME[0]}" -- "$@"); then + exit 1 + fi + + eval set -- "$tmp" + unset tmp + + while true; do + case "$1" in + '--key-file' ) + local key_file="$2"; shift 2 + ;; + '--' ) + shift; break + ;; + * ) + _fatal 1 "unknown argument '$1'" + ;; + esac + done + + if [[ -v CLOUDINIT_SSHKEY && -n "${CLOUDINIT_SSHKEY}" ]]; then + return + fi + + if [[ ! -v key_file ]]; then + local key_file="" + key_file="$(find ~/.ssh -maxdepth 1 -type f -name "*.pub" | head -n 1)" + if [[ -z "${key_file}" ]]; then + _fatal 1 "No public key found in ~/.ssh. Try setting CLOUDINIT_SSHKEY." + fi + fi + + if [[ ! -f "${key_file}" ]]; then + _fatal 1 "File not found ${key_file}" + fi + + CLOUDINIT_SSHKEY=$(cat "${key_file}") +} + diff --git a/lib/qemu/rc b/lib/qemu/rc index b142028..d25dd6f 100644 --- a/lib/qemu/rc +++ b/lib/qemu/rc @@ -87,7 +87,7 @@ qemu_drive_add() { while true; do case "$1" in '--file' ) - local file="/$2"; shift 2 + local file="$2"; shift 2 ;; '--format' ) @@ -139,11 +139,9 @@ qemu_drive_add() { local id="$1" if [[ ! -v file ]]; then - local file="/state/${VMNAME}/${id}.img" - fi - - if [[ ! -v DOCKER_IMAGE ]]; then - file="${VMROOT}${file}" + local file="${VMROOT}/state/${VMNAME}/${id}.img" + elif [[ "${file}" != /* ]]; then + file="${VMROOT}/${file}" fi if [[ -v do_create ]]; then