btrfs and snapper with portage on Gentoo
This is just a quick share-a-recipe post to introduce snapper to anybody who hasn’t heard of it, and explain how to use it.
Snapper is a utility that manages btrfs snapshots. One of the nice features of btrfs is that snapshots are cheap (virtually instant, and consume space only as changes accumulate), and easy to access. Snapper allows you to automatically create and manage them based on time, events, manual action, etc.
Once snapper is set up you can display a list of snapshots. I have 10 hourly snapshots, 10 daily snapshots, and snapshots from before/after each emerge. I can diff them, browse them, etc. Btrfs snapshots can be browsed right from the filesystem, so if I nuke /etc/passwd I can always do a cp /.snapshots/1875/snapshot/etc/passwd /etc/passwd to restore one from a few hours before (though I do also have /etc in a git repo).
Snapper is currently available in the sunrise overlay – I won’t spend time on how to set that up/etc. Also, I’ve had time-based snapshots running for a while now and my memory is hazy as to whether I had to do anything to get those working – it just requires sticking some scripts in /etc/cron.*/ and creating a config file containing your policies.
What I did want to post is a recipe for getting pre/post-emerge snapshots working. All you need to do is add some lines to /etc/portage/bashrc:
case "${EBUILD_PHASE}" in preinst) DESC="${CATEGORY}/${PF}" NUMBER=`snapper create -t pre -p -d "${DESC}"` ;; postinst) snapper create -t post --pre-number $NUMBER -d "${DESC}" ;; esac
One of these days I might clean this up a bit and move it to portage.
Great hint rich0.
It was just yesterday, when I was looking if snapper is in the regular portage tree.
I read about his tool long time ago in some magazines, which is from Suse AFAIK.
Good that it is also available for us Gentoo users 😉
Installing it out of the sunrise overlay is no problem so far, but the bashrc rule seems to be very helpful to me.
Best, Andy.
Andy
November 27, 2013 at 6:46 am
Part of me thinks that I also had to tweak the cron job as well, or some other config file. If I get a chance I’ll do a diff of the default config vs what I have in /etc and see what comes up. If I get more time I might even move it into the tree (looks like they have recent releases too).
rich0
November 27, 2013 at 8:04 am
Just implemented btrfs/snapper on my Gentoo laptop too and started to think about package install/remove protection. I recently went through a Gnome update from 3.10 to 3.12. It was 150+ package build. If I used the proposed approach, I would end up with 300+ snapshots. this is not what I aimed for! I wanted only 2 – before and after.
Your approach works well for pre- snapshot. I need to raise some VAR like $INSTALL_STARTED in addition to your code and make sure I don’t create additional pre- snapshots before I create a post- snapshot.
Do you happen to know if I can hook emerge after it completes installing the last package of the run? It is the time I want to create my post- snapshot.
emerge may be interrupted in between and resumed (emerge –resume) later. Even in this situation I want to be able to create only 2 snapshots.
Anton
June 5, 2014 at 8:46 am
I managed to create the scripts that do exactly what I wanted – pre-snapshot before the 1st package is installed and post-snapshot when emerge session completes. Can you share them?
The modifications required to snapper config files:
/etc/conf.d/snapper:
#define a file prefix for saving vars between hooks
EMERGE_SNAPPER_STATE=/var/lock/emerge-snapper
/etc/snapper/configs/{config}
# define for every subvol config that needs to be pre- post- snapped for emerge operations
CREATE_EMERGE=”yes”
/etc/portage/bashrc:
pre_pkg_preinst() {
# define snapper-related actions
if [ -f /etc/conf.d/snapper ] ; then
. /etc/conf.d/snapper
fi
for CONFIG in $SNAPPER_CONFIGS ; do
EMERGE_CREATE=”no”
. /etc/snapper/configs/$CONFIG
if [ $EMERGE_CREATE = “yes” ] ; then
if [ -f $EMERGE_SNAPPER_STATE.$CONFIG ] ; then
. $EMERGE_SNAPPER_STATE.$CONFIG
echo “Keeping changes in snapshot $CONFIG:$EMERGE_PRE_NUMBER”
else
EMERGE_PRE_NUMBER=`snapper -c $CONFIG –quiet create –type=pre -p –description=”emerge $PN”`
echo EMERGE_PRE_NUMBER=$EMERGE_PRE_NUMBER > $EMERGE_SNAPPER_STATE.$CONFIG
set | grep PN= >> $EMERGE_SNAPPER_STATE.$CONFIG
fi
fi
done
}
##### /etc/portage/bashrc ends here
/etc/portage/bin/post_emerge:
#!/bin/bash
if [ -f /etc/conf.d/snapper ] ; then
. /etc/conf.d/snapper
fi
for CONFIG in $SNAPPER_CONFIGS ; do
EMERGE_CREATE=”no”
#source the snapper config
. /etc/snapper/configs/$CONFIG
#source the config-related saved state
if [ $EMERGE_CREATE = “yes” ] ; then
if [ -f $EMERGE_SNAPPER_STATE.$CONFIG ]; then
. $EMERGE_SNAPPER_STATE.$CONFIG
snapper –config=$CONFIG –quiet create –type=post –pre-number=$EMERGE_PRE_NUMBER –description=”post-emerge $PN”
rm $EMERGE_SNAPPER_STATE.$CONFIG
else
echo “emerge-snapper: strange… no pre-emerge snapper data saved for $CONFIG”
continue
fi
fi
done
exit 0
############# /etc/portage/bin/post_emerge ends here
Anton
June 6, 2014 at 3:21 am