ws_machineService.cpp 94 KB

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