Ironic: Deploy ramdisk to find the right root device
As part of the blueprint root-device-hints Ironic will pass some to the deploy ramdisk some hints about which disk device it should pick to be root device (the one where the image will be deployed on). Before the deploy ramdisk would pick the first device it finds, but as the machine could have more than one SATA, SCSI or IDE disk controllers the order in which their corresponding device nodes are added is arbitrary causing devices like /dev/sda and /dev/sdb switching around on each boot time. Plus, as people are adding support to build RAID arrays in Ironic we need a way to tell it to use the just created device to be the root device. The list of hints that could be passed to the deploy ramdisk so it finds the right disk is: * wwn (STRING): unique storage identifier * serial (STRING): disk serial number * model (STRING): device identifier * vendor (STRING): device vendor * size (INT): The size of the disk in GB If not hints are passed, the deploy ramdisk will continue to do what it did before to find the disk. Change-Id: I8425f593e1a610af5a3697988702603ff218f2de
This commit is contained in:
parent
e70ffdd15e
commit
b95cbb14b1
115
elements/deploy-ironic/init.d/70-ironic-root-device
Normal file
115
elements/deploy-ironic/init.d/70-ironic-root-device
Normal file
@ -0,0 +1,115 @@
|
||||
CHECK_SIZE=false
|
||||
CHECK_MODEL=false
|
||||
CHECK_VENDOR=false
|
||||
CHECK_UUID=false
|
||||
CHECK_WWN=false
|
||||
CHECK_HCTL=false
|
||||
CHECK_SERIAL=false
|
||||
|
||||
|
||||
# URL/Percent decode a text
|
||||
function urldecode() {
|
||||
local encoded="${1//+/ }"
|
||||
printf '%b' "${encoded//%/\x}"
|
||||
}
|
||||
|
||||
|
||||
# Lowercase and url decode the values
|
||||
function normalize() {
|
||||
echo `urldecode "${1,,}"`
|
||||
}
|
||||
|
||||
|
||||
function _exec_lsblk() {
|
||||
lsblk -Pbio $2 /dev/$1 | head -n 1 | grep -Po "(?<=^$2=).*" | tr "\"" " "
|
||||
}
|
||||
|
||||
|
||||
# Get the block device size in GiB
|
||||
function get_size() {
|
||||
echo $(( (512 * $(cat /sys/block/$1/size) ) / 2**30))
|
||||
}
|
||||
|
||||
|
||||
function get_model() {
|
||||
local file
|
||||
file=/sys/block/$1/device/model
|
||||
if [ -f $file ]; then
|
||||
normalize "$(cat $file)"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function get_vendor() {
|
||||
local file
|
||||
file=/sys/block/$1/device/vendor
|
||||
if [ -f $file ]; then
|
||||
normalize "$(cat $file)"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function get_wwn() {
|
||||
normalize "$(_exec_lsblk "$1" WWN)"
|
||||
}
|
||||
|
||||
|
||||
function get_serial() {
|
||||
normalize "$(_exec_lsblk "$1" SERIAL)"
|
||||
}
|
||||
|
||||
|
||||
# Parse all the hints from the Kernel cmdline and set the CHECK_*
|
||||
# variables
|
||||
function parse_hints() {
|
||||
IFS=',' read -ra H <<< "$ROOT_DEVICE"
|
||||
for i in "${H[@]}"; do
|
||||
case "$i" in
|
||||
size=*)
|
||||
CHECK_SIZE="${i#size=}"
|
||||
;;
|
||||
model=*)
|
||||
CHECK_MODEL=`normalize "${i#model=}"`
|
||||
;;
|
||||
vendor=*)
|
||||
CHECK_VENDOR=`normalize "${i#vendor=}"`
|
||||
;;
|
||||
wwn=*)
|
||||
CHECK_WWN=`normalize "${i#wwn=}"`
|
||||
;;
|
||||
serial=*)
|
||||
CHECK_SERIAL=`normalize "${i#serial=}"`
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function get_root_device() {
|
||||
# Parse the hints
|
||||
parse_hints
|
||||
|
||||
for DEV in /sys/block/* ; do
|
||||
DEV_NAME=${DEV##*/}
|
||||
DEV_PATH=/dev/$DEV_NAME
|
||||
|
||||
# Ignore loop and ram devices
|
||||
[[ $DEV_NAME = *loop* || $DEV_NAME = *ram* ]] && continue || :
|
||||
|
||||
# Find out if it's a CDROM
|
||||
TYPE=/sys/block/$DEV_NAME/device/type
|
||||
[[ -f $TYPE ]] && (( $(cat "$TYPE") == 5 )) && continue || :
|
||||
|
||||
[[ $CHECK_SIZE != false && $(get_size "$DEV_NAME") != $CHECK_SIZE ]] && continue || :
|
||||
[[ $CHECK_MODEL != false && $(get_model "$DEV_NAME") != $CHECK_MODEL ]] && continue || :
|
||||
[[ $CHECK_VENDOR != false && $(get_vendor "$DEV_NAME") != $CHECK_VENDOR ]] && continue || :
|
||||
[[ $CHECK_SERIAL != false && $(get_serial "$DEV_NAME") != $CHECK_SERIAL ]] && continue || :
|
||||
[[ $CHECK_WWN != false && $(get_wwn "$DEV_NAME") != $CHECK_WWN ]] && continue || :
|
||||
|
||||
# A device that matches all hints was found
|
||||
echo "$DEV_PATH"
|
||||
break
|
||||
done
|
||||
}
|
@ -1,20 +1,26 @@
|
||||
readonly IRONIC_API_URL=$(get_kernel_parameter ironic_api_url)
|
||||
readonly IRONIC_BOOT_OPTION=$(get_kernel_parameter boot_option)
|
||||
readonly IRONIC_BOOT_MODE=$(get_kernel_parameter boot_mode)
|
||||
readonly ROOT_DEVICE=$(get_kernel_parameter root_device)
|
||||
|
||||
if [ -z "$ISCSI_TARGET_IQN" ]; then
|
||||
err_msg "iscsi_target_iqn is not defined"
|
||||
troubleshoot
|
||||
fi
|
||||
|
||||
t=0
|
||||
while ! target_disk=$(find_disk "$DISK"); do
|
||||
if [ $t -eq 10 ]; then
|
||||
break
|
||||
fi
|
||||
t=$(($t + 1))
|
||||
sleep 1
|
||||
done
|
||||
target_disk=
|
||||
if [[ $ROOT_DEVICE ]]; then
|
||||
target_disk="$(get_root_device)"
|
||||
else
|
||||
t=0
|
||||
while ! target_disk=$(find_disk "$DISK"); do
|
||||
if [ $t -eq 10 ]; then
|
||||
break
|
||||
fi
|
||||
t=$(($t + 1))
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "$target_disk" ]; then
|
||||
err_msg "Could not find disk to use."
|
||||
|
Loading…
Reference in New Issue
Block a user