Hello community, here is the log from the commit of package rear for openSUSE:Factory checked in at 2015-10-19 22:51:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rear (Old) and /work/SRC/openSUSE:Factory/.rear.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rear" Changes: -------- --- /work/SRC/openSUSE:Factory/rear/rear.changes 2015-09-17 09:20:23.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.rear.new/rear.changes 2015-10-20 00:05:33.000000000 +0200 @@ -1,0 +2,26 @@ +Thu Oct 8 11:04:18 CEST 2015 - jsm...@suse.de + +- Version 1.17.2.a is rear 1.17.2 with SLE12-SP1-btrfs.patch that + makes it work specifically for the default btrfs structure + in SLE12-SP1, see https://github.com/rear/rear/issues/556 + (bsc#946006 fate#318701). +- SLE12-SP1-btrfs-example.conf is an example for SLE12-SP1 + with default btrfs subvolumes that gets installed + as /usr/share/rear/conf/SLE12-SP1-btrfs-example.conf +- Warning for users who upgrade Relax-and-Recover (rear): + Users who already use it must re-validate that their + particular disaster recovery procedure still works. + See in particular "Version upgrades" at + http://en.opensuse.org/SDB:Disaster_Recovery + Automatic version upgrades are not possible in practice. + The user must explicitly specify his intended rear version. + For one product like SLE11 or SLE12 we provide several versions + in parallel so that users where version N does not support their + particular needs can upgrade to version M but on the other hand + users who have a working disaster recovery procedure with + version N do not need to upgrade. Therefore the package name + contains the version and all packages conflict with each other + to avoid that an installed version gets accidentally + replaced with another version. + +------------------------------------------------------------------- New: ---- SLE12-SP1-btrfs-example.conf SLE12-SP1-btrfs.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rear.spec ++++++ --- /var/tmp/diff_new_pack.I9ryNY/_old 2015-10-20 00:05:34.000000000 +0200 +++ /var/tmp/diff_new_pack.I9ryNY/_new 2015-10-20 00:05:34.000000000 +0200 @@ -19,24 +19,50 @@ %bcond_without use_mkisofs Name: rear -Version: 1.17.2 +# Version 1.17.2.a is rear upstream version 1.17.2 plus SUSE specific patches, +# see https://github.com/rear/rear/issues/666 +Version: 1.17.2.a Release: 0 +%define upstream_version 1.17.2 +# Automatic version upgrades are not possible in practice. +# The user must explicitly specify his intended version. +# When users have a working disaster recovery procedure, they should not upgrade +# (see "Version upgrades" at http://en.opensuse.org/SDB:Disaster_Recovery). +# Users who already use it and like to upgrade, must re-validate that their +# particular disaster recovery procedure still works. +# For one product (e.g. SLE11 or SLE12) we provide several versions in parallel +# so that users where version N does not support their particular needs +# can upgrade to version M but on the other hand users who have a working +# disaster recovery procedure with version N do not need to upgrade. +# Therefore the package name contains the version and all packages conflict with each other +# to avoid that an installed version gets accidentally replaced with another version: +Provides: rear = %{version} +Conflicts: rear < %{version} +Conflicts: rear > %{version} Summary: Relax-and-Recover (abbreviated rear) is a Linux Disaster Recovery framework License: GPL-2.0+ Group: Productivity/Archiving/Backup Url: http://relax-and-recover.org/ -# as GitHub stopped with download section we need to go back to Sourceforge for downloads -Source0: http://sourceforge.net/projects/rear/files/rear/1.17/%{version}/rear-%{version}.tar.gz +# As GitHub stopped with download section we need to go back to Sourceforge for downloads +Source0: http://sourceforge.net/projects/rear/files/rear/1.17/%{upstream_version}/rear-%{upstream_version}.tar.gz # Source11 SLE11-ext3-example.conf is a working example for SLE11 with default ext3 filesystem # that gets installed as /usr/share/rear/conf/SLE11-ext3-example.conf Source11: SLE11-ext3-example.conf # Source12 SLE12-btrfs-example.conf is a working example for SLE12 with default btrfs subvolumes # that gets installed as /usr/share/rear/conf/SLE12-btrfs-example.conf Source12: SLE12-btrfs-example.conf -# Source99 rear-rpmlintrc filters false positives rpmlint warning messages, see +# Source121 SLE12-SP1-btrfs-example.conf is a working example for SLE12-SP1 with default btrfs subvolumes +# that gets installed as /usr/share/rear/conf/SLE12-SP1-btrfs-example.conf +Source121: SLE12-SP1-btrfs-example.conf +# Source999 rear-rpmlintrc filters false positives rpmlint warning messages, see # https://en.opensuse.org/openSUSE:Packaging_checks#Building_Packages_despite_of_errors -Source99: rear-rpmlintrc -# rear contains only bash scripts plus documentation so that on first glance it could be "BuildArch: noarch" +Source999: rear-rpmlintrc +# Patch121 SLE12-SP1-btrfs.patch make it work specifically for the default btrfs structure in SLE12-SP1 +# see https://github.com/rear/rear/issues/556 +# and https://bugzilla.suse.com/show_bug.cgi?id=946006 +# and https://fate.suse.com/318701 +Patch121: SLE12-SP1-btrfs.patch +# Rear contains only bash scripts plus documentation so that on first glance it could be "BuildArch: noarch" # but actually it is not "noarch" because it only works on those architectures that are explicitly supported. # Of course the rear bash scripts can be installed on any architecture just as any binaries can be installed on any architecture. # But the meaning of architecture dependent packages should be on what architectures they will work. @@ -177,7 +203,7 @@ %else Requires: %{_bindir}/genisoimage %endif -# recent SUSE versions have an extra nfs-client package +# Recent SUSE versions have an extra nfs-client package Requires: nfs-client # Rear calls openssl in /usr/share/rear/rescue/default/50_ssh.sh Requires: openssl @@ -212,8 +238,13 @@ procedure still works for you. %prep -%setup -q -n rear-%{version} -# add a specific os.conf to not depend on LSB dependencies +%setup -q -n rear-%{upstream_version} +# Patch121 SLE12-SP1-btrfs.patch make it work specifically for the default btrfs structure in SLE12-SP1 +# see https://github.com/rear/rear/issues/556 +# and https://bugzilla.suse.com/show_bug.cgi?id=946006 +# and https://fate.suse.com/318701 +%patch121 -p1 +# Add a specific os.conf to not depend on LSB dependencies # (otherwise it calls "lsb_release" in /usr/share/rear/lib/config-functions.sh) # for the suse_version values see the listing at # http://en.opensuse.org/openSUSE:Build_Service_cross_distribution_howto @@ -254,7 +285,7 @@ echo -e "OS_VENDOR=SUSE_LINUX\nOS_VERSION=$OS_VERSION" >etc/rear/os.conf %build -# no code to compile - all bash scripts - but at least run "make validate" +# No code to compile - all bash scripts - but at least run "make validate" # that runs "bash -n" for all bash files to test if the plain syntax is o.k. make validate @@ -266,6 +297,9 @@ # Source12 SLE12-btrfs-example.conf is a working example for SLE12 with default btrfs subvolumes # that gets installed as /usr/share/rear/conf/SLE12-btrfs-example.conf install -m 644 %{SOURCE12} %{buildroot}%{_datadir}/rear/conf/SLE12-btrfs-example.conf +# Source121 SLE12-SP1-btrfs-example.conf is a working example for SLE12-SP1 with default btrfs subvolumes +# that gets installed as /usr/share/rear/conf/SLE12-SP1-btrfs-example.conf +install -m 644 %{SOURCE121} %{buildroot}%{_datadir}/rear/conf/SLE12-SP1-btrfs-example.conf %files %defattr(-,root,root,-) ++++++ SLE12-SP1-btrfs-example.conf ++++++ # Begin example setup for SLE12-SP1 with default btrfs subvolumes. # On SLE12-SP1 what is mounted at '/' is a btrfs snapshot subvolume # see https://github.com/rear/rear/issues/556 # You must adapt "your.NFS.server.IP/path/to/your/rear/backup" at BACKUP_URL. # You must decide whether or not you want to have /home/* in the backup. # It depends on the size of your harddisk whether or not /home is by default # a btrfs subvolume or a separated xfs filesystem on a separated partition. # You may activate SSH_ROOT_PASSWORD and adapt the "password_on_the_rear_recovery_system". # For basic information see the SLE12-SP1 manuals. # Also see the support database article "SDB:Disaster Recovery" # at http://en.opensuse.org/SDB:Disaster_Recovery # In particular note: # There is no such thing as a disaster recovery solution that "just works". # Regarding btrfs snapshots: # Recovery of btrfs snapshot subvolumes is not possible. # Only recovery of "normal" btrfs subvolumes is possible. # On SLE12-SP1 the only exception is the btrfs snapshot subvolume # that is mounted at '/' but that one is not recreated but instead # it is created anew from scratch during the recovery installation with the # default first btrfs snapper snapshot subvolume path "@/.snapshots/1/snapshot" # by the SUSE tool "installation-helper --step 1" (cf. below). # Other snapshots like "@/.snapshots/234/snapshot" are not recreated. # Create rear rescue media as ISO image: OUTPUT=ISO # Store the backup file via NFS on a NFS server: BACKUP=NETFS # BACKUP_OPTIONS variable contains the NFS mount options and # with 'mount -o nolock' no rpc.statd (plus rpcbind) are needed: BACKUP_OPTIONS="nfsvers=3,nolock" # If the NFS server is not an IP address but a hostname, # DNS must work in the rear recovery system when the backup is restored. BACKUP_URL=nfs://your.NFS.server.IP/path/to/your/rear/backup # Keep an older copy of the backup in a HOSTNAME.old directory # provided there is no '.lockfile' in the HOSTNAME directory: NETFS_KEEP_OLD_BACKUP_COPY=yes # Have all modules of the original system in the recovery system with the # same module loading ordering as in the original system by using the output of # lsmod | tail -n +2 | cut -d ' ' -f 1 | tac | tr -s '[:space:]' ' ' # as value for MODULES_LOAD (cf. https://github.com/rear/rear/issues/626): #MODULES_LOAD=( ) # On SLE12-SP1 with default btrfs subvolumes what is mounted at '/' is a btrfs snapshot subvolume # that is controlled by snapper so that snapper is needed in the recovery system. # In SLE12-SP1 some btrfs subvolume directories (/var/lib/pgsql /var/lib/libvirt/images /var/lib/mariadb) # have the "no copy on write (C)" file attribute set so that chattr is needed in the recovery system. REQUIRED_PROGS=( "${REQUIRED_PROGS[@]}" snapper chattr ) # Snapper setup by the recovery system uses /usr/lib/snapper/installation-helper # that is linked to all libraries where snapper is linked to # (except libdbus that is only needed by snapper). # "installation-helper --step 1" creates a snapper config based on /etc/snapper/config-templates/default COPY_AS_IS=( "${COPY_AS_IS[@]}" /usr/lib/snapper/installation-helper /etc/snapper/config-templates/default ) # Files in btrfs subvolumes are excluded by 'tar --one-file-system' # so that such files must be explictly included to be in the backup. # Files in the following SLE12-SP1 default btrfs subvolumes are # in the below example not included to be in the backup # /.snapshots/* /var/crash/* # but files in /home/* are included to be in the backup. # Note that not having '/tmp/*' in BACKUP_PROG_INCLUDE when there are # matching entries in EXCLUDE_RECREATE like "fs:/tmp" would result # that during restore a /tmp/rear.*/tmp/restore-exclude-list.txt file # would contain the tar exclude patterns 'tmp' and 'tmp/*' so that # also other files and directories that match those tar exclude patterns # would not be restored (e.g. '/usr/tmp'). # You may use a command like # findmnt -t btrfs | cut -d ' ' -f 1 | cut -s -d '-' -f2 | egrep -v 'snapshots|crash' | sed -e "s/$/\/*'/" -e "s/^/'/" | tr '\n' ' ' # to generate the values: BACKUP_PROG_INCLUDE=( '/var/tmp/*' '/srv/*' '/var/lib/pgsql/*' '/var/spool/*' '/var/lib/libvirt/images/*' '/var/opt/*' '/tmp/*' '/var/lib/named/*' '/var/log/*' '/boot/grub2/i386/*' '/var/lib/mariadb/*' '/home/*' '/var/lib/mailman/*' '/opt/*' '/usr/local/*' '/boot/grub2/x86_64/*' ) # Also for every mounted btrfs subvolume exclude the mountpoint # of the mounted btrfs subvolumes from component recreation # see /usr/share/doc/packages/rear/user-guide/06-layout-configuration.txt # and /usr/share/rear/conf/default.conf # When /home is a separated filesystem remove "fs:/home" from the list below. # You may use a command like # findmnt -t btrfs | cut -d ' ' -f 1 | cut -s -d '-' -f2 | sed -e "s/$/'/" -e "s/^/'fs:/" | tr '\n' ' ' # to generate the values: EXCLUDE_RECREATE=( "${EXCLUDE_RECREATE[@]}" 'fs:/var/tmp' 'fs:/srv' 'fs:/var/lib/pgsql' 'fs:/var/spool' 'fs:/var/lib/libvirt/images' 'fs:/var/opt' 'fs:/tmp' 'fs:/.snapshots' 'fs:/var/lib/named' 'fs:/var/log' 'fs:/boot/grub2/i386' 'fs:/var/lib/mariadb' 'fs:/home' 'fs:/var/crash' 'fs:/var/lib/mailman' 'fs:/opt' 'fs:/usr/local' 'fs:/boot/grub2/x86_64' ) # This option defines a root password to allow SSH connection # whithout a public/private key pair #SSH_ROOT_PASSWORD="password_on_the_rear_recovery_system" # Let the rear recovery system run dhclient to get an IP address # instead of using the same IP address as the original system: #USE_DHCLIENT="yes" # End example setup for SLE12-SP1 with default btrfs subvolumes. ++++++ SLE12-SP1-btrfs.patch ++++++ diff -rp -U17 rear-1.17.2/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_filesystem_code.sh rear-1.17.2.SLE12-SP1-btrfs/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_filesystem_code.sh --- rear-1.17.2/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_filesystem_code.sh 2015-06-25 09:07:56.000000000 +0200 +++ rear-1.17.2.SLE12-SP1-btrfs/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_filesystem_code.sh 2015-10-02 12:33:46.000000000 +0200 @@ -1,41 +1,58 @@ # code to mount a file system # 13_mount_filesystem_code.sh contains the generic function 'mount_fs' # each distro may overrule the 'mount_fs' function with its proper way to do it # especially the case for btrfs related file systems mount_fs() { Log "Begin mount_fs( $@ )" local fs device mp fstype uuid label options ## mp: mount point read fs device mp fstype uuid label options < <(grep "^fs.* ${1#fs:} " "$LAYOUT_FILE") label=${label#label=} uuid=${uuid#uuid=} # Extract mount options. local option mountopts + # An input line could look like this (an example from SLES12-SP1): + # fs /dev/sda2 / btrfs uuid=a2b2c3 label= options=rw,relatime,space_cache,subvolid=259,subvol=/@/.snapshots/1/snapshot + # which means by the above 'read' the variable (that is unfortunately) named 'options' gets the + # value 'options=rw,relatime,space_cache,subvolid=259,subvol=/@/.snapshots/1/snapshot' + # i.e. options='options=rw,relatime,space_cache,subvolid=259,subvol=/@/.snapshots/1/snapshot' for option in $options ; do - name=${option%%=*} # options can contain more '=' signs - value=${option#*=} + name=${option%%=*} # an option can contain more '=' signs (see the above example value) + value=${option#*=} # therefore split the name from the actual value at the leftmost '=' case $name in (options) ### Do not mount nodev, as chrooting later on would fail. - mountopts=${value//nodev/dev} + value=${value//nodev/dev} + # btrfs mount options like subvolid=259 or subvol=/@/.snapshots/1/snapshot + # from the old system cannot work here for recovery because btrfs subvolumes + # are not yet created (and when created their subvolid is likely different) + # so that those mount options are removed here. All btrfs subvolume handling + # happens in the btrfs_subvolumes_setup function in 13_include_mount_subvolumes_code.sh + # First add a comma at the end so that it is easier to remove a mount option at the end: + value=${value/%/,} + # Remove all subvolid= and subvol= mount options (the extglob shell option is enabled in rear): + value=${value//subvolid=*([^,]),/} + value=${value//subvol=*([^,]),/} + # Remove all commas at the end: + mountopts=${value/%,/} ;; esac done if [ -n "$mountopts" ] ; then mountopts="-o $mountopts" fi echo "LogPrint \"Mounting filesystem $mp\"" >> "$LAYOUT_CODE" case $fstype in (btrfs) # The following commands are basically the same as in the default/fallback case. # The explicite case for btrfs is only there to be prepared for special adaptions for btrfs related file systems. # Because the btrfs filesystem was created anew just before by the create_fs function in 13_include_filesystem_code.sh # the code here mounts the whole btrfs filesystem because by default when creating a btrfs filesystem # its top-level/root subvolume is the btrfs default subvolume which gets mounted when no other subvolume is specified. diff -rp -U17 rear-1.17.2/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_subvolumes_code.sh rear-1.17.2.SLE12-SP1-btrfs/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_subvolumes_code.sh --- rear-1.17.2/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_subvolumes_code.sh 2015-06-08 09:50:38.000000000 +0200 +++ rear-1.17.2.SLE12-SP1-btrfs/usr/share/rear/layout/prepare/GNU/Linux/13_include_mount_subvolumes_code.sh 2015-10-02 13:22:15.000000000 +0200 @@ -19,206 +19,300 @@ btrfs_subvolumes_setup() { # where $device is the device node where the filesystem was already created by 13_include_filesystem_code.sh # (usually a harddisk partition like e.g. /dev/sda1): device=$1 mountpoint=$2 # mountopts are of the form "-o foo,bar,baz" (see 13_include_mount_filesystem_code.sh) # which means $3 is '-o' and 'foo,bar,baz' is $4: mountopts="$3 $4" # Empty device or mountpoint may indicate an error. In this case be verbose and inform the user: if test -z "$device" -o -z "$mountpoint" ; then LogPrint "Empty device='$device' or mountpoint='$mountpoint' may indicate an error, skipping btrfs_subvolumes_setup( $@ )." Log "Return 0 from btrfs_subvolumes_setup( $@ )" return 0 fi # FIXME: The following avoids to have '/mnt/local' hardcoded at many places in the code only here. # The root of the filesysten tree of the to-be-recovered-system in the recovery system should be in a global variable: recovery_system_root=/mnt/local ########################################### + # SLES 12 SP1 special btrfs subvolumes setup detection: + SLES12SP1_btrfs_detection_string="@/.snapshots/" + if grep "^btrfsdefaultsubvol $device $mountpoint [0-9]* $SLES12SP1_btrfs_detection_string" "$LAYOUT_FILE" ; then + info_message="Detected SLES 12 SP1 special btrfs subvolumes setup because the default subvolume path contains '$SLES12SP1_btrfs_detection_string'" + Log $info_message + echo "# $info_message" >> "$LAYOUT_CODE" + # For SLES 12 SP1 a btrfsdefaultsubvol entry in disklayout.conf looks like + # btrfsdefaultsubvol /dev/sda2 / 259 @/.snapshots/1/snapshot + # where "@/.snapshots/" should be fixed but "1/snapshot" may vary. + # This requires special setup because the btrfs default subvolume on SLES 12 SP1 + # is not a normal btrfs subvolume (as it was on SLES 12 (without SP1)) + # but on SLES 12 SP1 it is a snapper controlled btrfs snapshot subvolume, see + # https://github.com/rear/rear/issues/556 + # https://fate.suse.com/318701 (SUSE internal feature request) + # https://bugzilla.suse.com/show_bug.cgi?id=946006 (SUSE internal issue) + SLES12SP1_btrfs_subvolumes_setup="yes" + # Because that very special btrfs default subvolume on SLES 12 SP1 + # has to be controlled by snapper it must be set up by snapper + # which means that snapper is needed in the rear recovery system. + # For this special setup during installation a special SUSE tool + # /usr/lib/snapper/installation-helper is used: + SLES12SP1_installation_helper_executable="/usr/lib/snapper/installation-helper" + # What "snapper/installation-helper --step 1" basically does is + # creating a snapshot of the first root filesystem + # where the first root filesystem must have the btrfs subvolume '@' mounted at '/' + # which means the btrfs subvolume '@' must be the initial btrfs default subvolume: + SLES12SP1_initial_default_subvolume_path="@" + fi + ########################################### # Btrfs snapshot subvolumes handling: # Remember all btrfs snapshot subvolumes to exclude them when mounting all btrfs normal subvolumes below. # The btrfs snapshot subvolumes entries that are created by 23_filesystem_layout.sh # are deactivated (as '#btrfssnapshotsubvol ...') in the LAYOUT_FILE (disklayout.conf). # When there are active btrfs snapshot subvolumes entries, the user has manually # activated them (as 'btrfssnapshotsubvol ...') in the LAYOUT_FILE (disklayout.conf). # Because any btrfssnapshotsubvol entries are needed to exclude all btrfs snapshot subvolumes # 'grep "btrfssnapshotsubvol ..." ... | sed ...' is used. while read keyword dummy dummy dummy subvolume_path junk ; do if test -z "$subvolume_path" ; then continue fi # When there is a non-empty subvolume_path, btrfs snapshot subvolume handling is needed: Log "Handling snapshot subvolume $subvolume_path for $device at $mountpoint" # Remember btrfs snapshot subvolumes to exclude them when mounting all btrfs normal subvolumes below: snapshot_subvolumes_devices_and_paths="$snapshot_subvolumes_devices_and_paths $device,$subvolume_path" # Be verbose if there are active btrfs snapshot subvolumes entries (snapshot subvolumes cannot be recreated). # In this case inform the user that nothing can be done for activated snapshot subvolumes entries: if test "btrfssnapshotsubvol" = "$keyword" ; then info_message="It is not possible to recreate btrfs snapshot subvolumes, skipping $subvolume_path on $device at $mountpoint" LogPrint $info_message echo "# $info_message" >> "$LAYOUT_CODE" fi done < <( grep "btrfssnapshotsubvol $device $mountpoint " "$LAYOUT_FILE" | sed -e 's/.*#.*btrfssnapshotsubvol/#btrfssnapshotsubvol/' ) ########################################### # Btrfs normal subvolumes setup: # Create the normal btrfs subvolumes before the btrfs default subvolume setup # because currently the whole btrfs filesystem (i.e. its top-level/root subvolume) is mounted at the mountpoint # so that currently normal btrfs subvolumes can be created using the subvolume path relative to the btrfs toplevel/root subvolume # and that subvolume path relative to the btrfs toplevel/root subvolume is stored in the LAYOUT_FILE. # In contrast after the btrfs default subvolume setup only the btrfs filesystem default subvolume is mounted at the mountpoint and # then it would be no longer possible to create btrfs subvolumes with the subvolume path that is stored in the LAYOUT_FILE. # In particular a special btrfs default subvolume (i.e. when the btrfs default subvolume is not the toplevel/root subvolume) - # is also listed as a normal subvolume so that also the subvolume that is later used as default subvolume is hereby created. + # is also listed as a normal subvolume so that also the subvolume that is later used as default subvolume is hereby created + # provided the btrfs default subvolume is not a btrfs snapshot subvolume as in SLES 12 SP1 - but not in SLES 12 (without SP1): while read dummy dummy dummy dummy subvolume_path junk ; do # Empty subvolume_path may indicate an error. In this case be verbose and inform the user: if test -z "$subvolume_path" ; then LogPrint "btrfsnormalsubvol entry with empty subvolume_path for $device at $mountpoint may indicate an error, skipping subvolume setup for it." continue fi + # In case of SLES 12 SP1 special btrfs subvolumes setup + # skip setup of the normal btrfs subvolume '@/.snapshots' because + # that one will be created by "snapper/installation-helper --step 1" + # which fails if it already exists: + if test -n "$SLES12SP1_btrfs_subvolumes_setup" ; then + test "$subvolume_path" = "@/.snapshots" && continue + fi # When there is a non-empty subvolume_path, btrfs normal subvolume setup is needed: Log "Setup normal subvolume $subvolume_path for $device at $mountpoint" # E.g. for 'btrfs subvolume create /foo/bar/subvol' the directory path /foo/bar/ must already exist # but 'subvol' must not exist because 'btrfs subvolume create' creates the subvolume 'subvol' itself. # When 'subvol' already exists (e.g. as normal directory), it fails with ERROR: '/foo/bar/subvol' exists. subvolume_directory_path=${subvolume_path%/*} if test "$subvolume_directory_path" = "$subvolume_path" ; then # When subvolume_path is only plain 'mysubvol' then also subvolume_directory_path becomes 'mysubvol' # but 'mysubvol' must not be made as a normal directory by 'mkdir' below: subvolume_directory_path="" fi recovery_system_mountpoint=$recovery_system_root$mountpoint info_message="Creating normal btrfs subvolume $subvolume_path on $device at $mountpoint" Log $info_message ( echo "# $info_message" if test -n "$subvolume_directory_path" ; then # Test in the recovery system if the directory path already exists to avoid that # useless 'mkdir -p' commands are run which look confusing in the "rear recover" log # regardless that 'mkdir -p' does nothing when its argument already exists: echo "if ! test -d $recovery_system_mountpoint/$subvolume_directory_path ; then" echo " mkdir -p $recovery_system_mountpoint/$subvolume_directory_path" echo "fi" fi echo "btrfs subvolume create $recovery_system_mountpoint/$subvolume_path" ) >> "$LAYOUT_CODE" done < <( grep "^btrfsnormalsubvol $device $mountpoint " "$LAYOUT_FILE" ) ########################################### # Btrfs default subvolume setup: - # There is exactly one default subvolume for one btrfs filesystem on one specific device (usually a harddisk partition like e.g. /dev/sda1): + # No outer 'while read ...' loop because there is exactly one default subvolume for one btrfs filesystem + # on one specific device (usually a harddisk partition like e.g. /dev/sda1): read dummy dummy dummy dummy subvolume_path junk < <( grep "^btrfsdefaultsubvol $device $mountpoint " "$LAYOUT_FILE" ) # Artificial 'for' clause that is run only once to be able to 'continue' in the same syntactical way as in the 'while' loops # (because the 'for' loop is run only once 'continue' is the same as 'break'): for dummy in "once" ; do # Empty subvolume_path may indicate an error. In this case be verbose and inform the user: if test -z "$subvolume_path" ; then LogPrint "btrfsdefaultsubvol entry with empty subvolume_path for $device at $mountpoint may indicate an error, skipping default subvolume setup for it." continue fi # When there is a non-empty subvolume_path, btrfs default subvolume setup is needed: Log "Setup default subvolume $subvolume_path for $device at $mountpoint" # Remember the btrfs default subvolume on that specific device which is needed when mounting all btrfs normal subvolumes below # (also needed when the default subvolume path is "/" to avoid that it gets remounted when mounting normal subvolumes below): default_subvolume_path="$subvolume_path" # When subvolume_path is "/", the default for the btrfs default subvolume is used # (i.e. the btrfs default subvolume is the toplevel/root subvolume): if test "/" = "$subvolume_path" ; then info_message="No special btrfs default subvolume is used on $device at $mountpoint, no default subvolume setup needed" Log $info_message echo "# $info_message" >> "$LAYOUT_CODE" continue fi - # When in the original system the btrfs filesystem had a special different default subvolume, + # When in the original system the btrfs filesystem had a special different default subvolume + # (i.e. when the btrfs default subvolume is not the toplevel/root subvolume), then # that different subvolume needs to be set to be the default subvolume: recovery_system_mountpoint=$recovery_system_root$mountpoint Log "Setting $subvolume_path as btrfs default subvolume for $device at $mountpoint" - ( - echo "# Begin btrfs default subvolume setup on $device at $mountpoint" - echo "# Making the $subvolume_path subvolume the default subvolume" - echo "# Get the ID of the $subvolume_path subvolume" - echo "subvolumeID=\$( btrfs subvolume list -a $recovery_system_mountpoint | sed -e 's/<FS_TREE>\///' | grep ' $subvolume_path\$' | tr -s '[:blank:]' ' ' | cut -d ' ' -f 2 )" - echo "# Set the $subvolume_path subvolume as default subvolume using its subvolume ID" - echo "btrfs subvolume set-default \$subvolumeID $recovery_system_mountpoint" - ) >> "$LAYOUT_CODE" + if test -n "$SLES12SP1_btrfs_subvolumes_setup" ; then + ( + echo "# Begin btrfs default subvolume setup on $device at $mountpoint" + echo "# Doing special SLES 12 SP1 btrfs default snapper snapshot subvolume setup" + echo "# because the default subvolume path '$subvolume_path' contains '@/.snapshots/'" + echo "# Making the $SLES12SP1_initial_default_subvolume_path subvolume the initial default subvolume" + echo "# Get the ID of the $initial_default_subvolume_path subvolume" + echo "subvolumeID=\$( btrfs subvolume list -a $recovery_system_mountpoint | sed -e 's/<FS_TREE>\///' | grep ' $SLES12SP1_initial_default_subvolume_path\$' | tr -s '[:blank:]' ' ' | cut -d ' ' -f 2 )" + echo "# Set the $SLES12SP1_initial_default_subvolume_path subvolume as initial default subvolume using its subvolume ID" + echo "btrfs subvolume set-default \$subvolumeID $recovery_system_mountpoint" + echo "# Begin step 1 of special SLES 12 SP1 btrfs default snapper snapshot subvolume setup" + echo "umount $recovery_system_mountpoint" + echo "# Configuring snapper for root filesystem - step 1:" + echo "# - temporarily mounting device" + echo "# - copying/modifying config-file" + echo "# - creating filesystem config" + echo "# - creating snapshot of first root filesystem" + echo "# - setting default subvolume" + echo "if test -x $SLES12SP1_installation_helper_executable" + echo "then $SLES12SP1_installation_helper_executable --step 1 --device $device --description 'first root filesystem'" + echo "else LogPrint '$SLES12SP1_installation_helper_executable not executable may indicate an error with btrfs default subvolume setup for $subvolume_path on $device'" + echo "fi" + echo " mount -t btrfs -o subvolid=0 $mountopts $device $recovery_system_mountpoint" + echo "# End step 1 of special SLES 12 SP1 btrfs default snapper snapshot subvolume setup" + ) >> "$LAYOUT_CODE" + else + ( + echo "# Begin btrfs default subvolume setup on $device at $mountpoint" + echo "# Making the $subvolume_path subvolume the default subvolume" + echo "# Get the ID of the $subvolume_path subvolume" + echo "subvolumeID=\$( btrfs subvolume list -a $recovery_system_mountpoint | sed -e 's/<FS_TREE>\///' | grep ' $subvolume_path\$' | tr -s '[:blank:]' ' ' | cut -d ' ' -f 2 )" + echo "# Set the $subvolume_path subvolume as default subvolume using its subvolume ID" + echo "btrfs subvolume set-default \$subvolumeID $recovery_system_mountpoint" + ) >> "$LAYOUT_CODE" + fi # When the btrfs filesystem has a special default subvolume (one that is not the toplevel/root subvolume) # then a reasonable assumption is that this one was mounted in the original system and not something else. # FIXME: It is possible that the admin has actually mounted something else in his original system # which would result a wrong recovery because currently such an awkward setup is not supported. # Under the above assumption the btrfs filesystem needs to be umonted and mounted again so that # the special default subvolume gets mounted in the recovery system at /mnt/local$mountpoint. Log "Remounting the btrfs default subvolume $subvolume_path for $device at $mountpoint" ( echo "# Remounting the $subvolume_path default subvolume at $recovery_system_mountpoint" echo "umount $recovery_system_mountpoint" echo "mount -t btrfs $mountopts $device $recovery_system_mountpoint" echo "# End btrfs default subvolume setup on $device at $mountpoint" ) >> "$LAYOUT_CODE" done ########################################### # Mounting all btrfs normal subvolumes: # After the btrfs default subvolume setup now the btrfs default subvolume is mounted and then it is possible # to mount the other btrfs normal subvolumes at their mountpoints in the tree of the mounted filesystems: while read dummy dummy subvolume_mountpoint subvolume_mount_options subvolume_path junk ; do # Empty subvolume_mountpoint or subvolume_mount_options or subvolume_path may indicate an error. # E.g. missing subvolume mount options result that the subvolume path is read into subvolume_mount_options and subvolume_path becomes empty. # Therefore be verbose and inform the user: if test -z "$subvolume_mountpoint" -o -z "$subvolume_mount_options" -o -z "$subvolume_path" ; then LogPrint "btrfsmountedsubvol entry for $device where subvolume_mountpoint='$subvolume_mountpoint' or subvolume_mount_options='$subvolume_mount_options' or subvolume_path='$subvolume_path' is empty may indicate an error, skipping mounting it." continue fi # When there are non-empty values, mounting normal subvolume is needed: Log "Mounting normal subvolume $subvolume_path at $subvolume_mountpoint for $device" + # btrfs mount options like subvolid=259 or subvol=/@/.snapshots/1/snapshot + # from the old system cannot work here or are not needed here for recovery + # because for new created btrfs subvolumes their subvolid is likely different + # and the subvol=... value is already explicitly available via subvolume_path + # so that those mount options are removed here: + # First add a comma at the end so that it is easier to remove a mount option at the end: + subvolume_mount_options=${subvolume_mount_options/%/,} + # Remove all subvolid= and subvol= mount options (the extglob shell option is enabled in rear): + subvolume_mount_options=${subvolume_mount_options//subvolid=*([^,]),/} + subvolume_mount_options=${subvolume_mount_options//subvol=*([^,]),/} + # Remove all commas at the end: + subvolume_mount_options=${subvolume_mount_options/%,/} # Do not mount btrfs snapshot subvolumes: for snapshot_subvolume_device_and_path in $snapshot_subvolumes_devices_and_paths ; do # Assume $snapshot_subvolume_device_and_path is "/dev/sdX99,my/subvolume,path" then split # at the first comma because device nodes (e.g. /dev/sdX99) do not contain a comma # but a subvolume path may contain a comma (e.g. my/subvolume,path). # If a subvolume path contains space or tab characters it will break here # because space tab and newline are standard bash internal field separators ($IFS) # so that admins who use such characters for their subvolume paths get hereby # an exercise in using fail-safe names and/or how to enhance standard bash scripts: snapshot_subvolume_device=${snapshot_subvolume_device_and_path%%,*} snapshot_subvolume_path=${snapshot_subvolume_device_and_path#*,} if test "$device" = "$snapshot_subvolume_device" -a "$subvolume_path" = "$snapshot_subvolume_path" ; then info_message="It is not possible to recreate btrfs snapshot subvolumes, skipping mounting $subvolume_path on $device at $subvolume_mountpoint" Log $info_message echo "# $info_message" >> "$LAYOUT_CODE" # If one snapshot_subvolume_device_and_path matches, # continue with the next btrfsmountedsubvol line from the LAYOUT_FILE # (i.e. continue with the while loop which is the 2th enclosing loop): continue 2 fi done recovery_system_mountpoint=$recovery_system_root$subvolume_mountpoint # Remounting is needed when at the '/' mountpoint not the btrfs default subvolume is mounted: # On Fedora 21 what is mounted at the root of the filesystem tree (i.e. at the '/' mountpoint) # is not the btrfs default subvolume (the default subvolume is the toplevel/root subvolume). # On Fedora 21 there is a btrfs subvolume "root" which is mounted at the '/' mountpoint. # I (jsm...@suse.de) am not a btrfs expert but from my point of view it looks like # a misconfiguration (a.k.a. bug) in Fedora 21 how they set up btrfs. I think Fedora - # should specify as btrfs default subvolume what is mounted at the '/' mountpoint. - # Regardless if it is really a misconfiguration or not I like to have rear working fail-safe - # because an admin could manually create such an awkward btrfs setup. + # should specify as btrfs default subvolume what is mounted by default at the '/' mountpoint. + # On the other hand I noticed an openSUSE user who presented arguments that + # the btrfs default subvolume setting only belongs to the user and + # should not be used by the system to specify what is mounted by default, + # see what Chris Murphy wrote on the "Default btrfs subvolume after a rollback" + # and "systemd, btrfs, /var/lib/machines" mail threads on opensuse-fact...@opensuse.org + # http://lists.opensuse.org/opensuse-factory/2015-07/msg00517.html + # http://lists.opensuse.org/opensuse-factory/2015-07/msg00591.html + # and his GitHub snapper issue and openSUSE feature request + # "snapper improperly usurps control of the default subvolume from the user" + # https://github.com/openSUSE/snapper/issues/178 + # https://features.opensuse.org/319292 + # Regardless who or what is right or wrong here I like to have rear working fail-safe + # because an admin could manually create any kind of awkward btrfs setup. # Therefore remounting is needed when the subvolume_mountpoint is '/' # but the subvolume_path is neither '/' nor the default subvolume. # Examples: disklayout.conf contains # on openSUSE 13.2 at '/' the default subvolume which is the root subvolume (ID 5 '/') is mounted: # btrfsdefaultsubvol /dev/sda2 / 5 / # btrfsmountedsubvol /dev/sda2 / rw,relatime,space_cache / # on SLES 12 at '/' the default subvolume '@' is mounted: # btrfsdefaultsubvol /dev/sda2 / 257 @ # btrfsmountedsubvol /dev/sda2 / rw,relatime,space_cache @ + # on SLES 12 SP1 at '/' the default subvolume '@/.snapshots/1/snapshot' is mounted: + # btrfsdefaultsubvol /dev/sda2 / 259 @/.snapshots/1/snapshot + # #btrfssnapshotsubvol /dev/sda2 / 259 @/.snapshots/1/snapshot + # btrfsnormalsubvol /dev/sda2 / 258 @/.snapshots + # btrfsmountedsubvol /dev/sda2 / rw,relatime,space_cache,subvolid=259,subvol=/@/.snapshots/1/snapshot @/.snapshots/1/snapshot # on Fedora 21 at '/' not the default subvolume which is the root subvolume (ID 5 '/') but the subvolume 'root' is mounted: # btrfsdefaultsubvol /dev/sda3 / 5 / # btrfsmountedsubvol /dev/sda3 / rw,relatime,seclabel,space_cache root # FIXME: Currently only for the mountpoint '/' there is this special handling. # In general the subvolume_mountpoint could be anything. # For example for a second disk /dev/sdb1 the disklayout.conf file could contain those entries: # btrfsdefaultsubvol /dev/sdb1 /data 5 / # btrfsmountedsubvol /dev/sdb1 /data rw,relatime,seclabel,space_cache datasubvol # This would mean for /dev/sdb1 what is mounted at its mountpoint /data # is not its btrfs default subvolume but the btrfs subvolume "datasubvol". # Currently such a setup is not supported for mountpoints other than '/'. if test '/' = "$subvolume_mountpoint" ; then # No remounting needed when the subvolume_path is the default_subvolume_path for this device # because then the default subvolume is already mounted by the "Btrfs default subvolume setup" above: if test "$subvolume_path" = "$default_subvolume_path" ; then Log "On $device btrfs default subvolume $default_subvolume_path already mounted at $subvolume_mountpoint, no remounting needed" continue