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() {
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"
if ! output="$("$PARTED" -s -m "$dev" print)"; then
log_error "Unable to read partition table for device \`${dev}'"
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"
}
......@@ -120,6 +144,13 @@ get_partition_count() {
expr $(echo "$ptable" | wc -l) - 2
}
get_partition_by_id() {
local ptable="$1"
local id="$2"
grep "^$id:" <<< "$ptable"
}
get_last_partition() {
local ptable="$1"
......@@ -179,32 +210,36 @@ get_last_primary_partition() {
}
create_partition() {
local device=$1
local part=$2
local ptype=$3
local device="$1"
local part="$2"
local ptype="$3"
declare -a fields
IFS=":;" read -ra fields <<< "$part"
local id=${fields[0]}
local start=${fields[1]}
local end=${fields[2]}
local size=${fields[3]}
local fs=${fields[4]}
local name=${fields[5]}
local flags=${fields[6]//,/ }
$PARTED -s -m $device mkpart "$ptype" $fs "$start" "$end"
local id="${fields[0]}"
local start="${fields[1]}"
local end="${fields[2]}"
local size="${fields[3]}"
local fs="${fields[4]}"
local name="${fields[5]}"
local flags="${fields[6]//,/ }"
$PARTED -s -m -- $device mkpart "$ptype" $fs "$start" "$end"
for flag in $flags; do
$PARTED -s -m $device set "$id" "$flag" on
done
}
enlarge_partition() {
local device=$1
local part=$2
local ptype=$3
local device="$1"
local part="$2"
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
IFS=":;" read -ra fields <<< "$part"
fields[2]="$new_end"
......@@ -236,11 +271,17 @@ enlarge_partition() {
get_last_free_sector() {
local dev="$1"
local last_line="$("$PARTED" -s -m "$dev" print free | tail -1)"
local ptype="$(echo "$last_line" | cut -d: -f 5)"
local unit="$2"
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
echo "$last_line" | cut -d: -f 3
echo "$last_line"
fi
}
......@@ -256,11 +297,11 @@ cleanup() {
# before we give up with an error. This is needed for kpartx when
# dealing with ntfs partitions mounted through fuse. umount is not
# synchronous and may return while the partition is still busy. A
# premature attempt to delete partition mappings through kpartx on a
# device that hosts previously mounted ntfs partition may fail with
# a `device-mapper: remove ioctl failed: Device or resource busy'
# error. A sensible workaround for this is to wait for a while and
# then try again.
# premature attempt to delete partition mappings through kpartx on
# a device that hosts previously mounted ntfs partition may fail
# with a `device-mapper: remove ioctl failed: Device or resource
# busy' error. A sensible workaround for this is to wait for a
# while and then try again.
local cmd=${CLEANUP[$i]}
$cmd || for interval in 0.25 0.5 1 2 4; do
echo "Command $cmd failed!"
......@@ -289,4 +330,5 @@ check_if_excluded() {
trap cleanup EXIT
set -o pipefail
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
......@@ -59,6 +59,7 @@ target=$(mktemp -d --tmpdir target.XXXXXX)
add_cleanup rmdir "$target"
export SNF_IMAGE_TARGET="$target"
export SNF_IMAGE_RESIZE_PART="$(get_last_partition_id "$SNF_IMAGE_DEV")"
if [ ! -d "@tasksdir@" ]; then
log_error "snf-image/tasks directory is missing"
......
......@@ -43,12 +43,47 @@ table_type=$(get_partition_table_type "$table")
if [ "$table_type" != "msdos" ]; then # We are planning to add gpt support
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
last_part=$(get_last_partition "$table")
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
# Primary, extended and logical partitions is a concept for msdos partition
# tables. Parted's mkpart will use part-type as partition name if applied
......@@ -63,21 +98,52 @@ elif [ $last_part_id -gt 4 ]; then
last_prim_id=$(cut -d':' -f1 <<< "$last_primary")
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_id="$ext_id"
last_part_type="primary"
else
#enlarge the extended partition
enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended"
# Enlarge the extended partition
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
elif [ $(is_extended_partition "$SNF_IMAGE_DEV" "$last_part_id") = "yes" ]; then
last_part_type="extended"
extended="$last_part"
if [ $swap_num -ge 5]; then
new_end=$swap_end
fi
else
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
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
partprobe "$SNF_IMAGE_DEV"
......
......@@ -34,10 +34,15 @@ if [ ! -b "$SNF_IMAGE_DEV" ]; then
log_error "Device file:\`${SNF_IMAGE_DEV}' is not a block device"
fi
if [ -z "$SNF_IMAGE_RESIZE_PART" ]; then
warn "No partition chosen for resize"
exit 0
fi
table=$(get_partition_table "$SNF_IMAGE_DEV")
last_partition=$(get_last_partition "$table")
id=$(echo "$last_partition" | cut -d: -f1)
ptype=$(echo "$last_partition" | cut -d: -f5)
partition=$(get_partition_by_id "$table" "$SNF_IMAGE_RESIZE_PART")
id=$(cut -d: -f1 <<< "$partition")
ptype=$(cut -d: -f5 <<< "$partition")
if [[ "$ptype" == ext[234] ]]; then
device="${SNF_IMAGE_DEV}${id}"
......@@ -57,8 +62,7 @@ if [[ "$ptype" == ext[234] ]]; then
fi
else
warn "Last partition with id: \`$id' has an unsupported file system type:" \
" (ptype = $ptype)."
warn "Don't know how to resize partition \`$id' with file system \`$ptype'."
fi
exit 0
......
......@@ -39,9 +39,9 @@ if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" != "windows" ]; then
fi
table=$(get_partition_table "$SNF_IMAGE_DEV")
last_partition=$(get_last_partition "$table")
id=$(echo "$last_partition" | cut -d: -f1)
ptype=$(echo "$last_partition" | cut -d: -f5)
partition=$(get_partition_by_id "$table" "$SNF_IMAGE_RESIZE_PART")
id=$(cut -d: -f1 <<< "$partition")
ptype=$(cut -d: -f5 <<< "$partition")
if [ "$ptype" = "ntfs" ]; then
# 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