#!/usr/bin/env bash # Utility script used to interact with a deployment # @author Tim Rozet (trozet@redhat.com) VALID_CMDS="undercloud overcloud opendaylight debug-stack mock-detached -h --help" SSH_OPTIONS=(-o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o LogLevel=error) ##connects to undercloud ##params: user to login with, command to execute on undercloud (optional) function undercloud_connect { local user=$1 if [ -z "$1" ]; then echo "Missing required argument: user to login as to undercloud" return 1 fi if [ -z "$2" ]; then ssh ${SSH_OPTIONS[@]} ${user}@$(get_undercloud_ip) else ssh ${SSH_OPTIONS[@]} -T ${user}@$(get_undercloud_ip) "$2" fi } ##outputs the Undercloud's IP address ##params: none function get_undercloud_ip { echo $(arp -an | grep $(virsh domiflist undercloud | grep default |\ awk '{print $5}') | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") } ##connects to overcloud nodes ##params: node to login to, command to execute on overcloud (optional) function overcloud_connect { local node local node_output local node_ip if [ -z "$1" ]; then echo "Missing required argument: overcloud node to login to" return 1 elif ! echo "$1" | grep -E "(controller|compute)[0-9]+" > /dev/null; then echo "Invalid argument: overcloud node to login to must be in the format: \ controller or compute" return 1 fi node_output=$(undercloud_connect "stack" "source stackrc; nova list") node=$(echo "$1" | sed -E 's/([a-zA-Z]+)([0-9]+)/\1-\2/') node_ip=$(echo "$node_output" | grep "$node" | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") if [ "$node_ip" == "" ]; then echo -e "Unable to find IP for ${node} in \n${node_output}" return 1 fi if [ -z "$2" ]; then ssh ${SSH_OPTIONS[@]} heat-admin@${node_ip} else ssh ${SSH_OPTIONS[@]} -T heat-admin@${node_ip} "$2" fi } ##connects to opendaylight karaf console ##params: None function opendaylight_connect { local opendaylight_ip opendaylight_ip=$(undercloud_connect "stack" "cat overcloudrc | grep SDN_CONTROLLER_IP | grep -Eo [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") if [ "$opendaylight_ip" == "" ]; then echo -e "Unable to find IP for OpenDaylight in overcloudrc" return 1 else echo -e "Connecting to ODL Karaf console. Default password is 'karaf'" fi ssh -p 8101 ${SSH_OPTIONS[@]} karaf@${opendaylight_ip} } ##outputs heat stack deployment failures ##params: none function debug_stack { source ~/stackrc openstack stack failures list overcloud --long } resolve_cmd() { local given=$1 shift local list=($*) local inv=(${list[*]##${given}*}) local OIFS=$IFS; IFS='|'; local pat="${inv[*]}"; IFS=$OIFS shopt -s extglob echo "${list[*]##+($pat)}" shopt -u extglob } display_usage() { echo -e "Usage:\n$0 subcommand [ arguments ]\n" echo -e "Arguments:\n" echo -e " undercloud [ user [ command ] ] Connect to Undercloud VM as user and optionally execute a command" echo -e " user Optional: Defaults to 'stack'" echo -e " command Optional: Defaults to none" echo -e "" echo -e " opendaylight Connect to OpenDaylight Karaf console" echo -e "" echo -e " overcloud [ node [ command ] ] Connect to an Overcloud node and optionally execute a command" echo -e " node Required: in format controller|compute. Example: controller0" echo -e " command Optional: Defaults to none" echo -e "" echo -e " debug-stack Print parsed deployment failures to stdout" echo -e "" echo -e " mock-detached on | off Add firewall rules to the jump host to mock a detached deployment\n" } ##translates the command line argument ##params: $@ the entire command line is passed ##usage: parse_cmd_line() "$@" parse_cmdline() { local match match=($(resolve_cmd $1 $VALID_CMDS)) if [ ${#match[*]} -gt 1 ]; then echo "$1 is ambiguous, possible matches: ${match[*]}" >&2 exit 1 elif [ ${#match[*]} -lt 1 ]; then echo "$1 is not a recognized command. Use -h to see acceptable list" >&2 exit 1 else match=$(echo $match | tr -d ' ') fi case "$match" in -h|--help) display_usage exit 0 ;; undercloud) if [ -z "$2" ]; then # connect as stack by default undercloud_connect stack elif [ -z "$3" ]; then undercloud_connect "$2" else undercloud_connect "$2" "$3" fi exit 0 ;; overcloud) if [ -z "$2" ]; then overcloud_connect elif [ -z "$3" ]; then overcloud_connect "$2" else overcloud_connect "$2" "$3" fi exit 0 ;; opendaylight) opendaylight_connect exit 0 ;; debug-stack) undercloud_connect stack "$(typeset -f debug_stack); debug_stack" exit 0 ;; mock-detached) if [ "$2" == "on" ]; then echo "Ensuring we can talk to gerrit.opnfv.org" iptables -A OUTPUT -p tcp -d gerrit.opnfv.org --dport 443 -j ACCEPT echo "Blocking output http (80) traffic" iptables -A OUTPUT -p tcp --dport 80 -j REJECT iptables -A FORWARD -p tcp --dport 80 -j REJECT echo "Blocking output https (443) traffic" iptables -A OUTPUT -p tcp --dport 443 -j REJECT iptables -A FORWARD -p tcp --dport 443 -j REJECT echo "Blocking output dns (53) traffic" iptables -A FORWARD -p tcp --dport 53 -j REJECT elif [ "$2" == "off" ]; then echo "Cleaning gerrit.opnfv.org specific rule" iptables -D OUTPUT -p tcp -d gerrit.opnfv.org --dport 443 -j ACCEPT echo "Allowing output http (80) traffic" iptables -D OUTPUT -p tcp --dport 80 -j REJECT iptables -D FORWARD -p tcp --dport 80 -j REJECT echo "Allowing output https (443) traffic" iptables -D OUTPUT -p tcp --dport 443 -j REJECT iptables -D FORWARD -p tcp --dport 443 -j REJECT echo "Allowing output dns (53) traffic" iptables -D OUTPUT -p tcp --dport 53 -j REJECT iptables -D FORWARD -p tcp --dport 53 -j REJECT else display_usage fi exit 0 ;; *) echo -e "\n\nThis script is used to interact with Apex deployments\n\n" echo "Use -h to display help" exit 1 ;; esac } main() { parse_cmdline "$@" } main "$@"