Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh -e
- #
- # FreeBSD hotplug script for attaching disks
- #
- # Parameters:
- # $1: xenstore backend path of the vbd
- # $2: action, either "add" or "remove"
- #
- # Environment variables:
- # None
- #
- DIR=$(dirname "$0")
- . "${DIR}/hotplugpath.sh"
- . "${DIR}/locking.sh"
- ############################################################################
- ##
- # This set of functions could be used elsewhere and thus should be moved to
- # their own script file and be sourced here
- #
- ##
- # xenstore_read_default <path> <default>
- #
- # Read the given path, returning the value there or the given default if the
- # path is not present.
- #
- xenstore_read_default() {
- xenstore-read "$1" 2>/dev/null || echo "$2"
- }
- ##
- # xenstore_read <path>+
- #
- # Read each of the given paths, returning each result on a separate line, or
- # exit this script if any of the paths is missing.
- #
- xenstore_read() {
- local v=$(xenstore-read "$@" || true)
- [ "$v" != "" ] || fatal "xenstore-read $@ failed."
- echo "$v"
- }
- ##
- # _xenstore_write (<path> <value>)+
- #
- # Write each of the key/value pairs to the store.
- #
- _xenstore_write() {
- log debug "Writing $@ to xenstore."
- xenstore-write "$@"
- }
- ##
- # xenstore_write (<path> <value>)+
- #
- # Write each of the key/value pairs to the store, and exit this script if any
- # such writing fails.
- #
- xenstore_write() {
- _xenstore_write "$@" || fatal "Writing $@ to xenstore failed."
- }
- ##
- # add x
- #
- canonicalise_mode(){
- local mode="$1"
- if [ x"w" != x"$(echo $mode|grep -o "w")" ]; then
- echo "r"
- else
- if [ x"!" != x"$(echo $mode|grep -o "!")" ]; then
- echo "w"
- else
- echo "!"
- fi
- fi
- }
- log() {
- local level="$1"
- shift
- logger -p "daemon.$level" -- "$0:" "$@" || echo "$0 $@" >&2
- }
- ##
- # needs $backend to be defined
- #
- fatal() {
- _xenstore_write "$backend/hotplug-error" "$*" \
- "$backend/hotplug-status" error
- log err "$@"
- exit 1
- }
- ############################################################################
- ##
- # Pre:
- # After canonicalise_mode $mode is not null
- # Post: If the disk is already in use in another domain, report back that domain
- # so we can inform of the domain using the device, if not return 0
- check_sharing(){
- local device=$1
- local mode=$(canonicalise_mode $2)
- local dom_id=$3
- local base_path=$4
- local type=$5
- local physical_device=$6
- if [ "$mode" == "w" ]; then
- for dom in $(xenstore-list "$base_path/$type")
- do
- for dev in $(xenstore-list "$base_path/$type/$dom")
- do
- temp=$(xenstore_read_default "$base_path/$type/$dom/$dev/physical-device" "")
- if [ x"$temp" == x"$physical_device" ]; then
- # we could think we're done here, but it could be possible we were adding the same disk
- # two times in the same domain, the second time we would find the disk in the xenstore and
- # think it belongs two another machine. Thus we need to check the dom ids.
- if [ "$dom" != "$dom_id" ]; then
- echo "$dom"
- return
- fi
- fi
- done
- done
- fi
- echo "0"
- }
- ##
- # first argument is the device path
- # second argument is the action to be performed
- # third argument is the device type
- # fourth argument is the backend path of the disk
- # fifth argument is the disk backend base path (something like
- # /local/domain/0/backend/vbd/ where all the domain are listed with
- # their corresponding disks)
- # sixth argument is the dom_id
- path=$1
- action=$2
- type=$3
- backend=$4
- base_path=$5
- dom_id=$6
- physical_device=$(xenstore-read "$path/params")
- case $action in
- add)
- if [ ! -e $physical_device ]; then
- fatal "File $physical_device does not exist"
- fi
- # check if the device is a file and is mounted as a memory device (the mount command
- # does not show the original device but the block device associated with that file)
- # file has to exist or the mdconfig command will not be quiet if the file is not used
- # as a memory device
- if [ x$(mdconfig -l -f $physical_device) != "x" ]; then
- if [ x"$(mount | grep -E -o "$(mdconfig -l -f $physical_device).*on")" != "x" ]; then
- fatal "File $physical_device already in use as loop device"
- fi
- fi
- # check if the device is a block device (either a partition, raw disk, zvol) and is
- # already mounted
- if [ x"$(mount | grep -E -o "$physical_device.*on")" != "x" ]; then
- fatal "Block device $physical_device already in use"
- fi
- # check if the device is shareable (that is, if it's plugged on "r" or "!" mode then it can
- # straightly used, if it's used in "w" then we need to check whether that device is already
- #
- mode=$(xenstore-read "$backend/mode")
- another_dom=$(check_sharing $path $mode $dom_id $base_path $type $physical_device)
- if [ $another_dom != "0" ]; then
- fatal "The device $physical_device seems to already be in use in domain $another_dom"
- fi
- claim_lock "block"
- xenstore-write $path/physical-device $physical_device
- release_lock "block"
- exit 0
- ;;
- *)
- xenstore-rm $path/physical-device
- exit 0
- ;;
- esac
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement