Revision 9666a511

b/image_creator/disk.py
320 320

  
321 321
        self.out.output("Shrinking image (this may take a while)...", False)
322 322

  
323
        sector_size = self.g.blockdev_getss(self.guestfs_device)
324

  
323 325
        last_part = None
324 326
        fstype = None
325 327
        while True:
......
336 338
                part_del(last_part['part_num'])
337 339
                continue
338 340

  
339
            self.meta['SIZE'] = last_part['part_end'] + 1
341
            # Most disk manipulation programs leave 2048 sectors after the last
342
            # partition
343
            new_size = last_part['part_end'] + 1 + 2048 * sector_size
344
            self.meta['SIZE'] = min(self.meta['SIZE'], new_size)
340 345
            break
341 346

  
342 347
        if not re.match("ext[234]", fstype):
......
353 358
        block_cnt = int(
354 359
            filter(lambda x: x[0] == 'Block count', out)[0][1])
355 360

  
356
        sector_size = self.g.blockdev_getss(self.guestfs_device)
357 361
        start = last_part['part_start'] / sector_size
358 362
        end = start + (block_size * block_cnt) / sector_size - 1
359 363

  
......
398 402
                part_set_id(last_part['part_num'], last_part['id'])
399 403

  
400 404
        new_size = (end + 1) * sector_size
401
        self.out.success("new size is %dMB" % ((new_size + MB - 1) // MB))
405

  
406
        assert (new_size <= self.meta['SIZE'])
402 407

  
403 408
        if self.meta['PARTITION_TABLE'] == 'gpt':
404 409
            ptable = GPTPartitionTable(self.real_device)
405
            self.meta['SIZE'] = ptable.shrink(new_size)
410
            self.meta['SIZE'] = ptable.shrink(new_size, self.meta['SIZE'])
406 411
        else:
407
            self.meta['SIZE'] = new_size
412
            self.meta['SIZE'] = min(new_size + 2048 * sector_size,
413
                                    self.meta['SIZE'])
414

  
415
        self.out.success("new size is %dMB" %
416
                         ((self.meta['SIZE'] + MB - 1) // MB))
408 417

  
409 418
        return self.meta['SIZE']
410 419

  
b/image_creator/gpt.py
255 255
        """Returns the payload size of GPT partitioned device."""
256 256
        return (self.primary.backup_lba + 1) * BLOCKSIZE
257 257

  
258
    def shrink(self, size):
258
    def shrink(self, size, old_size):
259 259
        """Move the secondary GPT Header entries to the address specified by
260 260
        size parameter.
261 261
        """
262
        if size == self.size():
263
            return size
264 262

  
265
        assert size < self.size()
263
        # Most partition manipulation programs leave 2048 sector after the last
264
        # partition
265
        aligned = size + 2048 * BLOCKSIZE
266

  
267
        # new_size is at least: size + Partition Entries + Secondary GPT Header
268
        new_size = aligned if aligned <= old_size else \
269
                   size + len(self.part_entries) + BLOCKSIZE
270

  
271
        assert new_size <= old_size, "The secodary GPT fits in the device"
272

  
273
        if new_size == self.size():
274
            return new_size
266 275

  
267
        # new_size = size + Partition Entries + Secondary GPT Header
268
        new_size = size + len(self.part_entries) + BLOCKSIZE
269
        new_size = ((new_size + 4095) // 4096) * 4096  # align to 4K
270 276
        lba_count = new_size // BLOCKSIZE
271 277

  
272 278
        # Correct MBR

Also available in: Unified diff