From: Nikos Skalkotos Date: Thu, 26 Apr 2012 16:55:53 +0000 (+0300) Subject: Add support for GUID Partition Tables X-Git-Tag: v0.1~98 X-Git-Url: https://code.grnet.gr/git/snf-image-creator/commitdiff_plain/331aa0ec4a14fb2484e819961222297cb022e190?ds=sidebyside Add support for GUID Partition Tables --- diff --git a/image_creator/disk.py b/image_creator/disk.py index 287921a..79ce422 100644 --- a/image_creator/disk.py +++ b/image_creator/disk.py @@ -33,7 +33,7 @@ from image_creator.util import get_command from image_creator.util import warn, progress, success, output, FatalError - +from image_creator.gpt import GPTPartitionTable import stat import os import tempfile @@ -200,6 +200,9 @@ class DiskDevice(object): raise FatalError("Multiple operating systems found." "We only support images with one filesystem.") self.root = roots[0] + self.gdev = self.g.part_to_dev(self.root) + self.parttype = self.g.part_get_parttype(self.gdev) + self.ostype = self.g.inspect_get_type(self.root) self.distro = self.g.inspect_get_distro(self.root) success('found a(n) %s system' % self.distro) @@ -256,23 +259,21 @@ class DiskDevice(object): """ output("Shrinking image (this may take a while)...", False) - dev = self.g.part_to_dev(self.root) - parttype = self.g.part_get_parttype(dev) - if parttype != 'msdos': + if self.parttype not in 'msdos' 'gpt': raise FatalError("You have a %s partition table. " - "Only msdos partitions are supported" % parttype) + "Only msdos and gpt partitions are supported" % self.parttype) - last_partition = self.g.part_list(dev)[-1] + last_partition = self.g.part_list(self.gdev)[-1] if last_partition['part_num'] > 4: raise FatalError("This disk contains logical partitions. " "Only primary partitions are supported.") - part_dev = "%s%d" % (dev, last_partition['part_num']) + part_dev = "%s%d" % (self.gdev, last_partition['part_num']) fs_type = self.g.vfs_type(part_dev) if not re.match("ext[234]", fs_type): warn("Don't know how to resize %s partitions." % vfs_type) - return + return self.size() self.g.e2fsck_f(part_dev) self.g.resize2fs_M(part_dev) @@ -283,17 +284,22 @@ class DiskDevice(object): block_cnt = int( filter(lambda x: x[0] == 'Block count', out)[0][1]) - sector_size = self.g.blockdev_getss(dev) + sector_size = self.g.blockdev_getss(self.gdev) start = last_partition['part_start'] / sector_size end = start + (block_size * block_cnt) / sector_size - 1 - self.g.part_del(dev, last_partition['part_num']) - self.g.part_add(dev, 'p', start, end) + self.g.part_del(self.gdev, last_partition['part_num']) + self.g.part_add(self.gdev, 'p', start, end) new_size = (end + 1) * sector_size success("new image size is %dMB" % ((new_size + 2 ** 20 - 1) // 2 ** 20)) + + if self.parttype == 'gpt': + ptable = GPTPartitionTable(self.device) + return ptable.shrink(new_size) + return new_size def size(self): @@ -302,10 +308,16 @@ class DiskDevice(object): The size returned by this method is the size of the space occupied by the partitions (including the space before the first partition). """ - dev = self.g.part_to_dev(self.root) - last = self.g.part_list(dev)[-1] - return last['part_end'] + 1 + if self.parttype == 'msdos': + dev = self.g.part_to_dev(self.root) + last = self.g.part_list(dev)[-1] + return last['part_end'] + 1 + elif self.parttype == 'gpt': + ptable = GPTPartitionTable(self.device) + return ptable.size() + else: + raise FatalError("Unsupported partition table type: %s" % parttype) def dump(self, outfile): """Dumps the content of device into a file. diff --git a/image_creator/gpt.py b/image_creator/gpt.py new file mode 100644 index 0000000..f853058 --- /dev/null +++ b/image_creator/gpt.py @@ -0,0 +1,286 @@ +# Copyright 2012 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + +import struct +import sys +import uuid +import binascii + +BLOCKSIZE = 512 + + +class MBR(object): + class Partition(object): + format = "> 2) & 0xC0 | sector + byte2 = cylinder & 0xff + + return struct.pack('