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 "$@"
 | 
						|
 |