Netzwerkabhängigkeiten mit Nagios (Bash)

Das freie Monitoring Tool Nagios kann so konfiguriert werden, dass Hosts im Netzwerk Abhängigkeiten hat, über die sie angeschlossen sind. So kann man festlegen, dass der Server server01 z.B. am Switch switch02 angeschlossen ist, der wiederum am Router router03 hängt. Bei solchen Abhängigkeiten spricht man von Children (fälschlicherweise im deutschen auch Childs genannt) und Parents. Das genannte Beispiel hätte dann die folgenden Abhängigkeiten:

           -->                -->
   ...ist Child von... ..ist Child von..
   +------------------+----------------+
   |                  |                |
server01          switch02          router03

Beziehungsweise umgedreht:

           -->                -->
   ..ist Parent von..  ..ist Parent von..
   +------------------+----------------+
   |                  |                |
router03          switch02          server01

Diese Abhängigkeiten, sofern man sie brav pflegt, lassen sich sehr gut dazu verwenden, um Probleme im Netzwerk festzustellen. Fällt switch02 aus, und es ist keine Abhängigkeit zu server01 konfiguriert, muss man sich ggf. die Informationen erst zusammen suchen, dass diese beiden Systeme in direkter Verbindung zu einander stehen. Wertvolle Zeit geht verloren.

Nun bietet Nagios schon selbst die Möglichkeit, Systeme auf einer automatisch generierten Karte darzustellen. Diese, finde ich, ist aber sehr unübersichtlich und lässt sich nicht filtern, z.B. nur Systeme anzeigen, die ein Problem haben. Wer nicht nur eine Hand voll Systeme im Monitoring hat, weiss wovon ich spreche. Per default bietet Nagios auch keine Möglichkeit, die Ergbenisse des Monitoring anderen Prozessen sinnvoll verfügbar zu machen.

Außer man konfiguriert sich MK Livestatus als Broker Modul. Damit lassen sich so ziemlich alle Informationen aus Nagios herausholen. Auf die Installation und Konfiguration möchte ich nicht weiter eingehen. Vielmehr möchte ich aber zeigen, wie man sich mit diesem nützlichen Modul seine eigene Nettzwerkkkarte baut.

Dazu habe ich ein Bash-Script geschrieben, welches alle Hosts die ein Problem haben (egal ob Host oder Service Probleme) auf einer Karte mit Abhängigkeiten darstellt.

generiere_netzwerkkarte_mit_problemen.sh
#!/bin/bash
 
unixcat_bin='/pfad/zum/mk/livestatus/bin/unixcat'
unixcat_socket='/pfad/zum/mk/livestatus/var/rw/livestatus.sock'
 
dot_file='/pfad/fuer/ausgabe/der/network_problem_map.dot'
png_file='/pfad/fuer/ausgabe/der/network_problem_map.png'
host_state_file='/pfad/fuer/ausgabe/der/network_problem_map.states'
network_base="Internet"
 
> ${host_state_file}
 
function QueryOwnStateAndHostParent() {
  child=${1}
  state_parent=$(cat <<-EOF | ${unixcat_bin} ${unixcat_socket}
GET hosts
Columns: state parents
Filter: host_name = ${child}
EOF)
  host_state=$(echo ${state_parent} | awk -F";" '{print $1}')
  host_parent=$(echo ${state_parent} | awk -F";" '{print $2}')
 
  if ! ( echo ${child} | grep "," ) > /dev/null 2>&1 ; then
    if [ ${host_state} -eq 0 ] ; then
      host_state_color='limegreen'
    elif [  ${host_state} -eq 1 ] ; then
      host_state_color='firebrick'
    else
      host_state_color='goldenrod'
    fi
 
    echo '  "'${child}'" [shape = box, style = "rounded, filled", fillcolor = '${host_state_color}'];' >> ${host_state_file}
  fi
 
  if ( echo ${child} | grep "," ) > /dev/null 2>&1 ; then
    while read origin_child ; do
      child=${origin_child}
      while [ "${child}" != "${network_base}" ] ; do
        QueryOwnStateAndHostParent ${child}
      done
    done < <(echo ${child} | tr ',' '\n')
  else
    if ( echo ${host_parent} | grep "," ) > /dev/null 2>&1 ; then
      while read single_parent ; do
        echo '  "'${child}'" -> "'${single_parent}'";'
      done < <(echo ${host_parent}  | tr ',' '\n')
    else
      echo '  "'${child}'" -> "'${host_parent}'";'
    fi
    child=${host_parent}
  fi
}
 
children_list=$(cat <<-EOF | ${unixcat_bin} ${unixcat_socket}
GET hosts
Columns: host_name
Filter: state != 0
Filter: acknowledged = 0
EOF)
 
children_list=$(echo ${children_list} ; cat <<-EOF | ${unixcat_bin} ${unixcat_socket}
GET services
Columns: host_name
Filter: state != 0
Filter: acknowledged = 0
EOF)
 
children_list=$(echo ${children_list} | tr ' ' '\n' | sort -u)
 
for child in ${children_list} ; do
  while [ "${child}" != "${network_base}" ] ; do
    QueryOwnStateAndHostParent ${child}
  done
done > ${dot_file}
 
sort -u ${dot_file} > ${dot_file}.tmp
 
echo 'digraph map {' > ${dot_file}
echo '  node [ fontname=Arial, fontcolor=black, fontsize=35];' >> ${dot_file}
echo '  label = "Last generated at '$(date +%Y-%m-%d" "%H:%M:%S)'";' >> ${dot_file}
#echo '  rankdir = LR;' >> ${dot_file}
cat ${host_state_file} >> ${dot_file}
cat ${dot_file}.tmp >> ${dot_file}
echo '}' >> ${dot_file}
 
rm ${dot_file}.tmp
rm ${host_state_file}
 
dot -Tpng ${dot_file} -o ${png_file}

Im Endeffekt müssen nur die folgenden Variablen angepasst werden:

  • unixcat_bin - Pfad zum unixcat Binary, kommt bei MK Livestatus mit
  • unixcat_socket - Pfad zum MK Livestatus Socket, wird in der Nagios Config beim Broker Modul angegeben
  • dot_file - Pfad für Graphviz Config, wird während des Script-Laufs erzeugt
  • png_file - Pfad für Ausgabe der Map, wird während des Script-Laufs erzeugt
  • host_state_file - ein temporäres File für die Anzeige des Status in der Map
  • network_base - letzter Parent im Netzwerk (darf keine weiteren Parents haben)

Nach erfolgreicher Ausführung wird, für mein Beispiel, das folgende dot-File generiert:

network_map.dot
digraph map {
  node [ fontname=Arial, fontcolor=black, fontsize=35];
  label = "Last generated at 2012-01-09 19:14:04";
  "router03" [shape = box, style = "rounded, filled", fillcolor = limegreen];
  "server01" [shape = box, style = "rounded, filled", fillcolor = limegreen];
  "switch02" [shape = box, style = "rounded, filled", fillcolor = limegreen];
  "router03" -> "Internet";
  "server01" -> "switch02";
  "switch02" -> "router03";
}

Das damit generierte png-File sieht dann so aus:

scripts/netzwerkabhaengigkeiten.mit.nagios.bash.txt · Last modified: 2012/01/09 19:22 by daniel
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki