Commit 01da0f7d authored by Nikos Skalkotos's avatar Nikos Skalkotos
Browse files

Add swap partition if SWAP property is defined

parent d259b27c
...@@ -95,12 +95,36 @@ get_distro() { ...@@ -95,12 +95,36 @@ get_distro() {
fi fi
} }
get_partition_table() { normalize_unit() {
unit=$(tr [a-z] [A-Z] <<< $1)
case $unit in
"S") echo "s";;
"B"|"") echo "B";;
"KB") echo "kB";;
"MB") echo "MB";;
"GB") echo "GB";;
*) log_error "Unknown unit type: \`$1'";;
esac
}
get_last_partition_id() {
local dev="$1" local dev="$1"
if ! output="$("$PARTED" -s -m "$dev" print)"; then if ! output="$("$PARTED" -s -m "$dev" print)"; then
log_error "Unable to read partition table for device \`${dev}'" log_error "Unable to read partition table for device \`${dev}'"
fi fi
last_line=$(tail -1 <<< "$output")
echo $(cut -d: -f1 <<< "$last_line")
}
get_partition_table() {
local dev="$1"
if ! output="$("$PARTED" -s -m "$dev" unit s print)"; then
log_error "Unable to read partition table for device \`${dev}'"
fi
echo "$output" echo "$output"
} }
...@@ -120,6 +144,13 @@ get_partition_count() { ...@@ -120,6 +144,13 @@ get_partition_count() {
expr $(echo "$ptable" | wc -l) - 2 expr $(echo "$ptable" | wc -l) - 2
} }
get_partition_by_id() {
local ptable="$1"
local id="$2"
grep "^$id:" <<< "$ptable"
}
get_last_partition() { get_last_partition() {
local ptable="$1" local ptable="$1"
...@@ -179,32 +210,36 @@ get_last_primary_partition() { ...@@ -179,32 +210,36 @@ get_last_primary_partition() {
} }
create_partition() { create_partition() {
local device=$1 local device="$1"
local part=$2 local part="$2"
local ptype=$3 local ptype="$3"
declare -a fields declare -a fields
IFS=":;" read -ra fields <<< "$part" IFS=":;" read -ra fields <<< "$part"
local id=${fields[0]} local id="${fields[0]}"
local start=${fields[1]} local start="${fields[1]}"
local end=${fields[2]} local end="${fields[2]}"
local size=${fields[3]} local size="${fields[3]}"
local fs=${fields[4]} local fs="${fields[4]}"
local name=${fields[5]} local name="${fields[5]}"
local flags=${fields[6]//,/ } local flags="${fields[6]//,/ }"
$PARTED -s -m $device mkpart "$ptype" $fs "$start" "$end" $PARTED -s -m -- $device mkpart "$ptype" $fs "$start" "$end"
for flag in $flags; do for flag in $flags; do
$PARTED -s -m $device set "$id" "$flag" on $PARTED -s -m $device set "$id" "$flag" on
done done
} }
enlarge_partition() { enlarge_partition() {
local device=$1 local device="$1"
local part=$2 local part="$2"
local ptype=$3 local ptype="$3"
local new_end="$4"
if [ -z "$new_end" ]; then
new_end=$(cut -d: -f 3 <<< "$(get_last_free_sector "$device")")
fi
local new_end=$(get_last_free_sector "$device")
declare -a fields declare -a fields
IFS=":;" read -ra fields <<< "$part" IFS=":;" read -ra fields <<< "$part"
fields[2]="$new_end" fields[2]="$new_end"
...@@ -236,11 +271,17 @@ enlarge_partition() { ...@@ -236,11 +271,17 @@ enlarge_partition() {
get_last_free_sector() { get_last_free_sector() {
local dev="$1" local dev="$1"
local last_line="$("$PARTED" -s -m "$dev" print free | tail -1)" local unit="$2"
local ptype="$(echo "$last_line" | cut -d: -f 5)"
if [ -n "$unit" ]; then
unit="unit $unit"
fi
local last_line="$("$PARTED" -s -m "$dev" "$unit" print free | tail -1)"
local ptype="$(cut -d: -f 5 <<< "$last_line")"
if [ "$ptype" = "free;" ]; then if [ "$ptype" = "free;" ]; then
echo "$last_line" | cut -d: -f 3 echo "$last_line"
fi fi
} }
...@@ -256,11 +297,11 @@ cleanup() { ...@@ -256,11 +297,11 @@ cleanup() {
# before we give up with an error. This is needed for kpartx when # before we give up with an error. This is needed for kpartx when
# dealing with ntfs partitions mounted through fuse. umount is not # dealing with ntfs partitions mounted through fuse. umount is not
# synchronous and may return while the partition is still busy. A # synchronous and may return while the partition is still busy. A
# premature attempt to delete partition mappings through kpartx on a # premature attempt to delete partition mappings through kpartx on
# device that hosts previously mounted ntfs partition may fail with # a device that hosts previously mounted ntfs partition may fail
# a `device-mapper: remove ioctl failed: Device or resource busy' # with a `device-mapper: remove ioctl failed: Device or resource
# error. A sensible workaround for this is to wait for a while and # busy' error. A sensible workaround for this is to wait for a
# then try again. # while and then try again.
local cmd=${CLEANUP[$i]} local cmd=${CLEANUP[$i]}
$cmd || for interval in 0.25 0.5 1 2 4; do $cmd || for interval in 0.25 0.5 1 2 4; do
echo "Command $cmd failed!" echo "Command $cmd failed!"
...@@ -289,4 +330,5 @@ check_if_excluded() { ...@@ -289,4 +330,5 @@ check_if_excluded() {
trap cleanup EXIT trap cleanup EXIT
set -o pipefail set -o pipefail
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
...@@ -59,6 +59,7 @@ target=$(mktemp -d --tmpdir target.XXXXXX) ...@@ -59,6 +59,7 @@ target=$(mktemp -d --tmpdir target.XXXXXX)
add_cleanup rmdir "$target" add_cleanup rmdir "$target"
export SNF_IMAGE_TARGET="$target" export SNF_IMAGE_TARGET="$target"
export SNF_IMAGE_RESIZE_PART="$(get_last_partition_id "$SNF_IMAGE_DEV")"
if [ ! -d "@tasksdir@" ]; then if [ ! -d "@tasksdir@" ]; then
log_error "snf-image/tasks directory is missing" log_error "snf-image/tasks directory is missing"
......
...@@ -43,12 +43,47 @@ table_type=$(get_partition_table_type "$table") ...@@ -43,12 +43,47 @@ table_type=$(get_partition_table_type "$table")
if [ "$table_type" != "msdos" ]; then # We are planning to add gpt support if [ "$table_type" != "msdos" ]; then # We are planning to add gpt support
log_error "Device: \'${SNF_IMAGE_DEV}' contains unsupported partition " log_error "Device: \'${SNF_IMAGE_DEV}' contains unsupported partition "
"table type: \`$table_type'. For now only msdos partitions are supported." "table type: \`$table_type'. For now only msdos partitions are supported."
fi fi
last_part=$(get_last_partition "$table") last_part=$(get_last_partition "$table")
last_part_id=$(cut -d':' -f1 <<< "$last_part") last_part_id=$(cut -d':' -f1 <<< "$last_part")
# Check if swap is defined...
if [ -n "$SNF_IMAGE_PROPERTY_SWAP" ]; then
if [[ "$SNF_IMAGE_PROPERTY_SWAP" =~ ^([0-9]+):([0-9]+)$ ]]; then
swap_num=${BASH_REMATCH[1]}
swap_size=${BASH_REMATCH[2]}
swap_unit="MB"
else
log_error "SWAP property \`$SNF_IMAGE_PROPERTY_SWAP' is not valid"
fi
fi
if [ -z "$swap_num" ]; then
swap_num=0
fi
# Most partition setups leave 2048s in the end. For GPT partitions you need at
# least 34s for the secondary GPT header.
new_end="-2049"
if [ $swap_num -ne 0 ]; then
free=$(get_last_free_sector "$SNF_IMAGE_DEV" "$swap_unit")
free_size=$(cut -d: -f4 <<< "$free")
free_size_val=${free_size/$swap_unit/}
if [ $free_size_val -le $swap_size ]; then
log_error "Not enough space for swap partition"
fi
swap_end="$new_end"
swap_start=$((new_end - (swap_size * 2048) + 1)) # in sectors
new_end=$((swap_start - 1))
fi
extended=""
if [ "$table_type" != "msdos" ]; then if [ "$table_type" != "msdos" ]; then
# Primary, extended and logical partitions is a concept for msdos partition # Primary, extended and logical partitions is a concept for msdos partition
# tables. Parted's mkpart will use part-type as partition name if applied # tables. Parted's mkpart will use part-type as partition name if applied
...@@ -63,21 +98,52 @@ elif [ $last_part_id -gt 4 ]; then ...@@ -63,21 +98,52 @@ elif [ $last_part_id -gt 4 ]; then
last_prim_id=$(cut -d':' -f1 <<< "$last_primary") last_prim_id=$(cut -d':' -f1 <<< "$last_primary")
if [ "$ext_id" != "$last_prim_id" ]; then if [ "$ext_id" != "$last_prim_id" ]; then
#Mark last primary as the last partition # Mark last primary as the last partition
last_part="$extended" last_part="$extended"
last_part_id="$ext_id" last_part_id="$ext_id"
last_part_type="primary" last_part_type="primary"
else else
#enlarge the extended partition # Enlarge the extended partition
enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" if [ $swap_num -ge 5 ]; then
enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${swap_end}s"
else
enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${new_end}s"
fi
fi fi
elif [ $(is_extended_partition "$SNF_IMAGE_DEV" "$last_part_id") = "yes" ]; then elif [ $(is_extended_partition "$SNF_IMAGE_DEV" "$last_part_id") = "yes" ]; then
last_part_type="extended" last_part_type="extended"
extended="$last_part"
if [ $swap_num -ge 5]; then
new_end=$swap_end
fi
else else
last_part_type="primary" last_part_type="primary"
if [ $swap_num -ge 5 ]; then
# This is needed because the swap partition should be added inside a
# new extended partition. In order to align the swap partition, we
# need to create some extra space between the (aligned) primary and
# the swap.
new_end=$((new_end - 2048))
fi
fi fi
enlarge_partition "$SNF_IMAGE_DEV" "$last_part" "$last_part_type" enlarge_partition "$SNF_IMAGE_DEV" "$last_part" "$last_part_type" "${new_end}s"
if [ $swap_num -gt 0 ]; then
swap_part="$swap_num:${swap_start}s:${swap_end}s:0:linux-swap(v1)::;"
if [ "$table_type" != "msdos" ]; then
swap_ptype=""
elif [ $swap_num -ge 5 ]; then
if [ -z "$extended" ]; then
extended="0:$((swap_start - 2))s:${swap_end}s:0:::;"
create_partition "$SNF_IMAGE_DEV" "$extended" "extended"
fi
swap_ptype="logical"
else
swap_ptype="primary"
fi
create_partition "$SNF_IMAGE_DEV" "$swap_part" "$swap_ptype"
fi
# Inform the kernel about the changes # Inform the kernel about the changes
partprobe "$SNF_IMAGE_DEV" partprobe "$SNF_IMAGE_DEV"
......
...@@ -34,10 +34,15 @@ if [ ! -b "$SNF_IMAGE_DEV" ]; then ...@@ -34,10 +34,15 @@ if [ ! -b "$SNF_IMAGE_DEV" ]; then
log_error "Device file:\`${SNF_IMAGE_DEV}' is not a block device" log_error "Device file:\`${SNF_IMAGE_DEV}' is not a block device"
fi fi
if [ -z "$SNF_IMAGE_RESIZE_PART" ]; then
warn "No partition chosen for resize"
exit 0
fi
table=$(get_partition_table "$SNF_IMAGE_DEV") table=$(get_partition_table "$SNF_IMAGE_DEV")
last_partition=$(get_last_partition "$table") partition=$(get_partition_by_id "$table" "$SNF_IMAGE_RESIZE_PART")
id=$(echo "$last_partition" | cut -d: -f1) id=$(cut -d: -f1 <<< "$partition")
ptype=$(echo "$last_partition" | cut -d: -f5) ptype=$(cut -d: -f5 <<< "$partition")
if [[ "$ptype" == ext[234] ]]; then if [[ "$ptype" == ext[234] ]]; then
device="${SNF_IMAGE_DEV}${id}" device="${SNF_IMAGE_DEV}${id}"
...@@ -57,8 +62,7 @@ if [[ "$ptype" == ext[234] ]]; then ...@@ -57,8 +62,7 @@ if [[ "$ptype" == ext[234] ]]; then
fi fi
else else
warn "Last partition with id: \`$id' has an unsupported file system type:" \ warn "Don't know how to resize partition \`$id' with file system \`$ptype'."
" (ptype = $ptype)."
fi fi
exit 0 exit 0
......
...@@ -39,9 +39,9 @@ if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" != "windows" ]; then ...@@ -39,9 +39,9 @@ if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" != "windows" ]; then
fi fi
table=$(get_partition_table "$SNF_IMAGE_DEV") table=$(get_partition_table "$SNF_IMAGE_DEV")
last_partition=$(get_last_partition "$table") partition=$(get_partition_by_id "$table" "$SNF_IMAGE_RESIZE_PART")
id=$(echo "$last_partition" | cut -d: -f1) id=$(cut -d: -f1 <<< "$partition")
ptype=$(echo "$last_partition" | cut -d: -f5) ptype=$(cut -d: -f5 <<< "$partition")
if [ "$ptype" = "ntfs" ]; then if [ "$ptype" = "ntfs" ]; then
# Write a diskpart script to %SystemDrive%\Windows\SnfScripts. Sysprep will # Write a diskpart script to %SystemDrive%\Windows\SnfScripts. Sysprep will
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment