Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add orange flavor btrfs support #2207

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

rdesaintleger
Copy link

  • remove btrfs default subvolume,
  • save btrfs device in Btrfs structure,
  • rework brtfs state mountpoint detection (uses btrfs device, got rid of rootSubvolID and snapshotsSubvolID constants),
  • add 'active' relative symlink to active snapshot (updated in CloseTransaction() and read in getActiveSnapshot()),
  • add grub 'active_snap' variable (could it be replaced by dracut resolving the 'active' link ?),
  • add grub 'root_subpath' variable which allows to prefix kernel and initrd image with a subpath,
  • handle grub modules packaging under /usr/lib/elemental/bootloader
  • add RelativizeLink() to recursively make symbolic links relative,
  • ensure kernel and initrd are relative links (allow grub to process without mounting subvolume)
  • update orange Dockerfile

@kkaempf
Copy link
Contributor

kkaempf commented Oct 18, 2024

@rdesaintleger thanks for your PR !
Please add some explanation of why this change is needed (a link to an open issue is sufficient). See #2206

@kkaempf kkaempf added the kind/enhancement New feature or request label Oct 18, 2024
@kkaempf kkaempf changed the title Add orange btrfs support Add orange flavor btrfs support Oct 18, 2024
@rdesaintleger
Copy link
Author

Sorry, my PR is bad for the moment

I found a fix for the RelativizeLink() function which allow build tests to go further (up to snapshotter). Also I didn't notice that snapper did use the btrfs default subvolume feature.

I think that I'll make a new snapshotter without snapper named 'btrfs_nosnapper' with its own regression tests. This will have the advantage of not breaking existing btrfs green flavors and being cross distro when using new snapshotter.

@frelon
Copy link
Contributor

frelon commented Oct 18, 2024

@rdesaintleger really nice to see this implemented! Looking forward to the new snapshotter!

Looking back we should probably have named the current "btrfs" snapshotter as "snapper" instead.. oh well!

@davidcassany
Copy link
Contributor

I think that I'll make a new snapshotter without snapper named 'btrfs_nosnapper' with its own regression tests. This will have the advantage of not breaking existing btrfs green flavors and being cross distro when using new snapshotter.

At a time when I coded this snapshotter in head there were few configuration options for the btrfs snapshotter. Those were related to the required stack. Pure btrfs implementation, without snapper, implementation with snapper and third option using tukit. So my idea was having like three different levels of abstraction. So, even if the implementation could be in different files or structures I imagined all three as single snapshotter for btrfs. The thing is that snapper also support some sort of LVM snapshots which are definitely not supported by Elemental-toolkit and tukit assumes snapper. Hence in all cases we are talking about BTRFS subvolumes.

Just explaining that because most of the parts that are required to make a wrapper for btrfs tool are already implemented in the current snaphsotter hence we should figure out some ways to reuse all that.

See the following manual steps I did at a time to make a PoC before actually implementing the snapshotter for btrfs.

For install (first snaphsot):

# Enable quota management and create subvolumes
btrfs quota enable /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@/.snapshots

mkdir -p /mnt/@/.snapshots/1

btrfs subvolume snapshot /mnt/@ /mnt/@/.snapshots/1/snapshot

# ID should be computed from a "btrfs subvolume list" command
# default set to the equivalent of the STATE partition (probably a /@/state subvolume would make more sense)
volid=$(btrfs subvolume list --sort path /mnt | head -n 1 | cut -d" " -f2)
btrfs subvolume set-default ${volid} /mnt

# Create snapshot 1 info
date=$(date +'%Y-%m-%d %H:%M:%S')
cat << EOF > /mnt/@/.snapshots/1/info.xml
<?xml version="1.0"?>
<snapshot>
  <type>single</type>
  <num>1</num>
  <date>${date}</date>
  <description>first root filesystem</description>
</snapshot>
EOF

# Dump the built image into the first snapshot subvolume
./build/elemental pull-image --local ${osimage} /mnt/@/.snapshots/1/snapshot/


# Create the quota group
btrfs qgroup create 1/0 /mnt
#chroot /mnt/@/.snapshots/1/snapshot snapper --no-dbus set-config QGROUP=1/0

# set first snapshot as readonly
btrfs property set /mnt/@/.snapshots/1/snapshot ro true

All of the above is already coded in the current snapshotter. So most if not all pieces are already there. I'd be happy to help on getting a proper btrfs wrapper that can be used in both cases. With snapper and without. Probably it is even possible to achieve a snapper compatible setup without snapper.

For completeness the rough steps for an upgrade are:

# Get current snapshot
current=$(snapper --csvout list --columns number,active | grep yes | cut -d"," -f1)

# Create new snapshot from current
id=$(snapper create --from ${current} --read-write --print-number --description "Snapshot Update of #${current}" --userdata "update-in-progress=yes")

# Apply image to the new snapshot
elemental pull-image --local ${osimage} /mnt/@/.snapshots/${id}/snapshot/

snapper modify --userdata "update-in-progress=no" $id

# Make snapshot RO
btrfs property set /.snapshots/${id}/snapshot ro true

See here snapper is only used for the creation of a new subvolume.

@rdesaintleger
Copy link
Author

Thanks for information. I'll try the following (not sure yet for the grub part)

  • modify grub configuration to test (in case of btrfs root) for directory @/.snapshots/${active_snap}/snapshot (if false it's a snapshotter with actual behaviour).
  • add a DisableDefaultSubVolume property for BtrfsConfig yaml defaulting to 'false' (false is using snapper)
  • Update btrfs.go to handle properly both configuration

If grub is unable to test for snapshot directory I'll search for another solution. The property name comes from the original problem which is that other distro's grub do not handle properly default subvolumes.

@rdesaintleger
Copy link
Author

Now able to boot orange on btrfs.

elemental upgrade works in recovery but not in active state due to snapper configuration

- remove btrfs default subvolume,
- save btrfs device in Btrfs structure,
- rework brtfs state mountpoint detection (uses btrfs device, got rid of rootSubvolID and snapshotsSubvolID constants),
- add 'active' relative symlink to active snapshot (updated in CloseTransaction() and read in getActiveSnapshot()),
- add grub 'active_snap' variable (could it be replaced by dracut resolving the 'active' link ?),
- add grub 'root_subpath' variable which allows to prefix kernel and initrd image with a subpath,
- handle grub modules packaging under /usr/lib/elemental/bootloader
- add RelativizeLink() to recursively make symbolic links relative,
- ensure kernel and initrd are relative links (allow grub to process without mounting subvolume)
- update orange Dockerfile
orange now boots on btrfs snapshotter.
- grub configuration can now work without default subvolume
- moved kernel link relativize call
- added two configuration booleans for btrfs
- elemental upgrade is now working on orange flavor
- orange iso builds and install in btrfs

Still have to implement the 'max-snaps' when snapper is disabled.
Try to make snapper configuration work on orange too

btrfs configuration:
- disable-snapper: disable snapper usage and rely only over btrfsprogs. tested on orange and green
- disable-default-subvolume: disable subvolume get/set-default (as it is an incompat feature of btrfs). When default subvolume usage is disabled, a symlink is used in the state dir to find active snapshot.

It is not possible to disable default subvolume usage while using snapper (an error is returned).

TODO:
- try to rework snapper based snapshotter
- implements 'max-snaps'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement New feature or request
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

4 participants