Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions repos/system_upgrade/common/libraries/mounting.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ class MountingMode(object):
""" Used when no actual mount call needs to be issued """


class MountingPropagation(object):
"""
MountingPropagation are types of mounts propagation supported by the library
"""
PRIVATE = 'private'
""" Used for private propagation mounts """
SHARED = 'shared'
""" Used for shared propagation mounts """


def _makedirs(path, mode=0o777, exists_ok=True):
""" Helper function which extends os.makedirs with exists_ok on all versions of python. """
try:
Expand Down Expand Up @@ -293,19 +303,32 @@ class MountConfig(object):
class MountingBase(object):
""" Base class for all mount operations """

def __init__(self, source, target, mode, config=MountConfig.Mount):
def __init__(self, source, target, mode,
config=MountConfig.Mount,
propagation=MountingPropagation.SHARED):
self._mode = mode
self.source = source
self.target = target
self._config = config
self.propagation = propagation
self.additional_directories = ()

def _mount_options(self):
"""
Options to use with the mount call, individual implementations may override this function to return the
correct parameters
"""
return ['-o', self._mode, self.source]
return [
'-o', self._mode,
'--make-' + self.propagation,
self.source
]

def _umount_options(self):
"""
Options to use with the umount call.
"""
return ['-fl']

def chroot(self):
""" Create a ChrootActions instance for this mount """
Expand All @@ -323,7 +346,7 @@ def _cleanup(self):
""" Cleanup operations """
if os.path.exists(self.target) and os.path.ismount(self.target):
try:
run(['umount', '-fl', self.target], split=False)
run(['umount'] + self._umount_options() + [self.target], split=False)
except (OSError, CalledProcessError) as e:
api.current_logger().warning('Unmounting %s failed with: %s', self.target, str(e))
for directory in itertools.chain(self.additional_directories, (self.target,)):
Expand Down Expand Up @@ -404,6 +427,7 @@ def __init__(self, fstype, source, target, config=MountConfig.Mount):
def _mount_options(self):
return [
'-t', self.fstype,
'--make-' + self.propagation,
self.source
]

Expand All @@ -421,5 +445,6 @@ def __init__(self, name, source, workdir, config=MountConfig.Mount):
def _mount_options(self):
return [
'-t', 'overlay', 'overlay2',
'--make-' + self.propagation,
'-o', 'lowerdir={},upperdir={},workdir={}'.format(self.source, self._upper_dir, self._work_dir)
]
6 changes: 6 additions & 0 deletions repos/system_upgrade/common/libraries/overlaygen.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ def create_source_overlay(mounts_dir, scratch_dir, xfs_info, storage_info, mount
_create_mounts_dir(scratch_dir, mounts_dir)
mounts = _prepare_required_mounts(scratch_dir, mounts_dir, _get_mountpoints(storage_info), xfs_info)
with mounts.pop('/') as root_mount:
# it's important to make system_overlay shared because we
# later mount it into mount_target with some tricky way:
# 1. create system_overlay mount
# 2. mount system_overlay to mount_target (e.g. installroot)
# 3. mount other mounts like /tmp, /usr inside system_overlay
# if at stage 3 system_overlay is not shared, mounts will not appear in `mount_target`
with mounting.OverlayMount(name='system_overlay', source='/', workdir=root_mount.target) as root_overlay:
if mount_target:
target = mounting.BindMount(source=root_overlay.target, target=mount_target)
Expand Down