def test_set_partition_type_gpt(self):
     image = Image(self.img, MiB(6), VolumeSchema.gpt)
     image.partition(offset=MiB(1), size=MiB(1))
     self.assertEqual(len(image.disk.partitions), 1)
     image.set_parition_type(1, '21686148-6449-6E6F-744E-656564454649')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      '21686148-6449-6E6F-744E-656564454649')
     image.set_parition_type(1, '00000000-0000-0000-0000-0000DEADBEEF')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      '00000000-0000-0000-0000-0000DEADBEEF')
Exemple #2
0
 def test_set_partition_type_mbr(self):
     image = Image(self.img, MiB(6), VolumeSchema.mbr)
     image.partition(offset=MiB(1), size=MiB(1))
     self.assertEqual(len(image.disk.partitions), 1)
     image.set_parition_type(1, '83')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      '83')
     image.set_parition_type(1, 'da')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      'da')
 def test_set_partition_type_mbr(self):
     image = Image(self.img, MiB(6), VolumeSchema.mbr)
     image.partition(offset=MiB(1), size=MiB(1))
     self.assertEqual(len(image.disk.partitions), 1)
     image.set_parition_type(1, '83')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      '83')
     image.set_parition_type(1, 'da')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      'da')
Exemple #4
0
 def test_set_partition_type_gpt(self):
     image = Image(self.img, MiB(6), VolumeSchema.gpt)
     image.partition(offset=MiB(1), size=MiB(1))
     self.assertEqual(len(image.disk.partitions), 1)
     image.set_parition_type(1, '21686148-6449-6E6F-744E-656564454649')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      '21686148-6449-6E6F-744E-656564454649')
     image.set_parition_type(1, '00000000-0000-0000-0000-0000DEADBEEF')
     disk_info = image.diagnostics()
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['type'],
                      '00000000-0000-0000-0000-0000DEADBEEF')
Exemple #5
0
 def test_small_partition_size_and_offset(self):
     # LP: #1630709 - structure parts with size and offset < 1MB.
     image = Image(self.img, MiB(2), VolumeSchema.mbr)
     image.partition(offset=256, size=512)
     disk_info = image.diagnostics()
     # Even though the offset and size are set at 256 bytes and 512 bytes
     # respectively, the minimum granularity is one sector (i.e. 512
     # bytes).  The start and size returned by diagnostics() are in sector
     # units.
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['start'],
                      1)
     self.assertEqual(disk_info['partitiontable']['partitions'][0]['size'],
                      1)
 def _make_one_disk(self, imgfile, name, volume):
     part_id = 1
     # Create the image object for the selected volume schema
     image = Image(imgfile, volume.image_size, volume.schema)
     offset_writes = []
     part_offsets = {}
     # We first create all the needed partitions.
     # For regular core16 and core18 builds, this means creating all of the
     # defined partitions.  For core20 (the so called 'seeded images'), we
     # only create all the role-less partitions and mbr + system-seed.
     # The rest is created dynamically by snapd on first boot.
     for part in volume.structures:
         if part.name is not None:
             part_offsets[part.name] = part.offset
         if part.offset_write is not None:
             offset_writes.append((part.offset, part.offset_write))
         if (part.role is StructureRole.mbr or part.type == 'bare' or
                 self._should_skip_partition(part)):
             continue
         activate = False
         if (volume.schema is VolumeSchema.mbr and
                 part.role is StructureRole.system_boot):
             activate = True
         elif (volume.schema is VolumeSchema.gpt and
                 part.role is StructureRole.system_data and
                 part.name is None):
             part.name = 'writable'
         image.partition(part.offset, part.size, part.name, activate)
     # Now since we're done, we need to do a second pass to copy the data
     # and set all the partition types.  This needs to be done like this as
     # libparted's commit() operation resets type GUIDs to defaults and
     # clobbers things like hybrid MBR partitions.
     part_id = 1
     for i, part in enumerate(volume.structures):
         if self._should_skip_partition(part):
             continue
         image.copy_blob(volume.part_images[i],
                         bs=image.sector_size,
                         seek=part.offset // image.sector_size,
                         count=ceil(part.size / image.sector_size),
                         conv='notrunc')
         if part.role is StructureRole.mbr or part.type == 'bare':
             continue
         image.set_parition_type(part_id, part.type)
         part_id += 1
     for value, dest in offset_writes:
         # Decipher non-numeric offset_write values.
         if isinstance(dest, tuple):
             dest = part_offsets[dest[0]] + dest[1]
         image.write_value_at_offset(value // image.sector_size, dest)
 def test_small_partition_size_and_offset(self):
     # LP: #1630709 - structure parts with size and offset < 1MB.
     image = Image(self.img, MiB(2), VolumeSchema.mbr)
     image.partition(offset=256, size=512)
     disk_info = image.diagnostics()
     # Even though the offset and size are set at 256 bytes and 512 bytes
     # respectively, the minimum granularity is one sector (i.e. 512
     # bytes).  The start and size returned by diagnostics() are in sector
     # units.
     self.assertEqual(
         disk_info['partitiontable']['partitions'][0]['start'],
         1)
     self.assertEqual(
         disk_info['partitiontable']['partitions'][0]['size'],
         1)
Exemple #8
0
 def test_mbr_image_partitions(self):
     image = Image(self.img, MiB(2), VolumeSchema.mbr)
     # Create the first partition.
     image.partition(offset=image.sector(33),
                     size=image.sector(3000),
                     is_bootable=True)
     self.assertEqual(len(image.disk.partitions), 1)
     # Append the next one.
     image.partition(offset=image.sector(3033), size=image.sector(1000))
     self.assertEqual(len(image.disk.partitions), 2)
     image.set_parition_type(1, '83')
     image.set_parition_type(2, 'dd')
     disk_info = image.diagnostics()
     partitions = disk_info['partitiontable']
     # The device id is unpredictable.
     partitions.pop('id')
     # XXX: In later versions of pyparted the partitiontable structure
     #  added a 'grain' entry that we're not really interested in.
     #  Remove it so we can have the tests working for all series.
     if 'grain' in partitions:
         partitions.pop('grain')
     # Newer sfdisk displays an additional field of 'sectorsize' that
     # we're not really interested in.
     partitions.pop('sectorsize', None)
     self.assertEqual(
         partitions, {
             'label':
             'dos',
             'device':
             self.img,
             'unit':
             'sectors',
             'partitions': [{
                 'node': '{}1'.format(self.img),
                 'start': 33,
                 'size': 3000,
                 'type': '83',
                 'bootable': True,
             }, {
                 'node': '{}2'.format(self.img),
                 'start': 3033,
                 'size': 1000,
                 'type': 'dd',
             }],
         })
Exemple #9
0
 def test_gpt_image_partitions(self):
     image = Image(self.img, MiB(10), VolumeSchema.gpt)
     image.partition(offset=MiB(4), size=MiB(1), name='grub')
     self.assertEqual(len(image.disk.partitions), 1)
     image.partition(offset=MiB(5), size=MiB(4))
     self.assertEqual(len(image.disk.partitions), 2)
     image.set_parition_type(1, '21686148-6449-6E6F-744E-656564454649')
     image.set_parition_type(2, '0FC63DAF-8483-4772-8E79-3D69D8477DE4')
     # Use an external tool for checking the partition table to be sure
     # that it's indeed correct as suspected.
     disk_info = image.diagnostics()
     partitions = disk_info['partitiontable']
     # The device id is unpredictable.
     partitions.pop('id')
     # Newer sfdisk displays an additional field of 'sectorsize' that
     # we're not really interested in.
     partitions.pop('sectorsize', None)
     # The partition uuids as well.
     [p.pop('uuid') for p in partitions['partitions']]
     self.maxDiff = None
     self.assertEqual(
         partitions, {
             'label':
             'gpt',
             'device':
             self.img,
             'unit':
             'sectors',
             'firstlba':
             34,
             'lastlba':
             20446,
             'partitions': [{
                 'node': '{}1'.format(self.img),
                 'start': 8192,
                 'size': 2048,
                 'type': '21686148-6449-6E6F-744E-656564454649',
                 'name': 'grub',
             }, {
                 'node': '{}2'.format(self.img),
                 'start': 10240,
                 'size': 8192,
                 'type': '0FC63DAF-8483-4772-8E79-3D69D8477DE4',
             }],
         })
 def _make_one_disk(self, imgfile, name, volume):
     part_id = 1
     # Create the image object for the selected volume schema
     image = Image(imgfile, volume.image_size, volume.schema)
     offset_writes = []
     part_offsets = {}
     # We first create all the partitions.
     for part in volume.structures:
         if part.name is not None:
             part_offsets[part.name] = part.offset
         if part.offset_write is not None:
             offset_writes.append((part.offset, part.offset_write))
         if part.role is StructureRole.mbr or part.type == 'bare':
             continue
         activate = False
         if (volume.schema is VolumeSchema.mbr and
                 part.role is StructureRole.system_boot):
             activate = True
         elif (volume.schema is VolumeSchema.gpt and
                 part.role is StructureRole.system_data and
                 part.name is None):
             part.name = 'writable'
         image.partition(part.offset, part.size, part.name, activate)
     # Now since we're done, we need to do a second pass to copy the data
     # and set all the partition types.  This needs to be done like this as
     # libparted's commit() operation resets type GUIDs to defaults and
     # clobbers things like hybrid MBR partitions.
     part_id = 1
     for i, part in enumerate(volume.structures):
         image.copy_blob(volume.part_images[i],
                         bs=image.sector_size,
                         seek=part.offset // image.sector_size,
                         count=ceil(part.size / image.sector_size),
                         conv='notrunc')
         if part.role is StructureRole.mbr or part.type == 'bare':
             continue
         image.set_parition_type(part_id, part.type)
         part_id += 1
     for value, dest in offset_writes:
         # Decipher non-numeric offset_write values.
         if isinstance(dest, tuple):
             dest = part_offsets[dest[0]] + dest[1]
         image.write_value_at_offset(value // image.sector_size, dest)
 def test_mbr_image_partitions(self):
     image = Image(self.img, MiB(2), VolumeSchema.mbr)
     # Create the first partition.
     image.partition(offset=image.sector(33),
                     size=image.sector(3000),
                     is_bootable=True)
     self.assertEqual(len(image.disk.partitions), 1)
     # Append the next one.
     image.partition(offset=image.sector(3033),
                     size=image.sector(1000))
     self.assertEqual(len(image.disk.partitions), 2)
     image.set_parition_type(1, '83')
     image.set_parition_type(2, 'dd')
     disk_info = image.diagnostics()
     partitions = disk_info['partitiontable']
     # The device id is unpredictable.
     partitions.pop('id')
     # XXX: In later versions of pyparted the partitiontable structure
     #  added a 'grain' entry that we're not really interested in.
     #  Remove it so we can have the tests working for all series.
     if 'grain' in partitions:
         partitions.pop('grain')
     self.assertEqual(partitions, {
         'label': 'dos',
         'device': self.img,
         'unit': 'sectors',
         'partitions': [{
             'node': '{}1'.format(self.img),
             'start': 33,
             'size': 3000,
             'type': '83',
             'bootable': True,
             }, {
             'node': '{}2'.format(self.img),
             'start': 3033,
             'size': 1000,
             'type': 'dd',
             }],
         })
Exemple #12
0
 def test_mbr_image_partitions(self):
     image = Image(self.img, MiB(2), VolumeSchema.mbr)
     # Create the first partition.
     image.partition(offset=image.sector(33),
                     size=image.sector(3000),
                     is_bootable=True)
     self.assertEqual(len(image.disk.partitions), 1)
     # Append the next one.
     image.partition(offset=image.sector(3033), size=image.sector(1000))
     self.assertEqual(len(image.disk.partitions), 2)
     image.set_parition_type(1, '83')
     image.set_parition_type(2, 'dd')
     disk_info = image.diagnostics()
     partitions = disk_info['partitiontable']
     # The device id is unpredictable.
     partitions.pop('id')
     self.assertEqual(
         partitions, {
             'label':
             'dos',
             'device':
             self.img,
             'unit':
             'sectors',
             'partitions': [{
                 'node': '{}1'.format(self.img),
                 'start': 33,
                 'size': 3000,
                 'type': '83',
                 'bootable': True,
             }, {
                 'node': '{}2'.format(self.img),
                 'start': 3033,
                 'size': 1000,
                 'type': 'dd',
             }],
         })
 def test_gpt_image_partitions(self):
     image = Image(self.img, MiB(10), VolumeSchema.gpt)
     image.partition(offset=MiB(4), size=MiB(1), name='grub')
     self.assertEqual(len(image.disk.partitions), 1)
     image.partition(offset=MiB(5), size=MiB(4))
     self.assertEqual(len(image.disk.partitions), 2)
     image.set_parition_type(1, '21686148-6449-6E6F-744E-656564454649')
     image.set_parition_type(2, '0FC63DAF-8483-4772-8E79-3D69D8477DE4')
     # Use an external tool for checking the partition table to be sure
     # that it's indeed correct as suspected.
     disk_info = image.diagnostics()
     partitions = disk_info['partitiontable']
     # The device id is unpredictable.
     partitions.pop('id')
     # The partition uuids as well.
     [p.pop('uuid') for p in partitions['partitions']]
     self.maxDiff = None
     self.assertEqual(partitions, {
         'label': 'gpt',
         'device': self.img,
         'unit': 'sectors',
         'firstlba': 34,
         'lastlba': 20446,
         'partitions': [{
             'node': '{}1'.format(self.img),
             'start': 8192,
             'size': 2048,
             'type': '21686148-6449-6E6F-744E-656564454649',
             'name': 'grub',
             }, {
             'node': '{}2'.format(self.img),
             'start': 10240,
             'size': 8192,
             'type': '0FC63DAF-8483-4772-8E79-3D69D8477DE4',
             }],
         })
Exemple #14
0
 def test_partition(self):
     # Create BIOS boot partition
     #
     # The partition is 1MiB in size, as recommended by various
     # partitioning guides.  The actual required size is much, much
     # smaller.
     image = Image(self.img, MiB(10))
     image.partition(new='1:4MiB:+1MiB')
     image.partition(typecode='1:21686148-6449-6E6F-744E-656564454649')
     image.partition(change_name='1:grub')
     mbr = image.diagnostics(Diagnostics.mbr)
     # We should see that the disk size is 10MiB.
     self.assertRegex(mbr, '10.0 MiB')
     gpt = image.diagnostics(Diagnostics.gpt)
     # We should see that there is 1 partition named grub.
     self.assertRegex(gpt, 'grub')
Exemple #15
0
image = Image('img', GiB(4))

# Install GRUB to MBR
# TODO: this has to be represented in the image.yaml
# NOTE: the boot.img has to be a part of the gadget snap itself
# FIXME: embed a pointer to 2nd stage in bios-boot partition
image.copy_blob('blogs/img.mbr', bs=446, count=1, conv='notrunc')

# Create BIOS boot partition
#
# The partition is 1MiB in size, as recommended by various partitioning guides.
# The actual required size is much, much smaller.
#
# https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html#BIOS-installation
image.partition(new='1:4MiB:+1MiB')
image.partition(typecode='1:21686148-6449-6E6F-744E-656564454649')
image.partition(change_name='1:grub')
image.copy_blob('blobs/img.bios-boot',
                bs='1MiB',
                seek=4,
                count=1,
                conv='notrunc')

# Create EFI system partition
#
# TODO: switch to 512MiB as recommended by the standard
image.partition(new='2:5MiB:+64MiB')
image.partition(typecode='2:C12A7328-F81F-11D2-BA4B-00A0C93EC93B')
image.partition(change_name='2:system-boot')
image.copy_blob('blobs/img.system-boot',
Exemple #16
0
 def make_disk(self):
     self.disk_img = os.path.join(self.images, 'disk.img')
     image = Image(self.disk_img, GiB(4))
     # Create BIOS boot partition
     #
     # The partition is 1MiB in size, as recommended by various
     # partitioning guides.  The actual required size is much, much
     # smaller.
     #
     # https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html#BIOS-installation
     # image.partition(new='1:4MiB:+1MiB')
     # image.partition(typecode='1:21686148-6449-6E6F-744E-656564454649')
     # image.partition(change_name='1:grub')
     # image.copy_blob(self.boot_img,
     #                 bs='1MiB', seek=4, count=1, conv='notrunc')
     # Create EFI system partition
     #
     # TODO: switch to 512MiB as recommended by the standard
     image.partition(new='2:5MiB:+64MiB')
     image.partition(typecode='2:C12A7328-F81F-11D2-BA4B-00A0C93EC93B')
     image.partition(change_name='2:system-boot')
     image.copy_blob(self.boot_img,
                     bs='1MB', seek=4, count=64, conv='notrunc')
     # Create main snappy writable partition
     image.partition(new='3:72MiB:+3646MiB')
     image.partition(typecode='3:0FC63DAF-8483-4772-8E79-3D69D8477DE4')
     image.partition(change_name='3:writable')
     image.copy_blob(self.root_img,
                     bs='1MiB', seek=72, count=3646, conv='notrunc')
     self._next.append(self.finish)
Exemple #17
0
image = Image('img', GiB(4))

# Install GRUB to MBR
# TODO: this has to be represented in the image.yaml
# NOTE: the boot.img has to be a part of the gadget snap itself
# FIXME: embed a pointer to 2nd stage in bios-boot partition
image.copy_blob('blogs/img.mbr', bs=446, count=1, conv='notrunc')

# Create BIOS boot partition
#
# The partition is 1MiB in size, as recommended by various partitioning guides.
# The actual required size is much, much smaller.
#
# https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html#BIOS-installation
image.partition(new='1:4MiB:+1MiB')
image.partition(typecode='1:21686148-6449-6E6F-744E-656564454649')
image.partition(change_name='1:grub')
image.copy_blob('blobs/img.bios-boot',
                bs='1MiB', seek=4, count=1, conv='notrunc')

# Create EFI system partition
#
# TODO: switch to 512MiB as recommended by the standard
image.partition(new='2:5MiB:+64MiB')
image.partition(typecode='2:C12A7328-F81F-11D2-BA4B-00A0C93EC93B')
image.partition(change_name='2:system-boot')
image.copy_blob('blobs/img.system-boot',
                bs='1MB', seek=4, count=64, conv='notrunc')

# Create main snappy writable partition