Use blockdev instead of partprobe after disklabel
[snf-image] / snf-image-helper / tasks / 10FixPartitionTable.in
1 #! /bin/bash
2
3 # Copyright (C) 2011 GRNET S.A. 
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 # 02110-1301, USA.
19
20 ### BEGIN TASK INFO
21 # Provides:             FixPartitionTable
22 # RunBefore:            FilesystemResizeUnmounted
23 # Short-Description:    Enlarge last partition to use all the available space
24 ### END TASK INFO
25
26 set -e
27 . "@commondir@/common.sh"
28
29 trap task_cleanup EXIT
30 report_task_start
31 # Check if the task should be prevented from running.
32 check_if_excluded
33
34 if [ ! -b "$SNF_IMAGE_DEV" ]; then
35     log_error "Device file:\`${SNF_IMAGE_DEV}' is not a block device"
36 fi
37
38 if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = openbsd ]; then
39     @scriptsdir@/disklabel.py -d "$($BLOCKDEV --getsz "$SNF_IMAGE_DEV")" -p "$SNF_IMAGE_DEV"
40     # Tell the kernel to recreate the disk partitions.
41     # We cannot use partprobe to do this because partprobe uses BLKPG ioctl
42     # to create the partitions device files by itself one by one. Since parted
43     # does not support disklabels, the partitions with id larger than 4 will
44     # not be created.
45     # We need to tell the kernel to read the partition table by itself.
46     $BLOCKDEV --rereadpt "$SNF_IMAGE_DEV"
47     exit 0
48 fi
49
50 if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = netbsd ]; then
51     warn "Partition resizing currently not supported for NetBSD"
52     exit 0
53 fi
54
55 table=$(get_partition_table "$SNF_IMAGE_DEV")
56
57 if [ $(get_partition_count "$table") -eq 0 ]; then
58     log_error "Device: \`${SNF_IMAGE_DEV}' does not contain any partition"
59 fi
60
61 table_type=$(get_partition_table_type "$table")
62
63 if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "freebsd" -a "$table_type" != "gpt" ]; then
64     log_error "The image contains a(n) $table_type partition table. " \
65         "For FreeBSD images only GUID Partition Tables are supported."
66 fi
67
68 if [ "$table_type" == "gpt" ]; then
69     "$SGDISK" --move-second-header "$SNF_IMAGE_DEV"
70 elif [ "$table_type" != "msdos" ]; then
71     log_error "Device: \'${SNF_IMAGE_DEV}' contains unsupported partition " \
72               "table type: \`$table_type'. Only msdos & gpt partitions are" \
73               "supported."
74 fi
75
76 last_part=$(get_last_partition "$table")
77 last_part_id=$(cut -d':' -f1 <<< "$last_part")
78
79 # Check if swap is defined...
80 if [ -n "$SNF_IMAGE_PROPERTY_SWAP" ]; then
81     if [[ "$SNF_IMAGE_PROPERTY_SWAP" =~ ^([0-9]+):([0-9]+)$ ]]; then
82         swap_num=${BASH_REMATCH[1]}
83         swap_size=${BASH_REMATCH[2]}
84         swap_unit="MB"
85     else
86         log_error "SWAP property \`$SNF_IMAGE_PROPERTY_SWAP' is not valid"
87     fi
88 fi
89
90 if [ -z "$swap_num" ]; then
91     swap_num=0
92 fi
93
94 # Most partition setups leave 2048s in the end. For GPT partitions you need at
95 # least 34s for the secondary GPT header.
96 new_end="-2049"
97
98 if [ $swap_num -ne 0 ]; then
99     free=$(get_last_free_sector "$SNF_IMAGE_DEV" "$swap_unit")
100     free_size=$(cut -d: -f4 <<< "$free")
101     free_size_val=${free_size/$swap_unit/}
102     if [ $free_size_val -le $swap_size ]; then
103         log_error "Not enough space for swap partition"
104     fi
105
106     swap_end="$new_end"
107
108     swap_start=$((new_end - (swap_size * 2048) + 1)) # in sectors
109     new_end=$((swap_start - 1))
110 fi
111
112 extended=""
113
114 if [ "$table_type" != "msdos" ]; then
115     # For gpt partitions, get the partition GUID code as partition type
116     last_part_type="$($SGDISK -i "$last_part_id" "$SNF_IMAGE_DEV" | grep "^Partition GUID code:" | cut -d"(" -f1 | cut -d: -f2 | xargs echo)"
117 elif [ $last_part_id -gt 4 ]; then
118     last_part_type="logical"
119     extended=$(get_extended_partition "$table")
120     last_primary=$(get_last_primary_partition "$table")
121
122     ext_id=$(cut -d':' -f1 <<< "$extended")
123     last_prim_id=$(cut -d':' -f1 <<< "$last_primary")
124
125     if [ "$ext_id" != "$last_prim_id" ]; then
126         # Mark last primary as the last partition
127         last_part="$extended"
128         last_part_id="$ext_id"
129         last_part_type="primary"
130     else
131         # Enlarge the extended partition
132         if [ $swap_num -ge 5 ]; then
133             # This is needed because logical partitions need to have at least
134             # 1 sector gap between them. We make the gap 2048 sectors to
135             # properly align them.
136             new_end=$((new_end - 2048))
137             enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${swap_end}s"
138         else
139             enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${new_end}s"
140         fi
141     fi
142 elif [ $(is_extended_partition "$SNF_IMAGE_DEV" "$last_part_id") = "yes" ]; then
143     last_part_type="extended"
144     extended="$last_part"
145     if [ $swap_num -ge 5]; then
146         new_end=$swap_end
147     fi
148 else
149     last_part_type="primary"
150     if [ $swap_num -ge 5 ]; then
151         # This is needed because the swap partition should be added inside a
152         # new extended partition. In order to align the swap partition, we
153         # need to create some extra space between the (aligned) primary and
154         # the swap.
155         new_end=$((new_end - 2048))
156     fi
157 fi
158
159 enlarge_partition "$SNF_IMAGE_DEV" "$last_part" "$last_part_type" "${new_end}s"
160
161 if [ $swap_num -gt 0 ]; then
162     swap_part="$swap_num:${swap_start}s:${swap_end}s:0:linux-swap(v1)::;"
163     if [ "$table_type" != "msdos" ]; then
164         swap_ptype="swap" # in gpt this is used as a partition name
165     elif [ $swap_num -ge 5 ]; then
166         if [ -z "$extended" ]; then
167             extended="0:$((swap_start - 2))s:${swap_end}s:0:::;"
168             create_partition "$SNF_IMAGE_DEV" "$extended" "extended"
169         fi
170         swap_ptype="logical"
171     else
172         swap_ptype="primary"
173     fi
174     create_partition "$SNF_IMAGE_DEV" "$swap_part" "$swap_ptype"
175 fi
176
177 # Inform the kernel about the changes
178 partprobe "$SNF_IMAGE_DEV"
179
180 exit 0
181
182 # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :