[Questions] BTRFS and booting PVE from snapshot!

yjjoe

Member
Dec 27, 2021
34
2
13
24
Hi! I would like to know if booting from BTRFS snapshot if sighted by you dear Proxmox developers! Since Proxmox is a Debian based OS (more specifically a hyper-visor), I don't think of any thing that could be a blocker, if not related to the possible lack of robustness of that file system since it's relatively new.

Maybe you have something in your test repo?

The idea would be to have an option item at boot to select a snapshot. It would become possible to rollback pve so easily! Not mentioning the number of user support request that could eliminated by having that rollback system.

Here is a page that describe a standard implementation of snapshot creation along with GRUB setup.
https://dataswamp.org/~solene/2023-01-04-boot-on-btrfs-snapshot.html

The questions:
1) Do you plan to go this way for production?
2) Do you plan to explore it in the test branch?

Cheers!
 
You should make a Bugzilla feature request if interested in this (you will get an answer there more likely than here if it falls through the page 1), but as there's nothing like this even for ZFS install (and BTRFS is marked as experimental for PVE), you will likely be out of luck. The question however is, if you have set up replications and run clusters, why would you actually need this, as you can reinstall a node at will if something goes wrong.

Do you get to need to do rollbacks any regularly?
 
Thank you for the recommendations! I will look into it for sure.

I'm not sure if in my particular case I would need this in a regular basis (production wise), but for any test environment, I think that would be a neat way to experiment without having to figure out how to manually back out changes.

Personally, in our staging environment, I would feel more confident with experimenting if that super convenient way of roll back would be available.

Cheers
 
Would the following script work for you? It's targeted at ZFS and only lightly tested, but feedback is welcome:

Bash:
#!/bin/sh

if [ $PPID -eq 1 ]; then
  # This code snippet runs inside of the initramfs, right after the kernel
  # has mounted the ZFS root file system.
  # If there is a file telling us that a rollback was previously requested,
  # attempt to do so now.
  # N.B.: This code runs in a BusyBox environment. Don't expect to get all of
  # the same powerful commands that a full Linux system has access to. Tread
  # with care when writing shell scripts.
  if [ -r "${rootmnt}/.rollback-zfs" ]; then
    rollback() {
      local label="$1"
      # We only ever attempt to roll back the root filesystem, as it is the only
      # one that is a little tricky to do. Snapshots for other mountpoints
      # should be handled with the tools that Linux and/or PVE provide for this
      # purpose.
      local root="$(awk "/ ${rootmnt////\\/} zfs /"'{ print $1 }' /proc/mounts)"
      # While ZFS has the option to roll back multiple generations of snapshots,
      # we aim to be conservative and will only ever roll back the most recent
      # snapshot. If you need to roll back to an earlier snapshot, you should
      # explicitly destroy the ones that you no longer need.
      local snapshots="$(zfs list -t snapshot "${root}" 2>/dev/null |
                         awk "/^${root////\\/}/"'{ print $1 }')"
      local last="$(echo "${snapshots}" | sed -n 's/[^@]*@//;$p')"
      [ -n "${last}" -a "x${last}" = "x${label}" ] || return
      # Remove the file telling us to perform a rollback operation. This should
      # help avoid boot loops if the rollback is not successful.
      rm -f "${rootmnt}/.rollback-zfs"
      zfs rollback "${root}@${label}" || :
    }
    rollback "$(cat "${rootmnt}/.rollback-zfs")"
    # Again, remove the file telling us to perform rollbacks. This prevents
    # nasty surprises if this file made it into the snapshot.
    rm -f "${rootmnt}/.rollback-zfs"
  fi
elif [ "x$*" = "xprereqs" ]; then
  # Our script can get invoked for several different reasons; one of them
  # would be when the initramfs gets assembled. Don't do anything in that
  # case.
  exit 0
else
  # This is our entry-point into this script, when a user invokes us to
  # manage their snapshots. Perform the required sanity checking and print
  # appropriate messages.
  usage() {
    echo "${0##*/}: [--cancel] <snapshot>" >&2
  }

  # Check for root permissions
  [ "$(id -u)" = 0 ] || { echo "Must run as root user" >&2; exit 1; }
  [ $# = 1 ] || { usage; exit 1; }

  # If invoked with the "--cancel" option, delete the file that controls
  # rollbacks.
  if [ "x$1" = "x--cancel" ]; then
    rm -f /.rollback-zfs
    exit 0
  fi

  # Sanity check that the caller is asking us to remove the most recent
  # snapshot. This information can of course still change several times
  # before the system has actually rebooted, and we will double-check again
  # before performing the actual rollback. But an early check at this
  # place allows us to print helpful messages to the user.
  root="$(awk "/ \/ zfs /"'{ print $1 }' /proc/mounts)"
  [ -n "${root}" ] || {
    echo "Cannot find a root ZFS filesystem" >&2
    exit 1
  }
  r_="$(echo "${root}" | sed 's,/,\/,g')"
  snapshots="$(zfs list -t snapshot "${root}" 2>/dev/null |
               awk "/^${r}/"'{ print $1 }')"
  echo "${snapshots}" | egrep @"$1"'([[:space:]]|$)' >/dev/null 2>&1 || {
    echo "Root filesystem on ${root} does not have a snapshot called $1" >&2
    exit 1
  }
  last="$(echo "${snapshots}" | sed -n 's/[^@]*@//;$p')"
  [ "x$1" = "x${last}" ] || {
    echo "Will only roll back to most recent snapshot. Delete any uneeded" >&2
    echo "snapshots, if you want to roll back to an older one instead." >&2
    exit 1
  }

  # Make sure our script is part of the initramfs for the current kernel.
  if ! [ -r /usr/share/initramfs-tools/scripts/local-bottom/rollback-zfs ] ||
      ! cmp "$0" /usr/share/initramfs-tools/scripts/local-bottom/rollback-zfs \
            >/dev/null 2>&1; then
    cp "$0" /usr/share/initramfs-tools/scripts/local-bottom/rollback-zfs
    update-initramfs -u
    # proxmox-boot-tool refresh
    echo
  fi

  # Explain the next steps that the user needs to take.
  echo "$1" >/.rollback-zfs
  cat <<EOF
The system will roll back to "$1" upon the next reboot.

You must initiate this reboot yourself (e.g. by running "/usr/sbin/reboot").

After the system has booted again, the snapshot will NOT be removed
automatically. If you no longer need it, you must execute
"zfs destroy ${root}@$1" yourself.
EOF
fi
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!