db_updater: Put parentheses back
[merlin.git] / install-merlin.sh
blob24352913f25f05916d2200c451ad2f570a08031e
1 #!/bin/bash
3 src_dir=$(dirname $0)
4 pushd "$src_dir" >/dev/null 2>&1
5 src_dir=$(pwd)
6 popd >/dev/null 2>&1
8 nagios_cfg=/usr/local/nagios/etc/nagios.cfg
9 dest_dir=/usr/local/nagios/addons/merlin
10 root_path=
11 bindir=/usr/bin
12 libexecdir=/usr/libexec/merlin
13 db_type=mysql
14 db_name=merlin
15 db_user=merlin
16 db_pass=merlin
17 db_root_user=root
18 db_root_pass=
19 batch=
20 install=db,files,config,init,apps
22 progname="$0"
23 raw_sed_version=$(sed --version | sed '1q')
24 sed_version=$(echo "$raw_sed_version" | sed -e 's/[^0-9]*//' -e 's/[.]//g')
25 if [ "$sed_version" -lt 409 ]; then
26 echo "You need GNU sed version 4.0.9 or above for this script to work"
27 echo "Your sed claims to be \"$raw_sed_version\" ($sed_version)"
28 exit 1
31 abort ()
33 echo "$@"
34 echo "Aborting."
35 exit 1
38 modify_nagios_cfg ()
40 if ! grep -q "merlin.so" "$nagios_cfg"; then
41 say "Adding merlin.so as eventbroker to nagios"
42 sed -i "s#^log_file.*#broker_module=$libexecdir/merlin.so $dest_dir/merlin.conf\\n\\n&#" \
43 "$nagios_cfg"
44 return 0
47 if grep -q "$libexecdir/merlin.so" "$nagios_cfg"; then
48 say "merlin.so is already a registered eventbroker in Nagios"
49 return 0
52 say "Updating path to merlin.so in $nagios_cfg"
53 sed -i "s#broker_module.*merlin.so.*#broker_module=$libexecdir/merlin.so $dest_dir/merlin.conf#" \
54 "$nagios_cfg"
55 return 0
58 get_arg ()
60 expr "z$1" : 'z[^=]*=\(.*\)'
63 db_setup ()
65 mysql="mysql"
66 if [ -n "$db_root_user" ]; then
67 mysql="$mysql -u$db_root_user"
68 test -n "$db_root_pass" && mysql="$mysql -p$db_root_pass"
71 case "$db_type" in
72 mysql)
73 # Try to connect to database
74 $(eval "$mysql -e ''")
75 if [ $? -ne 0 ]; then
76 echo "Couldn't connect to database, giving up."
77 exit 1
79 new_install=0
80 # Create database if it do not exist
81 db_count=$(eval "$mysql -N -s -e \"SHOW DATABASES LIKE '$db_name'\"" | wc -l)
82 if [ $db_count -eq 0 ]; then
83 echo "Creating database $db_name"
84 eval "$mysql -e \"CREATE DATABASE IF NOT EXISTS $db_name\""
85 new_install=1
87 # Always set privileges (to be on the extra safe side)
88 eval "$mysql -e \
89 \"GRANT ALL ON $db_name.* TO $db_user@localhost IDENTIFIED BY '$db_pass'\""
90 eval "$mysql -e 'FLUSH PRIVILEGES'"
92 eval "$mysql -f $db_name" < $src_dir/sql/mysql/merlin.sql > /tmp/merlin-sql-upgrade.log 2>&1
94 # Fetch db_version and do upgrade stuff if/when needed
95 query="SELECT version FROM db_version"
96 db_version=$(eval "$mysql $db_name -BNe \"$query\"" 2>/dev/null)
98 # Check for upgrade scripts
99 ver=$db_version
100 if test "$db_version"; then
101 while true; do
102 nextver=$((ver+1))
103 f="$src_dir/sql/update-db-${ver}to${nextver}.sql"
104 test -f "$f" || break
105 eval "$mysql $db_name" < $f 2>&1 >>/tmp/merlin-sql-upgrade.log || abort "Incremental database upgrade from version $ver to version $nextver failed!"
106 eval "$mysql $db_name -e \"UPDATE db_version SET version=$nextver\"" 2>&1 >> /tmp/merlin-sql-upgrade.log || abort "Failed to set new database version $nextver!"
107 ver=$nextver
108 done
110 if [ $new_install -eq 1 ]; then
111 for index in $src_dir/sql/mysql/*-indexes.sql; do
112 eval "$mysql -f $db_name" < $index 2>&1 >>/tmp/merlin-sql-upgrade.log
113 done
114 else
115 # only check for indexes in report_data. sloppy, yes, but should be sufficient
116 idx=$(eval "$mysql $db_name -N -s -e \"SHOW INDEX IN report_data\"" | wc -l);
117 if [ $idx -eq '1' ]; then
118 cat <<EOF
119 ***************
120 *** WARNING ***
121 ***************
123 Some of your tables lack indexes, which might cause bad performance.
124 Installing indexes might take quite some time (several hours for big installations), so I'm going
125 to let you install them when it's convenient for you.
127 To install them manually, run:
129 mon db fixindexes
136 echo "Unknown database type '$db_type'"
137 echo "I understand only lower-case database types."
138 return 0
140 esac
143 macro_subst ()
145 sed -e "s/@@DBNAME@@/$db_name/g" -e "s/@@DBTYPE@@/$db_type/g" \
146 -e "s/@@DBUSER@@/$db_user/g" -e "s/@@DBPASS@@/$db_pass/g" \
147 -e "s#@@NAGIOSCFG@@#$nagios_cfg#g" -e "s#@@DESTDIR@@#$dest_dir#g" \
148 -e "s#@@LIBEXECDIR@@#$libexecdir#g" \
149 -e "s#@@SRCDIR@@#$src_dir#g" -e "s#@@BINDIR@@#$bindir#g" \
150 "$@"
153 ask ()
155 local question options answer
156 question="$1" options="$2" default="$3"
157 test "$batch" && { echo "$default"; return 0; }
159 while true; do
160 echo -n "$question " >&2
161 read answer
162 case "$answer,$default" in
163 "",*)
164 answer="$default"
165 break
167 ",") ;;
169 echo "$options " | grep -q "$answer" && break
171 esac
172 echo "Please answer one of '$options'" >&2
173 done
174 echo "$answer" >&1
177 say ()
179 test "$batch" || echo "$@"
182 install_apps ()
184 mkdir -p $root_path/$bindir
185 mkdir -p $root_path/$libexecdir/mon
186 rm -f "$root_path/$bindir/mon"
187 rm -f "$root_path/$bindir/op5"
188 macro_subst "$src_dir/apps/mon.py" > "$root_path/$bindir/op5"
189 ln -s op5 "$root_path/$bindir/mon"
190 cp -a apps/libexec/* $root_path/$libexecdir/mon
191 rm -f $root_path/$libexecdir/mon/-oconf
192 cp oconf $root_path/$libexecdir/mon/-oconf
193 chmod 755 $root_path/$bindir/op5
194 chmod 755 $root_path/$libexecdir/mon/*
197 install_files ()
199 bins="merlind" # user-visible binaries
200 libexecs="import ocimp merlin.so showlog" # binaries that are outside of /opt/monitor lockdown
201 files="install-merlin.sh rename" # files going straight to /opt/monitor/op5/merlin/
202 subst="example.conf init.sh" # files needing substitution
203 execs="import ocimp showlog install-merlin.sh init.sh rename merlind" # everything that should +x
204 missing=
205 for i in $bins $libexecs $files $execs $subst; do
206 if ! test -f "$src_dir/$i"; then
207 echo "$src_dir/$i is missing"
208 missing="$missing $src_dir/$i"
210 done
211 test "$missing" && abort "Essential files are missing. Perhaps you need to run 'make'?"
213 test -d "$root_path/$dest_dir" || mkdir -p -m 755 "$root_path/$dest_dir"
214 test -d "$root_path/$dest_dir/logs" || mkdir -p -m 777 "$root_path/$dest_dir/logs"
215 test -d "$root_path/$dest_dir" || { echo "$root_path/$dest_dir is not a directory"; return 1; }
216 test -d "$root_path/$libexecdir" || mkdir -p -m 755 "$root_path/$libexecdir"
218 for f in $files; do
219 cp "$src_dir/$f" "$root_path/$dest_dir"
220 done
221 mkdir -p "$root_path/$dest_dir/sql/mysql/"
222 cp -r "$src_dir/sql" "$root_path/$dest_dir"
223 macro_subst "$src_dir/example.conf" > "$root_path/$dest_dir/sample.merlin.conf"
224 test -f "$root_path/$dest_dir/merlin.conf" || \
225 cp "$root_path/$dest_dir/sample.merlin.conf" \
226 "$root_path/$dest_dir/merlin.conf"
227 mkdir -p $root_path/$bindir
228 for f in $bins; do
229 cp "$src_dir/$f" "$root_path/$bindir"
230 done
231 for f in $libexecs; do
232 cp "$src_dir/$f" "$root_path/$libexecdir"
233 done
236 install_init ()
238 if [ $(id -u) -eq 0 -o "$root_path" ]; then
239 init_path="$root_path/etc/init.d"
240 test -d "$init_path" || mkdir -p "$init_path"
241 macro_subst "$src_dir/init.sh" > "$init_path/merlind"
242 chmod 755 "$init_path/merlind"
243 else
244 say "Lacking root permissions, so not installing init-script."
248 show_usage()
250 cat << END_OF_HELP
252 usage: $progname [options]
254 Where options can be any combination of:
255 --help|-h Print this cruft and exit
256 --nagios-cfg=</path/to/nagios.cfg> Path to nagios.cfg
257 --dest-dir=</install/directory> Where to install Merlin
258 --batch Assume 'yes' to all questions
259 --root=</path/to/fakeroot> Useful for package builders
260 --install=<db,config,files,init> Components to install. Any combo works
261 --db-name=<database name> Name of database to modify
262 --db-type=<mysql> Database type. Only mysql for now
263 --db-user=<username> User merlin should use with db
264 --db-pass=<password> Password for the db user
265 --db-root-user=<db admin> Database admin username
266 --db-root-pass=<pass> Database admin password
267 --bindir=/path/to/binaries Usually /usr/bin
268 --libexecdir=/path/to/libexecdir Usually /usr/libexec/merlin
270 END_OF_HELP
271 exit 1
274 while test "$1"; do
275 case "$1" in
276 --nagios-cfg=*)
277 nagios_cfg=$(get_arg "$1")
279 --nagios-cfg)
280 shift
281 nagios_cfg="$1"
283 --dest-dir=*)
284 dest_dir=$(get_arg "$1")
286 --dest-dir)
287 shift
288 dest_dir="$1"
290 --db-name=*)
291 db_name=$(get_arg "$1")
293 --db-name)
294 shift
295 db_name="$1"
297 --db-type=*)
298 db_type=$(get_arg "$1")
300 --db-type)
301 shift
302 db_type="$1"
304 --db-user=*)
305 db_user=$(get_arg "$1")
307 --db-user)
308 shift
309 db_user="$1"
311 --db-pass=*)
312 db_pass=$(get_arg "$1")
314 --db-pass)
315 shift
316 db_pass="$1"
318 --db-root-user=*)
319 db_root_user=$(get_arg "$1")
321 --db-root-user)
322 db_root_user="$1"
323 shift
325 --db-root-pass=*)
326 db_root_pass=$(get_arg "$1")
328 --db-root-pass)
329 shift
330 db_root_pass="$1"
332 --batch)
333 batch=y
335 --install=*)
336 install=$(get_arg "$1")
338 --install)
339 shift
340 install="$1"
342 --root=*)
343 root_path=$(get_arg "$1")
345 --root)
346 shift
347 root_path="$1"
349 --libexecdir=*)
350 libexecdir=$(get_arg "$1")
352 --libexecdir)
353 shift
354 libexecdir="$1"
356 --bindir=*)
357 bindir=$(get_arg "$1")
359 --bindir)
360 shift
361 bindir="$1"
363 --help|-h)
364 show_usage
367 echo "Illegal argument. I have no idea what to make of '$1'"
368 exit 1
370 esac
371 shift
372 done
374 if [ "$db_pass" = "generate" ]; then
375 db_pass=$(dd if=/dev/random bs=32 count=1 | sha1sum | sed -n '$s/\([0-9a-f]*\).*/\1/p')
378 for c in $(echo "$install" | sed 's/,/ /g'); do
379 case "$c" in
380 files|db|config|init|apps) ;;
382 echo "I don't know how to install component $c"
383 echo "You may only pass one or more of 'db,files,config' to --install"
384 echo "and you must pass one of them if you use --install"
385 exit 1
387 esac
388 done
390 cat << EOF
391 Database settings:
392 Type (--db-type): $db_type
393 Name (--db-name): $db_name
395 Path settings:
396 Nagios config file (--nagios-cfg): $nagios_cfg
397 Destination directory (--dest-dir): $dest_dir
398 libexecdir (--libexecdir): $libexecdir
399 bindir (--bindir): $bindir
400 Base root (--root): $root_path
402 Installing the following components: $install
405 case $(ask "Does this look ok? [Y/n]" "ynYN" y) in
406 n|N) echo "Aborting installation"; exit 1;;
407 esac
409 components=
410 for i in db config files apps; do
411 echo "$install" | grep -q $i && components="$i"
412 done
413 if ! test "$components"; then
414 echo "### No components selected to install."
415 echo "### You must pass one or more of 'db', 'config' and 'files'"
416 echo "### to the --install argument"
417 exit 1
421 say "Installing"
424 if echo "$install" | grep -q 'files'; then
425 install_files || abort "Failed to install files."
427 if echo "$install" | grep -q 'init'; then
428 install_init || abort "Failed to install merlind init script"
430 if echo "$install" | grep -q 'db'; then
431 db_setup || abort "Failed to setup database."
433 if echo "$install" | grep -q 'config'; then
434 modify_nagios_cfg || abort "Failed to modify Nagios config."
436 if echo "$install" | grep -q 'apps'; then
437 install_apps || abort "Failed to install apps"
440 say
441 say "Installation successfully completed"
443 say "You will need to restart Nagios and start Merlind for changes to take effect"