Instance discovery scripts can return instances as map instance/instance name
authorVictor Kirhenshtein <victor@netxms.org>
Thu, 29 Sep 2016 08:46:32 +0000 (11:46 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Thu, 29 Sep 2016 08:46:32 +0000 (11:46 +0300)
ChangeLog
include/nxsl_classes.h
src/libnxsl/hashmap.cpp
src/server/core/dctarget.cpp
src/server/core/node.cpp
src/server/include/nms_objects.h

index 579053f..6e5d3f6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -26,6 +26,7 @@
 - Added method "getResourceOwner" and attribute "nodes" to NXSL "Cluster" class
 - New object tool type "server script"
 - Number of polls can be set for "diff" type thresholds 
+- Instance discovery scripts can return instances as map instance/instance name
 - New agent metrics for self-monitoring:
        Agent.SyslogProxy.IsEnabled, Agent.SyslogProxy.ReceivedMessages, Agent.SyslogProxy.QueueSize
 - Management console
index 67589bf..859996f 100644 (file)
@@ -225,6 +225,8 @@ public:
    NXSL_Value *getKeys() const;
    NXSL_Value *getValues() const;
 
+   StringMap *toStringMap() const;
+
        int size() const { return m_values->size(); }
 };
 
index ab7fa3d..94f0f66 100644 (file)
@@ -85,3 +85,22 @@ NXSL_Value *NXSL_HashMap::getValues() const
    delete values;
    return new NXSL_Value(array);
 }
+
+/**
+ * Get hash map as string map
+ * Resulting string map is dynamically allocated and should be destroyed by caller
+ */
+StringMap *NXSL_HashMap::toStringMap() const
+{
+   StringMap *map = new StringMap();
+   StructArray<KeyValuePair> *values = m_values->toArray();
+   for(int i = 0; i < values->size(); i++)
+   {
+      KeyValuePair *p = values->get(i);
+      const TCHAR *s = ((NXSL_Value *)p->value)->getValueAsCString();
+      if (s != NULL)
+         map->set(p->key, s);
+   }
+   delete values;
+   return map;
+}
index 286b5f1..979cccb 100644 (file)
@@ -744,6 +744,95 @@ UINT32 DataCollectionTarget::getListFromScript(const TCHAR *param, StringList **
    return rc;
 }
 
+/**
+ * Get string map from library script
+ */
+UINT32 DataCollectionTarget::getStringMapFromScript(const TCHAR *param, StringMap **map)
+{
+   TCHAR name[256];
+   nx_strncpy(name, param, 256);
+   Trim(name);
+
+   ObjectArray<NXSL_Value> args(16, 16, false);
+
+   // Can be in form parameter(arg1, arg2, ... argN)
+   TCHAR *p = _tcschr(name, _T('('));
+   if (p != NULL)
+   {
+      if (name[_tcslen(name) - 1] != _T(')'))
+         return DCE_NOT_SUPPORTED;
+      name[_tcslen(name) - 1] = 0;
+
+      if (!ParseValueList(&p, args))
+      {
+         // argument parsing error
+         args.clear();
+         return DCE_NOT_SUPPORTED;
+      }
+   }
+
+   UINT32 rc = DCE_NOT_SUPPORTED;
+   NXSL_VM *vm = g_pScriptLibrary->createVM(name, new NXSL_ServerEnv);
+   if (vm != NULL)
+   {
+      vm->setGlobalVariable(_T("$object"), createNXSLObject());
+      if (getObjectClass() == OBJECT_NODE)
+      {
+         vm->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, this)));
+      }
+      vm->setGlobalVariable(_T("$isCluster"), new NXSL_Value((getObjectClass() == OBJECT_CLUSTER) ? 1 : 0));
+      if (vm->run(&args))
+      {
+         rc = DCE_SUCCESS;
+         NXSL_Value *value = vm->getResult();
+         if (value->isHashMap())
+         {
+            *map = value->getValueAsHashMap()->toStringMap();
+         }
+         else if (value->isArray())
+         {
+            *map = new StringMap();
+            NXSL_Array *a = value->getValueAsArray();
+            for(int i = 0; i < a->size(); i++)
+            {
+               NXSL_Value *v = a->getByPosition(i);
+               if (v->isString())
+               {
+                  (*map)->set(v->getValueAsCString(), v->getValueAsCString());
+               }
+            }
+         }
+         else if (value->isString())
+         {
+            *map = new StringMap();
+            (*map)->set(value->getValueAsCString(), value->getValueAsCString());
+         }
+         else if (value->isNull())
+         {
+            rc = DCE_COMM_ERROR;
+         }
+         else
+         {
+            *map = new StringMap();
+         }
+      }
+      else
+      {
+         DbgPrintf(4, _T("DataCollectionTarget(%s)->getListFromScript(%s): Script execution error: %s"), m_name, param, vm->getErrorText());
+         PostEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, "ssd", name, vm->getErrorText(), m_id);
+         rc = DCE_COMM_ERROR;
+      }
+      delete vm;
+   }
+   else
+   {
+      args.setOwner(true);
+      DbgPrintf(4, _T("DataCollectionTarget(%s)->getListFromScript(%s): script \"%s\" not found"), m_name, param, name);
+   }
+   DbgPrintf(7, _T("DataCollectionTarget(%s)->getListFromScript(%s): rc=%d"), m_name, param, rc);
+   return rc;
+}
+
 /**
  * Get last (current) DCI values for summary table.
  */
index 107c96e..5b8c740 100644 (file)
@@ -3521,7 +3521,7 @@ StringMap *Node::getInstanceList(DCItem *dci)
                        node->getListFromAgent(dci->getInstanceDiscoveryData(), &instances);
                        break;
       case IDM_SCRIPT:
-         node->getListFromScript(dci->getInstanceDiscoveryData(), &instances);
+         node->getStringMapFromScript(dci->getInstanceDiscoveryData(), &instanceMap);
          break;
                case IDM_SNMP_WALK_VALUES:
                   node->getListFromSNMP(dci->getSnmpPort(), dci->getInstanceDiscoveryData(), &instances);
index a35dc7c..2125f6b 100644 (file)
@@ -1030,6 +1030,7 @@ public:
    virtual UINT32 getEffectiveSourceNode(DCObject *dco);
 
    UINT32 getListFromScript(const TCHAR *param, StringList **list);
+   UINT32 getStringMapFromScript(const TCHAR *param, StringMap **map);
 
    UINT32 getTableLastValues(UINT32 dciId, NXCPMessage *msg);
        UINT32 getThresholdSummary(NXCPMessage *msg, UINT32 baseId);