summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Ipsum <richard.ipsum@codethink.co.uk>2015-10-31 16:56:59 +0000
committerBaserock Gerrit <gerrit@baserock.org>2015-11-02 15:37:46 +0000
commit567818d8db287208522b8ac935d2dadc73d6d3da (patch)
tree3e77c5032d43cba0d6dafca071b60080b02d8fca
parent065f4c19b08907df37bc551467baad4aede8bf0b (diff)
downloaddefinitions-567818d8db287208522b8ac935d2dadc73d6d3da.tar.gz
Fix bug in fstab layout generation
This fixes a bug in our fstab layout generation, currently we fail to generate the complete fstab layout, so /etc/fstab in any newly deployed or upgraded baserocks contains just: # Morph default system layout UUID=<uuid> / btrfs defaults,rw,noatime 0 1 This is actually a pretty bad problem because it breaks system-version-manager, since systemd creates a btrfs subvolume and mounts it to /var/lib/machines if /var/lib/machines doesn't already exist[1]. As a result system-version-manager when asked to remove an image will fail to do so, since it will fail to remove the /run subvolume because of the subvolume created at /run/var/lib/machines. The result is a partially removed image that cannot be removed with system-version-manager. The fstab layout we use currently: UUID=<uuid> / btrfs defaults,rw,noatime 0 1 UUID=<uuid> /var btrfs subvol=/state/var,defaults,rw,noatime 0 2 UUID=<uuid> /opt btrfs subvol=/state/opt,defaults,rw,noatime 0 2 UUID=<uuid> /srv btrfs subvol=/state/srv,defaults,rw,noatime 0 2 UUID=<uuid> /root btrfs subvol=/state/root,defaults,rw,noatime 0 2 UUID=<uuid> /home btrfs subvol=/state/home,defaults,rw,noatime 0 2 ensures that anything created under /var goes into a shared /state/var subvolume, so when systemd creates its 'machines' subvolume it will be under state/ which doesn't cause any problems when we try to remove a system. To reproduce, deploy an upgrade to your machine, reboot into the upgraded system, when you cat /etc/fstab you should see only one entry, mounting /. Now switch back to the previous image with, system-version-manager set-default <previous image name> reboot remove the newly deployed image with, system-version-manager remove <upgraded image name> after some time this will fail with an error message similar to this: Removing system: faultylayout Delete subvolume (no-commit): '/tmp/tmp1gdIL2/systems/faultylayout/run' ERROR: cannot delete '/tmp/tmp1gdIL2/systems/faultylayout/run' - Directory not empty Delete subvolume (no-commit): '/tmp/tmp1gdIL2/systems/faultylayout/orig' Traceback (most recent call last): File "/usr/bin/system-version-manager", line 421, in <module> SystemVersionManager(sys.argv, mount_dir).run() File "/usr/bin/system-version-manager", line 401, in run self.cmd_remove(args.system_name) File "/usr/bin/system-version-manager", line 363, in cmd_remove shutil.rmtree(system_root) File "/usr/lib/python2.7/shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "/usr/lib/python2.7/shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "/usr/lib/python2.7/shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "/usr/lib/python2.7/shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "/usr/lib/python2.7/shutil.py", line 256, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/usr/lib/python2.7/shutil.py", line 254, in rmtree os.rmdir(path) OSError: [Errno 1] Operation not permitted: '/tmp/tmp1gdIL2/systems/faultylayout/run/var/lib/machines [1]: http://cgit.freedesktop.org/systemd/systemd/commit/?id=113b3fc1a8061f4a24dd0db74e9a3cd0083b2251 Change-Id: I9c160d1fdd75fbbf9a3336d1ce35e4ce8ed7787d
-rw-r--r--extensions/writeexts.py7
1 files changed, 4 insertions, 3 deletions
diff --git a/extensions/writeexts.py b/extensions/writeexts.py
index de7c0f2e..f356a34a 100644
--- a/extensions/writeexts.py
+++ b/extensions/writeexts.py
@@ -606,10 +606,10 @@ class WriteExtension(Extension):
fstab.add_line('%s / btrfs defaults,rw,noatime 0 1' % root_device)
# Add fstab entries for partitions
+ part_mountpoints = set()
if device:
mount_parts = set(p for p in device.partitionlist
if hasattr(p, 'mountpoint') and p.mountpoint != '/')
- part_mountpoints = set(p.mountpoint for p in mount_parts)
for part in mount_parts:
if part.mountpoint not in existing_mounts:
# Get filesystem UUID
@@ -621,17 +621,18 @@ class WriteExtension(Extension):
fstab.add_line('UUID=%s %s %s defaults,rw,noatime '
'0 2' % (part_uuid, part.mountpoint,
part.filesystem))
+ part_mountpoints.add(part.mountpoint)
else:
self.status(msg='WARNING: an entry already exists in '
'fstab for %s partition, skipping' %
part.mountpoint)
# Add entries for state dirs
+ all_mountpoints = set(existing_mounts.keys()) | part_mountpoints
state_dirs_to_create = set()
for state_dir in shared_state_dirs:
mp = '/' + state_dir
- if (mp not in existing_mounts and
- (device and mp not in part_mountpoints)):
+ if mp not in all_mountpoints:
state_dirs_to_create.add(state_dir)
state_subvol = os.path.join('/state', state_dir)
fstab.add_line(