dahdi_span_types: compare
[dahdi/tools.git] / dahdi_span_types
1 #! /bin/sh
2 #
3 # /usr/sbin/dahdi_span_types
4 #
5 # This script can be used both from udev and
6 # from the command line to manage PRI spans
7 # type (E1/T1/J1).
8 #
9 # Span types can be set only *BEFORE* span are assigned.
10 #
11 # It uses a configuration file: $DAHDICONFDIR/span-types.conf
12 # (default DAHDICONFDIR=/etc/dahdi)
13 # (the format is documented inside that file)
14 #
15 # The first argument is an action:
16 #   "set"        - actually write the setting to the driver
17 #   "list"       - human-readable list of E1/T1/J1 types
18 #   "dumpconfig" - dump current assignments in a /etc/dahdi/span-types.conf
19 #                  compatible format
20 #
21 # Without further arguments, it operates on all existing spans
22 # With one or more sysfs dahdi_devices it is limited to those.
23 #
24 # We may use alternative "keys" for device matching:
25 # * Available keys:
26 #   - "hwid"       - Hardware id attribute from sysfs
27 #   - "@location"  - Location attribute from sysfs (embeded inside '<>')
28 #   - "/devpath"   - The sysfs absolute devpath
29 #
30 # * Wildcard are allowed in the configuration file:
31 #   - In the device specifiers (keys)
32 #   - In the span numbers
33 #   - Example for "match-all":    *   *:T1
34 #
35 # * During "set":
36 #   - If there are multiple matches, for a span, all are applied
37 #   - They are always applied in their order in the configuration file
38 #   - This means the last match wins
39 #   - Example:
40 #         *                   *:T1        # All span on all devices are T1
41 #         usb:X1234567        [34]:E1      # Except spans 3,4 on specific device
42 #
43 # * During "dumpconfig", for each device we take the first available key:
44 #   - The preference is: "hwid" or else "@location" or else "/devpath"
45 #   - This can be overriden via the SPAN_ASSIGNMENTS_KEY environment variable
46 #     or the '{-k|--key} key' command line option.
47 #
48 # Command line options:
49 #  - The '-h|--help' show a usage message.
50 #  - The '-v|--verbose' show debugging messages (on stderr)
51 #  - The '-n|--dry-run' During "set", only show what would be done
52 #  - The '-k <key>|--key <key>' overrides the SPAN_ASSIGNMENTS_KEY environment
53 #    variable.
54 #
55 # Examples:
56 #    dahdi_span_types list
57 #    dahdi_span_types set            # all devices
58 #    dahdi_span_types set /sys/bus/dahdi_devices/devices/astribanks:xbus-00
59 #    dahdi_span_types -k location dumpconfig
60 #
61
62
63 devbase='/sys/bus/dahdi_devices/devices'
64 DAHDICONFDIR="${DAHDICONFDIR:-/etc/dahdi}"
65 DAHDISPANTYPESCONF="${DAHDISPANTYPESCONF:-"${DAHDICONFDIR}/span-types.conf"}"
66 SPAN_ASSIGNMENTS_KEY=${SPAN_ASSIGNMENTS_KEY:-hwid}
67
68 usage() {
69         echo >&2 "Usage: $0 [options] action [devpath ...]"
70         echo >&2 "       action:"
71         echo >&2 "         set        - set spans to E1/T1 according to /etc/dahdi/span-types.conf"
72         echo >&2 "         compare    - show config values that differ from system"
73         echo >&2 "         list       - human-readable list of all spans"
74         echo >&2 "         dumpconfig - dump current state in /etc/dahdi/span-types.conf format"
75         echo >&2 ""
76         echo >&2 "       options:"
77         echo >&2 "         -h|--help      - Show this help"
78         echo >&2 "         -v|--verbose'  - Show debugging messages (on stderr)"
79         echo >&2 "         -n|--dry-run'  - During 'set', only show what would be done"
80         echo >&2 "         -k|--key <k>   - Override prefered key during dumpconfig action"
81         echo >&2 "         --line-mode <m> - Set default line mode to <m> (E1/T1/J1)"
82         exit 1
83 }
84
85 # Parse command line options
86 TEMP=`getopt -o hnvk: --long help,dry-run,verbose,key:,line-mode: -n "$0" -- "$@"`
87 if [ $? != 0 ]; then
88         echo >&2 "Bad options"
89         usage
90 fi
91
92 compare=false
93
94 # Note the quotes around `$TEMP': they are essential!
95 eval set -- "$TEMP"
96
97 while true ; do
98         case "$1" in
99         -h|--help)
100                 usage
101                 ;;
102         -n|--dry-run)
103                 shift
104                 dry_run=true
105                 ;;
106         -v|--verbose)
107                 shift
108                 verbose=true
109                 ;;
110         -k|--key)
111                 SPAN_ASSIGNMENTS_KEY="$2"
112                 shift
113                 shift
114                 ;;
115         --line-mode)
116                 DEFAULT_LINE_MODE="$2"
117                 shift
118                 shift
119                 ;;
120         --)
121                 shift
122                 break
123                 ;;
124         *)
125                 echo "Internal error!"
126                 exit 1
127                 ;;
128         esac
129 done
130
131 if [ "$#" -eq 0 ]; then
132         echo >&2 "Missing action argument"
133         usage
134 fi
135 action="$1"
136 shift
137
138 # Validate SPAN_ASSIGNMENTS_KEY
139 case "$SPAN_ASSIGNMENTS_KEY" in
140 hwid|location|devpath)
141         ;;
142 *)
143         echo >&2 "Bad --key='$SPAN_ASSIGNMENTS_KEY' (should be: hwid|location|devpath)"
144         usage
145         ;;
146 esac
147
148 # Validate DEFAULT_LINE_MODE
149 case "$DEFAULT_LINE_MODE" in
150 E1|T1|J1|'')
151         ;;
152 *)
153         echo >&2 "Bad --line-mode='$DEFAULT_LINE_MODE' (should be: E1|T1|J1)"
154         usage
155         ;;
156 esac
157
158 if [ ! -d "$devbase" ]; then
159         echo >&2 "$0: Missing '$devbase' (DAHDI driver unloaded?)"
160         exit 1
161 fi
162
163 # Use given devices or otherwise, all existing devices
164 if [ "$#" -gt 0 ]; then
165         DEVICES="$@"
166 else
167         DEVICES=`ls -d $devbase/* 2>/dev/null`
168 fi
169
170 # Beware of special characters in attributes
171 attr_clean() {
172         cat "$1" 2>/dev/null | tr -d '\n' | tr '!' '/' | tr -c 'a-zA-Z0-9/:.-' '_'
173 }
174
175 show_spantypes() {
176         echo "# PRI span types (E1/T1/J1)"
177         for device in $DEVICES
178         do
179                 devpath=`cd "$device" && pwd -P`
180                 location='@'`attr_clean "$device/location"`
181                 hardware_id=`attr_clean "$device/hardware_id"`
182                 cat "$device/spantype" | while read st; do
183                         case "$st" in
184                         *:[ETJ]1)
185                                 printf "%-10s %-20s %-30s %s\n" \
186                                         "$st" "[$hardware_id]" "$location" \
187                                         "$devpath"
188                                 ;;
189                         esac
190                 done
191         done
192 }
193
194 list_pri_spantypes() {
195         find $DEVICES -follow -maxdepth 1 -name spantype | \
196                 xargs cat | \
197                 sed -n '/:[ETJ]1$/s/^.*://p' | \
198                 sort -u | \
199                 tr '\n' ' ' | \
200                 sed -e 's/^ *//' -e 's/ *$//'
201 }
202
203 dump_config() {
204         pri_spantypes=`list_pri_spantypes`
205         num_spantypes=`echo "$pri_spantypes" | wc -w`
206         gen_default=''
207         echo '#'
208         echo "# Autogenerated by $0 on `date`"
209         echo "# Map PRI DAHDI devices to span types for E1/T1/J1"
210         echo "#"
211
212         echo "# Summary:"
213         if [ "$DEFAULT_LINE_MODE" != '' ]; then
214                 gen_default="$DEFAULT_LINE_MODE"
215                 echo "#  * Generating wildcard match of $gen_default."
216                 echo "#    - Was run with '--line-mode=$DEFAULT_LINE_MODE'"
217         elif [ "$num_spantypes" -eq 1 ]; then
218                 gen_default="$pri_spantypes"
219                 echo "#  * Generating wildcard match of $gen_default."
220                 echo "#    - Spans were $pri_spantypes"
221         else
222                 echo "#  * Not generating wildcard match."
223                 echo "#    - Was run without '--line-mode' option and span were of mixed types [$pri_spantypes]"
224         fi
225         echo "#"
226         if [ "$num_spantypes" -eq 1 ]; then
227                 echo "#  * Generating a list of commented out configurations for spans."
228                 echo "#    - Spans were $pri_spantypes"
229                 echo "#    - Uncomment for specific overrides"
230         else
231                 echo "#  * Generating a list of specific span configurations."
232                 echo "#    - Spans were of mixed types: $pri_spantypes"
233         fi
234         echo "#"
235         echo ''
236
237         fmt="%-65s %s"
238         printf "$fmt\n" '# @location/hardware_id' 'span_type'
239
240         if [ "$gen_default" != '' ]; then
241                 printf "$fmt\t\t# Wildcard line-mode" "*" "*:$gen_default"
242                 echo ""
243         fi
244         echo ""
245         for device in $DEVICES
246         do
247                 devpath=`cd "$device" && pwd -P`
248                 location=`attr_clean "$device/location"`
249                 hardware_id=`attr_clean "$device/hardware_id"`
250                 if [ "$SPAN_ASSIGNMENTS_KEY" = 'hwid' -a "$hardware_id" != '' ]; then
251                         id="$hardware_id"
252                 elif [ "$SPAN_ASSIGNMENTS_KEY" = 'location' -a "$location" != '' ]; then
253                         id="@$location"
254                 else
255                         id="$devpath"
256                 fi
257                 echo "# Device: [$hardware_id] @$location $devpath"
258                 cat "$device/spantype" | while read st; do
259                         case "$st" in
260                         *:[ETJ]1)
261                                 if [ "$num_spantypes" -eq 1 ]; then
262                                         printf "#$fmt\n" "$id" "$st"
263                                 else
264                                         printf "$fmt\n" "$id" "$st"
265                                 fi
266                                 ;;
267                         *)
268                                 #echo "#    Skipped local span `echo $st | sed 's/:/ -- /'`"
269                                 ;;
270                         esac
271                 done | sort -n
272                 echo ''
273         done
274 }
275
276 # Allow comments and empty lines in config file
277 filter_conf() {
278         sed -e 's/#.*//' -e '/^[ \t]*$/d' "$DAHDISPANTYPESCONF"
279 }
280
281 handle_span() {
282         device="$1"
283         spantype="$2"
284         attr_file="$device/spantype"
285         devpath=`cd "$device" && pwd -P`
286         devname=`echo "$device" | sed "s,$devbase/,,"`
287         location='@'`attr_clean "$device/location"`
288         hardware_id=`attr_clean "$device/hardware_id"`
289         spanno=`echo "$spantype" | cut -d: -f1`
290         #echo >&2 "DEBUG: $device $spanno ($spantype)"
291         filter_conf | while read id span_spec; do
292                         sn=`echo "$span_spec" | cut -d: -f1`
293                         val=`echo "$span_spec" | cut -d: -f2`
294                         case "$spanno" in
295                         $sn)
296                                 ;;
297                         *)
298                                 #echo >&2 "no-match($device $spanno): $sn"
299                                 continue
300                                 ;;
301                         esac
302                         found=no
303                         # GLOBBING
304                         case "$location" in
305                         $id)
306                                 #echo >&2 "match($id): $span_spec"
307                                 found=yes
308                                 ;;
309                         esac
310                         case "$hardware_id" in
311                         $id)
312                                 #echo >&2 "match([$id]): $span_spec"
313                                 found=yes
314                                 ;;
315                         esac
316                         case "$devpath" in
317                         $id)
318                                 #echo >&2 "match([$id]): $span_spec"
319                                 found=yes
320                                 ;;
321                         esac
322                         if [ "$found" = 'yes' ]; then
323                                 if [ "$dry_run" = 'true' -o "$verbose" = 'true' ]; then
324                                         echo >&2 "Set $devname span $spanno = $val"
325                                 fi
326                                 if [ "$dry_run" != 'true' ]; then
327                                         if [ "$compare" = 'true' ]; then
328                                                 config="$spanno:$val"
329                                                 system=`grep "$spanno:" "$attr_file"`
330                                                 if [ "$config" != "$system" ]; then
331
332                                                         active_val=`echo $system | cut -d: -f2`
333                                                         echo "$devname $spanno     $val     $active_val" >>"$compare_results_file"
334                                                 fi
335                                         else
336                                                 echo "$spanno:$val" > "$attr_file"
337                                         fi
338                                 fi
339                         fi
340                 done
341 }
342
343 set_all_devices() {
344         span_differs='false'
345         SPANS_DIFFER='false'
346
347         if [ ! -f "$DAHDISPANTYPESCONF" ]; then
348                 echo >&2 "$0: Missing configuration '$DAHDISPANTYPESCONF'"
349                 exit 1
350         fi
351         for device in $DEVICES
352         do
353                 devname=`echo "$device" | sed "s,$devbase/,,"`
354                 cat "$device/spantype" | while read spantype; do
355                         case "$spantype" in
356                         *:[ETJ]1)
357                                 handle_span "$device" "$spantype"
358                                 ;;
359                         *)
360                                 if [ "$dry_run" = 'true' -o "$verbose" = 'true' ]; then
361                                         echo >&2 "Skipping non-E1/T1/J1 span ($devname -- $spantype)"
362                                 fi
363                                 ;;
364                         esac
365                 done
366         done
367         if [ "$compare" = 'true' ]; then
368                 if [ -s "$compare_results_file" ]; then
369                         echo "# Device           Unit  Config Active"
370                         cat "$compare_results_file"
371                         rm -f "$compare_results_file"
372                         exit 5
373                 fi
374                 rm -f "$compare_results_file"
375                 exit 0
376         fi
377 }
378
379 case "$action" in
380 list)
381         show_spantypes
382         ;;
383 dumpconfig)
384         dump_config
385         ;;
386 set)
387         set_all_devices
388         ;;
389 compare)
390         compare=true
391         compare_results_file=`mktemp`
392         set_all_devices
393         ;;
394 *)
395         usage
396         ;;
397 esac