diff --git a/bootstrapvz/plugins/tmpfs_workspace/README.rst b/bootstrapvz/plugins/tmpfs_workspace/README.rst new file mode 100644 index 0000000..092ebc4 --- /dev/null +++ b/bootstrapvz/plugins/tmpfs_workspace/README.rst @@ -0,0 +1,18 @@ +tmpfs workspace +--------------- + +The ``tmpfs workspace`` plugin mounts a tmpfs filesystem for the +workspace temporary files. This is useful when the workspace directory +is placed on a slow medium (e.g. a hard disk drive), the build process +performs lots of local I/O (e.g. building a vagrant box), and there is +enough RAM to store data necessary for the build process. For example, +the ``stretch-vagrant.yml`` manifest file from the examples directory +takes 33 minutes to build on the plugin author's home server. Using +this plugin reduces this time to 3 minutes at the cost of 1.2GB of +additional RAM usage. + +Settings +~~~~~~~~ + +This plugin has no settings. To enable it add ``"tmpfs_workspace":{}`` +to the plugin section of the manifest. diff --git a/bootstrapvz/plugins/tmpfs_workspace/__init__.py b/bootstrapvz/plugins/tmpfs_workspace/__init__.py new file mode 100644 index 0000000..5124cd7 --- /dev/null +++ b/bootstrapvz/plugins/tmpfs_workspace/__init__.py @@ -0,0 +1,17 @@ +from bootstrapvz.common.tasks.workspace import CreateWorkspace, DeleteWorkspace +from tasks import CreateTmpFsWorkspace, MountTmpFsWorkspace, UnmountTmpFsWorkspace, DeleteTmpFsWorkspace + + +def resolve_tasks(taskset, manifest): + taskset.discard(CreateWorkspace) + taskset.discard(DeleteWorkspace) + + taskset.add(CreateTmpFsWorkspace) + taskset.add(MountTmpFsWorkspace) + taskset.add(UnmountTmpFsWorkspace) + taskset.add(DeleteTmpFsWorkspace) + + +def resolve_rollback_tasks(taskset, manifest, completed, counter_task): + counter_task(taskset, MountTmpFsWorkspace, UnmountTmpFsWorkspace) + counter_task(taskset, CreateTmpFsWorkspace, DeleteTmpFsWorkspace) diff --git a/bootstrapvz/plugins/tmpfs_workspace/tasks.py b/bootstrapvz/plugins/tmpfs_workspace/tasks.py new file mode 100644 index 0000000..a7f318e --- /dev/null +++ b/bootstrapvz/plugins/tmpfs_workspace/tasks.py @@ -0,0 +1,50 @@ +from os import makedirs, rmdir + +from bootstrapvz.base import Task +from bootstrapvz.common.tasks.workspace import CreateWorkspace, DeleteWorkspace +from bootstrapvz.common import phases +from bootstrapvz.common.tools import log_check_call + + +class CreateTmpFsWorkspace(Task): + description = 'Creating directory for tmpfs-based workspace' + phase = phases.preparation + + @classmethod + def run(cls, info): + makedirs(info.workspace) + + +class MountTmpFsWorkspace(Task): + description = 'Mounting tmpfs-based workspace' + phase = phases.preparation + + # CreateWorkspace is explicitly skipped (see the plugin's resolve_task function). Several other tasks + # depend on CreateWorkspace to put their own files inside the workspace. We position MountTmpFs before + # CreateWorkspace to leverage these dependencies. See also UnmountTmpFs/DeleteWorkspace below. + successors = [CreateWorkspace] + predecessors = [CreateTmpFsWorkspace] + + @classmethod + def run(cls, info): + log_check_call(['mount', '--types', 'tmpfs', 'none', info.workspace]) + + +class UnmountTmpFsWorkspace(Task): + description = 'Unmounting tmpfs-based workspace' + phase = phases.cleaning + predecessors = [DeleteWorkspace] + + @classmethod + def run(cls, info): + log_check_call(['umount', info.workspace]) + + +class DeleteTmpFsWorkspace(Task): + description = 'Deleting directory for tmpfs-based workspace' + phase = phases.cleaning + predecessors = [UnmountTmpFsWorkspace] + + @classmethod + def run(cls, info): + rmdir(info.workspace)