]> granicus.if.org Git - icinga2/blobdiff - plugins/check_swap.cpp
Merge pull request #7150 from Icinga/bugfix/api-config-package-active-stage-name
[icinga2] / plugins / check_swap.cpp
index 784f313152056f638beb0c6b7693803755b55b01..dc08f3b3b98c12c431f1c94051ee6c8f4d5f84ef 100644 (file)
@@ -1,50 +1,48 @@
-/******************************************************************************
- * Icinga 2                                                                   *
- * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/)  *
- *                                                                            *
- * This program is free software; you can redistribute it and/or              *
- * modify it under the terms of the GNU General Public License                *
- * as published by the Free Software Foundation; either version 2             *
- * of the License, or (at your option) any later version.                     *
- *                                                                            *
- * This program is distributed in the hope that it will be useful,            *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
- * GNU General Public License for more details.                               *
- *                                                                            *
- * You should have received a copy of the GNU General Public License          *
- * along with this program; if not, write to the Free Software Foundation     *
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
- ******************************************************************************/
-#include <Shlwapi.h>
-#include <iostream>
-#include <WinBase.h>
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
 
-#include "check_swap.h"
+#include "plugins/thresholds.hpp"
+#include <boost/program_options.hpp>
+#include <iostream>
+#include <shlwapi.h>
+#include <Psapi.h>
+#include <vector>
 
 #define VERSION 1.0
 
 namespace po = boost::program_options;
 
-static BOOL debug = FALSE;
-
-INT wmain(INT argc, WCHAR **argv)
+struct printInfoStruct
 {
-       printInfoStruct printInfo = { };
-       po::variables_map vm;
+       threshold warn;
+       threshold crit;
+       double tSwap;
+       double aSwap;
+       double percentFree;
+       Bunit unit = BunitMB;
+       bool showUsed;
+};
+
+struct pageFileInfo
+{
+       SIZE_T totalSwap;
+       SIZE_T availableSpwap;
+};
 
-       INT ret = parseArguments(argc, argv, vm, printInfo);
-       if (ret != -1)
-               return ret;
+static bool l_Debug;
 
-       ret = check_swap(printInfo);
-       if (ret != -1)
-               return ret;
+BOOL EnumPageFilesProc(LPVOID pContext, PENUM_PAGE_FILE_INFORMATION pPageFileInfo, LPCWSTR lpFilename) {
+       std::vector<pageFileInfo>* pageFile = static_cast<std::vector<pageFileInfo>*>(pContext);
+       SYSTEM_INFO systemInfo;
 
-       return printOutput(printInfo);
+       GetSystemInfo(&systemInfo);
+
+       // pPageFileInfo output is in pages, we need to multiply it by the page size
+       pageFile->push_back({ pPageFileInfo->TotalSize * systemInfo.dwPageSize, (pPageFileInfo->TotalSize - pPageFileInfo->TotalInUse) * systemInfo.dwPageSize });
+
+       return TRUE;
 }
 
-INT parseArguments(INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo)
+static int parseArguments(int ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo)
 {
        WCHAR namePath[MAX_PATH];
        GetModuleFileName(NULL, namePath, MAX_PATH);
@@ -59,21 +57,22 @@ INT parseArguments(INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& p
                ("warning,w", po::wvalue<std::wstring>(), "Warning threshold")
                ("critical,c", po::wvalue<std::wstring>(), "Critical threshold")
                ("unit,u", po::wvalue<std::wstring>(), "The unit to use for display (default MB)")
+               ("show-used,U", "Show used swap instead of the free swap")
                ;
 
-       po::basic_command_line_parser<WCHAR> parser(ac, av);
+       po::wcommand_line_parser parser(ac, av);
 
        try {
                po::store(
                        parser
                        .options(desc)
                        .style(
-                       po::command_line_style::unix_style |
-                       po::command_line_style::allow_long_disguise)
+                               po::command_line_style::unix_style |
+                               po::command_line_style::allow_long_disguise)
                        .run(),
                        vm);
                vm.notify();
-       } catch (std::exception& e) {
+       } catch (const std::exception& e) {
                std::cout << e.what() << '\n' << desc << '\n';
                return 3;
        }
@@ -125,7 +124,7 @@ INT parseArguments(INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& p
        if (vm.count("warning")) {
                try {
                        printInfo.warn = threshold(vm["warning"].as<std::wstring>());
-               } catch (std::invalid_argument& e) {
+               } catch (const std::invalid_argument& e) {
                        std::cout << e.what() << '\n';
                        return 3;
                }
@@ -135,75 +134,105 @@ INT parseArguments(INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& p
        if (vm.count("critical")) {
                try {
                        printInfo.crit = threshold(vm["critical"].as<std::wstring>());
-               } catch (std::invalid_argument& e) {
+               } catch (const std::invalid_argument& e) {
                        std::cout << e.what() << '\n';
                        return 3;
                }
                printInfo.crit.legal = !printInfo.crit.legal;
        }
 
-       if (vm.count("debug"))
-               debug = TRUE;
+       l_Debug = vm.count("debug") > 0;
 
        if (vm.count("unit")) {
                try {
                        printInfo.unit = parseBUnit(vm["unit"].as<std::wstring>());
-               } catch (std::invalid_argument& e) {
+               } catch (const std::invalid_argument& e) {
                        std::cout << e.what() << '\n';
                        return 3;
                }
        }
 
+       if (vm.count("show-used")) {
+               printInfo.showUsed = true;
+               printInfo.warn.legal = true;
+               printInfo.crit.legal = true;
+       }
+
        return -1;
 }
 
-INT printOutput(printInfoStruct& printInfo)
+static int printOutput(printInfoStruct& printInfo)
 {
-       if (debug)
+       if (l_Debug)
                std::wcout << L"Constructing output string" << '\n';
 
        state state = OK;
 
-       if (printInfo.warn.rend(printInfo.aSwap, printInfo.tSwap))
+       std::wcout << L"SWAP ";
+
+       double currentValue;
+
+       if (!printInfo.showUsed)
+               currentValue = printInfo.aSwap;
+       else
+               currentValue = printInfo.tSwap - printInfo.aSwap;
+
+       if (printInfo.warn.rend(currentValue, printInfo.tSwap))
                state = WARNING;
 
-       if (printInfo.crit.rend(printInfo.aSwap, printInfo.tSwap))
+       if (printInfo.crit.rend(currentValue, printInfo.tSwap))
                state = CRITICAL;
 
-       switch (state) {
-       case OK:
-               std::wcout << L"SWAP OK - " << printInfo.percentFree << L"% free | swap=" << printInfo.aSwap << BunitStr(printInfo.unit) << L";"
-                       << printInfo.warn.pString(printInfo.tSwap) << L";" << printInfo.crit.pString(printInfo.tSwap)
-                       << L";0;" << printInfo.tSwap << '\n';
-               break;
-       case WARNING:
-               std::wcout << L"SWAP WARNING - " << printInfo.percentFree << L"% free | swap=" << printInfo.aSwap << BunitStr(printInfo.unit) << L";"
-                       << printInfo.warn.pString(printInfo.tSwap) << L";" << printInfo.crit.pString(printInfo.tSwap)
-                       << L";0;" << printInfo.tSwap << '\n';
-               break;
-       case CRITICAL:
-               std::wcout << L"SWAP CRITICAL - " << printInfo.percentFree << L"% free | swap=" << printInfo.aSwap << BunitStr(printInfo.unit) << L";"
-                       << printInfo.warn.pString(printInfo.tSwap) << L";" << printInfo.crit.pString(printInfo.tSwap)
-                       << L";0;" << printInfo.tSwap << '\n';
-               break;
-       }
+       std::wcout << stateToString(state) << " - ";
+
+       if (!printInfo.showUsed)
+               std::wcout << printInfo.percentFree << L"% free ";
+       else
+               std::wcout << 100 - printInfo.percentFree << L"% used ";
+
+       std::wcout << "| 'swap'=" << currentValue << BunitStr(printInfo.unit) << L";"
+               << printInfo.warn.pString(printInfo.tSwap) << L";" << printInfo.crit.pString(printInfo.tSwap)
+               << L";0;" << printInfo.tSwap << '\n';
 
        return state;
 }
 
-INT check_swap(printInfoStruct& printInfo)
+static int check_swap(printInfoStruct& printInfo)
 {
-       MEMORYSTATUSEX MemBuf;
-       MemBuf.dwLength = sizeof(MemBuf);
+       // Needs explicit cast: http://msinilo.pl/blog2/post/p1348/
+       PENUM_PAGE_FILE_CALLBACKW pageFileCallback = (PENUM_PAGE_FILE_CALLBACKW)EnumPageFilesProc;
+       std::vector<pageFileInfo> pageFiles;
 
-       if (!GlobalMemoryStatusEx(&MemBuf)) {
-               die();
+       if(!EnumPageFilesW(pageFileCallback, &pageFiles)) {
+               printErrorInfo();
                return 3;
        }
 
-       printInfo.tSwap = round(MemBuf.ullTotalPageFile / pow(1024.0, printInfo.unit));
-       printInfo.aSwap = round(MemBuf.ullAvailPageFile / pow(1024.0, printInfo.unit));
-       printInfo.percentFree = 100.0 * MemBuf.ullAvailPageFile / MemBuf.ullTotalPageFile;
+       for (int i = 0; i < pageFiles.size(); i++) {
+               printInfo.tSwap += round(pageFiles.at(i).totalSwap / pow(1024.0, printInfo.unit));
+               printInfo.aSwap += round(pageFiles.at(i).availableSpwap / pow(1024.0, printInfo.unit));
+       }
+
+       if (printInfo.aSwap > 0 && printInfo.tSwap > 0)
+               printInfo.percentFree = 100.0 * printInfo.aSwap / printInfo.tSwap;
+       else
+               printInfo.percentFree = 0;
 
        return -1;
 }
+
+int wmain(int argc, WCHAR **argv)
+{
+       printInfoStruct printInfo = { };
+       po::variables_map vm;
+
+       int ret = parseArguments(argc, argv, vm, printInfo);
+       if (ret != -1)
+               return ret;
+
+       ret = check_swap(printInfo);
+       if (ret != -1)
+               return ret;
+
+       return printOutput(printInfo);
+}