summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2014-06-09 15:52:37 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2014-06-16 15:06:43 +0000
commit86322cbe09f404929a7d4b205a262cead79e03ce (patch)
treee524455a992d914628e543674f93e5763684c124
parentc01d44f22983b5e61271c728e8e209e73d69fe16 (diff)
downloadtbdiff-86322cbe09f404929a7d4b205a262cead79e03ce.tar.gz
Generate extlinux.conf using deployment options from /baserock/deployment.meta
This will add the initramfs to the config and tell it to mount the disk by UUID if INITRAMFS_PATH was provided in the initial deployment. It will also include the extra KERNEL_ARGS provided. This is required to be able to upgrade a system that uses an initramfs and have it continue to use the initramfs. The system will continue to work without this patch if the initramfs' only responsibility was translating a UUID into a disk path, since system-version-manager would generate an extlinux.conf that boots with the same disk as it is currently using, but that would break if the device enumeration order changed e.g. if another disk was inserted before the rootfs, or the disk is transplanted into another machine.
-rwxr-xr-xsystem-version-manager/system-version-manager57
1 files changed, 52 insertions, 5 deletions
diff --git a/system-version-manager/system-version-manager b/system-version-manager/system-version-manager
index bd31c66..4d7dff3 100755
--- a/system-version-manager/system-version-manager
+++ b/system-version-manager/system-version-manager
@@ -17,8 +17,10 @@
import argparse
+import errno
import subprocess
import tempfile
+import json
import os
import sys
import shutil
@@ -39,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.device_uuid = self._get_device_uuid(self.device)
# create the top-level parser
parser = argparse.ArgumentParser(prog='system-version-manager')
@@ -112,6 +115,19 @@ class SystemVersionManager(object):
return self.current_system
+ def _get_deployment_config(self, system):
+ try:
+ meta = open(os.path.join(self.mount_dir, 'systems', system,
+ 'run/baserock/deployment.meta'))
+ except IOError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ deployment_config = {}
+ else:
+ deployment_config = json.load(meta).get('configuration', {})
+ meta.close()
+ return deployment_config
+
def _atomic_symlink_update(self, source, link_name):
dirname = os.path.dirname(link_name)
temp_dir = tempfile.mkdtemp(dir=dirname)
@@ -136,11 +152,18 @@ class SystemVersionManager(object):
f.write('prompt 0\n')
f.write('ontimeout ' + default +'\n')
for system in systems:
- f.write('label ' + system +'\n')
- f.write('kernel /systems/'+ system +'/kernel\n')
- f.write('append root='+ device +' '
- 'rootflags=subvol=systems/'+ system +'/run '
- 'init=/sbin/init rw\n')
+ deployment_config = self._get_deployment_config(system)
+ f.write('label ' + system + '\n')
+ f.write('kernel /systems/' + system + '/kernel\n')
+ kernel_args = ('rw init=/sbin/init rootfstype=btrfs '
+ 'rootflags=subvol=systems/'+ system +'/run ')
+ if 'INITRAMFS_PATH' in deployment_config:
+ f.write('initrd /systems/%s/initramfs\n' % system)
+ kernel_args += ('root=UUID=%s ' % self.device_uuid)
+ else:
+ kernel_args += ('root=%s ' % self.device)
+ kernel_args += deployment_config.get('KERNEL_ARGS', '')
+ f.write('append %s\n' % kernel_args)
os.rename(temp_config, config)
default_path = os.path.join(self.mount_dir, 'systems', 'default')
@@ -209,11 +232,18 @@ class SystemVersionManager(object):
self.status(msg="Installing the kernel")
self._install_kernel(version_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)
+
except Exception as e:
# We are not controlling if deleting the suvolume fails
subprocess.call(['btrfs', 'subvolume', 'delete', run_dir])
raise
+ self.status(msg="Rewriting boot menu")
self._rewrite_boot_menu(self.device, self._get_default(), self._get_systems())
def _install_kernel(self, version_root):
@@ -230,6 +260,16 @@ class SystemVersionManager(object):
shutil.copy2(try_path, kernel_dest)
break
+ def _install_initramfs(self, initramfs_path, version_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_src = os.path.join(version_root, 'run', initramfs_path)
+ shutil.copy2(initramfs_src, initramfs_dest)
+
def _get_mount_info(self):
mountpoint = subprocess.check_output(
['findmnt', '/', '-l', '-n', '-o', 'SOURCE'])
@@ -241,6 +281,13 @@ class SystemVersionManager(object):
device = os.path.realpath(device)
return device, current_system
+ def _get_device_uuid(self, device):
+ # Find block device's UUID. Does not work with busybox blkid,
+ # but given this is written in python, that's probably the least
+ # of our worries
+ return subprocess.check_output(
+ ['blkid', '-s', 'UUID', '-o', 'value', device]).strip()
+
def cmd_remove(self, system_name):
self._check_system_exists(system_name)