"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.8.166/src/agent/subagents/linux/drbd.cpp" (23 Feb 2021, 7201 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "drbd.cpp" see the Fossies "Dox" file reference documentation.

    1 /* 
    2 ** NetXMS subagent for GNU/Linux
    3 ** Copyright (C) 2006-2020 Victor Kirhenshtein
    4 **
    5 ** This program is free software; you can redistribute it and/or modify
    6 ** it under the terms of the GNU General Public License as published by
    7 ** the Free Software Foundation; either version 2 of the License, or
    8 ** (at your option) any later version.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13 ** GNU General Public License for more details.
   14 **
   15 ** You should have received a copy of the GNU General Public License
   16 ** along with this program; if not, write to the Free Software
   17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18 **
   19 **/
   20 
   21 #include <linux_subagent.h>
   22 #include <regex.h>
   23 
   24 /**
   25  * Constants
   26  */
   27 #define MAX_DEVICE_COUNT        64
   28 #define STATUS_FIELD_LEN        64
   29 
   30 /**
   31  * DRBD device structure
   32  */
   33 typedef struct
   34 {
   35    int id;
   36    int protocol;
   37    char connState[STATUS_FIELD_LEN];
   38    char localDeviceState[STATUS_FIELD_LEN];
   39    char remoteDeviceState[STATUS_FIELD_LEN];
   40    char localDataState[STATUS_FIELD_LEN];
   41    char remoteDataState[STATUS_FIELD_LEN];
   42 } DRBD_DEVICE;
   43 
   44 /**
   45  * Static data
   46  */
   47 static DRBD_DEVICE s_devices[MAX_DEVICE_COUNT];
   48 static MUTEX s_deviceAccess = INVALID_MUTEX_HANDLE;
   49 static MUTEX s_versionAccess = INVALID_MUTEX_HANDLE;
   50 static char s_drbdVersion[32] = "0.0.0";
   51 static int s_apiVersion = 0;
   52 static char s_protocolVersion[32] = "0";
   53 static CONDITION s_stopCondition = INVALID_CONDITION_HANDLE;
   54 static THREAD s_collectorThread = INVALID_THREAD_HANDLE;
   55 
   56 /**
   57  * Read and parse /proc/drbd file
   58  */
   59 static bool ParseDrbdStatus()
   60 {
   61     char line[1024];
   62     FILE *fp;
   63     regex_t pregDevice, pregVersion;
   64     regmatch_t pmatch[9];
   65     DRBD_DEVICE device;
   66     bool rc = false;
   67 
   68     if (regcomp(&pregVersion, "version: (.*) \\(api\\:([0-9]+)\\/proto\\:([0-9\\-]+)\\)", REG_EXTENDED) != 0)
   69         return false;
   70     if (regcomp(&pregDevice, "^[[:space:]]*([0-9]+)\\: cs\\:(.*) (st|ro)\\:(.*)\\/(.*) ds\\:(.*)\\/([^[:space:]]*) ([^[:space:]]*) .*", REG_EXTENDED) != 0)
   71     {
   72         regfree(&pregVersion);
   73         return false;
   74     }
   75 
   76     fp = fopen("/proc/drbd", "r");
   77     if (fp != NULL)
   78     {
   79         MutexLock(s_deviceAccess);
   80         for(int i = 0; i < MAX_DEVICE_COUNT; i++)
   81             s_devices[i].id = -1;
   82 
   83         while(!feof(fp))
   84         {
   85             if (fgets(line, 1024, fp) == NULL)
   86                 break;
   87             if (regexec(&pregDevice, line, 9, pmatch, 0) == 0)
   88             {
   89                 for(int i = 1; i < 9; i++)
   90                     line[pmatch[i].rm_eo] = 0;
   91 
   92                 memset(&device, 0, sizeof(DRBD_DEVICE));
   93                 device.id = strtol(&line[pmatch[1].rm_so], NULL, 10);
   94                 device.protocol = line[pmatch[8].rm_so];
   95                 strlcpy(device.connState, &line[pmatch[2].rm_so], STATUS_FIELD_LEN);
   96                 strlcpy(device.localDeviceState, &line[pmatch[4].rm_so], STATUS_FIELD_LEN);
   97                 strlcpy(device.remoteDeviceState, &line[pmatch[5].rm_so], STATUS_FIELD_LEN);
   98                 strlcpy(device.localDataState, &line[pmatch[6].rm_so], STATUS_FIELD_LEN);
   99                 strlcpy(device.remoteDataState, &line[pmatch[7].rm_so], STATUS_FIELD_LEN);
  100 
  101                 if ((device.id >= 0) && (device.id < MAX_DEVICE_COUNT))
  102                 {
  103                     memcpy(&s_devices[device.id], &device, sizeof(DRBD_DEVICE));
  104                 }
  105             }
  106             else if (regexec(&pregVersion, line, 9, pmatch, 0) == 0)
  107             {
  108                 for(int i = 1; i < 4; i++)
  109                     line[pmatch[i].rm_eo] = 0;
  110 
  111                 MutexLock(s_versionAccess);
  112                 strlcpy(s_drbdVersion, &line[pmatch[1].rm_so], 32);
  113                 s_apiVersion = strtol(&line[pmatch[2].rm_so], NULL, 10);
  114                 strlcpy(s_protocolVersion, &line[pmatch[3].rm_so], 32);
  115                 MutexUnlock(s_versionAccess);
  116             }
  117         }
  118         MutexUnlock(s_deviceAccess);
  119         fclose(fp);
  120         rc = true;
  121     }
  122     else
  123     {
  124         MutexLock(s_deviceAccess);
  125         for(int i = 0; i < MAX_DEVICE_COUNT; i++)
  126             s_devices[i].id = -1;
  127         MutexUnlock(s_deviceAccess);
  128     }
  129 
  130     regfree(&pregVersion);
  131     regfree(&pregDevice);
  132     return rc;
  133 }
  134 
  135 /**
  136  * DRBD stat collector thread
  137  */
  138 static THREAD_RESULT THREAD_CALL CollectorThread(void *arg)
  139 {
  140     if (!ParseDrbdStatus())
  141     {
  142         AgentWriteDebugLog(1, _T("Unable to parse /proc/drbd, DRBD data collector will not start"));
  143         return THREAD_OK;
  144     }
  145 
  146     while(!ConditionWait(s_stopCondition, 15000))
  147         ParseDrbdStatus();
  148     return THREAD_OK;
  149 }
  150 
  151 /**
  152  * Initialize DRBD stat collector
  153  */
  154 void InitDrbdCollector()
  155 {
  156     s_deviceAccess = MutexCreate();
  157     s_versionAccess = MutexCreate();
  158     s_stopCondition = ConditionCreate(TRUE);
  159     s_collectorThread = ThreadCreateEx(CollectorThread, 0, NULL);
  160 }
  161 
  162 /**
  163  * Stop DRBD stat collector
  164  */
  165 void StopDrbdCollector()
  166 {
  167     ConditionSet(s_stopCondition);
  168     ThreadJoin(s_collectorThread);
  169     ConditionDestroy(s_stopCondition);
  170     MutexDestroy(s_deviceAccess);
  171     MutexDestroy(s_versionAccess);
  172 }
  173 
  174 /**
  175  * Get list of configured DRBD devices
  176  */
  177 LONG H_DRBDDeviceList(const TCHAR *pszCmd, const TCHAR *pArg, StringList *pValue, AbstractCommSession *session)
  178 {
  179    MutexLock(s_deviceAccess);
  180    for(int i = 0; i < MAX_DEVICE_COUNT; i++)
  181    {
  182       if (s_devices[i].id != -1)
  183       {
  184          TCHAR szBuffer[1024];
  185          _sntprintf(szBuffer, 1024, _T("/dev/drbd%d %hs %hs/%hs %hs/%hs %c"),
  186                i, s_devices[i].connState, s_devices[i].localDeviceState,
  187                s_devices[i].remoteDeviceState, s_devices[i].localDataState,
  188                s_devices[i].remoteDataState, (TCHAR)s_devices[i].protocol);
  189          pValue->add(szBuffer);
  190       }
  191    }
  192    MutexUnlock(s_deviceAccess);
  193    return SYSINFO_RC_SUCCESS;
  194 }
  195 
  196 /**
  197  * Get DRBD version
  198  */
  199 LONG H_DRBDVersion(const TCHAR *pszCmd, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
  200 {
  201     LONG nRet = SYSINFO_RC_SUCCESS;
  202     switch(*pArg)
  203     {
  204         case 'v':   // DRBD version
  205             ret_mbstring(pValue, s_drbdVersion);
  206             break;
  207         case 'a':   // API version
  208             ret_int(pValue, s_apiVersion);
  209             break;
  210         case 'p':   // Protocol version
  211             ret_mbstring(pValue, s_protocolVersion);
  212             break;
  213         default:
  214             nRet = SYSINFO_RC_UNSUPPORTED;
  215             break;
  216     }
  217     return nRet;
  218 }
  219 
  220 /**
  221  * Get information for specific DRBD device
  222  */
  223 LONG H_DRBDDeviceInfo(const TCHAR *pszCmd, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
  224 {
  225     TCHAR szDev[256], *eptr;
  226 
  227     if (!AgentGetParameterArg(pszCmd, 1, szDev, 256))
  228         return SYSINFO_RC_UNSUPPORTED;
  229 
  230    int nDev = _tcstol(szDev, &eptr, 0);
  231    if ((nDev < 0) || (nDev >= MAX_DEVICE_COUNT) || (*eptr != 0))
  232       return SYSINFO_RC_UNSUPPORTED;
  233 
  234    LONG nRet = SYSINFO_RC_ERROR;
  235    MutexLock(s_deviceAccess);
  236    if (s_devices[nDev].id != -1)
  237    {
  238       nRet = SYSINFO_RC_SUCCESS;
  239       switch(*pArg)
  240       {
  241          case 'c':   // Connection state as text
  242                 ret_mbstring(pValue, s_devices[nDev].connState);
  243                 break;
  244             case 's':   // State as text
  245                 ret_mbstring(pValue, s_devices[nDev].localDeviceState);
  246                 break;
  247             case 'S':   // Peer state as text
  248                 ret_mbstring(pValue, s_devices[nDev].remoteDeviceState);
  249                 break;
  250             case 'd':   // Data state as text
  251                 ret_mbstring(pValue, s_devices[nDev].localDataState);
  252                 break;
  253             case 'D':   // Peer data state as text
  254                 ret_mbstring(pValue, s_devices[nDev].remoteDataState);
  255                 break;
  256             case 'p':   // Protocol
  257                 pValue[0] = s_devices[nDev].protocol;
  258                 pValue[1] = 0;
  259                 break;
  260             default:
  261                 nRet = SYSINFO_RC_UNSUPPORTED;
  262                 break;
  263         }
  264    }
  265    MutexUnlock(s_deviceAccess);
  266 
  267    return nRet;
  268 }