Initial commit
[ta/infra-ansible.git] / roles / baremetal_provision / files / tmux_setup / tmux.inc
1 #!/bin/bash
2 # vim:noet:sw=4:ts=4:ft=sh
3
4 # Copyright 2019 Nokia
5
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #     http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17
18 [ -n "$__AUTOCOM_LIB_TMUX_INC__" ] && return || __AUTOCOM_LIB_TMUX_INC__=1
19
20 source "$(dirname "$BASH_SOURCE")/log.inc"
21
22 TMUX_SESSION_PREFIX="tmux-session-"
23 TMUX_TMPDIR="/tmp/tmp_console"
24 TMUX_SESSION="${TMUX_SESSION_PREFIX}deploy"
25 TMUX_LOGDIR="/var/log/ironic/console_logs/"
26 TMUX_RC_FILE="$(dirname "$BASH_SOURCE")/tmux.conf"
27
28 tmux_log_start()
29 {
30         local name="$1"
31
32         TMUX="" tmux -C -f "$TMUX_RC_FILE" \
33                         attach-session -t "$TMUX_SESSION" \; \
34                         select-window -t "$name" \; \
35                         pipe-pane -o "exec cat>>\"$TMUX_LOGDIR/$name.log\"" \; \
36                         detach &>/dev/null \
37                 || crit "Failed to start logging tmux window '%s'." "$name"
38 }
39
40 tmux_session_env_set()
41 {
42         local tmpdir="${1:-$TMUX_TMPDIR}"
43         local session="$2"
44         local name="$3"
45         local value="$4"
46
47         TMUX_TMPDIR="$tmpdir" tmux -f "$TMUX_RC_FILE" set-environment ${session:+-t "$session"} "$name" "$value" \
48                 || crit "Failed to set session '%s' environment variable '%s' to '%s'." "$session" "$name" "$value"
49 }
50
51 tmux_env_set()
52 {
53         tmux_session_env_set "" "$TMUX_SESSION" "$@"
54 }
55
56 tmux_session_env_get()
57 {
58         local tmpdir="${1:-$TMUX_TMPDIR}"
59         local session="$2"
60         local name="$3"
61         local output
62
63         output="$(TMUX_TMPDIR="$tmpdir" tmux 2>/dev/null -f "$TMUX_RC_FILE" show-environment ${session:+-t "$session"} "$name")" || :
64
65         echo "${output#$name=}"
66 }
67
68 tmux_env_get()
69 {
70         tmux_session_env_get "" "$TMUX_SESSION" "$@"
71 }
72
73 tmux_session_start()
74 {
75         local name="$1"
76         shift
77
78         debug "Starting new tmux session with window '%s'." "$name"
79
80         tmux -f "$TMUX_RC_FILE" new-session -s "$TMUX_SESSION" -d -n "$name" "$(printf "'%s' " "$@")" \
81                 || crit "Failed to start a new tmux session with '%s' running in it." "$name"
82
83         tmux_log_start "$name"
84 }
85
86 tmux_list_sessions()
87 {
88         local tmpdir="${1:-$TMUX_TMPDIR}"
89
90         debug "Listing tmux sessions found from the temporary directory '%s'." "$tmpdir"
91
92         TMUX_TMPDIR="$tmpdir" tmux ${TMUX_RC_FILE:+-f "$TMUX_RC_FILE"} list-sessions -F '#{session_name}' 2> /dev/null
93 }
94
95 tmux_session_is_running()
96 {
97         tmux -f "$TMUX_RC_FILE" has-session -t "$TMUX_SESSION" &>/dev/null
98 }
99
100 _tmux_cmd_title_is_new()
101 {
102         local name="$1"
103
104         debug "Checking that a tmux window with name '%s' is not already running." "$name"
105
106         ! tmux_cmd_is_running "$name"
107 }
108
109 tmux_cmd_exists()
110 {
111         local name="$1"
112
113         debug "Checking if a command with the name '%s' exists." "$name"
114
115         tmux_cmd_list | grep -q "^$name\$"
116 }
117
118 tmux_cmd_pid()
119 {
120         local name="$1"
121         local output pid
122
123         debug "Fetching pid of tmux command '%s'." "$name"
124
125         output="$(tmux -f "$TMUX_RC_FILE" list-windows -t "$TMUX_SESSION" -F '#{window_name}-pid=#{pane_pid}')" \
126                 || crit "Failed to list tmux session's windows."
127
128         pid="$(grep -m1 "^${name}-pid=" <<< "$output")"
129
130         [ -n "$pid" ] || return 1
131
132         echo "${pid##*=}"
133 }
134
135 tmux_cmd()
136 {
137         local name="$1"
138         shift
139
140         debug "Executing '%s' in a new tmux window." "$name"
141
142         ! tmux_cmd_exists "$name" \
143                 || crit "A command with the name '%s' already exists." "$name"
144
145         tmux -f "$TMUX_RC_FILE" new-window -n "$name" -d "/bin/bash -c \"sleep .2 ; $(printf "'%s' " "$@") ; echo \\\"@@@@@ autocom:tmux_cmd:exit_value: \\\$? @@@@@\\\" ; sleep 1\" " \
146                 || crit "Failed to execute command '%s' / '%s'." "$name" "$*"
147
148         tmux_log_start "$name"
149 }
150
151 tmux_cmd_list()
152 {
153         local name="$name"
154
155         debug "Listing tmux commands / windows in session '%s'." "$TMUX_SESSION"
156
157         tmux -f "$TMUX_RC_FILE" list-windows -F '#{window_name}' \
158                 || crit "Failed to list tmux session's windows."
159 }
160
161 tmux_attach()
162 {
163         local foreground name new_prefix
164
165         [ "$1" != "--foreground" ] \
166                 || { foreground="set-option exit-unattached on ;" ; shift ; }
167
168         name="$1"
169         new_prefix="$2"
170
171         debug "Attaching %sto window '%s' in session '%s' with prefix '%s'." \
172                 "${foreground:+"with foreground option "}" "$name" "$SESSION_ID" "$new_prefix"
173
174         tmux_cmd_exists "$name" \
175                 || name=""
176
177         tmux \
178                         new-session -t "$TMUX_SESSION" -s "${TMUX_SESSION/$TMUX_SESSION_PREFIX/$new_prefix}" \; \
179                         select-window ${name:+-t "$name"} \; \
180                         set status on \; \
181                         set destroy-unattached on \; \
182                         $foreground \
183                         set-window-option remain-on-exit off \
184                 || crit "Failed to attach to session %s's window '%s' with new prefix '%s'." "$SESSION_ID" "$name" "$new_prefix"
185 }
186
187 tmux_cmd_assert()
188 {
189         local delay="$1"
190         shift
191
192         tmux_cmd "$@"
193
194         sleep "$delay"
195
196         tmux_cmd_is_running "$1" \
197                 || crit "Executing '%s' in a tmux window seems to have failed soon after starting." "$1"
198 }
199
200 tmux_kill_try()
201 {
202         local name="$1"
203
204         debug "Killing '%s' from a tmux session." "$name"
205
206         tmux -f "$TMUX_RC_FILE" kill-window -t "$name"
207 }
208
209 tmux_kill()
210 {
211         local name="$1"
212
213         tmux_kill_try "$name" \
214                 || crit "Failed to kill '%s' from the tmux session." "$name"
215 }
216
217 tmux_get_window_count()
218 {
219         tmux_cmd_list | wc -l
220 }
221
222 tmux_cmd_is_running()
223 {
224         local name="$1"
225
226         debug "Checking whether '%s' is running in tmux." "$name"
227
228         tmux -f "$TMUX_RC_FILE" list-windows -F "#{window_name}-dead=#{pane_dead}" \
229                 | grep -q "^$name-dead=0\$"
230 }
231
232 tmux_count_zombies()
233 {
234         debug "Counting dead tmux windows."
235
236         tmux -f "$TMUX_RC_FILE" list-windows -F "window-is-dead=#{pane_dead}" \
237                 | grep -c "^window-is-dead=1\$"
238 }
239
240 tmux_cmd_exit_status()
241 {
242         local name="$1" e
243
244         debug "Checking whether '%s' has returned an error." "$name"
245
246         ! tmux_cmd_is_running "$name" \
247                 || crit "Cannot check if command returned an error; command is still running."
248
249         e="$(tmux -f "$TMUX_RC_FILE" capture-pane -t "$name" -p | grep -o '@@@@@ autocom:tmux_cmd:exit_value: [0-9]\+ @@@@@' | grep -o '[0-9]\+')"
250
251         [[ "$e" =~ ^[0-9]+$ ]] \
252                 || crit "Command %s's exit status '%s' doesn't look like a number." "$name" "$e"
253
254         return $e
255 }
256
257 tmux_session_init()
258 {
259         export TMUX_TMPDIR="$1"
260         export TMUX_SESSION="${TMUX_SESSION_PREFIX}$2"
261         export TMUX_LOGDIR="$3"
262         export TMUX_RC_FILE="$4"
263
264         debug "Initializing tmux session '%s': tmpdir='%s', logdir='%s'" \
265                 "$TMUX_SESSION" "$TMUX_TMPDIR" "$TMUX_LOGDIR"
266
267         mkdir -p "$TMUX_TMPDIR" \
268                 || crit "Failed to create tmux's temporary directory '%s'." "$TMUX_TMPDIR"
269
270         mkdir -p "$TMUX_LOGDIR" \
271                 || crit "Failed to create tmux's log file directory."
272 }
273
274 tmux_kill_other_sessions()
275 {
276         local session sessions
277
278         debug "Killing other tmux sessions than '%s' (that are still related to the same autocom session)." \
279                 "$TMUX_SESSION"
280
281         sessions="$(tmux_list_sessions)" \
282                 || crit "Failed to get a list of sessions to kill."
283
284         sessions="$(echo "$sessions" | grep "${TMUX_SESSION/$TMUX_SESSION_PREFIX/}")" \
285                 || crit "No tmux sessions found for the running autocom session."
286
287         sessions="$(echo "$sessions" | grep -v "$TMUX_SESSION")" \
288                 || debug "No other tmux sessions in this autocom session."
289
290         for session in $sessions
291         do
292                 tmux -f "$TMUX_RC_FILE" kill-session -t "$session" \
293                         || crit "Failed to kill tmux session '%s'." "$session"
294         done
295 }
296
297 tmux_kill_other_windows()
298 {
299         local name="$1"
300
301         [ -n "$name" ] \
302                 && debug "Killing all other tmux windows than '%s'." "$name" \
303                 || debug "Killing all other tmux windows."
304
305         tmux -f "$TMUX_RC_FILE" kill-window -a ${name:+-t "$name"}
306 }
307
308 tmux_session_uninit()
309 {
310         local name="$1"
311
312         debug "Uninitializing tmux session (name='%s')." "$name"
313
314         tmux_kill_other_sessions
315         tmux_kill_other_windows "$name"
316 }
317
318 tmux_set_alternate_prefix()
319 {
320         local prefix="$1"
321
322         TMUX_SESSION_PREFIX="${prefix}-"
323 }
324
325 # Local Variables:
326 # mode: sh
327 # tab-width: 4
328 # End: