Fixed function that is checked in libmongo and libvirt. Fixed vmgr chased information...
authorzev <zev@radensolutions.com>
Fri, 22 Jul 2016 12:46:02 +0000 (15:46 +0300)
committerzev <zev@radensolutions.com>
Fri, 22 Jul 2016 12:46:09 +0000 (15:46 +0300)
configure.ac
src/agent/subagents/vmgr/dataproviders.cpp
src/agent/subagents/vmgr/hostconnections.cpp
src/agent/subagents/vmgr/vmgr.cpp
src/agent/subagents/vmgr/vmgr.h

index 6a4c7b8..72dccde 100644 (file)
@@ -2927,7 +2927,7 @@ if test $? = 0; then
        fi
        
        AC_CHECK_HEADER(mongoc.h,,AC_MSG_ERROR([*** Cannot find mongoc.h - check your MongoDB installation ***]))
-       AC_CHECK_LIB(mongoc-1.0, nanosleep, [ MONGODB_LIBS="$MONGODB_LIBS -lmongoc-1.0" ])
+       AC_CHECK_LIB(mongoc-1.0, mongoc_client_get_database, [ MONGODB_LIBS="$MONGODB_LIBS -lmongoc-1.0" ])
        AC_CHECK_LIB(bson-1.0, nanosleep, [ MONGODB_LIBS="$MONGODB_LIBS -lbson-1.0" ])
 
        LIBS="$LIBS $MONGODB_LIBS"
@@ -2960,7 +2960,7 @@ if test $? = 0; then
        fi
        
        AC_CHECK_HEADER(libvirt.h,,AC_MSG_ERROR([*** Cannot find libvirt.h - check your libvirt installation ***]))
-       AC_CHECK_LIB(virt, nanosleep, [ VMGR_LIBS="$VMGR_LIBS -lvirt" ])
+       AC_CHECK_LIB(virt, virConnectGetLibVersion, [ VMGR_LIBS="$VMGR_LIBS -lvirt" ])
        LIBS="$LIBS $VMGR_LIBS"
 
        CPPFLAGS="$OLD_CPPFLAGS"
index 2d63198..fa98389 100644 (file)
@@ -273,25 +273,43 @@ static const TCHAR *vmOpStateDescMapping[] =
    _T("Error caused due to internal failure in libvirt")
 };
 
+struct VMDataStr
+{
+   Table *value;
+   HostConnections *conn;
+};
+
 EnumerationCallbackResult FillVMData(const TCHAR *key, const void *obj, void *userData)
 {
    virDomainPtr vm = (virDomainPtr)obj;
-   Table *value = (Table *)userData;
+   Table *value = ((VMDataStr *)userData)->value;
+   HostConnections *conn = ((VMDataStr *)userData)->conn;
+
+   const char *xml = conn->getDomainDefenitionAndLock(key, vm);
+   Config conf;
+   if(!conf.loadXmlConfigFromMemory(xml, strlen(xml), NULL, "domain", false))
+      AgentWriteLog(2, _T("VMGR.FillVMData(): Not possible to parse VM XML definition"));
+   conn->unlockDomainDefenition();
 
    value->addRow();
    value->set(0, virDomainGetID(vm));
    value->set(1, key);
-   char uuid[VIR_UUID_STRING_BUFLEN];
-   if(virDomainGetUUIDString(vm,uuid) == 0)
-      value->set(2, uuid);
-   else
-      value->set(2, _T(""));
+   value->set(2, conf.getValue(_T("/uuid"), _T("")));
+   String os(conf.getValue(_T("/os/type"), _T("Unkonown")));
+   ConfigEntry *entry = conf.getEntry(_T("/os/type"));
+   if(entry != NULL)
+   {
+      os.append(_T("/"));
+      os.append(entry->getAttribute(_T("arch")));
+   }
+   value->set(4, os.getBuffer());
+
    virDomainInfo info;
    if(virDomainGetInfo(vm, &info) == 0)
    {
       value->set(3, info.state < 8 ? vmStateMapping[info.state] :  _T("Unkonown"));
-      value->set(6, (UINT64)info.maxMem);
-      value->set(7, (UINT64)info.memory);
+      value->set(6, (UINT64)info.maxMem * 1024);
+      value->set(7, (UINT64)info.memory * 1024);
       value->set(8, info.nrVirtCpu);
       value->set(9, info.cpuTime);
    }
@@ -304,15 +322,6 @@ EnumerationCallbackResult FillVMData(const TCHAR *key, const void *obj, void *us
       value->set(9, 0);
    }
 
-   char *osType = virDomainGetOSType(vm);
-   if(osType != NULL)
-   {
-      value->set(4, osType);
-      free(osType);
-   }
-   else
-      value->set(4, _T("Unkonown"));
-
    int autostart;
    if(virDomainGetAutostart(vm, &autostart) == 0)
    {
@@ -380,7 +389,11 @@ LONG H_GetVMTable(const TCHAR *cmd, const TCHAR *arg, Table *value, AbstractComm
        value->addColumn(_T("TIME"), DCI_DT_UINT, _T("Current VM time")); // +DISPLAY NAME AND TYPE
        value->addColumn(_T("IS_PERSISTENT"), DCI_DT_STRING, _T("VM is persistent"));
 
-   domains->forEach(FillVMData, value);
+   VMDataStr data;
+   data.value = value;
+   data.conn = conn;
+
+   domains->forEach(FillVMData, &data);
    conn->unlockDomainList();
    return SYSINFO_RC_SUCCESS;
 }
index 2ed51b3..839f5de 100644 (file)
@@ -23,7 +23,7 @@
 /**
  * Host connection constructor
  */
-HostConnections::HostConnections(const TCHAR *name, const char *url, const char *login, const char *password)
+HostConnections::HostConnections(const TCHAR *name, const char *url, const char *login, const char *password) : m_vmXMLs(true)
 {
    m_name = _tcsdup(name);
    m_url = strdup(url);
@@ -31,6 +31,7 @@ HostConnections::HostConnections(const TCHAR *name, const char *url, const char
    m_password = strdup(password);
    m_domains.setMalloc(false);
    m_iface.setMalloc(false);
+   m_vmXMLMutex = MutexCreate();
 }
 
 /**
@@ -43,6 +44,7 @@ HostConnections::~HostConnections()
    free(m_name);
    free(m_login);
    free(m_password);
+   MutexDestroy(m_vmXMLMutex);
 }
 
 /**
@@ -104,9 +106,9 @@ void HostConnections::disconnect()
  */
 const char *HostConnections::getCapabilitiesAndLock()
 {
+   m_capabilities.lock();
    if(m_capabilities.shouldUpdate())
    {
-      m_capabilities.setWriteLock();
       char *caps = virConnectGetCapabilities(m_connection);
       if (caps == NULL)
       {
@@ -116,11 +118,11 @@ const char *HostConnections::getCapabilitiesAndLock()
          virResetError(&err);
          return NULL;
       }
-      m_capabilities.updateChaseAndUnlock(caps);
+      m_capabilities.update(caps);
       //AgentWriteLog(NXLOG_DEBUG, _T("VMGR: Capabilities of connection %hs: %hs"), m_url, caps);
    }
 
-   return m_capabilities.getDataAndLock();
+   return m_capabilities.getData();
 }
 
 void HostConnections::unlockCapabilities()
@@ -149,9 +151,9 @@ UINT64 HostConnections::getHostFreeMemory()
  */
 const virNodeInfo *HostConnections::getNodeInfoAndLock()
 {
+   m_nodeInfo.lock();
    if(m_nodeInfo.shouldUpdate())
    {
-      m_nodeInfo.setWriteLock();
       virNodeInfo *nodeInfo = (virNodeInfo *) malloc(sizeof(virNodeInfo));
       if (virNodeGetInfo(m_connection, nodeInfo) == -1)
       {
@@ -162,10 +164,10 @@ const virNodeInfo *HostConnections::getNodeInfoAndLock()
          free(nodeInfo);
          return NULL;
       }
-      m_nodeInfo.updateChaseAndUnlock(nodeInfo);
+      m_nodeInfo.update(nodeInfo);
    }
 
-   return m_nodeInfo.getDataAndLock();
+   return m_nodeInfo.getData();
 }
 
 void HostConnections::unlockNodeInfo()
@@ -214,35 +216,103 @@ UINT64 HostConnections::getLibraryVersion()
  */
 const StringObjectMap<virDomain> *HostConnections::getDomainListAndLock()
 {
+   m_domains.lock();
    if(m_domains.shouldUpdate())
    {
-      m_domains.setWriteLock();
-      virDomainPtr *vms;
-      int ret = virConnectListAllDomains(m_connection, &vms, 0);
-      if (ret < 0)
-         return NULL;
+      int numActiveDomains = virConnectNumOfDomains(m_connection);
+      int numInactiveDomains = virConnectNumOfDefinedDomains(m_connection);
+
+      char **inactiveDomains = (char **)malloc(sizeof(char *) * numInactiveDomains);
+      int *activeDomains = (int *)malloc(sizeof(int) * numActiveDomains);
+
+      numActiveDomains = virConnectListDomains(m_connection, activeDomains, numActiveDomains);
+      numInactiveDomains = virConnectListDefinedDomains(m_connection, inactiveDomains, numInactiveDomains);
 
       StringObjectMapC<virDomain> *allDomains = new StringObjectMapC<virDomain>(true);
 
-      for (int i = 0; i < ret; i++)
+      for (int i = 0 ; i < numActiveDomains ; i++)
       {
+         virDomainPtr vm = virDomainLookupByID(m_connection, activeDomains[i]);
 #ifdef UNICODE
-         allDomains->setPreallocated(WideStringFromMBString(virDomainGetName(vms[i])), vms[i]);
+         allDomains->setPreallocated(WideStringFromMBString(virDomainGetName(vm)), vm);
+#else
+         allDomains->set(virDomainGetName(vm), vm);
+#endif
+      }
+
+      for (int i = 0 ; i < numInactiveDomains ; i++)
+      {
+ #ifdef UNICODE
+         allDomains->setPreallocated(WideStringFromMBString(inactiveDomains[i]), virDomainLookupByName(m_connection, inactiveDomains[i]));
+         free(inactiveDomains[i]);
 #else
-         allDomains->set(virDomainGetName(vms[i]), vms[i]);
+         allDomains->setPreallocated(inactiveDomains[i], virDomainLookupByName(m_connection, inactiveDomains[i]));
 #endif
       }
-      free(vms);
-      m_domains.updateChaseAndUnlock(allDomains);
+
+      free(activeDomains);
+      free(inactiveDomains);
+
+      m_domains.update(allDomains);
    }
-   return m_domains.getDataAndLock();
+   return m_domains.getData();
 }
 
+/**
+ * Unlocks domain list
+ */
 void HostConnections::unlockDomainList()
 {
    m_domains.unlock();
 }
 
+/**
+ * Returns domain definition in XML format
+ */
+const char *HostConnections::getDomainDefenitionAndLock(const TCHAR *name, virDomainPtr vm)
+{
+   MutexLock(m_vmXMLMutex);
+   Cashe<char> *xmlChase = m_vmXMLs.get(name);
+   if (xmlChase == NULL || xmlChase->shouldUpdate())
+   {
+      if(vm == NULL)
+      {
+         const StringObjectMap<virDomain> *vmMap = getDomainListAndLock();
+         virDomainPtr vm = vmMap->get(name);
+      }
+      if(vm != NULL)
+      {
+         char *xml = virDomainGetXMLDesc(vm, VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_INACTIVE);
+         if(xmlChase == NULL)
+         {
+            xmlChase = new Cashe<char>();
+            m_vmXMLs.set(name, xmlChase);
+         }
+         xmlChase->update(xml);
+
+      }
+      else
+      {
+         m_vmXMLs.remove(name);
+      }
+   }
+/*
+   if(xmlChase != NULL)
+      AgentWriteLog(6, _T("VMGR: ******Domain defenition: %hs"), xmlChase->getData());
+   else
+      AgentWriteLog(6, _T("VMGR: ******Domain defenition: NULL"));
+*/
+   return xmlChase != NULL ? xmlChase->getData() : NULL;
+}
+
+/**
+ * Unlocks domain definition
+ */
+void HostConnections::unlockDomainDefenition()
+{
+   MutexUnlock(m_vmXMLMutex);
+}
+
 /**---------
  * Iface
  */
@@ -252,10 +322,9 @@ void HostConnections::unlockDomainList()
  */
 const StringList *HostConnections::getIfaceListAndLock()
 {
+   m_iface.lock();
    if(m_iface.shouldUpdate())
    {
-      m_iface.setWriteLock();
-
       int activeCount = virConnectNumOfInterfaces(m_connection);
       int inactiveCount = virConnectNumOfDefinedInterfaces(m_connection);
       StringList *ifaceList = new StringList();
@@ -268,7 +337,7 @@ const StringList *HostConnections::getIfaceListAndLock()
          {
             virInterfacePtr iface = virInterfaceLookupByName(m_connection, active[i]);
             //AgentWriteLog(6, _T("VMGR: iface info!!!: %hs"), virInterfaceGetXMLDesc(iface, 0));
-
+            virInterfaceFree(iface);
             ifaceList->addMBString(active[i]);
             free(active[i]);
          }
@@ -283,15 +352,15 @@ const StringList *HostConnections::getIfaceListAndLock()
          {
             virInterfacePtr iface = virInterfaceLookupByName(m_connection, inactive[i]);
             //AgentWriteLog(6, _T("VMGR: iface info!!!: %hs"), virInterfaceGetXMLDesc(iface, 0));
-
+            virInterfaceFree(iface);
             ifaceList->addMBString(inactive[i]);
             free(inactive[i]);
          }
          free(inactive);
       }
-      m_iface.updateChaseAndUnlock(ifaceList);
+      m_iface.update(ifaceList);
    }
-   return m_iface.getDataAndLock();
+   return m_iface.getData();
 }
 
 void HostConnections::unlockIfaceList()
index 1bff845..410bdea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- ** File management subagent
+ ** Vmgr management subagent
  ** Copyright (C) 2016 Raden Solutions
  **
  ** This program is free software; you can redistribute it and/or modify
@@ -167,7 +167,7 @@ static void SubagentShutdown()
 }
 
 /**
- * Process commands like get files in folder, delete file/folder, copy file/folder, move file/folder
+ * Process commands like VM up/down
  */
 static BOOL ProcessCommands(UINT32 command, NXCPMessage *request, NXCPMessage *response, AbstractCommSession *session)
 {
@@ -233,7 +233,7 @@ static NETXMS_SUBAGENT_INFO m_info =
 /**
  * Entry point for NetXMS agent
  */
-DECLARE_SUBAGENT_ENTRY_POINT(FILEMGR)
+DECLARE_SUBAGENT_ENTRY_POINT(VMGR)
 {
    *ppInfo = &m_info;
    return TRUE;
index 4593422..e5e5d76 100644 (file)
@@ -58,24 +58,35 @@ public:
 /**
  * Data cashing class
  */
-template <class StoredData> class XmlCashe
+template <class StoredData> class Cashe
 {
 private:
    time_t m_lastCollectionTime;
    StoredData *m_data;
-   RWLOCK m_lock;
    bool isMallocAlloc;
 public:
-   XmlCashe() { m_lastCollectionTime = NEVER; m_data = NULL; m_lock = RWLockCreate(); isMallocAlloc = true;}
-   ~XmlCashe() { RWLockDestroy(m_lock); if(isMallocAlloc){ free(m_data); } else { delete(m_data); } }
+   Cashe() { m_lastCollectionTime = NEVER; m_data = NULL; isMallocAlloc = true;}
+   ~Cashe() { if(isMallocAlloc){ free(m_data); } else { delete(m_data); } }
    //XmlCashe(StoredData *data) { m_lastCollectionTime = time(NULL); m_data = data; }
    void setMalloc(bool value) { isMallocAlloc = value; }
-   const StoredData *getDataAndLock() { RWLockReadLock(m_lock, 10000); return m_data; }
+   const StoredData *getData() { return m_data; }
    const time_t getLastCollecitonTime() { return m_lastCollectionTime; }
-   void updateChaseAndUnlock(StoredData* data) { m_lastCollectionTime = time(NULL); if(isMallocAlloc){ free(m_data); } else { delete(m_data); } m_data = data; RWLockUnlock(m_lock); }
+   void update(StoredData* data) { m_lastCollectionTime = time(NULL); if(isMallocAlloc){ free(m_data); } else { delete(m_data); } m_data = data; }
    bool shouldUpdate() { return (time(NULL) - m_lastCollectionTime) > DATA_COLLECTION_CASHE_TIME; }
-   void setWriteLock() { RWLockWriteLock(m_lock, INFINITE); }
-   void unlock() { RWLockUnlock(m_lock); }
+};
+
+/**
+ * Data cashing class
+ */
+template <class StoredData> class CasheAndLock : public Cashe<StoredData>
+{
+private:
+   MUTEX m_mutex;
+public:
+   CasheAndLock() : Cashe<StoredData>() { m_mutex = MutexCreate(); }
+   ~CasheAndLock() { MutexDestroy(m_mutex); }
+   void lock() { MutexLock(m_mutex); }
+   void unlock() { MutexUnlock(m_mutex); }
 };
 
 /**
@@ -90,11 +101,13 @@ private:
    char *m_login;
    char *m_password;
 
-   XmlCashe<char> m_capabilities;
-   XmlCashe<virNodeInfo> m_nodeInfo;
-   XmlCashe<StringObjectMap<virDomain> > m_domains;
-   XmlCashe<StringList> m_iface;
+   CasheAndLock<char> m_capabilities;
+   CasheAndLock<virNodeInfo> m_nodeInfo;
+   CasheAndLock<StringObjectMap<virDomain> > m_domains;
+   CasheAndLock<StringList> m_iface;
    //XmlCashe m_storages;
+   MUTEX m_vmXMLMutex;
+   StringObjectMap<Cashe<char> > m_vmXMLs;
 
    static int authCb(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata);
 
@@ -108,8 +121,12 @@ public:
    void unlockCapabilities();
    const virNodeInfo *getNodeInfoAndLock();
    void unlockNodeInfo();
+   //Domains
    const StringObjectMap<virDomain> *getDomainListAndLock();
    void unlockDomainList();
+   const char *getDomainDefenitionAndLock(const TCHAR *name, virDomainPtr vm = NULL);
+   void unlockDomainDefenition();
+   //Iface
    const StringList *getIfaceListAndLock();
    void unlockIfaceList();
    //void getStorages();