summaryrefslogtreecommitdiffstats
path: root/modules.d/slx-addons/hooks/s3-setup-addons.sh
blob: 5068d2c27e5ca928984b5eabcd987cc6e4d0cce2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/bin/bash
#
# Stage4 addons setup script
#
###############################################################################
# Support stage4 addons residing under '/opt/openslx/addons'.
# This script will loop over all addons found, in the form of
# directories containing directory structures relative to '/'
#
# Additionally addons are expected to provide:
# * <addon_dir>/addon-required -> script to check whether the
#   addon should be installed (exit 0) or not (exit 1).
#
# * <addon_dir>/opt/openslx/etc/<addon_name>.whiteout -> list of files
#   that were removed during the addon installation and thus need to be
#   removed after the addon was installed.
#
# * <addon_dir>/opt/openslx/etc/<addon_name> ld.so.cache -> ld cache containing
#   the newly installed libraries. CAVE: multiple addons -> ld cache combination
#
### CURRENTLY NOT EXECUTED
# * <addon_dir>/addon-init -> script that will be automatically
#   be executed after the addon was installed.
#   NOTE: question remains if this should be done within stage3
#         or by chroot'ing into the stage4 before executing it.
### CURRENTLY NOT EXECUTED: Since whiteouts could be handled for _all_addons

# Check if we even have any addons to process
if ! [ -d "$NEWROOT/opt/openslx/addons" ]; then
	echo "No stage4 addons found."
	exit 0
fi

# This just activates the ldconfig service to run during the sysinit target
# Since addons are likely to install libs, this is necessary to garantee
# that the live system "sees" the libraries.
activate_stage4_ldconfig() {
	local service_path="/opt/openslx/services/ldconfig-stage4.service"
	[ -e "$service_path" ] || return 1
	local target_dir="${NEWROOT}/etc/systemd/system/sysinit.target.wants"
	mkdir -p "$target_dir"
	cp -f "$service_path" "${NEWROOT}/etc/systemd/system/${service_path##*/}"
	ln -sf "../${service_path##*/}" "${target_dir}/${service_path##*/}"
}

setup_addon() {
	if [ ! -d "$1" ]; then
		echo "Given '$1' not a directory, skipping."
		return 1
	fi
	local addon_dir="$1"
	cd "$addon_dir" || return 1
	if ! bash addon-required 2>&1 ; then
		echo "'$addon_dir/addon-required' missing or returned non-zero, skipping..."
		return 1
	fi
	# purge addon-* files
	rm -f -- addon-*

	# make directory struct, replicate owners/perms - should we keep-old-files?
	echo "Replicating directory tree in $NEWROOT"
	# Doing this once in advance instead of doing a mkdir for each file's parent directory
	# every time in the loop below brought us from 3.6s down to 2.2s for VMware
	find . -type d -print0 | tar --no-recursion --null -T - -c | tar -C "$NEWROOT" --keep-old-files -x
	# move all the files over
	echo "Moving files over"
	while read -r entry || [ -n "$entry" ]; do
		# Doing the mv in parallel brought us from 2.2s to 380ms for VMware (~850 files),
		# but I've no idea if there'd be an adverse effect if we had a lot more files
		# to move and we'd spawn thousands of mv processes in parallel...
		mv -f -- "$entry" "${NEWROOT}/${entry}" &
	done < <( find . -not -type d ) # do it this way so we don't end up with a pipe-subshell
	wait # and can properly wait for all the mv processes.

	# post merge: remove files marked as whiteouts
	# (e.g. they were removed during the addon installation)
	echo "Applying whiteouts"
	for WHITEOUT in "$NEWROOT/opt/openslx/etc/"*.whiteout; do
		[ -e "$WHITEOUT" ] || continue
		while read -r line; do
			rm -f -- "${NEWROOT}/${line}"
		done < "$WHITEOUT"
	done

	return 0
}

active=()
for addon in "${NEWROOT}/opt/openslx/addons/"*; do
	if setup_addon "$addon"; then
		active+=("${addon#"${NEWROOT}/opt/openslx/addons/"}")
		echo "Activated '$addon' (@ $(date +%s))"
	fi
done

# if only one addon was installed, use its pre-generated ld.so.cache
# if more than one were installed, make sure ldconfig is called in stage4
if [ "${#active[@]}" -eq 1 ]; then
	addon_cache="${NEWROOT}/opt/openslx/etc/${active[0]}.ld.so.cache"
	if [ -e "$addon_cache" ]; then
		echo "Using ld.so.cache of '${active[0]}'."
		mv -f -- "${NEWROOT}/etc/ld.so.cache"{,.stage4}
		mv -f -- "$addon_cache" "${NEWROOT}/etc/ld.so.cache"
	fi
elif [ "${#active[@]}" -gt 1 ]; then
	echo "Activating ldconfig in stage4 due to multiple loaded addons: ${active[*]}"
	activate_stage4_ldconfig
fi

exit 0