ws_machineService.cpp 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #include <math.h>
  15. #include "ws_machineService.hpp"
  16. #include "jarray.hpp"
  17. #include "jmisc.hpp"
  18. #include "jutil.hpp"
  19. #include "thirdparty.h"
  20. #include "ws_topology.hpp"
  21. #include "rmtfile.hpp"
  22. #include "exception_util.hpp"
  23. #ifndef eqHoleCluster
  24. #define eqHoleCluster "HoleCluster"
  25. #endif
  26. #ifndef eqThorCluster
  27. #define eqThorCluster "ThorCluster"
  28. #endif
  29. #ifndef eqRoxieCluster
  30. #define eqRoxieCluster "RoxieCluster"
  31. #endif
  32. #ifndef eqEclCCServer
  33. #define eqEclCCServer "EclCCServerProcess"
  34. #endif
  35. #ifndef eqEclAgent
  36. #define eqEclAgent "EclAgentProcess"
  37. #endif
  38. #ifndef eqEclScheduler
  39. #define eqEclScheduler "EclSchedulerProcess"
  40. #endif
  41. #ifndef eqThorMasterProcess
  42. #define eqThorMasterProcess "ThorMasterProcess"
  43. #endif
  44. #ifndef eqThorSlaveProcess
  45. #define eqThorSlaveProcess "ThorSlaveProcess"
  46. #endif
  47. #ifndef eqThorSpareProcess
  48. #define eqThorSpareProcess "ThorSpareProcess"
  49. #endif
  50. #ifndef eqHOLEMACHINES
  51. #define eqHOLEMACHINES "HOLEMACHINES"
  52. #endif
  53. #ifndef eqROXIEMACHINES
  54. #define eqROXIEMACHINES "ROXIEMACHINES"
  55. #endif
  56. #ifndef eqMACHINES
  57. #define eqMACHINES "MACHINES"
  58. #endif
  59. static const int THREAD_POOL_SIZE = 40;
  60. static const int THREAD_POOL_STACK_SIZE = 64000;
  61. static const char* FEATURE_URL = "MachineInfoAccess";
  62. //---------------------------------------------------------------------------------------------
  63. //NOTE: PART I of implementation for Cws_machineEx
  64. // PART II and III are in ws_machineServiceMetrics.cpp and ws_machineServiceRexec.cpp resp.
  65. //---------------------------------------------------------------------------------------------
  66. class CMachineInfoThreadParam : public CWsMachineThreadParam
  67. {
  68. public:
  69. IMPLEMENT_IINTERFACE;
  70. IEspContext& m_context;
  71. StringBuffer m_sProcessType;
  72. StringBuffer m_sCompName;
  73. StringBuffer m_sConfigAddress;
  74. StringBuffer m_sUserId;
  75. StringBuffer m_sPassword;
  76. StringBuffer m_sPath;
  77. bool m_bECLAgent;
  78. bool m_bGetProcessorInfo;
  79. bool m_bGetStorageInfo;
  80. bool m_bGetSwInfo;
  81. bool m_bFilterProcesses;
  82. bool m_bMonitorDaliFileServer;
  83. bool m_bMultipleInstances;
  84. Cws_machineEx::OpSysType m_operatingSystem;
  85. Linked<IEspMachineInfoEx> m_pMachineInfo;
  86. Linked<IEspMachineInfoEx> m_pMachineInfo1;
  87. set<string>& m_columnSet;
  88. StringArray& m_columnArray;
  89. const StringArray& m_additionalProcesses;
  90. CMachineInfoThreadParam( const char* pszAddress, const char* pszProcessType, const char* pszCompName, const char* pszUserId,
  91. const char* pszPassword, const char* pszPath, set<string>& columnSet, StringArray& columnArray,
  92. bool bGetProcessorInfo, bool bGetStorageInfo, bool bGetSwInfo, bool bFilterProcesses,
  93. bool bMonitorDaliFileServer, Cws_machineEx::OpSysType os, const StringArray& additionalProcesses,
  94. IEspMachineInfoEx* pMachineInfo, Cws_machineEx* pService, IEspContext& context, const char* pszConfigAddress)
  95. : CWsMachineThreadParam(pszAddress, pszUserId, pszPassword, pService),
  96. m_columnSet(columnSet),
  97. m_columnArray(columnArray),
  98. m_operatingSystem(os),
  99. m_context(context),
  100. m_additionalProcesses(additionalProcesses)
  101. {
  102. m_bECLAgent = false;
  103. m_sUserId = pszUserId;
  104. m_sPassword = pszPassword;
  105. m_sPath = pszPath;
  106. m_bFilterProcesses = bFilterProcesses;
  107. m_bMonitorDaliFileServer = bMonitorDaliFileServer;
  108. m_sProcessType = pszProcessType;
  109. m_sCompName = pszCompName;
  110. m_sConfigAddress = pszConfigAddress,
  111. m_bGetProcessorInfo= bGetProcessorInfo;
  112. m_bGetStorageInfo = bGetStorageInfo;
  113. m_bGetSwInfo = bGetSwInfo;
  114. m_pMachineInfo.set( pMachineInfo );
  115. m_bMultipleInstances = false;
  116. }
  117. CMachineInfoThreadParam( const char* pszAddress, const char* pszProcessType, const char* pszCompName, const char* pszUserId,
  118. const char* pszPassword, const char* pszPath, set<string>& columnSet, StringArray& columnArray,
  119. bool bGetProcessorInfo, bool bGetStorageInfo, bool bGetSwInfo, bool bFilterProcesses,
  120. bool bMonitorDaliFileServer, Cws_machineEx::OpSysType os, const StringArray& additionalProcesses,
  121. IEspMachineInfoEx* pMachineInfo, IEspMachineInfoEx* pMachineInfo1, Cws_machineEx* pService, IEspContext& context, const char* pszConfigAddress)
  122. : CWsMachineThreadParam(pszAddress, pszUserId, pszPassword, pService),
  123. m_columnSet(columnSet),
  124. m_columnArray(columnArray),
  125. m_operatingSystem(os),
  126. m_context(context),
  127. m_additionalProcesses(additionalProcesses)
  128. {
  129. m_sUserId = pszUserId;
  130. m_sPassword = pszPassword;
  131. m_sPath = pszPath;
  132. m_bFilterProcesses = bFilterProcesses;
  133. m_bMonitorDaliFileServer = bMonitorDaliFileServer;
  134. m_sProcessType = pszProcessType;
  135. m_sCompName = pszCompName;
  136. m_sConfigAddress = pszConfigAddress,
  137. m_bGetProcessorInfo= bGetProcessorInfo;
  138. m_bGetStorageInfo = bGetStorageInfo;
  139. m_bGetSwInfo = bGetSwInfo;
  140. m_pMachineInfo.set( pMachineInfo );
  141. m_pMachineInfo1.set( pMachineInfo1 );
  142. m_bECLAgent = true;
  143. m_bMultipleInstances = false;
  144. }
  145. CMachineInfoThreadParam( const char* pszAddress, const char* pszProcessType,
  146. const char* pszCompName, const char* pszSecString, const char* pszUserId,
  147. const char* pszPassword, const char* pszPath, set<string>& columnSet, StringArray& columnArray,
  148. bool bGetProcessorInfo, bool bGetStorageInfo, bool bGetSwInfo, bool bFilterProcesses,
  149. bool bMonitorDaliFileServer, Cws_machineEx::OpSysType os, const StringArray& additionalProcesses,
  150. IEspMachineInfoEx* pMachineInfo, Cws_machineEx* pService, IEspContext& context)
  151. : CWsMachineThreadParam(pszAddress, pszSecString, pService),
  152. m_columnSet(columnSet),
  153. m_columnArray(columnArray),
  154. m_operatingSystem(os),
  155. m_context(context),
  156. m_additionalProcesses(additionalProcesses)
  157. {
  158. m_sUserId = pszUserId;
  159. m_sPassword = pszPassword;
  160. m_sPath = pszPath;
  161. m_bFilterProcesses = bFilterProcesses;
  162. m_bMonitorDaliFileServer = bMonitorDaliFileServer;
  163. m_sProcessType = pszProcessType;
  164. m_sCompName = pszCompName;
  165. m_bGetProcessorInfo= bGetProcessorInfo;
  166. m_bGetStorageInfo = bGetStorageInfo;
  167. m_bGetSwInfo = bGetSwInfo;
  168. m_pMachineInfo.set( pMachineInfo );
  169. m_bMultipleInstances = false;
  170. m_bECLAgent = false;
  171. }
  172. virtual void doWork()
  173. {
  174. m_pService->doGetMachineInfo(m_context, this);
  175. }
  176. void addColumn(const char* columnName)
  177. {
  178. synchronized block(s_mutex);
  179. if (m_columnSet.find(columnName) == m_columnSet.end())
  180. {
  181. m_columnSet.insert(columnName);
  182. m_columnArray.append(columnName);
  183. }
  184. }
  185. private:
  186. static Mutex s_mutex;
  187. };
  188. /*static*/Mutex CMachineInfoThreadParam::s_mutex;
  189. //---------------------------------------------------------------------------------------------
  190. /*static*/map<string, int> Cws_machineEx::s_processTypeToSnmpIdMap;
  191. /*static*/map<string, const char*> Cws_machineEx::s_oid2CompTypeMap;
  192. void Cws_machineEx::init(IPropertyTree *cfg, const char *process, const char *service)
  193. {
  194. StringBuffer xpath;
  195. xpath.appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]", process, service);
  196. Owned<IPropertyTree> pServiceNode = cfg->getPropTree(xpath.str());
  197. m_bMonitorDaliFileServer = pServiceNode->getPropBool("@monitorDaliFileServer", false);
  198. m_processFilters.setown( pServiceNode->getPropTree("ProcessFilters") );
  199. const char* pchExcludePartitions = pServiceNode->queryProp("@excludePartitions");
  200. if (pchExcludePartitions && *pchExcludePartitions)
  201. {
  202. StringArray sPartitions;
  203. DelimToStringArray(pchExcludePartitions, sPartitions, ", ;");
  204. unsigned int nPartitions = sPartitions.ordinality();
  205. for (unsigned int i=0; i<nPartitions; i++)
  206. {
  207. const char* partition = sPartitions.item(i);
  208. if (partition && *partition)
  209. if (strchr(partition, '*'))
  210. m_excludePartitionPatterns.insert( partition );
  211. else
  212. m_excludePartitions.insert( partition );
  213. }
  214. }
  215. m_envFactory.setown( getEnvironmentFactory() );
  216. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]", process, service);
  217. Owned<IPropertyTree> pProcessNode = cfg->getPropTree(xpath.str());
  218. m_useDefaultSSHUserID = pProcessNode->getPropBool("UseDefaultSSHUserID", true);
  219. m_useDefaultHPCCInit = pProcessNode->getPropBool("UseDefaultHPCCInit", true);
  220. m_useDefaultPIDFileName = pProcessNode->getPropBool("UseDefaultPIDFileName", false);
  221. const char* machineInfoPath = pProcessNode->queryProp("MachineInfoFile");
  222. if (machineInfoPath && *machineInfoPath)
  223. {
  224. m_machineInfoFile.append(machineInfoPath);
  225. }
  226. else
  227. {
  228. m_machineInfoFile.append("preflight");
  229. }
  230. Owned<IConstEnvironment> constEnv = getConstEnvironment();
  231. Owned<IPropertyTree> pRoot = &constEnv->getPTree();
  232. IPropertyTree* pEnvSettings = pRoot->getPropTree("EnvSettings");
  233. if (pEnvSettings)
  234. {
  235. pEnvSettings->getProp("configs", m_environmentConfData.m_configsPath.clear());
  236. pEnvSettings->getProp("path", m_environmentConfData.m_executionPath.clear());
  237. pEnvSettings->getProp("runtime", m_environmentConfData.m_runtimePath.clear());
  238. pEnvSettings->getProp("lock", m_environmentConfData.m_lockPath.clear());
  239. pEnvSettings->getProp("pid", m_environmentConfData.m_pidPath.clear());
  240. }
  241. IThreadFactory* pThreadFactory = new CWsMachineThreadFactory();
  242. m_threadPool.setown(createThreadPool("WsMachine Thread Pool", pThreadFactory,
  243. NULL, THREAD_POOL_SIZE, 10000, THREAD_POOL_STACK_SIZE)); //10 sec timeout for available thread; use stack size of 2MB
  244. pThreadFactory->Release();
  245. //populate the process type to SNMP component index map
  246. if (s_processTypeToSnmpIdMap.empty())
  247. {
  248. //add mappings in random order to keep the map balanced
  249. //don't add Hole and Thor since they have numerous sub-types and are better
  250. //handled as special cases
  251. s_processTypeToSnmpIdMap.insert(pair<string, int>("ThorMasterProcess", 3));
  252. s_processTypeToSnmpIdMap.insert(pair<string, int>("EclServerProcess", 4));
  253. s_processTypeToSnmpIdMap.insert(pair<string, int>("DaliServerProcess", 7));
  254. s_processTypeToSnmpIdMap.insert(pair<string, int>("RoxieServerProcess", 16));
  255. s_processTypeToSnmpIdMap.insert(pair<string, int>("DfuServerProcess", 18));
  256. s_processTypeToSnmpIdMap.insert(pair<string, int>("SashaServerProcess", 20));
  257. s_processTypeToSnmpIdMap.insert(pair<string, int>("EspProcess", 100));
  258. }
  259. if (s_processTypeToProcessMap.empty())
  260. {
  261. s_processTypeToProcessMap.insert(pair<string, const char*>("DaliServerProcess", "daserver"));
  262. s_processTypeToProcessMap.insert(pair<string, const char*>("DfuServerProcess", "dfuserver"));
  263. s_processTypeToProcessMap.insert(pair<string, const char*>("EclServerProcess", "eclserver"));
  264. s_processTypeToProcessMap.insert(pair<string, const char*>("FTSlaveProcess", "ftslave"));
  265. s_processTypeToProcessMap.insert(pair<string, const char*>("SashaServerProcess", "saserver"));
  266. s_processTypeToProcessMap.insert(pair<string, const char*>("ThorMasterProcess", "thormaster"));
  267. s_processTypeToProcessMap.insert(pair<string, const char*>("RoxieServerProcess", "roxie"));
  268. }
  269. }
  270. Cws_machineEx::~Cws_machineEx()
  271. {
  272. }
  273. IConstEnvironment* Cws_machineEx::getConstEnvironment()
  274. {
  275. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  276. Owned<IConstEnvironment> constEnv = envFactory->openEnvironmentByFile();
  277. return constEnv.getLink();
  278. }
  279. const char* Cws_machineEx::getEnvironmentConf(const char* confFileName)
  280. {
  281. if (!confFileName || !*confFileName)
  282. return NULL;
  283. StringBuffer environmentConf;
  284. IFile * pFile = createIFile(confFileName);
  285. if (pFile->exists( ))
  286. {
  287. Owned<IFileIO> pFileIO = pFile->openShared(IFOread, IFSHfull);
  288. if (pFileIO)
  289. {
  290. StringBuffer tmpBuf;
  291. offset_t fileSize = pFile->size();
  292. tmpBuf.ensureCapacity((unsigned)fileSize);
  293. tmpBuf.setLength((unsigned)fileSize);
  294. size32_t nRead = pFileIO->read(0, (size32_t) fileSize, (char*)tmpBuf.str());
  295. if (nRead == fileSize)
  296. {
  297. environmentConf = tmpBuf;
  298. }
  299. }
  300. }
  301. return environmentConf.str();
  302. }
  303. bool Cws_machineEx::onGetMachineInfo(IEspContext &context, IEspGetMachineInfoRequest & req,
  304. IEspGetMachineInfoResponse & resp)
  305. {
  306. #ifdef DETECT_WS_MC_MEM_LEAKS
  307. static bool firstTime = true;
  308. if (firstTime)
  309. {
  310. firstTime = false;
  311. unsigned t = setAllocHook(true);
  312. }
  313. #endif //DETECT_WS_MC_MEM_LEAKS
  314. try
  315. {
  316. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  317. throw MakeStringException(ECLWATCH_MACHINE_INFO_ACCESS_DENIED, "Failed to Get Machine Information. Permission denied.");
  318. StringBuffer user;
  319. StringBuffer pw;
  320. context.getUserID(user);
  321. context.getPassword(pw);
  322. IEspRequestInfoStruct& reqInfo = resp.updateRequestInfo();
  323. reqInfo.setSecurityString(req.getSecurityString());
  324. reqInfo.setSortBy(req.getSortBy());
  325. reqInfo.setGetProcessorInfo(req.getGetProcessorInfo());
  326. reqInfo.setGetStorageInfo(req.getGetStorageInfo());
  327. reqInfo.setGetSoftwareInfo(req.getGetSoftwareInfo());
  328. reqInfo.setSortBy("Address");
  329. reqInfo.setAutoRefresh( req.getAutoRefresh() );
  330. reqInfo.setMemThreshold(req.getMemThreshold());
  331. reqInfo.setDiskThreshold(req.getDiskThreshold());
  332. reqInfo.setCpuThreshold(req.getCpuThreshold());
  333. reqInfo.setMemThresholdType(req.getMemThresholdType());
  334. reqInfo.setDiskThresholdType(req.getDiskThresholdType());
  335. reqInfo.setApplyProcessFilter( req.getApplyProcessFilter() );
  336. reqInfo.setClusterType( req.getClusterType() );
  337. reqInfo.setCluster( req.getCluster() );
  338. reqInfo.setAddProcessesToFilter( req.getAddProcessesToFilter() );
  339. reqInfo.setOldIP( req.getOldIP() );
  340. reqInfo.setPath( req.getPath() );
  341. IArrayOf<IEspMachineInfoEx> machineArray;
  342. StringArray columnArray;
  343. const char* userName = m_sTestStr1.str();
  344. const char* password = m_sTestStr2.str();
  345. if (userName && *userName)
  346. {
  347. reqInfo.setUserName(userName);
  348. resp.setUserName(userName);
  349. }
  350. else
  351. {
  352. reqInfo.setUserName(user.str());
  353. }
  354. if (password && *password)
  355. {
  356. reqInfo.setPassword(password);
  357. resp.setPassword(password);
  358. }
  359. else
  360. {
  361. reqInfo.setPassword(pw.str());
  362. }
  363. RunMachineQuery(context, req.getAddresses(),reqInfo,machineArray,columnArray);
  364. resp.setColumns( columnArray );
  365. resp.setMachines(machineArray);
  366. char timeStamp[32];
  367. getTimeStamp(timeStamp);
  368. resp.setTimeStamp( timeStamp );
  369. }
  370. catch(IException* e)
  371. {
  372. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  373. }
  374. #ifdef DETECT_WS_MC_MEM_LEAKS
  375. DBGLOG("Allocated=%d", setAllocHook(false));
  376. #endif //DETECT_WS_MC_MEM_LEAKS
  377. return true;
  378. }
  379. bool Cws_machineEx::onGetMachineInfoEx(IEspContext &context, IEspGetMachineInfoRequestEx & req,
  380. IEspGetMachineInfoResponseEx & resp)
  381. {
  382. try
  383. {
  384. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  385. throw MakeStringException(ECLWATCH_MACHINE_INFO_ACCESS_DENIED, "Failed to Get Machine Information. Permission denied.");
  386. StringBuffer user;
  387. StringBuffer pw;
  388. context.getUserID(user);
  389. context.getPassword(pw);
  390. Owned<IEspRequestInfoStruct> reqInfo = new CRequestInfoStruct("","");
  391. reqInfo->setGetProcessorInfo(true);
  392. reqInfo->setGetStorageInfo(true);
  393. reqInfo->setGetSoftwareInfo(true);
  394. reqInfo->setUserName(user.str());
  395. reqInfo->setPassword(pw.str());
  396. reqInfo->setSortBy("Address");
  397. reqInfo->setClusterType( req.getClusterType() );
  398. IArrayOf<IEspMachineInfoEx> machineArray;
  399. StringArray columnArray;
  400. RunMachineQuery(context, req.getAddresses(),*reqInfo,machineArray,columnArray);
  401. resp.setMachines(machineArray);
  402. }
  403. catch(IException* e)
  404. {
  405. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  406. }
  407. return true;
  408. }
  409. void Cws_machineEx::RunMachineQuery(IEspContext &context, StringArray &addresses,IEspRequestInfoStruct& reqInfo,
  410. IArrayOf<IEspMachineInfoEx>& machineArray, StringArray& columnArray)
  411. {
  412. bool bMonitorDaliFileServer = m_bMonitorDaliFileServer;
  413. bool bFilterProcesses = reqInfo.getApplyProcessFilter();
  414. int ordinality= addresses.ordinality();
  415. int index = 0;
  416. if (!ordinality)
  417. return;
  418. StringArray additionalProcesses;
  419. if (bFilterProcesses)
  420. {
  421. const char* xpath = reqInfo.getPath();
  422. if (xpath && *xpath)
  423. {
  424. StringBuffer decodedPath;
  425. JBASE64_Decode(xpath, decodedPath);
  426. try
  427. {
  428. //xpath is the Path to parent node (normally a cluster)
  429. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  430. Owned<IConstEnvironment> constEnv = envFactory->openEnvironmentByFile();
  431. Owned<IPropertyTree> root0 = &constEnv->getPTree();
  432. if (!root0)
  433. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information.");
  434. char* xpath = (char*)decodedPath.str();
  435. if (!strnicmp(xpath, "/Environment/", 13))
  436. xpath += 13;
  437. IPropertyTree* root = root0->queryPropTree( xpath );
  438. if (!root)
  439. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Specified path '%s' is invalid!", decodedPath.str());
  440. bMonitorDaliFileServer = root->getPropBool("@monitorDaliFileServer", false);
  441. }
  442. catch(IException* e)
  443. {
  444. StringBuffer msg;
  445. e->errorMessage(msg);
  446. WARNLOG("%s", msg.str());
  447. e->Release();
  448. }
  449. catch(...)
  450. {
  451. WARNLOG("Unknown Exception caught within Cws_machineEx::RunMachineQuery");
  452. }
  453. }
  454. DelimToStringArray(reqInfo.getAddProcessesToFilter(), additionalProcesses, " ,\t");
  455. int len = additionalProcesses.length();
  456. for (int i=0; i<len; i++)
  457. {
  458. StringBuffer sProcessName = additionalProcesses.item(i);
  459. sProcessName.toLowerCase().replaceString(".exe", "");
  460. if (sProcessName.length()==0)
  461. {
  462. additionalProcesses.remove(i--, true);//decrement i so we process the next item (now at position i)
  463. len--;
  464. }
  465. else
  466. additionalProcesses.replace(sProcessName, i, true);
  467. }
  468. }
  469. typedef multimap<unsigned, string> AddressMap;
  470. AddressMap addressMap; //maps <numeric address> to <process>:<comp name>:<os>:<path>
  471. UnsignedArray threadHandles;
  472. set<string> columnSet;
  473. IpAddress ipAddr;
  474. for (index=0; index<ordinality; index++)
  475. {
  476. char *address = strdup( addresses.item(index) );
  477. char* props = strchr(address, ':');
  478. if (props)
  479. *props++ = '\0';
  480. else
  481. props = (char *)"";
  482. char* configAddress = NULL;
  483. char* props1 = strchr(address, '|');
  484. if (props1)
  485. {
  486. configAddress = props1+1;
  487. *props1 = '\0';
  488. }
  489. if (!configAddress || !*configAddress)
  490. {
  491. configAddress = address;
  492. }
  493. IpAddress ipAddr;
  494. unsigned numIps = ipAddr.ipsetrange(address);
  495. //address is like 192.168.1.4-6:ThorSlaveProcess:thor1:2:path1
  496. //so process each address in the range
  497. for (unsigned j=0;j<numIps;j++)
  498. {
  499. if (!ipAddr.isIp4())
  500. IPV6_NOT_IMPLEMENTED();
  501. unsigned numAddr;
  502. if (ipAddr.getNetAddress(sizeof(numAddr),&numAddr)!=sizeof(numAddr))
  503. IPV6_NOT_IMPLEMENTED(); // Not quite right exception, but will use when IPv4 hack sanity check fails
  504. //if no mapping exists for numAddr yet or if we are using filters and props are different then
  505. //insert in the map
  506. AddressMap::const_iterator i = addressMap.find(numAddr);
  507. bool bInsert = (i == addressMap.end()) ||
  508. (reqInfo.getGetSoftwareInfo() && 0 != strcmp((*i).second.c_str(), props));
  509. if (bInsert)
  510. {
  511. StringBuffer sBuf;
  512. if (configAddress && *configAddress)
  513. sBuf.appendf("%s:%s", configAddress, props);
  514. addressMap.insert(pair<unsigned, string>(numAddr, sBuf.str()));
  515. }
  516. ipAddr.ipincrement(1);
  517. }
  518. free(address);
  519. }
  520. AddressMap::const_iterator iBeginAddr = addressMap.begin();
  521. AddressMap::const_iterator iEndAddr = addressMap.end();
  522. for (AddressMap::const_iterator iAddr = iBeginAddr; iAddr != iEndAddr; iAddr++)
  523. {
  524. IpAddress ipAddr;
  525. unsigned numAddr = (*iAddr).first; // TBD IPv6
  526. ipAddr.setNetAddress(sizeof(numAddr),&numAddr);
  527. StringBuffer address;
  528. ipAddr.getIpText(address);
  529. StringBuffer sProcessType;
  530. StringBuffer sCompName;
  531. OpSysType os = OS_Windows;
  532. StringBuffer sPath;
  533. const char *configAddress = (*iAddr).second.c_str();
  534. char* props = (char*) strchr(configAddress, ':');
  535. if (props)
  536. *props++ = '\0';
  537. else
  538. props = (char*) configAddress;
  539. if (props)
  540. parseProperties( props, sProcessType, sCompName, os, sPath);
  541. else
  542. bFilterProcesses = false;
  543. //OS is constant for a m/c so can be ignored if IP is already recorded
  544. if (*address.str())
  545. {
  546. bool bAgentExec = stricmp(sProcessType.str(), "EclAgentProcess")==0;
  547. Owned<IEspMachineInfoEx> pMachineInfo = static_cast<IEspMachineInfoEx*>(new CMachineInfoEx(""));
  548. pMachineInfo->setOS( os );
  549. if (!bAgentExec)
  550. {
  551. machineArray.append(*pMachineInfo.getLink());
  552. CMachineInfoThreadParam* pThreadReq =
  553. new CMachineInfoThreadParam( address.str(), sProcessType.str(), sCompName.str(), reqInfo.getUserName(), reqInfo.getPassword(), sPath.str(),
  554. columnSet, columnArray, reqInfo.getGetProcessorInfo(), reqInfo.getGetStorageInfo(), reqInfo.getGetSoftwareInfo(),
  555. bFilterProcesses, bMonitorDaliFileServer, os, additionalProcesses, pMachineInfo, this, context, configAddress);
  556. PooledThreadHandle handle = m_threadPool->start( pThreadReq );
  557. threadHandles.append(handle);
  558. }
  559. else
  560. {
  561. Owned<IEspMachineInfoEx> pMachineInfo1 = static_cast<IEspMachineInfoEx*>(new CMachineInfoEx(""));
  562. pMachineInfo1->setOS( os );
  563. machineArray.append(*pMachineInfo1.getLink());
  564. CMachineInfoThreadParam* pThreadReq =
  565. new CMachineInfoThreadParam( address.str(), sProcessType.str(), sCompName.str(), reqInfo.getUserName(), reqInfo.getPassword(), sPath.str(),
  566. columnSet, columnArray, reqInfo.getGetProcessorInfo(), reqInfo.getGetStorageInfo(), reqInfo.getGetSoftwareInfo(),
  567. bFilterProcesses, bMonitorDaliFileServer, os, additionalProcesses, pMachineInfo, pMachineInfo1, this, context, configAddress);
  568. PooledThreadHandle handle = m_threadPool->start( pThreadReq );
  569. threadHandles.append(handle);
  570. }
  571. }
  572. }
  573. //block for worker theads to finish, if necessary and then collect results
  574. PooledThreadHandle* pThreadHandle = threadHandles.getArray();
  575. unsigned i=threadHandles.ordinality();
  576. while (i--)
  577. {
  578. m_threadPool->join(*pThreadHandle);
  579. pThreadHandle++;
  580. }
  581. }
  582. // the following method is invoked on worker threads of
  583. void Cws_machineEx::getUpTime(CMachineInfoThreadParam* pParam, StringBuffer& out)
  584. {
  585. if (pParam->m_sAddress.length() < 1)
  586. return;
  587. SocketEndpoint ep(pParam->m_sAddress.str());
  588. MemoryBuffer outbuf;
  589. int ret = remoteExec(ep,"/bin/cat /proc/uptime",NULL,true,0,NULL,&outbuf);
  590. if (ret != 0)
  591. return;
  592. outbuf.append((byte)0);
  593. const char *pStr = outbuf.toByteArray();
  594. if (!pStr)
  595. return;
  596. char *pStr0 = (char *) strchr(pStr, ' ');
  597. if (!pStr0)
  598. return;
  599. pStr0[0] = 0;
  600. int days = 0, hours = 0, min = 0;
  601. double seconds = 0.0;
  602. double dSec = atof(pStr);
  603. if (dSec > 24*3600)
  604. {
  605. days = (int) dSec/(24*3600);
  606. }
  607. hours = (int) (dSec/3600 - days * 24);
  608. min = (int) (dSec/60 - (days * 24 + hours) * 60);
  609. seconds = (int) (dSec - (days * 24 * 3600 + hours * 3600 + min * 60));
  610. if (days > 0)
  611. out.appendf("%d days, %d:%d:%2.2f", days, hours, min, seconds);
  612. else
  613. out.appendf("%d:%d:%2.2f", hours, min, seconds);
  614. return;
  615. }
  616. void Cws_machineEx::readAString(const char *orig, const char *begin, const char *end, StringBuffer& strReturn, bool bTrim)
  617. {
  618. char* pStr = (char*) strstr(orig, begin);
  619. if (pStr)
  620. {
  621. pStr += strlen(begin);
  622. if (pStr)
  623. {
  624. char buf[1024];
  625. char* pStr1 = (char*) strchr(pStr, 0x0a);
  626. if (pStr1)
  627. {
  628. strncpy(buf, pStr, pStr1 - pStr);
  629. buf[pStr1 - pStr] = 0;
  630. }
  631. else
  632. strcpy(buf, pStr);
  633. strReturn.append(buf);
  634. if (bTrim)
  635. strReturn.trim();
  636. }
  637. }
  638. }
  639. void Cws_machineEx::readTwoStrings(const char *orig, const char *begin, const char *middle, const char *end, StringBuffer& strReturn1, StringBuffer& strReturn2, bool bTrim)
  640. {
  641. char* pStr = (char*) strstr(orig, begin);
  642. if (pStr)
  643. {
  644. pStr += strlen(begin);
  645. if (pStr)
  646. {
  647. char buf[1024];
  648. char* pStr1 = (char*) strchr(pStr, 0x0a);
  649. if (pStr1)
  650. {
  651. strncpy(buf, pStr, pStr1 - pStr);
  652. buf[pStr1 - pStr] = 0;
  653. }
  654. else
  655. strcpy(buf, pStr);
  656. strReturn1.append(buf);
  657. if (bTrim)
  658. strReturn1.trim();
  659. if (strReturn1.length() > 0)
  660. {
  661. pStr = (char*) strReturn1.str();
  662. if (pStr)
  663. {
  664. char* pStr1 = (char*) strstr(pStr, middle);
  665. if (pStr1)
  666. {
  667. int len0 = strReturn1.length();
  668. int len1 = pStr1 - pStr;
  669. int len2 = len0 - strlen(middle) - len1;
  670. strReturn2.append(strReturn1);
  671. strReturn1.remove(len1, len0-len1);
  672. strReturn2.remove(0, len0-len2);
  673. }
  674. }
  675. }
  676. }
  677. }
  678. }
  679. void Cws_machineEx::readSpace(const char *line, char* title, __int64& free, __int64& total, int& percentAvail)
  680. {
  681. if (!line)
  682. return;
  683. __int64 used = 0;
  684. char free0[1024], used0[1024];
  685. char* pStr = (char*) line;
  686. char* pStr1 = (char*) strchr(pStr, ':');
  687. if (!pStr1)
  688. return;
  689. strncpy(title, pStr, pStr1 - pStr);
  690. title[pStr1 - pStr] = 0;
  691. pStr = pStr1 + 2;
  692. pStr1 = (char*) strchr(pStr, ' ');
  693. if (!pStr1)
  694. return;
  695. strncpy(used0, pStr, pStr1 - pStr);
  696. used0[pStr1 - pStr] = 0;
  697. pStr = pStr1 + 1;
  698. if (!pStr)
  699. return;
  700. strcpy(free0, pStr);
  701. __int64 factor1 = 1;
  702. if (strlen(free0) > 9)
  703. {
  704. free0[strlen(free0) - 6] = 0;
  705. factor1 = 1000000;
  706. }
  707. free = atol(free0)*factor1;
  708. __int64 factor2 = 1;
  709. if (strlen(used0) > 9)
  710. {
  711. used0[strlen(used0) - 6] = 0;
  712. factor2 = 1000000;
  713. }
  714. used = atol(used0)*factor2;
  715. total = free + used;
  716. if (total > 0)
  717. percentAvail = (int) ((free*100)/total);
  718. free = (__int64) free /1000; //MByte
  719. total = (__int64) total /1000; //MByte
  720. return;
  721. }
  722. int Cws_machineEx::readMachineInfo(const char *response, CMachineInfo& machineInfo)
  723. {
  724. if (!response || !*response)
  725. return -1;
  726. StringBuffer computerUptime;
  727. readAString(response, "ProcessUpTime:", "\r", machineInfo.m_sProcessUptime, true);
  728. if (machineInfo.m_sProcessUptime.length() > 0)
  729. readAString(response, "ProcessID:", "\r", machineInfo.m_sID, true);
  730. readAString(response, "CPU-Idle:", "\r", machineInfo.m_sCPUIdle, true);
  731. readAString(response, "ComputerUpTime:", "\r", computerUptime, true);
  732. const char* spaceLine = "---SpaceUsedAndFree---";
  733. char* pStr = (char*) strstr(response, spaceLine);
  734. if (pStr)
  735. {
  736. pStr += strlen(spaceLine)+1;
  737. if (pStr)
  738. machineInfo.m_sSpace.append(pStr);
  739. }
  740. if (computerUptime.length() > 0)
  741. {
  742. machineInfo.m_sComputerUptime = computerUptime;
  743. char* pStr = (char*) computerUptime.str();
  744. char* ppStr = strchr(pStr, ' ');
  745. if (ppStr)
  746. {
  747. ppStr++;
  748. ppStr = strchr(ppStr, ' ');
  749. if (ppStr)
  750. {
  751. ppStr++;
  752. if (ppStr)
  753. machineInfo.m_sComputerUptime.clear().append(ppStr);
  754. }
  755. }
  756. }
  757. return 0;
  758. }
  759. int Cws_machineEx::runCommand(IEspContext& context, const char* sAddress, const char* sConfigAddress, const char* sCommand, const char* sUserId,
  760. const char* sPassword, StringBuffer& sResponse)
  761. {
  762. int iRet = 0;
  763. try
  764. {
  765. StringBuffer command(sCommand);
  766. StringBuffer cmdLine;
  767. StringBuffer userId;
  768. StringBuffer password;
  769. bool bLinux;
  770. int exitCode = -1;
  771. if (sConfigAddress && *sConfigAddress)
  772. getAccountAndPlatformInfo(sConfigAddress, userId, password, bLinux);
  773. else
  774. getAccountAndPlatformInfo(sAddress, userId, password, bLinux);
  775. if (!sUserId || !*sUserId || !sPassword ||!*sPassword)
  776. {
  777. //BUG: 9825 - remote execution on linux needs to use individual accounts
  778. //use userid/password in ESP context for remote execution...
  779. if (bLinux)
  780. {
  781. userId.clear();
  782. password.clear();
  783. context.getUserID(userId);
  784. context.getPassword(password);
  785. }
  786. }
  787. else
  788. {
  789. userId.clear().append(sUserId);
  790. password.clear().append(sPassword);
  791. }
  792. #ifdef _WIN32
  793. #ifndef CHECK_LINUX_COMMAND
  794. #define popen _popen
  795. #define pclose _pclose
  796. // Use psexec as default remote control program
  797. if (bLinux)
  798. {
  799. if (!checkFileExists(".\\plink.exe"))
  800. throw MakeStringException(ECLWATCH_PLINK_NOT_INSTALLED, "Invalid ESP installation: missing plink.exe to execute the remote program!");
  801. command.replace('\\', '/');//replace all '\\' by '/'
  802. /*
  803. note that if we use plink (cmd line ssh client) for the first time with a computer,
  804. it generates the following message:
  805. The server's host key is not cached in the registry. You have no guarantee that the
  806. server is the computer you think it is. The server's key fingerprint is:
  807. 1024 aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp
  808. If you trust this host, enter "y" to add the key to
  809. PuTTY's cache and carry on connecting. If you want to carry on connecting just once,
  810. without adding the key to the cache, enter "n".If you do not trust this host, press
  811. Return to abandon the connection.
  812. To get around this, we pipe "n" to plink without using its -batch parameter. We need
  813. help from cmd.exe to do this though...
  814. */
  815. if (!m_useDefaultSSHUserID)
  816. {
  817. cmdLine.appendf("cmd /c \"echo y | .\\plink.exe -ssh -l espuser -i id_rsa.ppk %s bash -c '%s' 2>&1\"",
  818. sAddress, command.str());
  819. }
  820. else
  821. {
  822. cmdLine.appendf("cmd /c \"echo y | .\\plink.exe -ssh -l %s -pw %s %s sudo bash -c '%s' 2>&1\"",
  823. userId.str(), password.str(), sAddress, command.str());
  824. }
  825. }
  826. else
  827. {
  828. if (!checkFileExists(".\\psexec.exe"))
  829. throw MakeStringException(ECLWATCH_PSEXEC_NOT_INSTALLED, "Invalid ESP installation: missing psexec.exe to execute the remote program!");
  830. cmdLine.appendf(".\\psexec \\\\%s -u %s -p %s %s cmd /c %s 2>&1",
  831. sAddress, userId.str(), password.str(),
  832. "", command.str());
  833. }
  834. #else
  835. if (bLinux)
  836. {
  837. command.replace('\\', '/');//replace all '\\' by '/'
  838. //cmdLine.appendf("./pssh %s@%s -o password=%s -o StrictHostKeyChecking=no sudo %s 2>&1",
  839. // userId.str(), sAddress, password.str(), command.str());
  840. ///cmdLine.appendf("echo %s | %s/bin/pssh %s@%s -o password=%s -o StrictHostKeyChecking=no sudo -S %s 2>&1",
  841. /// password.str(), m_environmentConfData.m_executionPath.str(), userId.str(), sAddress, password.str(), command.str());
  842. cmdLine.appendf("ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5");
  843. if (!m_useDefaultSSHUserID)
  844. {
  845. cmdLine.appendf(" -i /home/espuser/.ssh/id_rsa espuser@%s '%s' 2>&1", sAddress, command.str());
  846. }
  847. else
  848. {
  849. cmdLine.appendf(" %s '%s' 2>&1", sAddress, command.str());
  850. }
  851. }
  852. else
  853. {
  854. sResponse.append("Remote execution from Linux to Windows is not supported!");
  855. exitCode = 1;
  856. }
  857. #endif
  858. #else
  859. if (bLinux)
  860. {
  861. command.replace('\\', '/');//replace all '\\' by '/'
  862. //cmdLine.appendf("./pssh %s@%s -o password=%s -o StrictHostKeyChecking=no sudo %s 2>&1",
  863. // userId.str(), sAddress, password.str(), command.str());
  864. ///cmdLine.appendf("echo %s | %s/bin/pssh %s@%s -o password=%s -o StrictHostKeyChecking=no sudo -S %s 2>&1",
  865. /// password.str(), m_environmentConfData.m_executionPath.str(), userId.str(), sAddress, password.str(), command.str());
  866. cmdLine.appendf("ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5");
  867. if (!m_useDefaultSSHUserID)
  868. {
  869. cmdLine.appendf(" -i /home/espuser/.ssh/id_rsa espuser@%s '%s' 2>&1", sAddress, command.str());
  870. }
  871. else
  872. {
  873. cmdLine.appendf(" %s '%s' 2>&1", sAddress, command.str());
  874. }
  875. }
  876. else
  877. {
  878. sResponse.append("Remote execution from Linux to Windows is not supported!");
  879. exitCode = 1;
  880. }
  881. #endif
  882. if (*cmdLine.str())
  883. {
  884. StringBuffer response, response1;
  885. exitCode = invokeProgram(cmdLine, response);
  886. if (exitCode < 0)
  887. response1.append("Failed in executing a system command.\n");
  888. else
  889. response1.append("System command(s) has been executed.\n");
  890. //remove \n at the end
  891. int len = response.length();
  892. if (len > 0 && response.charAt(--len) == '\n')
  893. response.setLength(len);
  894. if (response.length() > 0)
  895. response1.appendf("Response: %s", response.str());
  896. else
  897. response1.append("No response received.\n");
  898. sResponse.append(response1.str());
  899. }
  900. iRet = exitCode;
  901. }
  902. catch(IException* e)
  903. {
  904. StringBuffer buf;
  905. e->errorMessage(buf);
  906. sResponse.append(buf.str());
  907. iRet = e->errorCode();
  908. }
  909. #ifndef NO_CATCHALL
  910. catch(...)
  911. {
  912. sResponse.append("An unknown exception occurred!");
  913. iRet = -1;
  914. }
  915. #endif
  916. return iRet;
  917. }
  918. //---------------------------------------------------------------------------
  919. // createProcess
  920. //---------------------------------------------------------------------------
  921. int Cws_machineEx::invokeProgram(const char *command_line, StringBuffer& response)
  922. {
  923. char buffer[128];
  924. FILE *fp;
  925. // Run the command so that it writes its output to a pipe. Open this
  926. // pipe with read text attribute so that we can read it
  927. // like a text file.
  928. if (getEspLogLevel()>LogNormal)
  929. {
  930. DBGLOG("command_line=<%s>", command_line);
  931. }
  932. if( (fp = popen( command_line, "r" )) == NULL )
  933. return -1;
  934. // Read pipe until end of file. End of file indicates that
  935. //the stream closed its standard out (probably meaning it
  936. //terminated).
  937. while ( !feof(fp) )
  938. if ( fgets( buffer, 128, fp) )
  939. response.append( buffer );
  940. if (getEspLogLevel()>LogNormal)
  941. {
  942. DBGLOG("response=<%s>", response.str());
  943. }
  944. // Close pipe and print return value of CHKDSK.
  945. return pclose( fp );
  946. }
  947. 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)
  948. {
  949. #ifdef DETECT_WS_MC_MEM_LEAKS
  950. static bool firstTime = true;
  951. if (firstTime)
  952. {
  953. firstTime = false;
  954. unsigned t = setAllocHook(true);
  955. }
  956. #endif //DETECT_WS_MC_MEM_LEAKS
  957. int iRet = runCommand(context, address, configAddress, preflightCommand, user, password, sResponse);
  958. if (iRet == 0)
  959. {
  960. iRet = readMachineInfo(sResponse.str(), machineInfo);
  961. }
  962. #ifdef DETECT_WS_MC_MEM_LEAKS
  963. DBGLOG("Allocated=%d", setAllocHook(false));
  964. #endif //DETECT_WS_MC_MEM_LEAKS
  965. return iRet;
  966. }
  967. // the following method is invoked on worker threads of
  968. void Cws_machineEx::doGetMachineInfo(IEspContext& context, CMachineInfoThreadParam* pParam)
  969. {
  970. IEspMachineInfoEx* info = pParam->m_pMachineInfo;
  971. IEspMachineInfoEx* info1 = pParam->m_pMachineInfo1;
  972. StringBuffer& sSecurityString = pParam->m_sSecurityString;
  973. try
  974. {
  975. info->setAddress(pParam->m_sAddress.str());
  976. info->setConfigAddress(pParam->m_sConfigAddress.str());
  977. info->setProcessType(pParam->m_sProcessType.str());
  978. info->setComponentName( pParam->m_sCompName.str() );
  979. info->setComponentPath( pParam->m_sPath.str());
  980. char displayName[128];
  981. GetDisplayProcessName(pParam->m_sProcessType.str(), displayName);
  982. info->setDisplayType(displayName);
  983. if (pParam->m_bECLAgent)
  984. {
  985. info1->setAddress(pParam->m_sAddress.str());
  986. info1->setConfigAddress(pParam->m_sConfigAddress.str());
  987. info1->setProcessType("AgentExecProcess");
  988. info1->setComponentName( pParam->m_sCompName.str() );
  989. info1->setComponentPath( pParam->m_sPath.str());
  990. char displayName[128];
  991. GetDisplayProcessName("AgentExecProcess", displayName);
  992. info1->setDisplayType(displayName);
  993. }
  994. int iRet = 0;
  995. CMachineInfo machineInfo;
  996. StringBuffer preFlightCommand;
  997. if (m_useDefaultPIDFileName)
  998. {
  999. StringBuffer sBuf = pParam->m_sPath;
  1000. if (sBuf.charAt(sBuf.length() - 1) == '/')
  1001. sBuf.remove(sBuf.length()-1, 1);
  1002. preFlightCommand.appendf("sudo /sbin/preflight %s component", sBuf.str());
  1003. }
  1004. else
  1005. {
  1006. preFlightCommand.appendf("/%s/sbin/%s %s", m_environmentConfData.m_executionPath.str(), m_machineInfoFile.str(), m_environmentConfData.m_pidPath.str());
  1007. if (preFlightCommand.charAt(preFlightCommand.length() - 1) == '/')
  1008. preFlightCommand.remove(preFlightCommand.length()-1, 1);
  1009. preFlightCommand.appendf(" %s", pParam->m_sCompName.str());
  1010. if (!stricmp(pParam->m_sProcessType.str(), "ThorMasterProcess"))
  1011. preFlightCommand.append("_master");
  1012. else if (!stricmp(pParam->m_sProcessType.str(), "ThorSlaveProcess"))
  1013. preFlightCommand.append("_slave");
  1014. }
  1015. StringBuffer sResponse;
  1016. iRet = remoteGetMachineInfo(context, pParam->m_sAddress.str(), pParam->m_sConfigAddress.str(), preFlightCommand.str(), pParam->m_sUserName.str(), pParam->m_sPassword.str(), sResponse, machineInfo);
  1017. if (iRet != 0)
  1018. {
  1019. info->setDescription(sResponse.str());
  1020. if (pParam->m_bECLAgent)
  1021. info1->setDescription(sResponse.str());
  1022. }
  1023. else
  1024. {
  1025. IArrayOf<IEspProcessInfo> runningProcesses;
  1026. getRunningProcesses(context, pParam->m_sAddress.str(), pParam->m_sConfigAddress.str(), pParam->m_sUserName.str(), pParam->m_sPassword.str(), runningProcesses);
  1027. if (pParam->m_bGetStorageInfo)
  1028. {
  1029. IArrayOf<IEspStorageInfo> storageArray;
  1030. doGetStorageInfo(pParam, storageArray, machineInfo);
  1031. info->setStorage(storageArray);
  1032. if (pParam->m_bECLAgent)
  1033. info1->setStorage(storageArray);
  1034. storageArray.kill();
  1035. }
  1036. if (pParam->m_bGetProcessorInfo)
  1037. {
  1038. IArrayOf<IEspProcessorInfo> processorArray;
  1039. doGetProcessorInfo(pParam, processorArray, machineInfo);
  1040. info->setProcessors(processorArray);
  1041. if (pParam->m_bECLAgent)
  1042. info1->setProcessors(processorArray);
  1043. }
  1044. if (pParam->m_bGetSwInfo)
  1045. {
  1046. IArrayOf<IEspSWRunInfo> runArray;
  1047. doGetSWRunInfo(context, pParam, runArray, machineInfo, runningProcesses,
  1048. pParam->m_sProcessType.str(),
  1049. pParam->m_bFilterProcesses,
  1050. pParam->m_bMonitorDaliFileServer,
  1051. pParam->m_additionalProcesses);
  1052. info->setRunning(runArray);
  1053. if (pParam->m_bECLAgent)
  1054. info1->setRunning(runArray);
  1055. }
  1056. if (machineInfo.m_sComputerUptime.length() > 0)
  1057. {
  1058. info->setUpTime(machineInfo.m_sComputerUptime.str());
  1059. if (pParam->m_bECLAgent)
  1060. info1->setUpTime(machineInfo.m_sComputerUptime.str());
  1061. }
  1062. else
  1063. {
  1064. info->setUpTime("-");
  1065. if (pParam->m_bECLAgent)
  1066. info1->setUpTime("-");
  1067. }
  1068. pParam->addColumn("Up Time");
  1069. }
  1070. }
  1071. catch (IException* e)
  1072. {
  1073. StringBuffer sError;
  1074. e->errorMessage(sError);
  1075. e->Release();
  1076. info->setDescription(sError.str());
  1077. }
  1078. catch (const char* e)
  1079. {
  1080. info->setDescription(e);
  1081. }
  1082. catch (...)
  1083. {
  1084. info->setDescription("Unknown exception!");
  1085. }
  1086. }
  1087. void Cws_machineEx::doGetSecurityString(const char* address, StringBuffer& securityString)
  1088. {
  1089. //another client (like configenv) may have updated the constant environment and we got notified
  1090. //(thanks to our subscription) so reload it
  1091. m_envFactory->validateCache();
  1092. securityString.clear();
  1093. Owned<IConstEnvironment> constEnv = getConstEnvironment();
  1094. Owned<IConstMachineInfo> machine = constEnv->getMachineByAddress(address);
  1095. if (machine)
  1096. {
  1097. Owned<IConstDomainInfo> domain = machine->getDomain();
  1098. if (domain)
  1099. {
  1100. StringBufferAdaptor strval(securityString);
  1101. domain->getSnmpSecurityString(strval);
  1102. }
  1103. }
  1104. }
  1105. IPropertyTree* Cws_machineEx::getComponent(const char* compType, const char* compName)
  1106. {
  1107. StringBuffer xpath;
  1108. xpath.append("Software/").append(compType).append("[@name='").append(compName).append("']");
  1109. m_envFactory->validateCache();
  1110. Owned<IConstEnvironment> constEnv = getConstEnvironment();
  1111. Owned<IPropertyTree> pEnvRoot = &constEnv->getPTree();
  1112. return pEnvRoot->getPropTree( xpath.str() );
  1113. }
  1114. void Cws_machineEx::getAccountAndPlatformInfo(const char* address, StringBuffer& userId,
  1115. StringBuffer& password, bool& bLinux)
  1116. {
  1117. m_envFactory->validateCache();
  1118. Owned<IConstEnvironment> constEnv = getConstEnvironment();
  1119. Owned<IConstMachineInfo> machine = constEnv->getMachineByAddress(address);
  1120. if (!machine && !stricmp(address, "."))
  1121. {
  1122. machine.setown(constEnv->getMachineByAddress("127.0.0.1"));
  1123. }
  1124. if (!machine)
  1125. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Machine %s is not defined in environment!", address);
  1126. bLinux = machine->getOS() == MachineOsLinux;
  1127. Owned<IConstDomainInfo> domain = machine->getDomain();
  1128. if (!domain)
  1129. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Machine %s does not have any domain information!", address);
  1130. userId.clear();
  1131. password.clear();
  1132. StringBufferAdaptor strval1(userId);
  1133. StringBufferAdaptor strval2(password);
  1134. domain->getAccountInfo(strval1, strval2);
  1135. StringBuffer domainName;
  1136. StringBufferAdaptor strval3(domainName);
  1137. domain->getName(strval3);
  1138. if ((machine->getOS() == MachineOsW2K) && domainName.length())
  1139. {
  1140. domainName.append('\\');
  1141. userId.insert(0, domainName);
  1142. }
  1143. }
  1144. void Cws_machineEx::determineRequredProcesses(CMachineInfoThreadParam* pParam,
  1145. const char* pszProcessType,
  1146. bool bMonitorDaliFileServer,
  1147. const StringArray& additionalProcesses,
  1148. set<string>& requiredProcesses)
  1149. {
  1150. StringBuffer xpath;
  1151. const char* pszOperatingSystem = pParam->m_operatingSystem == OS_Windows ? "Windows" : "Linux";
  1152. xpath.appendf("Platform[@name='%s']", pszOperatingSystem);
  1153. IPropertyTree* pOsSpecificFilters = m_processFilters->queryPropTree( xpath.str() );
  1154. if (!pOsSpecificFilters)
  1155. throw MakeStringException(ECLWATCH_INVALID_PROCESS_FILTER, "No process filters have been defined for %s!", pszOperatingSystem);
  1156. //create a set (sorted list that is easy to search into) of processes expected to run
  1157. //on this box
  1158. StringBuffer sProcessName;
  1159. //first collect all "common" processes that are required on any box irrespective of
  1160. //its type
  1161. StringBuffer xPath("ProcessFilter[@name='any']/Process");
  1162. Owned<IPropertyTreeIterator> iProcesses = pOsSpecificFilters->getElements(xPath.str());
  1163. ForEach (*iProcesses)
  1164. {
  1165. iProcesses->query().getProp("@name", sProcessName.clear());
  1166. sProcessName.toLowerCase().replaceString(".exe", "");
  1167. //if this process name is valid and either we are monitoring dali file server or
  1168. //(we are not monitoring that and) it is not that process then add it to list of required processes
  1169. if (m_useDefaultHPCCInit)
  1170. {
  1171. if (*sProcessName.str() && (bMonitorDaliFileServer || 0 != strcmp(sProcessName.str(), "dafilesrv")))
  1172. requiredProcesses.insert(sProcessName.str());
  1173. }
  1174. else
  1175. {
  1176. if (*sProcessName.str() && (bMonitorDaliFileServer || 0 != strcmp(sProcessName.str(), "dafilesrv")))
  1177. requiredProcesses.insert(sProcessName.str());
  1178. }
  1179. }
  1180. //insert all additional processes that may have been specified with the request
  1181. int len = additionalProcesses.length();
  1182. for (int i=0; i<len; i++)
  1183. requiredProcesses.insert(additionalProcesses.item(i));
  1184. //now collect all "box-specific" processes that are required to be running
  1185. //for eg. thorslave[.exe] on a thor slave box
  1186. if (pszProcessType && *pszProcessType)
  1187. {
  1188. xPath.clear().appendf("ProcessFilter[@name='%s']", pszProcessType);
  1189. IPropertyTree* pProcessFilterNode = pOsSpecificFilters->queryPropTree(xPath.str());
  1190. if (pProcessFilterNode)
  1191. {
  1192. pParam->m_bMultipleInstances = pParam->m_operatingSystem == OS_Linux && pProcessFilterNode->getPropBool("@multipleInstances", false);
  1193. StringBuffer strCompName(pParam->m_sCompName);
  1194. strCompName.trim();
  1195. Owned<IPropertyTreeIterator> iProcesses = pProcessFilterNode->getElements("Process");
  1196. ForEach (*iProcesses)
  1197. {
  1198. IPropertyTree* pProcess = &iProcesses->query();
  1199. bool bRemove = pProcess->getPropBool("@remove", false);
  1200. const char* sName = pProcess->queryProp("@name");
  1201. sProcessName.clear();
  1202. if (!strcmp(sName, "."))
  1203. sProcessName = pParam->m_sCompName;
  1204. else
  1205. sProcessName.append(sName);
  1206. if (bRemove)
  1207. sProcessName.toLowerCase().replaceString(".exe", "");
  1208. if (*sProcessName.str())
  1209. {
  1210. if (bRemove)
  1211. requiredProcesses.erase(sProcessName.str());
  1212. else
  1213. {
  1214. //support multithor: if this is a linux system and processtype is either a thor master or slave
  1215. if (!strncmp(pszProcessType, "Thor", 4) && pParam->m_operatingSystem != OS_Windows)
  1216. {
  1217. //lookup port from environment
  1218. Owned<IPropertyTree> pComponent = getComponent("ThorCluster", strCompName.str());
  1219. const bool bMaster = !strcmp(pszProcessType, "ThorMasterProcess");
  1220. StringBuffer szPort;
  1221. if (pComponent)
  1222. szPort.append(pComponent->queryProp( bMaster ? "@masterport" : "@slaveport"));
  1223. if (szPort.length() == 0)
  1224. szPort.appendf("%s", bMaster ? "6500" : "6600");
  1225. StringBuffer sPort(szPort);
  1226. sProcessName.append('_').append(sPort.trim().str());
  1227. }
  1228. requiredProcesses.insert(sProcessName.str());
  1229. }
  1230. }
  1231. }
  1232. }
  1233. }
  1234. }
  1235. char* Cws_machineEx::skipChar(const char* sBuf, char c)
  1236. {
  1237. char* pStr2 = (char*) strchr(sBuf, c);
  1238. if (pStr2)
  1239. {
  1240. while (pStr2[0] == c)
  1241. pStr2++;
  1242. }
  1243. return pStr2;
  1244. }
  1245. void Cws_machineEx::readRunningProcess(const char* lineBuf, IArrayOf<IEspProcessInfo>& runningProcesses)
  1246. {
  1247. if (strlen(lineBuf) < 1)
  1248. return;
  1249. int pid = -1;
  1250. char desc[256];
  1251. char param[4096];
  1252. char* pStr1 = (char*) lineBuf;
  1253. //skip UID
  1254. char* pStr2 = skipChar(pStr1, ' ');
  1255. if (!pStr2)
  1256. return;
  1257. //read PID
  1258. pStr1 = pStr2;
  1259. pStr2 = (char*) strchr(pStr1, ' ');
  1260. if (!pStr2)
  1261. return;
  1262. char id[32];
  1263. strncpy(id, pStr1, pStr2 - pStr1);
  1264. id[pStr2 - pStr1] = 0;
  1265. for (unsigned i = 0; i < strlen(id); i++)
  1266. {
  1267. if (!isdigit(id[i]))
  1268. return;
  1269. }
  1270. pid = atoi(id);
  1271. while (pStr2[0] == ' ')
  1272. pStr2++;
  1273. //skip PPID
  1274. pStr2 = skipChar(pStr2, ' ');
  1275. if (!pStr2)
  1276. return;
  1277. //skip C
  1278. pStr2 = skipChar(pStr2, ' ');
  1279. if (!pStr2)
  1280. return;
  1281. //skip STIME
  1282. pStr2 = skipChar(pStr2, ' ');
  1283. if (!pStr2)
  1284. return;
  1285. //skip TTY
  1286. pStr2 = skipChar(pStr2, ' ');
  1287. if (!pStr2)
  1288. return;
  1289. //skip TIME
  1290. pStr2 = skipChar(pStr2, ' ');
  1291. if (!pStr2)
  1292. return;
  1293. //Read CMD
  1294. bool bFound = false;
  1295. if (!bFound)
  1296. {
  1297. strcpy(param, pStr2);
  1298. pStr1 = pStr2;
  1299. pStr2 = (char*) strchr(pStr1, ' ');
  1300. if (!pStr2)
  1301. {
  1302. strcpy(desc, param);
  1303. }
  1304. else
  1305. {
  1306. if (pStr1[0] == '.' && pStr1[1] == '/')
  1307. pStr1 += 2;
  1308. strncpy(desc, pStr1, pStr2 - pStr1);
  1309. desc[pStr2 - pStr1] = 0;
  1310. }
  1311. if (!strcmp(desc, "ps"))
  1312. return;
  1313. }
  1314. //clean path, etc
  1315. StringBuffer descStr(desc);
  1316. if (descStr.charAt(0) == '[')
  1317. {
  1318. descStr.remove(0, 1);
  1319. descStr = descStr.reverse();
  1320. if (descStr.charAt(0) == ']')
  1321. descStr.remove(0, 1);
  1322. descStr = descStr.reverse();
  1323. }
  1324. else
  1325. {
  1326. descStr = descStr.reverse();
  1327. pStr1 = (char*) descStr.str();
  1328. pStr2 = (char*) strchr(pStr1, '/');
  1329. if (pStr2)
  1330. {
  1331. strncpy(desc, pStr1, pStr2 - pStr1);
  1332. desc[pStr2 - pStr1] = 0;
  1333. descStr.clear().append(desc);
  1334. }
  1335. descStr = descStr.reverse();
  1336. }
  1337. Owned<IEspProcessInfo> info = createProcessInfo("","");
  1338. info->setPID(pid);
  1339. info->setParameter(param);
  1340. info->setDescription(descStr.str());
  1341. runningProcesses.append(*info.getClear());
  1342. return;
  1343. }
  1344. void Cws_machineEx::getRunningProcesses(IEspContext& context, const char* address, const char* configAddress, const char* userId, const char* password, IArrayOf<IEspProcessInfo>& runningProcesses)
  1345. {
  1346. StringBuffer sResponse;
  1347. int iRet = runCommand(context, address, configAddress, "ps -ef", userId, password, sResponse);
  1348. if (iRet == 0)
  1349. {
  1350. bool bStop = false;
  1351. char* pStr = (char*) sResponse.str();
  1352. while (!bStop && pStr)
  1353. {
  1354. char lineBuf[4096];
  1355. //read a line
  1356. char* pStr1 = (char*) strchr(pStr, 0x0a);
  1357. if (!pStr1)
  1358. {
  1359. strcpy(lineBuf, pStr);
  1360. bStop = true;
  1361. }
  1362. else
  1363. {
  1364. strncpy(lineBuf, pStr, pStr1 - pStr);
  1365. lineBuf[pStr1 - pStr] = 0;
  1366. pStr = pStr1+1;
  1367. }
  1368. if (strlen(lineBuf) > 0)
  1369. {
  1370. readRunningProcess(lineBuf, runningProcesses);
  1371. }
  1372. }
  1373. }
  1374. return;
  1375. }
  1376. void Cws_machineEx::checkRunningProcessesByPID(IEspContext& context, CMachineInfoThreadParam* pParam, set<string>* pRequiredProcesses)
  1377. {
  1378. StringBuffer sCommand;
  1379. StringBuffer sResponse;
  1380. sCommand.appendf("ls %s", m_environmentConfData.m_pidPath.str());
  1381. int iRet = runCommand(context, pParam->m_sAddress.str(), pParam->m_sConfigAddress.str(), sCommand.str(), pParam->m_sUserName.str(), pParam->m_sPassword.str(), sResponse);
  1382. if (iRet == 0)
  1383. {
  1384. bool bStop = false;
  1385. char* pStr = (char*) sResponse.str();
  1386. while (!bStop)
  1387. {
  1388. char lineBuf[4096];
  1389. //read a line
  1390. char* pStr1 = (char*) strchr(pStr, 0x0a);
  1391. if (!pStr1)
  1392. {
  1393. strcpy(lineBuf, pStr);
  1394. bStop = true;
  1395. }
  1396. else
  1397. {
  1398. strncpy(lineBuf, pStr, pStr1 - pStr);
  1399. lineBuf[pStr1 - pStr] = 0;
  1400. pStr = pStr1+1;
  1401. }
  1402. if (strlen(lineBuf) > 0)
  1403. {
  1404. char* foundProcess = NULL;
  1405. set<string>::const_iterator it = pRequiredProcesses->begin();
  1406. set<string>::const_iterator iEnd = pRequiredProcesses->end();
  1407. for (; it != iEnd; it++) //add in sorted order simply by traversing the map
  1408. {
  1409. StringBuffer sName;
  1410. if (strchr(lineBuf, ' '))
  1411. {
  1412. sName.appendf(" %s.pid", (*it).c_str());
  1413. const char* pStr = strstr(lineBuf, sName);
  1414. if (pStr)
  1415. {
  1416. foundProcess = (char*) ((*it).c_str());
  1417. break;
  1418. }
  1419. }
  1420. else
  1421. {
  1422. sName.appendf("%s.pid", (*it).c_str());
  1423. if (!stricmp(lineBuf, sName.str()))
  1424. {
  1425. foundProcess = (char*) ((*it).c_str());
  1426. break;
  1427. }
  1428. }
  1429. }
  1430. if (foundProcess)
  1431. pRequiredProcesses->erase(foundProcess);
  1432. }
  1433. }
  1434. }
  1435. return;
  1436. }
  1437. void Cws_machineEx::enumerateRunningProcesses(CMachineInfoThreadParam* pParam,
  1438. IArrayOf<IEspProcessInfo>& runningProcesses,
  1439. bool bLinuxInstance,
  1440. bool bFilterProcesses,
  1441. map<string, StlLinked<IEspSWRunInfo> >* processMap,
  1442. map<int, StlLinked<IEspSWRunInfo> >& pidMap,
  1443. set<string>* pRequiredProcesses)
  1444. {
  1445. const bool bThorMasterOrSlave = !strncmp(pParam->m_sProcessType, "Thor", 4);
  1446. ForEachItemIn(k, runningProcesses)
  1447. {
  1448. IEspProcessInfo& processInfo = runningProcesses.item(k);
  1449. StringBuffer scmName = processInfo.getDescription();
  1450. StringBuffer scmPath; //keep this in scope since pszName may point to it
  1451. int pid = processInfo.getPID();
  1452. const char* pszName = scmName.str();
  1453. const char* pszPath = pszName;
  1454. if (bLinuxInstance)
  1455. {
  1456. //dafilesrv would probably be running from a global directory
  1457. //and not component's installation directory so ignore their paths
  1458. if (//pParam->m_bMultipleInstances &&
  1459. 0 != stricmp(pszName, "dafilesrv"))
  1460. {
  1461. scmPath.append(processInfo.getParameter());
  1462. pszPath = scmPath.str();
  1463. if (pszPath && *pszPath)
  1464. {
  1465. if (!strncmp(pszPath, "bash ", 5))
  1466. {
  1467. pszPath = scmPath.remove(0, 5).str();
  1468. if (!pszPath || !*pszPath)
  1469. continue;
  1470. }
  1471. //params typically is like "/c$/esp_dir/esp [parameters...]"
  1472. //so just pick the full path
  1473. const char* pch = strchr(pszPath, ' ');
  1474. if (pch)
  1475. {
  1476. scmPath.setLength( pch - pszPath );
  1477. pszPath = scmPath.str();
  1478. }
  1479. }
  1480. else
  1481. pszPath = scmName.insert(0, '[').append(']').str();
  1482. }
  1483. if (pRequiredProcesses)
  1484. {
  1485. const char* pszProcessName;
  1486. if (bThorMasterOrSlave && !strnicmp(pszName, "thor", 4))
  1487. {
  1488. const char* pch = strrchr(pszPath, '/');
  1489. pszProcessName = pch ? pch+1 : pszName;
  1490. }
  1491. else
  1492. {
  1493. const char* pszName0 = pParam->m_bMultipleInstances ? pszPath : pszName;
  1494. const char* pch = strrchr(pszName0, '/');
  1495. pszProcessName = pch ? pch+1 : pszName0;
  1496. }
  1497. pRequiredProcesses->erase(pszProcessName);
  1498. }
  1499. pszName = pszPath;
  1500. }
  1501. else
  1502. {
  1503. pszName = scmName.toLowerCase().replaceString(".exe", "");
  1504. if (pRequiredProcesses)
  1505. pRequiredProcesses->erase(pszName);
  1506. }
  1507. //skip processes starting with '[' character on linux unless we are not
  1508. //applying filters and have to return a complete list of processes.
  1509. //On windows, skip [system process] regardless.
  1510. if ((bLinuxInstance && (!bFilterProcesses || *pszName != '[')) ||
  1511. (!bLinuxInstance && *pszName != '['))
  1512. {
  1513. map<string, StlLinked<IEspSWRunInfo> >::iterator it;
  1514. if (processMap)
  1515. it = processMap->find(pszName);
  1516. StlLinked<IEspSWRunInfo> lptr;
  1517. if ( !processMap || it == processMap->end()) //not in the set
  1518. {
  1519. Owned<IEspSWRunInfo> info = static_cast<IEspSWRunInfo*>(new CSWRunInfo(""));
  1520. info->setName(pszName);
  1521. info->setInstances(1);
  1522. lptr = info.get();
  1523. if (processMap)
  1524. processMap->insert(pair<string, StlLinked<IEspSWRunInfo> >(pszName, lptr));
  1525. }
  1526. else
  1527. {
  1528. const StlLinked<IEspSWRunInfo>& linkedPtr = (*it).second;
  1529. lptr = linkedPtr;
  1530. lptr->setInstances( lptr->getInstances() + 1);
  1531. }
  1532. pidMap.insert(pair<int, StlLinked<IEspSWRunInfo> >(pid, lptr));
  1533. }
  1534. }
  1535. }
  1536. void Cws_machineEx::doGetStorageInfo(CMachineInfoThreadParam* pParam, IArrayOf<IEspStorageInfo> &output,
  1537. CMachineInfo machineInfo)
  1538. {
  1539. ///const int mbyte = !strcmp(temp.str(), "FixedDisk") ? 1000*1000 : 1024*1024;
  1540. ///int units = storage->getUnits();
  1541. if (machineInfo.m_sSpace.length() < 1)
  1542. return;
  1543. char* pStr = (char*) machineInfo.m_sSpace.str();
  1544. while (pStr)
  1545. {
  1546. char buf[1024], title[1024];
  1547. char* pStr1 = (char*) strchr(pStr, 0x0a);
  1548. if (pStr1)
  1549. {
  1550. strncpy(buf, pStr, pStr1 - pStr);
  1551. buf[pStr1 - pStr] = 0;
  1552. pStr = pStr1+1;
  1553. }
  1554. else
  1555. {
  1556. strcpy(buf, pStr);
  1557. pStr = NULL;
  1558. }
  1559. if (strlen(buf) < 1)
  1560. continue;
  1561. __int64 available = 0;
  1562. __int64 total = 0;
  1563. int percentAvail = 0;
  1564. readSpace(buf, title, available, total, percentAvail);
  1565. if ((strlen(title) < 1) || (total < 1))
  1566. continue;
  1567. if (!excludePartition(title))
  1568. {
  1569. Owned<IEspStorageInfo> info = static_cast<IEspStorageInfo*>(new CStorageInfo(""));
  1570. pParam->addColumn( title );
  1571. info->setDescription(title);
  1572. info->setTotal(total);
  1573. info->setAvailable(available);
  1574. info->setPercentAvail(percentAvail);
  1575. output.append(*info.getLink());
  1576. }
  1577. }
  1578. }
  1579. void Cws_machineEx::doGetProcessorInfo(CMachineInfoThreadParam* pParam, IArrayOf<IEspProcessorInfo> &output,
  1580. CMachineInfo machineInfo)
  1581. {
  1582. pParam->addColumn("CPU Load");
  1583. int cpuLoad = 0;
  1584. if (machineInfo.m_sCPUIdle.length() > 0)
  1585. {
  1586. char* cpuIdle = (char*) machineInfo.m_sCPUIdle.str();
  1587. if (cpuIdle[strlen(cpuIdle) - 1] == '%')
  1588. cpuIdle[strlen(cpuIdle) - 1] = 0;
  1589. cpuLoad = 100-atoi(cpuIdle);
  1590. }
  1591. Owned<IEspProcessorInfo> info = static_cast<IEspProcessorInfo*>(new CProcessorInfo(""));
  1592. info->setLoad(cpuLoad);
  1593. output.append(*info.getLink());
  1594. }
  1595. void Cws_machineEx::doGetSWRunInfo(IEspContext& context, CMachineInfoThreadParam* pParam, IArrayOf<IEspSWRunInfo> &output,
  1596. CMachineInfo machineInfo, IArrayOf<IEspProcessInfo>& runningProcesses,
  1597. const char* pszProcessType, bool bFilterProcesses,
  1598. bool bMonitorDaliFileServer,
  1599. const StringArray& additionalProcesses)
  1600. {
  1601. map<string, StlLinked<IEspSWRunInfo> > processMap; //save only one description of each process
  1602. map<int, StlLinked<IEspSWRunInfo> > pidMap;
  1603. bool bLinuxInstance = pParam->m_operatingSystem == OS_Linux;
  1604. bool bAddColumn = false;
  1605. bool bDafilesrvDown = false;
  1606. if (bFilterProcesses)
  1607. {
  1608. bAddColumn = true;
  1609. if (!m_useDefaultHPCCInit)
  1610. {
  1611. set<string> requiredProcesses;
  1612. determineRequredProcesses( pParam, pszProcessType, bMonitorDaliFileServer, additionalProcesses,
  1613. requiredProcesses);
  1614. //now enumerate the processes running on this box and remove them from required processes
  1615. //ignoring any non-required process
  1616. if (runningProcesses.length() > 0)
  1617. {
  1618. enumerateRunningProcesses( pParam, runningProcesses, bLinuxInstance, true, NULL, pidMap, &requiredProcesses);
  1619. }
  1620. set<string>::const_iterator it = requiredProcesses.begin();
  1621. set<string>::const_iterator iEnd = requiredProcesses.end();
  1622. for (; it != iEnd; it++) //add in sorted order simply by traversing the map
  1623. {
  1624. const char* procName = (*it).c_str();
  1625. if (procName && *procName)
  1626. {
  1627. IEspSWRunInfo* info = static_cast<IEspSWRunInfo*>(new CSWRunInfo(""));
  1628. if (!stricmp(procName, "dafilesrv"))
  1629. bDafilesrvDown = true;
  1630. info->setName(procName);
  1631. info->setInstances(0);
  1632. output.append(*info);
  1633. }
  1634. }
  1635. }
  1636. }
  1637. else
  1638. {
  1639. if (pParam->m_operatingSystem == OS_Linux && pszProcessType && *pszProcessType)
  1640. {
  1641. StringBuffer xpath;
  1642. xpath.appendf("Platform[@name='Linux']/ProcessFilter[@name='%s']/@multipleInstances", pszProcessType);
  1643. pParam->m_bMultipleInstances = m_processFilters->getPropBool(xpath.str(), false);
  1644. }
  1645. if (runningProcesses.length() > 0)
  1646. {
  1647. bAddColumn = true;
  1648. enumerateRunningProcesses( pParam, runningProcesses, bLinuxInstance,
  1649. bFilterProcesses, &processMap, pidMap, NULL);
  1650. }
  1651. map<string, StlLinked<IEspSWRunInfo> >::const_iterator it;
  1652. map<string, StlLinked<IEspSWRunInfo> >::const_iterator iEnd = processMap.end();
  1653. if (!m_useDefaultHPCCInit)
  1654. {
  1655. set<string> requiredProcesses;
  1656. determineRequredProcesses( pParam, pszProcessType, bMonitorDaliFileServer, additionalProcesses,
  1657. requiredProcesses);
  1658. set<string>::const_iterator it1 = requiredProcesses.begin();
  1659. for (; it1 != requiredProcesses.end(); it1++) //add in sorted order simply by traversing the map
  1660. {
  1661. const char* procName = (*it1).c_str();
  1662. if (procName && *procName && !stricmp(procName, "dafilesrv"))
  1663. {
  1664. bDafilesrvDown = true;
  1665. }
  1666. }
  1667. for (it=processMap.begin(); it != iEnd; it++) //add in sorted order simply by traversing the map
  1668. {
  1669. Linked<IEspSWRunInfo> info( (*it).second );
  1670. const char* procName = info->getName();
  1671. if (procName && *procName && !stricmp(procName, "dafilesrv"))
  1672. {
  1673. bDafilesrvDown = false;
  1674. }
  1675. output.append( *info.getLink() );
  1676. }
  1677. }
  1678. else
  1679. {
  1680. for (it=processMap.begin(); it != iEnd; it++) //add in sorted order simply by traversing the map
  1681. {
  1682. Linked<IEspSWRunInfo> info( (*it).second );
  1683. output.append( *info.getLink() );
  1684. }
  1685. }
  1686. }
  1687. if (bAddColumn)
  1688. pParam->addColumn("Processes");
  1689. if (!bFilterProcesses)
  1690. {
  1691. if (pParam->m_operatingSystem == OS_Linux && pszProcessType && *pszProcessType)
  1692. {
  1693. StringBuffer xpath;
  1694. xpath.appendf("Platform[@name='Linux']/ProcessFilter[@name='%s']/@multipleInstances", pszProcessType);
  1695. pParam->m_bMultipleInstances = m_processFilters->getPropBool(xpath.str(), false);
  1696. }
  1697. }
  1698. pParam->addColumn("Condition");
  1699. pParam->addColumn("State");
  1700. pParam->addColumn("UpTime");
  1701. const char* procType = pParam->m_sProcessType.str();
  1702. IEspComponentInfo* pComponentInfo = &pParam->m_pMachineInfo->updateComponentInfo();
  1703. pComponentInfo->setCondition(-1);//failed to retrieve SNMP info - will get overwritten by walker callback, if successful
  1704. //The bDafilesrvDown is set only when used
  1705. if (!bDafilesrvDown && machineInfo.m_sID.length() > 0)
  1706. {
  1707. //conditions: unknown, normal, warning, minor, major, critical, fatal
  1708. pComponentInfo->setCondition( 1 );
  1709. pComponentInfo->setState(5);
  1710. if (machineInfo.m_sProcessUptime.length() > 0)
  1711. {
  1712. char day[1024];
  1713. char* pDay = (char*) machineInfo.m_sProcessUptime.str();
  1714. char* pTime = strchr(pDay, '-');
  1715. if (!pTime)
  1716. {
  1717. pComponentInfo->setUpTime( pDay );
  1718. }
  1719. else
  1720. {
  1721. strncpy(day, pDay, pTime - pDay);
  1722. day[pTime - pDay] = 0;
  1723. StringBuffer upTime;
  1724. upTime.appendf("%s days %s", day, pTime+1);
  1725. pComponentInfo->setUpTime( upTime.str() );
  1726. }
  1727. }
  1728. }
  1729. else
  1730. {
  1731. pComponentInfo->setCondition(2); //Warnning
  1732. pComponentInfo->setState(0);
  1733. if (bFilterProcesses && (machineInfo.m_sID.length() < 1))
  1734. {
  1735. IEspSWRunInfo* info = static_cast<IEspSWRunInfo*>(new CSWRunInfo(""));
  1736. info->setName(pParam->m_sCompName.str());
  1737. info->setInstances(0);
  1738. output.append(*info);
  1739. }
  1740. }
  1741. if (pParam->m_bECLAgent)
  1742. {
  1743. IEspComponentInfo* pComponentInfo1 = &pParam->m_pMachineInfo1->updateComponentInfo();
  1744. pComponentInfo1->setCondition(pComponentInfo->getCondition()); //for AgentExec
  1745. pComponentInfo1->setState(pComponentInfo->getState()); //for AgentExec
  1746. pComponentInfo1->setUpTime(pComponentInfo->getUpTime()); //for AgentExec
  1747. pComponentInfo->setUpTime("-"); //for ECL Agent
  1748. }
  1749. }
  1750. //this method parses address info of the form "192.168.1.4-6:ThorSlaveProcess:thor1:2:path1"
  1751. //into respective components
  1752. void Cws_machineEx::parseProperties(const char* info, StringBuffer& processType, StringBuffer& sCompName,
  1753. OpSysType& os, StringBuffer& path)
  1754. {
  1755. StringArray sArray;
  1756. DelimToStringArray(info, sArray, ":");
  1757. unsigned int ordinality = sArray.ordinality();
  1758. if (ordinality == 0)
  1759. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Invalid address format '%s'.", info);
  1760. processType.clear().append( sArray.item(0) );
  1761. sCompName.clear();
  1762. path.clear();
  1763. os = OS_Windows;
  1764. if (ordinality > 1)
  1765. {
  1766. sCompName.append( sArray.item(1) );
  1767. if (ordinality > 2)
  1768. {
  1769. os = (OpSysType) atoi( sArray.item(2) );
  1770. if (ordinality > 3)
  1771. {
  1772. path.append( sArray.item(3) );
  1773. if (path.length())
  1774. {
  1775. char pat1, pat2;
  1776. char rep1, rep2;
  1777. if (os == OS_Linux)
  1778. {
  1779. pat1 = ':'; rep1 = '$';
  1780. pat2 = '\\';rep2 = '/';
  1781. }
  1782. else
  1783. {
  1784. pat1 = '$'; rep1 = ':';
  1785. pat2 = '/';rep2 = '\\';
  1786. }
  1787. path.replace( pat1, rep1 );
  1788. path.replace( pat2, rep2 );
  1789. const char* pszPath = path.str();
  1790. if (os == OS_Linux && *pszPath != '/')
  1791. {
  1792. path.insert(0, '/');
  1793. pszPath = path.str();
  1794. }
  1795. if (*(pszPath + path.length()-1) != rep2)
  1796. path.append(rep2);
  1797. }
  1798. }
  1799. }
  1800. }
  1801. }
  1802. void Cws_machineEx::getTimeStamp(char* timeStamp)
  1803. {
  1804. //set time stamp in the result for this machine
  1805. time_t tNow;
  1806. time(&tNow);
  1807. #ifdef _WIN32
  1808. struct tm *ltNow;
  1809. ltNow = localtime(&tNow);
  1810. strftime(timeStamp, 32, "%m/%d/%y %H:%M:%S", ltNow);
  1811. #else
  1812. struct tm ltNow;
  1813. localtime_r(&tNow, &ltNow);
  1814. strftime(timeStamp, 32, "%m/%d/%y %H:%M:%S", &ltNow);
  1815. #endif
  1816. }
  1817. int Cws_machineEx::lookupSnmpComponentIndex(const StringBuffer& sProcessType)
  1818. {
  1819. map<string, int>::const_iterator it = s_processTypeToSnmpIdMap.find( sProcessType.str() );
  1820. return (it != s_processTypeToSnmpIdMap.end()) ? (*it).second : -1;
  1821. }
  1822. const char* Cws_machineEx::lookupProcessname(const StringBuffer& sProcessType)
  1823. {
  1824. map<string, const char*>::const_iterator it = s_processTypeToProcessMap.find( sProcessType.str() );
  1825. return (it != s_processTypeToProcessMap.end()) ? (*it).second : "";
  1826. }
  1827. //---------------------------------------------------------------------------
  1828. // GetDisplayProcessName
  1829. //---------------------------------------------------------------------------
  1830. const char* Cws_machineEx::GetDisplayProcessName(const char* processName, char* buf)
  1831. {
  1832. //produces "LDAPServerProcess" as "LDAP Server" and "EspService" as "Esp Service", etc.
  1833. const char* begin = buf;
  1834. const char* end = strstr(processName, "Process");
  1835. if (!end)
  1836. end = processName + strlen(processName);
  1837. *buf++ = *processName++;
  1838. bool bLower = false;
  1839. while (processName < end)
  1840. {
  1841. char ch = *processName;
  1842. if (isupper(ch))
  1843. {
  1844. if (bLower || //last char was uppercase or the following character is lowercase?
  1845. ((processName+1 < end) && islower(*(processName+1))))
  1846. {
  1847. *buf++ = ' ';
  1848. }
  1849. bLower = false;
  1850. }
  1851. else
  1852. bLower = true;
  1853. *buf++ = *processName++;
  1854. }
  1855. *buf = '\0';
  1856. return begin;
  1857. }
  1858. bool Cws_machineEx::excludePartition(const char* partition) const
  1859. {
  1860. //first see if this partition is meant to be excluded as is - for instance
  1861. //if partition is /dev and /dev is one of the predefined partitions to be excluded
  1862. set<string>::const_iterator it = m_excludePartitions.find( partition );
  1863. set<string>::const_iterator itEnd = m_excludePartitions.end();
  1864. bool bFound = false;
  1865. if (it != itEnd)
  1866. bFound = true;
  1867. else
  1868. {
  1869. //now check if /dev* is one of the partitions to be excluded
  1870. set<string>::const_iterator itBegin = m_excludePartitionPatterns.begin();
  1871. itEnd = m_excludePartitionPatterns.end();
  1872. unsigned int partitionLen = strlen(partition);
  1873. for (it=itBegin; it != itEnd; it++)
  1874. {
  1875. const string& pattern = *it;
  1876. if (bFound = ::WildMatch(partition, partitionLen, pattern.c_str(), pattern.length(), false))
  1877. break;
  1878. }
  1879. }
  1880. return bFound;
  1881. }
  1882. void Cws_machineEx::setAttPath(StringBuffer& Path,const char* PathToAppend,const char* AttName,const char* AttValue)
  1883. {
  1884. Path.append("/");
  1885. Path.append(PathToAppend);
  1886. Path.append("[@");
  1887. Path.append(AttName);
  1888. Path.append("=\"");
  1889. Path.append(AttValue);
  1890. Path.append("\"]");
  1891. }
  1892. int Cws_machineEx::checkProcess(const char* type, const char* name, StringArray& typeArray, StringArray& nameArray)
  1893. {
  1894. int pos = -1;
  1895. if (!type || !*type || !name || !*name)
  1896. return pos;
  1897. int count = nameArray.ordinality();
  1898. if (count < 1)
  1899. return pos;
  1900. int i = 0;
  1901. while (i < count)
  1902. {
  1903. const char* name0 = nameArray.item(i);
  1904. const char* type0 = typeArray.item(i);
  1905. if (type0 && !strcmp(type, type0) && name0 && !strcmp(name, name0))
  1906. {
  1907. pos = i;
  1908. break;
  1909. }
  1910. i++;
  1911. }
  1912. return pos;
  1913. }
  1914. void Cws_machineEx::getMachineList(IConstEnvironment* constEnv, IPropertyTree* envRoot, const char* machineName,
  1915. const char* machineType, const char* status, const char* directory,
  1916. StringArray& processAddresses,
  1917. set<string>* pMachineNames/*=NULL*/)
  1918. {
  1919. StringBuffer directoryStr = directory;
  1920. Owned<IPropertyTreeIterator> machines= envRoot->getElements(machineType);
  1921. if (machines->first())
  1922. {
  1923. do
  1924. {
  1925. StringArray machineInstance;
  1926. IPropertyTree &machine = machines->query();
  1927. const char* computerName = machine.queryProp("@computer");
  1928. if (!computerName || !*computerName)
  1929. {
  1930. Owned<IPropertyTreeIterator> instances= machine.getElements("Instance");
  1931. if (instances->first())
  1932. {
  1933. do
  1934. {
  1935. IPropertyTree &instance = instances->query();
  1936. computerName = instance.queryProp("@computer");
  1937. if (!computerName || !*computerName)
  1938. continue;
  1939. if (directoryStr.length() < 1)
  1940. directoryStr.append(instance.queryProp("@directory"));
  1941. machineInstance.append(computerName);
  1942. } while (instances->next());
  1943. }
  1944. }
  1945. else
  1946. {
  1947. machineInstance.append(computerName);
  1948. }
  1949. if (machineInstance.length() < 1)
  1950. continue;
  1951. for (unsigned i = 0; i < machineInstance.length(); i++)
  1952. {
  1953. const char* name0 = machineInstance.item(i);
  1954. if (pMachineNames)//caller wishes us to avoid inserting duplicate entries for machines
  1955. {
  1956. if (pMachineNames->find(name0) != pMachineNames->end())
  1957. continue;
  1958. pMachineNames->insert(name0);
  1959. }
  1960. StringBuffer processAddress, name, netAddress, configNetAddress, os;
  1961. if (machineName && *machineName)
  1962. name.append(machineName);
  1963. else
  1964. name.append(name0);
  1965. Owned<IConstMachineInfo> pMachineInfo = constEnv->getMachine(name0);
  1966. if (pMachineInfo.get())
  1967. {
  1968. SCMStringBuffer ep;
  1969. pMachineInfo->getNetAddress(ep);
  1970. const char* ip = ep.str();
  1971. if (!ip || stricmp(ip, "."))
  1972. {
  1973. netAddress.append(ep.str());
  1974. configNetAddress.append(ep.str());
  1975. }
  1976. else
  1977. {
  1978. StringBuffer ipStr;
  1979. IpAddress ipaddr = queryHostIP();
  1980. ipaddr.getIpText(ipStr);
  1981. if (ipStr.length() > 0)
  1982. {
  1983. netAddress.append(ipStr.str());
  1984. configNetAddress.append(".");
  1985. }
  1986. }
  1987. os.append(pMachineInfo->getOS());
  1988. }
  1989. processAddress.appendf("%s|%s:%s:%s:%s:%s", netAddress.str(), configNetAddress.str(), machineType, name.str(), os.str(), directoryStr.str());
  1990. processAddresses.append(processAddress);
  1991. }
  1992. } while (machines->next());
  1993. }
  1994. return;
  1995. }
  1996. const char* Cws_machineEx::getProcessTypeFromMachineType(const char* machineType)
  1997. {
  1998. const char* processType = machineType;
  1999. if (!stricmp(machineType, eqThorMasterProcess) || !stricmp(machineType, eqThorSlaveProcess) || !stricmp(machineType, eqThorSpareProcess))
  2000. {
  2001. processType = eqThorCluster;
  2002. }
  2003. else if (!stricmp(machineType, "RoxieServerProcess") || !stricmp(machineType, "RoxieSlaveProcess"))
  2004. {
  2005. processType = eqRoxieCluster;
  2006. }
  2007. else if (!stricmp(machineType, "AgentExecProcess"))
  2008. {
  2009. processType = eqEclAgent;
  2010. }
  2011. return processType;
  2012. }
  2013. void Cws_machineEx::setTargetClusterInfo(IPropertyTree* pTargetClusterTree, IArrayOf<IEspMachineInfoEx>& machineArray, IArrayOf<IEspTargetClusterInfo>& targetClusterInfoList)
  2014. {
  2015. unsigned machineCount = machineArray.ordinality();
  2016. if (machineCount < 1)
  2017. return;
  2018. if (!pTargetClusterTree)
  2019. return;
  2020. Owned<IPropertyTreeIterator> targetClusters = pTargetClusterTree->getElements("TargetCluster");
  2021. ForEach(*targetClusters)
  2022. {
  2023. IPropertyTree& targetCluster = targetClusters->query();
  2024. StringBuffer targetName, targetType;
  2025. targetCluster.getProp("@Name", targetName);
  2026. targetCluster.getProp("@Type", targetType);
  2027. Owned<IEspTargetClusterInfo> targetClusterInfo = static_cast<IEspTargetClusterInfo*>(new CTargetClusterInfo(""));
  2028. targetClusterInfo->setName( targetName.str() );
  2029. targetClusterInfo->setType( targetType.str() );
  2030. IArrayOf<IEspMachineInfoEx> machineArrayNew;
  2031. Owned<IPropertyTreeIterator> processes = targetCluster.getElements("Process");
  2032. ForEach(*processes)
  2033. {
  2034. IPropertyTree& process = processes->query();
  2035. StringBuffer processName, processType;
  2036. process.getProp("@Name", processName);
  2037. process.getProp("@Type", processType);
  2038. for (unsigned i = 0; i < machineCount; i++)
  2039. {
  2040. IEspMachineInfoEx& machineInfoEx = machineArray.item(i);
  2041. const char* name = machineInfoEx.getComponentName();
  2042. const char* type = machineInfoEx.getProcessType();
  2043. if (!name || !type || stricmp(name, processName.str()) || stricmp(getProcessTypeFromMachineType(type), processType.str()))
  2044. continue;
  2045. Owned<IEspMachineInfoEx> pMachineInfo = static_cast<IEspMachineInfoEx*>(new CMachineInfoEx(""));
  2046. pMachineInfo->copy(machineInfoEx);
  2047. machineArrayNew.append(*pMachineInfo.getLink());
  2048. }
  2049. }
  2050. if (machineArrayNew.ordinality())
  2051. targetClusterInfo->setProcesses(machineArrayNew);
  2052. targetClusterInfoList.append(*targetClusterInfo.getLink());
  2053. }
  2054. }
  2055. void Cws_machineEx::getTargetClusterProcesses(StringArray& targetClusters, StringArray& processTypes,
  2056. StringArray& processNames, StringArray& processAddresses, IPropertyTree* pTargetClusterTree)
  2057. {
  2058. unsigned ordinality= targetClusters.ordinality();
  2059. if (ordinality < 1)
  2060. return;
  2061. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  2062. Owned<IConstEnvironment> constEnv = envFactory->openEnvironmentByFile();
  2063. Owned<IPropertyTree> pEnvironmentRoot = &constEnv->getPTree();
  2064. if (!pEnvironmentRoot)
  2065. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information.");
  2066. IPropertyTree* pEnvironmentSoftware = pEnvironmentRoot->queryPropTree("Software");
  2067. if (!pEnvironmentSoftware)
  2068. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information.");
  2069. IPropertyTree* pEnvironmentDirectories = pEnvironmentSoftware->queryPropTree("Directories");
  2070. for (unsigned index=0; index<ordinality; index++)
  2071. {
  2072. char* clusterName = strdup( targetClusters.item(index) );
  2073. char type[1024];
  2074. char* pClusterName = strchr(clusterName, ':');
  2075. if (!pClusterName)
  2076. {
  2077. pClusterName = clusterName;
  2078. }
  2079. else
  2080. {
  2081. strncpy(type, clusterName, pClusterName - clusterName);
  2082. type[pClusterName - clusterName] = 0;
  2083. pClusterName++;
  2084. }
  2085. if (!pClusterName || !*pClusterName)
  2086. continue;
  2087. StringBuffer path;
  2088. path.appendf("Software/Topology/Cluster[@name='%s']", pClusterName);
  2089. IPropertyTree* pCluster = pEnvironmentRoot->queryPropTree(path.str());
  2090. if (!pCluster)
  2091. continue;
  2092. Owned<IPropertyTreeIterator> thorClusters= pCluster->getElements(eqThorCluster);
  2093. Owned<IPropertyTreeIterator> roxieClusters= pCluster->getElements(eqRoxieCluster);
  2094. Owned<IPropertyTreeIterator> eclCCServerProcesses= pCluster->getElements(eqEclCCServer);
  2095. Owned<IPropertyTreeIterator> eclAgentProcesses= pCluster->getElements(eqEclAgent);
  2096. Owned<IPropertyTreeIterator> eclSchedulerProcesses= pCluster->getElements(eqEclScheduler);
  2097. if (type && !stricmp(type, eqThorCluster) && !thorClusters->first())
  2098. continue;
  2099. if (type && !stricmp(type, eqRoxieCluster) && !roxieClusters->first())
  2100. continue;
  2101. if (type && !stricmp(type, eqHoleCluster) && (roxieClusters->first() || thorClusters->first()))
  2102. continue;
  2103. IPropertyTree *pTargetClusterInfo = pTargetClusterTree->addPropTree("TargetCluster", createPTree("TargetCluster"));
  2104. if (!pTargetClusterInfo)
  2105. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree");
  2106. pTargetClusterInfo->setProp("@Name", pClusterName);
  2107. if (type && *type)
  2108. pTargetClusterInfo->setProp("@Type", type);
  2109. //Read Cluster process
  2110. if (thorClusters->first())
  2111. {
  2112. IArrayOf<IEspMachineInfoEx> machineArray;
  2113. do
  2114. {
  2115. IPropertyTree &thorCluster = thorClusters->query();
  2116. const char* process = thorCluster.queryProp("@process");
  2117. if (process && *process)
  2118. {
  2119. IPropertyTree *pThorClusterInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process"));
  2120. if (!pThorClusterInfo)
  2121. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree");
  2122. pThorClusterInfo->setProp("@Name", process);
  2123. pThorClusterInfo->setProp("@Type", eqThorCluster);
  2124. if (checkProcess(eqThorCluster, process, processTypes, processNames) < 0)
  2125. {
  2126. Owned<IEspMachineInfoEx> pMachineInfo = static_cast<IEspMachineInfoEx*>(new CMachineInfoEx(""));
  2127. pMachineInfo->setComponentName( process );
  2128. pMachineInfo->setProcessType(eqThorCluster);
  2129. machineArray.append(*pMachineInfo.getLink());
  2130. processTypes.append(eqThorCluster);
  2131. processNames.append(process);
  2132. StringBuffer dirStr;
  2133. if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqThorCluster, process, dirStr))
  2134. {
  2135. dirStr.clear().append(thorCluster.queryProp("@directory"));
  2136. }
  2137. path.clear().appendf("Software/%s[@name='%s']", eqThorCluster, process);
  2138. IPropertyTree* pClusterProcess = pEnvironmentRoot->queryPropTree(path.str());
  2139. if (pClusterProcess)
  2140. {
  2141. if (dirStr.length() < 1)
  2142. dirStr.append(pClusterProcess->queryProp("@directory"));
  2143. getMachineList(constEnv, pClusterProcess, process, eqThorMasterProcess, "", dirStr.str(), processAddresses);
  2144. getMachineList(constEnv, pClusterProcess, process, eqThorSlaveProcess, "", dirStr.str(), processAddresses);
  2145. getMachineList(constEnv, pClusterProcess, process, eqThorSpareProcess, "", dirStr.str(), processAddresses);
  2146. }
  2147. }
  2148. }
  2149. } while (thorClusters->next());
  2150. }
  2151. if (roxieClusters->first())
  2152. {
  2153. do {
  2154. IPropertyTree &roxieCluster = roxieClusters->query();
  2155. const char* process = roxieCluster.queryProp("@process");
  2156. if (process && *process)
  2157. {
  2158. IPropertyTree *pRoxieClusterInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process"));
  2159. if (!pRoxieClusterInfo)
  2160. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree");
  2161. pRoxieClusterInfo->setProp("@Name", process);
  2162. pRoxieClusterInfo->setProp("@Type", eqRoxieCluster);
  2163. if (checkProcess(eqRoxieCluster, process, processTypes, processNames) < 0)
  2164. {
  2165. processTypes.append(eqRoxieCluster);
  2166. processNames.append(process);
  2167. StringBuffer dirStr;
  2168. if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqRoxieCluster, process, dirStr))
  2169. {
  2170. dirStr.clear().append(roxieCluster.queryProp("@directory"));
  2171. }
  2172. path.clear().appendf("Software/%s[@name='%s']", eqRoxieCluster, process);
  2173. IPropertyTree* pClusterProcess = pEnvironmentRoot->queryPropTree(path.str());
  2174. if (pClusterProcess)
  2175. {
  2176. if (dirStr.length() < 1)
  2177. dirStr.append(pClusterProcess->queryProp("@directory"));
  2178. set<string> machineNames; //used for checking duplicates
  2179. getMachineList(constEnv, pClusterProcess, process, "RoxieServerProcess", "", dirStr.str(), processAddresses, &machineNames);
  2180. getMachineList(constEnv, pClusterProcess, process, "RoxieSlaveProcess", "", dirStr.str(), processAddresses, &machineNames);
  2181. }
  2182. }
  2183. }
  2184. } while (thorClusters->next());
  2185. }
  2186. //Read eclCCServer process
  2187. if (eclCCServerProcesses->first())
  2188. {
  2189. IPropertyTree &eclCCServerProcess = eclCCServerProcesses->query();
  2190. const char* process = eclCCServerProcess.queryProp("@process");
  2191. if (process && *process)
  2192. {
  2193. IPropertyTree *pEclCCServerInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process"));
  2194. if (!pEclCCServerInfo)
  2195. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree");
  2196. pEclCCServerInfo->setProp("@Name", process);
  2197. pEclCCServerInfo->setProp("@Type", eqEclCCServer);
  2198. if (checkProcess(eqEclCCServer, process, processTypes, processNames) < 0)
  2199. {
  2200. processTypes.append(eqEclCCServer);
  2201. processNames.append(process);
  2202. StringBuffer dirStr;
  2203. if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqEclCCServer, process, dirStr))
  2204. {
  2205. dirStr.clear().append(eclCCServerProcess.queryProp("@directory"));
  2206. }
  2207. getMachineList(constEnv, pEnvironmentSoftware, process, eqEclCCServer, "", dirStr.str(), processAddresses);
  2208. }
  2209. }
  2210. }
  2211. //Read eclAgent process
  2212. if (eclAgentProcesses->first())
  2213. {
  2214. IPropertyTree &eclAgentProcess = eclAgentProcesses->query();
  2215. const char* process = eclAgentProcess.queryProp("@process");
  2216. if (process && *process)
  2217. {
  2218. IPropertyTree *pEclAgentInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process"));
  2219. if (!pEclAgentInfo)
  2220. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree");
  2221. pEclAgentInfo->setProp("@Name", process);
  2222. pEclAgentInfo->setProp("@Type", eqEclAgent);
  2223. if (checkProcess(eqEclAgent, process, processTypes, processNames) < 0)
  2224. {
  2225. processTypes.append(eqEclAgent);
  2226. processNames.append(process);
  2227. StringBuffer dirStr;
  2228. if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqEclAgent, process, dirStr))
  2229. {
  2230. dirStr.clear().append(eclAgentProcess.queryProp("@directory"));
  2231. }
  2232. getMachineList(constEnv, pEnvironmentSoftware, process, eqEclAgent, "", dirStr.str(), processAddresses);
  2233. }
  2234. }
  2235. }
  2236. //Read eclScheduler process
  2237. if (eclSchedulerProcesses->first())
  2238. {
  2239. IPropertyTree &eclSchedulerProcess = eclSchedulerProcesses->query();
  2240. const char* process = eclSchedulerProcess.queryProp("@process");
  2241. if (process && *process)
  2242. {
  2243. IPropertyTree *pEclSchedulerInfo = pTargetClusterInfo->addPropTree("Process", createPTree("Process"));
  2244. if (!pEclSchedulerInfo)
  2245. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed in creating an XML tree");
  2246. pEclSchedulerInfo->setProp("@Name", process);
  2247. pEclSchedulerInfo->setProp("@Type", eqEclScheduler);
  2248. if (checkProcess(eqEclScheduler, process, processTypes, processNames) < 0)
  2249. {
  2250. processTypes.append(eqEclScheduler);
  2251. processNames.append(process);
  2252. StringBuffer dirStr;
  2253. if (pEnvironmentDirectories && !getConfigurationDirectory(pEnvironmentDirectories, "run", eqEclScheduler, process, dirStr))
  2254. {
  2255. dirStr.clear().append(eclSchedulerProcess.queryProp("@directory"));
  2256. }
  2257. getMachineList(constEnv, pEnvironmentSoftware, process, eqEclScheduler, "", dirStr.str(), processAddresses);
  2258. }
  2259. }
  2260. }
  2261. free(clusterName);
  2262. }
  2263. return;
  2264. }
  2265. bool Cws_machineEx::onGetTargetClusterInfo(IEspContext &context, IEspGetTargetClusterInfoRequest & req,
  2266. IEspGetTargetClusterInfoResponse & resp)
  2267. {
  2268. try
  2269. {
  2270. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  2271. throw MakeStringException(ECLWATCH_MACHINE_INFO_ACCESS_DENIED, "Failed to Get Machine Information. Permission denied.");
  2272. StringBuffer user;
  2273. StringBuffer pw;
  2274. context.getUserID(user);
  2275. context.getPassword(pw);
  2276. IEspRequestInfoStruct& reqInfo = resp.updateRequestInfo();
  2277. reqInfo.setGetProcessorInfo(req.getGetProcessorInfo());
  2278. reqInfo.setGetStorageInfo(req.getGetStorageInfo());
  2279. reqInfo.setGetSoftwareInfo(req.getGetSoftwareInfo());
  2280. reqInfo.setAutoRefresh( req.getAutoRefresh() );
  2281. reqInfo.setMemThreshold(req.getMemThreshold());
  2282. reqInfo.setDiskThreshold(req.getDiskThreshold());
  2283. reqInfo.setCpuThreshold(req.getCpuThreshold());
  2284. reqInfo.setMemThresholdType(req.getMemThresholdType());
  2285. reqInfo.setDiskThresholdType(req.getDiskThresholdType());
  2286. reqInfo.setApplyProcessFilter( req.getApplyProcessFilter() );
  2287. reqInfo.setAddProcessesToFilter( req.getAddProcessesToFilter() );
  2288. StringArray& targetClusters = req.getTargetClusters();
  2289. StringArray processTypes, processNames, processAddresses;
  2290. Owned<IPropertyTree> pTargetClusterTree = createPTreeFromXMLString("<Root/>");
  2291. getTargetClusterProcesses(targetClusters, processTypes, processNames, processAddresses, pTargetClusterTree);
  2292. if (processAddresses.ordinality())
  2293. {
  2294. IArrayOf<IEspMachineInfoEx> machineArray;
  2295. StringArray columnArray;
  2296. RunMachineQuery(context, processAddresses,reqInfo,machineArray,columnArray);
  2297. resp.setColumns( columnArray );
  2298. if (machineArray.ordinality())
  2299. {
  2300. IArrayOf<IEspTargetClusterInfo> targetClusterInfoList;
  2301. setTargetClusterInfo(pTargetClusterTree, machineArray, targetClusterInfoList);
  2302. resp.setTargetClusterInfoList(targetClusterInfoList);
  2303. }
  2304. }
  2305. char timeStamp[32];
  2306. getTimeStamp(timeStamp);
  2307. resp.setTimeStamp( timeStamp );
  2308. }
  2309. catch(IException* e)
  2310. {
  2311. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2312. }
  2313. return true;
  2314. }