def test_lazy_unmount(self): src_file = pjoin(self.source, 'file') bind_file = pjoin(self.target, 'file') touch(src_file) with open(src_file, 'w') as f: f.write('foo') try: with Namespace(user=True, mount=True): mount(self.source, self.target, None, MS_BIND) assert os.path.exists(bind_file) with open(bind_file) as f: # can't unmount the target due to the open file with pytest.raises(OSError) as cm: umount(self.target) assert cm.value.errno == errno.EBUSY # lazily unmount instead umount(self.target, MNT_DETACH) # confirm the file doesn't exist in the bind mount anymore assert not os.path.exists(bind_file) # but the file is still accessible to the process assert f.read() == 'foo' # trying to reopen causes IOError with pytest.raises(IOError) as cm: f = open(bind_file) assert cm.value.errno == errno.ENOENT except PermissionError: pytest.skip('No permission to use user and mount namespace')
def test_no_perms(self): with pytest.raises(OSError) as cm: mount(self.source, self.target, None, MS_BIND) assert cm.value.errno in (errno.EPERM, errno.EACCES) with pytest.raises(OSError) as cm: umount(self.target) assert cm.value.errno in (errno.EPERM, errno.EINVAL)
def test_root(self): # test umount mount(self.source, self.target, None, MS_BIND) umount(self.target) # test umount2 mount(self.source, self.target, None, MS_BIND) umount(self.target, MNT_FORCE)
def _umount_archive(self): """Unmount the squashfs archive.""" try: umount(self.location) return except FileNotFoundError as e: raise repo_errors.InitializationError( f'failed unmounting squashfs archive: {e.filename} required') except OSError as e: # fail out if not a permissions issue (regular or loopback failure inside userns) if e.errno not in (errno.EPERM, errno.EPIPE): raise repo_errors.InitializationError( f'failed unmounting squashfs archive: {e.strerror}') # fallback to using fusermount try: # TODO: switch to capture_output=True when >= py3.7 ret = subprocess.run(['fusermount', '-u', self.location], stderr=subprocess.PIPE, stdout=subprocess.PIPE) except FileNotFoundError as e: raise repo_errors.InitializationError( f'failed unmounting squashfs archive: {e.filename} required') if ret.returncode: self._failed_cmd(ret, 'unmounting')
def test_no_perms(self): with self.assertRaises(OSError) as cm: mount(self.source, self.target, None, MS_BIND) self.assertTrue(cm.exception.errno in (errno.EPERM, errno.EACCES)) with self.assertRaises(OSError) as cm: umount(self.target) self.assertTrue(cm.exception.errno in (errno.EPERM, errno.EINVAL))
def _umount_archive(self): """Unmount the squashfs archive.""" try: umount(self.location) return except FileNotFoundError as e: raise repo_errors.InitializationError( f'failed unmounting squashfs archive: {e.filename} required') except OSError as e: # fail out if not a permissions issue (regular or loopback failure inside userns) if e.errno not in (errno.EPERM, errno.EPIPE): raise repo_errors.InitializationError( f'failed unmounting squashfs archive: {e.strerror}') # fallback to using fusermount try: # TODO: switch to capture_output=True when >= py3.7 ret = subprocess.run( ['fusermount', '-u', self.location], stderr=subprocess.PIPE, stdout=subprocess.PIPE) except FileNotFoundError as e: raise repo_errors.InitializationError( f'failed unmounting squashfs archive: {e.filename} required') if ret.returncode: self._failed_cmd(ret, 'unmounting')
def test_bind_mount(self): src_file = pjoin(self.source, 'file') bind_file = pjoin(self.target, 'file') touch(src_file) try: with Namespace(user=True, mount=True): assert not os.path.exists(bind_file) mount(self.source, self.target, None, MS_BIND) assert os.path.exists(bind_file) umount(self.target) assert not os.path.exists(bind_file) except PermissionError: pytest.skip('No permission to use user and mount namespace')