mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
vdo: lvm_import_vdo enhancements
Work also with devices that may have ':' inside their generated /dev/disk/by-id Ensure there is no race with systems' auto activation while using the snapshot for conversion. Update system's vdoconf.yml after the use of snapshot for conversion. Skip unnecesary prompt for 'convert' while using snapshot and query only for final snaphot merge. Prohibit conversion for a device with the PV header. Enhance 'trap' protection for more signals. Improve clean() recovery path. Replace bash 'test' command with []. Correct some output message to print $TOOL. Support also options without '-' in the middle i.e. --nosnapshot. For shellcheck predefine all variables extracted from vdoconf.yml.
This commit is contained in:
parent
fa49651301
commit
d9cebeaf34
@ -36,6 +36,9 @@ TEMPDIR="${TMPDIR:-/tmp}/$IMPORT_NAME"
|
|||||||
_SAVEPATH=$PATH
|
_SAVEPATH=$PATH
|
||||||
PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
|
PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
|
||||||
|
|
||||||
|
# Set of trapped signals
|
||||||
|
declare -a SIGNALS=("HUP" "INT" "QUIT" "ABRT" "TERM" "EXIT")
|
||||||
|
|
||||||
# user may override lvm location by setting LVM_BINARY
|
# user may override lvm location by setting LVM_BINARY
|
||||||
LVM=${LVM_BINARY:-lvm}
|
LVM=${LVM_BINARY:-lvm}
|
||||||
VDO=${VDO_BINARY:-vdo}
|
VDO=${VDO_BINARY:-vdo}
|
||||||
@ -52,7 +55,9 @@ DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
|
|||||||
DM_UUID_PREFIX="${DM_UUID_PREFIX:-}"
|
DM_UUID_PREFIX="${DM_UUID_PREFIX:-}"
|
||||||
DM_VG_NAME=
|
DM_VG_NAME=
|
||||||
DM_LV_NAME=
|
DM_LV_NAME=
|
||||||
|
DEFAULT_VDO_CONFIG="/etc/vdoconf.yml" # Default location of vdo's manager config file
|
||||||
VDO_CONFIG=${VDO_CONFIG:-} # can be overridden with --vdo-config
|
VDO_CONFIG=${VDO_CONFIG:-} # can be overridden with --vdo-config
|
||||||
|
VDO_CONFIG_RESTORE=
|
||||||
VDOCONF=
|
VDOCONF=
|
||||||
test -n "$VDO_CONFIG" && VDOCONF="-f $VDO_CONFIG"
|
test -n "$VDO_CONFIG" && VDOCONF="-f $VDO_CONFIG"
|
||||||
|
|
||||||
@ -61,16 +66,17 @@ VGNAME=
|
|||||||
LVNAME=
|
LVNAME=
|
||||||
DEVMAJOR=0
|
DEVMAJOR=0
|
||||||
DEVMINOR=0
|
DEVMINOR=0
|
||||||
PROMPTING=""
|
PROMPTING=
|
||||||
USE_VDO_DM_SNAPSHOT=1
|
USE_VDO_DM_SNAPSHOT="--yes"
|
||||||
VDO_DM_SNAPSHOT_NAME=
|
VDO_DM_SNAPSHOT_NAME=
|
||||||
VDO_DM_SNAPSHOT_DEVICE=
|
VDO_DM_SNAPSHOT_DEVICE=
|
||||||
VDO_SNAPSHOT_LOOP=
|
VDO_SNAPSHOT_LOOP=
|
||||||
|
VDO_INCONSISTENT=
|
||||||
|
|
||||||
DRY=0
|
DRY=0
|
||||||
VERB=""
|
VERB=
|
||||||
FORCE=""
|
FORCE=
|
||||||
YES=""
|
YES=
|
||||||
ABORT_AFTER_VDO_CONVERT=0
|
ABORT_AFTER_VDO_CONVERT=0
|
||||||
VDO_ALLOCATION_PARAMS=
|
VDO_ALLOCATION_PARAMS=
|
||||||
|
|
||||||
@ -78,6 +84,25 @@ VDO_ALLOCATION_PARAMS=
|
|||||||
DEFAULT_NAME="vdovg/vdolvol"
|
DEFAULT_NAME="vdovg/vdolvol"
|
||||||
NAME=""
|
NAME=""
|
||||||
|
|
||||||
|
# predefine empty
|
||||||
|
vdo_ackThreads=
|
||||||
|
vdo_bioRotationInterval=
|
||||||
|
vdo_bioThreads=
|
||||||
|
vdo_blockMapCacheSize=
|
||||||
|
vdo_blockMapPeriod=
|
||||||
|
vdo_compression=
|
||||||
|
vdo_cpuThreads=
|
||||||
|
vdo_deduplication=
|
||||||
|
vdo_hashZoneThreads=
|
||||||
|
vdo_indexMemory=
|
||||||
|
vdo_indexSparse=
|
||||||
|
vdo_logicalBlockSize=
|
||||||
|
vdo_logicalThreads=
|
||||||
|
vdo_maxDiscardSize=
|
||||||
|
vdo_physicalThreads=
|
||||||
|
vdo_slabSize=
|
||||||
|
vdo_writePolicy=
|
||||||
|
|
||||||
# help message
|
# help message
|
||||||
tool_usage() {
|
tool_usage() {
|
||||||
echo "${TOOL}: Utility to convert VDO volume to VDO LV."
|
echo "${TOOL}: Utility to convert VDO volume to VDO LV."
|
||||||
@ -107,7 +132,11 @@ error() {
|
|||||||
for i in "$@" ; do
|
for i in "$@" ; do
|
||||||
echo "$TOOL: $i" >&2
|
echo "$TOOL: $i" >&2
|
||||||
done
|
done
|
||||||
cleanup 1
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo "$TOOL: WARNING: $i" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
dry() {
|
dry() {
|
||||||
@ -120,20 +149,31 @@ dry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
trap '' 2
|
RC=$? # Return code + 128 of the last command eg INT=2 + 128 -> 130
|
||||||
test -n "$VDO_DM_SNAPSHOT_NAME" && {
|
|
||||||
|
trap '' "${SIGNALS[@]}" # mute trap for all signals to not interrupt cleanup() on any next signal
|
||||||
|
|
||||||
|
[ -z "$PROMPTING" ] || echo "No"
|
||||||
|
|
||||||
|
[ -e "$VDO_CONFIG_RESTORE" ] && { dry cp -a "$VDO_CONFIG_RESTORE" "${VDO_CONFIG:-"$DEFAULT_VDO_CONFIG"}" || true ; }
|
||||||
|
|
||||||
|
if [ -n "$VDO_DM_SNAPSHOT_NAME" ]; then
|
||||||
|
dry "$LVM" vgchange -an --devices "$VDO_DM_SNAPSHOT_DEVICE" "$VGNAME" &>/dev/null || true
|
||||||
for i in {1..20} ; do
|
for i in {1..20} ; do
|
||||||
test "$("$DMSETUP" info --noheading -co open "$VDO_DM_SNAPSHOT_NAME")" = "0" && break
|
[ "$(dry "$DMSETUP" info --noheading -co open "$VDO_DM_SNAPSHOT_NAME")" = "0" ] && break
|
||||||
sleep .1
|
sleep .1
|
||||||
done
|
done
|
||||||
"$DMSETUP" remove "$VDO_DM_SNAPSHOT_NAME" || true
|
dry "$DMSETUP" remove "$VDO_DM_SNAPSHOT_NAME" &>/dev/null || true
|
||||||
}
|
fi
|
||||||
test -n "$VDO_SNAPSHOT_LOOP" && { "$LOSETUP" -d "$VDO_SNAPSHOT_LOOP" || true ; }
|
|
||||||
|
|
||||||
|
[ -n "$VDO_SNAPSHOT_LOOP" ] && { dry "$LOSETUP" -d "$VDO_SNAPSHOT_LOOP" || true ; }
|
||||||
|
|
||||||
|
[ -z "$VDO_INCONSISTENT" ] || echo "$TOOL: VDO volume import process exited unexpectedly!" >&2
|
||||||
|
|
||||||
test -z "$PROMPTING" || echo "No"
|
|
||||||
rm -rf "$TEMPDIR" || true
|
rm -rf "$TEMPDIR" || true
|
||||||
# error exit status for break
|
|
||||||
exit "${1:-1}"
|
exit "$RC"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create snapshot target like for persistent snapshot with 16KiB chunksize
|
# Create snapshot target like for persistent snapshot with 16KiB chunksize
|
||||||
@ -148,7 +188,7 @@ snapshot_create_() {
|
|||||||
# TODO: maybe use ramdisk via 'brd' device ?)
|
# TODO: maybe use ramdisk via 'brd' device ?)
|
||||||
"$TRUNCATE" -s 20M "$file"
|
"$TRUNCATE" -s 20M "$file"
|
||||||
VDO_SNAPSHOT_LOOP=$("$LOSETUP" -f --show "$file")
|
VDO_SNAPSHOT_LOOP=$("$LOSETUP" -f --show "$file")
|
||||||
"$DMSETUP" create "$VDO_DM_SNAPSHOT_NAME" -u "${DM_UUID_PREFIX}-${VDO_DM_SNAPSHOT_NAME}-priv" --table "$(snapshot_target_line_ "$1" "$VDO_SNAPSHOT_LOOP")"
|
"$DMSETUP" create "$VDO_DM_SNAPSHOT_NAME" -u "${DM_UUID_PREFIX}${VDO_DM_SNAPSHOT_NAME}-priv" --table "$(snapshot_target_line_ "$1" "$VDO_SNAPSHOT_LOOP")"
|
||||||
VDO_DM_SNAPSHOT_DEVICE="$DM_DEV_DIR/mapper/$VDO_DM_SNAPSHOT_NAME"
|
VDO_DM_SNAPSHOT_DEVICE="$DM_DEV_DIR/mapper/$VDO_DM_SNAPSHOT_NAME"
|
||||||
verbose "Snapshot of VDO device $1 created: $VDO_DM_SNAPSHOT_DEVICE."
|
verbose "Snapshot of VDO device $1 created: $VDO_DM_SNAPSHOT_DEVICE."
|
||||||
}
|
}
|
||||||
@ -164,6 +204,8 @@ snapshot_merge_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
verbose "Merging converted VDO volume..."
|
verbose "Merging converted VDO volume..."
|
||||||
|
VDO_INCONSISTENT=1
|
||||||
|
|
||||||
# Running merging
|
# Running merging
|
||||||
"$DMSETUP" resume "$VDO_DM_SNAPSHOT_NAME"
|
"$DMSETUP" resume "$VDO_DM_SNAPSHOT_NAME"
|
||||||
|
|
||||||
@ -175,20 +217,24 @@ snapshot_merge_() {
|
|||||||
for i in $(seq 1 20) ; do
|
for i in $(seq 1 20) ; do
|
||||||
status=( $("$DMSETUP" status "$VDO_DM_SNAPSHOT_NAME") )
|
status=( $("$DMSETUP" status "$VDO_DM_SNAPSHOT_NAME") )
|
||||||
# Check if merging is finished
|
# Check if merging is finished
|
||||||
test "${status[3]%/*}" = "${status[4]}" && break
|
[ "${status[3]%/*}" = "${status[4]}" ] && break
|
||||||
# Wait a bit and retry
|
# Wait a bit and retry
|
||||||
sleep .2
|
sleep .2
|
||||||
done
|
done
|
||||||
test "${status[3]%/*}" = "${status[4]}" || {
|
|
||||||
|
if [ "${status[3]%/*}" != "${status[4]}" ]; then
|
||||||
# FIXME: Now what shall we do ??? Help....
|
# FIXME: Now what shall we do ??? Help....
|
||||||
# Keep snapshot in table for possible analysis...
|
# Keep snapshot in DM table for possible analysis...
|
||||||
VDO_DM_SNAPSHOT_NAME=
|
VDO_DM_SNAPSHOT_NAME=
|
||||||
VDO_SNAPSHOT_LOOP=
|
VDO_SNAPSHOT_LOOP=
|
||||||
echo "Initial snapshot status ${initial_status[*]}"
|
echo "$TOOL: Initial snapshot status ${initial_status[*]}"
|
||||||
echo "Failing merge snapshot status ${status[*]}"
|
echo "$TOOL: Failing merge snapshot status ${status[*]}"
|
||||||
error "ABORTING: Snapshot failed to merge! (Administrator required...)"
|
error "ABORTING: Snapshot failed to merge! (Administrator required...)"
|
||||||
}
|
fi
|
||||||
sync
|
|
||||||
|
VDO_INCONSISTENT=
|
||||||
|
VDO_CONFIG_RESTORE=
|
||||||
|
|
||||||
"$DMSETUP" remove "$VDO_DM_SNAPSHOT_NAME" || {
|
"$DMSETUP" remove "$VDO_DM_SNAPSHOT_NAME" || {
|
||||||
sleep 1 # sleep and retry once more
|
sleep 1 # sleep and retry once more
|
||||||
"$DMSETUP" remove "$VDO_DM_SNAPSHOT_NAME" || {
|
"$DMSETUP" remove "$VDO_DM_SNAPSHOT_NAME" || {
|
||||||
@ -227,9 +273,9 @@ get_largest_extent_size_() {
|
|||||||
|
|
||||||
for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do
|
for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do
|
||||||
d=$(( $1 / i ))
|
d=$(( $1 / i ))
|
||||||
test $(( d * i )) -eq "$1" || break
|
[ $(( d * i )) -eq "$1" ] || break
|
||||||
d=$(( $2 / i ))
|
d=$(( $2 / i ))
|
||||||
test $(( d * i )) -eq "$2" || break
|
[ $(( d * i )) -eq "$2" ] || break
|
||||||
max=$i
|
max=$i
|
||||||
done
|
done
|
||||||
echo "$max"
|
echo "$max"
|
||||||
@ -244,7 +290,7 @@ detect_lv_() {
|
|||||||
|
|
||||||
DEVICE=${1/#"${DM_DEV_DIR}/"/}
|
DEVICE=${1/#"${DM_DEV_DIR}/"/}
|
||||||
DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE" || true)
|
DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE" || true)
|
||||||
test -n "$DEVICE" || error "Readlink cannot access device \"$1\"."
|
[ -n "$DEVICE" ] || error "Readlink cannot access device \"$1\"."
|
||||||
RDEVICE=$DEVICE
|
RDEVICE=$DEVICE
|
||||||
case "$RDEVICE" in
|
case "$RDEVICE" in
|
||||||
# hardcoded /dev since udev does not create these entries elsewhere
|
# hardcoded /dev since udev does not create these entries elsewhere
|
||||||
@ -256,12 +302,12 @@ detect_lv_() {
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
RSTAT=$("$STAT" --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE" || true)
|
RSTAT=$("$STAT" --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE" || true)
|
||||||
test -n "$RSTAT" || error "Cannot get major:minor for \"$DEVICE\"."
|
[ -n "$RSTAT" ] || error "Cannot get major:minor for \"$DEVICE\"."
|
||||||
eval "$RSTAT"
|
eval "$RSTAT"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
test "$DEVMAJOR" != "$(grep device-mapper /proc/devices | cut -f1 -d' ')" && return
|
[ "$DEVMAJOR" != "$(grep device-mapper /proc/devices | cut -f1 -d' ')" ] && return
|
||||||
|
|
||||||
DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
|
DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
|
||||||
case "$DEV" in
|
case "$DEV" in
|
||||||
@ -337,9 +383,10 @@ convert_lv_() {
|
|||||||
vg_extent_size=$("$LVM" vgs -o vg_extent_size --units b --nosuffix --noheadings "$VGNAME")
|
vg_extent_size=$("$LVM" vgs -o vg_extent_size --units b --nosuffix --noheadings "$VGNAME")
|
||||||
vg_extent_size=$(( vg_extent_size / 1024 ))
|
vg_extent_size=$(( vg_extent_size / 1024 ))
|
||||||
|
|
||||||
test "$vg_extent_size" -le "$extent_size" || {
|
[ "$vg_extent_size" -le "$extent_size" ] || {
|
||||||
error "Please vgchange extent_size to at most $extent_size KiB or extend and align virtual size of VDO device on $vg_extent_size KiB before retrying conversion."
|
error "Please vgchange extent_size to at most $extent_size KiB or extend and align virtual size of VDO device on $vg_extent_size KiB before retrying conversion."
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
|
verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
|
||||||
dry "$LVM" lvrename $YES $VERB "$VGNAME/$DM_LV_NAME" "$VGNAME/${LVNAME}_vpool" || {
|
dry "$LVM" lvrename $YES $VERB "$VGNAME/$DM_LV_NAME" "$VGNAME/${LVNAME}_vpool" || {
|
||||||
error "Rename of LV \"$VGNAME/$DM_LV_NAME\" failed, while VDO header has been already moved!"
|
error "Rename of LV \"$VGNAME/$DM_LV_NAME\" failed, while VDO header has been already moved!"
|
||||||
@ -367,25 +414,39 @@ convert_non_lv_() {
|
|||||||
local output
|
local output
|
||||||
local pvfree
|
local pvfree
|
||||||
|
|
||||||
if [ "$USE_VDO_DM_SNAPSHOT" = "1" ]; then
|
if [ -n "$USE_VDO_DM_SNAPSHOT" ]; then
|
||||||
dry snapshot_create_ "$DEVICE"
|
dry snapshot_create_ "$DEVICE"
|
||||||
sed "s:$DEVICE:$VDO_DM_SNAPSHOT_DEVICE:" "$TEMPDIR/vdoconf.yml" > "$TEMPDIR/vdo_snap.yml"
|
sed "s|$DEVICE|$VDO_DM_SNAPSHOT_DEVICE|" "$TEMPDIR/vdoconf.yml" > "$TEMPDIR/vdo_snap.yml"
|
||||||
|
# In case of error in the middle of conversion restore original config file
|
||||||
|
VDO_CONFIG_RESTORE="$TEMPDIR/vdoconf.yml"
|
||||||
# Let VDO manager operate on snapshot volume
|
# Let VDO manager operate on snapshot volume
|
||||||
VDOCONF="-f $TEMPDIR/vdo_snap.yml"
|
dry cp -a "$TEMPDIR/vdo_snap.yml" "${VDO_CONFIG:-"$DEFAULT_VDO_CONFIG"}"
|
||||||
|
else
|
||||||
|
# If error in the following section, report possible problems ahead
|
||||||
|
VDO_INCONSISTENT=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
verbose "Moving VDO header."
|
# In case we operate with snapshot, all lvm2 operation will also run on top of snapshot
|
||||||
|
local device=${VDO_DM_SNAPSHOT_DEVICE:-$DEVICE}
|
||||||
|
|
||||||
|
# Check if there is not already an existing PV header, this would have fail on pvcreate after conversion
|
||||||
|
"$LVM" pvs --devices "$device" "$device" 2>/dev/null && {
|
||||||
|
error "Cannot convert volume \"$DEVICE\" with existing PV header."
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose "Moving VDO header on \"$device\"."
|
||||||
|
|
||||||
output=$(dry "$VDO" convert $VDOCONF $VERB --force --name "$VDONAME" 2>&1) || {
|
output=$(dry "$VDO" convert $VDOCONF $VERB --force --name "$VDONAME" 2>&1) || {
|
||||||
|
local rc=$?
|
||||||
echo "$output"
|
echo "$output"
|
||||||
error "Failed to convert VDO volume \"$DEVICE\" (exit code $?)."
|
error "Failed to convert VDO volume \"$DEVICE\" (exit code $rc)."
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "$output"
|
echo "$output"
|
||||||
|
|
||||||
if [ "$ABORT_AFTER_VDO_CONVERT" != "0" ]; then
|
if [ "$ABORT_AFTER_VDO_CONVERT" != "0" ]; then
|
||||||
verbose "Aborting VDO conversion after moving VDO header, volume is useless!"
|
warn "Aborting VDO conversion after moving VDO header, volume is useless!"
|
||||||
cleanup 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Parse result from VDO preparation/conversion tool
|
# Parse result from VDO preparation/conversion tool
|
||||||
@ -410,12 +471,7 @@ convert_non_lv_() {
|
|||||||
esac
|
esac
|
||||||
done <<< "$output"
|
done <<< "$output"
|
||||||
|
|
||||||
# In case we operation with snapshot, all lvm2 operation will also run on top of snapshot
|
dry "$LVM" pvcreate $YES $VERB $FORCE --devices "$device" --dataalignment "$vdo_offset"b "$device"
|
||||||
local devices=${VDO_DM_SNAPSHOT_DEVICE:-$DEVICE}
|
|
||||||
|
|
||||||
dry "$LVM" pvcreate $YES --devices "$devices" --dataalignment "$vdo_offset"b "$devices" || {
|
|
||||||
error "Creation of PV on \"$DEVICE\" failed, while VDO header has been already moved!"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Obtain free space in this new PV
|
# Obtain free space in this new PV
|
||||||
# after 'vdo convert' call there is ~(1-2)M free space at the front of the device
|
# after 'vdo convert' call there is ~(1-2)M free space at the front of the device
|
||||||
@ -432,54 +488,57 @@ convert_non_lv_() {
|
|||||||
# To precisely byte-synchronize the size of VDO LV, user can lvresize such VDO LV later.
|
# To precisely byte-synchronize the size of VDO LV, user can lvresize such VDO LV later.
|
||||||
vdo_logicalSizeRounded=$(( ( vdo_logicalSize / extent_size ) * extent_size ))
|
vdo_logicalSizeRounded=$(( ( vdo_logicalSize / extent_size ) * extent_size ))
|
||||||
|
|
||||||
verbose "Creating VG \"${NAME%/*}\" with extent size $extent_size KiB."
|
verbose "Creating volume group \"$VGNAME\" with the extent size $extent_size KiB."
|
||||||
dry "$LVM" vgcreate $YES $VERB --devices "$devices" -s "${extent_size}k" "$VGNAME" "$devices" || {
|
dry "$LVM" vgcreate $YES $VERB --devices "$device" -s "${extent_size}k" "$VGNAME" "$device"
|
||||||
error "Creation of VG \"$VGNAME\" failed, while VDO header has been already moved!"
|
|
||||||
}
|
|
||||||
|
|
||||||
verbose "Creating VDO pool data LV from all extents in volume group $VGNAME."
|
verbose "Creating VDO pool data LV from all extents in the volume group \"$VGNAME\"."
|
||||||
dry "$LVM" lvcreate -Zn -Wn -an $YES $VERB --devices "$devices" -l100%VG -n "${LVNAME}_vpool" "$VGNAME" "$devices"
|
dry "$LVM" lvcreate -Zn -Wn -an $YES $VERB --devices "$device" -l100%VG -n "${LVNAME}_vpool" "$VGNAME" "$device"
|
||||||
|
|
||||||
verbose "Converting to VDO pool."
|
verbose "Converting to VDO pool."
|
||||||
dry "$LVM" lvconvert $YES $VERB $FORCE --devices "$devices" --config "$VDO_ALLOCATION_PARAMS" -Zn -V "${vdo_logicalSizeRounded}k" -n "$LVNAME" --type vdo-pool "$VGNAME/${LVNAME}_vpool"
|
dry "$LVM" lvconvert ${USE_VDO_DM_SNAPSHOT:-"$YES"} $VERB $FORCE --devices "$device" --config "$VDO_ALLOCATION_PARAMS" -Zn -V "${vdo_logicalSizeRounded}k" -n "$LVNAME" --type vdo-pool "$VGNAME/${LVNAME}_vpool"
|
||||||
|
|
||||||
if [ "$vdo_logicalSizeRounded" -lt "$vdo_logicalSize" ]; then
|
if [ "$vdo_logicalSizeRounded" -lt "$vdo_logicalSize" ]; then
|
||||||
# need to extend virtual size to be covering all the converted area
|
# need to extend virtual size to be covering all the converted area
|
||||||
# let lvm2 to round to the proper virtual size of VDO LV
|
# let lvm2 to round to the proper virtual size of VDO LV
|
||||||
dry "$LVM" lvextend $YES $VERB --fs ignore --devices "$devices" -L "$vdo_logicalSize"k "$VGNAME/$LVNAME"
|
dry "$LVM" lvextend $YES $VERB --fs ignore --devices "$device" -L "$vdo_logicalSize"k "$VGNAME/$LVNAME"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dry "$LVM" vgchange -an $VERB $FORCE --devices "$devices" "$VGNAME"
|
VDO_INCONSISTENT=
|
||||||
|
|
||||||
|
if [ -n "$USE_VDO_DM_SNAPSHOT" ]; then
|
||||||
|
dry "$LVM" vgchange -an $VERB $FORCE --devices "$device" "$VGNAME"
|
||||||
|
|
||||||
|
# Prevent unwanted auto activation when VG is merged
|
||||||
|
dry "$LVM" vgchange --setautoactivation n $VERB $FORCE --devices "$device" "$VGNAME"
|
||||||
|
|
||||||
if [ "$USE_VDO_DM_SNAPSHOT" = "1" ]; then
|
|
||||||
if [ -z "$YES" ]; then
|
if [ -z "$YES" ]; then
|
||||||
PROMPTING=yes
|
PROMPTING=yes
|
||||||
echo "Warning: Do not interrupt merging process once it starts (VDO data may become irrecoverable)!"
|
warn "Do not interrupt merging process once it starts (VDO data may become irrecoverable)!"
|
||||||
echo -n "Do you want to merge converted VDO device \"$DEVICE\" to VDO LV \"$VGNAME/$LVNAME\"? [y|N]: "
|
echo -n "$TOOL: Do you want to merge converted VDO device \"$DEVICE\" to VDO LV \"$VGNAME/$LVNAME\"? [y|N]: "
|
||||||
read -r -n 1 -s ANSWER
|
read -r -n 1 -s ANSWER
|
||||||
case "${ANSWER:0:1}" in
|
case "${ANSWER:0:1}" in
|
||||||
y|Y ) echo "Yes" ;;
|
y|Y ) echo "Yes" ;;
|
||||||
* ) echo "No" ; PROMPTING=""; cleanup 1 ;;
|
* ) echo "No" ; PROMPTING=""; return 1 ;;
|
||||||
esac
|
esac
|
||||||
PROMPTING=""
|
PROMPTING=""
|
||||||
YES="-y" # From now, now prompting
|
YES="-y" # From now, now prompting
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dry snapshot_merge_ "$DEVICE"
|
dry snapshot_merge_ "$DEVICE"
|
||||||
if [ -e "$TEMPDIR/vdo_snap.yml" ]; then
|
|
||||||
dry cp "$TEMPDIR/vdo_snap.yml" "$VDO_CONFIG"
|
|
||||||
elif [ -e "$VDO_CONFIG" ]; then
|
|
||||||
dry rm -f "$VDO_CONFIG"
|
|
||||||
fi
|
|
||||||
verbose "Merging of VDO device finished."
|
verbose "Merging of VDO device finished."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
output=$(dry "$LVM" pvs "$DEVICE" 2>&1) || {
|
output=$("$LVM" pvs "$DEVICE" 2>&1) || {
|
||||||
if echo "$output" | grep -q "not in devices file" ; then
|
if echo "$output" | grep -q "not in devices file" ; then
|
||||||
verbose "Adding \"$DEVICE\" to devices file."
|
verbose "Adding \"$DEVICE\" to devices file."
|
||||||
dry "$LVM" lvmdevices --adddev "$DEVICE"
|
dry "$LVM" lvmdevices --adddev "$DEVICE"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Restore auto activation for a VG
|
||||||
|
[ -n "$USE_VDO_DM_SNAPSHOT" ] && dry "$LVM" vgchange --setautoactivation y $VERB $FORCE "$VGNAME"
|
||||||
|
|
||||||
dry "$LVM" lvchange -ay $VERB $FORCE "$VGNAME/$LVNAME"
|
dry "$LVM" lvchange -ay $VERB $FORCE "$VGNAME/$LVNAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +559,7 @@ convert2lvm_() {
|
|||||||
if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]; then
|
if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]; then
|
||||||
VGNAME=$DM_VG_NAME
|
VGNAME=$DM_VG_NAME
|
||||||
verbose "Using existing volume group name \"$VGNAME\"."
|
verbose "Using existing volume group name \"$VGNAME\"."
|
||||||
test -n "$LVNAME" || LVNAME=$DM_LV_NAME
|
[ -n "$LVNAME" ] || LVNAME=$DM_LV_NAME
|
||||||
elif [ "$VGNAME" != "$DM_VG_NAME" ]; then
|
elif [ "$VGNAME" != "$DM_VG_NAME" ]; then
|
||||||
error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for VDO device \"$DEVICE\"."
|
error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for VDO device \"$DEVICE\"."
|
||||||
fi
|
fi
|
||||||
@ -510,30 +569,30 @@ convert2lvm_() {
|
|||||||
if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]; then
|
if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ]; then
|
||||||
VGNAME=${DEFAULT_NAME%/*}
|
VGNAME=${DEFAULT_NAME%/*}
|
||||||
# Find largest matching VG name to our 'default' vgname
|
# Find largest matching VG name to our 'default' vgname
|
||||||
LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~"${VGNAME}" | grep -E "${VGNAME}[0-9]? ?" | head -1 || true)
|
LASTVGNAME=$(LC_ALL=C "$LVM" vgs -oname -O-name --noheadings -S name=~"${VGNAME}" | grep -m 1 -E "${VGNAME}[0-9]? ?" || true)
|
||||||
if [ -n "$LASTVGNAME" ]; then
|
if [ -n "$LASTVGNAME" ]; then
|
||||||
LASTVGNAME=${LASTVGNAME#*"${VGNAME}"}
|
LASTVGNAME=${LASTVGNAME#*"${VGNAME}"}
|
||||||
# If the number is becoming too high, try some random number
|
# If the number is becoming too high, try some random number
|
||||||
test "$LASTVGNAME" -gt 99999999 2>/dev/null && LASTVGNAME=$RANDOM
|
[ -n "$LASTVGNAME" ] && [ "$LASTVGNAME" -gt 99999999 ] && LASTVGNAME=$RANDOM
|
||||||
# Generate new unused VG name
|
# Generate new unused VG name
|
||||||
VGNAME="${VGNAME}$(( LASTVGNAME + 1 ))"
|
VGNAME="${VGNAME}$(( LASTVGNAME + 1 ))"
|
||||||
verbose "Selected unused volume group name \"$VGNAME\"."
|
verbose "Selected unused volume group name \"$VGNAME\"."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# New VG is created, LV name should be always unused.
|
# New VG is created, LV name should be always unused.
|
||||||
test -n "$LVNAME" || LVNAME=${DEFAULT_NAME#*/}
|
[ -n "$LVNAME" ] || LVNAME=${DEFAULT_NAME#*/}
|
||||||
"$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"."
|
"$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"."
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
verbose "Checked whether device \"$DEVICE\" is already logical volume."
|
verbose "Checked whether device \"$DEVICE\" is already logical volume."
|
||||||
|
|
||||||
"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
|
"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create \"$TEMPDIR\"."
|
||||||
|
|
||||||
# TODO: might use directly /etc/vdoconf.yml (avoiding need of 'vdo' manager)
|
# TODO: might use directly /etc/vdoconf.yml (avoiding need of 'vdo' manager)
|
||||||
verbose "Getting YAML VDO configuration."
|
verbose "Getting YAML VDO configuration."
|
||||||
"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
|
"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
|
||||||
test -s "$TEMPDIR/vdoconf.yml" || error "Cannot work without VDO configuration"
|
[ -s "$TEMPDIR/vdoconf.yml" ] || error "Cannot work without VDO configuration."
|
||||||
|
|
||||||
# Check list of devices in VDO configure file for their major:minor
|
# Check list of devices in VDO configure file for their major:minor
|
||||||
# and match with given $DEVICE devmajor:devminor
|
# and match with given $DEVICE devmajor:devminor
|
||||||
@ -542,13 +601,13 @@ convert2lvm_() {
|
|||||||
DEV=$("$READLINK" $READLINK_E "$i") || continue
|
DEV=$("$READLINK" $READLINK_E "$i") || continue
|
||||||
RSTAT=$("$STAT" --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
|
RSTAT=$("$STAT" --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue
|
||||||
eval "$RSTAT"
|
eval "$RSTAT"
|
||||||
test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && {
|
if [ "$MAJOR" = "$DEVMAJOR" ] && [ "$MINOR" = "$DEVMINOR" ]; then
|
||||||
test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i"
|
[ -z "$FOUND" ] || error "VDO configuration contains duplicate entries $FOUND and $i."
|
||||||
FOUND=$i
|
FOUND=$i
|
||||||
}
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
test -n "$FOUND" || error "Can't find matching device in VDO configuration file."
|
[ -n "$FOUND" ] || error "Can't find matching device in VDO configuration file."
|
||||||
verbose "Found matching device $FOUND $MAJOR:$MINOR."
|
verbose "Found matching device $FOUND $MAJOR:$MINOR."
|
||||||
|
|
||||||
VDONAME=$(awk -v DNAME="$FOUND" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
|
VDONAME=$(awk -v DNAME="$FOUND" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
|
||||||
@ -559,7 +618,7 @@ convert2lvm_() {
|
|||||||
case "$DM_OPEN" in
|
case "$DM_OPEN" in
|
||||||
Device*) ;; # no devices
|
Device*) ;; # no devices
|
||||||
*) eval "$DM_OPEN"
|
*) eval "$DM_OPEN"
|
||||||
test "${DM_OPEN:-0}" -eq 0 || error "Cannot convert in use VDO volume \"$VDONAME\"!"
|
[ "${DM_OPEN:-0}" -eq 0 ] || error "Cannot convert in use VDO volume \"$VDONAME\"!"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@ -601,20 +660,20 @@ EOF
|
|||||||
dry "$VDO" stop $VDOCONF --name "$VDONAME" $VERB
|
dry "$VDO" stop $VDOCONF --name "$VDONAME" $VERB
|
||||||
|
|
||||||
# If user has not provided '--yes', prompt before conversion
|
# If user has not provided '--yes', prompt before conversion
|
||||||
if [ -z "$YES" ] && [ "$USE_VDO_DM_SNAPSHOT" != "1" ]; then
|
if [ -z "$YES" ] && [ -z "$USE_VDO_DM_SNAPSHOT" ]; then
|
||||||
PROMPTING=yes
|
PROMPTING=yes
|
||||||
echo -n "Convert VDO device \"$DEVICE\" to VDO LV \"$VGNAME/$LVNAME\"? [y|N]: "
|
echo -n "$TOOL: Convert VDO device \"$DEVICE\" to VDO LV \"$VGNAME/$LVNAME\"? [y|N]: "
|
||||||
read -r -n 1 -s ANSWER
|
read -r -n 1 -s ANSWER
|
||||||
case "${ANSWER:0:1}" in
|
case "${ANSWER:0:1}" in
|
||||||
y|Y ) echo "Yes" ;;
|
y|Y ) echo "Yes" ;;
|
||||||
* ) echo "No" ; PROMPTING=""; cleanup 1 ;;
|
* ) echo "No" ; PROMPTING=""; return 1 ;;
|
||||||
esac
|
esac
|
||||||
PROMPTING=""
|
PROMPTING=""
|
||||||
YES="-y" # From now, no prompting
|
YES="-y" # From now, no prompting
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Make a backup of the existing VDO yaml configuration file
|
# Make a backup of the existing VDO yaml configuration file
|
||||||
test -e "$VDO_CONFIG" && dry cp -a "$VDO_CONFIG" "${VDO_CONFIG}.backup"
|
[ -e "$VDO_CONFIG" ] && dry cp -a "$VDO_CONFIG" "${VDO_CONFIG}.backup"
|
||||||
|
|
||||||
DEVICE=$FOUND
|
DEVICE=$FOUND
|
||||||
case "$DM_UUID" in
|
case "$DM_UUID" in
|
||||||
@ -627,9 +686,9 @@ EOF
|
|||||||
# start point of this script
|
# start point of this script
|
||||||
# - parsing parameters
|
# - parsing parameters
|
||||||
#############################
|
#############################
|
||||||
trap "cleanup 2" 2
|
trap "cleanup" "${SIGNALS[@]}"
|
||||||
|
|
||||||
test "$#" -eq 0 && tool_usage
|
[ "$#" -eq 0 ] && tool_usage
|
||||||
|
|
||||||
while [ "$#" -ne 0 ]
|
while [ "$#" -ne 0 ]
|
||||||
do
|
do
|
||||||
@ -640,19 +699,17 @@ do
|
|||||||
"-n"|"--name" ) shift; NAME=$1 ;;
|
"-n"|"--name" ) shift; NAME=$1 ;;
|
||||||
"-v"|"--verbose") VERB="--verbose" ;;
|
"-v"|"--verbose") VERB="--verbose" ;;
|
||||||
"-y"|"--yes" ) YES="-y" ;;
|
"-y"|"--yes" ) YES="-y" ;;
|
||||||
"--abort-after-vdo-convert" ) ABORT_AFTER_VDO_CONVERT=1; USE_VDO_DM_SNAPSHOT=0 ;; # For testing only
|
"--abort-after-vdo-convert"|"--abortaftervdoconvert" ) ABORT_AFTER_VDO_CONVERT=1; USE_VDO_DM_SNAPSHOT= ;; # For testing only
|
||||||
"--dry-run" ) DRY="1" ; VERB="-v" ;;
|
"--dry-run"|"--dryrun" ) DRY="1" ; VERB="-v" ;;
|
||||||
"--no-snapshot" ) USE_VDO_DM_SNAPSHOT=0 ;;
|
"--no-snapshot"|"--nosnapshot" ) USE_VDO_DM_SNAPSHOT= ;;
|
||||||
"--uuid-prefix" ) shift; DM_UUID_PREFIX=$1 ;; # For testing only
|
"--uuid-prefix"|"--uuidprefix" ) shift; DM_UUID_PREFIX=$1 ;; # For testing only
|
||||||
"--vdo-config" ) shift; VDO_CONFIG=$1 ; VDOCONF="-f $VDO_CONFIG" ;;
|
"--vdo-config"|"--vdoconfig" ) shift; VDO_CONFIG=$1 ; VDOCONF="-f $VDO_CONFIG" ;;
|
||||||
"-*") error "Wrong argument \"$1\". (see: $TOOL --help)" ;;
|
-* ) error "Wrong argument \"$1\". (see: $TOOL --help)" ;;
|
||||||
*) DEVICE=$1 ;; # device name does not start with '-'
|
*) DEVICE=$1 ;; # device name does not start with '-'
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
test -n "$DEVICE" || error "Device name is not specified. (see: $TOOL --help)"
|
[ -n "$DEVICE" ] || error "Device name is not specified. (see: $TOOL --help)"
|
||||||
|
|
||||||
convert2lvm_
|
convert2lvm_
|
||||||
|
|
||||||
cleanup 0
|
|
||||||
|
Loading…
Reference in New Issue
Block a user