#!/bin/bash -x

export BASE_COLLECTION_PATH="${BASE_COLLECTION_PATH:-/must-gather}"
export PROS="${PROS:-5}"
DIR_NAME=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
INSTALLATION_NAMESPACE="${INSTALLATION_NAMESPACE:-kubevirt-hyperconverged}"

function gather_vm_info() {
  ocproject=$1
  ocvm=$2
  vmname=$3

  vm_collection_path="${BASE_COLLECTION_PATH}/namespaces/${ocproject}/vms/${vmname}"
  mkdir -p "${vm_collection_path}"

  /usr/bin/oc adm inspect --dest-dir "${BASE_COLLECTION_PATH}" -n "${ocproject}" pod "$ocvm"
  /usr/bin/oc adm inspect --dest-dir "${BASE_COLLECTION_PATH}" -n "${ocproject}" virtualmachineinstances "${vmname}"

  # VM : dumpxml
  /usr/bin/oc exec "${ocvm}" -n "${ocproject}" -c compute -- virsh dumpxml "${ocproject}_${vmname}" > "${vm_collection_path}/${ocvm}.dumpxml.xml"

  # VM : QEMU logs
  # libvirt logs are already relayed to virt-launcher, and we capture the virt-launcher pod logs elsewhere. We are want the QEMU log here.
  /usr/bin/oc exec "${ocvm}" -n "${ocproject}" -c compute -- cat "/var/log/libvirt/qemu/${ocproject}_${vmname}.log" > "${vm_collection_path}/${ocvm}.qemu.log"

  # VM : IP
  /usr/bin/oc exec "${ocvm}" -n "${ocproject}" -c compute -- ip a 2>/dev/null > "${vm_collection_path}/${ocvm}.ip.txt"

  # VM : Bridge
  {
    echo "###################################"
    echo "brctl show:"
    echo "###################################"
    /usr/bin/oc exec "${ocvm}" -n "${ocproject}" -c compute -- brctl show 2>/dev/null

    echo "###################################"
    echo "bridge fdb show:"
    echo "###################################"
    /usr/bin/oc exec "${ocvm}" -n "${ocproject}" -c compute -- bridge fdb show 2>/dev/null

    echo "###################################"
    echo "bridge vlan show:"
    echo "###################################"
    /usr/bin/oc exec "${ocvm}" -n "${ocproject}" -c compute -- bridge vlan show 2>/dev/null
  } > "${vm_collection_path}/${ocvm}.bridge.txt"

  # VM : nftables / iptables
  {
    get_vm_rule_tables "${ocproject}" "${vmname}"
  } > "${vm_collection_path}/${ocvm}.ruletables.txt"
}

function gather_vm_by_pod_name() {
  pod=$1
  ocproject=$(echo "$pod" | awk -F_ '{print $1}')
  ocvm=$(echo "$pod" | awk -F_ '{print $2}')
  vmname=$(echo "${ocvm}" 2>/dev/null | cut -d'-' -f3- | sed "s/-[^-]*$//")

  if [[ -n ${VM_EXP} ]]; then
    if [[ ! "${vmname}" =~ ${VM_EXP} ]]; then
      return 0
    fi
  fi
  echo "inspecting ${vmname}"
  gather_vm_info "${ocproject}" "${ocvm}" "${vmname}"
}

function get_vm_rule_tables() {
  ocproject=$1
  vmname=$2

  vminfo=$(/usr/bin/oc get vmi -n "${ocproject}" "${vmname}" -o=custom-columns=UID:.metadata.uid,NODE:.status.nodeName --no-headers)
  vmuid=$(echo "${vminfo}" | tr -s ' ' | cut -d ' ' -f 1)
  vmnode=$(echo "${vminfo}" | tr -s ' ' | cut -d ' ' -f 2)

  handler=$(/usr/bin/oc get pods -A -l kubevirt.io=virt-handler -o=custom-columns=NAME:.metadata.name --field-selector spec.nodeName="${vmnode}" --no-headers)

  pid=$(/usr/bin/oc exec -n "${INSTALLATION_NAMESPACE}" "${handler}" -- /bin/bash -c "pgrep -f \"uid ${vmuid}.*no-fork\"")

  if /usr/bin/oc exec -n "${INSTALLATION_NAMESPACE}" "${handler}" -- /bin/bash -c "nft -v" > /dev/null 2>&1; then
    /usr/bin/oc exec -n "${INSTALLATION_NAMESPACE}" "${handler}" -- /bin/bash -c "nsenter -t ${pid} -n -- nft list ruleset" 2>/dev/null
  else
    echo "###################################"
    echo "Filter table:"
    echo "###################################"
    /usr/bin/oc exec -n "${INSTALLATION_NAMESPACE}" "${handler}" -- /bin/bash -c "nsenter -t ${pid} -n -- iptables -t filter -L" 2>/dev/null

    echo -e "\n\n###################################"
    echo "NAT table:"
    echo "###################################"
    /usr/bin/oc exec -n "${INSTALLATION_NAMESPACE}" "${handler}" -- /bin/bash -c "nsenter -t ${pid} -n -- iptables -t nat -L" 2>/dev/null
  fi
}

export -f gather_vm_by_pod_name
export -f gather_vm_info
export -f get_vm_rule_tables

"${DIR_NAME}"/version

"${DIR_NAME}"/vmConvertor

"${DIR_NAME}"/gather_vms_namespaces

if [[ -n $NS ]]; then
  if [[ -n "${VM}" ]]; then
    mapfile -t VMS < <(echo "${VM}" | tr ',' ' ')
    mapfile -t PODS < <(oc get pod -n "${NS}" --no-headers -o 'custom-columns=name:metadata.name')
    for vm in "${VMS[@]}"; do
      POD=$(echo "${PODS[@]}" | tr ' ' '\n' | grep -E "virt-launcher-${vm}-[^-]+$")
      gather_vm_info "${NS}" "${POD}" "${vm}"
    done

  else
    mapfile -t PODS < <(/usr/bin/oc get pod -n "$NS" -l kubevirt.io=virt-launcher --no-headers -o custom-columns=NAME:.metadata.name)
    echo "${PODS[@]}" | tr ' ' '\n' | xargs -t -P "${PROS}" --max-args=1 -I{} sh -c 'gather_vm_by_pod_name $1' -- "${NS}"_{}
  fi

else
  if [[ -n $VM ]]; then
    echo "ERROR: can't collect information for a specific VM without specifying the namespace"
    exit 1
  fi

  mapfile -t PODS < <(oc get pod --all-namespaces -l kubevirt.io=virt-launcher --no-headers | awk '{print $1 "_" $2}')
  echo "${PODS[@]}" | tr ' ' '\n' | xargs -P "${PROS}" --max-args=1 -t -I{} sh -c 'gather_vm_by_pod_name $1' -- {}

fi

"${DIR_NAME}"/logs.sh

sync

exit 0
