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