summaryrefslogtreecommitdiffstats
path: root/builder/dnbd3-qcow2-rootfs/scripts/setup-qcow2
blob: 70babc17cef22569b1b18bea78b95dcdbc3351c1 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/bash

# dracut-lib to use debugging functions
command -v warn >/dev/null || . /lib/dracut-lib.sh
command -v emergency_shell >/dev/null || . /lib/dracut-lib.sh

###############################################################################
# GLOBALS
#
# TODO make this configurable
[ -f /opt/openslx/config ] && . /opt/openslx/config
[ -z $SLX_DNBD3_SERVER ] && SLX_DNBD3_SERVER="132.230.4.1"
[ -z $SLX_STAGE4 ] && SLX_STAGE4="stage4/joe/centos7"
[ -z $SLX_STAGE4_RID ] && SLX_STAGE4_RID="4"
declare -rg DNBD3_SERVER="$SLX_DNBD3_SERVER"
declare -rg DNBD3_IMAGE="$SLX_STAGE4"
declare -rg DNBD3_RID="$SLX_STAGE4_RID"
declare -rg DNBD3_DEVICE="/dev/dnbd0"
declare -rg QCOW_CONTAINER="/opt/openslx/system/system.qcow2"
#
# END GLOBALS
###############################################################################

###############################################################################
# FUNCTION DEFINITIONS
#
# helper to do some sanity checks
check_dnbd3() {
	if [ ! command -v "dnbd3-client" >/dev/null ]; then
		warn "No 'dnbd3-client' found. Was the initramfs built correctly?"
		emergency_shell -n "Error in $0"
		return 1
	fi
	return 0
}

# helper to connect to the dnbd3-server
connect_dnbd3() {
	# check if it already connected
	local current_image_name="$(cat /sys/block/${DNBD3_DEVICE#/dev/}/net/image_name)"
	[ "x${current_image_name}" != "x(null)" ] && return 0

	# not connected yet, do it
	if ! dnbd3-client -h "${DNBD3_SERVER}" \
							-i "${DNBD3_IMAGE}" \
							-r "${DNBD3_RID}" \
							-d "${DNBD3_DEVICE}" ; then
		warn "Failed to mount $DNBD3_IMAGE from $DNBD3_SERVER to $DNBD3_DEVICE"
		emergency_shell -n "Error in $0"
		return 1
	fi
	return 0
}

# helper to create the qcow2 container file using
# DNBD3_DEVICE as the base of the filesystem
# QCOW_CONTAINER as the writable file
# (our future rootfs)
create_qcow() {
	# check if we already created the qcow2-container
	[ -e "$QCOW_CONTAINER" ] && return 0

	# check if we have our target directory, if not create it
	[ ! -d "$(busybox dirname $QCOW_CONTAINER)" ] && \
		mkdir -p "$(busybox dirname $QCOW_CONTAINER)"

	# we did not, let's create it
	if ! qemu-img create -f qcow2 -o \
		backing_file="$DNBD3_DEVICE",backing_fmt=qcow2 "$QCOW_CONTAINER"; then
		warn "Failed to create qcow2-Container from $DNBD3_DEVICE"
		emergency_shell -n "Error in $0"
		rm -f -- "$QCOW_CONTAINER"
		return 1
	fi
	return 0
}
# helper to start qemu-nbd on localhost:2000
# use our wrapper to set argv[0][0] to '@'
# this keeps qemu-nbd running after switching root
export_qcow() {
	# check if we already have a qemu-nbd
	if [ -e /tmp/qemu-nbd.pid ]; then
			kill -0 $(cat /tmp/qemu-nbd.pid) && return 0
	fi
	# since we use the wrapper, we need a little more logic to see if it runs
	/usr/bin/systemd-preserve-process-marker \
		/usr/bin/qemu-nbd -t -p 2000 "$QCOW_CONTAINER" &
	# the wrapper returns 255 if the qemu-nbd binary is missing
	local qemu_nbd_pid="$!"
	for i in 0.5 1 2; do
		sleep $i
		if ! kill -0 $qemu_nbd_pid; then
			# not running
			wait $qemu_nbd_pid
			local ret_wrapper="$?"
			if [ "${ret_wrapper}" -eq 127 ]; then
				# wrapper was not found by bash
				warn "No such file or directory: /usr/bin/systemd-preserve-process-marker"
			elif [ "${ret_wrapper}" -eq 255 ]; then
				# qemu-nbd was not found
				warn "No such file or directory: /usr/bin/qemu-nbd"
			fi
			emergency_shell -n "Error in $0"
			return 1
		else
			# all good, qemu-nbd is running, remember its pid
			echo $qemu_nbd_pid > /tmp/qemu-nbd.pid
			return 0
		fi
	done
	# fallback
	return 1
}
# helper to mount the qcow2-container per nbd
connect_qcow() {
	# try to mount the locally exported qcow2-container using nbd-client
	if /usr/bin/systemd-preserve-process-marker \
		nbd-client --persist 127.0.0.1 2000 /dev/nbd0; then
		# it worked, lets set the symlink to /dev/root as dracut needs it
		# later on to mount that device to the future root (/sysroot)
		ln -sf /dev/nbd0 /dev/root
		return 0
	else
		# this is pretty bad, dracut would spawn an emergency later on
		# since there is no /dev/root to mount.
		# For debugging purposes, we drop an emergency shell ourselves
		# if the mount fails.
		warn "Could not mount /dev/nbd0 from 127.0.0.1:2000."
		emergency_shell -n "Error in $0"
		return 1
	fi
}
#
# END FUNCTION DEFINITIONS
###############################################################################

# No main, use functions!