check_omada.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. #!/bin/bash
  2. #############################################################
  3. #
  4. # check_omada
  5. #
  6. # Version 1.0
  7. #
  8. # Ein Plugin fuer Icinga / Nagios
  9. # zur ueberwachung und Auswertung eines
  10. # Omada-Controllers ab Version 5
  11. #
  12. # Urheber: Daniel Wenzel
  13. # Kontakt: daniel@klenzel.de
  14. #
  15. #
  16. # Abhaengigkeiten:
  17. # - 'jq'
  18. # - 'curl'
  19. #
  20. # Beispiel fuer Debian: apt-get install jq curl
  21. #
  22. # ---------------------------------------------
  23. #
  24. # 1.0 - Changelog:
  25. #
  26. # 20230312
  27. # - Initiale Version
  28. #
  29. #
  30. #############################################################
  31. #Funktionen
  32. function showUsage {
  33. echo "
  34. Benutzung: $0 [Parameter]
  35. -H Hostname / IP-Adresse des Omada Controllers
  36. -P Port (Standard = 443) des Omada-Controllers
  37. -u Benutzername
  38. -p Passwort
  39. -s Angabe der Seiten-ID (nicht Name!)
  40. -m Modul
  41. 'Count-EAPUsers' => Zeigt auf dem Accesspoint angemeldete Nutzer an
  42. 'Get-DeviceLoad' => Gibt CPU-Auslastung aus
  43. 'Get-DeviceMem' => Gibt Arbeitsspeicher-Auslastung aus
  44. 'Get-PortStat' => Zeigt Traffic-Statistiken eines Ports
  45. 'Show-Updates' => Zeigt, ob fuer den Unifi-Controller Aktualisierungen verfuegbar sind
  46. 'Show-Connection' => Prueft, ob ein Geraet am Omada-Controller angemeldet ist
  47. 'Show-PoEStatus' => Zeigt die verbleibende PoE-Kapazitaet an
  48. -i (nur bei Get-PortStat notwendig) Angabe des abzufragenden Ports
  49. -d Angabe des abzufragenden Geraets
  50. -w Angabe, unter welchem Wert der Status 'Warning' ausgegeben werden soll
  51. 'Count-Users' => Warnung, wenn Anzahl Nutzer kleiner als der definierte Warning-Wert
  52. Eingabe im Format: 'n'
  53. 'Active-Alarms' => Ab dieser Anzahl von Alarmmeldungen wird der Status 'Warning' ausgeben
  54. Eingabe im Format: 'n'
  55. 'Offline-APs' => Ab dieser Anzahl nicht verfuegbarer APs wird der Status 'Warning' ausgeben
  56. Eingabe im Format: 'n'
  57. 'Has-Updates' => Ab dieser Anzahl von gefundenen Upgrades wird der Status 'Warning' ausgeben
  58. Eingabe im Format: 'n'
  59. 'Not-Adopted' => Ab dieser Anzahl nicht zugewiesener Accesspoints wird der Status 'Warning' ausgeben
  60. Eingabe im Format: 'n'
  61. 'Get-DeviceLoad' => Ist die Load der letzten Minute größer als der angegebene Wert, wird der Status 'Warning' ausgeben
  62. Eingabe im Format: 'n.nn'
  63. 'Get-DeviceMem' => Ist die Auslastung des Arbeitsspeichers höher als der angegebene Wert, wird der Status 'Warning' ausgeben
  64. Eingabe im Format: 'nn' (z.B. '80' fuer 80% Auslastung)
  65. 'Get-DeviceUsers' => Gibt die maximale Anzahl der mit einem AP verbundenen Nutzer an, ab der der Status 'Warning' ausgegeben wird
  66. Eingabe im Format: 'n'
  67. 'Get-DeviceGuests' => Gibt die maximale Anzahl der mit einem AP verbundenen Gaeste an, ab der der Status 'Warning' ausgegeben wird
  68. Eingabe im Format: 'n'
  69. 'Show-DevLastSeen' => Gibt die vergangenen Sekunden der letzten Sichtung an, ab die der Status 'Warning' ausgegeben wird
  70. -c Angabe, unter welchem Wert der Status 'Critical' ausgegeben werden soll
  71. Erlaeuterungen analog zu 'Warning'
  72. "
  73. }
  74. #Paramter verarbeiten
  75. while [ "$1" != "" ]; do
  76. case "$1" in
  77. -H) shift; strHost="$1";;
  78. -P) shift; intPort="$1";;
  79. -u) shift; strUsername="$1";;
  80. -p) shift; strPassword="$1";;
  81. -m) shift; strModus="$1";;
  82. -i) shift; strInterface="$1";;
  83. -d) shift; strDevice="$1";;
  84. -s) shift; strSeite="$1";;
  85. -w) shift; intWarning="$1";;
  86. -c) shift; intCritical="$1";;
  87. *) showUsage; exit 3;;
  88. esac
  89. shift
  90. done
  91. if [ -z $strHost ] || [ -z $strUsername ] || [ -z $strPassword ] || [ -z $strModus ] || [ -z $strDevice ] || [ -z $strSeite ]; then
  92. showUsage
  93. exit 1
  94. fi
  95. if ( [ "$strModus" == "Get-PortStat" ] ) && ( [ -z $strInterface ] ) ; then
  96. showUsage
  97. exit 1
  98. fi
  99. if ( [ "$strModus" == "Get-DeviceLoad" ] || [ "$strModus" == "Get-DeviceMem" ] || [ "$strModus" == "Count-EAPUsers" ] || [ "$strModus" == "Show-PoEStatus" ] ) && ( [ -z $intWarning ] || [ -z $intCritical ] ) ; then
  100. showUsage
  101. exit 1
  102. fi
  103. strDevice=$(echo ${strDevice^^})
  104. if [ -z $intPort ] ; then
  105. intPort=443
  106. fi
  107. #################
  108. strJQBinary=$(which jq)
  109. if [ $? -ne 0 ] ; then
  110. echo "Bitte den JSON-Prozessor ${strJQBinary} installieren"
  111. exit 3
  112. fi
  113. strCurlBinary=$(which curl)
  114. if [ $? -ne 0 ] ; then
  115. echo "Bitte das Paket curl installieren"
  116. exit 3
  117. fi
  118. #Meta
  119. intRandom=$(( $RANDOM % 100000 ))
  120. strBaseURL="https://${strHost}:${intPort}"
  121. strCookieFile="/tmp/omada_${intRandom}.cookie"
  122. strCurlCommand="${strCurlBinary} --silent --cookie ${strCookieFile} --cookie-jar ${strCookieFile} --insecure"
  123. #strLogOutAndCleanUp="${strCurlCommand} $strBaseURL/logout > /dev/null 2>&1 ; rm -f ${strCookieFile}"
  124. strLogOutAndCleanUp="rm -f ${strCookieFile}"
  125. #Anmelden am Controller
  126. intControllerID=$(${strCurlCommand} "${strBaseURL}/api/info" | jq -r .result.omadacId)
  127. intToken=$(${strCurlCommand} -X POST -H "Content-Type: application/json" "${strBaseURL}/${intControllerID}/api/v2/login" -d '{"username": "'"${strUsername}"'", "password": "'"${strPassword}"'"}' | ${strJQBinary} -r .result.token)
  128. strLoginStatus=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/loginStatus" | ${strJQBinary} -r .msg)
  129. if [ "$strLoginStatus" != "Success." ] ; then
  130. echo "Unknown: Anmeldung am Omada-Controller fehlgeschlagen"
  131. eval ${strLogOutAndCleanUp}
  132. exit 2
  133. fi
  134. ########## Modi Beginn ##########
  135. # [Count-EAPUsers] Zeigt auf dem Accesspoint angemeldete Nutzer an
  136. # -------------------------------------------
  137. if [ "$strModus" == "Count-EAPUsers" ] ; then
  138. intAngemeldeteNutzer=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/devices" | jq '.result | map(. | select(.name=="'${strDevice}'")) | . [] .clientNum')
  139. if [ $intAngemeldeteNutzer -lt $intCritical ] ; then
  140. echo "Critical: Angemeldete Nutzer (${intAngemeldeteNutzer}) kleiner als die minimale Menge (${intCritical}) | ActiveUsers=${intAngemeldeteNutzer}"
  141. eval ${strLogOutAndCleanUp}
  142. exit 2
  143. elif [ $intAngemeldeteNutzer -lt $intWarning ] ; then
  144. echo "Warning: Angemeldete Nutzer (${intAngemeldeteNutzer}) kleiner als die minimale Menge (${intWarning}) | ActiveUsers=${intAngemeldeteNutzer}"
  145. eval ${strLogOutAndCleanUp}
  146. exit 1
  147. else
  148. echo "OK: Es sind ${intAngemeldeteNutzer} Nutzer/Geraete am Accesspoint angemeldet | ActiveUsers=${intAngemeldeteNutzer}"
  149. eval ${strLogOutAndCleanUp}
  150. exit 0
  151. fi
  152. fi
  153. # [Show-PoEStatus] Zeigt die verbleibende PoE-Kapazitaet an
  154. # -------------------------------------------
  155. if [ "$strModus" == "Show-PoEStatus" ] ; then
  156. intPoERemaining=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/devices" | jq '.result | map(. | select(.name=="'${strDevice}'")) | . [] .poeRemain')
  157. intPoERemaining=$(echo $intPoERemaining | cut -d. -f1)
  158. if [ -z "$intPoERemaining" ] || [ "$intPoERemaining" == "null" ]; then
  159. echo "UNKNOWN: Entweder kein PoE-faehiges Geraet oder unbekannter Fehler"
  160. eval ${strLogOutAndCleanUp}
  161. exit 3
  162. fi
  163. if [ $intPoERemaining -lt $intCritical ] ; then
  164. echo "Critical: Es stehen nur noch ${intPoERemaining} Watt zur Verfuegung | PoERemaining=${intPoERemaining}"
  165. eval ${strLogOutAndCleanUp}
  166. exit 2
  167. elif [ $intPoERemaining -lt $intWarning ] ; then
  168. echo "Warning: Es stehen nur noch ${intPoERemaining} Watt zur Verfuegung | PoERemaining=${intPoERemaining}"
  169. eval ${strLogOutAndCleanUp}
  170. exit 1
  171. else
  172. echo "OK: Es stehen noch ${intPoERemaining} Watt zur Verfuegung | PoERemaining=${intPoERemaining}"
  173. eval ${strLogOutAndCleanUp}
  174. exit 0
  175. fi
  176. fi
  177. # [Show-Connection] Prueft, ob ein Geraet am Omada-Controller angemeldet ist
  178. # -------------------------------------------
  179. if [ "$strModus" == "Show-Connection" ] ; then
  180. intDeviceStatus=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/devices" | jq '.result | map(. | select(.name=="'${strDevice}'")) | . [] .status')
  181. if [ $intDeviceStatus -eq 14 ] ; then
  182. echo "OK: Geraet ist mit dem Omada-Controller verbunden"
  183. eval ${strLogOutAndCleanUp}
  184. exit 0
  185. elif [ $intDeviceStatus -eq 0 ] ; then
  186. echo "Critical: Keine Verbindung vom Omada-Controller zum Geraet"
  187. eval ${strLogOutAndCleanUp}
  188. exit 2
  189. else
  190. echo "Warning: Geraet verbunden, aber in einem anderen Status (Status ${intDeviceStatus})"
  191. eval ${strLogOutAndCleanUp}
  192. exit 1
  193. fi
  194. fi
  195. # [Show-Updates] Zeigt, ob fuer den das Geraet Aktualisierungen verfuegbar sind
  196. # -------------------------------------------
  197. if [ "$strModus" == "Show-Updates" ] ; then
  198. strDeviceMAC=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/devices?searchKey=${strDevice}" | ${strJQBinary} -r .result.devices[0].mac)
  199. strFirmwares=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/devices/${strDeviceMAC}/firmware" | jq '.result.curFwVer + ";" + .result.lastFwVer' | tr -d "\"")
  200. strFirmwareCur=$(echo $strFirmwares | cut -d ";" -f 1)
  201. strFirmwareAvail=$(echo $strFirmwares | cut -d ";" -f 2)
  202. if [ -z "$strFirmwareAvail" ] ; then
  203. echo "OK: Firmware ist auf dem neusten Stand."
  204. eval ${strLogOutAndCleanUp}
  205. exit 0
  206. fi
  207. if [[ "$strFirmwareCur" != "$strFirmwareAvail" ]] ; then
  208. echo "Warning: Geraeteaktualisierung vorhanden (Neue Firmware: ${strFirmwareAvail})"
  209. eval ${strLogOutAndCleanUp}
  210. exit 1
  211. else
  212. echo "OK: Firmware ist auf dem neusten Stand (Version ${strFirmwareCur})"
  213. eval ${strLogOutAndCleanUp}
  214. exit 0
  215. fi
  216. fi
  217. # [Get-DeviceLoad] Zeigt die CPU-Auslastung eines Geraets an
  218. # -------------------------------------------
  219. if [ "$strModus" == "Get-DeviceLoad" ] ; then
  220. intDeviceUtil=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/devices" | jq '.result | map(. | select(.name=="'${strDevice}'")) | . [] .cpuUtil')
  221. intDeviceUtil=$(echo $intDeviceUtil | cut -d. -f1)
  222. if [ $intDeviceUtil -gt $intCritical ] ; then
  223. echo "Critical: CPU-Auslastung des Geraets '${strDevice}' zu hoch (${intDeviceUtil}% > ${intCritical}%) | APLoad=${intDeviceUtil}%"
  224. eval ${strLogOutAndCleanUp}
  225. exit 2
  226. elif [ $intDeviceUtil -gt $intWarning ] ; then
  227. echo "Warning: CPU-Auslastung des Geraets '${strDevice}' zu hoch (${intDeviceUtil}% > ${intWarning}%) | APLoad=${intDeviceUtil}%"
  228. eval ${strLogOutAndCleanUp}
  229. exit 1
  230. else
  231. echo "OK: CPU-Auslastung des Geraets '${strDevice}' in Ordnung (${intDeviceUtil}%) | APLoad=${intDeviceUtil}%"
  232. eval ${strLogOutAndCleanUp}
  233. exit 0
  234. fi
  235. fi
  236. # [Get-DeviceMem] Zeigt die RAM-Belegung eines Geraets an
  237. # -------------------------------------------
  238. if [ "$strModus" == "Get-DeviceMem" ] ; then
  239. intDeviceMem=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/devices" | jq '.result | map(. | select(.name=="'${strDevice}'")) | . [] .memUtil')
  240. intDeviceMem=$(echo $intDeviceMem | cut -d. -f1)
  241. if [ $intDeviceMem -gt $intCritical ] ; then
  242. echo "Critical: Speicher-Auslastung des Geraets '${strDevice}' zu hoch (${intDeviceMem}% > ${intCritical}%) | APMem=${intDeviceMem}%"
  243. eval ${strLogOutAndCleanUp}
  244. exit 2
  245. elif [ $intDeviceMem -gt $intWarning ] ; then
  246. echo "Warning: Speicher-Auslastung des Geraets '${strDevice}' zu hoch (${intDeviceMem}% > ${intWarning}%) | APMem=${intDeviceMem}%"
  247. eval ${strLogOutAndCleanUp}
  248. exit 1
  249. else
  250. echo "OK: Speicher-Auslastung des Geraets '${strDevice}' in Ordnung (${intDeviceMem}%) | APMem=${intDeviceMem}%"
  251. eval ${strLogOutAndCleanUp}
  252. exit 0
  253. fi
  254. fi
  255. # [Get-PortStat] Zeigt Statistiken eines Switchports an
  256. # -------------------------------------------
  257. if [ "$strModus" == "Get-PortStat" ] ; then
  258. intTXRate=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/insight/switch/port/overview?currentPage=1&currentPageSize=100&searchKey=${strDevice}" | ${strJQBinary} '.result.data | map(. | select(.port=='${strInterface}')) | .[] .txRate')
  259. intRXRate=$(${strCurlCommand} -X GET -H "Content-Type: application/json" -H "Csrf-Token: ${intToken}" "${strBaseURL}/${intControllerID}/api/v2/sites/${strSeite}/insight/switch/port/overview?currentPage=1&currentPageSize=100&searchKey=${strDevice}" | ${strJQBinary} '.result.data | map(. | select(.port=='${strInterface}')) | .[] .rxRate')
  260. echo "OK: Switchport-Statistiken gefunden (RX: ${intRXRate} TX: ${intTXRate}) | SwitchPort${strInterface}TX=${intTXRate}b SwitchPort${strInterface}RX=${intRXRate}b"
  261. eval ${strLogOutAndCleanUp}
  262. exit 0
  263. fi
  264. #es wurde kein passender Modus gefunden
  265. echo "Unkown: Ungueltige Angabe des Moduls"
  266. eval ${strLogOutAndCleanUp}
  267. exit 3
  268. ########## Modi Ende ##########