r1992 + switchvlans and slbconfig gateways now rely on the higher-level RackCode...
[racktables] / gateways / switchvlans / main
CommitLineData
533aefb8 1#!/bin/sh
47a3aa24
DO
2
3# This is a RackTables gateway for changing switch ports membership
4# across VLANs. It works accordingly to the gateway protocol described
5# in gateways.php and accepts the following commands on its stdin:
fc11a02c
DO
6#
7# * connect: connect to a switch, fetch all necessary data, store and
8# disconnect
9#
47a3aa24
DO
10# * listvlans: list all VLANs found on the switch, propably filtering
11# out those administratively prohibited. Only the VLANs from this
12# list will be allowed as new destination for 'set' command.
fc11a02c 13#
47a3aa24 14# * listports: list all ports on the switch and their current status.
fc11a02c
DO
15# Untagged (switchport mode access) ports will be shown with their
16# VLAN ID and tagged ports will be shown as 'trunk' regardless of
17# how many VLANs they are members of.
18#
19# * listmacs: output unsorted list of all dynamically learned MAC
20# addresses present on the switch
21#
47a3aa24 22
7865c525
DO
23endpoint=
24hw=
25sw=
26user=
35331abf 27handler=
7865c525 28CONNECTED=0
35331abf 29MYDIR=`dirname $0`
47a3aa24 30
35331abf 31# Not only connect, but gather all the data at once and remember the context.
533aefb8
DO
32do_connect()
33{
7865c525
DO
34 endpoint=`echo $args | cut -s -d' ' -f1`
35 hw=`echo $args | cut -s -d' ' -f2`
36 sw=`echo $args | cut -s -d' ' -f3`
37 user=`echo $args | cut -s -d' ' -f4`
35331abf 38 # sanity checks
533aefb8
DO
39 if [ -z "$endpoint" -o -z "$hw" -o -z "$sw" -o -z "$user" ]; then
40 echo 'ERR!too few arguments to connect'
41 return
42 fi
35331abf 43 case "$sw" in
987af914 44 Cisco+IOS+12.0|Cisco+IOS+12.1|Cisco+IOS+12.2)
35331abf
DO
45 handler=cisco
46 ;;
47 *)
48 echo "ERR!Don't know how to handle $sw on $endpoint"
49 return
50 ;;
51 esac
52
533aefb8
DO
53 # prepare temp files
54 PORTINFO=`mktemp /tmp/racktables.XXXX`
55 if ! [ -f "$PORTINFO" ]; then
56 echo 'ERR!could not create portinfo tmpfile'
57 return
58 fi
59 VLANINFO=`mktemp /tmp/racktables.XXXX`
60 if ! [ -f "$VLANINFO" ]; then
61 echo 'ERR!could not create vlaninfo tmpfile'
62 rm -f "$PORTINFO"
63 return
64 fi
fc11a02c
DO
65 MACINFO=`mktemp /tmp/racktables.XXXX`
66 if ! [ -f "$MACINFO" ]; then
67 echo 'ERR!could not create MACinfo tmpfile'
68 rm -f "$PORTINFO" "$VLANINFO"
69 return
70 fi
47a3aa24 71
533aefb8 72 # get the data
fc11a02c 73 "$MYDIR/$handler.connector" $endpoint $hw $sw fetch "$VLANINFO" "$PORTINFO" "$MACINFO"
35331abf
DO
74 ret=$?
75 if [ $ret = 0 ]; then
76 CONNECTED=1
77 echo "OK!connected to $endpoint";
78 else
79 echo "ERR!Cannot connect to $endpoint, connector returned code $ret"
80 fi
533aefb8
DO
81}
82
83do_listfile()
84{
85 local F=$1
86 if ! [ -f "$F" ]; then
87 echo "ERR!Lost temp file '$F' on the way"
88 return
89 fi
90 echo -n 'OK!'
d28ea105 91 local semicolon=''
533aefb8
DO
92 # tr might do the work, but use our chance to perform filtering once more
93 cat "$F" | while read line; do
94 [ "$line" = "" ] && continue
d28ea105
DO
95 echo -n "$semicolon$line"
96 semicolon=';'
533aefb8
DO
97 done
98 echo
99}
100
101do_set()
102{
7865c525
DO
103 # sanity checks
104 local setline=$1
105 if [ -z "$setline" ]; then
106 echo 'ERR!missing set argument'
107 return
108 fi
7865c525
DO
109 local REQUESTS=`mktemp /tmp/racktables.XXXX`
110 local REPLIES=`mktemp /tmp/racktables.XXXX`
111 echo $1 | tr ';' '\n' | while read setexpr; do
112 portname=`echo $setexpr | cut -s -d'=' -f1`
113 newvlan=`echo $setexpr | cut -s -d'=' -f2`
0dc931a4 114 curvlan=`egrep "^$portname=" $PORTINFO | cut -s -d'=' -f2 | cut -d',' -f2`
7865c525
DO
115 if [ -z "$curvlan" ]; then
116 echo "E!Could not find port $portname" >> "$REPLIES"
117 continue
118 fi
119 if [ "$curvlan" = "trunk" ]; then
120 echo "E!Port $portname is a trunk" >> "$REPLIES"
121 continue
122 fi
5b6704b5 123 [ "$curvlan" = "$newvlan" ] && continue
7865c525 124 echo "$portname $newvlan" >> "$REQUESTS"
7082c58d 125 cmembers=`grep -c ",$newvlan$" "$PORTINFO"`
38356044 126 if [ "$cmembers" = "0" -a $newvlan -lt 4096 ]; then
7082c58d
DO
127 echo "W!Port $portname seems to be the first in VLAN $newvlan at this switch." >> "$REPLIES"
128 echo "W!Check uplink/downlink configuration for proper operation." >> "$REPLIES"
129 fi
7865c525 130 done
7082c58d 131 nr=`egrep -c '^E!.' "$REPLIES"`
7865c525 132 if [ "$nr" -ge 1 ]; then
5b6704b5 133 echo "W!$nr change request(s) have been ignored" >> "$REPLIES"
7865c525 134 fi
533aefb8 135
7865c525 136 nq=`egrep -c '^.' "$REQUESTS"`
5b6704b5 137 if [ "$nq" -ge 1 ]; then
7865c525 138 # Go!
fc11a02c 139 "$MYDIR/$handler.connector" $endpoint $hw $sw push "$REQUESTS" "$REPLIES" "$MACINFO"
7865c525
DO
140 local ret=$?
141
142 if [ $ret != 0 ]; then
143 echo "ERR!Failed to configure $endpoint, connector returned code $ret"
144 return
145 fi
5b6704b5 146 echo "I!$nq change request(s) have been processed" >> "$REPLIES"
7865c525
DO
147 fi
148 echo -n 'OK!'
149 local SEMICOLON=
150 while read reply; do
151 echo -n $SEMICOLON$reply
152 SEMICOLON=';'
7c3cb03c 153 timestamp=`date '+%Y-%m-%d %H:%M:%S'`
0dc931a4 154 [ -w "$MYDIR/changes.log" ] && echo "$timestamp $user@$endpoint $reply" >> "$MYDIR/changes.log"
7865c525
DO
155 done < "$REPLIES"
156 echo
157 rm -f "$REQUESTS" "$REPLIES"
158}
533aefb8
DO
159
160# main loop
161while read cmd args; do
47a3aa24 162 case $cmd in
533aefb8
DO
163 connect)
164 if [ $CONNECTED = 1 ]; then
165 echo 'ERR!Already connected'
166 else
167 do_connect $args
168 fi
169 ;;
47a3aa24 170 listvlans)
533aefb8
DO
171 if [ $CONNECTED = 1 ]; then
172 do_listfile "$VLANINFO"
173 else
174 echo 'ERR!Not connected'
175 fi
47a3aa24
DO
176 ;;
177 listports)
533aefb8
DO
178 if [ $CONNECTED = 1 ]; then
179 do_listfile "$PORTINFO"
180 else
181 echo 'ERR!Not connected'
182 fi
47a3aa24 183 ;;
9e76e210
DO
184 listmacs)
185 if [ $CONNECTED = 1 ]; then
186 do_listfile "$MACINFO"
187 else
188 echo 'ERR!Not connected'
189 fi
190 ;;
47a3aa24 191 set)
533aefb8
DO
192 if [ $CONNECTED = 1 ]; then
193 do_set $args
194 else
195 echo 'ERR!Not connected'
196 fi
47a3aa24
DO
197 ;;
198 *)
343d4bec 199 echo "ERR!unknown command $cmd"
47a3aa24
DO
200 esac
201done
202
fc11a02c 203rm -f "$PORTINFO" "$VLANINFO" "$MACINFO"
47a3aa24 204exit 0