self.out.output("Shrinking image (this may take a while)...", False)
+ sector_size = self.g.blockdev_getss(self.guestfs_device)
+
last_part = None
fstype = None
while True:
part_del(last_part['part_num'])
continue
- self.meta['SIZE'] = last_part['part_end'] + 1
+ # Most disk manipulation programs leave 2048 sectors after the last
+ # partition
+ new_size = last_part['part_end'] + 1 + 2048 * sector_size
+ self.meta['SIZE'] = min(self.meta['SIZE'], new_size)
break
if not re.match("ext[234]", fstype):
block_cnt = int(
filter(lambda x: x[0] == 'Block count', out)[0][1])
- sector_size = self.g.blockdev_getss(self.guestfs_device)
start = last_part['part_start'] / sector_size
end = start + (block_size * block_cnt) / sector_size - 1
part_set_id(last_part['part_num'], last_part['id'])
new_size = (end + 1) * sector_size
- self.out.success("new size is %dMB" % ((new_size + MB - 1) // MB))
+
+ assert (new_size <= self.meta['SIZE'])
if self.meta['PARTITION_TABLE'] == 'gpt':
ptable = GPTPartitionTable(self.real_device)
- self.meta['SIZE'] = ptable.shrink(new_size)
+ self.meta['SIZE'] = ptable.shrink(new_size, self.meta['SIZE'])
else:
- self.meta['SIZE'] = new_size
+ self.meta['SIZE'] = min(new_size + 2048 * sector_size,
+ self.meta['SIZE'])
+
+ self.out.success("new size is %dMB" %
+ ((self.meta['SIZE'] + MB - 1) // MB))
return self.meta['SIZE']
"""Returns the payload size of GPT partitioned device."""
return (self.primary.backup_lba + 1) * BLOCKSIZE
- def shrink(self, size):
+ def shrink(self, size, old_size):
"""Move the secondary GPT Header entries to the address specified by
size parameter.
"""
- if size == self.size():
- return size
- assert size < self.size()
+ # Most partition manipulation programs leave 2048 sector after the last
+ # partition
+ aligned = size + 2048 * BLOCKSIZE
+
+ # new_size is at least: size + Partition Entries + Secondary GPT Header
+ new_size = aligned if aligned <= old_size else \
+ size + len(self.part_entries) + BLOCKSIZE
+
+ assert new_size <= old_size, "The secodary GPT fits in the device"
+
+ if new_size == self.size():
+ return new_size
- # new_size = size + Partition Entries + Secondary GPT Header
- new_size = size + len(self.part_entries) + BLOCKSIZE
- new_size = ((new_size + 4095) // 4096) * 4096 # align to 4K
lba_count = new_size // BLOCKSIZE
# Correct MBR