diff --git a/span_assignments b/span_assignments index 8f29d39..96e49cd 100755 --- a/span_assignments +++ b/span_assignments @@ -22,28 +22,116 @@ # Without further arguments, it operates on all existing spans # With one or more sysfs dahdi_devices it is limited to those. # +# We may use alternative "keys" for device matching: +# * Available keys: +# - "hwid" - Hardware id attribute from sysfs +# - "@location" - Location attribute from sysfs (embeded inside '<>') +# - "/devpath" - The sysfs absolute devpath +# +# * During "dumpconfig", for each device we take the first available key: +# - The preference is: "hwid" or else "@location" or else "/devpath" +# - This can be overriden via the SPAN_ASSIGNMENTS_KEY environment variable +# or the '{-k|--key} key' command line option. +# +# * During "add": +# - Any key match is valid (hwid/location/devpath) +# - Shell globs (wildcards: '*', '?', '[...]') may be optionally used. +# +# Command line options: +# - The '-h|--help' show a usage message. +# - The '-n|--dry-run' affects the "add" and "remove" operations. +# - The '-v|--verbose' currently shows device matches during "add" operation. +# - The '-k |--key ' overrides the SPAN_ASSIGNMENTS_KEY environment +# variable. +# # Examples: # span_assignments list -# span_assignments add # all -# span_assignments add /sys/bus/dahdi_devices/devices/astribanks:xbus-00 -# span_assignments remove # all +# span_assignments add # all unassigned devices +# span_assignments add /sys/bus/dahdi_devices/devices/astribanks:xbus-00 +# span_assignments remove # all assigned devices +# span_assignments -k location dumpconfig # devbase='/sys/bus/dahdi_devices/devices' DAHDICONFDIR="${DAHDICONFDIR:-/etc/dahdi}" pinned_spans_conf="$DAHDICONFDIR/pinned-spans.conf" +SPAN_ASSIGNMENTS_KEY=${SPAN_ASSIGNMENTS_KEY:-hwid} +dry_run= +verbose= usage() { - echo >&2 "Usage: $0 {auto|add|remove|list|dumpconfig} [devpath ...]" + echo >&2 "Usage: $0 [options] action [devpath ...]" + echo >&2 " action:" + echo >&2 " auto - trigger driver auto_assign attribute for given devices" + echo >&2 " add - assign spans, according to /etc/dahdi/pinned-spans.conf" + echo >&2 " remove - unassign spans" + echo >&2 " list - human-readable list of all spans" + echo >&2 " dumpconfig - dump current state as new configuration" + echo >&2 "" + echo >&2 " options:" + echo >&2 " -h|--help - Show this help" + echo >&2 " -n|--dry-run - For 'add/remove' actions" + echo >&2 " -v|--versbose - Show matches during 'add' action" + echo >&2 " -k|--key - Override prefered key during dumpconfig action" exit 1 } +# Parse command line options +TEMP=`getopt -o hnvk: --long help,dry-run,verbose,key: -n "$0" -- "$@"` +if [ $? != 0 ]; then + echo >&2 "Bad options" + usage +fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$TEMP" + +while true ; do + case "$1" in + -h|--help) + usage + ;; + -n|--dry-run) + dry_run='true' + shift + ;; + -v|--verbose) + verbose='true' + shift + ;; + -k|--key) + SPAN_ASSIGNMENTS_KEY="$2" + shift + shift + ;; + --) + shift + break + ;; + *) + echo "Internal error!" + exit 1 + ;; + esac +done + if [ "$#" -eq 0 ]; then + echo >&2 "Missing action argument" usage fi action="$1" shift +# Validate SPAN_ASSIGNMENTS_KEY +case "$SPAN_ASSIGNMENTS_KEY" in +hwid|location|devpath) + ;; +*) + echo >&2 "Bad SPAN_ASSIGNMENTS_KEY='$SPAN_ASSIGNMENTS_KEY' (should be: hwid|location|devpath)" + usage + ;; +esac + if [ ! -d "$devbase" ]; then echo >&2 "$0: Missing '$devbase' (DAHDI driver unloaded?)" exit 1 @@ -56,12 +144,18 @@ else DEVICES=`echo $devbase/*` fi +# Beware of special characters in attributes +attr_clean() { + cat "$1" 2>/dev/null | tr -d '\n' | tr '!' '/' | tr -c 'a-zA-Z0-9/:.-' '_' +} + show_devices() { for device in $DEVICES do - hw_id=`cat "$device/hardware_id"` - location=`cd "$device" && pwd -P | sed 's,/sys/devices/,,'` + devpath=`cd "$device" && pwd -P` + location='@'`attr_clean "$device/location"` + hardware_id=`attr_clean "$device/hardware_id"` for local_spanno in `cut -d: -f1 "$device/spantype"` do span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \ @@ -74,7 +168,7 @@ show_devices() { spanno='-' basechan='-' fi - printf "%-8s %-14s %s\n" "$local_spanno:$spanno:$basechan" "[$hw_id]" "@$location" + printf "%-8s %-14s %s %s\n" "$local_spanno:$spanno:$basechan" "[$hardware_id]" "$location" "$devpath" done | sort -n done } @@ -86,14 +180,17 @@ dump_config() { echo '' for device in $DEVICES do - hw_id=`cat "$device/hardware_id"` - location='@'`cd "$device" && pwd -P | sed 's,/sys/devices/,,'` - if [ "$hw_id" != '' ]; then - id="$hw_id" + devpath=`cd "$device" && pwd -P` + location=`attr_clean "$device/location"` + hardware_id=`attr_clean "$device/hardware_id"` + if [ "$SPAN_ASSIGNMENTS_KEY" = 'hwid' -a "$hardware_id" != '' ]; then + id="$hardware_id" + elif [ "$SPAN_ASSIGNMENTS_KEY" = 'location' -a "$location" != '' ]; then + id="@$location" else - id="$location" + id="$devpath" fi - echo "# Device: [$hw_id] $location" + echo "# Device: [$hardware_id] @$location $devpath" for local_spanno in `cut -d: -f1 "$device/spantype"` do span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \ @@ -117,6 +214,10 @@ unassign_all_spans() { find "$device" -follow -maxdepth 1 -name 'span-*' -type d | \ sort | while read spandir; do local_spanno=`cat "$spandir/local_spanno"` + if [ "$dry_run" = true ]; then + echo "(dry-run) unassign $device $local_spanno" + continue + fi echo "unassign $device $local_spanno" if ! echo "$local_spanno" > "$device/unassign_span"; then echo >&2 "$0: failed unassigning '$local_spanno' in '$device'" @@ -130,11 +231,6 @@ filter_conf() { sed -e 's/#.*//' -e '/^[ \t]*$/d' "$pinned_spans_conf" } -# Beware of special characters in attributes -attr_clean() { - cat "$1" | tr -d '\n' | tr '!' '/' | tr -c 'a-zA-Z0-9/:.-' '_' -} - assign_device_spans() { device="$1" for s in $spanspecs @@ -142,12 +238,16 @@ assign_device_spans() { local_spanno=`echo "$s" | cut -d: -f1` spanno=`echo "$s" | cut -d: -f2` span="$device/span-$spanno" + if [ "$dry_run" = true ]; then + echo "(dry-run) assign $device: $s" + continue + fi if [ -d "$span" ]; then span_local_spanno=`cat "$span/local_spanno"` if [ "$span_local_spanno" != "$local_spanno" ]; then echo "WARNING: $span_local_spanno != $local_spanno" fi - echo "$device [$local_spanno] already assigned to $spanno. Skipping..." + echo "$device [$local_spanno] already assigned to span $spanno. Skipping..." continue fi echo "assign $device: $s" @@ -159,21 +259,29 @@ assign_device_spans() { match_device() { device="$1" - location='@'`cd "$device" && pwd -P | sed 's,/sys/devices/,,'` + devpath=`cd "$device" && pwd -P` + location='@'`attr_clean "$device/location"` hardware_id=`attr_clean "$device/hardware_id"` filter_conf | while read id spanspecs do # We use case to enable shell-style globbing in configuration - case "$location" in + case "$hardware_id" in $id) - #echo "match location($id ~ $location): $spanspecs" + [ "$verbose" = true ] && echo "match by hwid ($id ~ $hardware_id): $spanspecs" assign_device_spans "$device" ;; esac # We use case to enable shell-style globbing in configuration - case "$hardware_id" in + case "$location" in $id) - #echo "match hardware_id([$id] ~ $hardware_id): $spanspecs" + [ "$verbose" = true ] && echo "match by location ($id ~ $location): $spanspecs" + assign_device_spans "$device" + ;; + esac + # We use case to enable shell-style globbing in configuration + case "$devpath" in + $id) + [ "$verbose" = true ] && echo "match by devpath ($id ~ $devpath): $spanspecs" assign_device_spans "$device" ;; esac @@ -196,7 +304,9 @@ auto_assign_devices() { for device in $DEVICES do echo "auto-assign $device" - echo 1 > "$device/auto_assign" + if [ "$dry_run" != true ]; then + echo 1 > "$device/auto_assign" + fi done } @@ -217,6 +327,7 @@ dumpconfig) dump_config ;; *) + echo >&2 "Bad action='$action'" usage ;; esac