aboutsummaryrefslogtreecommitdiff
path: root/buildos
blob: 9a0224ad4cb5882dcf58bb4e0d2b6a3ef0fb62db (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
#!/bin/bash

# Build OS monitor. It starts as a systemd service and performs the following
# steps:
#
# 1. Bootstrap the build2 toolchain.
# 2. Build and start bbot.
# 3. Build and start bslave.
# 4. Monitor for OS and toolchain changes and reboot if detected.
#

# @@ What do we do in case or error, trap? Send email? Reboot? Probably
#    reboot bad idea since someone may need to login to examine what's
#    going on.
#
# @@ What will systemd do if we fail? Perhaps configure it to restart
#    us? Or not since we may hose the logs.
#
trap "exit 1" ERR
set -o errtrace # Trap in functions.

# Note: diagnostics goes to stdout.
#
function info () { echo "$*" 1>&2; }
function error ()
{
  if [ "$#" -gt 0 ]; then
    info "$*";
  fi

  exit 1
}

info "starting buildos monitor..."

# Parse the kernel command line. This is complicated by the fact that the
# values can be quoted, for example:
#
# foo='foo fox'
# bar="bar 'box'"
#
# First we separete quoted variables and arguments with newlines (giving
# priority to assignments). Then we replace whitespaces with newline on
# lines that don't contain quites. Finally, clean up by removing blank
# lines.
#
# Note: the same code as in init.
#
readarray -t cmdline < <(cat /proc/cmdline | \
  sed -r -e "s/([^ ]+=)?('[^']*'|\"[^\"]*\")/\n\1\2\n/g" | \
  sed -r -e "/['\"]/!s/ /\n/g" |
  sed -r -e '/^\s*$/d')

# Enter all buildos variables as bash variables.
#
for v in "${cmdline[@]}"; do
  var="$(sed -r -n -e 's/^buildos\.([^=]+)=.*$/\1/p' <<<"$v")" # Extract name.

  if [ -n "$var" ]; then
    val="$(sed -r -e 's/^[^=]+=(.*)$/\1/' <<<"$v")"            # Extract value.
    val="$(sed -r -e "s/^('(.*)'|\"(.*)\")$/\2\3/" <<<"$val")" # Strip quoted.
    declare "$var=$val"
  fi
done

hname="$(hostname)"

# Get the build id.
#
buildid="$(sed -n -re 's/^BUILD_ID="(.+)"$/\1/p' /etc/os-release)"

function email () # <subject> < <body>
{
  (echo -e "Subject: [$hname] $1\n"; cat -) | sendmail -i "$admin_email"
}

function restart ()
{
  sendmail -q # Flush mail queue.
  sleep 10    # Give any remaining mail chance to go through.
  sudo systemctl reboot
}

if [ -z "$buildid_url" ]; then
  info "no buildos.buildid_url specified, not monitoring for new os builds"
fi

email "starting buildos monitor" <<EOF
buildid:     $buildid
buildid_url: $buildid_url
EOF

while true; do
  info "monitoring..."

  sleep 5

  if [ -n "$buildid_url" ]; then
    # Fetch the current id. While normally it will be a TFTP URL, it could also
    # be HTTP(S) so we configure sensible behavior for that.
    #
    if id="$(curl -f -L -s -S "$buildid_url")"; then
      if [ "$id" != "$buildid" ]; then
	email "rebooting because of new os build" <<EOF
old_buildid: $buildid
new_buildid: $id
EOF
	info "new os build ($id), rebooting..."
	restart
      fi
    else
      info "unable to fetch $buildid_url, will try again"
    fi
  fi
done