#!/bin/bash
# Utility to capture a disk image from a remote NetScaler device
# Copyright 2020 FireEye, Inc. and Citrix Systems, Inc.
#
# Usage:
#
#    bash get_image_from_remote.sh NS_SSH_DEST [LOCAL_DIR]
#
# If not specified LOCAL_DIR to the current working directory.
# LOCAL_DIR must be writable.
#
# When executed this script makes several ssh connections to NS_SSH_DEST.
#

# unset variables are errors
set -o nounset;

if [[ ($# -lt 1) || ($# -gt 2) ]]; then
    echo "SYNTAX: bash get_image_from_remote.sh ssh_dest [local_dir]";
    exit 1;
fi

# collect script args
ssh_dest="$1";
if [[ $# -eq 2 ]]; then
    local_dir="$2";
else
    local_dir=$(pwd);
fi

# tempfile for `mount` output
readonly mkimage_temp="/tmp/$(date +%s)";
mkdir "$mkimage_temp";
readonly mnt_file="$mkimage_temp/mount.txt";
echo "mount output: $mnt_file";

# get the mount table
cmd_prefix="";
out_filter="cat";
echo "";
echo "**********************************************************************";
echo "getting mount table"
echo "**********************************************************************";
echo "";
errtxt=$((ssh "$ssh_dest" "$cmd_prefix" mount | $out_filter >"$mnt_file") 2>&1);

if [[ $errtxt == *"ERROR: No such command" ]]; then
    # login shell is NS shell;
    #  need to prefix commands with "shell"
    cmd_prefix="shell";
    # strip the leading " Done.\n" from command output
    out_filter="tail -c+7";
    # get the mount table
    echo "";
    echo "**********************************************************************";
    echo "getting mount table: retry using NS shell syntax";
    echo "**********************************************************************";
    echo "";
    errtxt=$((ssh "$ssh_dest" "$cmd_prefix" mount | $out_filter >"$mnt_file") 2>&1);
fi

# get the df table
#   (for size info)
echo "";
echo "**********************************************************************";
echo "getting partition sizes";
echo "**********************************************************************";
echo "";

readonly df_file="$mkimage_temp/df.txt";
ssh "$ssh_dest" "$cmd_prefix" "df -h" | $out_filter > "$df_file";

declare -a mounts;
mounts[0]="root /"
mounts[1]="flash /flash"
mounts[2]="var /var"

for mnt in "${mounts[@]}"; do
    fields=( $mnt )
    mntname=${fields[0]}
    mntdir=${fields[1]}
    # get device name from mount table
    mntdev=$(grep "on $mntdir " "$mnt_file" | cut -d" " -f1);
    # break off the basename to use for the output file name
    mntbase=$(echo "$mntdev" | awk -F "/" '{print $NF}');
    # get the size
    mntsize=$(grep "$mntdir$" "$df_file" | awk -F " "  '{print $2}')

    echo "";
    echo "**********************************************************************";
    echo "copying $mntname ($mntdir) from remote mount point $mntdev ($mntsize)";
    echo "(this will take a while...)"
    echo "**********************************************************************";
    echo "";

    rcmd="'dd if=$mntdev | gzip -1 - '";
    ssh "$ssh_dest" "$cmd_prefix" "$rcmd" | $out_filter | dd status=progress "of=$local_dir/${mntname}_${mntbase}.img.gz";
done

echo "done";
