ws_smcService.cpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #pragma warning (disable : 4786)
  14. #include "build-config.h"
  15. #ifdef _USE_OPENLDAP
  16. #include "ldapsecurity.ipp"
  17. #endif
  18. #include "ws_smcService.hpp"
  19. #include "wshelpers.hpp"
  20. #include "dalienv.hpp"
  21. #include "WUWrapper.hpp"
  22. #include "wujobq.hpp"
  23. #include "dfuwu.hpp"
  24. #include "exception_util.hpp"
  25. #include "roxiecontrol.hpp"
  26. static const char* FEATURE_URL = "SmcAccess";
  27. const char* THORQUEUE_FEATURE = "ThorQueueAccess";
  28. static const char* ROXIE_CONTROL_URL = "RoxieControlAccess";
  29. const char* PERMISSIONS_FILENAME = "espsmc_permissions.xml";
  30. void AccessSuccess(IEspContext& context, char const * msg,...) __attribute__((format(printf, 2, 3)));
  31. void AccessSuccess(IEspContext& context, char const * msg,...)
  32. {
  33. StringBuffer buf;
  34. buf.appendf("User %s: ",context.queryUserId());
  35. va_list args;
  36. va_start(args, msg);
  37. buf.valist_appendf(msg, args);
  38. va_end(args);
  39. AUDIT(AUDIT_TYPE_ACCESS_SUCCESS,buf.str());
  40. }
  41. void AccessFailure(IEspContext& context, char const * msg,...) __attribute__((format(printf, 2, 3)));
  42. void AccessFailure(IEspContext& context, char const * msg,...)
  43. {
  44. StringBuffer buf;
  45. buf.appendf("User %s: ",context.queryUserId());
  46. va_list args;
  47. va_start(args, msg);
  48. buf.valist_appendf(msg, args);
  49. va_end(args);
  50. AUDIT(AUDIT_TYPE_ACCESS_FAILURE,buf.str());
  51. }
  52. struct QueueWrapper
  53. {
  54. QueueWrapper(const char* targetName, const char* queueExt)
  55. {
  56. StringBuffer name;
  57. name.append(targetName).append('.').append(queueExt);
  58. queue.setown(createJobQueue(name.str()));
  59. }
  60. QueueWrapper(const char* queueName)
  61. {
  62. queue.setown(createJobQueue(queueName));
  63. }
  64. operator IJobQueue*() { return queue.get(); }
  65. IJobQueue* operator->() { return queue.get(); }
  66. Owned<IJobQueue> queue;
  67. };
  68. struct QueueLock
  69. {
  70. QueueLock(IJobQueue* q): queue(q) { queue->lock(); }
  71. ~QueueLock()
  72. {
  73. queue->unlock();
  74. }
  75. Linked<IJobQueue> queue;
  76. };
  77. void CWsSMCEx::init(IPropertyTree *cfg, const char *process, const char *service)
  78. {
  79. if (!daliClientActive())
  80. {
  81. ERRLOG("No Dali Connection Active.");
  82. throw MakeStringException(-1, "No Dali Connection Active. Please Specify a Dali to connect to in you configuration file");
  83. }
  84. m_BannerAction = 0;
  85. m_EnableChatURL = false;
  86. m_BannerSize = "4";
  87. m_BannerColor = "red";
  88. m_BannerScroll = "2";
  89. StringBuffer xpath;
  90. xpath.appendf("Software/EspProcess[@name='%s']/@portalurl", process);
  91. const char* portalURL = cfg->queryProp(xpath.str());
  92. if (portalURL && *portalURL)
  93. m_PortalURL.append(portalURL);
  94. }
  95. static void countProgress(IPropertyTree *t,unsigned &done,unsigned &total)
  96. {
  97. total = 0;
  98. done = 0;
  99. Owned<IPropertyTreeIterator> it = t->getElements("DFT/progress");
  100. ForEach(*it) {
  101. IPropertyTree &e=it->query();
  102. if (e.getPropInt("@done",0))
  103. done++;
  104. total++;
  105. }
  106. }
  107. struct CActiveWorkunitWrapper: public CActiveWorkunit
  108. {
  109. CActiveWorkunitWrapper(IEspContext &context, const char* wuid,unsigned index=0): CActiveWorkunit("","")
  110. {
  111. double version = context.getClientVersion();
  112. CWUWrapper wu(wuid, context);
  113. SCMStringBuffer state,owner,jobname;
  114. setWuid(wuid);
  115. if(index)
  116. state.s.append("queued(").append(index).append(")");
  117. else
  118. wu->getStateDesc(state);
  119. setState(state.str());
  120. setStateID(wu->getState());
  121. if ((version > 1.09) && (wu->getState() == WUStateFailed))
  122. setWarning("The job will ultimately not complete. Please check ECLAgent.");
  123. setOwner(wu->getUser(owner).str());
  124. setJobname(wu->getJobName(jobname).str());
  125. switch(wu->getPriority())
  126. {
  127. case PriorityClassHigh: setPriority("high"); break;
  128. default:
  129. case PriorityClassNormal: setPriority("normal"); break;
  130. case PriorityClassLow: setPriority("low"); break;
  131. }
  132. if (version > 1.08 && wu->isPausing())
  133. {
  134. setIsPausing(true);
  135. }
  136. }
  137. CActiveWorkunitWrapper(const char* wuid,const char* owner, const char* jobname, const char* state, const char* priority): CActiveWorkunit("","")
  138. {
  139. setWuid(wuid);
  140. setState(state);
  141. setOwner(owner);
  142. setJobname(jobname);
  143. setPriority(priority);
  144. }
  145. };
  146. bool CWsSMCEx::onIndex(IEspContext &context, IEspSMCIndexRequest &req, IEspSMCIndexResponse &resp)
  147. {
  148. resp.setRedirectUrl("/");
  149. return true;
  150. }
  151. static int stringcmp(const char **a, const char **b)
  152. {
  153. return strcmp(*a, *b);
  154. }
  155. bool isInWuList(IArrayOf<IEspActiveWorkunit>& aws, const char* wuid)
  156. {
  157. bool bFound = false;
  158. if (wuid && *wuid && (aws.length() > 0))
  159. {
  160. ForEachItemIn(k, aws)
  161. {
  162. IEspActiveWorkunit& wu = aws.item(k);
  163. const char* wuid0 = wu.getWuid();
  164. const char* server0 = wu.getServer();
  165. if (wuid0 && !strcmp(wuid0, wuid) && (!server0 || strcmp(server0, "ECLagent")))
  166. {
  167. bFound = true;
  168. break;
  169. }
  170. }
  171. }
  172. return bFound;
  173. }
  174. void addQueuedWorkUnits(const char *queueName, CJobQueueContents &contents, IArrayOf<IEspActiveWorkunit> &aws, IEspContext &context, const char *serverName, const char *instanceName)
  175. {
  176. Owned<IJobQueueIterator> iter = contents.getIterator();
  177. unsigned count=0;
  178. ForEach(*iter)
  179. {
  180. if (!isInWuList(aws, iter->query().queryWUID()))
  181. {
  182. try
  183. {
  184. Owned<IEspActiveWorkunit> wu(new CActiveWorkunitWrapper(context, iter->query().queryWUID(),++count));
  185. wu->setServer(serverName);
  186. wu->setInstance(instanceName); // JCSMORE In thor case at least, if queued it is unknown which instance it will run on..
  187. wu->setQueueName(queueName);
  188. aws.append(*wu.getLink());
  189. }
  190. catch (IException *e)
  191. {
  192. // JCSMORE->KWang what is this handling? Why would this succeeed and above fail?
  193. StringBuffer msg;
  194. Owned<IEspActiveWorkunit> wu(new CActiveWorkunitWrapper(iter->query().queryWUID(), "", "", e->errorMessage(msg).str(), "normal"));
  195. wu->setServer(serverName);
  196. wu->setInstance(instanceName);
  197. wu->setQueueName(queueName);
  198. aws.append(*wu.getLink());
  199. }
  200. }
  201. }
  202. }
  203. void CWsSMCEx::getQueueState(int runningJobsInQueue, StringBuffer& queueState, BulletType& bulletType)
  204. {
  205. bool queuePausedOrStopped = false;
  206. if ((queueState.length() > 0) && (strieq(queueState.str(),"stopped") || strieq(queueState.str(),"paused")))
  207. queuePausedOrStopped = true;
  208. else
  209. queueState.set("running");
  210. if (NotFound == runningJobsInQueue)
  211. {
  212. if (queuePausedOrStopped)
  213. bulletType = bulletWhite; //show bullet_white.png
  214. else
  215. bulletType = bulletError; //show bullet_error.png
  216. }
  217. else if (runningJobsInQueue > 0)
  218. {
  219. if (queuePausedOrStopped)
  220. bulletType = bulletOrange; //show bullet_orange.png
  221. else
  222. bulletType = bulletGreen; //show bullet_green.png
  223. }
  224. else if (queuePausedOrStopped)
  225. bulletType = bulletYellow; //show bullet_yellow.png
  226. return;
  227. }
  228. bool CWsSMCEx::onActivity(IEspContext &context, IEspActivityRequest &req, IEspActivityResponse& resp)
  229. {
  230. context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, true);
  231. try
  232. {
  233. const char* build_ver = getBuildVersion();
  234. resp.setBuild(build_ver);
  235. double version = context.getClientVersion();
  236. bool isSuperUser = true;
  237. #ifdef _USE_OPENLDAP
  238. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  239. if(secmgr && !secmgr->isSuperUser(context.queryUser()))
  240. isSuperUser = false;
  241. #endif
  242. if(isSuperUser && req.getFromSubmitBtn())
  243. {
  244. StringBuffer chatURLStr, bannerStr;
  245. const char* chatURL = req.getChatURL();
  246. const char* banner = req.getBannerContent();
  247. //Only display valid strings
  248. if (chatURL)
  249. {
  250. const char* pStr = chatURL;
  251. for (unsigned i = 0; i < strlen(chatURL); i++)
  252. {
  253. if ((pStr[0] > 31) && (pStr[0] < 127))
  254. chatURLStr.append(pStr[0]);
  255. pStr++;
  256. }
  257. }
  258. if (banner)
  259. {
  260. const char* pStr = banner;
  261. for (unsigned i = 0; i < strlen(banner); i++)
  262. {
  263. if ((pStr[0] > 31) && (pStr[0] < 127))
  264. bannerStr.append(pStr[0]);
  265. pStr++;
  266. }
  267. }
  268. chatURLStr.trim();
  269. bannerStr.trim();
  270. if (!req.getBannerAction_isNull() && req.getBannerAction() && (bannerStr.length() < 1))
  271. {
  272. throw MakeStringException(ECLWATCH_MISSING_BANNER_CONTENT, "If a Banner is enabled, the Banner content must be specified.");
  273. }
  274. if (!req.getEnableChatURL_isNull() && req.getEnableChatURL() && (chatURLStr.length() < 1))
  275. {
  276. throw MakeStringException(ECLWATCH_MISSING_CHAT_URL, "If a Chat is enabled, the Chat URL must be specified.");
  277. }
  278. m_ChatURL = chatURLStr;
  279. m_Banner = bannerStr;
  280. const char* bannerSize = req.getBannerSize();
  281. if (bannerSize && *bannerSize)
  282. m_BannerSize.clear().append(bannerSize);
  283. const char* bannerColor = req.getBannerColor();
  284. if (bannerColor && *bannerColor)
  285. m_BannerColor.clear().append(bannerColor);
  286. const char* bannerScroll = req.getBannerScroll();
  287. if (bannerScroll && *bannerScroll)
  288. m_BannerScroll.clear().append(bannerScroll);
  289. m_BannerAction = req.getBannerAction();
  290. if(!req.getEnableChatURL_isNull())
  291. m_EnableChatURL = req.getEnableChatURL();
  292. }
  293. if (version > 1.05)
  294. {
  295. if (version > 1.11)
  296. resp.setSuperUser(isSuperUser);
  297. resp.setShowBanner(m_BannerAction);
  298. resp.setShowChatURL(m_EnableChatURL);
  299. resp.setBannerContent(m_Banner.str());
  300. resp.setBannerSize(m_BannerSize.str());
  301. resp.setBannerColor(m_BannerColor.str());
  302. resp.setChatURL(m_ChatURL.str());
  303. if (version > 1.07)
  304. {
  305. resp.setBannerScroll(m_BannerScroll.str());
  306. }
  307. }
  308. Owned<IRemoteConnection> conn = querySDS().connect("/Status/Servers",myProcessSession(),RTM_LOCK_READ,30000);
  309. StringArray runningQueueNames;
  310. int runningJobsInQueue[256];
  311. for (int i = 0; i < 256; i++)
  312. runningJobsInQueue[i] = 0;
  313. IArrayOf<IEspActiveWorkunit> aws;
  314. if (conn.get())
  315. {
  316. Owned<IPropertyTreeIterator> it(conn->queryRoot()->getElements("Server"));
  317. ForEach(*it)
  318. {
  319. StringBuffer instance;
  320. StringBuffer qname;
  321. int serverID = -1;
  322. IPropertyTree& node = it->query();
  323. const char* name = node.queryProp("@name");
  324. if (name && *name)
  325. {
  326. node.getProp("@queue", qname);
  327. if (0 == stricmp("ThorMaster", name))
  328. {
  329. node.getProp("@thorname",instance);
  330. }
  331. else if (0 == stricmp(name, "ECLAgent"))
  332. {
  333. qname.append(name);
  334. }
  335. if ((instance.length()==0))
  336. {
  337. instance.append( !strcmp(name, "ECLagent") ? "ECL agent" : name);
  338. instance.append(" on ").append(node.queryProp("@node"));
  339. }
  340. }
  341. if (qname.length() > 0)
  342. {
  343. StringArray qlist;
  344. qlist.appendListUniq(qname.str(), ",");
  345. ForEachItemIn(q, qlist)
  346. {
  347. const char *_qname = qlist.item(q);
  348. serverID = runningQueueNames.find(_qname);
  349. if (NotFound == serverID)
  350. {
  351. serverID = runningQueueNames.ordinality(); // i.e. last
  352. runningQueueNames.append(_qname);
  353. }
  354. }
  355. }
  356. Owned<IPropertyTreeIterator> wuids(node.getElements("WorkUnit"));
  357. ForEach(*wuids)
  358. {
  359. const char* wuid=wuids->query().queryProp(NULL);
  360. if (!wuid)
  361. continue;
  362. try
  363. {
  364. IEspActiveWorkunit* wu=new CActiveWorkunitWrapper(context,wuid);
  365. const char* servername = node.queryProp("@name");
  366. const char *cluster = node.queryProp("Cluster");
  367. wu->setServer(servername);
  368. wu->setInstance(instance.str());
  369. StringBuffer thorQueue;
  370. if (cluster) // backward compat check.
  371. getClusterThorQueueName(thorQueue, cluster);
  372. else
  373. thorQueue.append(qname);
  374. serverID = runningQueueNames.find(thorQueue.str());
  375. wu->setQueueName(thorQueue);
  376. double version = context.getClientVersion();
  377. if (version > 1.01)
  378. {
  379. if (wu->getStateID() == WUStateRunning)
  380. {
  381. int sg_duration = node.getPropInt("@sg_duration", -1);
  382. const char* graph = node.queryProp("@graph");
  383. int subgraph = node.getPropInt("@subgraph", -1);
  384. if (subgraph > -1 && sg_duration > -1)
  385. {
  386. StringBuffer durationStr;
  387. StringBuffer subgraphStr;
  388. durationStr.appendf("%d min", sg_duration);
  389. subgraphStr.appendf("%d", subgraph);
  390. wu->setGraphName(graph);
  391. wu->setDuration(durationStr.str());
  392. wu->setGID(subgraphStr.str());
  393. }
  394. int memoryBlocked = node.getPropInt("@memoryBlocked ", 0);
  395. if (memoryBlocked != 0)
  396. {
  397. wu->setMemoryBlocked(1);
  398. }
  399. if (serverID > -1)
  400. {
  401. runningJobsInQueue[serverID]++;
  402. }
  403. }
  404. }
  405. aws.append(*wu);
  406. }
  407. catch (IException *e)
  408. {
  409. StringBuffer msg;
  410. Owned<IEspActiveWorkunit> wu(new CActiveWorkunitWrapper(wuid, "", "", e->errorMessage(msg).str(), "normal"));
  411. wu->setServer(node.queryProp("@name"));
  412. wu->setInstance(instance.str());
  413. wu->setQueueName(qname.str());
  414. aws.append(*wu.getLink());
  415. }
  416. }
  417. }
  418. }
  419. SecAccessFlags access;
  420. bool fullAccess=(context.authorizeFeature(THORQUEUE_FEATURE, access) && access>=SecAccess_Full);
  421. Owned<IRemoteConnection> connEnv = querySDS().connect("Environment", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  422. IPropertyTree* envRoot = connEnv->queryRoot();
  423. if (!envRoot)
  424. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO,"Failed to get environment information.");
  425. IArrayOf<IEspThorCluster> ThorClusters;
  426. IArrayOf<IEspHThorCluster> HThorClusters;
  427. IArrayOf<IEspRoxieCluster> RoxieClusters;
  428. CConstWUClusterInfoArray clusters;
  429. getEnvironmentClusterInfo(envRoot, clusters);
  430. ForEachItemIn(c, clusters)
  431. {
  432. IConstWUClusterInfo &cluster = clusters.item(c);
  433. SCMStringBuffer str;
  434. if (cluster.getThorProcesses().ordinality())
  435. {
  436. IEspThorCluster* returnCluster = new CThorCluster("","");
  437. returnCluster->setThorLCR(ThorLCRCluster == cluster.getPlatform() ? "withLCR" : "noLCR");
  438. str.clear();
  439. returnCluster->setClusterName(cluster.getName(str).str());
  440. str.clear();
  441. const char *queueName = cluster.getThorQueue(str).str();
  442. returnCluster->setQueueName(queueName);
  443. StringBuffer queueState;
  444. CJobQueueContents contents;
  445. Owned<IJobQueue> queue = createJobQueue(queueName);
  446. queue->copyItemsAndState(contents, queueState);
  447. addQueuedWorkUnits(queueName, contents, aws, context, "ThorMaster", NULL);
  448. BulletType bulletType = bulletGreen; //show bullet_green.png
  449. int serverID = runningQueueNames.find(queueName);
  450. int numRunningJobsInQueue = (NotFound != serverID) ? runningJobsInQueue[serverID] : -1;
  451. getQueueState(numRunningJobsInQueue, queueState, bulletType);
  452. returnCluster->setQueueStatus(queueState.str());
  453. if (version > 1.06)
  454. returnCluster->setQueueStatus2(bulletType);
  455. if (version > 1.10)
  456. returnCluster->setClusterSize(cluster.getSize());
  457. addToThorClusterList(ThorClusters, returnCluster, req.getSortBy(), req.getDescending());
  458. }
  459. if (version > 1.06)
  460. {
  461. str.clear();
  462. if (cluster.getRoxieProcess(str).length())
  463. {
  464. IEspRoxieCluster* returnCluster = new CRoxieCluster("","");
  465. str.clear();
  466. returnCluster->setClusterName(cluster.getName(str).str());
  467. str.clear();
  468. returnCluster->setQueueName(cluster.getAgentQueue(str).str());
  469. str.clear();
  470. const char *queueName = cluster.getAgentQueue(str).str();
  471. StringBuffer queueState;
  472. CJobQueueContents contents;
  473. Owned<IJobQueue> queue = createJobQueue(queueName);
  474. queue->copyItemsAndState(contents, queueState);
  475. addQueuedWorkUnits(queueName, contents, aws, context, "RoxieServer", NULL);
  476. BulletType bulletType = bulletGreen; //show bullet_green.png
  477. int serverID = runningQueueNames.find(queueName);
  478. int numRunningJobsInQueue = (NotFound != serverID) ? runningJobsInQueue[serverID] : -1;
  479. getQueueState(numRunningJobsInQueue, queueState, bulletType);
  480. returnCluster->setQueueStatus(queueState.str());
  481. returnCluster->setQueueStatus2(bulletType);
  482. if (version > 1.10)
  483. returnCluster->setClusterSize(cluster.getSize());
  484. addToRoxieClusterList(RoxieClusters, returnCluster, req.getSortBy(), req.getDescending());
  485. }
  486. }
  487. if (version > 1.11 && (cluster.getPlatform() == HThorCluster))
  488. {
  489. IEspHThorCluster* returnCluster = new CHThorCluster("","");
  490. str.clear();
  491. returnCluster->setClusterName(cluster.getName(str).str());
  492. str.clear();
  493. returnCluster->setQueueName(cluster.getAgentQueue(str).str());
  494. str.clear();
  495. const char *queueName = cluster.getAgentQueue(str).str();
  496. StringBuffer queueState;
  497. CJobQueueContents contents;
  498. Owned<IJobQueue> queue = createJobQueue(queueName);
  499. queue->copyItemsAndState(contents, queueState);
  500. addQueuedWorkUnits(queueName, contents, aws, context, "HThorServer", NULL);
  501. BulletType bulletType = bulletGreen; //show bullet_green.png
  502. int serverID = runningQueueNames.find(queueName);
  503. int numRunningJobsInQueue = (NotFound != serverID) ? runningJobsInQueue[serverID] : -1;
  504. getQueueState(numRunningJobsInQueue, queueState, bulletType);
  505. returnCluster->setQueueStatus(queueState.str());
  506. returnCluster->setQueueStatus2(bulletType);
  507. HThorClusters.append(*returnCluster);
  508. }
  509. }
  510. resp.setThorClusters(ThorClusters);
  511. if (version > 1.06)
  512. resp.setRoxieClusters(RoxieClusters);
  513. if (version > 1.10)
  514. {
  515. resp.setSortBy(req.getSortBy());
  516. resp.setDescending(req.getDescending());
  517. }
  518. if (version > 1.11)
  519. {
  520. resp.setHThorClusters(HThorClusters);
  521. if (fullAccess)
  522. resp.setAccessRight("Access_Full");
  523. }
  524. IArrayOf<IEspServerJobQueue> serverJobQueues;
  525. IArrayOf<IConstTpEclServer> eclccservers;
  526. CTpWrapper dummy;
  527. dummy.getTpEclCCServers(envRoot->queryBranch("Software"), eclccservers);
  528. ForEachItemIn(x1, eclccservers)
  529. {
  530. IConstTpEclServer& eclccserver = eclccservers.item(x1);
  531. const char* serverName = eclccserver.getName();
  532. if (!serverName || !*serverName)
  533. continue;
  534. Owned <IStringIterator> targetClusters = getTargetClusters(eqEclCCServer, serverName);
  535. if (!targetClusters->first())
  536. continue;
  537. ForEach (*targetClusters)
  538. {
  539. SCMStringBuffer targetCluster;
  540. targetClusters->str(targetCluster);
  541. StringBuffer queueName;
  542. StringBuffer queueState;
  543. CJobQueueContents contents;
  544. getClusterEclCCServerQueueName(queueName, targetCluster.str());
  545. Owned<IJobQueue> queue = createJobQueue(queueName);
  546. queue->copyItemsAndState(contents, queueState);
  547. unsigned count=0;
  548. Owned<IJobQueueIterator> iter = contents.getIterator();
  549. ForEach(*iter)
  550. {
  551. if (isInWuList(aws, iter->query().queryWUID()))
  552. continue;
  553. Owned<IEspActiveWorkunit> wu(new CActiveWorkunitWrapper(context, iter->query().queryWUID(),++count));
  554. wu->setServer("ECLCCserver");
  555. wu->setInstance(serverName);
  556. wu->setQueueName(queueName);
  557. aws.append(*wu.getLink());
  558. }
  559. addServerJobQueue(serverJobQueues, queueName, queueState.str(), serverName, "ECLCCserver");
  560. }
  561. }
  562. StringBuffer dirxpath;
  563. dirxpath.appendf("Software/%s", eqDfu);
  564. Owned<IPropertyTreeIterator> services = envRoot->getElements(dirxpath);
  565. if (services->first())
  566. {
  567. do
  568. {
  569. IPropertyTree &serviceTree = services->query();
  570. const char *queuename = serviceTree.queryProp("@queue");
  571. const char *serverName = serviceTree.queryProp("@name");
  572. if (queuename && *queuename)
  573. {
  574. StringArray queues;
  575. loop
  576. {
  577. StringAttr subq;
  578. const char *comma = strchr(queuename,',');
  579. if (comma)
  580. subq.set(queuename,comma-queuename);
  581. else
  582. subq.set(queuename);
  583. bool added;
  584. const char *s = strdup(subq.get());
  585. queues.bAdd(s, stringcmp, added);
  586. if (!added)
  587. free((void *)s);
  588. if (!comma)
  589. break;
  590. queuename = comma+1;
  591. if (!*queuename)
  592. break;
  593. }
  594. ForEachItemIn(q, queues)
  595. {
  596. const char *queueName = queues.item(q);
  597. StringAttrArray wulist;
  598. unsigned running = queuedJobs(queueName, wulist);
  599. ForEachItemIn(i, wulist)
  600. {
  601. const char *wuid = wulist.item(i).text.get();
  602. try
  603. {
  604. StringBuffer jname, uname, state;
  605. Owned<IConstDFUWorkUnit> wu = getDFUWorkUnitFactory()->openWorkUnit(wuid, false);
  606. if (wu)
  607. {
  608. wu->getUser(uname);
  609. wu->getJobName(jname);
  610. if (i<running)
  611. state.append("running");
  612. else
  613. state.append("queued");
  614. Owned<IEspActiveWorkunit> wu1(new CActiveWorkunitWrapper(wuid, uname.str(), jname.str(), state.str(), "normal"));
  615. wu1->setServer("DFUserver");
  616. wu1->setInstance(serverName);
  617. wu1->setQueueName(queueName);
  618. aws.append(*wu1.getLink());
  619. }
  620. }
  621. catch (IException *e)
  622. {
  623. StringBuffer msg;
  624. Owned<IEspActiveWorkunit> wu1(new CActiveWorkunitWrapper(wuid, "", "", e->errorMessage(msg).str(), "normal"));
  625. wu1->setServer("DFUserver");
  626. wu1->setInstance(serverName);
  627. wu1->setQueueName(queueName);
  628. aws.append(*wu1.getLink());
  629. }
  630. }
  631. addServerJobQueue(serverJobQueues, queueName, serverName, "DFUserver");
  632. }
  633. }
  634. } while (services->next());
  635. }
  636. resp.setRunning(aws);
  637. if (version > 1.03)
  638. resp.setServerJobQueues(serverJobQueues);
  639. IArrayOf<IEspDFUJob> jobs;
  640. conn.setown(querySDS().connect("DFU/RECOVERY",myProcessSession(),0, INFINITE));
  641. if (conn)
  642. {
  643. Owned<IPropertyTreeIterator> it(conn->queryRoot()->getElements("job"));
  644. ForEach(*it)
  645. {
  646. IPropertyTree &e=it->query();
  647. if (e.getPropBool("Running",false))
  648. {
  649. unsigned done;
  650. unsigned total;
  651. countProgress(&e,done,total);
  652. Owned<IEspDFUJob> job = new CDFUJob("","");
  653. job->setTimeStarted(e.queryProp("@time_started"));
  654. job->setDone(done);
  655. job->setTotal(total);
  656. StringBuffer cmd;
  657. cmd.append(e.queryProp("@command")).append(" ").append(e.queryProp("@command_parameters"));
  658. job->setCommand(cmd.str());
  659. jobs.append(*job.getLink());
  660. }
  661. }
  662. }
  663. resp.setDFUJobs(jobs);
  664. }
  665. catch(IException* e)
  666. {
  667. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  668. }
  669. return true;
  670. }
  671. void CWsSMCEx::addServerJobQueue(IArrayOf<IEspServerJobQueue>& jobQueues, const char* queueName, const char* serverName, const char* serverType)
  672. {
  673. if (!queueName || !*queueName || !serverName || !*serverName || !serverType || !*serverType)
  674. return;
  675. Owned<IEspServerJobQueue> jobQueue = createServerJobQueue("", "");
  676. jobQueue->setQueueName(queueName);
  677. jobQueue->setServerName(serverName);
  678. jobQueue->setServerType(serverType);
  679. Owned<IJobQueue> queue = createJobQueue(queueName);
  680. if (queue->stopped())
  681. jobQueue->setQueueStatus("stopped");
  682. else if (queue->paused())
  683. jobQueue->setQueueStatus("paused");
  684. else
  685. jobQueue->setQueueStatus("running");
  686. jobQueues.append(*jobQueue.getClear());
  687. }
  688. void CWsSMCEx::addServerJobQueue(IArrayOf<IEspServerJobQueue>& jobQueues, const char* queueName, const char* queueState, const char* serverName, const char* serverType)
  689. {
  690. if (!queueName || !*queueName || !serverName || !*serverName || !serverType || !*serverType)
  691. return;
  692. Owned<IEspServerJobQueue> jobQueue = createServerJobQueue("", "");
  693. jobQueue->setQueueName(queueName);
  694. jobQueue->setServerName(serverName);
  695. jobQueue->setServerType(serverType);
  696. if (queueState && (strieq(queueState,"stopped") || strieq(queueState,"paused")))
  697. jobQueue->setQueueStatus(queueState);
  698. else
  699. jobQueue->setQueueStatus("running");
  700. jobQueues.append(*jobQueue.getClear());
  701. }
  702. void CWsSMCEx::addToThorClusterList(IArrayOf<IEspThorCluster>& clusters, IEspThorCluster* cluster, const char* sortBy, bool descending)
  703. {
  704. if (clusters.length() < 1)
  705. {
  706. clusters.append(*cluster);
  707. return;
  708. }
  709. const char* clusterName = cluster->getClusterName();
  710. unsigned clusterSize = cluster->getClusterSize();
  711. bool clusterAdded = false;
  712. ForEachItemIn(i, clusters)
  713. {
  714. int strCmp = 0;
  715. IEspThorCluster& cluster1 = clusters.item(i);
  716. if (!sortBy || !*sortBy || strieq(sortBy, "name"))
  717. {
  718. strCmp = strcmp(cluster1.getClusterName(), clusterName);
  719. }
  720. else
  721. {//size
  722. //strCmp = cluster1.getClusterSize() - clusterSize;
  723. int si = cluster1.getClusterSize();
  724. strCmp = si - clusterSize;
  725. }
  726. if ((descending && (strCmp < 0)) || (!descending && (strCmp > 0)))
  727. {
  728. clusters.add(*cluster, i);
  729. clusterAdded = true;
  730. break;
  731. }
  732. }
  733. if (!clusterAdded)
  734. clusters.append(*cluster);
  735. return;
  736. }
  737. void CWsSMCEx::addToRoxieClusterList(IArrayOf<IEspRoxieCluster>& clusters, IEspRoxieCluster* cluster, const char* sortBy, bool descending)
  738. {
  739. if (clusters.length() < 1)
  740. {
  741. clusters.append(*cluster);
  742. return;
  743. }
  744. const char* clusterName = cluster->getClusterName();
  745. unsigned clusterSize = cluster->getClusterSize();
  746. bool clusterAdded = false;
  747. ForEachItemIn(i, clusters)
  748. {
  749. int strCmp = 0;
  750. IEspRoxieCluster& cluster1 = clusters.item(i);
  751. if (!sortBy || !*sortBy || strieq(sortBy, "name"))
  752. {
  753. strCmp = strcmp(cluster1.getClusterName(), clusterName);
  754. }
  755. else
  756. {//size
  757. strCmp = cluster1.getClusterSize() - clusterSize;
  758. }
  759. if ((descending && (strCmp < 0)) || (!descending && (strCmp > 0)))
  760. {
  761. clusters.add(*cluster, i);
  762. clusterAdded = true;
  763. break;
  764. }
  765. }
  766. if (!clusterAdded)
  767. clusters.append(*cluster);
  768. return;
  769. }
  770. void CWsSMCEx::addCapabilities(IPropertyTree* pFeatureNode, const char* access,
  771. IArrayOf<IEspCapability>& capabilities)
  772. {
  773. StringBuffer xpath(access);
  774. xpath.append("/Capability");
  775. Owned<IPropertyTreeIterator> it = pFeatureNode->getElements(xpath.str());
  776. ForEach(*it)
  777. {
  778. IPropertyTree* pCapabilityNode = &it->query();
  779. IEspCapability* pCapability = new CCapability("ws_smc");
  780. pCapability->setName( pCapabilityNode->queryProp("@name") );
  781. pCapability->setDescription( pCapabilityNode->queryProp("@description") );
  782. capabilities.append(*pCapability);
  783. }
  784. }
  785. static void checkAccess(IEspContext &context, const char* feature,int level)
  786. {
  787. if (!context.validateFeatureAccess(feature, level, false))
  788. throw MakeStringException(ECLWATCH_THOR_QUEUE_ACCESS_DENIED, "Failed to access the queue functions. Permission denied.");
  789. }
  790. bool CWsSMCEx::onMoveJobDown(IEspContext &context, IEspSMCJobRequest &req, IEspSMCJobResponse &resp)
  791. {
  792. try
  793. {
  794. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  795. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  796. QueueLock lock(queue);
  797. unsigned index=queue->findRank(req.getWuid());
  798. if(index<queue->ordinality())
  799. {
  800. IJobQueueItem * item0 = queue->getItem(index);
  801. IJobQueueItem * item = queue->getItem(index+1);
  802. if(item && item0 && (item0->getPriority() == item->getPriority()))
  803. queue->moveAfter(req.getWuid(),item->queryWUID());
  804. }
  805. AccessSuccess(context, "Changed job priority %s",req.getWuid());
  806. resp.setRedirectUrl("/WsSMC/");
  807. }
  808. catch(IException* e)
  809. {
  810. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  811. }
  812. return true;
  813. }
  814. bool CWsSMCEx::onMoveJobUp(IEspContext &context, IEspSMCJobRequest &req, IEspSMCJobResponse &resp)
  815. {
  816. try
  817. {
  818. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  819. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  820. QueueLock lock(queue);
  821. unsigned index=queue->findRank(req.getWuid());
  822. if(index>0 && index<queue->ordinality())
  823. {
  824. IJobQueueItem * item0 = queue->getItem(index);
  825. IJobQueueItem * item = queue->getItem(index-1);
  826. if(item && item0 && (item0->getPriority() == item->getPriority()))
  827. queue->moveBefore(req.getWuid(),item->queryWUID());
  828. }
  829. AccessSuccess(context, "Changed job priority %s",req.getWuid());
  830. resp.setRedirectUrl("/WsSMC/");
  831. }
  832. catch(IException* e)
  833. {
  834. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  835. }
  836. return true;
  837. }
  838. bool CWsSMCEx::onMoveJobBack(IEspContext &context, IEspSMCJobRequest &req, IEspSMCJobResponse &resp)
  839. {
  840. try
  841. {
  842. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  843. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  844. QueueLock lock(queue);
  845. unsigned index=queue->findRank(req.getWuid());
  846. if(index<queue->ordinality())
  847. {
  848. int priority0 = queue->getItem(index)->getPriority();
  849. unsigned biggestIndoxInSamePriority = index;
  850. unsigned nextIndex = biggestIndoxInSamePriority + 1;
  851. while (nextIndex<queue->ordinality())
  852. {
  853. IJobQueueItem * item = queue->getItem(nextIndex);
  854. if (priority0 != item->getPriority())
  855. {
  856. break;
  857. }
  858. biggestIndoxInSamePriority = nextIndex;
  859. nextIndex++;
  860. }
  861. if (biggestIndoxInSamePriority != index)
  862. {
  863. IJobQueueItem * item = queue->getItem(biggestIndoxInSamePriority);
  864. queue->moveAfter(req.getWuid(),item->queryWUID());
  865. }
  866. }
  867. AccessSuccess(context, "Changed job priority %s",req.getWuid());
  868. resp.setRedirectUrl("/WsSMC/");
  869. }
  870. catch(IException* e)
  871. {
  872. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  873. }
  874. return true;
  875. }
  876. bool CWsSMCEx::onMoveJobFront(IEspContext &context, IEspSMCJobRequest &req, IEspSMCJobResponse &resp)
  877. {
  878. try
  879. {
  880. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  881. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  882. QueueLock lock(queue);
  883. unsigned index=queue->findRank(req.getWuid());
  884. if(index>0 && index<queue->ordinality())
  885. {
  886. int priority0 = queue->getItem(index)->getPriority();
  887. unsigned smallestIndoxInSamePriority = index;
  888. int nextIndex = smallestIndoxInSamePriority - 1;
  889. while (nextIndex >= 0)
  890. {
  891. IJobQueueItem * item = queue->getItem(nextIndex);
  892. if (priority0 != item->getPriority())
  893. {
  894. break;
  895. }
  896. smallestIndoxInSamePriority = nextIndex;
  897. nextIndex--;
  898. }
  899. if (smallestIndoxInSamePriority != index)
  900. {
  901. IJobQueueItem * item = queue->getItem(smallestIndoxInSamePriority);
  902. queue->moveBefore(req.getWuid(),item->queryWUID());
  903. }
  904. }
  905. AccessSuccess(context, "Changed job priority %s",req.getWuid());
  906. resp.setRedirectUrl("/WsSMC/");
  907. }
  908. catch(IException* e)
  909. {
  910. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  911. }
  912. return true;
  913. }
  914. bool CWsSMCEx::onRemoveJob(IEspContext &context, IEspSMCJobRequest &req, IEspSMCJobResponse &resp)
  915. {
  916. try
  917. {
  918. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  919. secAbortWorkUnit(req.getWuid(), *context.querySecManager(), *context.queryUser());
  920. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  921. QueueLock lock(queue);
  922. unsigned index=queue->findRank(req.getWuid());
  923. if(index<queue->ordinality())
  924. {
  925. if(!queue->cancelInitiateConversation(req.getWuid()))
  926. throw MakeStringException(ECLWATCH_CANNOT_DELETE_WORKUNIT,"Failed to remove the workunit %s",req.getWuid());
  927. }
  928. AccessSuccess(context, "Removed job %s",req.getWuid());
  929. resp.setRedirectUrl("/WsSMC/");
  930. }
  931. catch(IException* e)
  932. {
  933. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  934. }
  935. return true;
  936. }
  937. bool CWsSMCEx::onStopQueue(IEspContext &context, IEspSMCQueueRequest &req, IEspSMCQueueResponse &resp)
  938. {
  939. try
  940. {
  941. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  942. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  943. queue->stop();
  944. AccessSuccess(context, "Stopped queue %s",req.getCluster());
  945. resp.setRedirectUrl("/WsSMC/");
  946. }
  947. catch(IException* e)
  948. {
  949. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  950. }
  951. return true;
  952. }
  953. bool CWsSMCEx::onResumeQueue(IEspContext &context, IEspSMCQueueRequest &req, IEspSMCQueueResponse &resp)
  954. {
  955. try
  956. {
  957. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  958. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  959. queue->resume();
  960. AccessSuccess(context, "Resumed queue %s",req.getCluster());
  961. resp.setRedirectUrl("/WsSMC/");
  962. }
  963. catch(IException* e)
  964. {
  965. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  966. }
  967. return true;
  968. }
  969. bool CWsSMCEx::onPauseQueue(IEspContext &context, IEspSMCQueueRequest &req, IEspSMCQueueResponse &resp)
  970. {
  971. try
  972. {
  973. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  974. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  975. queue->pause();
  976. AccessSuccess(context, "Paused queue %s",req.getCluster());
  977. resp.setRedirectUrl("/WsSMC/");
  978. }
  979. catch(IException* e)
  980. {
  981. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  982. }
  983. return true;
  984. }
  985. bool CWsSMCEx::onClearQueue(IEspContext &context, IEspSMCQueueRequest &req, IEspSMCQueueResponse &resp)
  986. {
  987. try
  988. {
  989. checkAccess(context,THORQUEUE_FEATURE,SecAccess_Full);
  990. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  991. {
  992. QueueLock lock(queue);
  993. for(unsigned i=0;i<queue->ordinality();i++)
  994. secAbortWorkUnit(queue->getItem(i)->queryWUID(), *context.querySecManager(), *context.queryUser());
  995. queue->clear();
  996. }
  997. AccessSuccess(context, "Cleared queue %s",req.getCluster());
  998. resp.setRedirectUrl("/WsSMC/");
  999. }
  1000. catch(IException* e)
  1001. {
  1002. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1003. }
  1004. return true;
  1005. }
  1006. bool CWsSMCEx::onSetJobPriority(IEspContext &context, IEspSMCPriorityRequest &req, IEspSMCPriorityResponse &resp)
  1007. {
  1008. try
  1009. {
  1010. Owned<IWorkUnitFactory> factory = getSecWorkUnitFactory(*context.querySecManager(), *context.queryUser());
  1011. Owned<IWorkUnit> lw = factory->updateWorkUnit(req.getWuid());
  1012. if(stricmp(req.getPriority(),"high")==0)
  1013. lw->setPriority(PriorityClassHigh);
  1014. else if(stricmp(req.getPriority(),"normal")==0)
  1015. lw->setPriority(PriorityClassNormal);
  1016. else if(stricmp(req.getPriority(),"low")==0)
  1017. lw->setPriority(PriorityClassLow);
  1018. // set job priority
  1019. int priority = lw->getPriorityValue();
  1020. Owned<IJobQueue> queue = createJobQueue(req.getQueueName());
  1021. QueueLock lock(queue);
  1022. queue->changePriority(req.getWuid(),priority);
  1023. resp.setRedirectUrl("/WsSMC/");
  1024. }
  1025. catch(IException* e)
  1026. {
  1027. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1028. }
  1029. return true;
  1030. }
  1031. bool CWsSMCEx::onGetThorQueueAvailability(IEspContext &context, IEspGetThorQueueAvailabilityRequest &req, IEspGetThorQueueAvailabilityResponse& resp)
  1032. {
  1033. try
  1034. {
  1035. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  1036. throw MakeStringException(ECLWATCH_SMC_ACCESS_DENIED, "Failed to get Thor Queue availability. Permission denied.");
  1037. StringArray thorNames, groupNames, targetNames, queueNames;
  1038. getEnvironmentThorClusterNames(thorNames, groupNames, targetNames, queueNames);
  1039. IArrayOf<IEspThorCluster> ThorClusters;
  1040. ForEachItemIn(x, thorNames)
  1041. {
  1042. const char* targetName = targetNames.item(x);
  1043. const char* queueName = queueNames.item(x);
  1044. IEspThorCluster* returnCluster = new CThorCluster("","");
  1045. returnCluster->setClusterName(targetName);
  1046. returnCluster->setQueueName(queueName);
  1047. Owned<IJobQueue> queue = createJobQueue(queueName);
  1048. if(queue->stopped())
  1049. returnCluster->setQueueStatus("stopped");
  1050. else if (queue->paused())
  1051. returnCluster->setQueueStatus("paused");
  1052. else
  1053. returnCluster->setQueueStatus("running");
  1054. unsigned enqueued=0;
  1055. unsigned connected=0;
  1056. unsigned waiting=0;
  1057. queue->getStats(connected,waiting,enqueued);
  1058. returnCluster->setQueueAvailable(waiting);
  1059. returnCluster->setJobsRunning(connected - waiting);
  1060. returnCluster->setJobsInQueue(enqueued);
  1061. ThorClusters.append(*returnCluster);
  1062. }
  1063. resp.setThorClusters(ThorClusters);
  1064. }
  1065. catch(IException* e)
  1066. {
  1067. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1068. }
  1069. return true;
  1070. }
  1071. bool CWsSMCEx::onSetBanner(IEspContext &context, IEspSetBannerRequest &req, IEspSetBannerResponse& resp)
  1072. {
  1073. try
  1074. {
  1075. #ifdef _USE_OPENLDAP
  1076. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  1077. if(!secmgr || !secmgr->isSuperUser(context.queryUser()))
  1078. throw MakeStringException(ECLWATCH_SUPER_USER_ACCESS_DENIED, "access denied, administrators only.");
  1079. #endif
  1080. StringBuffer chatURLStr, bannerStr;
  1081. const char* chatURL = req.getChatURL();
  1082. const char* banner = req.getBannerContent();
  1083. //Only display valid strings
  1084. if (chatURL)
  1085. {
  1086. const char* pStr = chatURL;
  1087. for (unsigned i = 0; i < strlen(chatURL); i++)
  1088. {
  1089. if ((pStr[0] > 31) && (pStr[0] < 127))
  1090. chatURLStr.append(pStr[0]);
  1091. pStr++;
  1092. }
  1093. }
  1094. if (banner)
  1095. {
  1096. const char* pStr = banner;
  1097. for (unsigned i = 0; i < strlen(banner); i++)
  1098. {
  1099. if ((pStr[0] > 31) && (pStr[0] < 127))
  1100. bannerStr.append(pStr[0]);
  1101. pStr++;
  1102. }
  1103. }
  1104. chatURLStr.trim();
  1105. bannerStr.trim();
  1106. if (!req.getBannerAction_isNull() && req.getBannerAction() && (bannerStr.length() < 1))
  1107. {
  1108. throw MakeStringException(ECLWATCH_MISSING_BANNER_CONTENT, "If a Banner is enabled, the Banner content must be specified.");
  1109. }
  1110. if (!req.getEnableChatURL_isNull() && req.getEnableChatURL() && (!req.getChatURL() || !*req.getChatURL()))
  1111. {
  1112. throw MakeStringException(ECLWATCH_MISSING_CHAT_URL, "If a Chat is enabled, the Chat URL must be specified.");
  1113. }
  1114. m_ChatURL = chatURLStr;
  1115. m_Banner = bannerStr;
  1116. const char* bannerSize = req.getBannerSize();
  1117. if (bannerSize && *bannerSize)
  1118. m_BannerSize.clear().append(bannerSize);
  1119. const char* bannerColor = req.getBannerColor();
  1120. if (bannerColor && *bannerColor)
  1121. m_BannerColor.clear().append(bannerColor);
  1122. const char* bannerScroll = req.getBannerScroll();
  1123. if (bannerScroll && *bannerScroll)
  1124. m_BannerScroll.clear().append(bannerScroll);
  1125. m_BannerAction = 0;
  1126. if(!req.getBannerAction_isNull())
  1127. m_BannerAction = req.getBannerAction();
  1128. m_EnableChatURL = 0;
  1129. if(!req.getEnableChatURL_isNull())
  1130. m_EnableChatURL = req.getEnableChatURL();
  1131. resp.setRedirectUrl("/WsSMC/Activity");
  1132. }
  1133. catch(IException* e)
  1134. {
  1135. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1136. }
  1137. return true;
  1138. }
  1139. bool CWsSMCEx::onNotInCommunityEdition(IEspContext &context, IEspNotInCommunityEditionRequest &req, IEspNotInCommunityEditionResponse &resp)
  1140. {
  1141. return true;
  1142. }
  1143. bool CWsSMCEx::onBrowseResources(IEspContext &context, IEspBrowseResourcesRequest & req, IEspBrowseResourcesResponse & resp)
  1144. {
  1145. try
  1146. {
  1147. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  1148. throw MakeStringException(ECLWATCH_SMC_ACCESS_DENIED, "Failed to Browse Resources. Permission denied.");
  1149. double version = context.getClientVersion();
  1150. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  1151. Owned<IConstEnvironment> constEnv = factory->openEnvironmentByFile();
  1152. //The resource files will be downloaded from the same box of ESP (not dali)
  1153. StringBuffer ipStr;
  1154. IpAddress ipaddr = queryHostIP();
  1155. ipaddr.getIpText(ipStr);
  1156. if (ipStr.length() > 0)
  1157. {
  1158. resp.setNetAddress(ipStr.str());
  1159. Owned<IConstMachineInfo> machine = constEnv->getMachineByAddress(ipStr.str());
  1160. if (machine)
  1161. {
  1162. int os = machine->getOS();
  1163. resp.setOS(os);
  1164. }
  1165. }
  1166. if (m_PortalURL.length() > 0)
  1167. resp.setPortalURL(m_PortalURL.str());
  1168. #ifndef USE_RESOURCE
  1169. if (version > 1.12)
  1170. resp.setUseResource(false);
  1171. #else
  1172. if (version > 1.12)
  1173. resp.setUseResource(true);
  1174. //Now, get a list of resources stored inside the ESP box
  1175. IArrayOf<IEspHPCCResourceRepository> resourceRepositories;
  1176. Owned<IPropertyTree> pEnvRoot = &constEnv->getPTree();
  1177. const char* ossInstall = pEnvRoot->queryProp("EnvSettings/path");
  1178. if (!ossInstall || !*ossInstall)
  1179. {
  1180. WARNLOG("Failed to get EnvSettings/Path in environment settings.");
  1181. return true;
  1182. }
  1183. StringBuffer path;
  1184. path.appendf("%s/componentfiles/files/downloads", ossInstall);
  1185. Owned<IFile> f = createIFile(path.str());
  1186. if(!f->exists() || !f->isDirectory())
  1187. {
  1188. WARNLOG("Invalid resource folder");
  1189. return true;
  1190. }
  1191. Owned<IDirectoryIterator> di = f->directoryFiles(NULL, false, true);
  1192. if(di.get() == NULL)
  1193. {
  1194. WARNLOG("Resource folder is empty.");
  1195. return true;
  1196. }
  1197. ForEach(*di)
  1198. {
  1199. if (!di->isDir())
  1200. continue;
  1201. StringBuffer folder, path0, tmpBuf;
  1202. di->getName(folder);
  1203. if (folder.length() == 0)
  1204. continue;
  1205. path0.appendf("%s/%s/description.xml", path.str(), folder.str());
  1206. Owned<IFile> f0 = createIFile(path0.str());
  1207. if(!f0->exists())
  1208. {
  1209. WARNLOG("Description file not found for %s", folder.str());
  1210. continue;
  1211. }
  1212. OwnedIFileIO rIO = f0->openShared(IFOread,IFSHfull);
  1213. if(!rIO)
  1214. {
  1215. WARNLOG("Failed to open the description file for %s", folder.str());
  1216. continue;
  1217. }
  1218. offset_t fileSize = f0->size();
  1219. tmpBuf.ensureCapacity((unsigned)fileSize);
  1220. tmpBuf.setLength((unsigned)fileSize);
  1221. size32_t nRead = rIO->read(0, (size32_t) fileSize, (char*)tmpBuf.str());
  1222. if (nRead != fileSize)
  1223. {
  1224. WARNLOG("Failed to read the description file for %s", folder.str());
  1225. continue;
  1226. }
  1227. Owned<IPropertyTree> desc = createPTreeFromXMLString(tmpBuf.str());
  1228. if (!desc)
  1229. {
  1230. WARNLOG("Invalid description file for %s", folder.str());
  1231. continue;
  1232. }
  1233. Owned<IPropertyTreeIterator> fileIterator = desc->getElements("file");
  1234. if (!fileIterator->first())
  1235. {
  1236. WARNLOG("Invalid description file for %s", folder.str());
  1237. continue;
  1238. }
  1239. IArrayOf<IEspHPCCResource> resourcs;
  1240. do {
  1241. IPropertyTree &fileItem = fileIterator->query();
  1242. const char* filename = fileItem.queryProp("filename");
  1243. if (!filename || !*filename)
  1244. continue;
  1245. const char* name0 = fileItem.queryProp("name");
  1246. const char* description0 = fileItem.queryProp("description");
  1247. const char* version0 = fileItem.queryProp("version");
  1248. Owned<IEspHPCCResource> onefile = createHPCCResource();
  1249. onefile->setFileName(filename);
  1250. if (name0 && *name0)
  1251. onefile->setName(name0);
  1252. if (description0 && *description0)
  1253. onefile->setDescription(description0);
  1254. if (version0 && *version0)
  1255. onefile->setVersion(version0);
  1256. resourcs.append(*onefile.getLink());
  1257. } while (fileIterator->next());
  1258. if (resourcs.ordinality())
  1259. {
  1260. StringBuffer path1;
  1261. path1.appendf("%s/%s", path.str(), folder.str());
  1262. Owned<IEspHPCCResourceRepository> oneRepository = createHPCCResourceRepository();
  1263. oneRepository->setName(folder.str());
  1264. oneRepository->setPath(path1.str());
  1265. oneRepository->setHPCCResources(resourcs);
  1266. resourceRepositories.append(*oneRepository.getLink());
  1267. }
  1268. }
  1269. if (resourceRepositories.ordinality())
  1270. resp.setHPCCResourceRepositories(resourceRepositories);
  1271. #endif
  1272. }
  1273. catch(IException* e)
  1274. {
  1275. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1276. }
  1277. return true;
  1278. }
  1279. int CWsSMCSoapBindingEx::onGetForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method)
  1280. {
  1281. try
  1282. {
  1283. if(stricmp(method,"NotInCommunityEdition")==0)
  1284. {
  1285. StringBuffer page, url, link;
  1286. request->getParameter("EEPortal", url);
  1287. if (url.length() > 0)
  1288. link.appendf("Further information can be found at <a href=\"%s\" target=\"_blank\">%s</a>.", url.str(), url.str());
  1289. page.append(
  1290. "<html>"
  1291. "<head>"
  1292. "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"
  1293. "<link rel=\"stylesheet\" type=\"text/css\" href=\"/esp/files/default.css\"/>"
  1294. "<link rel=\"stylesheet\" type=\"text/css\" href=\"/esp/files/yui/build/fonts/fonts-min.css\" />"
  1295. "<title>Advanced feature in Enterprise Edition</title>"
  1296. "</head>"
  1297. "<body>"
  1298. "<h3 style=\"text-align:centre;\">Advanced feature in the Enterprise Edition</h4>"
  1299. "<p style=\"text-align:centre;\">Support for this feature is coming soon. ");
  1300. if (link.length() > 0)
  1301. page.append(link.str());
  1302. page.append("</p></body>"
  1303. "</html>");
  1304. response->setContent(page.str());
  1305. response->setContentType("text/html");
  1306. response->send();
  1307. return 0;
  1308. }
  1309. else if(stricmp(method,"DisabledInThisVersion")==0)
  1310. {
  1311. StringBuffer page;
  1312. page.append(
  1313. "<html>"
  1314. "<head>"
  1315. "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"
  1316. "<link rel=\"stylesheet\" type=\"text/css\" href=\"/esp/files/default.css\"/>"
  1317. "<link rel=\"stylesheet\" type=\"text/css\" href=\"/esp/files/yui/build/fonts/fonts-min.css\" />"
  1318. "<title>Disabled Feature in This Version</title>"
  1319. "</head>"
  1320. "<body>"
  1321. "<h3 style=\"text-align:centre;\">Disabled Feature in This Version</h4>"
  1322. "<p style=\"text-align:centre;\">This feature is disabled in this version. ");
  1323. page.append("</p></body>"
  1324. "</html>");
  1325. response->setContent(page.str());
  1326. response->setContentType("text/html");
  1327. response->send();
  1328. return 0;
  1329. }
  1330. }
  1331. catch(IException* e)
  1332. {
  1333. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1334. }
  1335. return onGetForm(context, request, response, service, method);
  1336. }
  1337. inline const char *controlCmdMessage(int cmd)
  1338. {
  1339. switch (cmd)
  1340. {
  1341. case CRoxieControlCmd_ATTACH:
  1342. return "<control:unlockDali/>";
  1343. case CRoxieControlCmd_DETACH:
  1344. return "<control:lockDali/>";
  1345. case CRoxieControlCmd_RELOAD:
  1346. return "<control:reload/>";
  1347. case CRoxieControlCmd_STATE:
  1348. return "<control:state/>";
  1349. default:
  1350. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Unknown Roxie Control Command.");
  1351. }
  1352. return NULL;
  1353. }
  1354. bool CWsSMCEx::onRoxieControlCmd(IEspContext &context, IEspRoxieControlCmdRequest &req, IEspRoxieControlCmdResponse &resp)
  1355. {
  1356. if (!context.validateFeatureAccess(ROXIE_CONTROL_URL, SecAccess_Full, false))
  1357. throw MakeStringException(ECLWATCH_SMC_ACCESS_DENIED, "Cannot Access Roxie Control. Permission denied.");
  1358. const char *process = req.getProcessCluster();
  1359. if (!process || !*process)
  1360. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Process cluster not specified.");
  1361. const char *controlReq = controlCmdMessage(req.getCommand());
  1362. SocketEndpointArray addrs;
  1363. getRoxieProcessServers(process, addrs);
  1364. if (!addrs.length())
  1365. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Process cluster not found.");
  1366. Owned<IPropertyTree> controlResp = sendRoxieControlAllNodes(addrs.item(0), controlReq, true, req.getWait());
  1367. if (!controlResp)
  1368. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed to get control response from roxie.");
  1369. IArrayOf<IEspRoxieControlEndpointInfo> respEndpoints;
  1370. Owned<IPropertyTreeIterator> roxieEndpoints = controlResp->getElements("Endpoint");
  1371. ForEach(*roxieEndpoints)
  1372. {
  1373. IPropertyTree &roxieEndpoint = roxieEndpoints->query();
  1374. Owned<IEspRoxieControlEndpointInfo> respEndpoint = createRoxieControlEndpointInfo();
  1375. respEndpoint->setAddress(roxieEndpoint.queryProp("@ep"));
  1376. respEndpoint->setStatus(roxieEndpoint.queryProp("Status"));
  1377. if (roxieEndpoint.hasProp("Dali/@connected"))
  1378. respEndpoint->setAttached(roxieEndpoint.getPropBool("Dali/@connected"));
  1379. if (roxieEndpoint.hasProp("State/@hash"))
  1380. respEndpoint->setStateHash(roxieEndpoint.queryProp("State/@hash"));
  1381. respEndpoints.append(*respEndpoint.getClear());
  1382. }
  1383. resp.setEndpoints(respEndpoints);
  1384. return true;
  1385. }