bootstrap-vz/bootstrapvz/common/tasks/filesystem.py

276 lines
9.2 KiB
Python
Raw Normal View History

from bootstrapvz.base import Task
from .. import phases
from ..tools import log_check_call
import bootstrap
import host
import volume
2013-06-27 00:11:09 +02:00
class AddRequiredCommands(Task):
description = 'Adding commands required for formatting'
phase = phases.validation
successors = [host.CheckExternalCommands]
@classmethod
def run(cls, info):
if 'xfs' in (p.filesystem for p in info.volume.partition_map.partitions):
info.host_dependencies['mkfs.xfs'] = 'xfsprogs'
class Format(Task):
description = 'Formatting the volume'
phase = phases.volume_preparation
2013-06-27 00:11:09 +02:00
@classmethod
def run(cls, info):
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
for partition in info.volume.partition_map.partitions:
if isinstance(partition, UnformattedPartition):
continue
partition.format()
2013-06-27 00:11:09 +02:00
class TuneVolumeFS(Task):
description = 'Tuning the bootstrap volume filesystem'
phase = phases.volume_preparation
predecessors = [Format]
@classmethod
def run(cls, info):
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
import re
# Disable the time based filesystem check
for partition in info.volume.partition_map.partitions:
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])
2013-06-27 00:11:09 +02:00
class AddXFSProgs(Task):
description = 'Adding `xfsprogs\' to the image packages'
phase = phases.preparation
2013-06-27 00:11:09 +02:00
@classmethod
def run(cls, info):
info.packages.add('xfsprogs')
class CreateMountDir(Task):
description = 'Creating mountpoint for the root partition'
phase = phases.volume_mounting
@classmethod
def run(cls, info):
import os
info.root = os.path.join(info.workspace, 'root')
os.makedirs(info.root)
class MountRoot(Task):
description = 'Mounting the root partition'
phase = phases.volume_mounting
predecessors = [CreateMountDir]
@classmethod
def run(cls, info):
info.volume.partition_map.root.mount(destination=info.root)
class CreateBootMountDir(Task):
description = 'Creating mountpoint for the boot partition'
phase = phases.volume_mounting
predecessors = [MountRoot]
@classmethod
def run(cls, info):
import os.path
os.makedirs(os.path.join(info.root, 'boot'))
class MountBoot(Task):
description = 'Mounting the boot partition'
phase = phases.volume_mounting
predecessors = [CreateBootMountDir]
@classmethod
def run(cls, info):
p_map = info.volume.partition_map
p_map.root.add_mount(p_map.boot, 'boot')
class MountAdditional(Task):
description = 'Mounting additional partitions'
phase = phases.volume_mounting
predecessors = [MountRoot]
@classmethod
def run(cls, info):
import os
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
from bootstrapvz.base.fs.partitions.single import SinglePartition
2017-02-01 20:16:23 +01:00
def is_additional(partition):
return (not isinstance(partition, (UnformattedPartition, SinglePartition)) and
2017-02-01 20:16:23 +01:00
partition.name not in ["boot", "swap", "root"])
p_map = info.volume.partition_map
2017-02-01 18:38:37 +01:00
partitions = p_map.partitions
2017-02-01 20:16:23 +01:00
for partition in sorted(
filter(is_additional, partitions),
key=lambda partition: len(partition.name)):
2017-01-31 21:45:40 +01:00
partition = getattr(p_map, partition.name)
os.makedirs(os.path.join(info.root, partition.name))
if partition.mountopts is None:
p_map.root.add_mount(getattr(p_map, partition.name), partition.name)
else:
p_map.root.add_mount(getattr(p_map, partition.name), partition.name, ['--options'] + partition.mountopts)
class ChmodMountDirs(Task):
description = 'Chmod mount dirs'
phase = phases.volume_mounting
predecessors = [MountAdditional]
@classmethod
def run(cls, info):
import os
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
from bootstrapvz.base.fs.partitions.single import SinglePartition
def has_mode(partition):
return (not isinstance(partition, (UnformattedPartition, SinglePartition)) and
'mode' in info.manifest.volume['partitions'][partition.name] and
info.manifest.volume['partitions'][partition.name]['mode'] is not None)
p_map = info.volume.partition_map
partitions = p_map.partitions
for partition in list(
filter(has_mode, partitions)):
partition = getattr(p_map, partition.name)
mode_str = info.manifest.volume['partitions'][partition.name]['mode']
mode = int(mode_str, 8)
os.chmod(os.path.join(info.root, partition.name), mode)
2013-07-01 20:48:51 +02:00
class MountSpecials(Task):
description = 'Mounting special block devices'
phase = phases.os_installation
predecessors = [bootstrap.Bootstrap]
2013-07-01 20:48:51 +02:00
@classmethod
def run(cls, info):
root = info.volume.partition_map.root
root.add_mount('/dev', 'dev', ['--bind'])
root.add_mount('none', 'proc', ['--types', 'proc'])
root.add_mount('none', 'sys', ['--types', 'sysfs'])
root.add_mount('none', 'dev/pts', ['--types', 'devpts'])
2013-07-01 20:48:51 +02:00
class CopyMountTable(Task):
description = 'Copying mtab from host system'
phase = phases.os_installation
predecessors = [MountSpecials]
@classmethod
def run(cls, info):
import shutil
import os.path
shutil.copy('/proc/mounts', os.path.join(info.root, 'etc/mtab'))
class UnmountRoot(Task):
description = 'Unmounting the bootstrap volume'
phase = phases.volume_unmounting
successors = [volume.Detach]
2013-07-01 20:48:51 +02:00
@classmethod
def run(cls, info):
info.volume.partition_map.root.unmount()
2013-07-01 20:48:51 +02:00
class RemoveMountTable(Task):
description = 'Removing mtab'
phase = phases.volume_unmounting
successors = [UnmountRoot]
@classmethod
def run(cls, info):
import os
os.remove(os.path.join(info.root, 'etc/mtab'))
class DeleteMountDir(Task):
description = 'Deleting mountpoint for the bootstrap volume'
phase = phases.volume_unmounting
predecessors = [UnmountRoot]
@classmethod
def run(cls, info):
import os
os.rmdir(info.root)
del info.root
2013-07-07 13:02:04 +02:00
class FStab(Task):
description = 'Adding partitions to the fstab'
phase = phases.system_modification
@classmethod
def run(cls, info):
import os.path
from bootstrapvz.base.fs.partitions.unformatted import UnformattedPartition
from bootstrapvz.base.fs.partitions.single import SinglePartition
2017-02-01 20:16:23 +01:00
def is_additional(partition):
return (not isinstance(partition, (UnformattedPartition, SinglePartition)) and
2017-02-04 16:15:24 +01:00
partition.name not in ["boot", "swap", "root"])
2017-02-01 20:16:23 +01:00
p_map = info.volume.partition_map
2017-02-01 18:38:37 +01:00
partitions = p_map.partitions
mount_points = [{'path': '/',
'partition': p_map.root,
'dump': '1',
'pass_num': '1',
}]
if hasattr(p_map, 'boot'):
mount_points.append({'path': '/boot',
'partition': p_map.boot,
'dump': '1',
'pass_num': '2',
})
if hasattr(p_map, 'swap'):
mount_points.append({'path': 'none',
'partition': p_map.swap,
'dump': '1',
'pass_num': '0',
})
2017-01-31 21:45:40 +01:00
2017-02-01 20:16:23 +01:00
for partition in sorted(
filter(is_additional, partitions),
key=lambda partition: len(partition.name)):
2017-01-31 21:45:40 +01:00
mount_points.append({'path': "/" + partition.name,
'partition': getattr(p_map, partition.name),
'dump': '1',
'pass_num': '2',
})
fstab_lines = []
for mount_point in mount_points:
partition = mount_point['partition']
2016-12-10 16:03:02 +01:00
if partition.mountopts is None:
mount_opts = ['defaults']
else:
mount_opts = partition.mountopts
fstab_lines.append('UUID={uuid} {mountpoint} {filesystem} {mount_opts} {dump} {pass_num}'
.format(uuid=partition.get_uuid(),
mountpoint=mount_point['path'],
filesystem=partition.filesystem,
mount_opts=','.join(mount_opts),
dump=mount_point['dump'],
pass_num=mount_point['pass_num']))
fstab_path = os.path.join(info.root, 'etc/fstab')
with open(fstab_path, 'w') as fstab:
fstab.write('\n'.join(fstab_lines))
fstab.write('\n')