summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2014-06-18 10:54:54 +0100
committerRichard Maw <richard.maw@codethink.co.uk>2014-06-18 10:54:54 +0100
commit6a361a1a174667e2998578e49acd64932eb2c8a1 (patch)
treee524455a992d914628e543674f93e5763684c124
parent0b9a35045c6fb7baa7a2b29408c2df9017111432 (diff)
parent86322cbe09f404929a7d4b205a262cead79e03ce (diff)
downloadtbdiff-6a361a1a174667e2998578e49acd64932eb2c8a1.tar.gz
Merge branch 'baserock/richardmaw/S11230/initramfs-upgrades'
Reviewed-by: Sam Thursfield Reviewed-by: Emmet Hikory Reviewed-by: Pedro Alvarez
-rwxr-xr-xsystem-version-manager/system-version-manager68
1 files changed, 56 insertions, 12 deletions
diff --git a/system-version-manager/system-version-manager b/system-version-manager/system-version-manager
index 6638a35..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)
@@ -129,26 +145,30 @@ class SystemVersionManager(object):
# Logic copied from morphlib.SaveFile to not create
# a morphlib dependency.
fd, temp_config = tempfile.mkstemp(dir=self.mount_dir)
- os.close(fd)
config = os.path.join(self.mount_dir, 'extlinux.conf')
- with open(temp_config, 'w') as f:
+ with os.fdopen(fd, 'w') as f:
f.write('default menu.c32\n')
f.write('timeout 50\n')
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')
- default_path_tmp = os.path.join(self.mount_dir, 'systems', 'default-tmp')
if os.path.islink(default_path):
- os.symlink(default, default_path_tmp)
- os.rename(default_path_tmp, default_path)
+ self._atomic_symlink_update(default, default_path)
def cmd_list(self):
for system in self._get_systems():
@@ -212,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):
@@ -233,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'])
@@ -244,7 +281,14 @@ class SystemVersionManager(object):
device = os.path.realpath(device)
return device, current_system
- def cmd_remove (self, system_name):
+ 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)
default_system = self._get_default()
@@ -268,7 +312,7 @@ class SystemVersionManager(object):
self._rewrite_boot_menu(self.device, default_system, self._get_systems())
- def cmd_set_default (self, system_name):
+ def cmd_set_default(self, system_name):
self._check_system_exists(system_name)
self._rewrite_boot_menu(self.device, system_name, self._get_systems())