/*############################################################################## Copyright (C) 2011 HPCC Systems. All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . ############################################################################## */ #include #include "ws_machineService.hpp" #include "jarray.hpp" #include "jmisc.hpp" #include "jutil.hpp" #include "thirdparty.h" #include "dadfs.hpp" #include "ws_topology.hpp" #include "rmtfile.hpp" #include "exception_util.hpp" #ifndef eqHoleCluster #define eqHoleCluster "HoleCluster" #endif #ifndef eqThorCluster #define eqThorCluster "ThorCluster" #endif #ifndef eqRoxieCluster #define eqRoxieCluster "RoxieCluster" #endif #ifndef eqEclCCServer #define eqEclCCServer "EclCCServerProcess" #endif #ifndef eqEclAgent #define eqEclAgent "EclAgentProcess" #endif #ifndef eqEclScheduler #define eqEclScheduler "EclSchedulerProcess" #endif #ifndef eqThorMasterProcess #define eqThorMasterProcess "ThorMasterProcess" #endif #ifndef eqThorSlaveProcess #define eqThorSlaveProcess "ThorSlaveProcess" #endif #ifndef eqThorSpareProcess #define eqThorSpareProcess "ThorSpareProcess" #endif #ifndef eqHOLEMACHINES #define eqHOLEMACHINES "HOLEMACHINES" #endif #ifndef eqROXIEMACHINES #define eqROXIEMACHINES "ROXIEMACHINES" #endif #ifndef eqMACHINES #define eqMACHINES "MACHINES" #endif static const int THREAD_POOL_SIZE = 40; static const int THREAD_POOL_STACK_SIZE = 64000; static const char* FEATURE_URL = "MachineInfoAccess"; //--------------------------------------------------------------------------------------------- //NOTE: PART I of implementation for Cws_machineEx // PART II and III are in ws_machineServiceMetrics.cpp and ws_machineServiceRexec.cpp resp. //--------------------------------------------------------------------------------------------- class CMachineInfoThreadParam : public CWsMachineThreadParam { public: IMPLEMENT_IINTERFACE; IEspContext& m_context; StringBuffer m_sProcessType; StringBuffer m_sCompName; StringBuffer m_sConfigAddress; StringBuffer m_sUserId; StringBuffer m_sPassword; StringBuffer m_sPath; unsigned m_processNumber; bool m_bECLAgent; bool m_bGetProcessorInfo; bool m_bGetStorageInfo; bool m_bGetSwInfo; bool m_bFilterProcesses; bool m_bMonitorDaliFileServer; bool m_bMultipleInstances; Cws_machineEx::OpSysType m_operatingSystem; Linked m_pMachineInfo; Linked m_pMachineInfo1; set& m_columnSet; StringArray& m_columnArray; const StringArray& m_additionalProcesses; CMachineInfoThreadParam( const char* pszAddress, const char* pszProcessType, const char* pszCompName, const char* pszUserId, const char* pszPassword, const char* pszPath, unsigned processNumber, set& columnSet, StringArray& columnArray, bool bGetProcessorInfo, bool bGetStorageInfo, bool bGetSwInfo, bool bFilterProcesses, bool bMonitorDaliFileServer, Cws_machineEx::OpSysType os, const StringArray& additionalProcesses, IEspMachineInfoEx* pMachineInfo, Cws_machineEx* pService, IEspContext& context, const char* pszConfigAddress) : CWsMachineThreadParam(pszAddress, pszUserId, pszPassword, pService), m_columnSet(columnSet), m_columnArray(columnArray), m_operatingSystem(os), m_context(context), m_additionalProcesses(additionalProcesses) { m_bECLAgent = false; m_sUserId = pszUserId; m_sPassword = pszPassword; m_sPath = pszPath; m_bFilterProcesses = bFilterProcesses; m_bMonitorDaliFileServer = bMonitorDaliFileServer; m_sProcessType = pszProcessType; m_sCompName = pszCompName; m_sConfigAddress = pszConfigAddress, m_bGetProcessorInfo= bGetProcessorInfo; m_bGetStorageInfo = bGetStorageInfo; m_bGetSwInfo = bGetSwInfo; m_pMachineInfo.set( pMachineInfo ); m_bMultipleInstances = false; m_processNumber = processNumber; } CMachineInfoThreadParam( const char* pszAddress, const char* pszProcessType, const char* pszCompName, const char* pszUserId, const char* pszPassword, const char* pszPath, unsigned processNumber, set& columnSet, StringArray& columnArray, bool bGetProcessorInfo, bool bGetStorageInfo, bool bGetSwInfo, bool bFilterProcesses, bool bMonitorDaliFileServer, Cws_machineEx::OpSysType os, const StringArray& additionalProcesses, IEspMachineInfoEx* pMachineInfo, IEspMachineInfoEx* pMachineInfo1, Cws_machineEx* pService, IEspContext& context, const char* pszConfigAddress) : CWsMachineThreadParam(pszAddress, pszUserId, pszPassword, pService), m_columnSet(columnSet), m_columnArray(columnArray), m_operatingSystem(os), m_context(context), m_additionalProcesses(additionalProcesses) { m_sUserId = pszUserId; m_sPassword = pszPassword; m_sPath = pszPath; m_bFilterProcesses = bFilterProcesses; m_bMonitorDaliFileServer = bMonitorDaliFileServer; m_sProcessType = pszProcessType; m_sCompName = pszCompName; m_sConfigAddress = pszConfigAddress, m_bGetProcessorInfo= bGetProcessorInfo; m_bGetStorageInfo = bGetStorageInfo; m_bGetSwInfo = bGetSwInfo; m_pMachineInfo.set( pMachineInfo ); m_pMachineInfo1.set( pMachineInfo1 ); m_bECLAgent = true; m_bMultipleInstances = false; m_processNumber = processNumber; } virtual void doWork() { m_pService->doGetMachineInfo(m_context, this); } void addColumn(const char* columnName) { synchronized block(s_mutex); if (m_columnSet.find(columnName) == m_columnSet.end()) { m_columnSet.insert(columnName); m_columnArray.append(columnName); } } private: static Mutex s_mutex; }; /*static*/Mutex CMachineInfoThreadParam::s_mutex; //--------------------------------------------------------------------------------------------- /*static*/map Cws_machineEx::s_processTypeToSnmpIdMap; /*static*/map Cws_machineEx::s_oid2CompTypeMap; void Cws_machineEx::init(IPropertyTree *cfg, const char *process, const char *service) { StringBuffer xpath; xpath.appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]", process, service); Owned pServiceNode = cfg->getPropTree(xpath.str()); m_bMonitorDaliFileServer = pServiceNode->getPropBool("@monitorDaliFileServer", false); m_processFilters.setown( pServiceNode->getPropTree("ProcessFilters") ); const char* pchExcludePartitions = pServiceNode->queryProp("@excludePartitions"); if (pchExcludePartitions && *pchExcludePartitions) { StringArray sPartitions; DelimToStringArray(pchExcludePartitions, sPartitions, ", ;"); unsigned int nPartitions = sPartitions.ordinality(); for (unsigned int i=0; i pProcessNode = cfg->getPropTree(xpath.str()); m_useDefaultHPCCInit = pProcessNode->getPropBool("UseDefaultHPCCInit", true); const char* machineInfoPath = pProcessNode->queryProp("MachineInfoFile"); if (machineInfoPath && *machineInfoPath) { m_machineInfoFile.append(machineInfoPath); } else { m_machineInfoFile.append("preflight"); } Owned constEnv = getConstEnvironment(); Owned pRoot = &constEnv->getPTree(); IPropertyTree* pEnvSettings = pRoot->getPropTree("EnvSettings"); if (pEnvSettings) { pEnvSettings->getProp("configs", environmentConfData.m_configsPath.clear()); pEnvSettings->getProp("path", environmentConfData.m_executionPath.clear()); pEnvSettings->getProp("runtime", environmentConfData.m_runtimePath.clear()); pEnvSettings->getProp("lock", environmentConfData.m_lockPath.clear()); pEnvSettings->getProp("pid", environmentConfData.m_pidPath.clear()); pEnvSettings->getProp("user", environmentConfData.m_user.clear()); } IThreadFactory* pThreadFactory = new CWsMachineThreadFactory(); m_threadPool.setown(createThreadPool("WsMachine Thread Pool", pThreadFactory, NULL, THREAD_POOL_SIZE, 10000, THREAD_POOL_STACK_SIZE)); //10 sec timeout for available thread; use stack size of 2MB pThreadFactory->Release(); //populate the process type to SNMP component index map if (s_processTypeToSnmpIdMap.empty()) { //add mappings in random order to keep the map balanced //don't add Hole and Thor since they have numerous sub-types and are better //handled as special cases s_processTypeToSnmpIdMap.insert(pair("ThorMasterProcess", 3)); s_processTypeToSnmpIdMap.insert(pair("EclServerProcess", 4)); s_processTypeToSnmpIdMap.insert(pair("DaliServerProcess", 7)); s_processTypeToSnmpIdMap.insert(pair("RoxieServerProcess", 16)); s_processTypeToSnmpIdMap.insert(pair("DfuServerProcess", 18)); s_processTypeToSnmpIdMap.insert(pair("SashaServerProcess", 20)); s_processTypeToSnmpIdMap.insert(pair("EspProcess", 100)); } if (s_processTypeToProcessMap.empty()) { s_processTypeToProcessMap.insert(pair("DaliServerProcess", "daserver")); s_processTypeToProcessMap.insert(pair("DfuServerProcess", "dfuserver")); s_processTypeToProcessMap.insert(pair("EclServerProcess", "eclserver")); s_processTypeToProcessMap.insert(pair("FTSlaveProcess", "ftslave")); s_processTypeToProcessMap.insert(pair("SashaServerProcess", "saserver")); s_processTypeToProcessMap.insert(pair("ThorMasterProcess", "thormaster")); s_processTypeToProcessMap.insert(pair("RoxieServerProcess", "roxie")); } } Cws_machineEx::~Cws_machineEx() { } IConstEnvironment* Cws_machineEx::getConstEnvironment() { Owned envFactory = getEnvironmentFactory(); Owned constEnv = envFactory->openEnvironmentByFile(); return constEnv.getLink(); } const char* Cws_machineEx::getEnvironmentConf(const char* confFileName) { if (!confFileName || !*confFileName) return NULL; StringBuffer environmentConf; IFile * pFile = createIFile(confFileName); if (pFile->exists( )) { Owned pFileIO = pFile->openShared(IFOread, IFSHfull); if (pFileIO) { StringBuffer tmpBuf; offset_t fileSize = pFile->size(); tmpBuf.ensureCapacity((unsigned)fileSize); tmpBuf.setLength((unsigned)fileSize); size32_t nRead = pFileIO->read(0, (size32_t) fileSize, (char*)tmpBuf.str()); if (nRead == fileSize) { environmentConf = tmpBuf; } } } return environmentConf.str(); } bool Cws_machineEx::onGetMachineInfo(IEspContext &context, IEspGetMachineInfoRequest & req, IEspGetMachineInfoResponse & resp) { #ifdef DETECT_WS_MC_MEM_LEAKS static bool firstTime = true; if (firstTime) { firstTime = false; unsigned t = setAllocHook(true); } #endif //DETECT_WS_MC_MEM_LEAKS try { if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false)) throw MakeStringException(ECLWATCH_MACHINE_INFO_ACCESS_DENIED, "Failed to Get Machine Information. Permission denied."); StringBuffer user; StringBuffer pw; context.getUserID(user); context.getPassword(pw); IEspRequestInfoStruct& reqInfo = resp.updateRequestInfo(); reqInfo.setSecurityString(req.getSecurityString()); reqInfo.setSortBy(req.getSortBy()); reqInfo.setGetProcessorInfo(req.getGetProcessorInfo()); reqInfo.setGetStorageInfo(req.getGetStorageInfo()); reqInfo.setGetSoftwareInfo(req.getGetSoftwareInfo()); reqInfo.setSortBy("Address"); reqInfo.setAutoRefresh( req.getAutoRefresh() ); reqInfo.setMemThreshold(req.getMemThreshold()); reqInfo.setDiskThreshold(req.getDiskThreshold()); reqInfo.setCpuThreshold(req.getCpuThreshold()); reqInfo.setMemThresholdType(req.getMemThresholdType()); reqInfo.setDiskThresholdType(req.getDiskThresholdType()); reqInfo.setApplyProcessFilter( req.getApplyProcessFilter() ); reqInfo.setClusterType( req.getClusterType() ); reqInfo.setCluster( req.getCluster() ); reqInfo.setAddProcessesToFilter( req.getAddProcessesToFilter() ); reqInfo.setOldIP( req.getOldIP() ); reqInfo.setPath( req.getPath() ); IArrayOf machineArray; StringArray columnArray; const char* userName = m_sTestStr1.str(); const char* password = m_sTestStr2.str(); if (userName && *userName) { reqInfo.setUserName(userName); resp.setUserName(userName); } else { reqInfo.setUserName(user.str()); } if (password && *password) { reqInfo.setPassword(password); resp.setPassword(password); } else { reqInfo.setPassword(pw.str()); } RunMachineQuery(context, req.getAddresses(),reqInfo,machineArray,columnArray); resp.setColumns( columnArray ); resp.setMachines(machineArray); char timeStamp[32]; getTimeStamp(timeStamp); resp.setTimeStamp( timeStamp ); } catch(IException* e) { FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR); } #ifdef DETECT_WS_MC_MEM_LEAKS DBGLOG("Allocated=%d", setAllocHook(false)); #endif //DETECT_WS_MC_MEM_LEAKS return true; } bool Cws_machineEx::onGetMachineInfoEx(IEspContext &context, IEspGetMachineInfoRequestEx & req, IEspGetMachineInfoResponseEx & resp) { try { if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false)) throw MakeStringException(ECLWATCH_MACHINE_INFO_ACCESS_DENIED, "Failed to Get Machine Information. Permission denied."); StringBuffer user; StringBuffer pw; context.getUserID(user); context.getPassword(pw); Owned reqInfo = new CRequestInfoStruct("",""); reqInfo->setGetProcessorInfo(true); reqInfo->setGetStorageInfo(true); reqInfo->setGetSoftwareInfo(true); reqInfo->setUserName(user.str()); reqInfo->setPassword(pw.str()); reqInfo->setSortBy("Address"); reqInfo->setClusterType( req.getClusterType() ); IArrayOf machineArray; StringArray columnArray; RunMachineQuery(context, req.getAddresses(),*reqInfo,machineArray,columnArray); resp.setMachines(machineArray); } catch(IException* e) { FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR); } return true; } void Cws_machineEx::RunMachineQuery(IEspContext &context, StringArray &addresses,IEspRequestInfoStruct& reqInfo, IArrayOf& machineArray, StringArray& columnArray) { bool bMonitorDaliFileServer = m_bMonitorDaliFileServer; bool bFilterProcesses = reqInfo.getApplyProcessFilter(); int ordinality= addresses.ordinality(); int index = 0; if (!ordinality) return; StringArray additionalProcesses; if (bFilterProcesses) { const char* xpath = reqInfo.getPath(); if (xpath && *xpath) { StringBuffer decodedPath; JBASE64_Decode(xpath, decodedPath); try { //xpath is the Path to parent node (normally a cluster) Owned envFactory = getEnvironmentFactory(); Owned constEnv = envFactory->openEnvironmentByFile(); Owned root0 = &constEnv->getPTree(); if (!root0) throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information."); char* xpath = (char*)decodedPath.str(); if (!strnicmp(xpath, "/Environment/", 13)) xpath += 13; IPropertyTree* root = root0->queryPropTree( xpath ); if (!root) throw MakeStringException(ECLWATCH_INVALID_INPUT, "Specified path '%s' is invalid!", decodedPath.str()); bMonitorDaliFileServer = root->getPropBool("@monitorDaliFileServer", false); } catch(IException* e) { StringBuffer msg; e->errorMessage(msg); WARNLOG("%s", msg.str()); e->Release(); } catch(...) { WARNLOG("Unknown Exception caught within Cws_machineEx::RunMachineQuery"); } } DelimToStringArray(reqInfo.getAddProcessesToFilter(), additionalProcesses, " ,\t"); int len = additionalProcesses.length(); for (int i=0; i AddressMap; AddressMap addressMap; //maps to ::: UnsignedArray threadHandles; set columnSet; IpAddress ipAddr; for (index=0; index(numAddr, sBuf.str())); } ipAddr.ipincrement(1); } free(address); } AddressMap::const_iterator iBeginAddr = addressMap.begin(); AddressMap::const_iterator iEndAddr = addressMap.end(); for (AddressMap::const_iterator iAddr = iBeginAddr; iAddr != iEndAddr; iAddr++) { IpAddress ipAddr; unsigned numAddr = (*iAddr).first; // TBD IPv6 ipAddr.setNetAddress(sizeof(numAddr),&numAddr); StringBuffer address; ipAddr.getIpText(address); StringBuffer sProcessType; StringBuffer sCompName; OpSysType os = OS_Windows; StringBuffer sPath; unsigned processNumber = 0; const char *configAddress = (*iAddr).second.c_str(); char* props = (char*) strchr(configAddress, ':'); if (props) *props++ = '\0'; else props = (char*) configAddress; if (props) parseProperties( props, sProcessType, sCompName, os, sPath, processNumber); else bFilterProcesses = false; //OS is constant for a m/c so can be ignored if IP is already recorded if (*address.str()) { bool bAgentExec = stricmp(sProcessType.str(), "EclAgentProcess")==0; Owned pMachineInfo = static_cast(new CMachineInfoEx("")); pMachineInfo->setOS( os ); if (!bAgentExec) { machineArray.append(*pMachineInfo.getLink()); CMachineInfoThreadParam* pThreadReq = new CMachineInfoThreadParam( address.str(), sProcessType.str(), sCompName.str(), reqInfo.getUserName(), reqInfo.getPassword(), sPath.str(), processNumber, columnSet, columnArray, reqInfo.getGetProcessorInfo(), reqInfo.getGetStorageInfo(), reqInfo.getGetSoftwareInfo(), bFilterProcesses, bMonitorDaliFileServer, os, additionalProcesses, pMachineInfo, this, context, configAddress); PooledThreadHandle handle = m_threadPool->start( pThreadReq ); threadHandles.append(handle); } else { Owned pMachineInfo1 = static_cast(new CMachineInfoEx("")); pMachineInfo1->setOS( os ); machineArray.append(*pMachineInfo1.getLink()); CMachineInfoThreadParam* pThreadReq = new CMachineInfoThreadParam( address.str(), sProcessType.str(), sCompName.str(), reqInfo.getUserName(), reqInfo.getPassword(), sPath.str(), processNumber, columnSet, columnArray, reqInfo.getGetProcessorInfo(), reqInfo.getGetStorageInfo(), reqInfo.getGetSoftwareInfo(), bFilterProcesses, bMonitorDaliFileServer, os, additionalProcesses, pMachineInfo, pMachineInfo1, this, context, configAddress); PooledThreadHandle handle = m_threadPool->start( pThreadReq ); threadHandles.append(handle); } } } //block for worker theads to finish, if necessary and then collect results PooledThreadHandle* pThreadHandle = threadHandles.getArray(); unsigned i=threadHandles.ordinality(); while (i--) { m_threadPool->join(*pThreadHandle); pThreadHandle++; } } // the following method is invoked on worker threads of void Cws_machineEx::getUpTime(CMachineInfoThreadParam* pParam, StringBuffer& out) { if (pParam->m_sAddress.length() < 1) return; SocketEndpoint ep(pParam->m_sAddress.str()); MemoryBuffer outbuf; int ret = remoteExec(ep,"/bin/cat /proc/uptime",NULL,true,0,NULL,&outbuf); if (ret != 0) return; outbuf.append((byte)0); const char *pStr = outbuf.toByteArray(); if (!pStr) return; char *pStr0 = (char *) strchr(pStr, ' '); if (!pStr0) return; pStr0[0] = 0; int days = 0, hours = 0, min = 0; double seconds = 0.0; double dSec = atof(pStr); if (dSec > 24*3600) { days = (int) dSec/(24*3600); } hours = (int) (dSec/3600 - days * 24); min = (int) (dSec/60 - (days * 24 + hours) * 60); seconds = (int) (dSec - (days * 24 * 3600 + hours * 3600 + min * 60)); if (days > 0) out.appendf("%d days, %d:%d:%2.2f", days, hours, min, seconds); else out.appendf("%d:%d:%2.2f", hours, min, seconds); return; } void Cws_machineEx::readAString(const char *orig, const char *begin, const char *end, StringBuffer& strReturn, bool bTrim) { char* pStr = (char*) strstr(orig, begin); if (pStr) { pStr += strlen(begin); if (pStr) { char buf[1024]; char* pStr1 = (char*) strchr(pStr, 0x0a); if (pStr1) { strncpy(buf, pStr, pStr1 - pStr); buf[pStr1 - pStr] = 0; } else strcpy(buf, pStr); strReturn.append(buf); if (bTrim) strReturn.trim(); } } } void Cws_machineEx::readTwoStrings(const char *orig, const char *begin, const char *middle, const char *end, StringBuffer& strReturn1, StringBuffer& strReturn2, bool bTrim) { char* pStr = (char*) strstr(orig, begin); if (pStr) { pStr += strlen(begin); if (pStr) { char buf[1024]; char* pStr1 = (char*) strchr(pStr, 0x0a); if (pStr1) { strncpy(buf, pStr, pStr1 - pStr); buf[pStr1 - pStr] = 0; } else strcpy(buf, pStr); strReturn1.append(buf); if (bTrim) strReturn1.trim(); if (strReturn1.length() > 0) { pStr = (char*) strReturn1.str(); if (pStr) { char* pStr1 = (char*) strstr(pStr, middle); if (pStr1) { int len0 = strReturn1.length(); int len1 = pStr1 - pStr; int len2 = len0 - strlen(middle) - len1; strReturn2.append(strReturn1); strReturn1.remove(len1, len0-len1); strReturn2.remove(0, len0-len2); } } } } } } void Cws_machineEx::readSpace(const char *line, char* title, __int64& free, __int64& total, int& percentAvail) { if (!line) return; __int64 used = 0; char free0[1024], used0[1024]; char* pStr = (char*) line; char* pStr1 = (char*) strchr(pStr, ':'); if (!pStr1) return; strncpy(title, pStr, pStr1 - pStr); title[pStr1 - pStr] = 0; pStr = pStr1 + 2; pStr1 = (char*) strchr(pStr, ' '); if (!pStr1) return; strncpy(used0, pStr, pStr1 - pStr); used0[pStr1 - pStr] = 0; pStr = pStr1 + 1; if (!pStr) return; strcpy(free0, pStr); __int64 factor1 = 1; if (strlen(free0) > 9) { free0[strlen(free0) - 6] = 0; factor1 = 1000000; } free = atol(free0)*factor1; __int64 factor2 = 1; if (strlen(used0) > 9) { used0[strlen(used0) - 6] = 0; factor2 = 1000000; } used = atol(used0)*factor2; total = free + used; if (total > 0) percentAvail = (int) ((free*100)/total); free = (__int64) free /1000; //MByte total = (__int64) total /1000; //MByte return; } int Cws_machineEx::readMachineInfo(const char *response, CMachineInfo& machineInfo) { if (!response || !*response) return -1; StringBuffer computerUptime; readAString(response, "ProcessUpTime:", "\r", machineInfo.m_sProcessUptime, true); if (machineInfo.m_sProcessUptime.length() > 0) readAString(response, "ProcessID:", "\r", machineInfo.m_sID, true); readAString(response, "CPU-Idle:", "\r", machineInfo.m_sCPUIdle, true); readAString(response, "ComputerUpTime:", "\r", computerUptime, true); const char* spaceLine = "---SpaceUsedAndFree---"; char* pStr = (char*) strstr(response, spaceLine); if (pStr) { pStr += strlen(spaceLine)+1; if (pStr) machineInfo.m_sSpace.append(pStr); } if (computerUptime.length() > 0) { machineInfo.m_sComputerUptime = computerUptime; char* pStr = (char*) computerUptime.str(); char* ppStr = strchr(pStr, ' '); if (ppStr) { ppStr++; ppStr = strchr(ppStr, ' '); if (ppStr) { ppStr++; if (ppStr) machineInfo.m_sComputerUptime.clear().append(ppStr); } } } return 0; } int Cws_machineEx::runCommand(IEspContext& context, const char* sAddress, const char* sConfigAddress, const char* sCommand, const char* sUserId, const char* sPassword, StringBuffer& sResponse) { int iRet = 0; try { StringBuffer command(sCommand); StringBuffer cmdLine; StringBuffer userId; StringBuffer password; bool bLinux; int exitCode = -1; if (sConfigAddress && *sConfigAddress) getAccountAndPlatformInfo(sConfigAddress, userId, password, bLinux); else getAccountAndPlatformInfo(sAddress, userId, password, bLinux); if (!sUserId || !*sUserId || !sPassword ||!*sPassword) { //BUG: 9825 - remote execution on linux needs to use individual accounts //use userid/password in ESP context for remote execution... if (bLinux) { userId.clear(); password.clear(); context.getUserID(userId); context.getPassword(password); } } else { userId.clear().append(sUserId); password.clear().append(sPassword); } #ifdef _WIN32 #ifndef CHECK_LINUX_COMMAND #define popen _popen #define pclose _pclose // Use psexec as default remote control program if (bLinux) { if (!checkFileExists(".\\plink.exe")) throw MakeStringException(ECLWATCH_PLINK_NOT_INSTALLED, "Invalid ESP installation: missing plink.exe to execute the remote program!"); command.replace('\\', '/');//replace all '\\' by '/' /* note that if we use plink (cmd line ssh client) for the first time with a computer, it generates the following message: The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is. The server's key fingerprint is: 1024 aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp If you trust this host, enter "y" to add the key to PuTTY's cache and carry on connecting. If you want to carry on connecting just once, without adding the key to the cache, enter "n".If you do not trust this host, press Return to abandon the connection. To get around this, we pipe "n" to plink without using its -batch parameter. We need help from cmd.exe to do this though... */ cmdLine.appendf("cmd /c \"echo y | .\\plink.exe -ssh -l %s -pw %s %s sudo bash -c '%s' 2>&1\"", environmentConfData.m_user.str(), password.str(), sAddress, command.str()); } else { if (!checkFileExists(".\\psexec.exe")) throw MakeStringException(ECLWATCH_PSEXEC_NOT_INSTALLED, "Invalid ESP installation: missing psexec.exe to execute the remote program!"); cmdLine.appendf(".\\psexec \\\\%s -u %s -p %s %s cmd /c %s 2>&1", sAddress, userId.str(), password.str(), "", command.str()); } #else if (bLinux) { command.replace('\\', '/');//replace all '\\' by '/' cmdLine.appendf("ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5"); cmdLine.appendf(" %s '%s' 2>&1", sAddress, command.str()); } else { sResponse.append("Remote execution from Linux to Windows is not supported!"); exitCode = 1; } #endif #else if (bLinux) { command.replace('\\', '/');//replace all '\\' by '/' cmdLine.appendf("ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5"); cmdLine.appendf(" %s '%s' 2>&1", sAddress, command.str()); } else { sResponse.append("Remote execution from Linux to Windows is not supported!"); exitCode = 1; } #endif if (*cmdLine.str()) { StringBuffer response, response1; exitCode = invokeProgram(cmdLine, response); if (exitCode < 0) response1.append("Failed in executing a system command.\n"); else response1.append("System command(s) has been executed.\n"); //remove \n at the end int len = response.length(); if (len > 0 && response.charAt(--len) == '\n') response.setLength(len); if (response.length() > 0) response1.appendf("Response: %s", response.str()); else response1.append("No response received.\n"); sResponse.append(response1.str()); } iRet = exitCode; } catch(IException* e) { StringBuffer buf; e->errorMessage(buf); sResponse.append(buf.str()); iRet = e->errorCode(); } #ifndef NO_CATCHALL catch(...) { sResponse.append("An unknown exception occurred!"); iRet = -1; } #endif return iRet; } //--------------------------------------------------------------------------- // createProcess //--------------------------------------------------------------------------- int Cws_machineEx::invokeProgram(const char *command_line, StringBuffer& response) { char buffer[128]; FILE *fp; // Run the command so that it writes its output to a pipe. Open this // pipe with read text attribute so that we can read it // like a text file. if (getEspLogLevel()>LogNormal) { DBGLOG("command_line=<%s>", command_line); } if( (fp = popen( command_line, "r" )) == NULL ) return -1; // Read pipe until end of file. End of file indicates that //the stream closed its standard out (probably meaning it //terminated). while ( !feof(fp) ) if ( fgets( buffer, 128, fp) ) response.append( buffer ); if (getEspLogLevel()>LogNormal) { DBGLOG("response=<%s>", response.str()); } // Close pipe and print return value of CHKDSK. return pclose( fp ); } int Cws_machineEx::remoteGetMachineInfo(IEspContext& context, const char *address, const char *configAddress, const char *preflightCommand, const char* user, const char* password, StringBuffer& sResponse, CMachineInfo& machineInfo) { #ifdef DETECT_WS_MC_MEM_LEAKS static bool firstTime = true; if (firstTime) { firstTime = false; unsigned t = setAllocHook(true); } #endif //DETECT_WS_MC_MEM_LEAKS int iRet = runCommand(context, address, configAddress, preflightCommand, user, password, sResponse); if (iRet == 0) { iRet = readMachineInfo(sResponse.str(), machineInfo); } #ifdef DETECT_WS_MC_MEM_LEAKS DBGLOG("Allocated=%d", setAllocHook(false)); #endif //DETECT_WS_MC_MEM_LEAKS return iRet; } // the following method is invoked on worker threads of void Cws_machineEx::doGetMachineInfo(IEspContext& context, CMachineInfoThreadParam* pParam) { IEspMachineInfoEx* info = pParam->m_pMachineInfo; IEspMachineInfoEx* info1 = pParam->m_pMachineInfo1; StringBuffer& sSecurityString = pParam->m_sSecurityString; try { info->setAddress(pParam->m_sAddress.str()); info->setConfigAddress(pParam->m_sConfigAddress.str()); info->setProcessType(pParam->m_sProcessType.str()); info->setComponentName( pParam->m_sCompName.str() ); info->setComponentPath( pParam->m_sPath.str()); char displayName[128]; GetDisplayProcessName(pParam->m_sProcessType.str(), displayName); info->setDisplayType(displayName); if (pParam->m_bECLAgent) { info1->setAddress(pParam->m_sAddress.str()); info1->setConfigAddress(pParam->m_sConfigAddress.str()); info1->setProcessType("AgentExecProcess"); info1->setComponentName( pParam->m_sCompName.str() ); info1->setComponentPath( pParam->m_sPath.str()); char displayName[128]; GetDisplayProcessName("AgentExecProcess", displayName); info1->setDisplayType(displayName); } int iRet = 0; CMachineInfo machineInfo; StringBuffer preFlightCommand; preFlightCommand.appendf("/%s/sbin/%s %s", environmentConfData.m_executionPath.str(), m_machineInfoFile.str(), environmentConfData.m_pidPath.str()); if (preFlightCommand.charAt(preFlightCommand.length() - 1) == '/') preFlightCommand.remove(preFlightCommand.length()-1, 1); preFlightCommand.appendf(" %s", pParam->m_sCompName.str()); if (!stricmp(pParam->m_sProcessType.str(), "ThorMasterProcess")) preFlightCommand.append("_master"); else if (!stricmp(pParam->m_sProcessType.str(), "ThorSlaveProcess")) { preFlightCommand.appendf("_slave_%d", pParam->m_processNumber); double version = context.getClientVersion(); if (version > 1.09) info->setProcessNumber(pParam->m_processNumber); } StringBuffer sResponse; iRet = remoteGetMachineInfo(context, pParam->m_sAddress.str(), pParam->m_sConfigAddress.str(), preFlightCommand.str(), pParam->m_sUserName.str(), pParam->m_sPassword.str(), sResponse, machineInfo); if (iRet != 0) { info->setDescription(sResponse.str()); if (pParam->m_bECLAgent) info1->setDescription(sResponse.str()); } else { IArrayOf runningProcesses; getRunningProcesses(context, pParam->m_sAddress.str(), pParam->m_sConfigAddress.str(), pParam->m_sUserName.str(), pParam->m_sPassword.str(), runningProcesses); if (pParam->m_bGetStorageInfo) { IArrayOf storageArray; doGetStorageInfo(pParam, storageArray, machineInfo); info->setStorage(storageArray); if (pParam->m_bECLAgent) info1->setStorage(storageArray); storageArray.kill(); } if (pParam->m_bGetProcessorInfo) { IArrayOf processorArray; doGetProcessorInfo(pParam, processorArray, machineInfo); info->setProcessors(processorArray); if (pParam->m_bECLAgent) info1->setProcessors(processorArray); } if (pParam->m_bGetSwInfo) { IArrayOf runArray; doGetSWRunInfo(context, pParam, runArray, machineInfo, runningProcesses, pParam->m_sProcessType.str(), pParam->m_bFilterProcesses, pParam->m_bMonitorDaliFileServer, pParam->m_additionalProcesses); info->setRunning(runArray); if (pParam->m_bECLAgent) info1->setRunning(runArray); } if (machineInfo.m_sComputerUptime.length() > 0) { info->setUpTime(machineInfo.m_sComputerUptime.str()); if (pParam->m_bECLAgent) info1->setUpTime(machineInfo.m_sComputerUptime.str()); } else { info->setUpTime("-"); if (pParam->m_bECLAgent) info1->setUpTime("-"); } pParam->addColumn("Up Time"); } } catch (IException* e) { StringBuffer sError; e->errorMessage(sError); e->Release(); info->setDescription(sError.str()); } catch (const char* e) { info->setDescription(e); } catch (...) { info->setDescription("Unknown exception!"); } } void Cws_machineEx::doGetSecurityString(const char* address, StringBuffer& securityString) { //another client (like configenv) may have updated the constant environment and we got notified //(thanks to our subscription) so reload it m_envFactory->validateCache(); securityString.clear(); Owned constEnv = getConstEnvironment(); Owned machine = constEnv->getMachineByAddress(address); if (machine) { Owned domain = machine->getDomain(); if (domain) { StringBufferAdaptor strval(securityString); domain->getSnmpSecurityString(strval); } } } IPropertyTree* Cws_machineEx::getComponent(const char* compType, const char* compName) { StringBuffer xpath; xpath.append("Software/").append(compType).append("[@name='").append(compName).append("']"); m_envFactory->validateCache(); Owned constEnv = getConstEnvironment(); Owned pEnvRoot = &constEnv->getPTree(); return pEnvRoot->getPropTree( xpath.str() ); } void Cws_machineEx::getAccountAndPlatformInfo(const char* address, StringBuffer& userId, StringBuffer& password, bool& bLinux) { m_envFactory->validateCache(); Owned constEnv = getConstEnvironment(); Owned machine = constEnv->getMachineByAddress(address); if (!machine && !stricmp(address, ".")) { machine.setown(constEnv->getMachineByAddress("127.0.0.1")); } if (!machine) throw MakeStringException(ECLWATCH_INVALID_INPUT, "Machine %s is not defined in environment!", address); bLinux = machine->getOS() == MachineOsLinux; Owned domain = machine->getDomain(); if (!domain) throw MakeStringException(ECLWATCH_INVALID_INPUT, "Machine %s does not have any domain information!", address); userId.clear(); password.clear(); StringBufferAdaptor strval1(userId); StringBufferAdaptor strval2(password); domain->getAccountInfo(strval1, strval2); StringBuffer domainName; StringBufferAdaptor strval3(domainName); domain->getName(strval3); if ((machine->getOS() == MachineOsW2K) && domainName.length()) { domainName.append('\\'); userId.insert(0, domainName); } } void Cws_machineEx::determineRequredProcesses(CMachineInfoThreadParam* pParam, const char* pszProcessType, bool bMonitorDaliFileServer, const StringArray& additionalProcesses, set& requiredProcesses) { StringBuffer xpath; const char* pszOperatingSystem = pParam->m_operatingSystem == OS_Windows ? "Windows" : "Linux"; xpath.appendf("Platform[@name='%s']", pszOperatingSystem); IPropertyTree* pOsSpecificFilters = m_processFilters->queryPropTree( xpath.str() ); if (!pOsSpecificFilters) throw MakeStringException(ECLWATCH_INVALID_PROCESS_FILTER, "No process filters have been defined for %s!", pszOperatingSystem); //create a set (sorted list that is easy to search into) of processes expected to run //on this box StringBuffer sProcessName; //first collect all "common" processes that are required on any box irrespective of //its type StringBuffer xPath("ProcessFilter[@name='any']/Process"); Owned iProcesses = pOsSpecificFilters->getElements(xPath.str()); ForEach (*iProcesses) { iProcesses->query().getProp("@name", sProcessName.clear()); sProcessName.toLowerCase().replaceString(".exe", ""); //if this process name is valid and either we are monitoring dali file server or //(we are not monitoring that and) it is not that process then add it to list of required processes if (m_useDefaultHPCCInit) { if (*sProcessName.str() && (bMonitorDaliFileServer || 0 != strcmp(sProcessName.str(), "dafilesrv"))) requiredProcesses.insert(sProcessName.str()); } else { if (*sProcessName.str() && (bMonitorDaliFileServer || 0 != strcmp(sProcessName.str(), "dafilesrv"))) requiredProcesses.insert(sProcessName.str()); } } //insert all additional processes that may have been specified with the request int len = additionalProcesses.length(); for (int i=0; iqueryPropTree(xPath.str()); if (pProcessFilterNode) { pParam->m_bMultipleInstances = pParam->m_operatingSystem == OS_Linux && pProcessFilterNode->getPropBool("@multipleInstances", false); StringBuffer strCompName(pParam->m_sCompName); strCompName.trim(); Owned iProcesses = pProcessFilterNode->getElements("Process"); ForEach (*iProcesses) { IPropertyTree* pProcess = &iProcesses->query(); bool bRemove = pProcess->getPropBool("@remove", false); const char* sName = pProcess->queryProp("@name"); sProcessName.clear(); if (!strcmp(sName, ".")) sProcessName = pParam->m_sCompName; else sProcessName.append(sName); if (bRemove) sProcessName.toLowerCase().replaceString(".exe", ""); if (*sProcessName.str()) { if (bRemove) requiredProcesses.erase(sProcessName.str()); else { //support multithor: if this is a linux system and processtype is either a thor master or slave if (!strncmp(pszProcessType, "Thor", 4) && pParam->m_operatingSystem != OS_Windows) { //lookup port from environment Owned pComponent = getComponent("ThorCluster", strCompName.str()); const bool bMaster = !strcmp(pszProcessType, "ThorMasterProcess"); StringBuffer szPort; if (pComponent) szPort.append(pComponent->queryProp( bMaster ? "@masterport" : "@slaveport")); if (szPort.length() == 0) szPort.appendf("%s", bMaster ? "6500" : "6600"); StringBuffer sPort(szPort); sProcessName.append('_').append(sPort.trim().str()); } requiredProcesses.insert(sProcessName.str()); } } } } } } char* Cws_machineEx::skipChar(const char* sBuf, char c) { char* pStr2 = (char*) strchr(sBuf, c); if (pStr2) { while (pStr2[0] == c) pStr2++; } return pStr2; } void Cws_machineEx::readRunningProcess(const char* lineBuf, IArrayOf& runningProcesses) { if (strlen(lineBuf) < 1) return; int pid = -1; char desc[256]; char param[4096]; char* pStr1 = (char*) lineBuf; //skip UID char* pStr2 = skipChar(pStr1, ' '); if (!pStr2) return; //read PID pStr1 = pStr2; pStr2 = (char*) strchr(pStr1, ' '); if (!pStr2) return; char id[32]; strncpy(id, pStr1, pStr2 - pStr1); id[pStr2 - pStr1] = 0; for (unsigned i = 0; i < strlen(id); i++) { if (!isdigit(id[i])) return; } pid = atoi(id); while (pStr2[0] == ' ') pStr2++; //skip PPID pStr2 = skipChar(pStr2, ' '); if (!pStr2) return; //skip C pStr2 = skipChar(pStr2, ' '); if (!pStr2) return; //skip STIME pStr2 = skipChar(pStr2, ' '); if (!pStr2) return; //skip TTY pStr2 = skipChar(pStr2, ' '); if (!pStr2) return; //skip TIME pStr2 = skipChar(pStr2, ' '); if (!pStr2) return; //Read CMD bool bFound = false; if (!bFound) { strcpy(param, pStr2); pStr1 = pStr2; pStr2 = (char*) strchr(pStr1, ' '); if (!pStr2) { strcpy(desc, param); } else { if (pStr1[0] == '.' && pStr1[1] == '/') pStr1 += 2; strncpy(desc, pStr1, pStr2 - pStr1); desc[pStr2 - pStr1] = 0; } if (!strcmp(desc, "ps")) return; } //clean path, etc StringBuffer descStr(desc); if (descStr.charAt(0) == '[') { descStr.remove(0, 1); descStr = descStr.reverse(); if (descStr.charAt(0) == ']') descStr.remove(0, 1); descStr = descStr.reverse(); } else { descStr = descStr.reverse(); pStr1 = (char*) descStr.str(); pStr2 = (char*) strchr(pStr1, '/'); if (pStr2) { strncpy(desc, pStr1, pStr2 - pStr1); desc[pStr2 - pStr1] = 0; descStr.clear().append(desc); } descStr = descStr.reverse(); } Owned info = createProcessInfo("",""); info->setPID(pid); info->setParameter(param); info->setDescription(descStr.str()); runningProcesses.append(*info.getClear()); return; } void Cws_machineEx::getRunningProcesses(IEspContext& context, const char* address, const char* configAddress, const char* userId, const char* password, IArrayOf& runningProcesses) { StringBuffer sResponse; int iRet = runCommand(context, address, configAddress, "ps -ef", userId, password, sResponse); if (iRet == 0) { bool bStop = false; char* pStr = (char*) sResponse.str(); while (!bStop && pStr) { char lineBuf[4096]; //read a line char* pStr1 = (char*) strchr(pStr, 0x0a); if (!pStr1) { strcpy(lineBuf, pStr); bStop = true; } else { strncpy(lineBuf, pStr, pStr1 - pStr); lineBuf[pStr1 - pStr] = 0; pStr = pStr1+1; } if (strlen(lineBuf) > 0) { readRunningProcess(lineBuf, runningProcesses); } } } return; } void Cws_machineEx::checkRunningProcessesByPID(IEspContext& context, CMachineInfoThreadParam* pParam, set* pRequiredProcesses) { StringBuffer sCommand; StringBuffer sResponse; sCommand.appendf("ls %s", environmentConfData.m_pidPath.str()); int iRet = runCommand(context, pParam->m_sAddress.str(), pParam->m_sConfigAddress.str(), sCommand.str(), pParam->m_sUserName.str(), pParam->m_sPassword.str(), sResponse); if (iRet == 0) { bool bStop = false; char* pStr = (char*) sResponse.str(); while (!bStop) { char lineBuf[4096]; //read a line char* pStr1 = (char*) strchr(pStr, 0x0a); if (!pStr1) { strcpy(lineBuf, pStr); bStop = true; } else { strncpy(lineBuf, pStr, pStr1 - pStr); lineBuf[pStr1 - pStr] = 0; pStr = pStr1+1; } if (strlen(lineBuf) > 0) { char* foundProcess = NULL; set::const_iterator it = pRequiredProcesses->begin(); set::const_iterator iEnd = pRequiredProcesses->end(); for (; it != iEnd; it++) //add in sorted order simply by traversing the map { StringBuffer sName; if (strchr(lineBuf, ' ')) { sName.appendf(" %s.pid", (*it).c_str()); const char* pStr = strstr(lineBuf, sName); if (pStr) { foundProcess = (char*) ((*it).c_str()); break; } } else { sName.appendf("%s.pid", (*it).c_str()); if (!stricmp(lineBuf, sName.str())) { foundProcess = (char*) ((*it).c_str()); break; } } } if (foundProcess) pRequiredProcesses->erase(foundProcess); } } } return; } void Cws_machineEx::enumerateRunningProcesses(CMachineInfoThreadParam* pParam, IArrayOf& runningProcesses, bool bLinuxInstance, bool bFilterProcesses, map >* processMap, map >& pidMap, set* pRequiredProcesses) { const bool bThorMasterOrSlave = !strncmp(pParam->m_sProcessType, "Thor", 4); ForEachItemIn(k, runningProcesses) { IEspProcessInfo& processInfo = runningProcesses.item(k); StringBuffer scmName = processInfo.getDescription(); StringBuffer scmPath; //keep this in scope since pszName may point to it int pid = processInfo.getPID(); const char* pszName = scmName.str(); const char* pszPath = pszName; if (bLinuxInstance) { //dafilesrv would probably be running from a global directory //and not component's installation directory so ignore their paths if (//pParam->m_bMultipleInstances && 0 != stricmp(pszName, "dafilesrv")) { scmPath.append(processInfo.getParameter()); pszPath = scmPath.str(); if (pszPath && *pszPath) { if (!strncmp(pszPath, "bash ", 5)) { pszPath = scmPath.remove(0, 5).str(); if (!pszPath || !*pszPath) continue; } //params typically is like "/c$/esp_dir/esp [parameters...]" //so just pick the full path const char* pch = strchr(pszPath, ' '); if (pch) { scmPath.setLength( pch - pszPath ); pszPath = scmPath.str(); } } else pszPath = scmName.insert(0, '[').append(']').str(); } if (pRequiredProcesses) { const char* pszProcessName; if (bThorMasterOrSlave && !strnicmp(pszName, "thor", 4)) { const char* pch = strrchr(pszPath, '/'); pszProcessName = pch ? pch+1 : pszName; } else { const char* pszName0 = pParam->m_bMultipleInstances ? pszPath : pszName; const char* pch = strrchr(pszName0, '/'); pszProcessName = pch ? pch+1 : pszName0; } pRequiredProcesses->erase(pszProcessName); } pszName = pszPath; } else { pszName = scmName.toLowerCase().replaceString(".exe", ""); if (pRequiredProcesses) pRequiredProcesses->erase(pszName); } //skip processes starting with '[' character on linux unless we are not //applying filters and have to return a complete list of processes. //On windows, skip [system process] regardless. if ((bLinuxInstance && (!bFilterProcesses || *pszName != '[')) || (!bLinuxInstance && *pszName != '[')) { map >::iterator it; if (processMap) it = processMap->find(pszName); Linked lptr; if ( !processMap || it == processMap->end()) //not in the set { Owned info = static_cast(new CSWRunInfo("")); info->setName(pszName); info->setInstances(1); lptr = info; if (processMap) processMap->insert(pair >(pszName, lptr)); } else { const Linked& linkedPtr = (*it).second; lptr = linkedPtr; lptr->setInstances( lptr->getInstances() + 1); } pidMap.insert(pair >(pid, lptr)); } } } void Cws_machineEx::doGetStorageInfo(CMachineInfoThreadParam* pParam, IArrayOf &output, CMachineInfo machineInfo) { ///const int mbyte = !strcmp(temp.str(), "FixedDisk") ? 1000*1000 : 1024*1024; ///int units = storage->getUnits(); if (machineInfo.m_sSpace.length() < 1) return; char* pStr = (char*) machineInfo.m_sSpace.str(); while (pStr) { char buf[1024], title[1024]; char* pStr1 = (char*) strchr(pStr, 0x0a); if (pStr1) { strncpy(buf, pStr, pStr1 - pStr); buf[pStr1 - pStr] = 0; pStr = pStr1+1; } else { strcpy(buf, pStr); pStr = NULL; } if (strlen(buf) < 1) continue; __int64 available = 0; __int64 total = 0; int percentAvail = 0; readSpace(buf, title, available, total, percentAvail); if ((strlen(title) < 1) || (total < 1)) continue; if (!excludePartition(title)) { Owned info = static_cast(new CStorageInfo("")); pParam->addColumn( title ); info->setDescription(title); info->setTotal(total); info->setAvailable(available); info->setPercentAvail(percentAvail); output.append(*info.getLink()); } } } void Cws_machineEx::doGetProcessorInfo(CMachineInfoThreadParam* pParam, IArrayOf &output, CMachineInfo machineInfo) { pParam->addColumn("CPU Load"); int cpuLoad = 0; if (machineInfo.m_sCPUIdle.length() > 0) { char* cpuIdle = (char*) machineInfo.m_sCPUIdle.str(); if (cpuIdle[strlen(cpuIdle) - 1] == '%') cpuIdle[strlen(cpuIdle) - 1] = 0; cpuLoad = 100-atoi(cpuIdle); } Owned info = static_cast(new CProcessorInfo("")); info->setLoad(cpuLoad); output.append(*info.getLink()); } void Cws_machineEx::doGetSWRunInfo(IEspContext& context, CMachineInfoThreadParam* pParam, IArrayOf &output, CMachineInfo machineInfo, IArrayOf& runningProcesses, const char* pszProcessType, bool bFilterProcesses, bool bMonitorDaliFileServer, const StringArray& additionalProcesses) { map > processMap; //save only one description of each process map > pidMap; bool bLinuxInstance = pParam->m_operatingSystem == OS_Linux; bool bAddColumn = false; bool bDafilesrvDown = false; if (bFilterProcesses) { bAddColumn = true; if (!m_useDefaultHPCCInit) { set requiredProcesses; determineRequredProcesses( pParam, pszProcessType, bMonitorDaliFileServer, additionalProcesses, requiredProcesses); //now enumerate the processes running on this box and remove them from required processes //ignoring any non-required process if (runningProcesses.length() > 0) { enumerateRunningProcesses( pParam, runningProcesses, bLinuxInstance, true, NULL, pidMap, &requiredProcesses); } set::const_iterator it = requiredProcesses.begin(); set::const_iterator iEnd = requiredProcesses.end(); for (; it != iEnd; it++) //add in sorted order simply by traversing the map { const char* procName = (*it).c_str(); if (procName && *procName) { IEspSWRunInfo* info = static_cast(new CSWRunInfo("")); if (!stricmp(procName, "dafilesrv")) bDafilesrvDown = true; info->setName(procName); info->setInstances(0); output.append(*info); } } } } else { if (pParam->m_operatingSystem == OS_Linux && pszProcessType && *pszProcessType) { StringBuffer xpath; xpath.appendf("Platform[@name='Linux']/ProcessFilter[@name='%s']/@multipleInstances", pszProcessType); pParam->m_bMultipleInstances = m_processFilters->getPropBool(xpath.str(), false); } if (runningProcesses.length() > 0) { bAddColumn = true; enumerateRunningProcesses( pParam, runningProcesses, bLinuxInstance, bFilterProcesses, &processMap, pidMap, NULL); } map >::const_iterator it; map >::const_iterator iEnd = processMap.end(); if (!m_useDefaultHPCCInit) { set requiredProcesses; determineRequredProcesses( pParam, pszProcessType, bMonitorDaliFileServer, additionalProcesses, requiredProcesses); set::const_iterator it1 = requiredProcesses.begin(); for (; it1 != requiredProcesses.end(); it1++) //add in sorted order simply by traversing the map { const char* procName = (*it1).c_str(); if (procName && *procName && !stricmp(procName, "dafilesrv")) { bDafilesrvDown = true; } } for (it=processMap.begin(); it != iEnd; it++) //add in sorted order simply by traversing the map { Linked info( (*it).second ); const char* procName = info->getName(); if (procName && *procName && !stricmp(procName, "dafilesrv")) { bDafilesrvDown = false; } output.append( *info.getLink() ); } } else { for (it=processMap.begin(); it != iEnd; it++) //add in sorted order simply by traversing the map { Linked info( (*it).second ); output.append( *info.getLink() ); } } } if (bAddColumn) pParam->addColumn("Processes"); if (!bFilterProcesses) { if (pParam->m_operatingSystem == OS_Linux && pszProcessType && *pszProcessType) { StringBuffer xpath; xpath.appendf("Platform[@name='Linux']/ProcessFilter[@name='%s']/@multipleInstances", pszProcessType); pParam->m_bMultipleInstances = m_processFilters->getPropBool(xpath.str(), false); } } pParam->addColumn("Condition"); pParam->addColumn("State"); pParam->addColumn("UpTime"); const char* procType = pParam->m_sProcessType.str(); IEspComponentInfo* pComponentInfo = &pParam->m_pMachineInfo->updateComponentInfo(); pComponentInfo->setCondition(-1);//failed to retrieve SNMP info - will get overwritten by walker callback, if successful //The bDafilesrvDown is set only when used if (!bDafilesrvDown && machineInfo.m_sID.length() > 0) { //conditions: unknown, normal, warning, minor, major, critical, fatal pComponentInfo->setCondition( 1 ); pComponentInfo->setState(5); if (machineInfo.m_sProcessUptime.length() > 0) { char day[1024]; char* pDay = (char*) machineInfo.m_sProcessUptime.str(); char* pTime = strchr(pDay, '-'); if (!pTime) { pComponentInfo->setUpTime( pDay ); } else { strncpy(day, pDay, pTime - pDay); day[pTime - pDay] = 0; StringBuffer upTime; upTime.appendf("%s days %s", day, pTime+1); pComponentInfo->setUpTime( upTime.str() ); } } } else { pComponentInfo->setCondition(2); //Warnning pComponentInfo->setState(0); if (bFilterProcesses && (machineInfo.m_sID.length() < 1)) { IEspSWRunInfo* info = static_cast(new CSWRunInfo("")); info->setName(pParam->m_sCompName.str()); info->setInstances(0); output.append(*info); } } if (pParam->m_bECLAgent) { IEspComponentInfo* pComponentInfo1 = &pParam->m_pMachineInfo1->updateComponentInfo(); pComponentInfo1->setCondition(pComponentInfo->getCondition()); //for AgentExec pComponentInfo1->setState(pComponentInfo->getState()); //for AgentExec pComponentInfo1->setUpTime(pComponentInfo->getUpTime()); //for AgentExec pComponentInfo->setUpTime("-"); //for ECL Agent } } //this method parses address info of the form "192.168.1.4-6:ThorSlaveProcess:thor1:2:path1" //into respective components void Cws_machineEx::parseProperties(const char* info, StringBuffer& processType, StringBuffer& sCompName, OpSysType& os, StringBuffer& path, unsigned& processNumber) { StringArray sArray; DelimToStringArray(info, sArray, ":"); unsigned int ordinality = sArray.ordinality(); if (ordinality == 0) throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Invalid address format '%s'.", info); processType.clear().append( sArray.item(0) ); sCompName.clear(); path.clear(); os = OS_Windows; if (ordinality < 2) return; sCompName.append( sArray.item(1) ); if (ordinality < 3) return; os = (OpSysType) atoi( sArray.item(2) ); if (ordinality < 4) return; path.append( sArray.item(3) ); if (path.length()) { char pat1, pat2; char rep1, rep2; if (os == OS_Linux) { pat1 = ':'; rep1 = '$'; pat2 = '\\';rep2 = '/'; } else { pat1 = '$'; rep1 = ':'; pat2 = '/';rep2 = '\\'; } path.replace( pat1, rep1 ); path.replace( pat2, rep2 ); const char* pszPath = path.str(); if (os == OS_Linux && *pszPath != '/') { path.insert(0, '/'); pszPath = path.str(); } if (*(pszPath + path.length()-1) != rep2) path.append(rep2); } if (ordinality < 5) return; processNumber = atoi( sArray.item(4) ); return; } void Cws_machineEx::getTimeStamp(char* timeStamp) { //set time stamp in the result for this machine time_t tNow; time(&tNow); #ifdef _WIN32 struct tm *ltNow; ltNow = localtime(&tNow); strftime(timeStamp, 32, "%m/%d/%y %H:%M:%S", ltNow); #else struct tm ltNow; localtime_r(&tNow, <Now); strftime(timeStamp, 32, "%m/%d/%y %H:%M:%S", <Now); #endif } int Cws_machineEx::lookupSnmpComponentIndex(const StringBuffer& sProcessType) { map::const_iterator it = s_processTypeToSnmpIdMap.find( sProcessType.str() ); return (it != s_processTypeToSnmpIdMap.end()) ? (*it).second : -1; } const char* Cws_machineEx::lookupProcessname(const StringBuffer& sProcessType) { map::const_iterator it = s_processTypeToProcessMap.find( sProcessType.str() ); return (it != s_processTypeToProcessMap.end()) ? (*it).second : ""; } //--------------------------------------------------------------------------- // GetDisplayProcessName //--------------------------------------------------------------------------- const char* Cws_machineEx::GetDisplayProcessName(const char* processName, char* buf) { //produces "LDAPServerProcess" as "LDAP Server" and "EspService" as "Esp Service", etc. const char* begin = buf; const char* end = strstr(processName, "Process"); if (!end) end = processName + strlen(processName); *buf++ = *processName++; bool bLower = false; while (processName < end) { char ch = *processName; if (isupper(ch)) { if (bLower || //last char was uppercase or the following character is lowercase? ((processName+1 < end) && islower(*(processName+1)))) { *buf++ = ' '; } bLower = false; } else bLower = true; *buf++ = *processName++; } *buf = '\0'; return begin; } bool Cws_machineEx::excludePartition(const char* partition) const { //first see if this partition is meant to be excluded as is - for instance //if partition is /dev and /dev is one of the predefined partitions to be excluded set::const_iterator it = m_excludePartitions.find( partition ); set::const_iterator itEnd = m_excludePartitions.end(); bool bFound = false; if (it != itEnd) bFound = true; else { //now check if /dev* is one of the partitions to be excluded set::const_iterator itBegin = m_excludePartitionPatterns.begin(); itEnd = m_excludePartitionPatterns.end(); unsigned int partitionLen = strlen(partition); for (it=itBegin; it != itEnd; it++) { const string& pattern = *it; if (bFound = ::WildMatch(partition, partitionLen, pattern.c_str(), pattern.length(), false)) break; } } return bFound; } void Cws_machineEx::setAttPath(StringBuffer& Path,const char* PathToAppend,const char* AttName,const char* AttValue) { Path.append("/"); Path.append(PathToAppend); Path.append("[@"); Path.append(AttName); Path.append("=\""); Path.append(AttValue); Path.append("\"]"); } int Cws_machineEx::checkProcess(const char* type, const char* name, StringArray& typeArray, StringArray& nameArray) { int pos = -1; if (!type || !*type || !name || !*name) return pos; int count = nameArray.ordinality(); if (count < 1) return pos; int i = 0; while (i < count) { const char* name0 = nameArray.item(i); const char* type0 = typeArray.item(i); if (type0 && !strcmp(type, type0) && name0 && !strcmp(name, name0)) { pos = i; break; } i++; } return pos; } void Cws_machineEx::getThorMachineList(IConstEnvironment* constEnv, IPropertyTree* cluster, const char* machineName, const char* machineType, const char* directory, StringArray& processAddresses) { if (!constEnv || !cluster) throw MakeStringExceptionDirect(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information."); StringBuffer groupName; if (strieq(machineType, eqThorSlaveProcess)) getClusterGroupName(*cluster, groupName); else if (strieq(machineType, eqThorSpareProcess)) getClusterSpareGroupName(*cluster, groupName); if (groupName.length() < 1) return; Owned nodeGroup = queryNamedGroupStore().lookup(groupName.str()); if (!nodeGroup || (nodeGroup->ordinality() == 0)) return; unsigned processNumber = 0; Owned gi = nodeGroup->getIterator(); ForEach(*gi) { StringBuffer addressRead; gi->query().endpoint().getIpText(addressRead); if (addressRead.length() == 0) { WARNLOG("Net address not found for a node in node group %s", groupName.str()); continue; } processNumber++; StringBuffer netAddress; const char* ip = addressRead.str(); if (!streq(ip, ".")) { netAddress.append(ip); } else { IpAddress ipaddr = queryHostIP(); ipaddr.getIpText(netAddress); } if (netAddress.length() == 0) { WARNLOG("Net address not found for a node in node group %s", groupName.str()); continue; } Owned pMachineInfo = constEnv->getMachineByAddress(addressRead.str()); if (pMachineInfo.get()) { StringBuffer os, processAddress; os.append(pMachineInfo->getOS()); processAddress.appendf("%s|%s:%s:%s:%s:%s:%d", netAddress.str(), addressRead.str(), machineType, machineName, os.str(), directory, processNumber); processAddresses.append(processAddress); } else { WARNLOG("Machine not found for a node in node group %s", groupName.str()); } } return; } void Cws_machineEx::getMachineList(IConstEnvironment* constEnv, IPropertyTree* envRoot, const char* machineName, const char* machineType, const char* directory, StringArray& processAddresses, set* pMachineNames/*=NULL*/) { StringBuffer directoryStr = directory; Owned machines= envRoot->getElements(machineType); if (machines->first()) { do { StringArray machineInstance; IPropertyTree &machine = machines->query(); const char* computerName = machine.queryProp("@computer"); if (!computerName || !*computerName) { Owned instances= machine.getElements("Instance"); if (instances->first()) { do { IPropertyTree &instance = instances->query(); computerName = instance.queryProp("@computer"); if (!computerName || !*computerName) continue; if (directoryStr.length() < 1) directoryStr.append(instance.queryProp("@directory")); machineInstance.append(computerName); } while (instances->next()); } } else { machineInstance.append(computerName); } if (machineInstance.length() < 1) continue; for (unsigned i = 0; i < machineInstance.length(); i++) { const char* name0 = machineInstance.item(i); if (pMachineNames)//caller wishes us to avoid inserting duplicate entries for machines { if (pMachineNames->find(name0) != pMachineNames->end()) continue; pMachineNames->insert(name0); } StringBuffer processAddress, name, netAddress, configNetAddress, os; if (machineName && *machineName) name.append(machineName); else name.append(name0); Owned pMachineInfo = constEnv->getMachine(name0); if (pMachineInfo.get()) { SCMStringBuffer ep; pMachineInfo->getNetAddress(ep); const char* ip = ep.str(); if (!ip || stricmp(ip, ".")) { netAddress.append(ep.str()); configNetAddress.append(ep.str()); } else { StringBuffer ipStr; IpAddress ipaddr = queryHostIP(); ipaddr.getIpText(ipStr); if (ipStr.length() > 0) { netAddress.append(ipStr.str()); configNetAddress.append("."); } } os.append(pMachineInfo->getOS()); } processAddress.appendf("%s|%s:%s:%s:%s:%s", netAddress.str(), configNetAddress.str(), machineType, name.str(), os.str(), directoryStr.str()); processAddresses.append(processAddress); } } while (machines->next()); } return; } const char* Cws_machineEx::getProcessTypeFromMachineType(const char* machineType) { const char* processType = machineType; if (!stricmp(machineType, eqThorMasterProcess) || !stricmp(machineType, eqThorSlaveProcess) || !stricmp(machineType, eqThorSpareProcess)) { processType = eqThorCluster; } else if (!stricmp(machineType, "RoxieServerProcess") || !stricmp(machineType, "RoxieSlaveProcess")) { processType = eqRoxieCluster; } else if (!stricmp(machineType, "AgentExecProcess")) { processType = eqEclAgent; } return processType; } void Cws_machineEx::setTargetClusterInfo(IPropertyTree* pTargetClusterTree, IArrayOf& machineArray, IArrayOf& targetClusterInfoList) { unsigned machineCount = machineArray.ordinality(); if (machineCount < 1) return; if (!pTargetClusterTree) return; Owned targetClusters = pTargetClusterTree->getElements("TargetCluster"); ForEach(*targetClusters) { IPropertyTree& targetCluster = targetClusters->query(); StringBuffer targetName, targetType; targetCluster.getProp("@Name", targetName); targetCluster.getProp("@Type", targetType); Owned targetClusterInfo = static_cast(new CTargetClusterInfo("")); targetClusterInfo->setName( targetName.str() ); targetClusterInfo->setType( targetType.str() ); IArrayOf machineArrayNew; Owned processes = targetCluster.getElements("Process"); ForEach(*processes) { IPropertyTree& process = processes->query(); StringBuffer processName, processType; process.getProp("@Name", processName); process.getProp("@Type", processType); for (unsigned i = 0; i < machineCount; i++) { IEspMachineInfoEx& machineInfoEx = machineArray.item(i); const char* name = machineInfoEx.getComponentName(); const char* type = machineInfoEx.getProcessType(); if (!name || !type || stricmp(name, processName.str()) || stricmp(getProcessTypeFromMachineType(type), processType.str())) continue; Owned pMachineInfo = static_cast(new CMachineInfoEx("")); pMachineInfo->copy(machineInfoEx); machineArrayNew.append(*pMachineInfo.getLink()); } } if (machineArrayNew.ordinality()) targetClusterInfo->setProcesses(machineArrayNew); targetClusterInfoList.append(*targetClusterInfo.getLink()); } } void Cws_machineEx::getTargetClusterProcesses(StringArray& targetClusters, StringArray& processTypes, StringArray& processNames, StringArray& processAddresses, IPropertyTree* pTargetClusterTree) { unsigned ordinality= targetClusters.ordinality(); if (ordinality < 1) return; Owned envFactory = getEnvironmentFactory(); Owned constEnv = envFactory->openEnvironmentByFile(); Owned pEnvironmentRoot = &constEnv->getPTree(); if (!pEnvironmentRoot) throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information."); IPropertyTree* pEnvironmentSoftware = pEnvironmentRoot->queryPropTree("Software"); if (!pEnvironmentSoftware) throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information."); IPropertyTree* pEnvironmentDirectories = pEnvironmentSoftware->queryPropTree("Directories"); for (unsigned index=0; indexqueryPropTree(path.str()); if (!pCluster) continue; Owned thorClusters= pCluster->getElements(eqThorCluster); Owned roxieClusters= pCluster->getElements(eqRoxieCluster); Owned eclCCServerProcesses= pCluster->getElements(eqEclCCServer); Owned eclAgentProcesses= pCluster->getElements(eqEclAgent); Owned eclSchedulerProcesses= pCluster->getElements(eqEclScheduler); if (type && !stricmp(type, eqThorCluster) && !thorClusters->first()) continue; if (type && !stricmp(type, eqRoxieCluster) && !roxieClusters->first()) continue; if (type && !stricmp(type, eqHoleCluster) && (roxieClusters->first() || thorClusters->first())) continue; IPropertyTree *pTargetClusterInfo = pTargetClusterTree->addPropTree("TargetCluster", createPTree("TargetCluster")); if (!pTargetClusterInfo) throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree"); pTargetClusterInfo->setProp("@Name", pClusterName); if (type && *type) pTargetClusterInfo->setProp("@Type", type); //Read Cluster process if (thorClusters->first()) { IArrayOf machineArray; do { IPropertyTree &thorCluster = thorClusters->query(); const char* process = thorCluster.queryProp("@process"); if (process && *process) { IPropertyTree *pThorClusterInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process")); if (!pThorClusterInfo) throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree"); pThorClusterInfo->setProp("@Name", process); pThorClusterInfo->setProp("@Type", eqThorCluster); if (checkProcess(eqThorCluster, process, processTypes, processNames) < 0) { Owned pMachineInfo = static_cast(new CMachineInfoEx("")); pMachineInfo->setComponentName( process ); pMachineInfo->setProcessType(eqThorCluster); machineArray.append(*pMachineInfo.getLink()); processTypes.append(eqThorCluster); processNames.append(process); StringBuffer dirStr; if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqThorCluster, process, dirStr)) { dirStr.clear().append(thorCluster.queryProp("@directory")); } path.clear().appendf("Software/%s[@name='%s']", eqThorCluster, process); IPropertyTree* pClusterProcess = pEnvironmentRoot->queryPropTree(path.str()); if (pClusterProcess) { if (dirStr.length() < 1) dirStr.append(pClusterProcess->queryProp("@directory")); getMachineList(constEnv, pClusterProcess, process, eqThorMasterProcess, dirStr.str(), processAddresses); getThorMachineList(constEnv, pClusterProcess, process, eqThorSlaveProcess, dirStr.str(), processAddresses); getThorMachineList(constEnv, pClusterProcess, process, eqThorSpareProcess, dirStr.str(), processAddresses); } } } } while (thorClusters->next()); } if (roxieClusters->first()) { do { IPropertyTree &roxieCluster = roxieClusters->query(); const char* process = roxieCluster.queryProp("@process"); if (process && *process) { IPropertyTree *pRoxieClusterInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process")); if (!pRoxieClusterInfo) throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree"); pRoxieClusterInfo->setProp("@Name", process); pRoxieClusterInfo->setProp("@Type", eqRoxieCluster); if (checkProcess(eqRoxieCluster, process, processTypes, processNames) < 0) { processTypes.append(eqRoxieCluster); processNames.append(process); StringBuffer dirStr; if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqRoxieCluster, process, dirStr)) { dirStr.clear().append(roxieCluster.queryProp("@directory")); } path.clear().appendf("Software/%s[@name='%s']", eqRoxieCluster, process); IPropertyTree* pClusterProcess = pEnvironmentRoot->queryPropTree(path.str()); if (pClusterProcess) { if (dirStr.length() < 1) dirStr.append(pClusterProcess->queryProp("@directory")); set machineNames; //used for checking duplicates getMachineList(constEnv, pClusterProcess, process, "RoxieServerProcess", dirStr.str(), processAddresses, &machineNames); getMachineList(constEnv, pClusterProcess, process, "RoxieSlaveProcess", dirStr.str(), processAddresses, &machineNames); } } } } while (thorClusters->next()); } //Read eclCCServer process if (eclCCServerProcesses->first()) { IPropertyTree &eclCCServerProcess = eclCCServerProcesses->query(); const char* process = eclCCServerProcess.queryProp("@process"); if (process && *process) { IPropertyTree *pEclCCServerInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process")); if (!pEclCCServerInfo) throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree"); pEclCCServerInfo->setProp("@Name", process); pEclCCServerInfo->setProp("@Type", eqEclCCServer); if (checkProcess(eqEclCCServer, process, processTypes, processNames) < 0) { processTypes.append(eqEclCCServer); processNames.append(process); StringBuffer dirStr; if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqEclCCServer, process, dirStr)) { dirStr.clear().append(eclCCServerProcess.queryProp("@directory")); } getMachineList(constEnv, pEnvironmentSoftware, process, eqEclCCServer, dirStr.str(), processAddresses); } } } //Read eclAgent process if (eclAgentProcesses->first()) { IPropertyTree &eclAgentProcess = eclAgentProcesses->query(); const char* process = eclAgentProcess.queryProp("@process"); if (process && *process) { IPropertyTree *pEclAgentInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process")); if (!pEclAgentInfo) throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree"); pEclAgentInfo->setProp("@Name", process); pEclAgentInfo->setProp("@Type", eqEclAgent); if (checkProcess(eqEclAgent, process, processTypes, processNames) < 0) { processTypes.append(eqEclAgent); processNames.append(process); StringBuffer dirStr; if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqEclAgent, process, dirStr)) { dirStr.clear().append(eclAgentProcess.queryProp("@directory")); } getMachineList(constEnv, pEnvironmentSoftware, process, eqEclAgent, dirStr.str(), processAddresses); } } } //Read eclScheduler process if (eclSchedulerProcesses->first()) { IPropertyTree &eclSchedulerProcess = eclSchedulerProcesses->query(); const char* process = eclSchedulerProcess.queryProp("@process"); if (process && *process) { IPropertyTree *pEclSchedulerInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process")); if (!pEclSchedulerInfo) throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree"); pEclSchedulerInfo->setProp("@Name", process); pEclSchedulerInfo->setProp("@Type", eqEclScheduler); if (checkProcess(eqEclScheduler, process, processTypes, processNames) < 0) { processTypes.append(eqEclScheduler); processNames.append(process); StringBuffer dirStr; if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqEclScheduler, process, dirStr)) { dirStr.clear().append(eclSchedulerProcess.queryProp("@directory")); } getMachineList(constEnv, pEnvironmentSoftware, process, eqEclScheduler, dirStr.str(), processAddresses); } } } free(clusterName); } return; } bool Cws_machineEx::onGetTargetClusterInfo(IEspContext &context, IEspGetTargetClusterInfoRequest & req, IEspGetTargetClusterInfoResponse & resp) { try { if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false)) throw MakeStringException(ECLWATCH_MACHINE_INFO_ACCESS_DENIED, "Failed to Get Machine Information. Permission denied."); StringBuffer user; StringBuffer pw; context.getUserID(user); context.getPassword(pw); IEspRequestInfoStruct& reqInfo = resp.updateRequestInfo(); reqInfo.setGetProcessorInfo(req.getGetProcessorInfo()); reqInfo.setGetStorageInfo(req.getGetStorageInfo()); reqInfo.setGetSoftwareInfo(req.getGetSoftwareInfo()); reqInfo.setAutoRefresh( req.getAutoRefresh() ); reqInfo.setMemThreshold(req.getMemThreshold()); reqInfo.setDiskThreshold(req.getDiskThreshold()); reqInfo.setCpuThreshold(req.getCpuThreshold()); reqInfo.setMemThresholdType(req.getMemThresholdType()); reqInfo.setDiskThresholdType(req.getDiskThresholdType()); reqInfo.setApplyProcessFilter( req.getApplyProcessFilter() ); reqInfo.setAddProcessesToFilter( req.getAddProcessesToFilter() ); StringArray& targetClusters = req.getTargetClusters(); StringArray processTypes, processNames, processAddresses; Owned pTargetClusterTree = createPTreeFromXMLString(""); getTargetClusterProcesses(targetClusters, processTypes, processNames, processAddresses, pTargetClusterTree); if (processAddresses.ordinality()) { IArrayOf machineArray; StringArray columnArray; RunMachineQuery(context, processAddresses,reqInfo,machineArray,columnArray); resp.setColumns( columnArray ); if (machineArray.ordinality()) { IArrayOf targetClusterInfoList; setTargetClusterInfo(pTargetClusterTree, machineArray, targetClusterInfoList); resp.setTargetClusterInfoList(targetClusterInfoList); } } char timeStamp[32]; getTimeStamp(timeStamp); resp.setTimeStamp( timeStamp ); } catch(IException* e) { FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR); } return true; }