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