summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Thomas <james.thomas@codethink.co.uk>2014-11-20 11:03:18 (GMT)
committerJames Thomas <james.thomas@codethink.co.uk>2014-11-20 11:03:18 (GMT)
commit61f116bc5367e8ba26e8fd0f48aa71e644cb9b1e (patch)
treea85950665c49791227444407de70240c147cb980
parent3190be6906eb21a1ba6878d3c8edb4bd16f925d7 (diff)
downloadtbdiff-61f116bc5367e8ba26e8fd0f48aa71e644cb9b1e.tar.gz
Support booting from a different partition using BOOT_DEVICE
This allows bootloaders without btrfs support (e.g u-boot) to boot from an ext partition
-rwxr-xr-xsystem-version-manager/system-version-manager58
1 files changed, 38 insertions, 20 deletions
diff --git a/system-version-manager/system-version-manager b/system-version-manager/system-version-manager
index dcd7b80..2f46dfc 100755
--- a/system-version-manager/system-version-manager
+++ b/system-version-manager/system-version-manager
@@ -41,6 +41,7 @@ class SystemVersionManager(object):
def __init__(self, args, mount_dir):
self.device, self.current_system = self._get_mount_info()
self.mount_dir = mount_dir
+ self.boot_dir = mount_dir
self.device_uuid = self._get_device_uuid(self.device)
# create the top-level parser
@@ -103,7 +104,7 @@ class SystemVersionManager(object):
# value in the extlinux.conf file. If it's not present, then pick
# the first of the present systems.
def _get_default(self):
- extlinux = os.path.join(self.mount_dir, 'extlinux.conf')
+ extlinux = os.path.join(self.boot_dir, 'extlinux.conf')
with open(extlinux, 'r') as f:
for line in f:
line = line.rstrip('\n')
@@ -144,8 +145,8 @@ class SystemVersionManager(object):
def _rewrite_boot_menu(self, device, default, systems):
# Logic copied from morphlib.SaveFile to not create
# a morphlib dependency.
- fd, temp_config = tempfile.mkstemp(dir=self.mount_dir)
- config = os.path.join(self.mount_dir, 'extlinux.conf')
+ fd, temp_config = tempfile.mkstemp(dir=self.boot_dir)
+ config = os.path.join(self.boot_dir, 'extlinux.conf')
with os.fdopen(fd, 'w') as f:
# If theres no menu.c32 file, add a menu to the extlinux.conf file
if self._check_system_syslinux():
@@ -174,8 +175,13 @@ class SystemVersionManager(object):
kernel_args += deployment_config.get('KERNEL_ARGS', '')
f.write('append %s\n' % kernel_args)
os.rename(temp_config, config)
+ self._update_default_symlink(default, self.mount_dir)
+ # We may also need to do this for the boot partition
+ if self.mount_dir != self.boot_dir:
+ self._update_default_symlink(default, self.boot_dir)
- default_path = os.path.join(self.mount_dir, 'systems', 'default')
+ def _update_default_symlink(self, default, mount_dir):
+ default_path = os.path.join(mount_dir, 'systems', 'default')
if os.path.islink(default_path):
self._atomic_symlink_update(default, default_path)
@@ -216,6 +222,10 @@ class SystemVersionManager(object):
label = self._parse_deploy_location(location)
version_root = os.path.join(self.mount_dir, 'systems', label)
+ install_root = version_root
+ if self.mount_dir != self.boot_dir:
+ install_root = os.path.join(self.boot_dir, 'systems', label)
+ subprocess.call(['mkdir', '-p', install_root])
orig_dir = os.path.join(version_root, 'orig')
run_dir = os.path.join(version_root, 'run')
@@ -245,17 +255,17 @@ class SystemVersionManager(object):
subprocess.call(['cp', '-a', os.path.join(new_var, file), shared_var])
self.status(msg="Installing the kernel")
- self._install_kernel(version_root)
+ self._install_kernel(version_root, install_root)
deployment_config = self._get_deployment_config(label)
if 'INITRAMFS_PATH' in deployment_config:
self.status(msg="Installing the initramfs")
self._install_initramfs(deployment_config['INITRAMFS_PATH'],
- version_root)
+ version_root, install_root)
if 'DTB_PATH' in deployment_config:
self.status(msg="Installing the device tree")
self._install_dtb(deployment_config['DTB_PATH'],
- version_root)
+ version_root, install_root)
except Exception as e:
# We are not controlling if deleting the suvolume fails
@@ -265,21 +275,21 @@ class SystemVersionManager(object):
self.status(msg="Rewriting boot menu")
self._rewrite_boot_menu(self.device, self._get_default(), self._get_systems())
- def _install_kernel(self, version_root):
+ def _install_kernel(self, version_root, dest_root):
'''Install the kernel outside of 'orig' or 'run' subvolumes
This code is kind of duplicated in morphlib/writeexts.py.
'''
image_names = ['vmlinuz', 'zImage', 'uImage']
- kernel_dest = os.path.join(version_root, 'kernel')
+ kernel_dest = os.path.join(dest_root, 'kernel')
for name in image_names:
try_path = os.path.join(version_root, 'run', 'boot', name)
if os.path.exists(try_path):
shutil.copy2(try_path, kernel_dest)
break
- def _install_dtb(self, dtb_path, version_root):
+ def _install_dtb(self, dtb_path, version_root, dest_root):
'''Install the devicetree outside of 'orig' or 'run' subvolumes
This code is kind of duplicated in morphlib/writeexts.py.
@@ -287,17 +297,17 @@ class SystemVersionManager(object):
'''
self.status(msg='Installing devicetree')
self.status(msg='Device tree path=%s' % dtb_path)
- dtb_dest = os.path.join(version_root, 'dtb')
+ dtb_dest = os.path.join(dest_root, 'dtb')
try_path = os.path.join(version_root, 'run', dtb_path)
shutil.copy2(try_path, dtb_dest)
- def _install_initramfs(self, initramfs_path, version_root):
+ def _install_initramfs(self, initramfs_path, version_root, dest_root):
'''Install the initramfs outside of 'orig' or 'run' subvolumes
This code is kind of duplicated in morphlib/writeexts.py.
'''
- initramfs_dest = os.path.join(version_root, 'initramfs')
+ initramfs_dest = os.path.join(dest_root, 'initramfs')
initramfs_src = os.path.join(version_root, 'run', initramfs_path)
shutil.copy2(initramfs_src, initramfs_dest)
@@ -347,16 +357,16 @@ class SystemVersionManager(object):
self._check_system_exists(system_name)
self._rewrite_boot_menu(self.device, system_name, self._get_systems())
- def mount_fs(self):
- subprocess.check_call(['mount', self.device, self.mount_dir])
+ def mount_fs(self, device, mount_dir):
+ subprocess.check_call(['mount', device, mount_dir])
- def umount_fs(self):
- subprocess.call(['umount', self.mount_dir])
+ def umount_fs(self, mount_dir):
+ subprocess.call(['umount', mount_dir])
def _check_system_syslinux(self):
# It's not essential to have a menu.c32 file, if it's not there we can
# add a menu directly to the extlinux.conf file later
- menu_file = os.path.join(self.mount_dir, 'menu.c32')
+ menu_file = os.path.join(self.boot_dir, 'menu.c32')
if not os.path.isfile(menu_file):
return False
return True
@@ -364,8 +374,13 @@ class SystemVersionManager(object):
def run(self):
args = self.args
action = args.action
+ self.mount_fs(self.device, self.mount_dir)
+
+ deployment_config = self._get_deployment_config(self.current_system)
+ if 'BOOT_DEVICE' in deployment_config:
+ self.boot_dir = tempfile.mkdtemp()
+ self.mount_fs(deployment_config['BOOT_DEVICE'], self.boot_dir)
- self.mount_fs()
try:
if action == "list":
self.cmd_list()
@@ -385,7 +400,10 @@ class SystemVersionManager(object):
sys.stderr.write("ERROR, system not compatible: %s\n" % e.args[0])
raise
finally:
- self.umount_fs()
+ self.umount_fs(self.mount_dir)
+ if self.mount_dir != self.boot_dir:
+ self.umount_fs(self.boot_dir)
+ os.rmdir(self.boot_dir)
mount_dir = tempfile.mkdtemp()
try: