dahdi.init: Don't exit on lack of /etc/dahdi/system.conf
[dahdi/tools.git] / dahdi_span_assignments
1 #! /bin/sh
2 #
3 # /usr/sbin/dahdi_span_assignments:
4 #
5 # this script can be used both from udev and
6 # from the command line to assign/unassign and list
7 # current span assignments.
8 #
9 # It uses a configuration file: $DAHDICONFDIR/assigned-spans.conf
10 # (default DAHDICONFDIR=/etc/dahdi)
11 #
12 # The first argument is an action:
13 #   "auto"       - trigger driver auto_assign attribute for given devices
14 #                  (no configuration file is used)
15 #   "add"        - assign (spans which are not already assigned), according
16 #                  to /etc/dahdi/assigned-spans.conf configuration file
17 #   "remove"     - unassign spans which are not already unassigned
18 #   "list"       - human-readable list of all spans (with/without assignments)
19 #   "dumpconfig" - dump current assignments in a /etc/dahdi/assigned-spans.conf
20 #                  compatible format
21 #
22 # Without further arguments, it operates on all existing spans
23 # With one or more sysfs dahdi_devices it is limited to those.
24 #
25 # We may use alternative "keys" for device matching:
26 # * Available keys:
27 #   - "hwid"       - Hardware id attribute from sysfs
28 #   - "@location"  - Location attribute from sysfs (embeded inside '<>')
29 #   - "/devpath"   - The sysfs absolute devpath
30 #
31 # * During "dumpconfig", for each device we take the first available key:
32 #   - The preference is: "hwid" or else "@location" or else "/devpath"
33 #   - This can be overriden via the SPAN_ASSIGNMENTS_KEY environment variable
34 #     or the '{-k|--key} key' command line option.
35 #
36 # * During "add":
37 #   - Any key match is valid (hwid/location/devpath)
38 #   - Shell globs (wildcards: '*', '?', '[...]') may be optionally used.
39 #
40 # Command line options:
41 #  - The '-h|--help' show a usage message.
42 #  - The '-n|--dry-run' affects the "add" and "remove" operations.
43 #  - The '-v|--verbose' currently shows device matches during "add" operation.
44 #  - The '-k <key>|--key <key>' overrides the SPAN_ASSIGNMENTS_KEY environment
45 #    variable.
46 #
47 # Examples:
48 #    dahdi_span_assignments list
49 #    dahdi_span_assignments add # all unassigned devices
50 #    dahdi_span_assignments add       /sys/bus/dahdi_devices/devices/astribanks:xbus-00
51 #    dahdi_span_assignments remove      # all assigned devices
52 #    dahdi_span_assignments -k location dumpconfig
53 #
54
55 devbase='/sys/bus/dahdi_devices/devices'
56 DAHDICONFDIR="${DAHDICONFDIR:-/etc/dahdi}"
57 DAHDISASSIGNEDSPANSCONF="${DAHDIASSIGNEDSPANSCONF:-"${DAHDICONFDIR}/assigned-spans.conf"}"
58 SPAN_ASSIGNMENTS_KEY=${SPAN_ASSIGNMENTS_KEY:-hwid}
59 dry_run=
60 verbose=
61
62 usage() {
63         echo >&2 "Usage: $0 [options] action [devpath ...]"
64         echo >&2 "       action:"
65         echo >&2 "         auto       - trigger driver auto_assign attribute for given devices"
66         echo >&2 "         add        - assign spans, according to /etc/dahdi/assigned-spans.conf"
67         echo >&2 "         remove     - unassign spans"
68         echo >&2 "         list       - human-readable list of all spans"
69         echo >&2 "         dumpconfig - dump current state as new configuration"
70         echo >&2 ""
71         echo >&2 "       options:"
72         echo >&2 "         -h|--help      - Show this help"
73         echo >&2 "         -n|--dry-run   - For 'add/remove' actions"
74         echo >&2 "         -v|--versbose  - Show matches during 'add' action"
75         echo >&2 "         -k|--key <k>   - Override prefered key during dumpconfig action"
76         exit 1
77 }
78
79 # Parse command line options
80 TEMP=`getopt -o hnvk: --long help,dry-run,verbose,key: -n "$0" -- "$@"`
81 if [ $? != 0 ]; then
82         echo >&2 "Bad options"
83         usage
84 fi
85
86 # Note the quotes around `$TEMP': they are essential!
87 eval set -- "$TEMP"
88
89 while true ; do
90         case "$1" in
91         -h|--help)
92                 usage
93                 ;;
94         -n|--dry-run)
95                 dry_run='true'
96                 shift
97                 ;;
98         -v|--verbose)
99                 verbose='true'
100                 shift
101                 ;;
102         -k|--key)
103                 SPAN_ASSIGNMENTS_KEY="$2"
104                 shift
105                 shift
106                 ;;
107         --)
108                 shift
109                 break
110                 ;;
111         *)
112                 echo "Internal error!"
113                 exit 1
114                 ;;
115         esac
116 done
117
118 if [ "$#" -eq 0 ]; then
119         echo >&2 "Missing action argument"
120         usage
121 fi
122 action="$1"
123 shift
124
125 # Validate SPAN_ASSIGNMENTS_KEY
126 case "$SPAN_ASSIGNMENTS_KEY" in
127 hwid|location|devpath)
128         ;;
129 *)
130         echo >&2 "Bad SPAN_ASSIGNMENTS_KEY='$SPAN_ASSIGNMENTS_KEY' (should be: hwid|location|devpath)"
131         usage
132         ;;
133 esac
134
135 if [ ! -d "$devbase" ]; then
136         echo >&2 "$0: Missing '$devbase' (DAHDI driver unloaded?)"
137         exit 1
138 fi
139
140 # Use given devices or otherwise, all existing devices
141 if [ "$#" -gt 0 ]; then
142         DEVICES="$@"
143 else
144         DEVICES=`ls -d $devbase/* 2>/dev/null`
145 fi
146
147 # Beware of special characters in attributes
148 attr_clean() {
149         cat "$1" 2>/dev/null | tr -d '\n' | tr '!' '/' | tr -c 'a-zA-Z0-9/:.-' '_'
150 }
151
152 show_devices() {
153
154         for device in $DEVICES
155         do
156                 devpath=`cd "$device" && pwd -P`
157                 location='@'`attr_clean "$device/location"`
158                 hardware_id=`attr_clean "$device/hardware_id"`
159                 for local_spanno in `cut -d: -f1 "$device/spantype"`
160                 do
161                         span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \
162                                 sed -e 's,/local_spanno:.*,,' -e 's,.*/,,'`
163                         if [ "$span" != '' ]; then
164                                 spanno=`echo $span | sed 's/^.*-//'`
165                                 name=`cat 2>/dev/null "$device/$span/name"`
166                                 basechan=`cat 2>/dev/null "$device/$span/basechan"`
167                         else
168                                 spanno='-'
169                                 basechan='-'
170                         fi
171                         printf "%-8s %-14s %s %s\n" "$local_spanno:$spanno:$basechan" "[$hardware_id]" "$location" "$devpath"
172                 done | sort -n
173         done
174 }
175
176 dump_config() {
177         echo '#'
178         echo "# Autogenerated by $0 on `date`"
179         echo "# Map devices + local spans to span + base channel number"
180         echo ''
181         for device in $DEVICES
182         do
183                 devpath=`cd "$device" && pwd -P`
184                 location=`attr_clean "$device/location"`
185                 hardware_id=`attr_clean "$device/hardware_id"`
186                 if [ "$SPAN_ASSIGNMENTS_KEY" = 'hwid' -a "$hardware_id" != '' ]; then
187                         id="$hardware_id"
188                 elif [ "$SPAN_ASSIGNMENTS_KEY" = 'location' -a "$location" != '' ]; then
189                         id="@$location"
190                 else
191                         id="$devpath"
192                 fi
193                 echo "# Device: [$hardware_id] @$location $devpath"
194                 for local_spanno in `cut -d: -f1 "$device/spantype"`
195                 do
196                         span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \
197                                 sed -e 's,/local_spanno:.*,,' -e 's,.*/,,'`
198                         if [ "$span" != '' ]; then
199                                 spanno=`echo $span | sed 's/^.*-//'`
200                                 name=`cat 2>/dev/null "$device/$span/name"`
201                                 basechan=`cat 2>/dev/null "$device/$span/basechan"`
202                                 printf "%-30s %s\n" "$id" "$local_spanno:$spanno:$basechan"
203                         else
204                                 echo "#   Skipped unassigned local span $local_spanno"
205                         fi
206                 done | sort
207                 echo ''
208         done
209 }
210
211 unassign_all_spans() {
212         for device in $DEVICES
213         do
214                 find "$device" -follow -maxdepth 1 -name 'span-*' -type d | \
215                         sort | while read spandir; do
216                         local_spanno=`cat "$spandir/local_spanno"`
217                         if [ "$dry_run" = true ]; then
218                                 echo "(dry-run) unassign $device $local_spanno"
219                                 continue
220                         fi
221                         echo "unassign $device $local_spanno"
222                         if ! echo "$local_spanno" > "$device/unassign_span"; then
223                                 echo >&2 "$0: failed unassigning '$local_spanno' in '$device'"
224                         fi
225                 done
226         done
227 }
228
229 # Allow comments and empty lines in config file
230 filter_conf() {
231         sed -e 's/#.*//' -e '/^[ \t]*$/d' "$DAHDISASSIGNEDSPANSCONF"
232 }
233
234 assign_device_spans() {
235         device="$1"
236         for s in $spanspecs
237         do
238                 local_spanno=`echo "$s" | cut -d: -f1`
239                 spanno=`echo "$s" | cut -d: -f2`
240                 span="$device/span-$spanno"
241                 if [ "$dry_run" = true ]; then
242                         echo "(dry-run) assign $device: $s"
243                         continue
244                 fi
245                 if [ -d "$span" ]; then
246                         span_local_spanno=`cat "$span/local_spanno"`
247                         if [ "$span_local_spanno" != "$local_spanno" ]; then
248                                 echo "WARNING: $span_local_spanno != $local_spanno"
249                         fi
250                         echo "$device [$local_spanno] already assigned to span $spanno. Skipping..."
251                         continue
252                 fi
253                 echo "assign $device: $s"
254                 if ! echo "$s" > "$device/assign_span"; then
255                         echo >&2 "$0: failed assigning '$s' to '$device'"
256                 fi
257         done
258 }
259
260 match_device() {
261         device="$1"
262         devpath=`cd "$device" && pwd -P`
263         location='@'`attr_clean "$device/location"`
264         hardware_id=`attr_clean "$device/hardware_id"`
265         filter_conf | while read id spanspecs
266         do
267                 # We use case to enable shell-style globbing in configuration
268                 case "$hardware_id" in
269                 $id)
270                         [ "$verbose" = true ] && echo "match by hwid ($id ~ $hardware_id): $spanspecs"
271                         assign_device_spans "$device"
272                         ;;
273                 esac
274                 # We use case to enable shell-style globbing in configuration
275                 case "$location" in
276                 $id)
277                         [ "$verbose" = true ] && echo "match by location ($id ~ $location): $spanspecs"
278                         assign_device_spans "$device"
279                         ;;
280                 esac
281                 # We use case to enable shell-style globbing in configuration
282                 case "$devpath" in
283                 $id)
284                         [ "$verbose" = true ] && echo "match by devpath ($id ~ $devpath): $spanspecs"
285                         assign_device_spans "$device"
286                         ;;
287                 esac
288         done
289 }
290
291 assign_devices() {
292         if [ ! -f "$DAHDISASSIGNEDSPANSCONF" ]; then
293                 echo >&2 "$0: Missing '$DAHDISASSIGNEDSPANSCONF'"
294                 exit 1
295         fi
296         echo "using '$DAHDISASSIGNEDSPANSCONF'"
297         for device in $DEVICES
298         do
299                 match_device "$device"
300         done
301 }
302
303 auto_assign_devices() {
304         for device in $DEVICES
305         do
306                 echo "auto-assign $device"
307                 if [ "$dry_run" != true ]; then
308                         echo 1 > "$device/auto_assign"
309                 fi
310         done
311 }
312
313 case "$action" in
314 auto)
315         auto_assign_devices
316         ;;
317 add)
318         assign_devices
319         ;;
320 remove)
321         unassign_all_spans
322         ;;
323 list)
324         show_devices
325         ;;
326 dumpconfig)
327         dump_config
328         ;;
329 *)
330         echo >&2 "Bad action='$action'"
331         usage
332         ;;
333 esac