- Support for CMD_GET_PARAMETER_LIST added to AgentConnection class
authorVictor Kirhenshtein <victor@netxms.org>
Mon, 24 Jan 2005 09:26:40 +0000 (09:26 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Mon, 24 Jan 2005 09:26:40 +0000 (09:26 +0000)
- Parameters data types and descriptions added to winperf subagent
- nxget now able to retrieve supported parameters list via CMD_GET_PARAMETER_LIST

12 files changed:
include/nms_util.h
include/nxclapi.h
src/agent/core/getparam.cpp
src/agent/core/nxagentd.h
src/agent/core/subagent.cpp
src/agent/subagents/winperf/collect.cpp
src/agent/subagents/winperf/winperf.cpp
src/agent/subagents/winperf/winperf.h
src/libnetxms/tools.cpp
src/server/include/nxsrvapi.h
src/server/libnxsrv/agent.cpp
src/server/tools/nxget/nxget.cpp

index 4e948db..6db8298 100644 (file)
@@ -209,6 +209,7 @@ extern "C"
 
    DWORD LIBNETXMS_EXPORTABLE NxLoadConfig(TCHAR *pszFileName, TCHAR *pszSection, 
                                            NX_CFG_TEMPLATE *pTemplateList, BOOL bPrint);
+   int LIBNETXMS_EXPORTABLE NxDCIDataTypeFromText(TCHAR *pszText);
 
    HMODULE LIBNETXMS_EXPORTABLE DLOpen(TCHAR *szLibName, TCHAR *pszErrorText);
    void LIBNETXMS_EXPORTABLE DLClose(HMODULE hModule);
index dbc6ef4..e506258 100644 (file)
@@ -416,6 +416,18 @@ typedef void * NXC_SESSION;
 #define ACTION_SEND_SMS       3
 
 
+//
+// Agent's parameter information
+//
+
+typedef struct
+{
+   TCHAR szName[MAX_PARAM_NAME];
+   TCHAR szDescription[MAX_DB_STRING];
+   int iDataType;
+} NXC_AGENT_PARAM;
+
+
 //
 // Action structure
 //
index 031b2aa..3e6a718 100644 (file)
@@ -143,7 +143,7 @@ static NETXMS_SUBAGENT_PARAM m_stdParams[] =
 #ifdef _WIN32
    { "Disk.Free(*)", H_DiskInfo, NULL, DCI_DT_UINT64, "Free disk space on *" },
    { "Disk.Total(*)", H_DiskInfo, NULL, DCI_DT_UINT64, "Total disk space on *" },
-   { "Disk.Used(*)", H_DiskInfo, NULL, DCI_DT_INT64, "Used disk space on *" },
+   { "Disk.Used(*)", H_DiskInfo, NULL, DCI_DT_UINT64, "Used disk space on *" },
    { "Net.Interface.AdminStatus(*)", H_NetInterfaceStats, (char *)NET_IF_ADMIN_STATUS, DCI_DT_INT, "Administrative status of *" },
    { "Net.Interface.BytesIn(*)", H_NetInterfaceStats, (char *)NET_IF_BYTES_IN, DCI_DT_UINT, "" },
    { "Net.Interface.BytesOut(*)", H_NetInterfaceStats, (char *)NET_IF_BYTES_OUT, DCI_DT_UINT, "" },
@@ -252,7 +252,8 @@ BOOL InitParameterList(void)
 // Add parameter to list
 //
 
-void AddParameter(char *pszName, LONG (* fpHandler)(char *,char *,char *), char *pArg)
+void AddParameter(char *pszName, LONG (* fpHandler)(char *,char *,char *), char *pArg,
+                  int iDataType, char *pszDescription)
 {
    int i;
 
@@ -262,8 +263,10 @@ void AddParameter(char *pszName, LONG (* fpHandler)(char *,char *,char *), char
          break;
    if (i < m_iNumParams)
    {
-      // Replace existing handler
+      // Replace existing handler and attributes
       m_pParamList[i].fpHandler = fpHandler;
+      m_pParamList[i].iDataType = iDataType;
+      strncpy(m_pParamList[i].szDescription, pszDescription, MAX_DB_STRING);
 
       // If we are replacing System.PlatformName, add pointer to
       // platform suffix as argument, otherwise, use supplied pArg
@@ -283,7 +286,8 @@ void AddParameter(char *pszName, LONG (* fpHandler)(char *,char *,char *), char
       strncpy(m_pParamList[m_iNumParams].szName, pszName, MAX_PARAM_NAME - 1);
       m_pParamList[m_iNumParams].fpHandler = fpHandler;
       m_pParamList[m_iNumParams].pArg = pArg;
-      m_pParamList[m_iNumParams].szDescription[0] = 0;
+      m_pParamList[m_iNumParams].iDataType = iDataType;
+      strncpy(m_pParamList[m_iNumParams].szDescription, pszDescription, MAX_DB_STRING);
       m_iNumParams++;
    }
 }
@@ -338,7 +342,7 @@ BOOL AddExternalParameter(char *pszCfgLine)
    if ((*pszCfgLine == 0) || (*pszCmdLine == 0))
       return FALSE;
 
-   AddParameter(pszCfgLine, H_ExternalParameter, strdup(pszCmdLine));
+   AddParameter(pszCfgLine, H_ExternalParameter, strdup(pszCmdLine), DCI_DT_STRING, "");
    return TRUE;
 }
 
index ae894d9..adf5dd3 100644 (file)
@@ -279,7 +279,8 @@ void DebugPrintf(char *pszFormat, ...);
 void BuildFullPath(TCHAR *pszFileName, TCHAR *pszFullPath);
 
 BOOL InitParameterList(void);
-void AddParameter(char *szName, LONG (* fpHandler)(char *,char *,char *), char *pArg);
+void AddParameter(char *szName, LONG (* fpHandler)(char *,char *,char *), char *pArg,
+                  int iDataType, char *pszDescription);
 void AddEnum(char *szName, LONG (* fpHandler)(char *,char *,NETXMS_VALUES_LIST *), char *pArg);
 BOOL AddExternalParameter(char *pszCfgLine);
 DWORD GetParameterValue(char *pszParam, char *pszValue);
index fb3422d..57cf796 100644 (file)
@@ -95,7 +95,9 @@ BOOL LoadSubAgent(char *szModuleName)
                for(i = 0; i < pInfo->dwNumParameters; i++)
                   AddParameter(pInfo->pParamList[i].szName, 
                                pInfo->pParamList[i].fpHandler,
-                               pInfo->pParamList[i].pArg);
+                               pInfo->pParamList[i].pArg,
+                               pInfo->pParamList[i].iDataType,
+                               pInfo->pParamList[i].szDescription);
 
                // Add enums provided by this subagent to common list
                for(i = 0; i < pInfo->dwNumEnums; i++)
index 172ced2..d57165c 100644 (file)
@@ -125,7 +125,8 @@ WINPERF_COUNTER *AddCounter(TCHAR *pszName, int iClass, int iNumSamples, int iDa
 
 //
 // Add custom counter from configuration file
-// Should be in form <parameter name>:<counter path>:<number of samples>:<class>
+// Should be in form 
+// <parameter name>:<counter path>:<number of samples>:<class>:<data type>:<description>
 // Class can be A (poll every second), B (poll every 5 seconds) or C (poll every 30 seconds)
 //
 
@@ -133,7 +134,8 @@ BOOL AddCounterFromConfig(TCHAR *pszStr)
 {
    TCHAR *ptr, *eptr, *pszCurrField;
    TCHAR szParamName[MAX_PARAM_NAME], szCounterPath[MAX_PATH];
-   int iState, iField, iNumSamples, iClass, iPos;
+   TCHAR szDescription[MAX_DB_STRING] = _T("");
+   int iState, iField, iNumSamples, iClass, iPos, iDataType = DCI_DT_INT;
    WINPERF_COUNTER *pCnt;
 
    // Parse line
@@ -173,6 +175,14 @@ BOOL AddCounterFromConfig(TCHAR *pszStr)
                         if ((iClass < 0) || (iClass > 2))
                            iState = 255;  // Error
                         break;
+                     case 4:  // Data type
+                        iDataType = NxDCIDataTypeFromText(pszCurrField);
+                        if (iDataType == -1)    // Invalid data type specified
+                           iState = 255;
+                        break;
+                     case 5:  // Description
+                        _tcsncpy(szDescription, pszCurrField, MAX_DB_STRING);
+                        break;
                      default:
                         iState = 255;  // Error
                         break;
@@ -222,14 +232,15 @@ BOOL AddCounterFromConfig(TCHAR *pszStr)
    free(pszCurrField);
 
    // Add new counter if parsing was successful
-   if ((iState == -1) && (iField == 4))
+   if ((iState == -1) && (iField >= 4) && (iField <= 6))
    {
       pCnt = AddCounter(szCounterPath, iClass, iNumSamples, COUNTER_TYPE_AUTO);
       if (pCnt != NULL)
-         AddParameter(szParamName, H_CollectedCounterData, (TCHAR *)pCnt);
+         AddParameter(szParamName, H_CollectedCounterData, (TCHAR *)pCnt,
+                      iDataType, szDescription);
    }
 
-   return ((iState == -1) && (iField == 4));
+   return ((iState == -1) && (iField >= 4) && (iField <= 6));
 }
 
 
index dc12987..55b086a 100644 (file)
@@ -54,15 +54,23 @@ static struct
    int iClass;
    int iNumSamples;
    int iDataType;
+   TCHAR *pszDescription;
+   int iDCIDataType;
 } m_counterList[] =
 {
-   { _T("System.CPU.LoadAvg"), _T("\\System\\Processor Queue Length"), 0, 60, COUNTER_TYPE_FLOAT },
-   { _T("System.CPU.LoadAvg5"), _T("\\System\\Processor Queue Length"), 0, 300, COUNTER_TYPE_FLOAT },
-   { _T("System.CPU.LoadAvg15"), _T("\\System\\Processor Queue Length"), 0, 900, COUNTER_TYPE_FLOAT },
-   { _T("System.CPU.Usage"), _T("\\Processor(_Total)\\% Processor Time"), 0, 60, COUNTER_TYPE_INT32 },
-   { _T("System.CPU.Usage5"), _T("\\Processor(_Total)\\% Processor Time"), 0, 300, COUNTER_TYPE_INT32 },
-   { _T("System.CPU.Usage15"), _T("\\Processor(_Total)\\% Processor Time"), 0, 900, COUNTER_TYPE_INT32 },
-   { NULL, NULL, 0, 0, 0 }
+   { _T("System.CPU.LoadAvg"), _T("\\System\\Processor Queue Length"), 0,
+     60, COUNTER_TYPE_FLOAT, _T("Average CPU load for last minute"), DCI_DT_FLOAT },
+   { _T("System.CPU.LoadAvg5"), _T("\\System\\Processor Queue Length"), 0,
+     300, COUNTER_TYPE_FLOAT, _T("Average CPU load for last 5 minutes"), DCI_DT_FLOAT },
+   { _T("System.CPU.LoadAvg15"), _T("\\System\\Processor Queue Length"), 0,
+     900, COUNTER_TYPE_FLOAT, _T("Average CPU load for last 15 minutes"), DCI_DT_FLOAT },
+   { _T("System.CPU.Usage"), _T("\\Processor(_Total)\\% Processor Time"), 0,
+     60, COUNTER_TYPE_INT32, _T("Average CPU utilization for last minute"), DCI_DT_INT },
+   { _T("System.CPU.Usage5"), _T("\\Processor(_Total)\\% Processor Time"), 0,
+     300, COUNTER_TYPE_INT32, _T("Average CPU utilization for last 5 minutes"), DCI_DT_INT },
+   { _T("System.CPU.Usage15"), _T("\\Processor(_Total)\\% Processor Time"), 0,
+     900, COUNTER_TYPE_INT32, _T("Average CPU utilization for last 15 minutes"), DCI_DT_INT },
+   { NULL, NULL, 0, 0, 0, NULL, 0 }
 };
 
 
@@ -293,10 +301,10 @@ static void OnUnload(void)
 
 static NETXMS_SUBAGENT_PARAM m_parameters[] =
 {
-   { _T("PDH.CounterValue(*)"), H_PdhCounterValue, NULL },
-   { _T("PDH.Version"), H_PdhVersion, NULL },
-   { _T("System.ThreadCount"), H_CounterAlias, _T("(\\System\\Threads)") },
-   { _T("System.Uptime"), H_CounterAlias, _T("(\\System\\System Up Time)") }
+   { _T("PDH.CounterValue(*)"), H_PdhCounterValue, NULL, DCI_DT_INT, _T("") },
+   { _T("PDH.Version"), H_PdhVersion, NULL, DCI_DT_UINT, _T("Version of PDH.DLL") },
+   { _T("System.ThreadCount"), H_CounterAlias, _T("(\\System\\Threads)"), DCI_DT_INT, _T("Total number of threads") },
+   { _T("System.Uptime"), H_CounterAlias, _T("(\\System\\System Up Time)"), DCI_DT_UINT, _T("System uptime") }
 };
 static NETXMS_SUBAGENT_ENUM m_enums[] =
 {
@@ -319,7 +327,8 @@ static NETXMS_SUBAGENT_INFO m_info =
 // Add new parameter to list
 //
 
-BOOL AddParameter(TCHAR *pszName, LONG (* fpHandler)(TCHAR *, TCHAR *, TCHAR *), TCHAR *pArg)
+BOOL AddParameter(TCHAR *pszName, LONG (* fpHandler)(TCHAR *, TCHAR *, TCHAR *),
+                  TCHAR *pArg, int iDataType, TCHAR *pszDescription)
 {
    DWORD i;
 
@@ -339,6 +348,8 @@ BOOL AddParameter(TCHAR *pszName, LONG (* fpHandler)(TCHAR *, TCHAR *, TCHAR *),
    _tcsncpy(m_info.pParamList[i].szName, pszName, MAX_PARAM_NAME);
    m_info.pParamList[i].fpHandler = fpHandler;
    m_info.pParamList[i].pArg = pArg;
+   m_info.pParamList[i].iDataType = iDataType;
+   _tcsncpy(m_info.pParamList[i].szDescription, pszDescription, MAX_DB_STRING);
    
    return TRUE;
 }
@@ -358,7 +369,9 @@ static void AddPredefinedCounters(void)
       pCnt = AddCounter(m_counterList[i].pszCounterName, m_counterList[i].iClass,
                         m_counterList[i].iNumSamples, m_counterList[i].iDataType);
       if (pCnt != NULL)
-         AddParameter(m_counterList[i].pszParamName, H_CollectedCounterData, (TCHAR *)pCnt);
+         AddParameter(m_counterList[i].pszParamName, H_CollectedCounterData, 
+                      (TCHAR *)pCnt, m_counterList[i].iDCIDataType, 
+                      m_counterList[i].pszDescription);
    }
 }
 
index c67ae5a..b747d6b 100644 (file)
@@ -92,7 +92,8 @@ TCHAR *GetPdhErrorText(DWORD dwError, TCHAR *pszBuffer, int iBufferSize);
 void ReportPdhError(TCHAR *pszFunction, TCHAR *pszPdhCall, PDH_STATUS dwError);
 WINPERF_COUNTER *AddCounter(TCHAR *pszName, int iClass, int iNumSamples, int iDataType);
 BOOL AddCounterFromConfig(TCHAR *pszStr);
-BOOL AddParameter(TCHAR *pszName, LONG (* fpHandler)(TCHAR *, TCHAR *, TCHAR *), TCHAR *pArg);
+BOOL AddParameter(TCHAR *pszName, LONG (* fpHandler)(TCHAR *, TCHAR *, TCHAR *),
+                  TCHAR *pArg, int iDataType, TCHAR *pszDescription);
 LONG H_CollectedCounterData(TCHAR *pszParam, TCHAR *pArg, TCHAR *pValue);
 
 
index fecd9d4..b64e4bd 100644 (file)
@@ -622,3 +622,21 @@ TCHAR LIBNETXMS_EXPORTABLE *GetCleanFileName(TCHAR *pszFileName)
       ptr--;
    return (ptr + 1);
 }
+
+
+//
+// Translate DCI data type from text form to code
+//
+
+int LIBNETXMS_EXPORTABLE NxDCIDataTypeFromText(TCHAR *pszText)
+{
+   static TCHAR *m_pszValidTypes[] = { _T("INT"), _T("UINT"), _T("INT64"),
+                                       _T("UINT64"), _T("STRING"),
+                                       _T("FLOAT"), NULL };
+   int i;
+
+   for(i = 0; m_pszValidTypes[i] != NULL; i++)
+      if (!_tcsicmp(pszText, m_pszValidTypes[i]))
+         return i;
+   return -1;     // Invalid data type
+}
index 13ef5bc..f0a57d1 100644 (file)
@@ -186,6 +186,7 @@ public:
    DWORD StartUpgrade(TCHAR *pszPkgName);
    DWORD CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType, WORD wPort = 0, 
                              WORD wProto = 0, TCHAR *pszRequest = NULL, TCHAR *pszResponce = NULL);
+   DWORD GetSupportedParameters(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList);
 
    DWORD GetNumDataLines(void) { return m_dwNumDataLines; }
    const TCHAR *GetDataLine(DWORD dwIndex) { return dwIndex < m_dwNumDataLines ? m_ppDataLines[dwIndex] : _T("(error)"); }
index c41b9a1..da0ef2f 100644 (file)
@@ -827,3 +827,57 @@ DWORD AgentConnection::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int
 
    return dwResult;
 }
+
+
+//
+// Get list of supported parameters from subagent
+//
+
+DWORD AgentConnection::GetSupportedParameters(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
+{
+   DWORD i, dwId, dwRqId, dwResult;
+   CSCPMessage msg, *pResponce;
+
+   if (!m_bIsConnected)
+      return ERR_NOT_CONNECTED;
+
+   *pdwNumParams = 0;
+   *ppParamList = NULL;
+
+   dwRqId = m_dwRequestId++;
+
+   msg.SetCode(CMD_GET_PARAMETER_LIST);
+   msg.SetId(dwRqId);
+
+   if (SendMessage(&msg))
+   {
+      // Wait up to 90 seconds for results
+      pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
+      if (pResponce != NULL)
+      {
+         dwResult = pResponce->GetVariableLong(VID_RCC);
+         if (dwResult == ERR_SUCCESS)
+         {
+            *pdwNumParams = pResponce->GetVariableLong(VID_NUM_PARAMETERS);
+            *ppParamList = (NXC_AGENT_PARAM *)malloc(sizeof(NXC_AGENT_PARAM) * *pdwNumParams);
+            for(i = 0, dwId = VID_PARAM_LIST_BASE; i < *pdwNumParams; i++)
+            {
+               pResponce->GetVariableStr(dwId++, (*ppParamList)[i].szName, MAX_PARAM_NAME);
+               pResponce->GetVariableStr(dwId++, (*ppParamList)[i].szDescription, MAX_DB_STRING);
+               (*ppParamList)[i].iDataType = (int)pResponce->GetVariableShort(dwId++);
+            }
+         }
+         delete pResponce;
+      }
+      else
+      {
+         dwResult = ERR_REQUEST_TIMEOUT;
+      }
+   }
+   else
+   {
+      dwResult = ERR_CONNECTION_BROKEN;
+   }
+
+   return dwResult;
+}
index 6c564b7..ea0b797 100644 (file)
@@ -40,6 +40,7 @@
 #define CMD_GET            0
 #define CMD_LIST           1
 #define CMD_CHECK_SERVICE  2
+#define CMD_GET_PARAMS     3
 
 
 //
@@ -122,6 +123,35 @@ static int CheckService(AgentConnection *pConn, int iServiceType, DWORD dwServic
 }
 
 
+//
+// List supported parameters
+//
+
+static int ListParameters(AgentConnection *pConn)
+{
+   DWORD i, dwNumParams, dwError;
+   NXC_AGENT_PARAM *pParamList;
+   static char *pszDataType[] = { "INT", "UINT", "INT64", "UINT64", "STRING", "FLOAT", "UNKNOWN" };
+
+   dwError = pConn->GetSupportedParameters(&dwNumParams, &pParamList);
+   if (dwError == ERR_SUCCESS)
+   {
+      for(i = 0; i < dwNumParams; i++)
+      {
+         printf("%s %s \"%s\"\n", pParamList[i].szName,
+            pszDataType[(pParamList[i].iDataType < 6) && (pParamList[i].iDataType >= 0) ? pParamList[i].iDataType : 6],
+            pParamList[i].szDescription);
+      }
+      safe_free(pParamList);
+   }
+   else
+   {
+      printf("%d: %s\n", dwError, AgentErrorCodeToText(dwError));
+   }
+   return (dwError == ERR_SUCCESS) ? 0 : 1;
+}
+
+
 //
 // Startup
 //
@@ -138,7 +168,7 @@ int main(int argc, char *argv[])
 
    // Parse command line
    opterr = 1;
-   while((ch = getopt(argc, argv, "a:bi:hlnp:P:qr:R:s:S:t:vw:")) != -1)
+   while((ch = getopt(argc, argv, "a:bi:hIlnp:P:qr:R:s:S:t:vw:")) != -1)
    {
       switch(ch)
       {
@@ -150,6 +180,7 @@ int main(int argc, char *argv[])
                    "   -b           : Batch mode - get all parameters listed on command line.\n"
                    "   -h           : Display help and exit.\n"
                    "   -i <seconds> : Get specified parameter(s) continously with given interval.\n"
+                   "   -I           : Get list of supported parameters.\n"
                    "   -l           : Get list of values for enum parameter.\n"
                    "   -n           : Show parameter's name in result.\n"
                    "   -p <port>    : Specify agent's port number. Default is %d.\n"
@@ -196,6 +227,9 @@ int main(int argc, char *argv[])
                iInterval = i;
             }
             break;
+         case 'I':
+            iCommand = CMD_GET_PARAMS;
+            break;
          case 'l':
             iCommand = CMD_LIST;
             break;
@@ -286,7 +320,7 @@ int main(int argc, char *argv[])
    // Check parameter correctness
    if (bStart)
    {
-      if (argc - optind < ((iCommand == CMD_CHECK_SERVICE) ? 1 : 2))
+      if (argc - optind < (((iCommand == CMD_CHECK_SERVICE) || (iCommand == CMD_GET_PARAMS)) ? 1 : 2))
       {
          printf("Required argument(s) missing.\nUse nxget -h to get complete command line syntax.\n");
          bStart = FALSE;
@@ -347,6 +381,9 @@ int main(int argc, char *argv[])
                         iExitCode = CheckService(&conn, iServiceType, dwServiceAddr,
                                                  wServiceProto, wServicePort, szRequest, szResponce);
                         break;
+                     case CMD_GET_PARAMS:
+                        iExitCode = ListParameters(&conn);
+                        break;
                      default:
                         break;
                   }