mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-22 09:50:37 +00:00
Implement partition mounts.
This solves quite a few challenges with mounting directories into root etc.
This commit is contained in:
parent
970cbfccf2
commit
2af0968156
11 changed files with 65 additions and 97 deletions
|
@ -1,4 +1,5 @@
|
|||
from abc import ABCMeta
|
||||
import os.path
|
||||
from common.tools import log_check_call
|
||||
from common.fsm_proxy import FSMProxy
|
||||
|
||||
|
@ -13,10 +14,32 @@ class AbstractPartition(FSMProxy):
|
|||
{'name': 'unmount', 'src': 'mounted', 'dst': 'formatted'},
|
||||
]
|
||||
|
||||
class Mount(object):
|
||||
def __init__(self, source, destination, opts):
|
||||
self.source = source
|
||||
self.destination = destination
|
||||
self.opts = opts
|
||||
|
||||
def mount(self, prefix):
|
||||
mount_dir = os.path.join(prefix, self.destination)
|
||||
if isinstance(self.source, AbstractPartition):
|
||||
self.source.mount(mount_dir)
|
||||
else:
|
||||
log_check_call(['/bin/mount'] + self.opts + [self.source, mount_dir])
|
||||
self.mount_dir = mount_dir
|
||||
|
||||
def unmount(self):
|
||||
if isinstance(self.source, AbstractPartition):
|
||||
self.source.unmount()
|
||||
else:
|
||||
log_check_call(['/bin/umount', self.mount_dir])
|
||||
del self.mount_dir
|
||||
|
||||
def __init__(self, size, filesystem):
|
||||
self.size = size
|
||||
self.filesystem = filesystem
|
||||
self.device_path = None
|
||||
self.mounts = {}
|
||||
|
||||
cfg = {'initial': 'nonexistent', 'events': self.events, 'callbacks': {}}
|
||||
super(AbstractPartition, self).__init__(cfg)
|
||||
|
@ -36,6 +59,23 @@ class AbstractPartition(FSMProxy):
|
|||
log_check_call(['/bin/mount', '--types', self.filesystem, self.device_path, e.destination])
|
||||
self.mount_dir = e.destination
|
||||
|
||||
def _after_mount(self, e):
|
||||
for destination in sorted(self.mounts.iterkeys(), key=len):
|
||||
self.mounts[destination].mount(self.mount_dir)
|
||||
|
||||
def _before_unmount(self, e):
|
||||
for destination in sorted(self.mounts.iterkeys(), key=len, reverse=True):
|
||||
self.mounts[destination].unmount()
|
||||
log_check_call(['/bin/umount', self.mount_dir])
|
||||
del self.mount_dir
|
||||
|
||||
def add_mount(self, source, destination, opts=[]):
|
||||
mount = self.Mount(source, destination, opts)
|
||||
if self.fsm.current == 'mounted':
|
||||
mount.mount(self.mount_dir)
|
||||
self.mounts[destination] = mount
|
||||
|
||||
def remove_mount(self, destination):
|
||||
if self.fsm.current == 'mounted':
|
||||
self.mounts[destination].unmount()
|
||||
del self.mounts[destination]
|
||||
|
|
|
@ -17,7 +17,6 @@ class Volume(FSMProxy):
|
|||
|
||||
def __init__(self, partition_map):
|
||||
self.device_path = None
|
||||
self.specials_mounted = False
|
||||
self.partition_map = partition_map
|
||||
self.size = self.partition_map.get_total_size()
|
||||
|
||||
|
@ -34,31 +33,6 @@ class Volume(FSMProxy):
|
|||
if isinstance(self.partition_map, NoPartitions):
|
||||
self.partition_map.root.create()
|
||||
|
||||
def can_mount_specials(self):
|
||||
return self.fsm.current == 'attached'
|
||||
|
||||
def mount_specials(self):
|
||||
if self.specials_mounted:
|
||||
raise VolumeError('The special devices are already mounted')
|
||||
root = self.partition_map.root.mount_dir
|
||||
log_check_call(['/bin/mount', '--bind', '/dev', '{root}/dev'.format(root=root)])
|
||||
log_check_call(['/usr/sbin/chroot', root, '/bin/mount', '--types', 'proc', 'none', '/proc'])
|
||||
log_check_call(['/usr/sbin/chroot', root, '/bin/mount', '--types', 'sysfs', 'none', '/sys'])
|
||||
log_check_call(['/usr/sbin/chroot', root, '/bin/mount', '--types', 'devpts', 'none', '/dev/pts'])
|
||||
self.specials_mounted = True
|
||||
|
||||
def unmount_specials(self):
|
||||
if not self.specials_mounted:
|
||||
raise VolumeError('The special devices are not mounted')
|
||||
root = self.partition_map.root.mount_dir
|
||||
log_check_call(['/usr/sbin/chroot', root, '/bin/umount', '/dev/pts'])
|
||||
log_check_call(['/usr/sbin/chroot', root, '/bin/umount', '/sys'])
|
||||
log_check_call(['/usr/sbin/chroot', root, '/bin/umount', '/proc'])
|
||||
log_check_call(['/bin/umount', '{root}/dev'.format(root=root)])
|
||||
self.specials_mounted = False
|
||||
|
||||
def _check_blocking(self, e):
|
||||
if self.partition_map.is_blocking():
|
||||
raise VolumeError('The partitionmap prevents the detach procedure')
|
||||
if self.specials_mounted:
|
||||
raise VolumeError('The special devices are mounted and prevent the detaching procedure')
|
||||
|
|
|
@ -20,10 +20,6 @@ def remount(volume, fn):
|
|||
from base.fs.partitionmaps.none import NoPartitions
|
||||
|
||||
p_map = volume.partition_map
|
||||
volume.unmount_specials()
|
||||
if hasattr(p_map, 'boot'):
|
||||
boot_dir = p_map.boot.mount_dir
|
||||
p_map.boot.unmount()
|
||||
root_dir = p_map.root.mount_dir
|
||||
p_map.root.unmount()
|
||||
if not isinstance(p_map, NoPartitions):
|
||||
|
@ -33,7 +29,4 @@ def remount(volume, fn):
|
|||
else:
|
||||
result = fn()
|
||||
p_map.root.mount(root_dir)
|
||||
if hasattr(p_map, 'boot'):
|
||||
p_map.boot.mount(boot_dir)
|
||||
volume.mount_specials()
|
||||
return result
|
||||
|
|
|
@ -19,9 +19,6 @@ class LoopbackVolume(Volume):
|
|||
|
||||
extension = 'raw'
|
||||
|
||||
def can_mount_specials(self):
|
||||
return self.fsm.current in ['attached', 'linked']
|
||||
|
||||
def create(self, image_path):
|
||||
self.fsm.create(image_path=image_path)
|
||||
|
||||
|
|
|
@ -31,13 +31,11 @@ partitioning_set = [partitioning.PartitionVolume,
|
|||
|
||||
boot_partition_set = [filesystem.CreateBootMountDir,
|
||||
filesystem.MountBoot,
|
||||
filesystem.UnmountBoot,
|
||||
]
|
||||
|
||||
mounting_set = [filesystem.CreateMountDir,
|
||||
filesystem.MountRoot,
|
||||
filesystem.MountSpecials,
|
||||
filesystem.UnmountSpecials,
|
||||
filesystem.UnmountRoot,
|
||||
filesystem.DeleteMountDir,
|
||||
]
|
||||
|
|
|
@ -55,25 +55,24 @@ class MountRoot(Task):
|
|||
info.volume.partition_map.root.mount(info.root)
|
||||
|
||||
|
||||
class MountBoot(Task):
|
||||
description = 'Mounting the boot partition'
|
||||
phase = phases.volume_mounting
|
||||
predecessors = [MountRoot]
|
||||
|
||||
def run(self, info):
|
||||
info.volume.partition_map.boot.mount(info.boot_dir)
|
||||
|
||||
|
||||
class CreateBootMountDir(Task):
|
||||
description = 'Creating mountpoint for the boot partition'
|
||||
phase = phases.volume_mounting
|
||||
successors = [MountBoot]
|
||||
predecessors = [MountRoot]
|
||||
|
||||
def run(self, info):
|
||||
import os
|
||||
info.boot_dir = os.path.join(info.root, 'boot')
|
||||
os.makedirs(info.boot_dir)
|
||||
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]
|
||||
|
||||
def run(self, info):
|
||||
p_map = info.volume.partition_map
|
||||
p_map.root.add_mount(p_map.boot, 'boot')
|
||||
|
||||
|
||||
class MountSpecials(Task):
|
||||
|
@ -82,7 +81,11 @@ class MountSpecials(Task):
|
|||
predecessors = [Bootstrap]
|
||||
|
||||
def run(self, info):
|
||||
info.volume.mount_specials()
|
||||
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'])
|
||||
|
||||
|
||||
class UnmountRoot(Task):
|
||||
|
@ -94,24 +97,6 @@ class UnmountRoot(Task):
|
|||
info.volume.partition_map.root.unmount()
|
||||
|
||||
|
||||
class UnmountBoot(Task):
|
||||
description = 'Unmounting the boot partition'
|
||||
phase = phases.volume_unmounting
|
||||
successors = [UnmountRoot]
|
||||
|
||||
def run(self, info):
|
||||
info.volume.partition_map.boot.unmount()
|
||||
|
||||
|
||||
class UnmountSpecials(Task):
|
||||
description = 'Unmunting special block devices'
|
||||
phase = phases.volume_unmounting
|
||||
successors = [UnmountRoot]
|
||||
|
||||
def run(self, info):
|
||||
info.volume.unmount_specials()
|
||||
|
||||
|
||||
class DeleteMountDir(Task):
|
||||
description = 'Deleting mountpoint for the bootstrap volume'
|
||||
phase = phases.volume_unmounting
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"provider" : "virtualbox",
|
||||
"provider": "virtualbox",
|
||||
"bootstrapper": {
|
||||
"workspace": "/target"
|
||||
},
|
||||
"image": {
|
||||
"name" : "debian-{release}-{architecture}-{%y}{%m}{%d}",
|
||||
"name": "debian-{release}-{architecture}-{%y}{%m}{%d}",
|
||||
"description": "Debian {release} {architecture}"
|
||||
},
|
||||
"system": {
|
||||
"release" : "wheezy",
|
||||
"release": "wheezy",
|
||||
"architecture": "amd64",
|
||||
"timezone" : "UTC",
|
||||
"locale" : "en_US",
|
||||
"charmap" : "UTF-8"
|
||||
"timezone": "UTC",
|
||||
"locale": "en_US",
|
||||
"charmap": "UTF-8"
|
||||
},
|
||||
"volume": {
|
||||
"backing": "vdi",
|
||||
|
|
|
@ -2,7 +2,6 @@ from tasks import Snapshot
|
|||
from tasks import CopyImage
|
||||
from tasks import CreateFromSnapshot
|
||||
from tasks import CreateFromImage
|
||||
from tasks import SetBootMountDir
|
||||
from providers.ec2.tasks import ebs
|
||||
from common.tasks import loopback
|
||||
from common.tasks import volume
|
||||
|
@ -27,16 +26,12 @@ def tasks(tasklist, manifest):
|
|||
if 'snapshot' in settings and settings['snapshot'] is not None:
|
||||
tasklist.add(CreateFromSnapshot)
|
||||
tasklist.remove(*skip_tasks)
|
||||
if 'boot' in manifest.volume['partitions']:
|
||||
tasklist.add(SetBootMountDir)
|
||||
else:
|
||||
tasklist.add(Snapshot)
|
||||
else:
|
||||
if 'image' in settings and settings['image'] is not None:
|
||||
tasklist.add(CreateFromImage)
|
||||
tasklist.remove(*skip_tasks)
|
||||
if 'boot' in manifest.volume['partitions']:
|
||||
tasklist.add(SetBootMountDir)
|
||||
else:
|
||||
tasklist.add(CopyImage)
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ log = logging.getLogger(__name__)
|
|||
class Snapshot(Task):
|
||||
description = 'Creating a snapshot of the bootstrapped volume'
|
||||
phase = phases.os_installation
|
||||
predecessors = [bootstrap.Bootstrap, filesystem.MountSpecials]
|
||||
predecessors = [bootstrap.Bootstrap]
|
||||
|
||||
def run(self, info):
|
||||
def mk_snapshot():
|
||||
|
@ -45,7 +45,7 @@ class CreateFromSnapshot(Task):
|
|||
class CopyImage(Task):
|
||||
description = 'Creating a snapshot of the bootstrapped volume'
|
||||
phase = phases.os_installation
|
||||
predecessors = [bootstrap.Bootstrap, filesystem.MountSpecials]
|
||||
predecessors = [bootstrap.Bootstrap]
|
||||
|
||||
def run(self, info):
|
||||
loopback_backup_name = 'volume-{id:x}.{ext}.backup'.format(id=info.run_id, ext=info.volume.extension)
|
||||
|
@ -71,16 +71,6 @@ class CreateFromImage(Task):
|
|||
set_fs_states(info.volume)
|
||||
|
||||
|
||||
class SetBootMountDir(Task):
|
||||
description = 'Setting mountpoint for the boot partition'
|
||||
phase = phases.volume_mounting
|
||||
predecessors = [filesystem.MountRoot]
|
||||
successors = [filesystem.MountBoot]
|
||||
|
||||
def run(self, info):
|
||||
info.boot_dir = os.path.join(info.root, 'boot')
|
||||
|
||||
|
||||
def set_fs_states(volume):
|
||||
volume.fsm.current = 'detached'
|
||||
|
||||
|
|
|
@ -107,10 +107,8 @@ def rollback_tasks(tasklist, tasks_completed, manifest):
|
|||
|
||||
counter_task(partitioning.MapPartitions, partitioning.UnmapPartitions)
|
||||
counter_task(common_filesystem.CreateMountDir, common_filesystem.DeleteMountDir)
|
||||
counter_task(common_filesystem.MountSpecials, common_filesystem.UnmountSpecials)
|
||||
|
||||
counter_task(common_filesystem.MountRoot, common_filesystem.UnmountRoot)
|
||||
counter_task(common_filesystem.MountBoot, common_filesystem.UnmountBoot)
|
||||
counter_task(volume_tasks.Attach, volume_tasks.Detach)
|
||||
counter_task(workspace.CreateWorkspace, workspace.DeleteWorkspace)
|
||||
counter_task(ami.BundleImage, ami.RemoveBundle)
|
||||
|
|
|
@ -74,7 +74,5 @@ def rollback_tasks(tasklist, tasks_completed, manifest):
|
|||
counter_task(filesystem.CreateMountDir, filesystem.DeleteMountDir)
|
||||
counter_task(partitioning.MapPartitions, partitioning.UnmapPartitions)
|
||||
counter_task(filesystem.MountRoot, filesystem.UnmountRoot)
|
||||
counter_task(filesystem.MountBoot, filesystem.UnmountBoot)
|
||||
counter_task(filesystem.MountSpecials, filesystem.UnmountSpecials)
|
||||
counter_task(volume_tasks.Attach, volume_tasks.Detach)
|
||||
counter_task(workspace.CreateWorkspace, workspace.DeleteWorkspace)
|
||||
|
|
Loading…
Add table
Reference in a new issue