summaryrefslogtreecommitdiffstats
path: root/net/prplmesh/files/prplmesh.init
blob: f25a1f2dd0838ed057f4f9175b1df378148b8122 (plain)
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
#!/bin/sh /etc/rc.common
# shellcheck disable=SC2034
# shellcheck disable=SC3043 # ash supports local

START=99
STOP=10
USE_PROCD=1

PRPLMESH_DIR=/usr/libexec/prplmesh
LOG_ROLL_INTERVAL_SECONDS=86400

mesh_enabled() {
	[ "$(uci -q get prplmesh.config.enabled)" = "1" ]
}

register_process() {
	local name="$1"; shift
	procd_open_instance "$name"
	procd_set_param command "$@"
	procd_set_param env PRPLMESH_DIR="$PRPLMESH_DIR"
	procd_set_param respawn 3600 5 5
	procd_set_param stdout 1
	procd_set_param stderr 1
	procd_close_instance
}

register_log_roller() {
	local helper="$PRPLMESH_DIR/scripts/prplmesh_utils.sh"

	procd_open_instance log-roller
	# shellcheck disable=SC2016
	procd_set_param command /bin/sh -c '
		helper=$1
		interval=$2
		while sleep "$interval"; do
			"$helper" roll_logs || logger -t prplmesh "log roll failed"
		done' sh "$helper" "$LOG_ROLL_INTERVAL_SECONDS"
	procd_set_param respawn 3600 5 5
	procd_set_param stdout 1
	procd_set_param stderr 1
	procd_close_instance
}

start_service() {
	local mode need_agent=1 need_controller=1 log_roller=1

	mesh_enabled || return 0

	# A standalone controller runs without local radios, a plain agent
	# without the controller; everything else keeps both.
	mode="$(uci -q get prplmesh.config.management_mode)"
	case "$mode" in
	Multi-AP-Controller) need_agent=0 ;;
	Multi-AP-Agent) need_controller=0 ;;
	esac

	[ -x "$PRPLMESH_DIR/bin/ieee1905_transport" ] || {
		logger -t prplmesh "ieee1905_transport is missing or not executable"
		return 1
	}

	# Log rotation is not worth keeping the mesh down for: run without
	# it when the helper is stripped from the image.
	[ -x "$PRPLMESH_DIR/scripts/prplmesh_utils.sh" ] || {
		logger -t prplmesh "log-roll helper is missing or not executable; log rotation disabled"
		log_roller=0
	}

	if [ "$need_controller" = 1 ]; then
		[ -x "$PRPLMESH_DIR/bin/beerocks_controller" ] || {
			logger -t prplmesh "beerocks_controller is missing or not executable"
			return 1
		}
	fi

	if [ "$need_agent" = 1 ]; then
		[ -x "$PRPLMESH_DIR/bin/beerocks_agent" ] || {
			logger -t prplmesh "beerocks_agent is missing or not executable"
			return 1
		}
		[ -n "$(uci -q get prplmesh.config.mandatory_interfaces)" ] || {
			logger -t prplmesh "mandatory_interfaces not set; agent left stopped"
			return 1
		}
	fi

	if [ "$log_roller" = 1 ] && [ ! -e /var/run/prplmesh.boot_roll ]; then
		# Prune previous-boot logs before the daemons open new ones: the
		# helper only deletes old rotations and signals running daemons,
		# and none of ours are up yet, so nothing is rotated out early.
		# Reload triggers re-enter start_service with the daemons up
		# (procd reload falls through to start), so stamp the roll as
		# done for this boot; /var/run is tmpfs and clears the stamp.
		"$PRPLMESH_DIR/scripts/prplmesh_utils.sh" roll_logs >/dev/null 2>&1 \
			|| logger -t prplmesh "startup log roll failed"
		touch /var/run/prplmesh.boot_roll
	fi

	register_process transport "$PRPLMESH_DIR/bin/ieee1905_transport"

	if [ "$log_roller" = 1 ]; then
		register_log_roller
	fi

	if [ "$need_controller" = 1 ]; then
		register_process controller "$PRPLMESH_DIR/bin/beerocks_controller"
	fi

	if [ "$need_agent" = 1 ]; then
		# hostapd recreates its control sockets on boot and on wireless
		# reloads, so wait for them under procd supervision instead of
		# failing the whole start on a transient race.
		# shellcheck disable=SC2016
		register_process agent /bin/sh -c '
			while :; do
				ok=1
				IFS=","
				for interface in $(uci -q get prplmesh.config.mandatory_interfaces); do
					unset IFS
					[ -n "$interface" ] || continue
					[ -S "/var/run/hostapd/$interface" ] || { ok=0; break; }
				done
				unset IFS
				[ "$ok" = 1 ] && break
				sleep 5
			done
			exec "$PRPLMESH_DIR/bin/beerocks_agent"'
	fi
}

service_triggers() {
	procd_add_reload_trigger prplmesh wireless network
}