#!/usr/bin/env bash
# Copyright [2016] [Kevin Carter]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

function mkdir_check {
  if [ ! -d "$1" ];then
    mkdir -p "$1"
  fi
}

function ssh_agent_reset {
  # If you were running ssh-agent with forwarding this will clear out the keys
  #  in your cache which can cause confusion.
  if pgrep ssh-agent; then
    killall ssh-agent; eval `ssh-agent`
  fi
}

function iptables_general_rule_add {
if ! iptables -w -C $1;then
  iptables -w -I $1
fi
}

function iptables_filter_rule_add {
if ! iptables -w -t $1 -C $2;then
  iptables -w -t $1 -I $2
fi
}

function get_host_type {
python <<EOL
import json
with open('hosts.json') as f:
    x = json.loads(f.read())
for k, v in x.get("$1").items():
    print('%s:%s' % (k, v))
EOL
}

function get_all_hosts {
python <<EOL
import json
with open('hosts.json') as f:
    x = json.loads(f.read())
for i in x.values():
    for k, v in i.items():
      print('%s:%s' % (k, v))
EOL
}

function get_all_types {
python <<EOL
import json
with open('hosts.json') as f:
    x = json.loads(f.read())
for i in x.keys():
    print(i)
EOL
}

function wait_ssh {
echo "Waiting for all nodes to become available. This can take around ${1:-10} min"
for node in $(get_all_hosts); do
    echo "Waiting for node: ${node%%":"*} on 10.0.0.${node#*":"}"
    until ssh -q -o StrictHostKeyChecking=no -o BatchMode=yes -o ConnectTimeout=10 10.0.0.${node#*':'} exit > /dev/null; do
      sleep 15
    done
done
}

function rekick_vms {
# If you pass the short name of the host to the function it will only force rekick just the ONE host.
# Set the VM disk size in gigabytes
VM_DISK_SIZE="${VM_DISK_SIZE:-252}"
for node in ${1:-$(get_all_hosts)}; do
  for node_name in $(virsh list --all --name | grep "${node%%":"*}"); do
    virsh destroy "${node_name}" || true
  done
  # Instruct the system to run the image create.
  #  If you have the option ``VM_IMAGE_CREATE=true`` the system will reformat the disk image
  #  destroying anything that was it image previously.
  VM_IMAGE_CREATE=${VM_IMAGE_CREATE:-true}
  if [[ "${VM_IMAGE_CREATE}" = true ]]; then
    qemu-img create -f qcow2 \
                    -o preallocation=metadata,compat=1.1,lazy_refcounts=on \
                    /var/lib/libvirt/images/${node%%":"*}.openstackci.local.img \
                    "${VM_DISK_SIZE}G"
  fi
  VM_NAME=$(virsh list --all --name | grep "${node%%":"*}" || echo "")
  if [[ -z "${VM_NAME}" ]]; then
    virsh define /etc/libvirt/qemu/${node%%":"*}.openstackci.local.xml || true
    virsh create /etc/libvirt/qemu/${node%%":"*}.openstackci.local.xml || true
  else
    virsh start "${VM_NAME}"
  fi
done
}

function write_osa_general_confd {
CONFD_FILE="/etc/openstack_deploy/conf.d/${1}.yml"
echo "## DO NOT WRITE TO THIS FILE, CHANGES WILL BE LOST!" > ${CONFD_FILE}
echo "---" >> ${CONFD_FILE}
echo "$1:" >> ${CONFD_FILE}
for node in $(get_host_type ${2}); do
echo "  ${node%%':'*}:" >> ${CONFD_FILE}
echo "    ip: 172.29.236.${node#*":"}" >> ${CONFD_FILE}
done
}

function write_osa_cinder_confd {
CONFD_FILE="/etc/openstack_deploy/conf.d/${1}.yml"
echo "## DO NOT WRITE TO THIS FILE, CHANGES WILL BE LOST!" > ${CONFD_FILE}
echo "---" >> ${CONFD_FILE}
echo "$1:" >> ${CONFD_FILE}
for node in $(get_host_type ${2}); do
echo "  ${node%%':'*}:" >> ${CONFD_FILE}
echo "    ip: 172.29.236.${node#*":"}" >> ${CONFD_FILE}
cat >> ${CONFD_FILE} <<EOF
    container_vars:
      cinder_backends:
        limit_container_types: cinder_volume
        lvm:
          volume_group: cinder-volumes
          volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver
          volume_backend_name: LVM_iSCSI
          iscsi_ip_address: "172.29.236.${node#*":"}"
EOF
done
}

function write_osa_swift_proxy_confd {
CONFD_FILE="/etc/openstack_deploy/conf.d/${1}.yml"
echo "## DO NOT WRITE TO THIS FILE, CHANGES WILL BE LOST!" > ${CONFD_FILE}
echo "---" >> ${CONFD_FILE}
echo "$1:" >> ${CONFD_FILE}
for node in $(get_host_type ${2}); do
echo "  ${node%%':'*}:" >> ${CONFD_FILE}
echo "    ip: 172.29.236.${node#*":"}" >> ${CONFD_FILE}
cat >> ${CONFD_FILE} <<EOF
    container_vars:
      swift_proxy_vars:
        limit_container_types: swift_proxy
        read_affinity: "r1=100"
        write_affinity: "r1"
        write_affinity_node_count: "1 * replicas"
EOF
done
}

function write_osa_swift_storage_confd {
CONFD_FILE="/etc/openstack_deploy/conf.d/${1}.yml"
echo "## DO NOT WRITE TO THIS FILE, CHANGES WILL BE LOST!" > ${CONFD_FILE}
echo "---" >> ${CONFD_FILE}
echo "$1:" >> ${CONFD_FILE}
for node in $(get_host_type ${2}); do
echo "  ${node%%':'*}:" >> ${CONFD_FILE}
echo "    ip: 172.29.236.${node#*":"}" >> ${CONFD_FILE}
cat >> ${CONFD_FILE} <<EOF
    container_vars:
      swift_vars:
        limit_container_types: swift
        zone: 0
        region: 1
EOF
done
}

function osa_user_var_add {
  if ! grep -q "^$1" /etc/openstack_deploy/user_variables.yml; then
    echo "$2" | tee -a /etc/openstack_deploy/user_variables.yml
  else
    sed -i "s|$1.*|$2|g" /etc/openstack_deploy/user_variables.yml
  fi
}

function ansible_static_inventory {
CONFD_FILE="$1"
echo "## DO NOT WRITE TO THIS FILE, CHANGES WILL BE LOST!" > ${CONFD_FILE}
for node_type in $(get_all_types); do
  echo "[${node_type}]" >> ${CONFD_FILE}
  for node in $(get_host_type ${node_type}); do
    echo "10.0.0.${node#*":"}" >> ${CONFD_FILE}
  done
done
}

function install_bits {
successerator openstack-ansible $@
}

function successerator {
set +e
# Get the time taht the method was started
OP_START_TIME=$(date +%s)
#Set the initial return value to failure.
false
for ((RETRY=0; $? != 0 && RETRY < MAX_RETRIES; RETRY++)); do
  if [ ${RETRY} -gt 1 ]; then
    $@ -vvvv
  else
    $@
  fi
done

# If max retries were hit, fail.
if [ $? -ne 0 && [ ${RETRY} -eq ${MAX_RETRIES} ];then
  echo -e "\n Hit maximum number of retries, giving up..\n"
  exit
fi

# Print the time that the method completed.
OP_TOTAL_SECONDS="$(( $(date +%s) - OP_START_TIME ))"
REPORT_OUTPUT="${OP_TOTAL_SECONDS} seconds"
REPORT_DATA+="- Operation: [ $@ ]\t${REPORT_OUTPUT}\tNumber of Attempts [ ${RETRY} ]\n"
echo -e "Run Time = ${REPORT_OUTPUT}"
set -e
}