source: nscp/trunk/modules/CheckSystem/CheckSystem.cpp @ 3c35ad4

Last change on this file since 3c35ad4 was 3c35ad4, checked in by Michael Medin <michael@…>, 6 years ago

+ Added possibility to check many memory checks in one go, just stack type options.

type=paged type=physical etc...

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