10FixPartitionTable.in 5.62 KB
Newer Older
1
2
#! /bin/bash

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Copyright (C) 2011 GRNET S.A. 
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

20
21
22
### BEGIN TASK INFO
# Provides:		FixPartitionTable
# RunBefore:		FilesystemResizeUnmounted
23
# Short-Description:	Enlarge last partition to use all the available space
24
25
26
27
28
### END TASK INFO

set -e
. "@commondir@/common.sh"

29
trap task_cleanup EXIT
30
report_task_start
31
32
33
# Check if the task should be prevented from running.
check_if_excluded

34
35
36
37
if [ ! -b "$SNF_IMAGE_DEV" ]; then
    log_error "Device file:\`${SNF_IMAGE_DEV}' is not a block device"
fi

38
if [[ "$SNF_IMAGE_PROPERTY_OSFAMILY" =~ (net)|(open)bsd ]]; then
39
    os=${SNF_IMAGE_PROPERTY_OSFAMILY^^[bsd]}
40
41
42
43
    warn "Partition resizing currently not supported for ${os^?}"
    exit 0
fi

44
table=$(get_partition_table "$SNF_IMAGE_DEV")
45

46
if [ $(get_partition_count "$table") -eq 0 ]; then
47
48
49
    log_error "Device: \`${SNF_IMAGE_DEV}' does not contain any partition"
fi

50
table_type=$(get_partition_table_type "$table")
51

52
53
54
55
56
if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "freebsd" -a "$table_type" != "gpt" ]; then
    log_error "The image contains a(n) $table_type partition table. " \
        "For FreeBSD images only GUID Partition Tables are supported."
fi

57
if [ "$table_type" == "gpt" ]; then
58
    "$SGDISK" --move-second-header "$SNF_IMAGE_DEV"
59
elif [ "$table_type" != "msdos" ]; then
60
    log_error "Device: \'${SNF_IMAGE_DEV}' contains unsupported partition " \
61
62
              "table type: \`$table_type'. Only msdos & gpt partitions are" \
              "supported."
63
64
fi

65
66
67
last_part=$(get_last_partition "$table")
last_part_id=$(cut -d':' -f1 <<< "$last_part")

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# 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=""

103
if [ "$table_type" != "msdos" ]; then
104
105
    # For gpt partitions, get the partition GUID code as partition type
    last_part_type="$($SGDISK -i "$last_part_id" "$SNF_IMAGE_DEV" | grep "^Partition GUID code:" | cut -d"(" -f1 | cut -d: -f2 | xargs echo)"
106
107
108
109
110
111
112
113
114
elif [ $last_part_id -gt 4 ]; then
    last_part_type="logical"
    extended=$(get_extended_partition "$table")
    last_primary=$(get_last_primary_partition "$table")

    ext_id=$(cut -d':' -f1 <<< "$extended")
    last_prim_id=$(cut -d':' -f1 <<< "$last_primary")

    if [ "$ext_id" != "$last_prim_id" ]; then
115
        # Mark last primary as the last partition
116
117
118
119
        last_part="$extended"
        last_part_id="$ext_id"
        last_part_type="primary"
    else
120
121
        # Enlarge the extended partition
        if [ $swap_num -ge 5 ]; then
122
123
124
125
            # This is needed because logical partitions need to have at least
            # 1 sector gap between them. We make the gap 2048 sectors to
            # properly align them.
            new_end=$((new_end - 2048))
126
127
128
129
            enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${swap_end}s"
        else
            enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${new_end}s"
        fi
130
131
132
    fi
elif [ $(is_extended_partition "$SNF_IMAGE_DEV" "$last_part_id") = "yes" ]; then
    last_part_type="extended"
133
134
135
136
    extended="$last_part"
    if [ $swap_num -ge 5]; then
        new_end=$swap_end
    fi
137
138
else
    last_part_type="primary"
139
140
141
142
143
144
145
    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
146
147
fi

148
149
150
151
152
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
153
        swap_ptype="swap" # in gpt this is used as a partition name
154
155
156
157
158
159
160
161
162
163
164
    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
165

166
# Inform the kernel about the changes
167
168
169
170
171
partprobe "$SNF_IMAGE_DEV"

exit 0

# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :