diff --git a/base/fs/volume.py b/base/fs/volume.py index 4a4958e..7df9778 100644 --- a/base/fs/volume.py +++ b/base/fs/volume.py @@ -10,14 +10,13 @@ class Volume(FSMProxy): events = [{'name': 'create', 'src': 'nonexistent', 'dst': 'detached'}, {'name': 'attach', 'src': 'detached', 'dst': 'attached'}, - {'name': 'mount_specials', 'src': 'attached', 'dst': 'specials_mounted'}, - {'name': 'unmount_specials', 'src': 'specials_mounted', 'dst': 'attached'}, {'name': 'detach', 'src': 'attached', 'dst': 'detached'}, {'name': 'delete', 'src': 'detached', 'dst': 'deleted'}, ] 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() @@ -29,20 +28,31 @@ class Volume(FSMProxy): cfg = {'initial': 'nonexistent', 'events': self.events, 'callbacks': callbacks} super(Volume, self).__init__(cfg) - def _before_mount_specials(self, e): + def can_mount_specials(self): + return self.is_state('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 _before_unmount_specials(self, e): + 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') diff --git a/common/fs/loopbackvolume.py b/common/fs/loopbackvolume.py index d33d269..d2918ff 100644 --- a/common/fs/loopbackvolume.py +++ b/common/fs/loopbackvolume.py @@ -12,18 +12,16 @@ class LoopbackVolume(Volume): events = [{'name': 'create', 'src': 'nonexistent', 'dst': 'detached'}, {'name': 'attach', 'src': 'detached', 'dst': 'attached'}, {'name': 'link_dm_node', 'src': 'attached', 'dst': 'linked'}, - {'name': 'mount_specials', 'src': 'linked', 'dst': 'lnk_specials_mounted'}, - {'name': 'unmount_specials', 'src': 'lnk_specials_mounted', 'dst': 'linked'}, {'name': 'unlink_dm_node', 'src': 'linked', 'dst': 'attached'}, {'name': 'detach', 'src': 'attached', 'dst': 'detached'}, {'name': 'delete', 'src': 'detached', 'dst': 'deleted'}, - - {'name': 'mount_specials', 'src': 'linked', 'dst': 'specials_mounted'}, - {'name': 'unmount_specials', 'src': 'specials_mounted', 'dst': 'linked'}, ] extension = 'raw' + def can_mount_specials(self): + return self.is_state('attached') or self.is_state('linked') + def create(self, image_path): self.fsm.create(image_path=image_path) diff --git a/plugins/prebootstrapped/tasks.py b/plugins/prebootstrapped/tasks.py index 3899336..38d5275 100644 --- a/plugins/prebootstrapped/tasks.py +++ b/plugins/prebootstrapped/tasks.py @@ -34,12 +34,7 @@ class CreateFromSnapshot(Task): time.sleep(5) info.volume.update() - info.volume.force_state('detached_fmt') - partitions_state = 'formatted' - if 'partitions' in info.manifest.volume: - partitions_state = 'unmapped_fmt' - for partition in info.volume.partition_map.partitions: - partition.force_state(partitions_state) + set_fs_states(info.volume) class CopyImage(Task): @@ -68,10 +63,20 @@ class CreateFromImage(Task): info.volume.image_path = os.path.join(info.workspace, 'volume.{ext}'.format(ext=info.volume.extension)) loopback_backup_path = info.manifest.plugins['prebootstrapped']['image'] copyfile(loopback_backup_path, info.volume.image_path) + set_fs_states(info.volume) - info.volume.force_state('detached_fmt') - partitions_state = 'formatted' - if 'partitions' in info.manifest.volume: + +def set_fs_states(volume): + volume.set_state('detached') + + p_map = volume.partition_map + partitions_state = 'attached' + from base.fs.partitionmaps.none import NoPartitions + if isinstance(p_map, NoPartitions): + p_map.set_state('created') + partitions_state = 'formatted' + else: + p_map.set_state('unmapped') partitions_state = 'unmapped_fmt' - for partition in info.volume.partition_map.partitions: - partition.force_state(partitions_state) + for partition in p_map.partitions: + partition.set_state(partitions_state) diff --git a/providers/virtualbox/tasks/boot.py b/providers/virtualbox/tasks/boot.py index f800f06..12694c0 100644 --- a/providers/virtualbox/tasks/boot.py +++ b/providers/virtualbox/tasks/boot.py @@ -16,7 +16,7 @@ class ConfigureGrub(Task): boot_dir = os.path.join(info.root, 'boot') grub_dir = os.path.join(boot_dir, 'grub') - from partitionmaps.none import NoPartitions + from base.fs.partitionmaps.none import NoPartitions def remount(volume, fn): # GRUB cannot deal with installing to loopback devices @@ -28,10 +28,13 @@ class ConfigureGrub(Task): boot_dir = p_map.boot.mount_dir p_map.boot.unmount() p_map.root.unmount() - if isinstance(self.partition_map, NoPartitions): + if not isinstance(p_map, NoPartitions): p_map.unmap() fn() p_map.map() + else: + fn() + p_map.root.device_path = volume.device_path p_map.root.mount(info.root) if hasattr(p_map, 'boot'): p_map.boot.mount(boot_dir)