#!/bin/bash

## we run a python simple web server on this port.
WPORT=${WPORT:-32600}
## HOST_IP has to be an IP address that the vm will be able to access
## ie, it can't be "127.0.0.1".  If empty (default) then the ip from
## the device HOST_IP_NIC (default=eth0) will be used.
HOST_IP="10.0.2.2"
HOST_IP_NIC="eth0"
## set OVERLAY_DISK in environment to get this.
## set to 'temp' to just get a temp file to excercise that path
## set to some other path and it will be created if non-existant
## the overlay will then be put on this drive and read from there
## instead of a tmpfs
OVERLAY_DISK=${OVERLAY_DISK:-""}
##
## XKVM_BRIDGE: set to 'user' to use qemu user networking
## set to name of a bridge such as virbr0 to use tap on that bridge
XKVM_BRIDGE=${XKVM_BRIDGE:-"user"}

TGT_CONF=""
HTTP_PID=""
TGT_NAME=""

cleanup() {
    [ ! -d "$TEMP_D" ] || rm -Rf "$TEMP_D"
    if [ -f "$TGT_CONF" ]; then
       error "cleaning up tgt mount ${TGT_NAME}"
       sudo tgt-admin --force --delete="$TGT_NAME"
       sudo rm -f "$TGT_CONF"
    fi
    if [ -n "$HTTP_PID" ]; then
       kill $HTTP_PID
    fi
}
Usage() {
   cat <<EOF
${0##*/} image kernel initrd

puts 'image' into tgt, then boots kernel and initrd in kvm to use it as root.
EOF
}
error() { echo "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }


[ "$1" = "-h" -o "$1" = "--help" ] && { Usage ; exit 0; }
image_in=$1
kernel_in=$2
initrd_in=$3
[ $# -ge 3 ] || { Usage 1>&2; fail "must give image, kernel, initrd"; }

image=$(readlink -f "$image_in") ||
   fail "cannot get full path to $image_in"
kernel=$(readlink -f "$kernel_in") ||
   fail "cannot get full path to $kernel_in"
initrd=$(readlink -f "$initrd_in") ||
   fail "cannot get full path to $initrd_in"

TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}-XXXXXX") || exit 1
TEMP_D=$(cd "$TEMP_D" && pwd)
trap cleanup EXIT

t_image="${TEMP_D}/image"
t_kernel="${TEMP_D}/kernel"
t_initrd="${TEMP_D}/initrd"

# this is the IP address of the tgtd
if [ -n "$HOST_IP" ]; then
  ipaddr=${HOST_IP}
else
  ipaddr=$(ifconfig ${HOST_IP_NIC} |
           sed -n '/inet addr/s/\([^:]*:\)\([^ ]*\)\( .*\)/\2/p')
  [ $? -eq 0 -a -n "$ipaddr" ] ||
    fail "failed to get ipaddr from '$HOST_IP_NIC'. set HOST_IP or HOST_IP_NIC"
fi

## set up a user-data and meta-data for cloud-init
## and we'll seed that through the kernel command line
##
## The user data we provide will allow us to log in
## as the 'ubuntu' user with 'passw0rd'.
keys=$( (ssh-add -L 2>/dev/null ;
        [ -f ~/.ssh/id_rsa.pub ] && cat ~/.ssh/id_rsa.pub ) | sort -u )
if [ -n "$keys" ]; then
   d=$(IFS=$'\n'; for i in ${keys}; do echo "'$i',"; done)
   keys="[${d%,}]"
else
   keys="[]"
fi
mkdir "${TEMP_D}/ci-seed"
cat > "${TEMP_D}/ci-seed/user-data" <<EOF
#cloud-config
password: passw0rd
chpasswd: { expire: False }
ssh_pwauth: True
ssh_authorized_keys: $keys
EOF

### XXX: matsubara fix user data to collect stuff
## just an example of what you could do here.
## added when debugging resolvconf LP: #1501033
if true; then
   cat >> "${TEMP_D}/ci-seed/user-data" <<EOF
runcmd:
 - [ mkdir, -p, /mnt/output ]
 - [ cp, /etc/resolv.conf, /mnt/output]
 - [ tar, -C, /mnt/output, -cf, /dev/vda, . ]
power_state:
 mode: poweroff
 message: cloud-init finished. Shutting down.
 timeout: 60
EOF
fi

iid=$(uuidgen 2>/dev/null || echo i-abcdefg)
cat > "${TEMP_D}/ci-seed/meta-data" <<EOF
instance-id: $iid
EOF

## run a python web server to seed this
( cd "${TEMP_D}/ci-seed" && exec python -m SimpleHTTPServer $WPORT ) &
HTTP_PID=$!

if [ "${image%.gz}" != "$image" ]; then
   error "uncompressing $image_in -> temp-dir"
   gzcat "$image" > "${TEMP_D}/image" ||
      fail "failed uncompress of $image_in"
else
   ln -s "$image" "$t_image" || fail "symlink to $image failed"
fi

ln -s "$kernel" "$t_kernel" &&
   ln -s "$initrd" "$t_initrd" ||
   fail "failed link to kernel or initrd"


TGT_NAME=${TEMP_D##*/}
TGT_CONF="/etc/tgt/conf.d/$TGT_NAME.conf"

sudo tee "$TGT_CONF" >/dev/null <<EOF
<target ${TGT_NAME}>
    readonly 1
    backing-store "$t_image"
    allow-in-use yes
</target>
EOF
[ $? -eq 0 ] || fail "failed to write '$TGT_CONF'"

sudo tgt-admin "--update=${TGT_NAME}" || fail "failed tgt-admin update=$TGT_NAME"

overlay_disk=${OVERLAY_DISK}
overlay_drive_kernel="overlayroot=tmpfs"
overlay_drive_xkvm=""
if [ -n "$overlay_disk" ]; then
  if [ "${overlay_disk}" = "temp" ]; then
     overlay_disk="${TEMP_D}/overlay.img"
  fi
  if [ ! -f "$overlay_disk" ]; then
    qemu-img create -f raw "$overlay_disk" 1G
    mkfs.ext2 -L "delta" -F "$overlay_disk" >/dev/null 2>&1 ||
       fail "failed mkfs on $overlay_disk"
    overlay_drive_kernel="overlayroot=device:dev=LABEL=delta"
    overlay_drive_xkvm="--disk=${overlay_disk},format=raw"
  fi
fi

## Now boot a kvm from it
iport="3260"
root=LABEL=cloudimg-rootfs
root=/dev/disk/by-path/ip-$ipaddr:$iport-iscsi-${TGT_NAME}-lun-1
parms=(
  nomodeset
  iscsi_target_name=${TGT_NAME} iscsi_target_ip=$ipaddr
  iscsi_target_port=3260
  iscsi_initiator=maas-enlist
  ip=::::maas-enlist:BOOTIF ro
  net.ifnames=0
  BOOTIF_DEFAULT=eth0
  "root=${root}"
  ${overlay_drive_kernel}
  console=ttyS0 console=tty1
  "ds=nocloud-net;seedfrom=http://$ipaddr:$WPORT/"
)

mem="1024"
xkvm  --netdev ${XKVM_BRIDGE} \
   ${overlay_drive_xkvm} \
   ${OUTPUT_DISK:+--disk "$OUTPUT_DISK"} --\
   -m 1024 -nographic \
   -kernel "${t_kernel}" -initrd "${t_initrd}" \
   -append "${parms[*]}"
