Remove the PartitionGap class, it's way too much of a hassle to work with

Instead pad_start and pad_end have been introduced
This commit is contained in:
Anders Ingemann 2015-01-19 23:11:19 +01:00
parent 05006f2d83
commit a62ce1705a
11 changed files with 53 additions and 105 deletions

View file

@ -1,6 +1,5 @@
from abc import ABCMeta
from abc import abstractmethod
from ..partitions.gap import PartitionGap
from bootstrapvz.common.tools import log_check_call
from bootstrapvz.common.fsm_proxy import FSMProxy
from ..exceptions import PartitionError
@ -76,8 +75,6 @@ class AbstractPartitionMap(FSMProxy):
.format(device_path=volume.device_path))
log_check_call(['kpartx', '-as', volume.device_path])
mappable_partitions = filter(lambda p: not isinstance(p, PartitionGap), self.partitions)
import os.path
# Run through the kpartx output and map the paths to the partitions
for mapping in mappings:
@ -86,12 +83,10 @@ class AbstractPartitionMap(FSMProxy):
raise PartitionError('Unable to parse kpartx output: ' + mapping)
partition_path = os.path.join('/dev/mapper', match.group('name'))
p_idx = int(match.group('p_idx')) - 1
mappable_partitions[p_idx].map(partition_path)
self.partitions[p_idx].map(partition_path)
# Check if any partition was not mapped
for idx, partition in enumerate(self.partitions):
if isinstance(partition, PartitionGap):
continue
if partition.fsm.current not in ['mapped', 'formatted']:
raise PartitionError('kpartx did not map partition #' + str(partition.get_index()))
@ -117,8 +112,6 @@ class AbstractPartitionMap(FSMProxy):
volume = event.volume
# Run through all partitions before unmapping and make sure they can all be unmapped
for partition in self.partitions:
if isinstance(partition, PartitionGap):
continue
if partition.fsm.cannot('unmap'):
msg = 'The partition {partition} prevents the unmap procedure'.format(partition=partition)
raise PartitionError(msg)
@ -126,6 +119,4 @@ class AbstractPartitionMap(FSMProxy):
log_check_call(['kpartx', '-ds', volume.device_path])
# Call unmap on all partitions
for partition in self.partitions:
if isinstance(partition, PartitionGap):
continue
partition.unmap()

View file

@ -1,7 +1,6 @@
from abstract import AbstractPartitionMap
from ..partitions.gpt import GPTPartition
from ..partitions.gpt_swap import GPTSwapPartition
from ..partitions.gap import PartitionGap
from bootstrapvz.common.tools import log_check_call
@ -24,57 +23,60 @@ class GPTPartitionMap(AbstractPartitionMap):
def last_partition():
return self.partitions[-1] if len(self.partitions) > 0 else None
# The first 34 sectors are reserved for the primary GPT
primary_gpt = PartitionGap(Sectors(34, sector_size), last_partition())
self.partitions.append(primary_gpt)
if bootloader == 'grub':
# If we are using the grub bootloader we need to create an unformatted partition
# at the beginning of the map. Its size is 1007kb, which seems to be chosen so that
# gpt_primary + grub = 1024KiB
# So lets just specify grub size as 1MiB - 34 sectors
# primary gpt + grub = 1024KiB
# The 34 sectors for the primary gpt will be subtracted later on
from ..partitions.unformatted import UnformattedPartition
grub_size = Sectors('1MiB', sector_size) - primary_gpt.size
self.grub_boot = UnformattedPartition(grub_size, last_partition())
self.grub_boot = UnformattedPartition(Sectors('1MiB', sector_size), last_partition())
self.partitions.append(self.grub_boot)
# Offset all partitions by 1 sector.
# parted in jessie has changed and no longer allows
# gpt partitions to be right next to each other.
partition_gap = Sectors(1, sector_size)
# The boot and swap partitions are optional
if 'boot' in data:
self.boot = GPTPartition(Sectors(data['boot']['size'], sector_size),
data['boot']['filesystem'], data['boot'].get('format_command', None),
'boot', last_partition())
# Offset all partitions by 1 sector.
# parted in jessie has changed and no longer allows partitions to be right next to each other.
self.boot.offset = Sectors(1, sector_size)
self.boot.size -= self.boot.offset
if self.boot.previous is not None:
# No need to pad if this is the first partition
self.boot.pad_start += partition_gap
self.boot.size -= partition_gap
self.partitions.append(self.boot)
if 'swap' in data:
self.swap = GPTSwapPartition(Sectors(data['swap']['size'], sector_size), last_partition())
self.swap.offset = Sectors(1, sector_size)
self.swap.size -= self.swap.offset
if self.swap.previous is not None:
self.swap.pad_start += partition_gap
self.swap.size -= partition_gap
self.partitions.append(self.swap)
self.root = GPTPartition(Sectors(data['root']['size'], sector_size),
data['root']['filesystem'], data['root'].get('format_command', None),
'root', last_partition())
self.root.offset = Sectors(1, sector_size)
self.root.size -= self.root.offset
if self.root.previous is not None:
self.root.pad_start += partition_gap
self.root.size -= partition_gap
self.partitions.append(self.root)
# The last 34 sectors are reserved for the secondary GPT
secondary_gpt = PartitionGap(Sectors(34, sector_size), last_partition())
self.partitions.append(secondary_gpt)
# The first and last 34 sectors are reserved for the primary/secondary GPT
primary_gpt_size = Sectors(34, sector_size)
self.partitions[0].pad_start += primary_gpt_size
self.partitions[0].size -= primary_gpt_size
# reduce the size of the root partition so that the overall volume size is not exceeded
self.root.size -= primary_gpt.size + secondary_gpt.size
if hasattr(self, 'grub_boot'):
self.root.size -= self.grub_boot.size
secondary_gpt_size = Sectors(34, sector_size)
self.partitions[-1].pad_end += secondary_gpt_size
self.partitions[-1].size -= secondary_gpt_size
# Set the boot flag on the right partition
if hasattr(self, 'grub_boot'):
# Mark the partition as a bios_grub partition
# Mark the grub partition as a bios_grub partition
self.grub_boot.flags.append('bios_grub')
else:
# Mark the boot partition, or root, if boot does not exist
# Not using grub, mark the boot partition or root as bootable
getattr(self, 'boot', self.root).flags.append('legacy_boot')
super(GPTPartitionMap, self).__init__(bootloader)
@ -89,6 +91,4 @@ class GPTPartitionMap(AbstractPartitionMap):
'--', 'mklabel', 'gpt'])
# Create the partitions
for partition in self.partitions:
if isinstance(partition, PartitionGap):
continue
partition.create(volume)

View file

@ -1,7 +1,6 @@
from abstract import AbstractPartitionMap
from ..partitions.msdos import MSDOSPartition
from ..partitions.msdos_swap import MSDOSSwapPartition
from ..partitions.gap import PartitionGap
from bootstrapvz.common.tools import log_check_call
@ -31,9 +30,11 @@ class MSDOSPartitionMap(AbstractPartitionMap):
data['boot']['filesystem'], data['boot'].get('format_command', None),
last_partition())
self.partitions.append(self.boot)
if 'swap' in data:
self.swap = MSDOSSwapPartition(Sectors(data['swap']['size'], sector_size), last_partition())
self.partitions.append(self.swap)
self.root = MSDOSPartition(Sectors(data['root']['size'], sector_size),
data['root']['filesystem'], data['root'].get('format_command', None),
last_partition())
@ -47,16 +48,18 @@ class MSDOSPartitionMap(AbstractPartitionMap):
# The MBR offset is included in the grub offset, so if we don't use grub
# we should reduce the size of the first partition and move it by only 512 bytes.
if bootloader == 'grub':
offset = Sectors('2MiB', sector_size)
mbr_offset = Sectors('2MiB', sector_size)
else:
offset = Sectors('512B', sector_size)
mbr_offset = Sectors('512B', sector_size)
self.partitions[0].offset += offset
self.partitions[0].size -= offset
self.partitions[0].pad_start += mbr_offset
self.partitions[0].size -= mbr_offset
# Leave the last sector unformatted
# parted in jessie thinks that a partition 10 sectors in size
# goes from sector 0 to sector 9 (instead of 0 to 10)
self.partitions[-1].pad_end += 1
self.partitions[-1].size -= 1
self.partitions.append(PartitionGap(Sectors(1, sector_size), last_partition()))
super(MSDOSPartitionMap, self).__init__(bootloader)
@ -68,6 +71,4 @@ class MSDOSPartitionMap(AbstractPartitionMap):
'--', 'mklabel', 'msdos'])
# Create the partitions
for partition in self.partitions:
if isinstance(partition, PartitionGap):
continue
partition.create(volume)

View file

@ -1,5 +1,6 @@
from abc import ABCMeta
from abc import abstractmethod
from bootstrapvz.common.sectors import Sectors
from bootstrapvz.common.tools import log_check_call
from bootstrapvz.common.fsm_proxy import FSMProxy
@ -27,6 +28,9 @@ class AbstractPartition(FSMProxy):
self.size = size
self.filesystem = filesystem
self.format_command = format_command
# Initialize the start & end padding to 0 sectors, may be changed later
self.pad_start = Sectors(0, size.sector_size)
self.pad_end = Sectors(0, size.sector_size)
# Path to the partition
self.device_path = None
# Dictionary with mount points as keys and Mount objects as values
@ -55,7 +59,7 @@ class AbstractPartition(FSMProxy):
:return: The end of the partition
:rtype: Sectors
"""
return self.get_start() + self.size
return self.get_start() + self.pad_start + self.size + self.pad_end
def _before_format(self, e):
"""Formats the partition

View file

@ -1,4 +1,5 @@
from abstract import AbstractPartition
from bootstrapvz.common.sectors import Sectors
class BasePartition(AbstractPartition):
@ -25,12 +26,9 @@ class BasePartition(AbstractPartition):
:param list format_command: Optional format command, valid variables are fs, device_path and size
:param BasePartition previous: The partition that preceeds this one
"""
# By saving the previous partition we have
# a linked list that partitions can go backwards in to find the first partition.
# By saving the previous partition we have a linked list
# that partitions can go backwards in to find the first partition.
self.previous = previous
from bootstrapvz.common.sectors import Sectors
# Initialize the offset to 0 sectors, may be changed later
self.offset = Sectors(0, size.sector_size)
# List of flags that parted should put on the partition
self.flags = []
super(BasePartition, self).__init__(size, filesystem, format_command)
@ -62,11 +60,9 @@ class BasePartition(AbstractPartition):
:rtype: Sectors
"""
if self.previous is None:
# If there is no previous partition, this partition begins at the offset
return self.offset
return Sectors(0, self.size.sector_size)
else:
# Get the end of the previous partition and add the offset of this partition
return self.previous.get_end() + self.offset
return self.previous.get_end()
def map(self, device_path):
"""Maps the partition to a device_path
@ -81,8 +77,8 @@ class BasePartition(AbstractPartition):
from bootstrapvz.common.tools import log_check_call
# The create command is failry simple, start and end are just Bytes objects coerced into strings
create_command = ('mkpart primary {start} {end}'
.format(start=str(self.get_start()),
end=str(self.get_end())))
.format(start=str(self.get_start() + self.pad_start),
end=str(self.get_end() - self.pad_end)))
# Create the partition
log_check_call(['parted', '--script', '--align', 'none', e.volume.device_path,
'--', create_command])

View file

@ -1,34 +0,0 @@
from base import BasePartition
class PartitionGap(BasePartition):
"""Represents a non-existent partition
A gap in the partitionmap
"""
# The states for our state machine. It can neither be create nor mapped.
events = []
def __init__(self, size, previous):
"""
:param Bytes size: Size of the partition
:param BasePartition previous: The partition that preceeds this one
"""
super(PartitionGap, self).__init__(size, None, None, previous)
def get_index(self):
"""Gets the index of this partition in the partition map
Note that PartitionGap.get_index() simply returns the index of the
previous partition, since a gap does not count towards
the number of partitions.
If there is no previous partition 0 will be returned
(although partitions really are 1 indexed)
:return: The index of the partition in the partition map
:rtype: int
"""
if self.previous is None:
return 0
else:
# Recursive call to the previous partition, walking up the chain...
return self.previous.get_index()

View file

@ -12,5 +12,4 @@ class SinglePartition(AbstractPartition):
:rtype: Sectors
"""
from bootstrapvz.common.sectors import Sectors
# On an unpartitioned volume there is no offset and no previous partition
return Sectors(0, self.size.sector_size)

View file

@ -25,9 +25,8 @@ class Format(Task):
@classmethod
def run(cls, info):
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
from bootstrapvz.base.fs.partitions.gap import PartitionGap
for partition in info.volume.partition_map.partitions:
if isinstance(partition, (UnformattedPartition, PartitionGap)):
if isinstance(partition, UnformattedPartition):
continue
partition.format()
@ -40,11 +39,10 @@ class TuneVolumeFS(Task):
@classmethod
def run(cls, info):
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
from bootstrapvz.base.fs.partitions.gap import PartitionGap
import re
# Disable the time based filesystem check
for partition in info.volume.partition_map.partitions:
if isinstance(partition, (UnformattedPartition, PartitionGap)):
if isinstance(partition, UnformattedPartition):
continue
if re.match('^ext[2-4]$', partition.filesystem) is not None:
log_check_call(['tune2fs', '-i', '0', partition.device_path])

View file

@ -68,10 +68,7 @@ class InstallGrub_1_99(Task):
with open(device_map_path, 'w') as device_map:
device_map.write('(hd0) {device_path}\n'.format(device_path=device_path))
if not isinstance(p_map, partitionmaps.none.NoPartitions):
from bootstrapvz.base.fs.partitions.gap import PartitionGap
for idx, partition in enumerate(info.volume.partition_map.partitions):
if isinstance(partition, PartitionGap):
continue
device_map.write('(hd0,{prefix}{idx}) {device_path}\n'
.format(device_path=partition.device_path,
prefix=partition_prefix,

View file

@ -84,12 +84,9 @@ def set_fs_states(volume):
if not isinstance(p_map, NoPartitions):
p_map.fsm.current = 'unmapped'
from bootstrapvz.base.fs.partitions.gap import PartitionGap
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
from bootstrapvz.base.fs.partitions.single import SinglePartition
for partition in p_map.partitions:
if isinstance(partition, PartitionGap):
continue
if isinstance(partition, UnformattedPartition):
partition.fsm.current = 'unmapped'
continue

View file

@ -20,7 +20,6 @@ supported_classes = ['bootstrapvz.base.manifest.Manifest',
'bootstrapvz.base.fs.partitions.msdos_swap.MSDOSSwapPartition',
'bootstrapvz.base.fs.partitions.single.SinglePartition',
'bootstrapvz.base.fs.partitions.unformatted.UnformattedPartition',
'bootstrapvz.base.fs.partitions.gap.PartitionGap',
'bootstrapvz.common.bytes.Bytes',
'bootstrapvz.common.sectors.Sectors',
]