ws_machineService.cpp 95 KB

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