160 lines
3.6 KiB
Bash
Executable File
160 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
script_dir="$( cd -- "$( dirname -- "$(readlink -f "${BASH_SOURCE[0]}" )" )" &> /dev/null && pwd )"
|
|
qemu_args=()
|
|
|
|
function run_virtiofsd {
|
|
local shares=("$@")
|
|
local share_count=1
|
|
|
|
{
|
|
echo "mount -t tmpfs swap /var/run"
|
|
for m in "${shares[@]}"; do
|
|
local share_name="share.${share_count}"
|
|
local socket="$tmp_dir/$share_name"
|
|
|
|
echo "/usr/lib/qemu/virtiofsd --socket-path=$socket -o source=$m &"
|
|
echo "echo starting $m $socket"
|
|
|
|
share_count=$((share_count+1))
|
|
done
|
|
} | (unshare --user --map-root-user --mount bash)&
|
|
|
|
local mounts=${#shares[@]}
|
|
|
|
for i in $(seq "$mounts"); do
|
|
qemu_args+=("-chardev" "socket,id=share.$i,path=$tmp_dir/share.$i")
|
|
qemu_args+=("-device" "vhost-user-fs-pci,queue-size=1024,chardev=share.$i,tag=share.$i")
|
|
done
|
|
|
|
}
|
|
|
|
function start_qemu {
|
|
if [[ $# -lt 3 ]]; then
|
|
echo "Usage $(basename "$0") qemu <ssh_port> <app_port> <tmp_dir> [mount]"
|
|
exit 1
|
|
fi
|
|
|
|
trap finish EXIT
|
|
|
|
local ssh_port="$1"
|
|
local app_port="$2"
|
|
tmp_dir="$3"
|
|
|
|
local image
|
|
image="$tmp_dir/$(openssl rand -hex 12).qcow2"
|
|
|
|
qemu-img create -b "$script_dir/image/image.qcow2" -F qcow2 -f qcow2 "$image"
|
|
|
|
run_virtiofsd "${4:-$PWD}"
|
|
|
|
qemu-system-x86_64 \
|
|
-enable-kvm -cpu host -m 512m -smp 2 \
|
|
-kernel "$script_dir/image/vmlinuz-linux" -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/vda rw quiet" \
|
|
-initrd "$script_dir/image/initramfs-linux-custom.img" \
|
|
-m 4G -object memory-backend-file,id=mem,size=4G,mem-path=/dev/shm,share=on -numa node,memdev=mem \
|
|
-device virtio-rng-pci \
|
|
-bios /usr/share/qemu/qboot.rom \
|
|
-drive if=virtio,file="$image",format=qcow2 \
|
|
-netdev user,id=net0,hostfwd=tcp::"$ssh_port"-:22,hostfwd=tcp::"$app_port"-:8000 \
|
|
-device virtio-net-pci,netdev=net0 \
|
|
-nodefaults -no-user-config -nographic \
|
|
-serial stdio "${qemu_args[@]}"
|
|
}
|
|
|
|
function get_port {
|
|
local port="$1"
|
|
|
|
if netstat -tulen | grep -q "$port"; then
|
|
get_port "$((port+1))"
|
|
else
|
|
echo "$port"
|
|
fi
|
|
}
|
|
|
|
function run {
|
|
local ssh_port
|
|
ssh_port="$(get_port 5555)"
|
|
local app_port
|
|
app_port="$(get_port 8000)"
|
|
|
|
local work_dir="${1:-$PWD}"
|
|
|
|
tmp_dir="$(mktemp -d --suffix=.qemu)"
|
|
|
|
echo "$ssh_port" > "$tmp_dir/ssh"
|
|
echo "$ssh_port" > "$tmp_dir/app"
|
|
echo "$work_dir" > "$tmp_dir/work_dir"
|
|
|
|
systemd-run --user -d "$0" qemu "$ssh_port" "$app_port" "$tmp_dir" "$work_dir"
|
|
|
|
echo "[ ] SSH Port: $ssh_port"
|
|
echo "[ ] App Port: $app_port"
|
|
|
|
sleep 1
|
|
enter "$ssh_port"
|
|
}
|
|
|
|
function finish {
|
|
rm -rf "$tmp_dir"
|
|
}
|
|
|
|
function list {
|
|
for d in /tmp/*.qemu; do
|
|
if [[ -f "$d/ssh" ]]; then
|
|
echo "$(cat "$d/ssh") - $(cat "$d/work_dir")"
|
|
fi
|
|
done
|
|
}
|
|
|
|
function enter {
|
|
if [[ "$#" -eq 1 ]]; then
|
|
local port="$1"
|
|
else
|
|
echo "Using default port 5555"
|
|
local port="5555"
|
|
fi
|
|
|
|
ssh -i "$script_dir/ssh/qemu_ssh" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@localhost -p "$port"
|
|
}
|
|
|
|
function usage {
|
|
local bin
|
|
bin="$(basename "$0")"
|
|
|
|
echo "Usage:"
|
|
echo " $bin run [dir] - start sandbox and mount current working dir"
|
|
echo " $bin list - list running sandboxes"
|
|
echo " $bin enter - open ssh connection to a sandbox"
|
|
echo " $bin qemu - start the qemu process for a new sandbox, used by run"
|
|
}
|
|
|
|
function main {
|
|
if [[ "$#" -lt 1 ]]; then
|
|
usage "$@"
|
|
exit 1
|
|
fi
|
|
|
|
local cmd="$1"
|
|
shift
|
|
|
|
if [[ "$cmd" == "qemu" ]]; then
|
|
start_qemu "$@"
|
|
fi
|
|
|
|
if [[ "$cmd" == "list" ]]; then
|
|
list
|
|
fi
|
|
|
|
if [[ "$cmd" == "run" ]]; then
|
|
run "$@"
|
|
fi
|
|
|
|
if [[ "$cmd" == "enter" ]]; then
|
|
enter "$@"
|
|
fi
|
|
}
|
|
|
|
main "$@"
|
|
|