#!/bin/bash

VM_ID=$1
MARKET_ID=$2
APP_NAME="$3"

if [ -z "$VM_ID" -o -z "$MARKET_ID" ];then
  echo "Example: $(echo $0 | cut -d/ -f4) [ID_VM] [ID_MARKETPLACE]"
  exit 1
fi

MARKET_ENDPOINT="$(/usr/bin/onemarket show ${MARKET_ID} -x | xmlstarlet sel -t -v '/MARKETPLACE/TEMPLATE/ENDPOINT')"
if [ $? -ne 0 ] && [ -z "$MARKET_ENDPOINT" ]; then
  exit 102
fi
MARKET_FQDN="$(echo ${MARKET_ENDPOINT} | awk -F/ '{print $3}')"
market_img_url="http://${MARKET_FQDN}/brest-marketplace/data/"
market_index_path="/var/www/html/brest-marketplace/index.html"
market_data_path="/var/www/html/brest-marketplace/data/"
tmp_dump_path="/var/tmp/one-dump"
work_dir=$tmp_dump_path/${VM_ID}_$(($(date +%s%N)/1000000))
XPATH="/var/tmp/one/datastore/xpath.rb --stdin"
image_id=
imageName=

function clean {
  [ -n "$image_id" ] && /usr/bin/oneimage delete $image_id
  [ -n "$imageName" ] && ssh -o BatchMode=yes -o LogLevel=error -o ConnectTimeout=5 root@${MARKET_FQDN} "rm -f ${market_data_path}$imageName"
  rm -rf $work_dir
}

trap ctrl_c INT
function ctrl_c() {
  clean
  exit 0
}

# checking SSH connection
ssh -o BatchMode=yes -o ConnectTimeout=5 root@${MARKET_FQDN} "exit 0" > /dev/null 2>&1
if [ $? -ne 0 ]; then
  echo "Error. No connection with marketplace"
  exit 104
fi

# checking control key
loc_controlkey_path="/var/lib/one/remotes/market/brest/controlkey"
controlkey="$([ -f $loc_controlkey_path ] && cat $loc_controlkey_path)"
controlkey_path="${market_data_path}controlkey"
if ! ssh -o BatchMode=yes -o ConnectTimeout=5 root@${MARKET_FQDN} "test -f ${controlkey_path} || exit \$? ; [ \"\$(cat ${controlkey_path} | head -n 1)\" == \"${controlkey}\" ]; exit \$?" > /dev/null 2>&1;then
    echo "Access is denied."
    exit 105
fi

VM_XML="$(/usr/bin/onevm show --xml ${VM_ID})"
if [ $? -ne 0 ];then
  echo "Error. VM data not received"
  exit 106
fi

# get VM arguments
unset i XPATH_ELEMENTS
while read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <(echo "$VM_XML" | $XPATH  /VM/NAME \
                                  /VM/STATE \
                                  /VM/TEMPLATE/MEMORY \
                                  /VM/TEMPLATE/CPU \
                                  /VM/TEMPLATE/TM_MAD_SYSTEM \
                                  /VM/TEMPLATE/DISK/TYPE \
                                  /VM/TEMPLATE/GRAPHICS/TYPE \
                                  /VM/TEMPLATE/OS/ARCH \
                                  /VM/USER_TEMPLATE/HYPERVISOR \
                                  /VM/USER_TEMPLATE/VROUTER )
unset i
VM_NAME="${XPATH_ELEMENTS[i++]}"
VM_STATE="${XPATH_ELEMENTS[i++]}"
VM_MEMORY="${XPATH_ELEMENTS[i++]}"
VM_CPU="${XPATH_ELEMENTS[i++]}"
VM_TM_MAD_SYSTEM="${XPATH_ELEMENTS[i++]}"
VM_DISK_TYPE="${XPATH_ELEMENTS[i++]}"
VM_GRAPHICS_TYPE="${XPATH_ELEMENTS[i++]:-vnc}"
VM_OS_ARCH="${XPATH_ELEMENTS[i++]:-x86_64}"
VM_HYPERVISOR="${XPATH_ELEMENTS[i++]:-kvm}"
VM_VROUTER="${XPATH_ELEMENTS[i++]}"


[ -n "$VM_VROUTER" ] && VM_VROUTER="VROUTER = \"$VM_VROUTER\""
#default
VM_CONTEXT='CONTEXT = [ NETWORK = "YES",SSH_PUBLIC_KEY = "$USER[SSH_PUBLIC_KEY]"]'
VM_INPUTS_ORDER=
VM_USER_INPUTS=
#for USER_INPUTS
user_inputs=$(xmlstarlet sel -T -t -m '/VM/USER_TEMPLATE/USER_INPUTS/*' -v "concat(name(), '=\"',normalize-space(.), '\",')" <<< ${VM_XML} | sed 's/,$//' )
if [ -n "$user_inputs" ];then
  VM_USER_INPUTS="USER_INPUTS = [ ${user_inputs}]"
  user_inputs_for_context=$(xmlstarlet sel -T -t -m "/VM/USER_TEMPLATE/USER_INPUTS/*" -v "concat(name(), '=\"$', name(), '\",')" <<< ${VM_XML})
  VM_CONTEXT='CONTEXT = [ NETWORK = "YES",'${user_inputs_for_context}'SSH_PUBLIC_KEY = "$USER[SSH_PUBLIC_KEY]"]'
  for_inputs_order=$(xmlstarlet sel -T -t -m "/VM/USER_TEMPLATE/USER_INPUTS/*" -v "concat(name(), ',')" <<< ${VM_XML} | sed 's/,$//')
  VM_INPUTS_ORDER='INPUTS_ORDER = "'${for_inputs_order}'"'
fi

# checking VM status
if [ "$VM_STATE" != "8" ];then
   echo 'Error. State VM must be "POWEROFF"'
   exit 107
fi

# checking number of disks
checkd=($(echo "${VM_XML}" | xmlstarlet sel -t -v '/VM/TEMPLATE/DISK/DISK_ID'))
if [ ${#checkd[@]} -ne 1 ];then
  echo 'Error. The VM must have one disk'
  exit 107
fi
VM_DISK_ID=${checkd[0]}

# checking free space
space_tmp_dupm=$(df $tmp_dump_path | awk 'NR>1 {print $4}')
VM_DISK_SIZE=$(echo "${VM_XML}" | xmlstarlet sel -t -v '/VM/TEMPLATE/DISK[DISK_ID='$VM_DISK_ID']/SIZE')
if [ -n "$VM_DISK_SIZE" ] && [ $VM_DISK_SIZE -eq $VM_DISK_SIZE ] 2>/dev/null; then
  # disk size + 10MB
  let VM_DISK_SIZE=$VM_DISK_SIZE*1024+10240
  if [ $VM_DISK_SIZE -gt $space_tmp_dupm ];then
    echo "Error. Not enough disk space to prepare the application"
    exit -1
  fi
  ssh -o BatchMode=yes -o LogLevel=error -o ConnectTimeout=5 root@${MARKET_FQDN} "market_space=\$(df $market_data_path  | awk 'NR>1 {print \$4}'); if [ \$market_space -lt $VM_DISK_SIZE ]; then exit -1; fi"
  if [ $? -ne 0 ]; then
    echo "Error. There is not enough space on the marketplace"
    exit -1
  fi
else
  echo "Failed to get image size of VM $VM_ID"
  exit -1
fi

# check app name
if [ -z "${APP_NAME}" ]; then
  history_hostname=($(/usr/bin/onevm show $VM_ID -x | xmlstarlet sel -t -v '/VM/HISTORY_RECORDS/HISTORY/HOSTNAME' -n))
  [ -n "${history_hostname}" ] && APP_NAME="${VM_NAME}_${history_hostname[0]}_$(date +%d%m%y_%H%M%S)" || APP_NAME="${VM_NAME}_$(date +%d%m%y_%H%M%S)"
fi
AppList="$(curl -sSL "$MARKET_ENDPOINT")"
ArrayApp=($(echo "$AppList" | awk '/^APP=/ {gsub(/(APP=)|(")/,"");print}'))
for App in ${ArrayApp[@]}; do
    decApp="$(echo "$App" | base64 -d)"
    nameApp="$(echo "$decApp" | awk -F'/' '/^NAME/ {gsub(/(NAME=)|(")/,"");print}')"
  if [ "$nameApp" == "${APP_NAME}" ];then
    echo "An app named \"$APP_NAME\" already exists"
    exit 108
  fi
done


# # # creating an image and template for marketplace

# image
imgName="disk${VM_DISK_ID}_${VM_ID}_$(date +%d%m%y_%H%M%S)"
image_res=$(/usr/bin/onevm disk-saveas $VM_ID ${VM_DISK_ID} $imgName)

if [ $? -eq "0" ]; then

  echo "* Image preparation..."

  # mkdir
  mkdir -p $tmp_dump_path
  mkdir $work_dir

  image_id=$(echo "${image_res}" | awk '{print $NF}')

  # wait saving...
  CheckImageTime=10
  until [ $(/usr/bin/oneimage show ${image_id} --xml | xmlstarlet sel -t -v "/IMAGE/STATE") -eq 1 ]; do
    sleep $CheckImageTime
    checkTimes=++
  done

  # get image arguments
  IMG_XML="$(/usr/bin/oneimage show ${image_id} --xml)"
  if [ $? -ne 0 ];then
    echo "Error get image info"
    exit 109
  fi
  unset i XPATH_ELEMENTS
  while read -r -d '' element; do
      XPATH_ELEMENTS[i++]="$element"
  done < <(echo "$IMG_XML" | $XPATH /IMAGE/TYPE \
                                    /IMAGE/SOURCE \
                                    /IMAGE/SIZE \
                                    /IMAGE/FORMAT \
                                    /IMAGE/TEMPLATE/DEV_PREFIX )
  unset i
  IMG_TYPE="${XPATH_ELEMENTS[i++]}"
  IMG_SOURCE="${XPATH_ELEMENTS[i++]}"
  IMG_SIZE="${XPATH_ELEMENTS[i++]}"
  IMG_FORMAT="${XPATH_ELEMENTS[i++]}"
  IMG_DEV_PREFIX="${XPATH_ELEMENTS[i++]}"

  # default
  case $IMG_TYPE in
    '0') IMG_TYPE="OS";;
    '1') IMG_TYPE="CDROM";;
    '2') IMG_TYPE="DATABLOCK";;
    *) IMG_TYPE="$(/usr/bin/oneimage show ${image_id} | awk '/^TYPE/ {print $NF}')";;
  esac

  # create image
  imageName=$(echo "$(date +%s):$VM_ID" | md5sum | cut -d ' ' -f1)
  if [[ "${VM_DISK_TYPE,,}" == "rbd" ]]; then
      rbd export $IMG_SOURCE $work_dir/$imageName -p one --id libvirt > /dev/null 2>&1
  else
      if [ "${VM_TM_MAD_SYSTEM,,}" == "brest_lvm" ]; then
          lvchange -ay $IMG_SOURCE 2> /dev/null
          qemu-img convert -O qcow $IMG_SOURCE $work_dir/$imageName
          lvchange -an $IMG_SOURCE 2> /dev/null
      else
          cp $IMG_SOURCE $work_dir/$imageName
      fi
  fi
  if [ $? -eq "0" ]; then
      /usr/bin/oneimage delete ${image_id}
      IMG_MD5=$(md5sum $work_dir/$imageName | cut -d' ' -f1)
      IMG_URL="${market_img_url}${imageName}"
      image_id=
  else
      /usr/bin/oneimage delete ${image_id} > /dev/null 2>&1
      clean
      echo "Error copy $imgName"
      exit 110
  fi
else
    clean
    echo "Error get image $image_id"
    exit 111
fi

# taemplate base64

echo "* Template creation..."

IMG_MD5=$(md5sum $work_dir/$imageName | cut -d' ' -f1)
IMG_URL="${market_img_url}${imageName}"

APPTEMPLATE64=$(echo "$(cat << EOF
DEV_PREFIX = "${IMG_DEV_PREFIX}"
DRIVER = "${IMG_FORMAT}"
TYPE = "${IMG_TYPE}"
EOF
)" | base64 -w 0)

VMTEMPLATE64=$(echo "$(cat << EOF
${VM_CONTEXT}
CPU = "${VM_CPU}"
GRAPHICS = [ LISTEN = "0.0.0.0",TYPE = "${VM_GRAPHICS_TYPE}" ]
${VM_INPUTS_ORDER}
HYPERVISOR = "${VM_HYPERVISOR,,}"
MEMORY = "${VM_MEMORY}"
OS = [ ARCH = "${VM_OS_ARCH}" ]
${VM_USER_INPUTS}
${VM_VROUTER}
EOF
)" | base64 -w 0)

TEMPLATE64=$(echo "$(cat << EOF
NAME="${APP_NAME}"
SOURCE="${IMG_URL}"

ORIGIN_ID="-1"
TYPE="IMAGE"
PUBLISHER="Brest"
FORMAT="${IMG_FORMAT}"
DESCRIPTION="From VM-${VM_ID}"

TAGS="brest"
REGTIME="$(date +%s)"
SIZE="${IMG_SIZE}"
MD5="${IMG_MD5}"
APPTEMPLATE64="$APPTEMPLATE64"
VMTEMPLATE64="$VMTEMPLATE64"
EOF
)" | base64 -w 0)


# # # send templ and image to market

#  copy image
ssh -o BatchMode=yes -o ConnectTimeout=5 root@${MARKET_FQDN} "mkdir -p ${market_data_path} || exit \$?; test -f ${market_data_path}$imageName; exit \$?" > /dev/null 2>&1
if [ $? -ne 0 ]; then

    echo "* Transferring the application to the marketplace..."

    scp ${work_dir}/${imageName} root@${MARKET_FQDN}:${market_data_path} > /dev/null 2>&1
    # sudo -u oneadmin bash -c "scp ${work_dir}/${imageName} root@${MARKET_FQDN}:${market_data_path}" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
      app_name='APP=\"'${TEMPLATE64}'\"'
      ssh -o BatchMode=yes -o ConnectTimeout=5 root@${MARKET_FQDN} "chmod 644 ${market_data_path}$imageName; grep \"${app_name}\" ${market_index_path} || echo \"${app_name}\" >> ${market_index_path}" > /dev/null 2>&1
      imageName=
      clean
    else
      echo "Error copy app to the marketplace"
      clean
      exit 112
    fi
else
    echo "Error. Disk $imageName already exists"
    clean
    exit 113
fi
