]> granicus.if.org Git - icinga2/blob - plugins/check_uptime.cpp
Merge pull request #6308 from akrus/master
[icinga2] / plugins / check_uptime.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/)  *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "plugins/thresholds.hpp"
21 #include <boost/program_options.hpp>
22 #include <boost/chrono.hpp>
23 #include <iostream>
24 #include <windows.h>
25 #include <shlwapi.h>
26
27 #define VERSION 1.0
28
29 namespace po = boost::program_options;
30
31 struct printInfoStruct
32 {
33         threshold warn;
34         threshold crit;
35         long long time;
36         long long timeInSeconds;
37         Tunit unit;
38 };
39
40 static bool l_Debug;
41
42 static int parseArguments(int ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo)
43 {
44         WCHAR namePath[MAX_PATH];
45         GetModuleFileName(NULL, namePath, MAX_PATH);
46         WCHAR *progName = PathFindFileName(namePath);
47
48         po::options_description desc;
49
50         desc.add_options()
51                 ("help,h", "Print help message and exit")
52                 ("version,V", "Print version and exit")
53                 ("debug,d", "Verbose/Debug output")
54                 ("warning,w", po::wvalue<std::wstring>(), "Warning threshold (Uses -unit)")
55                 ("critical,c", po::wvalue<std::wstring>(), "Critical threshold (Uses -unit)")
56                 ("unit,u", po::wvalue<std::wstring>(), "Unit to use:\nh\t- hours\nm\t- minutes\ns\t- seconds (default)\nms\t- milliseconds")
57                 ;
58
59         po::wcommand_line_parser parser(ac, av);
60
61         try {
62                 po::store(
63                         parser
64                         .options(desc)
65                         .style(
66                                 po::command_line_style::unix_style |
67                                 po::command_line_style::allow_long_disguise)
68                         .run(),
69                         vm);
70                 vm.notify();
71         } catch (const std::exception& e) {
72                 std::cout << e.what() << '\n' << desc << '\n';
73                 return 3;
74         }
75
76         if (vm.count("help")) {
77                 std::wcout << progName << " Help\n\tVersion: " << VERSION << '\n';
78                 wprintf(
79                         L"%s is a simple program to check a machines uptime.\n"
80                         L"You can use the following options to define its behaviour:\n\n", progName);
81                 std::cout << desc;
82                 wprintf(
83                         L"\nIt will then output a string looking something like this:\n\n"
84                         L"\tUPTIME WARNING 712h | uptime=712h;700;1800;0\n\n"
85                         L"\"UPTIME\" being the type of the check, \"WARNING\" the returned status\n"
86                         L"and \"712h\" is the returned value.\n"
87                         L"The performance data is found behind the \"|\", in order:\n"
88                         L"returned value, warning threshold, critical threshold, minimal value and,\n"
89                         L"if applicable, the maximal value. Performance data will only be displayed when\n"
90                         L"you set at least one threshold\n\n"
91                         L"Note that the returned time ins always rounded down,\n"
92                         L"4 hours and 44 minutes will show as 4h.\n\n"
93                         L"%s' exit codes denote the following:\n"
94                         L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
95                         L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
96                         L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
97                         L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
98                         L"Threshold syntax:\n\n"
99                         L"-w THRESHOLD\n"
100                         L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
101                         L"(unless stated differently)\n\n"
102                         L"-w !THRESHOLD\n"
103                         L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
104                         L"-w [THR1-THR2]\n"
105                         L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
106                         L"-w ![THR1-THR2]\n"
107                         L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
108                         L"-w THRESHOLD%%\n"
109                         L"if the plugin accepts percentage based thresholds those will be used.\n"
110                         L"Does nothing if the plugin does not accept percentages, or only uses\n"
111                         L"percentage thresholds. Ranges can be used with \"%%\", but both range values need\n"
112                         L"to end with a percentage sign.\n\n"
113                         L"All of these options work with the critical threshold \"-c\" too.\n"
114                         , progName);
115                 std::cout << '\n';
116                 return 0;
117         }
118
119         if (vm.count("version")) {
120                 std::cout << VERSION << '\n';
121                 return 0;
122         }
123
124         if (vm.count("warning")) {
125                 try {
126                         printInfo.warn = threshold(vm["warning"].as<std::wstring>());
127                 } catch (const std::invalid_argument& e) {
128                         std::cout << e.what() << '\n';
129                         return 3;
130                 }
131         }
132         if (vm.count("critical")) {
133                 try {
134                         printInfo.crit = threshold(vm["critical"].as<std::wstring>());
135                 } catch (const std::invalid_argument& e) {
136                         std::cout << e.what() << '\n';
137                         return 3;
138                 }
139         }
140
141         if (vm.count("unit")) {
142                 try {
143                         printInfo.unit = parseTUnit(vm["unit"].as<std::wstring>());
144                 } catch (const std::invalid_argument&) {
145                         std::wcout << L"Unknown unit type " << vm["unit"].as<std::wstring>() << '\n';
146                         return 3;
147                 }
148         } else
149                 printInfo.unit = TunitS;
150
151         l_Debug = vm.count("debug") > 0;
152
153         return -1;
154 }
155
156 static int printOutput(printInfoStruct& printInfo)
157 {
158         if (l_Debug)
159                 std::wcout << L"Constructing output string" << '\n';
160
161         state state = OK;
162
163         if (printInfo.warn.rend(printInfo.time))
164                 state = WARNING;
165         if (printInfo.crit.rend(printInfo.time))
166                 state = CRITICAL;
167
168         switch (state) {
169         case OK:
170                 std::wcout << L"UPTIME OK " << printInfo.time << TunitStr(printInfo.unit) << L" | 'uptime'=" << printInfo.timeInSeconds
171                         << "s" << L";" << printInfo.warn.toSeconds(printInfo.unit).pString() << L";"
172                         << printInfo.crit.toSeconds(printInfo.unit).pString() << L";0;" << '\n';
173                 break;
174         case WARNING:
175                 std::wcout << L"UPTIME WARNING " << printInfo.time << TunitStr(printInfo.unit) << L" | 'uptime'=" << printInfo.timeInSeconds
176                         << "s" << L";" << printInfo.warn.toSeconds(printInfo.unit).pString() << L";"
177                         << printInfo.crit.toSeconds(printInfo.unit).pString() << L";0;" << '\n';
178                 break;
179         case CRITICAL:
180                 std::wcout << L"UPTIME CRITICAL " << printInfo.time << TunitStr(printInfo.unit) << L" | 'uptime'=" << printInfo.timeInSeconds
181                         << "s" << L";" << printInfo.warn.toSeconds(printInfo.unit).pString() << L";"
182                         << printInfo.crit.toSeconds(printInfo.unit).pString() << L";0;" << '\n';
183                 break;
184         }
185
186         return state;
187 }
188
189 static void getUptime(printInfoStruct& printInfo)
190 {
191         if (l_Debug)
192                 std::wcout << L"Getting uptime in milliseconds" << '\n';
193
194         boost::chrono::milliseconds uptime = boost::chrono::milliseconds(GetTickCount64());
195
196         if (l_Debug)
197                 std::wcout << L"Converting requested unit (default: seconds)" << '\n';
198
199         switch (printInfo.unit) {
200         case TunitH:
201                 printInfo.time = boost::chrono::duration_cast<boost::chrono::hours>(uptime).count();
202                 break;
203         case TunitM:
204                 printInfo.time = boost::chrono::duration_cast<boost::chrono::minutes>(uptime).count();
205                 break;
206         case TunitS:
207                 printInfo.time = boost::chrono::duration_cast<boost::chrono::seconds>(uptime).count();
208                 break;
209         case TunitMS:
210                 printInfo.time = uptime.count();
211                 break;
212         }
213
214         // For the Performance Data we need the time in seconds
215         printInfo.timeInSeconds = boost::chrono::duration_cast<boost::chrono::seconds>(uptime).count();
216 }
217
218 int wmain(int argc, WCHAR **argv)
219 {
220         po::variables_map vm;
221         printInfoStruct printInfo;
222         int ret = parseArguments(argc, argv, vm, printInfo);
223
224         if (ret != -1)
225                 return ret;
226
227         getUptime(printInfo);
228
229         return printOutput(printInfo);
230 }