aboutsummaryrefslogtreecommitdiff
path: root/nagios-downtime
blob: 46de12e468040943ccc702368650c1c48ad8ec93 (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
138
139
140
#!/usr/bin/env bash

#
# nagios-downtime(1) -- Shortcut to scheduling fixed downtime in Nagios,
# because it's annoying to do with the web interface for large sets of hosts
# or services.
#
#     $ ndt (<host[/service][,host[/service],...>|-) <start> <end> [comment]\n' "$self"
#
# You can specify multiple objects by separating them with commas:
#
#     $ ndt abc-example-ap-1,abc-example-ap-2/VOLTAGE 9am 10am 'Power problems at abc-example'
#
# Even easier is to pipe them into stdin by specifying - as the object:
#
#     $ nds abc-example | ndt - 9am 10am 'Power problems at abc-example'
#
# Assumes date(1) with +%s format and --date option (probably only GNU date).
#
# Author: Tom Ryder <tom@sanctum.geek.nz>
# Copyright: 2016
#

# Name self
self=nagios-downtime

# Usage printing function
usage() {
    printf 'USAGE: %s [<host[/service][,host[/service],...>|-] <start> <end> [comment]\n' "$self"
}

# Process options (just help at the moment)
OPTIND=1
while getopts 'h' opt ; do
    case "$opt" in
        h)
            usage
            exit 0
            ;;
        '?')
            usage >&2
            exit 1
            ;;
    esac
done
shift "$((OPTIND-1))"

# Bail if too few arguments left; we need at least the hostname, the start date, and the end date
if (($# < 3)) ; then
    usage >&2
    exit 1
fi

# Define relatively fixed/guaranteed fields for Nagios command; note that the
# comment has a default of 'no comment given'
now=$(date +%s)
spec=$1
fixed=1
trigger=0
duration=0
author=${SUDO_USER:-$USER}
comment=${4:-'no comment given'}
cmdfile=${NAGCMD_FILE:-/usr/local/nagios/var/rw/nagios.cmd}

# How to get the objects depends on the spec (the first argument)
declare -a objects
case $spec in

    # If the spec is just "-", we just read unique objects from stdin
    -)
        while read -r object ; do
            [[ $object ]] || continue
            objects[${#objects[@]}]=$object
        done < <(sort -u)
        ;;

    # If the spec is anything else, we break it up with commas and read the
    # objects that way
    *)
        IFS=, read -a objects -r < <(printf '%s\n' "$spec")
        ;;
esac

# There must be at least one object
if ! ((${#objects[@]})) ; then
    printf '%s: At least one host/service must be given\n' \
        "$self" >&2
    exit 1
fi

# All the hosts or services must exist, just to be strict
for object in "${objects[@]}" ; do
    nagios-exists "$object" && continue
    printf '%s: Host/service %s does not seem to exist\n' \
        "$self" "$object" >&2
    exit 1
done

# Attempt to parse start and end dates; fail if the call doesn't work
dta=$(date +%s --date "$2") || exit
dtb=$(date +%s --date "$3") || exit

# If the end time is less than right now, this is probably a mistake
dtn=$(date +%s)
if ((dtn > dtb)) ; then
    printf '%s: Refusing to schedule downtime ending in the past (%s)\n' \
        "$self" "$(date -d @"$dtb" +%c)"
    exit 1
fi

# If the end time is less than the start time, this is definitely a mistake
if ((dta > dtb)) ; then
    printf '%s: Refusing to schedule downtime that ends (%s) before it starts (%s)\n' \
        "$self" "$(date -d @"$dtb" +%c)" "$(date -d @"$dta" +%c)"
    exit 1
fi

# Quietly replace semicolons in comment with commas
comment=${comment//;/,}

# Write commands to schedule downtime for each of the objects, bail if a single
# one of them fails
for object in "${objects[@]}" ; do
    case $object in
        */*)
            host=${object%/*}
            service=${object##*/}
            cmd=$(printf '[%lu] SCHEDULE_SVC_DOWNTIME;%s;%s;%s;%s;%u;%u;%u;%s;%s' \
                "$now" "$host" "$service" "$dta" "$dtb" \
                "$fixed" "$trigger" "$duration" "$author" "$comment")
            ;;
        *)
            host=$object
            cmd=$(printf '[%lu] SCHEDULE_HOST_DOWNTIME;%s;%s;%s;%u;%u;%u;%s;%s' \
                "$now" "$host" "$dta" "$dtb" \
                "$fixed" "$trigger" "$duration" "$author" "$comment")
            ;;
    esac
    printf '%s\n' "$cmd" > "$cmdfile" || exit
done