mirror of
https://gitlab.com/kupfer/kupferbootstrap.git
synced 2025-02-23 13:45:45 -05:00
Chroot: clean up and centralise unmounting
This commit is contained in:
parent
2209447af0
commit
0884cb2efd
1 changed files with 25 additions and 11 deletions
36
chroot.py
36
chroot.py
|
@ -64,6 +64,11 @@ Chroot = None
|
||||||
chroots: dict[str, Chroot] = {}
|
chroots: dict[str, Chroot] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def make_abs_path(path: str) -> str:
|
||||||
|
"""Simply ensures the path string starts with a '/'. Does no disk modifications!"""
|
||||||
|
return '/' + path.lstrip('/')
|
||||||
|
|
||||||
|
|
||||||
def get_chroot_path(chroot_name, override_basepath: str = None) -> str:
|
def get_chroot_path(chroot_name, override_basepath: str = None) -> str:
|
||||||
base_path = config.get_path('chroots') if not override_basepath else override_basepath
|
base_path = config.get_path('chroots') if not override_basepath else override_basepath
|
||||||
return os.path.join(base_path, chroot_name)
|
return os.path.join(base_path, chroot_name)
|
||||||
|
@ -176,7 +181,8 @@ class Chroot:
|
||||||
raise Exception(f"Chroot {self.name} is already initialized, this seems like a bug")
|
raise Exception(f"Chroot {self.name} is already initialized, this seems like a bug")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.deactivate()
|
active_previously = self.active
|
||||||
|
self.deactivate_core()
|
||||||
|
|
||||||
if self.copy_base:
|
if self.copy_base:
|
||||||
if reset or not os.path.exists(self.get_path('usr/bin')):
|
if reset or not os.path.exists(self.get_path('usr/bin')):
|
||||||
|
@ -245,6 +251,8 @@ class Chroot:
|
||||||
raise Exception(f'Failed to initialize chroot "{self.name}"')
|
raise Exception(f'Failed to initialize chroot "{self.name}"')
|
||||||
|
|
||||||
self.initialized = True
|
self.initialized = True
|
||||||
|
if active_previously:
|
||||||
|
self.activate()
|
||||||
|
|
||||||
def mount(
|
def mount(
|
||||||
self,
|
self,
|
||||||
|
@ -267,9 +275,9 @@ class Chroot:
|
||||||
os.makedirs(absolute_destination, exist_ok=True)
|
os.makedirs(absolute_destination, exist_ok=True)
|
||||||
result = mount(absolute_source, absolute_destination, options=options, fs_type=fs_type, register_unmount=False)
|
result = mount(absolute_source, absolute_destination, options=options, fs_type=fs_type, register_unmount=False)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
raise Exception(f'{self.name}: failed to mount {absolute_source} to {relative_destination}')
|
raise Exception(f'{self.name}: failed to mount {absolute_source} to {absolute_destination}')
|
||||||
logging.debug(f'{self.name}: {absolute_source} successfully mounted to {absolute_destination}.')
|
logging.debug(f'{self.name}: {absolute_source} successfully mounted to {absolute_destination}.')
|
||||||
self.active_mounts += [relative_destination]
|
self.active_mounts += [make_abs_path(relative_destination)]
|
||||||
atexit.register(self.deactivate)
|
atexit.register(self.deactivate)
|
||||||
return absolute_destination
|
return absolute_destination
|
||||||
|
|
||||||
|
@ -278,10 +286,21 @@ class Chroot:
|
||||||
return
|
return
|
||||||
path = self.get_path(relative_path)
|
path = self.get_path(relative_path)
|
||||||
result = umount(path)
|
result = umount(path)
|
||||||
if result.returncode == 0 and relative_path in self.active_mounts:
|
if result.returncode == 0 and make_abs_path(relative_path) in self.active_mounts:
|
||||||
self.active_mounts.remove(relative_path)
|
self.active_mounts.remove(relative_path)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def umount_many(self, relative_paths: list[str]):
|
||||||
|
# make sure paths start with '/'. Important: also copies the collection and casts to list, which will be sorted!
|
||||||
|
mounts = [make_abs_path(path) for path in relative_paths]
|
||||||
|
mounts.sort(reverse=True)
|
||||||
|
for mount in mounts:
|
||||||
|
if mount == '/proc':
|
||||||
|
continue
|
||||||
|
self.umount(mount)
|
||||||
|
if '/proc' in mounts:
|
||||||
|
self.umount('/proc')
|
||||||
|
|
||||||
def activate(self, fail_if_active: bool = False):
|
def activate(self, fail_if_active: bool = False):
|
||||||
"""mount /dev, /sys and /proc"""
|
"""mount /dev, /sys and /proc"""
|
||||||
if self.active and fail_if_active:
|
if self.active and fail_if_active:
|
||||||
|
@ -293,8 +312,7 @@ class Chroot:
|
||||||
self.active = True
|
self.active = True
|
||||||
|
|
||||||
def deactivate_core(self):
|
def deactivate_core(self):
|
||||||
for dst in BASIC_MOUNTS.keys():
|
self.umount_many(BASIC_MOUNTS.keys())
|
||||||
self.umount(dst)
|
|
||||||
# TODO: so this is a weird one. while the basic bind-mounts get unmounted
|
# TODO: so this is a weird one. while the basic bind-mounts get unmounted
|
||||||
# additional mounts like crossdirect are intentionally left intact. Is such a chroot still `active` afterwards?
|
# additional mounts like crossdirect are intentionally left intact. Is such a chroot still `active` afterwards?
|
||||||
self.active = False
|
self.active = False
|
||||||
|
@ -303,11 +321,7 @@ class Chroot:
|
||||||
if not self.active:
|
if not self.active:
|
||||||
if fail_if_inactive:
|
if fail_if_inactive:
|
||||||
raise Exception(f"Chroot {self.name} not activated, can't deactivate!")
|
raise Exception(f"Chroot {self.name} not activated, can't deactivate!")
|
||||||
for mount in self.active_mounts[::-1]:
|
self.umount_many(self.active_mounts)
|
||||||
if mount == 'proc':
|
|
||||||
continue
|
|
||||||
self.umount(mount)
|
|
||||||
self.umount('proc')
|
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
def run_cmd(self,
|
def run_cmd(self,
|
||||||
|
|
Loading…
Add table
Reference in a new issue