summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Gomes <tiago.gomes@codethink.co.uk>2013-06-15 23:40:34 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2013-06-25 15:31:15 +0100
commit51f930da27942f1e412a16d87e38c1d6e4d215a4 (patch)
tree6c040cb0b5f7f00ebfd450811ca207beb46b173e
parent160ccc9e93284ad567f476beb32620bb1e0e33b7 (diff)
downloadtbdiff-51f930da27942f1e412a16d87e38c1d6e4d215a4.tar.gz
Script to merge and syncronize /etc in different system versions
This commit adds a script to merge and syncronize /etc in different system versions. The first argument read from command line is the mode, which can be one of the following: - test: the purpose of this mode is to test some merge cases. It receives from the command line v1_dir, vu_dir and v2_dir and vt_dir. The meaning of these arguments is explained in the script. - merge: merges the user changes in /etc in the run system of the version given as argument - sync: syncronizes /etc in all run versions, so that this directory is exactly the same as the version given as argument. This commit also includes an auxiliary script to mount the systems directory in a give directory given as argument, and some testing folders to use with the test mode.
-rw-r--r--Makefile.am3
-rw-r--r--baserock-system-config-sync/Makefile.am20
-rwxr-xr-xbaserock-system-config-sync/baserock-system-config-sync216
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/11
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/afile0
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v1/sshd_config123
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v2/sshd_config123
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/vu/sshd_config123
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v1/10
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v2/10
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v1/10
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v2/10
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/11
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/afile0
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl11
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl21
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl31
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1f0
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl11
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl31
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl41
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2f0
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl11
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl21
l---------baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl41
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vuf0
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file12
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file42
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file52
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file72
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file7.18
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subfile110
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subsubdir2/subsubfile40
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file12
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file22
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file32
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file42
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file52
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file62
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file72
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file7.18
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subfile110
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subsubdir2/subsubfile40
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file22
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file52
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file62
-rw-r--r--baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file72
-rwxr-xr-xbaserock-system-config-sync/mount-system-versions-dir40
-rw-r--r--configure.ac1
49 files changed, 725 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 8c301ea..c31eaed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
# vi:set ts=8 sw=8 noet ai nocindent:
# -
-# Copyright (c) 2011-2012 Codethink Ltd.
+# Copyright (c) 2011-2013 Codethink Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License Version 2 as
@@ -21,6 +21,7 @@ SUBDIRS = \
tbdiff-deploy \
tb-switch \
tb-update \
+ baserock-system-config-sync \
tests
.PHONY: ChangeLog
diff --git a/baserock-system-config-sync/Makefile.am b/baserock-system-config-sync/Makefile.am
new file mode 100644
index 0000000..914dc99
--- /dev/null
+++ b/baserock-system-config-sync/Makefile.am
@@ -0,0 +1,20 @@
+# Copyright (c) 2013 Codethink Ltd.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License Version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+bin_SCRIPTS = \
+ baserock-system-config-sync
+
+libexec_SCRIPTS = \
+ mount-system-versions-dir
diff --git a/baserock-system-config-sync/baserock-system-config-sync b/baserock-system-config-sync/baserock-system-config-sync
new file mode 100755
index 0000000..00ceac0
--- /dev/null
+++ b/baserock-system-config-sync/baserock-system-config-sync
@@ -0,0 +1,216 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Codethink Ltd.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License Version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -eu
+
+
+mounting_script="$(dirname "$0")/../libexec/mount-system-versions-dir"
+
+
+usage() {
+ echo "Usage: $(basename $0) test V1_DIR VU_DIR V2_DIR VT_DIR" >&2
+ echo " $(basename $0) merge NEW_VERSION_LABEL" >&2
+ echo " $(basename $0) sync CANONICAL_VERSION_LABEL" >&2
+ exit 1
+}
+
+
+die () {
+ echo $@ >&2
+ exit 1
+}
+
+
+merge() {
+ local vp_dir="$1" # version being processed
+ local v1_dir="$2" # factory version
+ local vu_dir="$3" # user modified version
+ local v2_dir="$4" # unmodified new deployed version
+ local vt_dir="$5" # target version where the result of the
+ # merge should be placed
+
+ # use `find "$vp_dir/"*` instead of `find "$vp_dir"` because
+ # the last one also gives $vp_dir in the list of directories
+ find "$vp_dir/"* | while read f; do
+ # strip first component from file name
+ local stripped_filename=${f#$vp_dir/}
+
+ local vp="$vp_dir/$stripped_filename"
+ local v1="$v1_dir/$stripped_filename"
+ local vu="$vu_dir/$stripped_filename"
+ local v2="$v2_dir/$stripped_filename"
+ local vt="$vt_dir/$stripped_filename"
+
+ if [ -e "$vt" ]; then
+ # If the file already exists in the target,
+ # check if it is of the same kind
+ vp_type="$(stat -c %F "$vp")"
+ vt_type="$(stat -c %F "$vt")"
+ echo "$vp - $vt - $vp_type - $vt_type" >&2
+ if [ "$vp_type" != "$vt_type" ]; then
+ die "found two different types for '$stripped_filename':" \
+ "$vp_type and $vt_type"
+ fi
+ elif [ -d "$vp" ] && [ ! -h "$vp" ]; then
+ mkdir "$vt"
+ elif [ -h "$vp" ]; then
+ # Discussion: what we want to do about symbolic links?
+ # I chose a symbolic link in this order of preference:
+ # Vuser, V2, V1
+ if [ -h "$vu" ]; then
+ cp -a "$vu" "$vt"
+ elif [ -h "$v2" ]; then
+ cp -a "$v2" "$vt"
+ else
+ cp -a "$v1" "$vt"
+ fi
+ elif [ -f "$vp" ]; then
+ merge_regular_file "$v1" "$vu" "$v2" "$vt"
+ else
+ die "ERROR: unexpected error"
+ fi
+ done
+}
+
+
+merge_regular_file() {
+ local v1="$1"
+ local vu="$2"
+ local v2="$3"
+ local vt="$4"
+ # Reference table for merging a regular file
+ #
+ # V1 Vuser V2 action
+ # ------------------------------------------
+ # none none none inconceivable!
+ # exists none none use V1
+ # none exists none use Vuser
+ # none none exists use V2
+ # exists none exists use V2
+ # exists exists none use V2
+ # none exists exists diff V2 Vuser applied to V2
+ # exists exists exists diff V1 Vuser applied to V2
+
+ v1_exists=$(test -f "$v1" && echo exists || echo none)
+ vu_exists=$(test -f "$vu" && echo exists || echo none)
+ v2_exists=$(test -f "$v2" && echo exists || echo none)
+ case "$v1_exists $vu_exists $v2_exists" in
+ 'exists none none')
+ cp -a "$v1" "$vt"
+ ;;
+ 'none exists none')
+ cp -a "$vu" "$vt"
+ ;;
+ 'none none exists')
+ cp -a "$v2" "$vt"
+ ;;
+ 'exists none exists')
+ cp -a "$v2" "$vt"
+ ;;
+ 'exists exists none')
+ # In the relevant mustard node it is specified that
+ # when we have v1 and vu, but not v2, we shouldn't
+ # do nothing. I changed to copy the user configuration
+ # instead
+ cp -a "$vu" "$vt"
+ ;;
+ 'none exists exists')
+ # In the relevant mustard node it is specified a diff
+ # between /dev/null and vu. However this causes a
+ # complaint against reversed patches. The option
+ # "-R" didn't help.
+ if ! (diff "$v2" "$vu" | patch "$v2" -o "$vt"); then
+ cp -a "$v2" "$vt" # merge failed, use v2
+ fi
+ ;;
+ 'exists exists exists')
+ if ! (diff "$v1" "$vu" | patch "$v2" -o "$vt"); then
+ cp -a "$v2" "$vt" # merge failed, use v2
+ fi
+ ;;
+ *)
+ die "ERROR: unexpected error"
+ ;;
+ esac
+}
+
+
+if [ "$#" = 0 ]; then
+ usage "$0"
+fi
+
+
+if [ "$1" = "test" ]; then
+ if [ "$#" != 5 ]; then
+ usage "$0"
+ fi
+ local v1="$2"
+ local vu="$3"
+ local v2="$4"
+ local vt="$5"
+ mkdir -p "$vt"
+ # For every pathname in V1, Vuser, or V2
+ merge "$v1" "$v1" "$vu" "$v2" "$vt"
+ merge "$vu" "$v1" "$vu" "$v2" "$vt"
+ merge "$v2" "$v1" "$vu" "$v2" "$vt"
+elif [ "$1" = "merge" ]; then
+ if [ "$#" != 2 ]; then
+ usage "$0"
+ fi
+ local new_version="$2"
+ local mounting_point=$(mktemp -d)
+ "$mounting_script" "$mounting_point"
+ trap 'umount "$mounting_point"' INT ERR EXIT
+ if [ ! -d "$mounting_point/systems/$new_version" ]; then
+ die "Error: version not found - '$new_version'"
+ fi
+ local v1_dir="$mounting_point/systems/default/orig/etc"
+ local vu_dir="$mounting_point/systems/default/run/etc"
+ local v2_dir="$mounting_point/systems/$new_version/run/etc"
+ local vt_dir="$mounting_point/systems/$new_version/run/etc.new"
+ mkdir "$vt_dir"
+
+ # For every pathname in V1, Vuser, or V2
+ merge "$v1_dir" "$v1_dir" "$vu_dir" "$v2_dir" "$vt_dir"
+ merge "$vu_dir" "$v1_dir" "$vu_dir" "$v2_dir" "$vt_dir"
+ merge "$v2_dir" "$v1_dir" "$vu_dir" "$v2_dir" "$vt_dir"
+
+ rm -rf "$v2_dir"
+ mv "$vt_dir" "$v2_dir"
+elif [ "$1" = "sync" ]; then
+ local canonical_version="$2"
+ local mounting_point=$(mktemp -d)
+ "$mounting_script" "$mounting_point"
+ trap 'umount "$mounting_point"' INT EXIT
+ if [ ! -d "$mounting_point/systems/$canonical_version" ]; then
+ die "Error: version not found - '$canonical_version'"
+ fi
+ for version_dir in "$mounting_point/systems/"*; do
+ version="$(basename "$version_dir")"
+ if [ -d "$version_dir" ] && [ ! -h "$version_dir" ] \
+ && [ $version != $canonical_version ]; then
+ cp -a "$mounting_point/systems/$canonical_version/run/etc" \
+ "$version_dir/run/etc.new"
+ mv "$version_dir/run/etc" "$version_dir/run/etc.old"
+ mv "$version_dir/run/etc.new" "$version_dir/run/etc"
+ rm -rf "$version_dir/run/etc.old"
+ fi
+ done
+else
+ usage "$0"
+fi
+
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/1
new file mode 120000
index 0000000..6a93f4f
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/1
@@ -0,0 +1 @@
+afile \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/afile b/baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/afile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.dir.symb/vu/afile
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v1/sshd_config b/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v1/sshd_config
new file mode 100644
index 0000000..98fa27e
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v1/sshd_config
@@ -0,0 +1,123 @@
+# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
+
+# This is the sshd server system-wide configuration file. See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented. Uncommented options override the
+# default value.
+
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# The default requires explicit activation of protocol 1
+#Protocol 2
+
+# HostKey for protocol version 1
+#HostKey /etc/ssh/ssh_host_key
+# HostKeys for protocol version 2
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_ecdsa_key
+
+# Lifetime and size of ephemeral version 1 server key
+#KeyRegenerationInterval 1h
+#ServerKeyBits 1024
+
+# Logging
+# obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile .ssh/authorized_keys
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
+# similar for protocol version 2
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication. Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+#UsePAM no
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+#UseLogin no
+#UsePrivilegeSeparation yes
+PermitUserEnvironment yes
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#UseDNS yes
+#PidFile /var/run/sshd.pid
+#MaxStartups 10
+#PermitTunnel no
+#ChrootDirectory none
+
+# no default banner path
+#Banner none
+
+# override default of no subsystems
+Subsystem sftp /usr/lib/openssh/sftp-server
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+# X11Forwarding no
+# AllowTcpForwarding no
+# ForceCommand cvs server
+
+AcceptEnv LANG LC_*
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v2/sshd_config b/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v2/sshd_config
new file mode 100644
index 0000000..4e6a5d3
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/v2/sshd_config
@@ -0,0 +1,123 @@
+# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
+
+# This is the sshd server system-wide configuration file. See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented. Uncommented options override the
+# default value.
+
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# The default requires explicit activation of protocol 1
+#Protocol 2
+
+# HostKey for protocol version 1
+#HostKey /etc/ssh/ssh_host_key
+# HostKeys for protocol version 2
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_ecdsa_key
+
+# Lifetime and size of ephemeral version 1 server key
+#KeyRegenerationInterval 1h
+#ServerKeyBits 1024
+
+# Logging
+# obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile .ssh/authorized_keys
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
+# similar for protocol version 2
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication. Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+#UsePAM no
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+#UseLogin no
+#UsePrivilegeSeparation yes
+PermitUserEnvironment yes
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#UseDNS yes
+#PidFile /var/run/sshd.pid
+#MaxStartups 10
+#PermitTunnel no
+ChrootDirectory none
+
+# no default banner path
+#Banner none
+
+# override default of no subsystems
+Subsystem sftp /usr/lib/openssh/sftp-server
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+# X11Forwarding no
+# AllowTcpForwarding no
+# ForceCommand cvs server
+
+AcceptEnv LANG LC_*
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/vu/sshd_config b/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/vu/sshd_config
new file mode 100644
index 0000000..c4b25e9
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.etc/vu/sshd_config
@@ -0,0 +1,123 @@
+# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
+
+# This is the sshd server system-wide configuration file. See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented. Uncommented options override the
+# default value.
+
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# The default requires explicit activation of protocol 1
+#Protocol 2
+
+# HostKey for protocol version 1
+#HostKey /etc/ssh/ssh_host_key
+# HostKeys for protocol version 2
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_ecdsa_key
+
+# Lifetime and size of ephemeral version 1 server key
+#KeyRegenerationInterval 1h
+#ServerKeyBits 1024
+
+# Logging
+# obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile .ssh/authorized_keys
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
+# similar for protocol version 2
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication. Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+#UsePAM no
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+UseLogin no
+#UsePrivilegeSeparation yes
+PermitUserEnvironment yes
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#UseDNS yes
+#PidFile /var/run/sshd.pid
+#MaxStartups 10
+#PermitTunnel no
+#ChrootDirectory none
+
+# no default banner path
+#Banner none
+
+# override default of no subsystems
+Subsystem sftp /usr/lib/openssh/sftp-server
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+# X11Forwarding no
+# AllowTcpForwarding no
+# ForceCommand cvs server
+
+AcceptEnv LANG LC_*
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v1/1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v1/1
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v1/1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v2/1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v2/1
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.dir/v2/1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v1/1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v1/1
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v1/1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v2/1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v2/1
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/v2/1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/1
new file mode 120000
index 0000000..6a93f4f
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/1
@@ -0,0 +1 @@
+afile \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/afile b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/afile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.regular.symb/vu/afile
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl1
new file mode 120000
index 0000000..d09a60b
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl1
@@ -0,0 +1 @@
+../v1f \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl2 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl2
new file mode 120000
index 0000000..d09a60b
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl2
@@ -0,0 +1 @@
+../v1f \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl3 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl3
new file mode 120000
index 0000000..d09a60b
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1/sl3
@@ -0,0 +1 @@
+../v1f \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1f b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1f
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v1f
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl1
new file mode 120000
index 0000000..e4b01f1
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl1
@@ -0,0 +1 @@
+../v2f \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl3 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl3
new file mode 120000
index 0000000..e4b01f1
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl3
@@ -0,0 +1 @@
+../v2f \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl4 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl4
new file mode 120000
index 0000000..e4b01f1
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2/sl4
@@ -0,0 +1 @@
+../v2f \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2f b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2f
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/v2f
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl1
new file mode 120000
index 0000000..fcf9fc4
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl1
@@ -0,0 +1 @@
+../vuf \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl2 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl2
new file mode 120000
index 0000000..fcf9fc4
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl2
@@ -0,0 +1 @@
+../vuf \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl4 b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl4
new file mode 120000
index 0000000..fcf9fc4
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vu/sl4
@@ -0,0 +1 @@
+../vuf \ No newline at end of file
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vuf b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vuf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades.symblinks/vuf
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file1
new file mode 100644
index 0000000..b73be5d
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file1
@@ -0,0 +1,2 @@
+whereami=v1
+version=v1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file4 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file4
new file mode 100644
index 0000000..9972a7a
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file4
@@ -0,0 +1,2 @@
+whereami=v1,v2
+version=v1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file5 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file5
new file mode 100644
index 0000000..8fbeda2
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file5
@@ -0,0 +1,2 @@
+whereami=v1,vu
+version=v1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file7 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file7
new file mode 100644
index 0000000..7c1f4fb
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file7
@@ -0,0 +1,2 @@
+whereami=v1,vu,v2
+version=v1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file7.1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file7.1
new file mode 100644
index 0000000..d579e7b
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/file7.1
@@ -0,0 +1,8 @@
+a=1
+b=2
+c=3
+whereami=v1,vu,v2
+version=v1
+d=1
+e=2
+f=3
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subfile1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subfile1
new file mode 100644
index 0000000..1cb075e
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subfile1
@@ -0,0 +1,10 @@
+qeq asda d
+s
+d
+a sd
+a
+d
+a
+d
+
+d
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subsubdir2/subsubfile4 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subsubdir2/subsubfile4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v1/subdir1/subsubdir2/subsubfile4
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file1
new file mode 100644
index 0000000..b73be5d
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file1
@@ -0,0 +1,2 @@
+whereami=v1
+version=v1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file2 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file2
new file mode 100644
index 0000000..9fa9381
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file2
@@ -0,0 +1,2 @@
+whereami=vu
+version=vu
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file3 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file3
new file mode 100644
index 0000000..b1580e3
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file3
@@ -0,0 +1,2 @@
+whereami=vu
+version=v2
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file4 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file4
new file mode 100644
index 0000000..ebc4914
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file4
@@ -0,0 +1,2 @@
+whereami=v1,v2
+version=v2
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file5 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file5
new file mode 100644
index 0000000..8fbeda2
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file5
@@ -0,0 +1,2 @@
+whereami=v1,vu
+version=v1
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file6 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file6
new file mode 100644
index 0000000..e76efb0
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file6
@@ -0,0 +1,2 @@
+whereami=vu,v2
+version=v2
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file7 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file7
new file mode 100644
index 0000000..93c46eb
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file7
@@ -0,0 +1,2 @@
+whereami=v1,vu,v2
+version=v2
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file7.1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file7.1
new file mode 100644
index 0000000..2462a4f
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/file7.1
@@ -0,0 +1,8 @@
+a=1
+b=2
+c=3
+whereami=v1,vu,v2
+version=v2
+d=1
+e=2
+f=3
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subfile1 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subfile1
new file mode 100644
index 0000000..1cb075e
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subfile1
@@ -0,0 +1,10 @@
+qeq asda d
+s
+d
+a sd
+a
+d
+a
+d
+
+d
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subsubdir2/subsubfile4 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subsubdir2/subsubfile4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/v2/subdir1/subsubdir2/subsubfile4
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file2 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file2
new file mode 100644
index 0000000..9fa9381
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file2
@@ -0,0 +1,2 @@
+whereami=vu
+version=vu
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file5 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file5
new file mode 100644
index 0000000..eddf4ca
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file5
@@ -0,0 +1,2 @@
+whereami=v1,vu
+version=vu
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file6 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file6
new file mode 100644
index 0000000..9802a97
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file6
@@ -0,0 +1,2 @@
+whereami=vu,v2
+version=vu
diff --git a/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file7 b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file7
new file mode 100644
index 0000000..24553ad
--- /dev/null
+++ b/baserock-system-config-sync/config-sync-tests/tests.upgrades/vu/file7
@@ -0,0 +1,2 @@
+whereami=v1,vu,v2
+version=vu
diff --git a/baserock-system-config-sync/mount-system-versions-dir b/baserock-system-config-sync/mount-system-versions-dir
new file mode 100755
index 0000000..6028ea4
--- /dev/null
+++ b/baserock-system-config-sync/mount-system-versions-dir
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Codethink Ltd.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License Version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -eu
+
+
+usage() {
+ echo usage: "$(basename $0) mounting_point" >&2
+ exit 1
+}
+
+
+
+if [ "$#" != 1 ]; then
+ usage $0
+fi
+
+
+mouting_point="$1"
+
+disk=$(awk '{ if ($1 != "rootfs" && $2 == "/") print $1 }' /proc/mounts)
+
+mkdir -p "$mouting_point"
+
+mount "$disk" "$mouting_point"
+
diff --git a/configure.ac b/configure.ac
index e0ba901..17ec2dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -121,6 +121,7 @@ tbdiff-create/Makefile
tbdiff-deploy/Makefile
tb-switch/Makefile
tb-update/Makefile
+baserock-system-config-sync/Makefile
tests/Makefile
])