mrrl-system-config

system configuration on top of MRRL
git clone https://ccx.te2000.cz/git/mrrl-system-config
Log | Files | Refs

postinstall (5360B)


      1 #!/bin/zsh
      2 setopt no_unset warn_create_global extended_glob
      3 
      4 # error handling
      5 typeset -ga revert
      6 
      7 die_ret() {
      8 	local ret step
      9 	ret=$1
     10 	shift
     11 	printf >&2 '%s\n' "$@"
     12 	for step in $revert; do
     13 		printf >&2 '* Running revert step: %s\n' $step
     14 		$step
     15 	done
     16 	exit $ret
     17 }
     18 die() {
     19 	die_ret 1 "$@"
     20 }
     21 die100() {  # 100: wrong usage
     22 	die_ret 100 "$@"
     23 }
     24 die111() {  # 111: system call failed
     25 	die_ret 111 "$@"
     26 }
     27 -() {
     28 	"$@" || die_ret $? "Command failed: $*"
     29 }
     30 fatal100() {
     31 	die_ret 100 "Fatal: ${(qqq)this_command:t}: $@"
     32 }
     33 fatal111() {
     34 	die_ret 111 "Fatal: ${(qqq)this_command:t}: $@"
     35 }
     36 
     37 # modules
     38 - zmodload -F zsh/stat b:zstat
     39 - zmodload -m -F zsh/files b:zf_\*
     40 - zmodload zsh/datetime  # for $EPOCHREALTIME
     41 
     42 # functions
     43 link_changed() {
     44 	local prev curr
     45 	prev=${${:-$prev_env/$1}:P}
     46 	curr=${${:-$current_env/$1}:P}
     47 	[[ "$prev" != "$curr" ]]
     48 }
     49 
     50 setup_rc() {
     51 	local diff_ret prev_source curr_source
     52 	prev_source=$prev_env/config/s6-rc-source
     53 	curr_source=./config/s6-rc-source
     54 	curr_db=./config/s6-rc-db
     55 	# Check if s6-rc definition changed
     56 	diff -r -q $prev_source $curr_source; diff_ret=$?
     57 	(( $diff_ret == 0 || $diff_ret == 1 )) || \
     58 		die111 "Could not diff s6-rc-source directories; exitcode $diff_ret"
     59 	if link_changed command/s6-rc; then
     60 		if (( $diff_ret == 1 )); then
     61 			# Both s6-rc DB source and installed software changed.
     62 			# s6-rc-format-upgrade to tmpdir, then s6-rc-update
     63 			local tmp_db=/run/old-s6-rc-db-migration.$EPOCHREALTIME
     64 
     65 			s6-rc-compile $tmp_db $prev_source || return $?
     66 			s6-rc-format-upgrade -v2 $tmp_db || return $?
     67 			s6-rc-update -v2 $curr_db:P || return $?
     68 			zf_rm -r $tmp_db || return $?
     69 		else
     70 			# Installed software changed but s6-rc DB source is the same.
     71 			# s6-rc-format-upgrade to new compiled DB directly
     72 			s6-rc-format-upgrade -v2 $curr_db:P || return $?
     73 		fi
     74 	elif (( $diff_ret == 1 )); then
     75 		# s6-rc DB source changed while keeping same version of software.
     76 		# s6-rc-update to new compiled DB directly
     77 		s6-rc-update -v2 $curr_db:P || return $?
     78 	fi
     79 	s6-rc -v2 -u -t 30000 change ok-all
     80 	true
     81 }
     82 
     83 setup_containers() {
     84 	# Check if we need to regenerate containers or their service directories.
     85 	if link_changed bzr/containers || link_changed bzr/confz; then
     86 		if (( $+confz_verbose )); then
     87 			zsh -lc "verbose=1 confz site_containers" </dev/null 2>&1 | cat -v
     88 			ret=$((${(j.|.)pipestatus}))  # Nonzero iff any of commands in pipeline returned nonzero.
     89 		else
     90 			zsh -lc "quiet=1 confz site_containers" </dev/null 2>&1 | cat -v
     91 			ret=$((${(j.|.)pipestatus}))  # Nonzero iff any of commands in pipeline returned nonzero.
     92 		fi
     93 		if (($ret)); then 
     94 			echo >&2 "Error: command failed ($ret): confz site_containers"
     95 			return $ret
     96 		fi
     97 		s6-svscanctl -a /run/service || return $?
     98 	fi
     99 }
    100 
    101 setup_fileset() {
    102 	local -a rsync=(
    103 		rsync
    104 		-a  # TODO compile rsync with ACL support
    105 		--delete
    106 		--log-format=$'%i\t%B\t%U:%G\t%M\t%l\t%n'
    107 		--filter="merge config/postinstall.rsfilter"
    108 		--filter='- *'
    109 	)
    110 	$rsync --delete-excluded --log-file $SETUP_DIR/rsync.log.get / $SETUP_DIR/files.pre/ || return $?
    111 	cp -a --reflink=auto $SETUP_DIR/files.pre $SETUP_DIR/files.post || return $?
    112 	./command/fileset ./config/postinstall.fileset >$SETUP_DIR/files.sh || exit $?
    113 	(cd $SETUP_DIR/files.post && exec sh ../files.sh) || exit $?
    114 	zf_mkdir $SETUP_DIR/files.bak || return $?
    115 	revert+=( revert_fileset )
    116 	$rsync --log-file $SETUP_DIR/rsync.log.put $SETUP_DIR/files.post/ / --backup --backup-dir=$SETUP_DIR/files.bak || return $?
    117 }
    118 
    119 revert_fileset() {
    120 	rsync -a --log-format=$'%i\t%B\t%U:%G\t%M\t%l\t%n' --log-file $SETUP_DIR/rsync.log.revert $SETUP_DIR/files.bak/ /
    121 }
    122 
    123 setup_containers() {
    124 	execlineb -P ./config/s6-rc-source/containers/up || return $?
    125 }
    126 
    127 # main function
    128 postinstall() {
    129 	- cd $current
    130 	typeset -g SETUP_DIR
    131 	if (( $# )); then
    132 		SETUP_DIR=$versions/postinstall/$EPOCHSECONDS.${current_env:t}..${prev_env:t}
    133 	else
    134 		SETUP_DIR=$versions/postinstall/$EPOCHSECONDS.${current_env:t}
    135 	fi
    136 	- zf_mkdir -p $SETUP_DIR
    137 
    138 	- setup_fileset
    139 
    140 	if (( $# )); then
    141 		- setup_rc
    142 		- setup_containers
    143 	fi
    144 	exit 0
    145 }
    146 typeset -ft postinstall
    147 
    148 typeset -g versions current
    149 current=/run/current
    150 versions=/versions
    151 
    152 typeset -g this_command this_conf current_command current_env current_conf
    153 this_command=$0
    154 this_conf=$0:P:h:h
    155 current_command=$current/command/install-as-current-environment.postinstall
    156 current_env=$current_command:h:P:h
    157 current_conf=$current_command:P:h:h
    158 
    159 # arguments and validation
    160 if (( $# > 1 )); then
    161 	fatal100 "Too many arguments"
    162 fi
    163 if [[ $0:P != $versions/* ]]; then
    164 	fatal100 "This script expects to be installed under ${(qqq)versions}."
    165 fi
    166 this_command=$current/command/install-as-current-environment.postinstall
    167 if [[ $0:P != $current_command:P ]]; then
    168 	fatal111 "Fatal: This script needs to be run after installing the given environment as ${(qqq)current}."
    169 fi
    170 if (( $# )); then
    171 	typeset -g prev_command prev_env prev_conf
    172 	prev_command=$1/command/install-as-current-environment.postinstall
    173 	prev_env=$1:P
    174 	prev_conf=$prev_command:P:h:h
    175 	if [[ $prev_env != $versions/* ]]; then
    176 		fatal111 "Old version doesn't seem to be inside ${(qqq)versions}: ${(qqq)prev_env}."
    177 	fi
    178 	if ! [[ $prev_env:t == env.* ]]; then
    179 		fatal111 "Unexpected previous environment name: ${(qqq)prev_env}"
    180 	fi
    181 fi
    182 if ! [[ $current_env:t == env.* ]]; then
    183 	fatal111 "Unexpected current environment name: ${(qqq)current_env}"
    184 fi
    185 
    186 - postinstall "$@"