1366 lines
31 KiB
Bash
Executable File
1366 lines
31 KiB
Bash
Executable File
#!/bin/bash
|
||
#
|
||
# yap - Yet Another Private WAN
|
||
#
|
||
|
||
export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
|
||
export DATA_DIR="/var/lib/yap/data"
|
||
|
||
SALT_PILLARS="/etc/bondingadmin/salt-config/pillars"
|
||
SALT_PILLARS_TOP="$SALT_PILLARS/top.sls"
|
||
|
||
|
||
# check_args <name>,[skip],<value>...
|
||
#
|
||
# Check a list of arguments for presence. Each argument is supplied along with
|
||
# the name and requirements. eg:
|
||
#
|
||
# "foo,,$1" - first argument is named 'foo' and is required
|
||
# "bar,,$2" - second argument is named 'bar' and is required
|
||
# "baz,skip,$3" - third argument is named 'baz' and may be omitted (skip args
|
||
# must be at the end)
|
||
#
|
||
# Displays message and returns error status if requirements are not met
|
||
#
|
||
# If successful, pass output to eval to set args in local scope:
|
||
#
|
||
# args=$(check_args foo,,$1 bar,,$2) || return 1
|
||
# eval $args
|
||
#
|
||
function check_args() {
|
||
for arg_def in "$@" ; do
|
||
OLD_IFS="$IFS"
|
||
IFS=","
|
||
set $arg_def
|
||
IFS="$OLD_IFS"
|
||
name="$1"
|
||
skip="$2"
|
||
value="$3"
|
||
if [ -z $skip ] ; then
|
||
if [ -z "$value" ] ; then
|
||
echo "Argument '$name' is required" >&2
|
||
return 1
|
||
fi
|
||
fi
|
||
echo "declare $name=\"$value\""
|
||
done
|
||
}
|
||
|
||
|
||
# get_var <var> [default]
|
||
#
|
||
# Get variable from data store. If unset, return default
|
||
#
|
||
function get_var() {
|
||
varfile="${DATA_DIR}/$1"
|
||
if [ -f "$varfile" ] ; then
|
||
cat "$varfile"
|
||
else
|
||
echo "$2"
|
||
fi
|
||
}
|
||
|
||
|
||
# set_var <var> <value>
|
||
#
|
||
# Set variable in data store
|
||
#
|
||
function set_var() {
|
||
varfile="${DATA_DIR}/$1"
|
||
vardir=$(dirname "$varfile")
|
||
if [ ! -d "$vardir" ] ; then
|
||
install -d -m 0755 "$vardir"
|
||
fi
|
||
echo -n "$2" > "$varfile"
|
||
}
|
||
|
||
|
||
# set_var <var> <value>
|
||
#
|
||
# Set variable in data store
|
||
#
|
||
function set_var_from_file() {
|
||
varfile="${DATA_DIR}/$1"
|
||
vardir=$(dirname "$varfile")
|
||
if [ ! -d "$vardir" ] ; then
|
||
install -d -m 0755 "$vardir"
|
||
fi
|
||
cp "$2" "$varfile"
|
||
}
|
||
|
||
|
||
# del_var <var>
|
||
#
|
||
# Delete variable from data store
|
||
#
|
||
function del_var() {
|
||
varfile="${DATA_DIR}/$1"
|
||
vardir=$(dirname "$varfile")
|
||
rm -f "$varfile"
|
||
|
||
# Clean up empty dirs
|
||
find $DATA_DIR -depth -type d -empty -exec rmdir {} \;
|
||
}
|
||
|
||
|
||
# del_section <section>
|
||
#
|
||
# Delete section from data store
|
||
#
|
||
function del_section() {
|
||
if [ -z "$1" ] ; then
|
||
echo "Refusing to delete entire store"
|
||
return 1
|
||
fi
|
||
vardir="${DATA_DIR}/$1"
|
||
rm -rf "$vardir"
|
||
|
||
# Clean up empty dirs
|
||
find $DATA_DIR -depth -type d -empty -exec rmdir {} \;
|
||
}
|
||
|
||
|
||
# has_var <var>
|
||
#
|
||
# Check if variable exists
|
||
#
|
||
function has_var() {
|
||
test -f "${DATA_DIR}/$1"
|
||
}
|
||
|
||
|
||
# List variables in data store. If an argument is specified, list only
|
||
# variables under that root.
|
||
#
|
||
function all_vars() {
|
||
for var in $(find $DATA_DIR/$1 -type f | sort) ; do
|
||
echo "${var#$DATA_DIR}"
|
||
done
|
||
}
|
||
|
||
|
||
# Dump variables in data store. If an argument is specified, list only
|
||
# variables under that root.
|
||
#
|
||
function dump_vars() {
|
||
for var in $(find $DATA_DIR/$1 -type f | sort) ; do
|
||
echo "${var#$DATA_DIR} $(cat $var)"
|
||
done
|
||
}
|
||
|
||
|
||
# List immediate variables in data store. If an argument is specified, list
|
||
# only variables under that root.
|
||
#
|
||
function list_vars() {
|
||
if [ -d "$DATA_DIR/$1" ] ; then
|
||
for var in $(find $DATA_DIR/$1 -mindepth 1 -maxdepth 1 -type f | sort) ; do
|
||
echo ${var#$DATA_DIR}
|
||
done
|
||
fi
|
||
}
|
||
|
||
|
||
# Check if section exists
|
||
#
|
||
function has_section() {
|
||
test -d ${DATA_DIR}/$1
|
||
}
|
||
|
||
|
||
# Get section location on disk
|
||
#
|
||
function get_section_path() {
|
||
echo ${DATA_DIR}/$1
|
||
}
|
||
|
||
|
||
# List immediate sections in data store. If an argument is specified, list only
|
||
# sections under that section.
|
||
#
|
||
function list_sections() {
|
||
if [ -d $DATA_DIR/$1 ] ; then
|
||
for var in $(find $DATA_DIR/$1 -mindepth 1 -maxdepth 1 -type d | sort) ; do
|
||
echo ${var#$DATA_DIR/}
|
||
done
|
||
fi
|
||
}
|
||
|
||
|
||
function ip2dec() {
|
||
local a b c d ip=$@
|
||
IFS=. read -r a b c d <<< "$ip"
|
||
printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))"
|
||
}
|
||
|
||
|
||
function dec2ip() {
|
||
local delim ip dec=$@
|
||
for e in {3..0} ; do
|
||
((octet = dec / (256 ** e) ))
|
||
((dec -= octet * 256 ** e))
|
||
ip+=$delim$octet
|
||
delim=.
|
||
done
|
||
printf '%s' "$ip"
|
||
}
|
||
|
||
|
||
# Generate an IP for a VLAN interface based on the VLAN and and the YAP ID.
|
||
# The first octet will always be 100, while the other 3 octets are split into
|
||
# 3 sections of varying size to contain the IP type, the VLAN, and the YAP ID:
|
||
#
|
||
# type: 1-bit
|
||
# vlan ID: 12-bits
|
||
# YAP ID: 11-bits
|
||
#
|
||
# The resulting IP should be used with a prefix length of 21
|
||
#
|
||
function get_vlan_ip() {
|
||
vlan_id=$1
|
||
yap_id=$2
|
||
|
||
# Start at 100.0.0.0
|
||
local ip=$(ip2dec 100.0.0.0)
|
||
|
||
# Add the VLAN ID, shifted 11-bits
|
||
((ip += vlan_id << 11))
|
||
|
||
# Add the YAP ID
|
||
((ip += yap_id))
|
||
|
||
dec2ip $ip
|
||
}
|
||
|
||
|
||
function validate_ip() {
|
||
if ! [[ $1 =~ ^(0*(1?[0-9]{1,2}|2([0-4][0-9]|5[0-5]))\.){3}0*(1?[0-9]{1,2}|2([0-4][0-9]|5[0-5]))$ ]] ; then
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Get resource from API
|
||
#
|
||
function api_get() {
|
||
args=$(check_args path,,$1) || return 1
|
||
eval $args
|
||
|
||
if ! has_var /auth/password ; then
|
||
echo "No bondingadmin auth set. Use $0 auth-set <email> <password> to set it."
|
||
return 1
|
||
fi
|
||
|
||
host=$(grep mgmt_server_url /etc/bondingadmin/bondingadmin.conf | cut -d ' ' -f 3)
|
||
email=$(get_var /auth/email)
|
||
password=$(get_var /auth/password)
|
||
|
||
curl --user "$email:$password" -k -s --fail https://$host$path
|
||
}
|
||
|
||
|
||
# Set the auth parameters for the API
|
||
#
|
||
function auth_set() {
|
||
args=$(check_args email,,$1 password,,$2) || return 1
|
||
eval $args
|
||
|
||
set_var /auth/email "$email"
|
||
set_var /auth/password "$password"
|
||
}
|
||
|
||
|
||
# Generate a table ID from the space ID of the given space
|
||
#
|
||
function get_table_id() {
|
||
args=$(check_args space,,$1) || return 1
|
||
eval $args
|
||
|
||
echo $(( $(get_var /spaces/$space/id) + 8192 ))
|
||
}
|
||
|
||
|
||
# Generate a unique ID for the YAP node, used in IP addresses
|
||
#
|
||
function get_next_yap_ip() {
|
||
local yap_id yap_id
|
||
if has_var last_yap_id ; then
|
||
yap_id=$(get_var last_yap_id)
|
||
else
|
||
yap_id=0
|
||
fi
|
||
((yap_id += 1))
|
||
set_var last_yap_id $yap_id
|
||
echo $yap_id
|
||
}
|
||
|
||
#
|
||
# Salt management
|
||
#
|
||
function get_full_nodelist() {
|
||
local nodelist=""
|
||
local vxr
|
||
for vxr in $(list_sections /vxrs) ; do
|
||
local name=$(basename $vxr)
|
||
nodelist="${nodelist} ${name}"
|
||
done
|
||
|
||
local aggregator
|
||
for aggregator in $(list_sections /aggregators) ; do
|
||
local id=$(basename $aggregator)
|
||
nodelist="${nodelist} node-${id}"
|
||
done
|
||
echo $(salt_nodelist $nodelist)
|
||
}
|
||
|
||
|
||
function get_vxr_nodelist() {
|
||
local nodelist=""
|
||
local vxr
|
||
for vxr in $(list_sections /vxrs) ; do
|
||
local name=$(basename $vxr)
|
||
nodelist="${nodelist} ${name}"
|
||
done
|
||
echo $(salt_nodelist $nodelist)
|
||
}
|
||
|
||
|
||
function get_region_nodelist() {
|
||
args=$(check_args region,,$1) || return 1
|
||
eval $args
|
||
|
||
local nodelist=""
|
||
local vxr
|
||
for vxr in $(list_sections /vxrs) ; do
|
||
local name=$(basename $vxr)
|
||
if [ "$(get_var $vxr/region)" = $region ] ; then
|
||
nodelist="${nodelist} ${name}"
|
||
fi
|
||
done
|
||
|
||
local aggregator
|
||
for aggregator in $(list_sections /aggregators) ; do
|
||
local id=$(basename $aggregator)
|
||
if [ "$(get_var $aggregator/region)" = $region ] ; then
|
||
nodelist="${nodelist} node-${id}"
|
||
fi
|
||
done
|
||
echo $(salt_nodelist $nodelist)
|
||
}
|
||
|
||
|
||
function salt_nodelist() {
|
||
local nodelist=''
|
||
local delim=''
|
||
for node in $@ ; do
|
||
nodelist="${nodelist}${delim}${node}"
|
||
delim=','
|
||
done
|
||
echo "L@$nodelist"
|
||
}
|
||
|
||
|
||
function salt_update() {
|
||
nodelist="$@"
|
||
|
||
install -d -m 0755 $SALT_PILLARS/yap/regions
|
||
install -d -m 0755 $SALT_PILLARS/yap/hosts
|
||
|
||
new_common_file=$(mktemp)
|
||
{
|
||
echo "yap:"
|
||
echo " ipsec_key: '$(get_var /ipsec/key)'"
|
||
} > $new_common_file
|
||
mv $new_common_file $SALT_PILLARS/yap/common.sls
|
||
chmod 0644 $SALT_PILLARS/yap/common.sls
|
||
|
||
local region
|
||
for region in $(list_sections /regions) ; do
|
||
pillar_file=$SALT_PILLARS/yap/regions/$(basename $region).sls
|
||
new_pillar_file=$(mktemp)
|
||
|
||
{
|
||
echo "yap:"
|
||
echo " spaces:"
|
||
local space
|
||
for space in $(list_sections $region/spaces) ; do
|
||
local space_name=$(basename $space)
|
||
local vlan=$(get_var $space/vlan)
|
||
local space_id=$(get_var /spaces/$space_name/id)
|
||
echo " $space_name:"
|
||
echo " vlan: $vlan"
|
||
echo " id: $space_id"
|
||
done
|
||
} > $new_pillar_file
|
||
|
||
mv $new_pillar_file $pillar_file
|
||
chmod 0644 $pillar_file
|
||
done
|
||
|
||
if [ ! -f $SALT_PILLARS_TOP ] ; then
|
||
echo "base:" > $SALT_PILLARS_TOP
|
||
fi
|
||
|
||
cp $SALT_PILLARS_TOP ${SALT_PILLARS_TOP}.prev
|
||
new_top=$(mktemp)
|
||
|
||
sed '/^### BEGIN YAP ###/,/### END YAP ###/d' $SALT_PILLARS_TOP > $new_top
|
||
|
||
echo "### BEGIN YAP ###" >> $new_top
|
||
|
||
local vxr
|
||
for vxr in $(list_sections /vxrs) ; do
|
||
new_host_file=$(mktemp)
|
||
local region=$(get_var $vxr/region)
|
||
local trunk=$(get_var $vxr/trunk)
|
||
local yap_id=$(get_var $vxr/yap_id)
|
||
local global=$(get_var $vxr/global false)
|
||
local name=$(basename $vxr)
|
||
local vxr_peers
|
||
{
|
||
echo -e "yap:"
|
||
echo -e " yap_id: $yap_id"
|
||
echo -e " trunk: $trunk"
|
||
echo -e " global: $global"
|
||
echo -e " global_interface_options:"
|
||
for option in $(list_vars $vxr/global_interface_options) ; do
|
||
echo -e " '$(basename $option)': '$(get_var $option)'"
|
||
done
|
||
echo -e " vxlan_peers:"
|
||
for peer_vxr in $(list_sections /vxrs) ; do
|
||
if [ "$peer_vxr" != "$vxr" ] ; then
|
||
echo -e " - $(get_var $peer_vxr/ip)"
|
||
fi
|
||
done
|
||
} > $new_host_file
|
||
mv $new_host_file $SALT_PILLARS/yap/hosts/$name.sls
|
||
chmod 0644 $SALT_PILLARS/yap/hosts/$name.sls
|
||
|
||
{
|
||
echo -e " '$name':"
|
||
echo -e " - yap.common"
|
||
echo -e " - yap.regions.$region"
|
||
echo -e " - yap.hosts.$name\n"
|
||
} >> $new_top
|
||
done
|
||
|
||
local aggregator
|
||
for aggregator in $(list_sections /aggregators) ; do
|
||
new_host_file=$(mktemp)
|
||
local id=$(basename $aggregator)
|
||
local yap_id=$(get_var $aggregator/yap_id)
|
||
local region=$(get_var $aggregator/region)
|
||
local trunk=$(get_var $aggregator/trunk)
|
||
{
|
||
echo -e "yap:"
|
||
echo -e " yap_id: $yap_id"
|
||
echo -e " trunk: $trunk"
|
||
} > $new_host_file
|
||
new_host_spaces_file=$(mktemp)
|
||
has_spaces=0
|
||
{
|
||
echo -e " spaces:"
|
||
for space in $(list_sections $aggregator/spaces) ; do
|
||
has_spaces=1
|
||
local space_name=$(basename $space)
|
||
{
|
||
echo -e " $space_name:"
|
||
local ip=$(get_var $space/ip)
|
||
if [ -n "$ip" ] ; then
|
||
echo -e " ip: $ip"
|
||
fi
|
||
local bird_config=$(get_var $space/bird_config)
|
||
if [ -n "$bird_config" ] ; then
|
||
echo -e " bird_config: |-"
|
||
echo -e "$bird_config" | sed -e 's/^/ /g'
|
||
fi
|
||
}
|
||
done
|
||
} > $new_host_spaces_file
|
||
|
||
if [ $has_spaces = 1 ] ; then
|
||
cat $new_host_spaces_file >> $new_host_file
|
||
fi
|
||
mv $new_host_file $SALT_PILLARS/yap/hosts/node-$id.sls
|
||
chmod 0644 $SALT_PILLARS/yap/hosts/node-$id.sls
|
||
|
||
{
|
||
echo -e " 'node-$id':"
|
||
echo -e " - yap.common"
|
||
echo -e " - yap.regions.$region"
|
||
echo -e " - yap.hosts.node-$id\n"
|
||
} >> $new_top
|
||
done
|
||
|
||
echo "### END YAP ###" >> $new_top
|
||
|
||
mv $new_top $SALT_PILLARS_TOP
|
||
chmod 0644 $SALT_PILLARS_TOP
|
||
|
||
# Update nodes if given
|
||
if [ -n "$nodelist" ] ; then
|
||
salt -C "$nodelist" state.sls yap
|
||
fi
|
||
}
|
||
|
||
function salt_exec() {
|
||
nodelist="$1"
|
||
shift
|
||
|
||
salt -C "$nodelist" "$@"
|
||
}
|
||
|
||
|
||
function upgrade() {
|
||
args=$(check_args region,skip,$1)
|
||
eval $args
|
||
|
||
if [ ! -z "$region" ] ; then
|
||
salt_update "$(get_region_nodelist $region)"
|
||
salt_exec "$(get_region_nodelist $region)" service.restart yap ||:
|
||
else
|
||
salt_update "$(get_full_nodelist)"
|
||
salt_exec "$(get_full_nodelist)" service.restart yap ||:
|
||
fi
|
||
}
|
||
|
||
|
||
#
|
||
# Region commands
|
||
#
|
||
|
||
function region_list() {
|
||
for region in $(list_sections /regions) ; do
|
||
basename "$region"
|
||
done
|
||
}
|
||
|
||
|
||
function region_show() {
|
||
args=$(check_args region,,$1) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/regions/$region" ; then
|
||
echo "Region does not exist"
|
||
return 1
|
||
fi
|
||
|
||
echo "name: $region"
|
||
echo
|
||
echo "Aggregators:"
|
||
|
||
for aggregator in $(list_sections "/aggregators") ; do
|
||
if [ "$(get_var $aggregator/region)" = $region ] ; then
|
||
echo " $(get_var $aggregator/name)"
|
||
fi
|
||
done
|
||
|
||
echo
|
||
echo "VLAN associations:"
|
||
|
||
for space in $(list_sections "/regions/$region/spaces") ; do
|
||
var="$space/vlan"
|
||
if has_var "$var" ; then
|
||
vlan_id=$(get_var $var)
|
||
echo " $(basename space) $vlan_id: $(get_vlan_ip $vlan_id 0)/21"
|
||
fi
|
||
done
|
||
|
||
|
||
}
|
||
|
||
|
||
function region_add() {
|
||
args=$(check_args region,,$1) || return 1
|
||
eval $args
|
||
|
||
if has_section "/regions/$region" ; then
|
||
echo "Region already exists"
|
||
return
|
||
fi
|
||
|
||
set_var "/regions/$region/name" "$region"
|
||
|
||
region_show $region
|
||
}
|
||
|
||
|
||
function region_delete() {
|
||
args=$(check_args region,,$1) || return 1
|
||
eval $args
|
||
|
||
del_section "/regions/$region"
|
||
}
|
||
|
||
|
||
#
|
||
# Space commands
|
||
#
|
||
|
||
function space_list() {
|
||
for space in $(list_sections /spaces) ; do
|
||
basename "$space"
|
||
done
|
||
}
|
||
|
||
|
||
function space_show() {
|
||
args=$(check_args space,,$1) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/spaces/$space" ; then
|
||
echo "Space does not exist"
|
||
return 1
|
||
fi
|
||
|
||
echo "key: $space"
|
||
echo "id: $(get_var /spaces/$space/id)"
|
||
echo "table id: $(get_table_id $space)"
|
||
echo
|
||
echo "VLAN associations:"
|
||
|
||
for region in $(list_sections /regions) ; do
|
||
var="$region/spaces/$space/vlan"
|
||
if has_var "$var" ; then
|
||
echo -e "$(basename $region)\t$(get_var $var)"
|
||
fi
|
||
done
|
||
}
|
||
|
||
|
||
function space_add() {
|
||
args=$(check_args space,,$1) || return 1
|
||
eval $args
|
||
|
||
if has_section "/spaces/$space" ; then
|
||
echo "Space already exists"
|
||
return 1
|
||
fi
|
||
|
||
if ! api_get "/api/v3/spaces/$space/" > /dev/null ; then
|
||
echo "Space not found in bondingadmin"
|
||
return 1
|
||
fi
|
||
|
||
space_json=$(api_get /api/v3/spaces/$space/)
|
||
private_wan_enabled=$(echo $space_json| jq .private_wan_enabled)
|
||
if ! $private_wan_enabled ; then
|
||
echo "Space ${space} does not have private WAN enabled."
|
||
return 1
|
||
fi
|
||
id=$(echo $space_json| jq .id)
|
||
set_var "/spaces/$space/id" "$id"
|
||
|
||
space_show $space
|
||
}
|
||
|
||
|
||
function space_delete() {
|
||
args=$(check_args space,,$1) || return 1
|
||
eval $args
|
||
|
||
for section in $(list_sections /regions/); do
|
||
for space_path in $(list_sections $section/spaces/); do
|
||
if [ "$(basename $space_path)" = "$space" ] ; then
|
||
echo "You must remove the VLAN for region $(basename $section) first. Use vlan-remove."
|
||
return 1
|
||
fi
|
||
done
|
||
done
|
||
|
||
# Clean up aggregator's space IP/custom configuration automatically
|
||
for agg_section in $(list_sections /aggregators/); do
|
||
for space_path in $(list_sections $agg_section/spaces/); do
|
||
if [ "$(basename $space_path)" = "$space" ] ; then
|
||
del_section "$space_path"
|
||
fi
|
||
done
|
||
done
|
||
|
||
del_section "/spaces/$space"
|
||
}
|
||
|
||
|
||
#
|
||
# Subnet commands
|
||
#
|
||
|
||
function subnet_get() {
|
||
args=$(check_args space,,$1, region,,$2, vlan_id,skip,$3) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/spaces/$space" ; then
|
||
echo "Space does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! has_section "/regions/$region" ; then
|
||
echo "Region does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! has_var "/regions/$region/spaces/$space/vlan"; then
|
||
if [ -z "$vlan_id" ] ; then
|
||
echo "No VLAN configured: argument 'vlan_id' is required"
|
||
return 1
|
||
fi
|
||
vlan_validate $space $region $vlan_id
|
||
else
|
||
vlan_id=$(get_var "/regions/$region/spaces/$space/vlan")
|
||
fi
|
||
|
||
echo "Subnet: $(get_vlan_ip $vlan_id 0)/21"
|
||
echo "Firewall: $(get_vlan_ip $vlan_id 1)"
|
||
echo "Aggregators:"
|
||
|
||
for aggregator in $(list_sections "/aggregators") ; do
|
||
if [ "$(get_var $aggregator/region)" = $region ] ; then
|
||
ip=$(get_vlan_ip $vlan_id $(get_var $aggregator/yap_id))
|
||
echo " $(get_var $aggregator/name): $ip"
|
||
fi
|
||
done
|
||
}
|
||
|
||
|
||
#
|
||
# Aggregator commands
|
||
#
|
||
|
||
function aggregator_list() {
|
||
for aggregator in $(list_sections /aggregators) ; do
|
||
basename "$aggregator"
|
||
done
|
||
}
|
||
|
||
|
||
function aggregator_show() {
|
||
args=$(check_args aggregator,,$1) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/aggregators/$aggregator" ; then
|
||
echo "Aggregator does not exist"
|
||
return 1
|
||
fi
|
||
|
||
echo "id: $aggregator"
|
||
echo "yap_id: $(get_var /aggregators/$aggregator/yap_id)"
|
||
echo "name: $(get_var /aggregators/$aggregator/name)"
|
||
echo "region: $(get_var /aggregators/$aggregator/region)"
|
||
echo "trunk: $(get_var /aggregators/$aggregator/trunk)"
|
||
}
|
||
|
||
|
||
function aggregator_add() {
|
||
args=$(check_args aggregator,,$1 region,,$2 trunk,,$3) || return 1
|
||
eval $args
|
||
|
||
if has_section "/aggregators/$aggregator" ; then
|
||
echo "Aggregator already exists"
|
||
return 1
|
||
fi
|
||
|
||
if ! has_section "/regions/$region" ; then
|
||
echo "Region does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! api_get "/api/v3/aggregators/$aggregator/" > /dev/null ; then
|
||
echo "Aggregator not found in bondingadmin"
|
||
return 1
|
||
fi
|
||
|
||
name=$(api_get /api/v3/aggregators/$aggregator/ | jq -r .name)
|
||
set_var "/aggregators/$aggregator/name" "$name"
|
||
set_var "/aggregators/$aggregator/region" "$region"
|
||
set_var "/aggregators/$aggregator/trunk" "$trunk"
|
||
set_var "/aggregators/$aggregator/yap_id" "$(get_next_yap_ip)"
|
||
|
||
salt_update node-$aggregator ||:
|
||
|
||
aggregator_show $aggregator
|
||
}
|
||
|
||
|
||
function aggregator_trunk_set() {
|
||
args=$(check_args aggregator,,$1 trunk,,$2) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/aggregators/$aggregator" ; then
|
||
echo "Aggregator does not exist"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/aggregators/$aggregator/trunk" "$trunk"
|
||
|
||
salt_update node-$aggregator ||:
|
||
salt_exec node-$aggregator service.restart yap ||:
|
||
|
||
aggregator_show $aggregator
|
||
}
|
||
|
||
|
||
function aggregator_set_space_ip() {
|
||
args=$(check_args aggregator,,$1 space,,$2 ip,,$3) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/aggregators/$aggregator" ; then
|
||
echo "Aggregator does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! has_section "/spaces/$space" ; then
|
||
echo "Space does not exist"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/aggregators/$aggregator/spaces/$space/ip" "$ip"
|
||
|
||
salt_update node-$aggregator ||:
|
||
salt_exec node-$aggregator cmd.run "yap restart $space" ||:
|
||
|
||
aggregator_show $aggregator
|
||
}
|
||
|
||
|
||
function aggregator_remove_space_ip() {
|
||
args=$(check_args aggregator,,$1 space,,$2) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/aggregators/$aggregator" ; then
|
||
echo "Aggregator does not exist"
|
||
return 1
|
||
fi
|
||
|
||
del_var "/aggregators/$aggregator/spaces/$space/ip"
|
||
|
||
salt_update node-$aggregator ||:
|
||
salt_exec node-$aggregator cmd.run "yap restart $space" ||:
|
||
|
||
aggregator_show $aggregator
|
||
}
|
||
|
||
|
||
function aggregator_set_space_bird_config() {
|
||
args=$(check_args aggregator,,$1 space,,$2 file,,$3) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/aggregators/$aggregator" ; then
|
||
echo "Aggregator does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! has_section "/spaces/$space" ; then
|
||
echo "Space does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if [ ! -f $file ] ; then
|
||
echo "File does not exist"
|
||
return 1
|
||
fi
|
||
|
||
set_var_from_file "/aggregators/$aggregator/spaces/$space/bird_config" $file
|
||
|
||
salt_update node-$aggregator ||:
|
||
salt_exec node-$aggregator cmd.run "yap restart $space" ||:
|
||
|
||
aggregator_show $aggregator
|
||
}
|
||
|
||
|
||
function aggregator_remove_space_bird_config() {
|
||
args=$(check_args aggregator,,$1 space,,$2) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/aggregators/$aggregator" ; then
|
||
echo "Aggregator does not exist"
|
||
return 1
|
||
fi
|
||
|
||
del_var "/aggregators/$aggregator/spaces/$space/bird_config"
|
||
|
||
salt_update node-$aggregator ||:
|
||
salt_exec node-$aggregator cmd.run "yap restart $space" ||:
|
||
|
||
aggregator_show $aggregator
|
||
}
|
||
|
||
|
||
function aggregator_delete() {
|
||
args=$(check_args aggregator,,$1) || return 1
|
||
eval $args
|
||
|
||
del_section "/aggregators/$aggregator"
|
||
|
||
for section in $(list_sections /regions/aggregators/) ; do
|
||
if [ "$(basename $section)" = "$aggregator" ] ; then
|
||
del_section "$section"
|
||
fi
|
||
done
|
||
|
||
salt_update node-$aggregator ||:
|
||
salt_exec node-$aggregator service.disable yap-check-policy-rules.timer ||:
|
||
salt_exec node-$aggregator service.stop yap-check-policy-rules.timer ||:
|
||
salt_exec node-$aggregator service.disable yap ||:
|
||
salt_exec node-$aggregator service.stop yap
|
||
}
|
||
|
||
|
||
#
|
||
# VXR commands
|
||
#
|
||
|
||
function vxr_list() {
|
||
for vxr in $(list_sections /vxrs) ; do
|
||
basename "$vxr"
|
||
done
|
||
}
|
||
|
||
|
||
function vxr_show() {
|
||
args=$(check_args vxr,,$1) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/vxrs/$vxr" ; then
|
||
echo "VXR does not exist"
|
||
return 1
|
||
fi
|
||
|
||
echo "name: $vxr"
|
||
echo "yap_id: $(get_var /vxrs/$vxr/yap_id)"
|
||
echo "ip: $(get_var /vxrs/$vxr/ip)"
|
||
echo "region: $(get_var /vxrs/$vxr/region)"
|
||
echo "trunk: $(get_var /vxrs/$vxr/trunk)"
|
||
echo "global: $(get_var /vxrs/$vxr/global false)"
|
||
}
|
||
|
||
|
||
function vxr_add() {
|
||
args=$(check_args vxr,,$1 ip,,$2 region,,$3 trunk,,$4) || return 1
|
||
eval $args
|
||
|
||
if has_section "/vxrs/$vxr" ; then
|
||
echo "VXR already exists"
|
||
return 1
|
||
fi
|
||
|
||
if ! has_section "/regions/$region" ; then
|
||
echo "Region does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! validate_ip $ip ; then
|
||
echo "IP is not valid"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/vxrs/$vxr/ip" "$ip"
|
||
set_var "/vxrs/$vxr/region" "$region"
|
||
set_var "/vxrs/$vxr/trunk" "$trunk"
|
||
set_var "/vxrs/$vxr/yap_id" "$(get_next_yap_ip)"
|
||
|
||
# All VXRs need the IP
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
|
||
# Additional apply for authorized keys, etc.
|
||
salt $vxr state.apply ||:
|
||
|
||
salt_exec $(get_vxr_nodelist) service.restart yap-firewall ||:
|
||
salt_exec $(get_vxr_nodelist) service.restart yap ||:
|
||
|
||
vxr_show $vxr
|
||
}
|
||
|
||
|
||
function vxr_trunk_set() {
|
||
args=$(check_args vxr,,$1 trunk,,$2) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/vxrs/$vxr" ; then
|
||
echo "VXR does not exist"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/vxrs/$vxr/trunk" "$trunk"
|
||
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
salt_exec $vxr service.restart yap ||:
|
||
|
||
vxr_show $vxr
|
||
}
|
||
|
||
|
||
function vxr_ip_set() {
|
||
args=$(check_args vxr,,$1 ip,,$2) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/vxrs/$vxr" ; then
|
||
echo "VXR does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! validate_ip $ip ; then
|
||
echo "IP is not valid"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/vxrs/$vxr/ip" "$ip"
|
||
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
salt_exec $(get_vxr_nodelist) service.restart yap
|
||
|
||
vxr_show $vxr
|
||
}
|
||
|
||
|
||
function vxr_enable_global() {
|
||
args=$(check_args vxr,,$1) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/vxrs/$vxr" ; then
|
||
echo "VXR does not exist"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/vxrs/$vxr/global" true
|
||
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
salt_exec $vxr cmd.run 'yap restart-global' ||:
|
||
|
||
vxr_show $vxr
|
||
}
|
||
|
||
|
||
function vxr_disable_global() {
|
||
args=$(check_args vxr,,$1) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/vxrs/$vxr" ; then
|
||
echo "VXR does not exist"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/vxrs/$vxr/global" false
|
||
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
salt_exec $vxr cmd.run 'yap restart-global' ||:
|
||
|
||
vxr_show $vxr
|
||
}
|
||
|
||
|
||
function vxr_set_global_interface_option() {
|
||
args=$(check_args vxr,,$1 name,,$2 value,,$3) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/vxrs/$vxr" ; then
|
||
echo "VXR does not exist"
|
||
return 1
|
||
fi
|
||
|
||
set_var "/vxrs/$vxr/global_interface_options/$name" "$value"
|
||
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
salt_exec $vxr cmd.run 'yap restart-global' ||:
|
||
|
||
vxr_show $vxr
|
||
}
|
||
|
||
|
||
function vxr_delete_global_interface_option() {
|
||
args=$(check_args vxr,,$1 name,,$2) || return 1
|
||
eval $args
|
||
|
||
if ! has_section "/vxrs/$vxr" ; then
|
||
echo "VXR does not exist"
|
||
return 1
|
||
fi
|
||
|
||
del_var "/vxrs/$vxr/global_interface_options/$name"
|
||
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
salt_exec $vxr cmd.run 'yap restart-global' ||:
|
||
|
||
vxr_show $vxr
|
||
}
|
||
|
||
|
||
function vxr_delete() {
|
||
args=$(check_args vxr,,$1) || return 1
|
||
eval $args
|
||
|
||
del_section "/vxrs/$vxr"
|
||
|
||
for section in $(list_sections /regions/vxrs/) ; do
|
||
if [ "$(basename $section)" = "$vxr" ] ; then
|
||
del_section "$section"
|
||
fi
|
||
done
|
||
|
||
salt_update $(get_vxr_nodelist) ||:
|
||
salt_exec $vxr service.disable yap ||:
|
||
salt_exec $vxr service.stop yap
|
||
}
|
||
|
||
|
||
#
|
||
# VLAN commands
|
||
#
|
||
|
||
function vlan_validate() {
|
||
args=$(check_args space,,$1 region,,$2 vlan_id,,$3) || return 1
|
||
eval $args
|
||
|
||
if ! [[ $vlan_id =~ [0-9]* ]] ; then
|
||
echo "VLAN must be numeric"
|
||
return 1
|
||
fi
|
||
|
||
if [[ $vlan_id -lt 2 ]] ; then
|
||
echo "VLAN must be greater than 1"
|
||
return 1
|
||
fi
|
||
|
||
if [[ $vlan_id -gt 4095 ]] ; then
|
||
echo "VLAN must be less than 4096"
|
||
return 1
|
||
fi
|
||
|
||
for space_path in $(list_sections /regions/$region/spaces); do
|
||
if [ "$(get_var $space_path/vlan)" = "$vlan_id" ] ; then
|
||
echo "VLAN ${vlan_id} conflicts with space $(basename $space_path) in region ${region}"
|
||
return 1
|
||
fi
|
||
done
|
||
}
|
||
|
||
function vlan_set() {
|
||
args=$(check_args space,,$1 region,,$2 vlan_id,,$3) || return 1
|
||
eval $args
|
||
|
||
if ! has_section /spaces/$space ; then
|
||
echo "Space does not exist"
|
||
return 1
|
||
fi
|
||
|
||
if ! has_section /regions/$region ; then
|
||
echo "Region does not exist"
|
||
return 1
|
||
fi
|
||
|
||
vlan_validate $space $region $vlan_id
|
||
|
||
set_var "/regions/$region/spaces/$space/vlan" "$vlan_id"
|
||
|
||
salt_update $(get_region_nodelist $region) ||:
|
||
salt_exec "$(get_region_nodelist $region)" cmd.run "yap restart $space"
|
||
}
|
||
|
||
|
||
function vlan_remove() {
|
||
args=$(check_args space,,$1 region,,$2) || return 1
|
||
eval $args
|
||
|
||
del_var "/regions/$region/spaces/$space/vlan"
|
||
|
||
salt_exec "$(get_region_nodelist $region)" cmd.run "yap stop $space" ||:
|
||
salt_update $(get_region_nodelist $region)
|
||
}
|
||
|
||
|
||
#
|
||
# IPSEC commands
|
||
#
|
||
|
||
function ipsec_enable() {
|
||
if has_var /ipsec/key ; then
|
||
echo "IPSEC is already enabled"
|
||
return 1
|
||
fi
|
||
|
||
key=$(hexdump -n 20 -e '5/4 "%08X"' /dev/urandom)
|
||
set_var /ipsec/key "0x$key"
|
||
|
||
nodelist="$(get_vxr_nodelist)"
|
||
if [ -n "$nodelist" ] ; then
|
||
salt_update $nodelist ||:
|
||
salt_exec "$nodelist" cmd.run "yap start-ipsec"
|
||
fi
|
||
}
|
||
|
||
function ipsec_disable() {
|
||
del_var /ipsec/key
|
||
nodelist="$(get_vxr_nodelist)"
|
||
if [ -n "$nodelist" ] ; then
|
||
salt_update $nodelist ||:
|
||
salt_exec "$nodelist" cmd.run "yap stop-ipsec"
|
||
fi
|
||
}
|
||
|
||
|
||
function usage() {
|
||
echo "$0 <action> [args]"
|
||
echo
|
||
echo "Actions:"
|
||
echo
|
||
echo "region-list"
|
||
echo "region-show <region>"
|
||
echo "region-add <region>"
|
||
echo "region-delete <region>"
|
||
echo
|
||
echo "space-list"
|
||
echo "space-show <spacekey>"
|
||
echo "space-add <spacekey>"
|
||
echo "space-delete <spacekey>"
|
||
echo
|
||
echo "subnet-get <spacekey> <region> [vlan_id]"
|
||
echo
|
||
echo "agg-list"
|
||
echo "agg-show <id>"
|
||
echo "agg-add <id> <region> <trunk>"
|
||
echo "agg-trunk-set <id> <trunk>"
|
||
echo "agg-delete <id>"
|
||
echo "agg-set-space-ip <id> <spacekey> <ip>"
|
||
echo "agg-remove-space-ip <id> <spacekey>"
|
||
echo "agg-set-space-bird-config <id> <spacekey> <filename>"
|
||
echo "agg-remove-space-bird-config <id> <spacekey>"
|
||
echo
|
||
echo "vxr-list"
|
||
echo "vxr-show <name>"
|
||
echo "vxr-add <name> <ip> <region> <trunk>"
|
||
echo "vxr-ip-set <name> <ip>"
|
||
echo "vxr-trunk-set <name> <trunk>"
|
||
echo "vxr-enable-global <name>"
|
||
echo "vxr-disable-global <name>"
|
||
echo "vxr-set-global-interface-option <name> <value>"
|
||
echo "vxr-delete-global-interface-option <name>"
|
||
echo "vxr-delete <name>"
|
||
echo
|
||
echo "vlan-set <spacekey> <region> <vlan_id>"
|
||
echo "vlan-remove <spacekey> <region>"
|
||
echo
|
||
echo "ipsec-enable"
|
||
echo "ipsec-disable"
|
||
|
||
echo "auth-set <email> <password>"
|
||
echo "dump-config"
|
||
echo "upgrade [region]"
|
||
echo
|
||
}
|
||
|
||
action=$1
|
||
shift
|
||
|
||
if [ -z "$action" ] ; then
|
||
usage
|
||
exit 0
|
||
fi
|
||
|
||
set -e
|
||
case "$action" in
|
||
auth-set)
|
||
auth_set "$@"
|
||
;;
|
||
dump-config)
|
||
dump_vars "$@"
|
||
;;
|
||
upgrade)
|
||
upgrade "$@"
|
||
;;
|
||
region-list)
|
||
region_list "$@"
|
||
;;
|
||
region-show)
|
||
region_show "$@"
|
||
;;
|
||
region-add)
|
||
region_add "$@"
|
||
;;
|
||
region-delete)
|
||
region_delete "$@"
|
||
;;
|
||
space-list)
|
||
space_list "$@"
|
||
;;
|
||
space-show)
|
||
space_show "$@"
|
||
;;
|
||
space-add)
|
||
space_add "$@"
|
||
;;
|
||
space-delete)
|
||
space_delete "$@"
|
||
;;
|
||
subnet-get)
|
||
subnet_get "$@"
|
||
;;
|
||
agg-list|aggregator-list)
|
||
aggregator_list "$@"
|
||
;;
|
||
agg-show|aggregator-show)
|
||
aggregator_show "$@"
|
||
;;
|
||
agg-add|aggregator-add)
|
||
aggregator_add "$@"
|
||
;;
|
||
agg-trunk-set|aggregator-trunk-set)
|
||
aggregator_trunk_set "$@"
|
||
;;
|
||
agg-delete|aggregator-delete)
|
||
aggregator_delete "$@"
|
||
;;
|
||
agg-set-space-ip|aggregator-set-space-ip)
|
||
aggregator_set_space_ip "$@"
|
||
;;
|
||
agg-remove-space-ip|aggregator-remove-space-ip)
|
||
aggregator_remove_space_ip "$@"
|
||
;;
|
||
agg-set-space-bird-config|aggregator-set-space-bird-config)
|
||
aggregator_set_space_bird_config "$@"
|
||
;;
|
||
agg-remove-space-bird-config|aggregator-remove-space-bird-config)
|
||
aggregator_remove_space_bird_config "$@"
|
||
;;
|
||
vxr-list)
|
||
vxr_list "$@"
|
||
;;
|
||
vxr-show)
|
||
vxr_show "$@"
|
||
;;
|
||
vxr-add)
|
||
vxr_add "$@"
|
||
;;
|
||
vxr-trunk-set)
|
||
vxr_trunk_set "$@"
|
||
;;
|
||
vxr-enable-global)
|
||
vxr_enable_global "$@"
|
||
;;
|
||
vxr-disable-global)
|
||
vxr_disable_global "$@"
|
||
;;
|
||
vxr-set-global-interface-option)
|
||
vxr_set_global_interface_option "$@"
|
||
;;
|
||
vxr-delete-global-interface-option)
|
||
vxr_delete_global_interface_option "$@"
|
||
;;
|
||
vxr-delete)
|
||
vxr_delete "$@"
|
||
;;
|
||
vlan-set)
|
||
vlan_set "$@"
|
||
;;
|
||
vlan-remove)
|
||
vlan_remove "$@"
|
||
;;
|
||
ipsec-enable)
|
||
ipsec_enable "$@"
|
||
;;
|
||
ipsec-disable)
|
||
ipsec_disable "$@"
|
||
;;
|
||
*)
|
||
usage
|
||
;;
|
||
esac
|