source: nscp/trunk/modules/CheckSystem/CheckSystem.cpp @ 2180143

Last change on this file since 2180143 was 2180143, checked in by Michael Medin <michael@…>, 6 years ago
  • Fixed the "check memory" issues for real this time.
    • Fixed problem with : in counter names #50 (anything starts with \ is considerd a counter so if you use aliases with \ this will break things for you.
  • Property mode set to 100644
File size: 33.7 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21
22#include "stdafx.h"
23#include "CheckSystem.h"
24#include <utils.h>
25#include <tlhelp32.h>
26#include <EnumNtSrv.h>
27#include <EnumProcess.h>
28#include <checkHelpers.hpp>
29#include <map>
30#include <set>
31#include <sysinfo.h>
32
33CheckSystem gCheckSystem;
34
35/**
36 * DLL Entry point
37 * @param hModule
38 * @param ul_reason_for_call
39 * @param lpReserved
40 * @return
41 */
42BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
43{
44        NSCModuleWrapper::wrapDllMain(hModule, ul_reason_for_call);
45        return TRUE;
46}
47
48/**
49 * Default c-tor
50 * @return
51 */
52CheckSystem::CheckSystem() : processMethod_(0), pdhThread("pdhThread") {}
53/**
54 * Default d-tor
55 * @return
56 */
57CheckSystem::~CheckSystem() {}
58/**
59 * Load (initiate) module.
60 * Start the background collector thread and let it run until unloadModule() is called.
61 * @return true
62 */
63bool CheckSystem::loadModule() {
64        pdhThread.createThread();
65        std::string wantedMethod = NSCModuleHelper::getSettingsString(C_SYSTEM_SECTION_TITLE, C_SYSTEM_ENUMPROC_METHOD, C_SYSTEM_ENUMPROC_METHOD_DEFAULT);
66        CEnumProcess tmp;
67        int method = tmp.GetAvailableMethods();
68        if (wantedMethod == C_SYSTEM_ENUMPROC_METHOD_AUTO) {
69                OSVERSIONINFO osVer = systemInfo::getOSVersion();
70                if (systemInfo::isBelowNT4(osVer)) {
71                        NSC_DEBUG_MSG_STD("Autodetected NT4<, using PSAPI process enumeration.");
72                        processMethod_ = ENUM_METHOD::PSAPI;
73                } else if (systemInfo::isAboveW2K(osVer)) {
74                        NSC_DEBUG_MSG_STD("Autodetected W2K>, using TOOLHELP process enumeration.");
75                        processMethod_ = ENUM_METHOD::TOOLHELP;
76                } else {
77                        NSC_DEBUG_MSG_STD("Autodetected failed, using PSAPI process enumeration.");
78                        processMethod_ = ENUM_METHOD::PSAPI;
79                }
80        } else if (wantedMethod == C_SYSTEM_ENUMPROC_METHOD_PSAPI) {
81                NSC_DEBUG_MSG_STD("Using PSAPI method.");
82                if (method == (method|ENUM_METHOD::PSAPI)) {
83                        processMethod_ = ENUM_METHOD::PSAPI;
84                } else {
85                        NSC_LOG_ERROR_STD("PSAPI method not available, check " C_SYSTEM_ENUMPROC_METHOD " option.");
86                }
87        } else {
88                NSC_DEBUG_MSG_STD("Using TOOLHELP method.");
89                if (method == (method|ENUM_METHOD::TOOLHELP)) {
90                        processMethod_ = ENUM_METHOD::TOOLHELP;
91                } else {
92                        NSC_LOG_ERROR_STD("TOOLHELP method not avalible, check " C_SYSTEM_ENUMPROC_METHOD " option.");
93                }
94        }
95       
96        return true;
97}
98/**
99 * Unload (terminate) module.
100 * Attempt to stop the background processing thread.
101 * @return true if successfully, false if not (if not things might be bad)
102 */
103bool CheckSystem::unloadModule() {
104        if (!pdhThread.exitThread(20000)) {
105                std::cout << "MAJOR ERROR: Could not unload thread..." << std::endl;
106                NSC_LOG_ERROR("Could not exit the thread, memory leak and potential corruption may be the result...");
107        }
108        return true;
109}
110/**
111 * Check if we have a command handler.
112 * @return true (as we have a command handler)
113 */
114bool CheckSystem::hasCommandHandler() {
115        return true;
116}
117/**
118 * Check if we have a message handler.
119 * @return false as we have no message handler
120 */
121bool CheckSystem::hasMessageHandler() {
122        return false;
123}
124
125int CheckSystem::commandLineExec(const char* command,const unsigned int argLen,char** args) {
126        if (_stricmp(command, "debugpdh") == 0) {
127                PDH::Enumerations::Objects lst;
128                try {
129                        lst = PDH::Enumerations::EnumObjects();
130                } catch (const PDH::PDHException e) {
131                        std::cout << "Service enumeration failed: " << e.getError();
132                        return 0;
133                }
134                for (PDH::Enumerations::Objects::iterator it = lst.begin();it!=lst.end();++it) {
135                        if ((*it).instances.size() > 0) {
136                                for (PDH::Enumerations::Instances::const_iterator it2 = (*it).instances.begin();it2!=(*it).instances.end();++it2) {
137                                        for (PDH::Enumerations::Counters::const_iterator it3 = (*it).counters.begin();it3!=(*it).counters.end();++it3) {
138                                                std::string counter = "\\" + (*it).name + "(" + (*it2).name + ")\\" + (*it3).name;
139                                                std::cout << "testing: " << counter << ": ";
140                                                std::list<std::string> errors;
141                                                std::list<std::string> status;
142                                                std::string error;
143                                                bool bStatus = true;
144                                                if (PDH::Enumerations::validate(counter, error)) {
145                                                        status.push_back("open");
146                                                } else {
147                                                        errors.push_back("NOT found: " + error);
148                                                        bStatus = false;
149                                                }
150                                                if (bStatus) {
151                                                        PDH::PDHCounter *pCounter = NULL;
152                                                        PDH::PDHQuery pdh;
153                                                        try {
154                                                                PDHCollectors::StaticPDHCounterListener<double, PDH_FMT_DOUBLE> cDouble;
155                                                                pCounter = pdh.addCounter(counter, &cDouble);
156                                                                pdh.open();
157
158                                                                if (pCounter != NULL) {
159                                                                        try {
160                                                                                PDH::PDHCounterInfo info = pCounter->getCounterInfo();
161                                                                                errors.push_back("CounterName: " + info.szCounterName);
162                                                                                errors.push_back("ExplainText: " + info.szExplainText);
163                                                                                errors.push_back("FullPath: " + info.szFullPath);
164                                                                                errors.push_back("InstanceName: " + info.szInstanceName);
165                                                                                errors.push_back("MachineName: " + info.szMachineName);
166                                                                                errors.push_back("ObjectName: " + info.szObjectName);
167                                                                                errors.push_back("ParentInstance: " + info.szParentInstance);
168                                                                                errors.push_back("Type: " + strEx::itos(info.dwType));
169                                                                                errors.push_back("Scale: " + strEx::itos(info.lScale));
170                                                                                errors.push_back("Default Scale: " + strEx::itos(info.lDefaultScale));
171                                                                                errors.push_back("Status: " + strEx::itos(info.CStatus));
172                                                                                status.push_back("described");
173                                                                        } catch (const PDH::PDHException e) {
174                                                                                errors.push_back("Describe failed: " + e.getError());
175                                                                                bStatus = false;
176                                                                        }
177                                                                }
178
179                                                                pdh.gatherData();
180                                                                pdh.close();
181                                                                status.push_back("queried");
182                                                        } catch (const PDH::PDHException e) {
183                                                                errors.push_back("Query failed: " + e.getError());
184                                                                bStatus = false;
185                                                                try {
186                                                                        pdh.gatherData();
187                                                                        pdh.close();
188                                                                        bStatus = true;
189                                                                } catch (const PDH::PDHException e) {
190                                                                        errors.push_back("Query failed (again!): " + e.getError());
191                                                                }
192                                                        }
193
194                                                }
195                                                if (!bStatus) {
196                                                        std::list<std::string>::const_iterator cit = status.begin();
197                                                        for (;cit != status.end(); ++cit) {
198                                                                std::cout << *cit << ", ";
199                                                        }
200                                                        std::cout << std::endl;
201                                                        std::cout << "  | Log" << std::endl;
202                                                        std::cout << "--+------  --    -" << std::endl;
203                                                        cit = errors.begin();
204                                                        for (;cit != errors.end(); ++cit) {
205                                                                std::cout << "  | " << *cit << std::endl;
206                                                        }
207                                                } else {
208                                                        std::list<std::string>::const_iterator cit = status.begin();
209                                                        for (;cit != status.end(); ++cit) {
210                                                                std::cout << *cit << ", ";;
211                                                        }
212                                                        std::cout << std::endl;
213                                                }
214                                        }
215                                }
216                        } else {
217                                for (PDH::Enumerations::Counters::const_iterator it2 = (*it).counters.begin();it2!=(*it).counters.end();++it2) {
218                                        std::string counter = "\\" + (*it).name + "\\" + (*it2).name;
219                                        std::cout << "testing: " << counter << ": ";
220                                        std::string error;
221                                        if (PDH::Enumerations::validate(counter, error)) {
222                                                std::cout << " found ";
223                                        } else {
224                                                std::cout << " *NOT* found (" << error << ") " << std::endl;
225                                                break;
226                                        }
227                                        bool bOpend = false;
228                                        try {
229                                                PDH::PDHQuery pdh;
230                                                PDHCollectors::StaticPDHCounterListener<double, PDH_FMT_DOUBLE> cDouble;
231                                                pdh.addCounter(counter, &cDouble);
232                                                pdh.open();
233                                                pdh.gatherData();
234                                                pdh.close();
235                                                bOpend = true;
236                                        } catch (const PDH::PDHException e) {
237                                                std::cout << " could *not* be open (" << e.getError() << ") " << std::endl;
238                                                break;
239                                        }
240                                        std::cout << " open ";
241                                        std::cout << std::endl;;
242                                }
243                        }
244                }
245        } else if (_stricmp(command, "listpdh") == 0) {
246                PDH::Enumerations::Objects lst;
247                try {
248                        lst = PDH::Enumerations::EnumObjects();
249                } catch (const PDH::PDHException e) {
250                        std::cout << "Service enumeration failed: " << e.getError();
251                        return 0;
252                }
253                for (PDH::Enumerations::Objects::iterator it = lst.begin();it!=lst.end();++it) {
254                        if ((*it).instances.size() > 0) {
255                                for (PDH::Enumerations::Instances::const_iterator it2 = (*it).instances.begin();it2!=(*it).instances.end();++it2) {
256                                        for (PDH::Enumerations::Counters::const_iterator it3 = (*it).counters.begin();it3!=(*it).counters.end();++it3) {
257                                                std::cout << "\\" << (*it).name << "(" << (*it2).name << ")\\" << (*it3).name << std::endl;;
258                                        }
259                                }
260                        } else {
261                                for (PDH::Enumerations::Counters::const_iterator it2 = (*it).counters.begin();it2!=(*it).counters.end();++it2) {
262                                        std::cout << "\\" << (*it).name << "\\" << (*it2).name << std::endl;;
263                                }
264                        }
265                }
266        }
267        return 0;
268}
269
270
271/**
272 * Main command parser and delegator.
273 * This also handles a lot of the simpler responses (though some are deferred to other helper functions)
274 *
275 *
276 * @param command
277 * @param argLen
278 * @param **args
279 * @return
280 */
281NSCAPI::nagiosReturn CheckSystem::handleCommand(const strEx::blindstr command, const unsigned int argLen, char **char_args, std::string &msg, std::string &perf) {
282        std::list<std::string> stl_args;
283        CheckSystem::returnBundle rb;
284        if (command == "checkCPU") {
285                return checkCPU(argLen, char_args, msg, perf);
286        } else if (command == "checkUpTime") {
287                return checkUpTime(argLen, char_args, msg, perf);
288        } else if (command == "checkServiceState") {
289                return checkServiceState(argLen, char_args, msg, perf);
290        } else if (command == "checkProcState") {
291                return checkProcState(argLen, char_args, msg, perf);
292        } else if (command == "checkMem") {
293                return checkMem(argLen, char_args, msg, perf);
294        } else if (command == "checkCounter") {
295                return checkCounter(argLen, char_args, msg, perf);
296        }
297        return NSCAPI::returnIgnored;
298}
299
300
301class cpuload_handler {
302public:
303        static int parse(std::string s) {
304                return strEx::stoi(s);
305        }
306        static int parse_percent(std::string s) {
307                return strEx::stoi(s);
308        }
309        static std::string print(int value) {
310                return strEx::itos(value) + "%";
311        }
312        static std::string print_unformated(int value) {
313                return strEx::itos(value);
314        }
315        static std::string print_percent(int value) {
316                return strEx::itos(value) + "%";
317        }
318        static std::string key_prefix() {
319                return "average load ";
320        }
321        static std::string key_postfix() {
322                return "";
323        }
324};
325NSCAPI::nagiosReturn CheckSystem::checkCPU(const unsigned int argLen, char **char_args, std::string &msg, std::string &perf)
326{
327        typedef checkHolders::CheckConatiner<checkHolders::MaxMinBounds<checkHolders::NumericBounds<int, cpuload_handler> > > CPULoadConatiner;
328
329        std::list<std::string> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args);
330        if (stl_args.empty()) {
331                msg = "ERROR: Missing argument exception.";
332                return NSCAPI::returnUNKNOWN;
333        }
334        std::list<CPULoadConatiner> list;
335        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
336        bool bNSClient = false;
337        bool bPerfData = true;
338        CPULoadConatiner tmpObject;
339
340        tmpObject.data = "cpuload";
341
342        MAP_OPTIONS_BEGIN(stl_args)
343                MAP_OPTIONS_NUMERIC_ALL(tmpObject, "")
344                MAP_OPTIONS_STR("warn", tmpObject.warn.max)
345                MAP_OPTIONS_STR("crit", tmpObject.crit.max)
346                MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
347                MAP_OPTIONS_STR_AND("time", tmpObject.data, list.push_back(tmpObject))
348                MAP_OPTIONS_STR_AND("Time", tmpObject.data, list.push_back(tmpObject))
349                MAP_OPTIONS_SHOWALL(tmpObject)
350                MAP_OPTIONS_BOOL_TRUE(NSCLIENT, bNSClient)
351                        MAP_OPTIONS_SECONDARY_BEGIN(":", p2)
352                        else if (p2.first == "Time") {
353                                tmpObject.data = p__.second;
354                                tmpObject.alias = p2.second;
355                                list.push_back(tmpObject);
356                        }
357                        MAP_OPTIONS_MISSING_EX(p2, msg, "Unknown argument: ")
358                        MAP_OPTIONS_SECONDARY_END()
359                MAP_OPTIONS_FALLBACK_AND(tmpObject.data, list.push_back(tmpObject))
360        MAP_OPTIONS_END()
361
362        for (std::list<CPULoadConatiner>::const_iterator it = list.begin(); it != list.end(); ++it) {
363                CPULoadConatiner load = (*it);
364                PDHCollector *pObject = pdhThread.getThread();
365                if (!pObject) {
366                        msg = "ERROR: PDH Collection thread not running.";
367                        return NSCAPI::returnUNKNOWN;
368                }
369                int value = pObject->getCPUAvrage(load.data + "m");
370                if (value == -1) {
371                        msg = "ERROR: We don't collect data this far back: " + load.getAlias();
372                        return NSCAPI::returnUNKNOWN;
373                }
374                if (bNSClient) {
375                        if (!msg.empty()) msg += "&";
376                        msg += strEx::itos(value);
377                } else {
378                        load.setDefault(tmpObject);
379                        load.perfData = bPerfData;
380                        load.runCheck(value, returnCode, msg, perf);
381                }
382        }
383
384        if (msg.empty())
385                msg = "OK CPU Load ok.";
386        else if (!bNSClient)
387                msg = NSCHelper::translateReturn(returnCode) + ": " + msg;
388        return returnCode;
389}
390
391NSCAPI::nagiosReturn CheckSystem::checkUpTime(const unsigned int argLen, char **char_args, std::string &msg, std::string &perf)
392{
393        typedef checkHolders::CheckConatiner<checkHolders::MaxMinBoundsTime> UpTimeConatiner;
394
395        std::list<std::string> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args);
396        if (stl_args.empty()) {
397                msg = "ERROR: Missing argument exception.";
398                return NSCAPI::returnUNKNOWN;
399        }
400        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
401        bool bNSClient = false;
402        bool bPerfData = true;
403        UpTimeConatiner bounds;
404
405        bounds.data = "uptime";
406
407        MAP_OPTIONS_BEGIN(stl_args)
408                MAP_OPTIONS_NUMERIC_ALL(bounds, "")
409                MAP_OPTIONS_STR("warn", bounds.warn.min)
410                MAP_OPTIONS_STR("crit", bounds.crit.min)
411                MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
412                MAP_OPTIONS_STR("Alias", bounds.data)
413                MAP_OPTIONS_SHOWALL(bounds)
414                MAP_OPTIONS_BOOL_TRUE(NSCLIENT, bNSClient)
415                MAP_OPTIONS_MISSING(msg, "Unknown argument: ")
416        MAP_OPTIONS_END()
417
418
419        PDHCollector *pObject = pdhThread.getThread();
420        if (!pObject) {
421                msg = "ERROR: PDH Collection thread not running.";
422                return NSCAPI::returnUNKNOWN;
423        }
424        unsigned long long value = pObject->getUptime();
425        if (bNSClient) {
426                msg = strEx::itos(value);
427        } else {
428                value *= 1000;
429                bounds.perfData = bPerfData;
430                bounds.runCheck(value, returnCode, msg, perf);
431        }
432
433        if (msg.empty())
434                msg = "OK all counters within bounds.";
435        else if (!bNSClient)
436                msg = NSCHelper::translateReturn(returnCode) + ": " + msg;
437        return returnCode;
438}
439
440// @todo state_handler
441
442
443
444/**
445 * Retrieve the service state of one or more services (by name).
446 * Parse a list with a service names and verify that all named services are running.
447 * <pre>
448 * Syntax:
449 * request: checkServiceState <option> [<option> [...]]
450 * Return: <return state>&<service1> : <state1> - <service2> : <state2> - ...
451 * Available options:
452 *              <name>=<state>  Check if a service has a specific state
453 *                      State can be wither started or stopped
454 *              ShowAll                 Show the state of all listed service. If not set only critical services are listed.
455 * Examples:
456 * checkServiceState showAll myService MyService
457 *</pre>
458 *
459 * @param command Command to execute
460 * @param argLen The length of the argument buffer
461 * @param **char_args The argument buffer
462 * @param &msg String to put message in
463 * @param &perf String to put performance data in
464 * @return The status of the command
465 */
466NSCAPI::nagiosReturn CheckSystem::checkServiceState(const unsigned int argLen, char **char_args, std::string &msg, std::string &perf)
467{
468        typedef checkHolders::CheckConatiner<checkHolders::SimpleBoundsStateBoundsInteger> StateConatiner;
469        std::list<std::string> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args);
470        if (stl_args.empty()) {
471                msg = "ERROR: Missing argument exception.";
472                return NSCAPI::returnUNKNOWN;
473        }
474        std::list<StateConatiner> list;
475        std::set<std::string> excludeList;
476        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
477        bool bNSClient = false;
478        StateConatiner tmpObject;
479        bool bPerfData = true;
480        bool bAutoStart = false;
481
482        tmpObject.data = "service";
483        tmpObject.crit.state = "started";
484        //{{
485        MAP_OPTIONS_BEGIN(stl_args)
486                MAP_OPTIONS_SHOWALL(tmpObject)
487                MAP_OPTIONS_STR("Alias", tmpObject.data)
488                MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
489                MAP_OPTIONS_BOOL_TRUE(NSCLIENT, bNSClient)
490                MAP_OPTIONS_BOOL_TRUE("CheckAll", bAutoStart)
491                MAP_OPTIONS_INSERT("exclude", excludeList)
492                MAP_OPTIONS_SECONDARY_BEGIN(":", p2)
493                        MAP_OPTIONS_MISSING_EX(p2, msg, "Unknown argument: ")
494                MAP_OPTIONS_SECONDARY_END()
495                else {
496                        tmpObject.data = p__.first;
497                        if (p__.second.empty())
498                                tmpObject.crit.state = "started";
499                        else
500                                tmpObject.crit.state = p__.second;
501                        list.push_back(tmpObject);
502                }
503        MAP_OPTIONS_END()
504        //}}
505        if (bAutoStart) {
506                // get a list of all service with startup type Automatic
507                std::list<TNtServiceInfo> service_list_automatic;
508                TNtServiceInfo::EnumServices(SERVICE_WIN32,SERVICE_INACTIVE|SERVICE_ACTIVE,&service_list_automatic);
509                for (std::list<TNtServiceInfo>::const_iterator service =service_list_automatic.begin();service!=service_list_automatic.end();++service) {
510                        if (excludeList.find((*service).m_strServiceName) == excludeList.end()) {
511                                if((*service).m_dwStartType == 2 ) {
512                                        tmpObject.data = (*service).m_strServiceName;
513                                        tmpObject.crit.state = "started";
514                                        list.push_back(tmpObject);
515                                        //stl_forward.push_back((*service).m_strServiceName);
516                                }
517                                else if((*service).m_dwStartType == 4 ) {
518                                        tmpObject.data = (*service).m_strServiceName;
519                                        tmpObject.crit.state = "stopped";
520                                        list.push_back(tmpObject);
521                                }
522                        }
523                }
524        }
525        for (std::list<StateConatiner>::iterator it = list.begin(); it != list.end(); ++it) {
526                TNtServiceInfo info;
527                if (bNSClient) {
528                        try {
529                                info = TNtServiceInfo::GetService((*it).data.c_str());
530                        } catch (NTServiceException e) {
531                                if (!msg.empty()) msg += " - ";
532                                msg += (*it).data + ": Unknown";
533                                NSCHelper::escalteReturnCodeToWARN(returnCode);
534                                continue;
535                        }
536                        if ((info.m_dwCurrentState == SERVICE_RUNNING) && (*it).showAll()) {
537                                if (!msg.empty()) msg += " - ";
538                                msg += (*it).data + ": Started";
539                        } else if (info.m_dwCurrentState == SERVICE_RUNNING) {
540                        } else if (info.m_dwCurrentState == SERVICE_STOPPED) {
541                                if (!msg.empty()) msg += " - ";
542                                msg += (*it).data + ": Stopped";
543                                NSCHelper::escalteReturnCodeToCRIT(returnCode);
544                        } else {
545                                if (!msg.empty()) msg += " - ";
546                                msg += (*it).data + ": Unknown";
547                                NSCHelper::escalteReturnCodeToWARN(returnCode);
548                        }
549                } else {
550                        try {
551                                info = TNtServiceInfo::GetService((*it).data.c_str());
552                        } catch (NTServiceException e) {
553                                NSC_LOG_ERROR_STD(e.getError());
554                                msg = e.getError();
555                                return NSCAPI::returnUNKNOWN;
556                        }
557                        checkHolders::state_type value;
558                        if (info.m_dwCurrentState == SERVICE_RUNNING)
559                                value = checkHolders::state_started;
560                        else if (info.m_dwCurrentState == SERVICE_STOPPED)
561                                value = checkHolders::state_stopped;
562                        else
563                                value = checkHolders::state_none;
564                        (*it).perfData = bPerfData;
565                        (*it).runCheck(value, returnCode, msg, perf);
566                }
567
568        }
569        if (msg.empty())
570                msg = "OK: All services are running.";
571        else if (!bNSClient)
572                msg = NSCHelper::translateReturn(returnCode) + ": " + msg;
573        return returnCode;
574}
575
576/**
577 * Check available memory and return various check results
578 * Example: checkMem showAll maxWarn=50 maxCrit=75
579 *
580 * @param command Command to execute
581 * @param argLen The length of the argument buffer
582 * @param **char_args The argument buffer
583 * @param &msg String to put message in
584 * @param &perf String to put performance data in
585 * @return The status of the command
586 */
587NSCAPI::nagiosReturn CheckSystem::checkMem(const unsigned int argLen, char **char_args, std::string &msg, std::string &perf)
588{
589        typedef checkHolders::CheckConatiner<checkHolders::MaxMinBounds<checkHolders::NumericPercentageBounds<checkHolders::PercentageValueType<unsigned __int64, unsigned __int64>, checkHolders::disk_size_handler<unsigned __int64> > > > MemoryConatiner;
590        std::list<std::string> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args);
591        if (stl_args.empty()) {
592                msg = "ERROR: Missing argument exception.";
593                return NSCAPI::returnUNKNOWN;
594        }
595        std::list<MemoryConatiner> list;
596        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
597        bool bShowAll = false;
598        bool bPerfData = true;
599        bool bNSClient = false;
600        MemoryConatiner tmpObject;
601
602        MAP_OPTIONS_BEGIN(stl_args)
603                MAP_OPTIONS_SHOWALL(tmpObject)
604                MAP_OPTIONS_STR_AND("type", tmpObject.data, list.push_back(tmpObject))
605                MAP_OPTIONS_STR_AND("Type", tmpObject.data, list.push_back(tmpObject))
606                MAP_OPTIONS_SECONDARY_BEGIN(":", p2)
607                        MAP_OPTIONS_SECONDARY_STR_AND(p2,"type", tmpObject.data, tmpObject.alias, list.push_back(tmpObject))
608                        MAP_OPTIONS_MISSING_EX(p2, msg, "Unknown argument: ")
609                MAP_OPTIONS_SECONDARY_END()
610                MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
611                MAP_OPTIONS_BOOL_TRUE(NSCLIENT, bNSClient)
612                MAP_OPTIONS_DISK_ALL(tmpObject, "", "Free", "Used")
613                MAP_OPTIONS_STR("Alias", tmpObject.data)
614                MAP_OPTIONS_SHOWALL(tmpObject)
615                MAP_OPTIONS_MISSING(msg, "Unknown argument: ")
616        MAP_OPTIONS_END()
617
618        if (bNSClient) {
619                tmpObject.data = "paged";
620                list.push_back(tmpObject);
621        }
622
623        checkHolders::PercentageValueType<unsigned long long, unsigned long long> dataPaged;
624        CheckMemory::memData data;
625        bool firstPaged = true;
626        bool firstMem = true;
627        for (std::list<MemoryConatiner>::const_iterator pit = list.begin(); pit != list.end(); ++pit) {
628                MemoryConatiner check = (*pit);
629                check.setDefault(tmpObject);
630                checkHolders::PercentageValueType<unsigned long long, unsigned long long> value;
631                if (firstPaged && (check.data == "paged")) {
632                        firstPaged = false;
633                        PDHCollector *pObject = pdhThread.getThread();
634                        if (!pObject) {
635                                msg = "ERROR: PDH Collection thread not running.";
636                                return NSCAPI::returnUNKNOWN;
637                        }
638                        dataPaged.value = pObject->getMemCommit();
639                        dataPaged.total = pObject->getMemCommitLimit();
640                } else if (firstMem) {
641                        try {
642                                data = memoryChecker.getMemoryStatus();
643                        } catch (CheckMemoryException e) {
644                                msg = e.getError() + ":" + strEx::itos(e.getErrorCode());
645                                return NSCAPI::returnCRIT;
646                        }
647                }
648
649                if (check.data == "page") {
650                        value.value = data.pageFile.total-data.pageFile.avail; // mem.dwTotalPageFile-mem.dwAvailPageFile;
651                        value.total = data.pageFile.total; //mem.dwTotalPageFile;
652                        if (check.alias.empty())
653                                check.alias = "page file";
654                } else if (check.data == "physical") {
655                        value.value = data.phys.total-data.phys.avail; //mem.dwTotalPhys-mem.dwAvailPhys;
656                        value.total = data.phys.total; //mem.dwTotalPhys;
657                        if (check.alias.empty())
658                                check.alias = "physical memory";
659                } else if (check.data == "virtual") {
660                        value.value = data.virtualMem.total-data.virtualMem.avail;//mem.dwTotalVirtual-mem.dwAvailVirtual;
661                        value.total = data.virtualMem.total;//mem.dwTotalVirtual;
662                        if (check.alias.empty())
663                                check.alias = "virtual memory";
664                } else  if (check.data == "paged") {
665                        value.value = dataPaged.value;
666                        value.total = dataPaged.total;
667                        if (check.alias.empty())
668                                check.alias = "paged bytes";
669                } else {
670                        msg = check.data + " is not a known check...";
671                        return NSCAPI::returnCRIT;
672                }
673                if (bNSClient) {
674                        msg = strEx::itos(value.total) + "&" + strEx::itos(value.value);
675                        return NSCAPI::returnOK;
676                } else {
677                        check.perfData = bPerfData;
678                        check.runCheck(value, returnCode, msg, perf);
679                }
680        }
681        NSC_DEBUG_MSG_STD("Perf data: " + strEx::itos(bPerfData) + ":" + perf);
682
683        if (msg.empty())
684                msg = "OK memory within bounds.";
685        else
686                msg = NSCHelper::translateReturn(returnCode) + ": " + msg;
687        return returnCode;
688}
689typedef struct NSPROCDATA__ {
690        NSPROCDATA__() : count(0) {}
691        NSPROCDATA__(const NSPROCDATA__ &other) {
692                count = other.count;
693                entry = other.entry;
694        }
695
696        unsigned int count;
697        CEnumProcess::CProcessEntry entry;
698} NSPROCDATA;
699typedef std::map<std::string,NSPROCDATA,strEx::case_blind_string_compare> NSPROCLST;
700/**
701* Get a hash_map with all running processes.
702* @return a hash_map with all running processes
703*/
704NSPROCLST GetProcessList(int processMethod)
705{
706        NSPROCLST ret;
707        if (processMethod == 0) {
708                NSC_LOG_ERROR_STD("ProcessMethod not defined or not available.");
709                return ret;
710        }
711        CEnumProcess enumeration;
712        enumeration.SetMethod(processMethod);
713        CEnumProcess::CProcessEntry entry;
714        for (BOOL OK = enumeration.GetProcessFirst(&entry); OK; OK = enumeration.GetProcessNext(&entry) ) {
715                NSPROCLST::iterator it = ret.find(entry.sFilename);
716                if (it == ret.end())
717                        ret[entry.sFilename].entry = entry;
718                else
719                        (*it).second.count++;
720        }
721        return ret;
722}
723
724/**
725 * Check process state and return result
726 *
727 * @param command Command to execute
728 * @param argLen The length of the argument buffer
729 * @param **char_args The argument buffer
730 * @param &msg String to put message in
731 * @param &perf String to put performance data in
732 * @return The status of the command
733 */
734NSCAPI::nagiosReturn CheckSystem::checkProcState(const unsigned int argLen, char **char_args, std::string &msg, std::string &perf)
735{
736        typedef checkHolders::CheckConatiner<checkHolders::MaxMinStateBoundsStateBoundsInteger> StateConatiner;
737        std::list<std::string> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args);
738        if (stl_args.empty()) {
739                msg = "ERROR: Missing argument exception.";
740                return NSCAPI::returnUNKNOWN;
741        }
742        std::list<StateConatiner> list;
743        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
744        bool bNSClient = false;
745        StateConatiner tmpObject;
746        bool bPerfData = true;
747
748        tmpObject.data = "uptime";
749        tmpObject.crit.state = "started";
750
751        MAP_OPTIONS_BEGIN(stl_args)
752                MAP_OPTIONS_NUMERIC_ALL(tmpObject, "Count")
753                MAP_OPTIONS_STR("Alias", tmpObject.alias)
754                MAP_OPTIONS_SHOWALL(tmpObject)
755                MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
756                MAP_OPTIONS_BOOL_TRUE(NSCLIENT, bNSClient)
757                MAP_OPTIONS_SECONDARY_BEGIN(":", p2)
758                else if (p2.first == "Proc") {
759                        tmpObject.data = p__.second;
760                        tmpObject.alias = p2.second;
761                        list.push_back(tmpObject);
762                }
763                MAP_OPTIONS_MISSING_EX(p2, msg, "Unknown argument: ")
764                        MAP_OPTIONS_SECONDARY_END()
765                else {
766                        tmpObject.data = p__.first;
767                        if (p__.second.empty())
768                                tmpObject.crit.state = "started";
769                        else
770                                tmpObject.crit.state = p__.second;
771                        list.push_back(tmpObject);
772                }
773        MAP_OPTIONS_END()
774
775
776        NSPROCLST runningProcs;
777        try {
778                runningProcs = GetProcessList(processMethod_);
779        } catch (char *c) {
780                NSC_LOG_ERROR_STD("ERROR: " + c);
781                msg = static_cast<std::string>("ERROR: ") + c;
782                return NSCAPI::returnUNKNOWN;
783        }
784
785        for (std::list<StateConatiner>::iterator it = list.begin(); it != list.end(); ++it) {
786                NSPROCLST::iterator proc = runningProcs.find((*it).data);
787                bool bFound = proc != runningProcs.end();
788                std::string tmp;
789                TNtServiceInfo info;
790                if (bNSClient) {
791                        if (bFound && (*it).showAll()) {
792                                if (!msg.empty()) msg += " - ";
793                                msg += (*it).data + ": Running";
794                        } else if (bFound) {
795                        } else {
796                                if (!msg.empty()) msg += " - ";
797                                msg += (*it).data + ": not running";
798                                NSCHelper::escalteReturnCodeToCRIT(returnCode);
799                        }
800                } else {
801                        checkHolders::MaxMinStateValueType<int, checkHolders::state_type> value;
802                        if (bFound) {
803                                value.count = (*proc).second.count;
804                                value.state = checkHolders::state_started;
805                        } else {
806                                value.count = 0;
807                                value.state = checkHolders::state_stopped;
808                        }
809                        (*it).perfData = bPerfData;
810                        (*it).runCheck(value, returnCode, msg, perf);
811                }
812
813        }
814        if (msg.empty())
815                msg = "OK: All processes are running.";
816        else if (!bNSClient)
817                msg = NSCHelper::translateReturn(returnCode) + ": " + msg;
818        return returnCode;
819}
820
821
822/**
823 * Check a counter and return the value
824 *
825 * @param command Command to execute
826 * @param argLen The length of the argument buffer
827 * @param **char_args The argument buffer
828 * @param &msg String to put message in
829 * @param &perf String to put performance data in
830 * @return The status of the command
831 *
832 * @todo add parsing support for NRPE
833 */
834NSCAPI::nagiosReturn CheckSystem::checkCounter(const unsigned int argLen, char **char_args, std::string &msg, std::string &perf)
835{
836        typedef checkHolders::CheckConatiner<checkHolders::MaxMinBoundsDouble> CounterConatiner;
837
838        std::list<std::string> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args);
839        if (stl_args.empty()) {
840                msg = "ERROR: Missing argument exception.";
841                return NSCAPI::returnUNKNOWN;
842        }
843        std::list<CounterConatiner> counters;
844        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
845        bool bNSClient = false;
846        bool bPerfData = true;
847        /* average maax */
848        bool bCheckAverages = true;
849        unsigned int averageDelay = 1000;
850        CounterConatiner tmpObject;
851
852        MAP_OPTIONS_BEGIN(stl_args)
853                MAP_OPTIONS_STR_AND("Counter", tmpObject.data, counters.push_back(tmpObject))
854                MAP_OPTIONS_STR("MaxWarn", tmpObject.warn.max)
855                MAP_OPTIONS_STR("MinWarn", tmpObject.warn.min)
856                MAP_OPTIONS_STR("MaxCrit", tmpObject.crit.max)
857                MAP_OPTIONS_STR("MinCrit", tmpObject.crit.min)
858                MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
859                MAP_OPTIONS_STR("Alias", tmpObject.data)
860                MAP_OPTIONS_SHOWALL(tmpObject)
861                MAP_OPTIONS_BOOL_EX("Averages", bCheckAverages, "true", "false")
862                MAP_OPTIONS_BOOL_TRUE(NSCLIENT, bNSClient)
863                MAP_OPTIONS_FIRST_CHAR('\\', tmpObject.data, counters.push_back(tmpObject))
864                MAP_OPTIONS_SECONDARY_BEGIN(":", p2)
865                        else if (p2.first == "Counter") {
866                                tmpObject.data = p__.second;
867                                tmpObject.alias = p2.second;
868                                counters.push_back(tmpObject);
869                        }
870                        MAP_OPTIONS_MISSING_EX(p2, msg, "Unknown argument: ")
871                MAP_OPTIONS_SECONDARY_END()
872                MAP_OPTIONS_FALLBACK_AND(tmpObject.data, counters.push_back(tmpObject))
873        MAP_OPTIONS_END()
874        for (std::list<CounterConatiner>::const_iterator cit = counters.begin(); cit != counters.end(); ++cit) {
875                CounterConatiner counter = (*cit);
876                try {
877                        std::string tstr;
878                        if (!PDH::Enumerations::validate(counter.data, tstr)) {
879                                msg = tstr;
880                                msg += " (" + counter.getAlias() + "|" + counter.data + ")";
881                                return NSCAPI::returnUNKNOWN;
882                        }
883                        PDH::PDHQuery pdh;
884                        PDHCollectors::StaticPDHCounterListener<double, PDH_FMT_DOUBLE> cDouble;
885                        pdh.addCounter(counter.data, &cDouble);
886                        pdh.open();
887                        if (bCheckAverages) {
888                                pdh.collect();
889                                Sleep(1000);
890                        }
891                        pdh.gatherData();
892                        pdh.close();
893                        double value = cDouble.getValue();
894                        std::cout << "Collected double data: " << value << std::endl;
895                        if (bNSClient) {
896                                msg += strEx::itos(value);
897                        } else {
898                                counter.perfData = bPerfData;
899                                counter.setDefault(tmpObject);
900                                counter.runCheck(value, returnCode, msg, perf);
901                        }
902                } catch (const PDH::PDHException e) {
903                        NSC_LOG_ERROR_STD("ERROR: " + e.getError() + " (" + counter.getAlias() + "|" + counter.data + ")");
904                        msg = static_cast<std::string>("ERROR: ") + e.getError()+ " (" + counter.getAlias() + "|" + counter.data + ")";
905                        return NSCAPI::returnUNKNOWN;
906                }
907        }
908
909        if (msg.empty())
910                msg = "OK all counters within bounds.";
911        else if (!bNSClient)
912                msg = NSCHelper::translateReturn(returnCode) + ": " + msg;
913        return returnCode;
914}
915NSC_WRAPPERS_MAIN_DEF(gCheckSystem);
916NSC_WRAPPERS_IGNORE_MSG_DEF();
917NSC_WRAPPERS_HANDLE_CMD_DEF(gCheckSystem);
918NSC_WRAPPERS_HANDLE_CONFIGURATION(gCheckSystem);
919NSC_WRAPPERS_CLI_DEF(gCheckSystem);
920
921
922
923MODULE_SETTINGS_START(CheckSystem, "System check module", "...")
924
925PAGE("Check options")
926
927ITEM_EDIT_TEXT("Check resolution", "This is how often the PDH data is polled and stored in the CPU buffer. (this is enterd in 1/th: of a second)")
928OPTION("unit", "1/10:th of a second")
929ITEM_MAP_TO("basic_ini_text_mapper")
930OPTION("section", "Check System")
931OPTION("key", "CheckResolution")
932OPTION("default", "10")
933ITEM_END()
934
935ITEM_EDIT_TEXT("CPU buffer size", "This is the size of the buffer that stores CPU history.")
936ITEM_MAP_TO("basic_ini_text_mapper")
937OPTION("section", "Check System")
938OPTION("key", "CPUBufferSize")
939OPTION("default", "1h")
940ITEM_END()
941
942PAGE_END()
943ADVANCED_PAGE("Compatiblity settings")
944
945ITEM_EDIT_TEXT("MemoryCommitByte", "The memory commited bytes used to calculate the avalible memory.")
946OPTION("disableCaption", "Attempt to autodetect this.")
947OPTION("disabled", "auto")
948ITEM_MAP_TO("basic_ini_text_mapper")
949OPTION("section", "Check System")
950OPTION("key", "MemoryCommitByte")
951OPTION("default", "auto")
952ITEM_END()
953
954ITEM_EDIT_TEXT("MemoryCommitLimit", "The memory commit limit used to calculate the avalible memory.")
955OPTION("disableCaption", "Attempt to autodetect this.")
956OPTION("disabled", "auto")
957ITEM_MAP_TO("basic_ini_text_mapper")
958OPTION("section", "Check System")
959OPTION("key", "MemoryCommitLimit")
960OPTION("default", "auto")
961ITEM_END()
962
963ITEM_EDIT_TEXT("SystemSystemUpTime", "The PDH counter for the System uptime.")
964OPTION("disableCaption", "Attempt to autodetect this.")
965OPTION("disabled", "auto")
966ITEM_MAP_TO("basic_ini_text_mapper")
967OPTION("section", "Check System")
968OPTION("key", "SystemSystemUpTime")
969OPTION("default", "auto")
970ITEM_END()
971
972ITEM_EDIT_TEXT("SystemTotalProcessorTime", "The PDH conter usaed to measure CPU load.")
973OPTION("disableCaption", "Attempt to autodetect this.")
974OPTION("disabled", "auto")
975ITEM_MAP_TO("basic_ini_text_mapper")
976OPTION("section", "Check System")
977OPTION("key", "SystemTotalProcessorTime")
978OPTION("default", "auto")
979ITEM_END()
980
981ITEM_EDIT_TEXT("ProcessEnumerationMethod", "The method to use when enumerating processes")
982OPTION("count", "3")
983OPTION("caption_1", "Autodetect (TOOLHELP for NT/4 and PSAPI for W2k)")
984OPTION("value_1", "auto")
985OPTION("caption_2", "TOOLHELP use this for NT/4 systems")
986OPTION("value_2", "TOOLHELP")
987OPTION("caption_3", "PSAPI use this for W2k (and abowe) systems")
988OPTION("value_3", "PSAPI")
989ITEM_MAP_TO("basic_ini_text_mapper")
990OPTION("section", "Check System")
991OPTION("key", "ProcessEnumerationMethod")
992OPTION("default", "auto")
993ITEM_END()
994
995PAGE_END()
996MODULE_SETTINGS_END()
Note: See TracBrowser for help on using the repository browser.