yap/yap
2018-12-04 13:50:02 -08:00

1108 lines
24 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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"
}
# 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 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"
echo " ips:"
local ip_key
for ip_key in $(list_vars $space/ips) ; do
echo " - '$(get_var $ip_key)'"
done
echo " routes:"
local route_key route
for route_key in $(list_vars $space/routes) ; do
route=$(basename $route_key)
route=${route/_//}
echo " '$route': '$(get_var $route_key)'"
done
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 name=$(basename $vxr)
local vxr_peers
{
echo -e "yap:"
echo -e " yap_id: $yap_id"
echo -e " trunk: $trunk"
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
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" "$@"
}
#
# 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="/regions/$region/spaces/$space/vlan"
if has_var "$var" ; then
echo " $(basename space) $(get_var $var)"
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
id=$(api_get /api/v3/spaces/$space/ | jq .id)
set_var "/spaces/$space/id" "$id"
space_show $space
}
function space_delete() {
args=$(check_args space,,$1) || return 1
eval $args
del_section "/spaces/$space"
for section in $(list_sections /regions/spaces/) ; do
if [ "$(basename $section)" = "$space" ] ; then
del_section "$section"
fi
done
salt_update
}
#
# 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_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)"
}
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 ||:
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_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_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
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
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)
}
#
# IP commands
#
function ip_add() {
args=$(check_args space,,$1 region,,$2 ip,,$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 ! validate_ip $ip ; then
echo "IP is not valid"
return 1
fi
ip_key=${ip/\//_}
set_var "/regions/$region/spaces/$space/ips/$ip_key" "$ip"
salt_update $(get_region_nodelist $region) ||:
salt_exec "$(get_region_nodelist $region)" cmd.run "yap restart $space"
}
function ip_remove() {
args=$(check_args space,,$1 region,,$2 ip,,$3) || return 1
eval $args
ip_key=${ip/\//_}
del_var "/regions/$region/spaces/$space/ips/$ip_key"
salt_update $(get_region_nodelist $region) ||:
salt_exec "$(get_region_nodelist $region)" cmd.run "yap restart $space"
}
#
# Route commands
#
function route_add() {
args=$(check_args space,,$1 region,,$2 route,,$3 gateway,,$4) || 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 ! validate_ip $route ; then
echo "Route is not valid"
return 1
fi
route_key=${route/\//_}
set_var "/regions/$region/spaces/$space/routes/$route_key" "$gateway"
salt_update $(get_region_nodelist $region) ||:
salt_exec "$(get_region_nodelist $region)" cmd.run "yap restart $space"
}
function route_remove() {
args=$(check_args space,,$1 region,,$2 route,,$3) || return 1
eval $args
route_key=${route/\//_}
del_var "/regions/$region/spaces/$space/routes/$route_key"
salt_update $(get_region_nodelist $region) ||:
salt_exec "$(get_region_nodelist $region)" cmd.run "yap restart $space"
}
#
# 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 "agg-list"
echo "agg-show <id>"
echo "agg-add <id> <region> <trunk>"
echo "agg-trunk-set <id> <trunk>"
echo "agg-delete <id>"
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-delete <name>"
echo
echo "vlan-set <spacekey> <region> <vlan_id>"
echo "vlan-remove <spacekey> <region>"
echo
echo "ip-add <spacekey> <region> <ip>"
echo "ip-remove <spacekey> <region> <ip>"
echo
echo "route-add <spacekey> <region> <route> <gateway>"
echo "route-remove <spacekey> <region> <route>"
echo
echo "ipsec-enable"
echo "ipsec-disable"
echo "auth-set <email> <password>"
echo "dump-config"
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 "$@"
;;
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 "$@"
;;
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 "$@"
;;
vxr-list)
vxr_list "$@"
;;
vxr-show)
vxr_show "$@"
;;
vxr-add)
vxr_add "$@"
;;
set|vxr-trunk-set)
vxr_trunk_set "$@"
;;
vxr-delete)
vxr_delete "$@"
;;
vlan-set)
vlan_set "$@"
;;
vlan-remove)
vlan_remove "$@"
;;
ip-add)
ip_add "$@"
;;
ip-remove)
ip_remove "$@"
;;
route-add)
route_add "$@"
;;
route-remove)
route_remove "$@"
;;
ipsec-enable)
ipsec_enable "$@"
;;
ipsec-disable)
ipsec_disable "$@"
;;
*)
usage
;;
esac