| 1 | #!/bin/sh |
|---|
| 2 | |
|---|
| 3 | # vblade-persist: this script sets up a permanent vblade instance under |
|---|
| 4 | # runit supervision |
|---|
| 5 | |
|---|
| 6 | # Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net> |
|---|
| 7 | # Copyright: November 2007 |
|---|
| 8 | # License: GPLv3 or later |
|---|
| 9 | |
|---|
| 10 | VDIR=/var/lib/vblade-persist/vblades |
|---|
| 11 | SDIR=/usr/share/vblade-persist |
|---|
| 12 | |
|---|
| 13 | usage() { |
|---|
| 14 | echo "usage: vblade-persist ls" |
|---|
| 15 | echo " vblade-persist start|stop|restart|auto|noauto SHELF SLOT" |
|---|
| 16 | echo " vblade-persist start|stop|restart|auto|noauto all" |
|---|
| 17 | echo " vblade-persist setup SHELF SLOT NETIF SOURCE" |
|---|
| 18 | echo " vblade-persist destroy SHELF SLOT" |
|---|
| 19 | echo " vblade-persist mac SHELF SLOT" |
|---|
| 20 | echo " vblade-persist mac SHELF SLOT clear" |
|---|
| 21 | echo " vblade-persist mac SHELF SLOT add [MAC ...] " |
|---|
| 22 | echo " vblade-persist mac SHELF SLOT del [MAC ...] " |
|---|
| 23 | } |
|---|
| 24 | |
|---|
| 25 | error() { |
|---|
| 26 | echo "vblade-persist: $1" >&2 |
|---|
| 27 | } |
|---|
| 28 | |
|---|
| 29 | fatal() { |
|---|
| 30 | error "$1" |
|---|
| 31 | exit ${2:-'1'} |
|---|
| 32 | } |
|---|
| 33 | |
|---|
| 34 | require_sv() { |
|---|
| 35 | [ -x /usr/bin/sv ] || fatal "/usr/bin/sv not available. Please install runit." |
|---|
| 36 | } |
|---|
| 37 | |
|---|
| 38 | # FIXME: make this test a little more robust. |
|---|
| 39 | verify_vblade_persist_path() { |
|---|
| 40 | [ -d "$1" ] |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | # shelf identifiers should be integers: |
|---|
| 44 | # FIXME: check that they're in a certain range? |
|---|
| 45 | verify_shelf() { |
|---|
| 46 | expr match "$1" '[0-9][0-9]*' >/dev/null |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | # slot identifiers should be integers: |
|---|
| 50 | # FIXME: check that they're in a certain range? |
|---|
| 51 | verify_slot() { |
|---|
| 52 | expr match "$1" '[0-9][0-9]*' >/dev/null |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | # FIXME: if there's no ip and no ifconfig, what do we do? |
|---|
| 56 | verify_interface() { |
|---|
| 57 | if [ -x /bin/ip ] ; then |
|---|
| 58 | /bin/ip link show "$1" >/dev/null |
|---|
| 59 | elif [ -x /sbin/ifconfig ] ; then |
|---|
| 60 | /sbin/ifconfig -s "$1" > /dev/null |
|---|
| 61 | else |
|---|
| 62 | error "Don't know how to test interface. Assuming '$1' is acceptable." |
|---|
| 63 | true |
|---|
| 64 | fi |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | # make sure that the device is either a block device or a link to a |
|---|
| 68 | # block device: |
|---|
| 69 | verify_source() { |
|---|
| 70 | [ -b `readlink -f "$1"` ] |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | setup() { |
|---|
| 74 | local SHELF="$1" |
|---|
| 75 | local SLOT="$2" |
|---|
| 76 | local NETIF="$3" |
|---|
| 77 | local SOURCE="$4" |
|---|
| 78 | |
|---|
| 79 | verify_shelf "$SHELF" || fatal "not a valid shelf: '$SHELF'" |
|---|
| 80 | verify_slot "$SLOT" || fatal "not a valid shelf: '$SLOT'" |
|---|
| 81 | verify_interface "$NETIF" || fatal "not a valid interface: '$NETIF'" |
|---|
| 82 | verify_source "$SOURCE" || fatal "not a valid source: '$SOURCE'" |
|---|
| 83 | |
|---|
| 84 | local DNAME="e$SHELF.$SLOT" |
|---|
| 85 | |
|---|
| 86 | mkdir "$VDIR/$DNAME" || fatal "Could not create directory '$VDIR/$DNAME'" |
|---|
| 87 | mkdir "$VDIR/$DNAME/env" |
|---|
| 88 | mkdir "$VDIR/$DNAME/log" |
|---|
| 89 | mkdir "$VDIR/$DNAME/macs" |
|---|
| 90 | |
|---|
| 91 | # start it off idle (so that the admin can decide when to start): |
|---|
| 92 | touch "$VDIR/$DNAME/down" |
|---|
| 93 | |
|---|
| 94 | ln -s "$SDIR/vblade-run" "$VDIR/$DNAME/run" |
|---|
| 95 | ln -s "$SDIR/vblade-finish" "$VDIR/$DNAME/finish" |
|---|
| 96 | ln -s "$SDIR/vblade-logrun" "$VDIR/$DNAME/log/run" |
|---|
| 97 | |
|---|
| 98 | echo "$SHELF" > "$VDIR/$DNAME/env/SHELF" |
|---|
| 99 | echo "$SLOT" > "$VDIR/$DNAME/env/SLOT" |
|---|
| 100 | echo "$NETIF" > "$VDIR/$DNAME/env/NETIF" |
|---|
| 101 | echo "$SOURCE" > "$VDIR/$DNAME/env/SOURCE" |
|---|
| 102 | |
|---|
| 103 | # tell runit to supervise this vblade: |
|---|
| 104 | ln -s "$VDIR/$DNAME" "/var/service/vblade-$DNAME" || fatal "Could not set up supervision for this vblade" |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | destroy() { |
|---|
| 108 | local SHELF="$1" |
|---|
| 109 | local SLOT="$2" |
|---|
| 110 | verify_shelf "$SHELF" || fatal "Not a valid shelf: '$SHELF'" |
|---|
| 111 | verify_slot "$SLOT" || fatal "Not a valid slot: '$SLOT'" |
|---|
| 112 | |
|---|
| 113 | local DNAME="e$SHELF.$SLOT" |
|---|
| 114 | local DPATH="$VDIR/$DNAME" |
|---|
| 115 | verify_vblade_persist_path "$DPATH" || fatal "'`basename $DPATH`' is not a vblade-persist-managed export." |
|---|
| 116 | |
|---|
| 117 | rm -f "/var/lib/service/vblade-$DNAME" |
|---|
| 118 | sv exit "$DPATH" |
|---|
| 119 | rm -rf "$DPATH" |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | |
|---|
| 123 | list() { |
|---|
| 124 | |
|---|
| 125 | echo -e '#shelf slot netif source auto stat' |
|---|
| 126 | for dev in `ls "$VDIR"` ; do |
|---|
| 127 | echo $(cat "$VDIR/$dev/env/SHELF" "$VDIR/$dev/env/SLOT" "$VDIR/$dev/env/NETIF" "$VDIR/$dev/env/SOURCE") $( [ -e "$VDIR/$dev/down" ] && echo 'no')auto $(cat "$VDIR/$dev/supervise/stat") |
|---|
| 128 | done |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | svcommand() { |
|---|
| 132 | require_sv |
|---|
| 133 | local CMD="$1" |
|---|
| 134 | local SVDIR="$2" |
|---|
| 135 | verify_vblade_persist_path "$SVDIR" || fatal "'`basename $DPATH`' is not a vblade-persist-managed export" |
|---|
| 136 | sv "$CMD" "$SVDIR" |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | |
|---|
| 140 | auto() { |
|---|
| 141 | verify_vblade_persist_path "$2" || fatal "'`basename $DPATH`' is not a vblade-persist-managed export" |
|---|
| 142 | if [ "$1" == "auto" ] ; then |
|---|
| 143 | rm -f "$2/down" |
|---|
| 144 | else |
|---|
| 145 | touch "$2/down" |
|---|
| 146 | fi |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | autoall() { |
|---|
| 150 | local AUTO="$1" |
|---|
| 151 | for dev in `ls "$VDIR"` ; do |
|---|
| 152 | auto "$AUTO" "$VDIR/$dev" |
|---|
| 153 | done |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | svall() { |
|---|
| 157 | require_sv |
|---|
| 158 | local CMD="$1" |
|---|
| 159 | for dev in `ls "$VDIR"` ; do |
|---|
| 160 | svcommand "$CMD" "$VDIR/$dev" |
|---|
| 161 | done |
|---|
| 162 | } |
|---|
| 163 | |
|---|
| 164 | mac() { |
|---|
| 165 | local SHELF="$1" |
|---|
| 166 | shift |
|---|
| 167 | local SLOT="$1" |
|---|
| 168 | shift |
|---|
| 169 | |
|---|
| 170 | verify_shelf "$SHELF" || fatal "Not a valid shelf: '$SHELF'" |
|---|
| 171 | verify_slot "$SLOT" || fatal "Not a valid slot: '$SLOT'" |
|---|
| 172 | |
|---|
| 173 | local DPATH="$VDIR/e$SHELF.$SLOT" |
|---|
| 174 | verify_vblade_persist_path "$DPATH" || fatal "'`basename $DPATH`' is not a vblade-persist-managed export." |
|---|
| 175 | |
|---|
| 176 | local CHANGES=no |
|---|
| 177 | |
|---|
| 178 | local CMD="$1" |
|---|
| 179 | case "$CMD" in |
|---|
| 180 | clear) |
|---|
| 181 | if (ls "$DPATH/macs/" | grep -q ^.) ; then |
|---|
| 182 | rm -f "$DPATH"/macs/* |
|---|
| 183 | CHANGES=yes |
|---|
| 184 | fi |
|---|
| 185 | ;; |
|---|
| 186 | add) |
|---|
| 187 | shift |
|---|
| 188 | for mac in "$@"; do |
|---|
| 189 | if [ ! -e "$DPATH/macs/$mac" ] ; then |
|---|
| 190 | touch "$DPATH/macs/$mac" |
|---|
| 191 | CHANGES=yes |
|---|
| 192 | fi |
|---|
| 193 | done |
|---|
| 194 | ;; |
|---|
| 195 | del) |
|---|
| 196 | shift |
|---|
| 197 | for mac in "$@"; do |
|---|
| 198 | if [ -e "$DPATH/macs/$mac" ] ; then |
|---|
| 199 | rm -f "$DPATH/macs/$mac" |
|---|
| 200 | CHANGES=yes |
|---|
| 201 | fi |
|---|
| 202 | done |
|---|
| 203 | ;; |
|---|
| 204 | *) |
|---|
| 205 | ls -1 "$DPATH/macs/" |
|---|
| 206 | ;; |
|---|
| 207 | esac |
|---|
| 208 | |
|---|
| 209 | # restart the vblade upon change |
|---|
| 210 | if [ "$CHANGES" == "yes" ] && [ `cat "$DPATH/supervise/stat"` == "run" ] ; then |
|---|
| 211 | sv restart "$DPATH" |
|---|
| 212 | fi |
|---|
| 213 | } |
|---|
| 214 | |
|---|
| 215 | case "$1" in |
|---|
| 216 | setup) |
|---|
| 217 | setup "$2" "$3" "$4" "$5" |
|---|
| 218 | ;; |
|---|
| 219 | destroy) |
|---|
| 220 | destroy "$2" "$3" |
|---|
| 221 | ;; |
|---|
| 222 | l*) |
|---|
| 223 | list |
|---|
| 224 | ;; |
|---|
| 225 | start|stop|restart) |
|---|
| 226 | if [ "all" == "$2" ] ; then |
|---|
| 227 | svall "$1" |
|---|
| 228 | else |
|---|
| 229 | verify_shelf "$2" || fatal "Not a valid shelf: '$2'" |
|---|
| 230 | verify_slot "$3" || fatal "Not a valid slot: '$3'" |
|---|
| 231 | svcommand "$1" "$VDIR/e$2.$3" |
|---|
| 232 | fi |
|---|
| 233 | ;; |
|---|
| 234 | auto|noauto) |
|---|
| 235 | if [ "all" == "$2" ] ; then |
|---|
| 236 | autoall "$1" |
|---|
| 237 | else |
|---|
| 238 | verify_shelf "$2" || fatal "Not a valid shelf: '$2'" |
|---|
| 239 | verify_slot "$3" || fatal "Not a valid slot: '$3'" |
|---|
| 240 | auto "$1" "$VDIR/e$2.$3" |
|---|
| 241 | fi |
|---|
| 242 | ;; |
|---|
| 243 | mac) |
|---|
| 244 | shift |
|---|
| 245 | mac "$@" |
|---|
| 246 | ;; |
|---|
| 247 | *) |
|---|
| 248 | usage |
|---|
| 249 | exit 1 |
|---|
| 250 | ;; |
|---|
| 251 | esac |
|---|