deploy.cpp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  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. #include "deploy.hpp"
  14. #include "environment.hpp"
  15. #include "jptree.hpp"
  16. #include "jarray.hpp"
  17. #include "jexcept.hpp"
  18. #include "jencrypt.hpp"
  19. #include "xslprocessor.hpp"
  20. #include "DeploymentEngine.hpp"
  21. #include "ThorDeploymentEngine.hpp"
  22. #include "EspDeploymentEngine.hpp"
  23. #include "dalideploymentengine.hpp"
  24. #include "RoxieDeploymentEngine.hpp"
  25. #include "configgenengine.hpp"
  26. #include "espconfiggenengine.hpp"
  27. #include "thorconfiggenengine.hpp"
  28. //---------------------------------------------------------------------------
  29. // CEnvironmentDeploymentEngine
  30. //---------------------------------------------------------------------------
  31. class CEnvironmentDeploymentEngine : public CInterface, implements IEnvDeploymentEngine
  32. {
  33. public:
  34. IMPLEMENT_IINTERFACE;
  35. //---------------------------------------------------------------------------
  36. // CEnvironmentDeploymentEngine
  37. //---------------------------------------------------------------------------
  38. CEnvironmentDeploymentEngine(IConstEnvironment &environment, IDeploymentCallback& callback,
  39. IPropertyTree* pSelectedComponents)
  40. : m_environment(environment),
  41. m_transform(NULL),
  42. m_abort(false),
  43. m_espModuleCount(0),
  44. m_tempFileCount(0),
  45. m_bLinuxDeployment(false),
  46. m_bInteractiveMode(true)
  47. {
  48. m_pCallback.set(&callback);
  49. m_validateAllXsl.clear().append("validateAll.xsl");
  50. if (pSelectedComponents)
  51. {
  52. initXML(pSelectedComponents);
  53. Owned<IPropertyTreeIterator> it = pSelectedComponents->getElements("*");
  54. ForEach(*it)
  55. {
  56. IPropertyTree* pComponent = &it->query();
  57. IDeploymentEngine* pEngine = addProcess(pComponent->queryName(), pComponent->queryProp("@name"));
  58. Owned<IPropertyTreeIterator> iter = pComponent->getElements("*");
  59. if (iter->first())
  60. {
  61. pEngine->resetInstances();
  62. ForEach(*iter)
  63. {
  64. IPropertyTree* pChild = &iter->query();
  65. const char* tagName = pChild->queryName();
  66. const char* instName = pChild->queryProp("@name");
  67. pEngine->addInstance(tagName, instName);
  68. //determine if this is linux deployment
  69. if (!m_bLinuxDeployment)
  70. {
  71. const char* computer = pChild->queryProp("@computer");
  72. IConstMachineInfo* pMachine = environment.getMachine(computer);
  73. if (pMachine->getOS() == MachineOsLinux)
  74. m_bLinuxDeployment = true;
  75. }
  76. }
  77. }
  78. else if (!m_bLinuxDeployment)//another previously added engine already does not have linux instance
  79. {
  80. //some components like thor and hole clusters don't show their instances in the
  81. //deployment wizard so detect if they have any linux instance.
  82. const IArrayOf<IPropertyTree>& instances = pEngine->getInstances();
  83. if (instances.ordinality() > 0)
  84. {
  85. Owned<IConstMachineInfo> machine = m_environment.getMachine(instances.item(0).queryProp("@computer"));
  86. if (machine && machine->getOS() == MachineOsLinux)
  87. m_bLinuxDeployment = true;
  88. }
  89. }
  90. }
  91. }
  92. #ifdef _WINDOWS
  93. EnumerateNetworkConnections();
  94. #endif
  95. }
  96. //---------------------------------------------------------------------------
  97. // ~CEnvironmentDeploymentEngine
  98. //---------------------------------------------------------------------------
  99. virtual ~CEnvironmentDeploymentEngine()
  100. {
  101. //delete all temporary files generated during deployemnt
  102. int count = m_tempFiles.length();
  103. int i;
  104. for (i = 0; i < count; i++)
  105. {
  106. if (!checkFileExists(m_tempFiles.item(i))) continue;
  107. if (!DeleteFile(m_tempFiles.item(i)))
  108. WARNLOG("Couldn't delete file %s", m_tempFiles.item(i));
  109. }
  110. count = m_tempDirs.length();
  111. for (i = 0; i < count; i++)
  112. deleteRecursive(m_tempDirs.item(i));
  113. m_processes.kill(); // must do this before destroying deplyCallback and deployLog
  114. m_pDeployLog.clear(); // this causes the log file to be written
  115. m_pCallback.clear();
  116. termXML();
  117. }
  118. void deleteRecursive(const char* path)
  119. {
  120. Owned<IFile> pDir = createIFile(path);
  121. if (pDir->exists())
  122. {
  123. if (pDir->isDirectory()==fileBool::foundYes)
  124. {
  125. Owned<IDirectoryIterator> it = pDir->directoryFiles(NULL, false, true);
  126. ForEach(*it)
  127. {
  128. StringBuffer name;
  129. it->getName(name);
  130. StringBuffer childPath(path);
  131. childPath.append(PATHSEPCHAR);
  132. childPath.append(name);
  133. deleteRecursive(childPath.str());
  134. }
  135. }
  136. pDir->remove();
  137. }
  138. }
  139. //---------------------------------------------------------------------------
  140. // addProcess
  141. //---------------------------------------------------------------------------
  142. IDeploymentEngine* addProcess(const char* processType, const char* processName)
  143. {
  144. assertex(processType);
  145. assertex(processName);
  146. StringBuffer xpath;
  147. xpath.appendf("Software/%s[@name='%s']", processType, processName);
  148. Owned<IPropertyTree> tree = &m_environment.getPTree();
  149. IPropertyTree* pComponent = tree->queryPropTree(xpath.str());
  150. if (!pComponent)
  151. throw MakeStringException(0, "%s with name %s was not found!", processType, processName);
  152. IDeploymentEngine* deployEngine;
  153. if (strcmp(processType, "DaliServerProcess")==0)
  154. deployEngine = new CDaliDeploymentEngine(*this, *m_pCallback, *pComponent);
  155. else if (strcmp(processType, "ThorCluster")==0)
  156. deployEngine = new CThorDeploymentEngine(*this, *m_pCallback, *pComponent);
  157. else if (strcmp(processType, "RoxieCluster")==0)
  158. deployEngine = new CRoxieDeploymentEngine(*this, *m_pCallback, *pComponent);
  159. else if (strcmp(processType, "EspProcess")==0)
  160. deployEngine = new CEspDeploymentEngine(*this, *m_pCallback, *pComponent);
  161. else
  162. deployEngine = new CDeploymentEngine(*this, *m_pCallback, *pComponent, "Instance", true);
  163. assertex(deployEngine);
  164. deployEngine->setXsl(m_processor, m_transform);
  165. m_processes.append(*deployEngine); // array releases members when destroyed
  166. return deployEngine;
  167. }
  168. //---------------------------------------------------------------------------
  169. // setSshAccount
  170. //---------------------------------------------------------------------------
  171. void setSshAccount(const char* userid, const char* password)
  172. {
  173. m_sSshUserid = userid;
  174. m_sSshPassword = password;
  175. }
  176. //---------------------------------------------------------------------------
  177. // isLinuxDeployment
  178. //---------------------------------------------------------------------------
  179. bool isLinuxDeployment() const
  180. {
  181. return m_bLinuxDeployment;
  182. }
  183. //---------------------------------------------------------------------------
  184. // start
  185. //---------------------------------------------------------------------------
  186. void start()
  187. {
  188. ForEachItemIn(idx, m_processes)
  189. {
  190. m_processes.item(idx).start();
  191. }
  192. }
  193. //---------------------------------------------------------------------------
  194. // stop
  195. //---------------------------------------------------------------------------
  196. void stop()
  197. {
  198. ForEachItemInRev(idx, m_processes)
  199. {
  200. m_processes.item(idx).stop();
  201. }
  202. }
  203. //---------------------------------------------------------------------------
  204. // stripXsltMessage
  205. //---------------------------------------------------------------------------
  206. void stripXsltMessage(StringBuffer& msg)
  207. {
  208. //for better readability of msg, remove redundant prefix of "[XSLT warning: ", if present
  209. const char* pattern = "[ElemMessageTerminateException: ";
  210. const int len =sizeof("[ElemMessageTerminateException: ")-1;
  211. if (!strncmp(msg, pattern, len))
  212. msg.remove(0, len);
  213. //remove the excessive info about XSLT context when this was thrown
  214. const char* begin = msg.str();
  215. const char* end = strstr(begin, "(file:");
  216. if (end)
  217. msg.setLength(end-begin);
  218. }
  219. //---------------------------------------------------------------------------
  220. // check
  221. //---------------------------------------------------------------------------
  222. void check()
  223. {
  224. if (m_pCallback->getAbortStatus())
  225. throw MakeStringException(0, "User abort");
  226. bool valid = false;
  227. m_nValidationErrors = 0;
  228. StringBuffer outputXml;
  229. Owned<IXslFunction> externalFunction;
  230. externalFunction.setown(m_transform->createExternalFunction("validationMessage", validationMessageFromXSLT));
  231. m_transform->setExternalFunction(SEISINT_NAMESPACE, externalFunction.get(), true);
  232. m_transform->loadXslFromFile(m_validateAllXsl.str());
  233. m_transform->setUserData(this);
  234. try
  235. {
  236. m_transform->transform( outputXml );
  237. m_transform->closeResultTarget();
  238. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "%s", m_transform->getMessages());
  239. if (!m_nValidationErrors)//this may get filled in by the external function
  240. valid = true;
  241. }
  242. catch (IException* e)
  243. {
  244. StringBuffer msg;
  245. e->errorMessage(msg);
  246. e->Release();
  247. stripXsltMessage(msg);
  248. m_sValidationErrors.append(msg);
  249. }
  250. catch (...)
  251. {
  252. m_sValidationErrors.appendf("Validation failed: Unspecified XSL error!");
  253. }
  254. m_transform->setExternalFunction(SEISINT_NAMESPACE, externalFunction.get(), false);
  255. m_transform->setUserData(NULL);
  256. if (!valid)
  257. {
  258. const char* errors = m_sValidationErrors.str();
  259. if (!errors || !*errors)
  260. errors = "Continue?";
  261. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Preliminary validation failed!");
  262. while ( !m_pCallback->processException(NULL, NULL, NULL, NULL, errors, "Preliminary validation failed!", NULL) )
  263. ;
  264. valid = true; //ignore validation errors
  265. }
  266. if (valid)
  267. {
  268. ForEachItemIn(idx, m_processes)
  269. m_processes.item(idx).check();
  270. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL);
  271. }
  272. }
  273. //---------------------------------------------------------------------------
  274. // compare
  275. //---------------------------------------------------------------------------
  276. void compare(unsigned mode)
  277. {
  278. ForEachItemIn(idx, m_processes)
  279. {
  280. m_processes.item(idx).compare(mode);
  281. }
  282. }
  283. //---------------------------------------------------------------------------
  284. // deploy
  285. //---------------------------------------------------------------------------
  286. void deploy(unsigned flags, bool useTempDir)
  287. {
  288. m_tempFileCount = m_espModuleCount = 0;
  289. if (flags != DEFLAGS_NONE)
  290. {
  291. ForEachItemIn(idx, m_processes)
  292. {
  293. m_processes.item(idx).deploy(flags, useTempDir);
  294. }
  295. }
  296. }
  297. //---------------------------------------------------------------------------
  298. // deploy
  299. //---------------------------------------------------------------------------
  300. void deploy(unsigned flags, BackupMode backupMode, bool bStop, bool bStart)
  301. {
  302. switch (backupMode)
  303. {
  304. case DEBACKUP_NONE:
  305. if (bStop)
  306. stop();
  307. deploy(flags, false);
  308. if (bStart)
  309. start();
  310. break;
  311. case DEBACKUP_COPY:
  312. backupDirs();
  313. if (bStop)
  314. stop();
  315. deploy(flags, false);
  316. if (bStart)
  317. start();
  318. break;
  319. case DEBACKUP_RENAME:
  320. deploy(flags, true);
  321. if (bStop)
  322. stop();
  323. renameDirs();
  324. if (bStart)
  325. start();
  326. break;
  327. default:
  328. assertex(false);
  329. }
  330. }
  331. //---------------------------------------------------------------------------
  332. // renameDirs
  333. //---------------------------------------------------------------------------
  334. void renameDirs()
  335. {
  336. ForEachItemIn(idx, m_processes)
  337. {
  338. m_processes.item(idx).renameDirs();
  339. }
  340. }
  341. //---------------------------------------------------------------------------
  342. // backupDirs
  343. //---------------------------------------------------------------------------
  344. void backupDirs()
  345. {
  346. ForEachItemIn(idx, m_processes)
  347. {
  348. m_processes.item(idx).backupDirs();
  349. }
  350. }
  351. //---------------------------------------------------------------------------
  352. // abort
  353. //---------------------------------------------------------------------------
  354. void abort()
  355. {
  356. m_abort = true;
  357. ForEachItemIn(idx, m_processes)
  358. {
  359. m_processes.item(idx).abort();
  360. }
  361. }
  362. //---------------------------------------------------------------------------
  363. // archive
  364. //---------------------------------------------------------------------------
  365. void archive(const char* filename)
  366. {
  367. if (!filename || !*filename) return;
  368. if (m_abort)
  369. {
  370. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Aborted!");
  371. throw MakeStringException(0, "User abort");
  372. }
  373. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Archiving environment data to %s...", filename);
  374. Owned<IPropertyTree> tree = &m_environment.getPTree();
  375. StringBuffer xml;
  376. toXML(tree, xml);
  377. Owned<IDeployTask> task = createDeployTask(*m_pCallback, "Archive File", NULL, NULL, NULL, NULL,
  378. filename, "", "", "", false);
  379. task->createFile(xml.str());
  380. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL);
  381. if (task->getAbort())
  382. throw MakeStringException(0, "User abort");
  383. Owned<IFile> pFile = createIFile(filename);
  384. pFile->setReadOnly(true);
  385. }
  386. //---------------------------------------------------------------------------
  387. // setLog
  388. //---------------------------------------------------------------------------
  389. void setLog(const char* filename, const char* envname)
  390. {
  391. if (!filename || !*filename) return;
  392. m_pDeployLog.setown(createDeployLog(*m_pCallback, filename, envname));
  393. }
  394. //---------------------------------------------------------------------------
  395. // initXML
  396. //---------------------------------------------------------------------------
  397. void initXML(IPropertyTree* pSelectedComponents)
  398. {
  399. if (m_abort)
  400. throw MakeStringException(0, "User abort");
  401. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Loading environment...");
  402. m_processor.setown(getXslProcessor());
  403. m_transform.setown(m_processor->createXslTransform());
  404. //decrypt external function is no longer used by any xslt
  405. //
  406. //m_externalFunction.setown(m_transform->createExternalFunction("decrypt", decrypt));
  407. //m_transform->setExternalFunction(SEISINT_NAMESPACE, m_externalFunction.get(), true);
  408. Owned<IPropertyTree> tree = &m_environment.getPTree();
  409. IPropertyTree* pDeploy = tree->queryPropTree("DeployComponents");
  410. if (pDeploy)
  411. tree->removeTree(pDeploy);
  412. pDeploy = tree->addPropTree("DeployComponents", createPTreeFromIPT(pSelectedComponents));
  413. StringBuffer xml;
  414. toXML(tree, xml);
  415. tree->removeTree(pDeploy);
  416. if (m_transform->setXmlSource(xml.str(), xml.length()) != 0)
  417. throw MakeStringException(0, "Invalid environment XML string");
  418. }
  419. //---------------------------------------------------------------------------
  420. // termXML
  421. //---------------------------------------------------------------------------
  422. void termXML()
  423. {
  424. //decrypt external function is no longer used by any xslt
  425. //
  426. //m_transform->setExternalFunction(SEISINT_NAMESPACE, m_externalFunction.get(), false);
  427. m_externalFunction.clear();
  428. m_transform.clear();
  429. m_processor.clear();
  430. }
  431. //---------------------------------------------------------------------------
  432. // incrementTempFileCount
  433. //---------------------------------------------------------------------------
  434. virtual int incrementTempFileCount()
  435. {
  436. return ++m_tempFileCount;
  437. }
  438. //---------------------------------------------------------------------------
  439. // incrementEspModuleCount
  440. //---------------------------------------------------------------------------
  441. virtual int incrementEspModuleCount()
  442. {
  443. return ++m_espModuleCount;
  444. }
  445. //---------------------------------------------------------------------------
  446. // validationMessageFromXSLT
  447. //---------------------------------------------------------------------------
  448. static void validationMessageFromXSLT(StringBuffer &ret, const char *in, IXslTransform* pTransform)
  449. {
  450. CEnvironmentDeploymentEngine* pEnvDepEngine = (CEnvironmentDeploymentEngine*) pTransform->getUserData();
  451. IDeploymentCallback* pCallback = pEnvDepEngine->m_pCallback;
  452. //input 'in' has format of the form [type]:[compType]:[compName]:[message]
  453. //type is either 'error' or 'warning' and any of the other parts may be empty strings
  454. //
  455. StringArray sArray;
  456. sArray.appendList(in, ":");
  457. if (sArray.ordinality() != 4)
  458. {
  459. pCallback->printStatus(STATUS_ERROR, NULL, NULL, NULL, "%s", in);
  460. return;
  461. }
  462. const char* msgType = sArray.item(0);
  463. const char* compType = sArray.item(1);
  464. const char* compName = sArray.item(2);
  465. const char* msg = sArray.item(3);
  466. if (compType && !*compType)
  467. compType = NULL;
  468. if (compName && !*compName)
  469. compName = NULL;
  470. StatusType statusType;
  471. if (!stricmp(msgType, "error"))
  472. {
  473. statusType = STATUS_ERROR;
  474. pEnvDepEngine->m_nValidationErrors++;
  475. if (!compType || !compName)//if this error is not being reported under a particular component in tree
  476. pEnvDepEngine->m_sValidationErrors.append(msg).append("\n");
  477. }
  478. else if (!strnicmp(msgType, "warn", 4))
  479. statusType = STATUS_WARN;
  480. else if (!stricmp(msgType, "OK"))
  481. statusType = STATUS_OK;
  482. else if (!strnicmp(msgType, "inc", 3))
  483. statusType = STATUS_INCOMPLETE;
  484. else statusType = !stricmp(msgType, "normal") ? STATUS_NORMAL : STATUS_ERROR;
  485. try
  486. {
  487. if (pCallback)
  488. pCallback->printStatus( statusType,
  489. compType,
  490. compName,
  491. NULL,
  492. "%s", msg);
  493. }
  494. catch (IException* e)
  495. {
  496. StringBuffer buf;
  497. e->errorMessage(buf);
  498. e->Release();
  499. pCallback->printStatus(STATUS_ERROR, NULL, NULL, NULL, "%s", buf.str());
  500. }
  501. catch(...)
  502. {
  503. pCallback->printStatus(STATUS_ERROR, NULL, NULL, NULL, "Unknown exception!");
  504. }
  505. }
  506. //---------------------------------------------------------------------------
  507. // getCallback
  508. //---------------------------------------------------------------------------
  509. virtual IDeploymentCallback& getCallback() const
  510. {
  511. return *m_pCallback;
  512. }
  513. //---------------------------------------------------------------------------
  514. // setInteractiveMode
  515. //---------------------------------------------------------------------------
  516. virtual void setInteractiveMode(bool bSet)
  517. {
  518. m_bInteractiveMode = bSet;
  519. }
  520. //---------------------------------------------------------------------------
  521. // getEnvironment
  522. //---------------------------------------------------------------------------
  523. IConstEnvironment& getEnvironment() const
  524. {
  525. return m_environment;
  526. }
  527. //---------------------------------------------------------------------------
  528. // getInteractiveMode
  529. //---------------------------------------------------------------------------
  530. virtual bool getInteractiveMode() const
  531. {
  532. return m_bInteractiveMode;
  533. }
  534. //---------------------------------------------------------------------------
  535. // getDeployLog
  536. //---------------------------------------------------------------------------
  537. virtual IDeployLog* getDeployLog()
  538. {
  539. return m_pDeployLog ? m_pDeployLog.getLink() : NULL;
  540. }
  541. //---------------------------------------------------------------------------
  542. // addTempFile
  543. //---------------------------------------------------------------------------
  544. virtual void addTempFile(const char* filePath)
  545. {
  546. if (filePath)
  547. m_tempFiles.appendUniq(filePath);
  548. }
  549. //---------------------------------------------------------------------------
  550. // addTempDirectory
  551. //---------------------------------------------------------------------------
  552. virtual void addTempDirectory(const char* dirPath)
  553. {
  554. if (dirPath)
  555. m_tempDirs.appendUniq(dirPath);
  556. }
  557. //---------------------------------------------------------------------------
  558. // setDeployToFolder
  559. //---------------------------------------------------------------------------
  560. virtual void setDeployToFolder(const char* path)
  561. {
  562. StringBuffer machineName;
  563. StringBuffer localPath;
  564. StringBuffer tail;
  565. StringBuffer ext;
  566. if (splitUNCFilename(path, &machineName, &localPath, &tail, &ext))
  567. {
  568. const char* hostName = machineName.str() + 2;
  569. Owned<IConstMachineInfo> machine = m_environment.getMachine(hostName);
  570. if (!machine)
  571. throw MakeStringException(-1, "The computer '%s' used for deployment folder is undefined!", hostName);
  572. StringAttr netAddress;
  573. StringAttrAdaptor adaptor(netAddress);
  574. machine->getNetAddress(adaptor);
  575. if (!netAddress.get() || !*netAddress.get())
  576. throw MakeStringException(-1,
  577. "The computer '%s' used for deployment folder does not have any network address defined!", hostName);
  578. StringBuffer uncPath(PATHSEPSTR PATHSEPSTR);
  579. uncPath.append( netAddress.get() );
  580. if (*localPath.str() != PATHSEPCHAR)
  581. uncPath.append( PATHSEPCHAR );
  582. uncPath.append( localPath );//note that the path ends with PATHSEPCHAR
  583. uncPath.append( tail );
  584. uncPath.append( ext );
  585. m_sDeployToFolder.set( uncPath.str() );
  586. getAccountInfo(hostName, m_sDeployToUser, m_sDeployToPswd);
  587. }
  588. else
  589. m_sDeployToFolder.set( path );
  590. /*
  591. Owned<IDeployTask> task = createDeployTask(*m_pCallback, "Create Directory", NULL, NULL, NULL, NULL, m_sDeployToFolder.get());
  592. m_pCallback->printStatus(task);
  593. task->createDirectory();
  594. m_pCallback->printStatus(task);
  595. */
  596. }
  597. //---------------------------------------------------------------------------
  598. // getDeployToFolder
  599. //---------------------------------------------------------------------------
  600. virtual const char* getDeployToFolder() const
  601. {
  602. return m_sDeployToFolder.get();
  603. }
  604. //---------------------------------------------------------------------------
  605. // getDeployToAccountInfo
  606. //---------------------------------------------------------------------------
  607. virtual void getDeployToAccountInfo(const char*& user, const char*& pswd) const
  608. {
  609. user = m_sDeployToUser.get();
  610. pswd = m_sDeployToPswd.get();
  611. }
  612. //---------------------------------------------------------------------------
  613. // lookupNetAddress
  614. //---------------------------------------------------------------------------
  615. StringAttr& lookupNetAddress(StringAttr& str, const char* computer) const
  616. {
  617. Owned<IConstMachineInfo> machine = m_environment.getMachine(computer);
  618. if (machine)
  619. {
  620. StringAttrAdaptor adaptor(str);
  621. machine->getNetAddress(adaptor);
  622. }
  623. return str;
  624. }
  625. //---------------------------------------------------------------------------
  626. // lookupMachineOS
  627. //---------------------------------------------------------------------------
  628. EnvMachineOS lookupMachineOS(IPropertyTree& node) const
  629. {
  630. Owned<IConstMachineInfo> machine = m_environment.getMachine(node.queryProp("@computer"));
  631. return machine ? machine->getOS() : MachineOsUnknown;
  632. }
  633. //---------------------------------------------------------------------------
  634. // getAccountInfo
  635. //---------------------------------------------------------------------------
  636. void getAccountInfo(const char* computer, StringAttr& user, StringAttr& pwd) const
  637. {
  638. Owned<IConstMachineInfo> machine = m_environment.getMachine(computer);
  639. if (machine)
  640. {
  641. Owned<IConstDomainInfo> domain = machine->getDomain();
  642. if (!domain)
  643. throw MakeStringException(-1, "The computer '%s' does not have any domain information!", computer);
  644. StringBuffer x;
  645. if (machine->getOS() == MachineOsW2K)
  646. {
  647. domain->getName(StringBufferAdaptor(x));
  648. if (x.length())
  649. x.append(PATHSEPCHAR);
  650. }
  651. domain->getAccountInfo(StringBufferAdaptor(x), StringAttrAdaptor(pwd));
  652. user.set(x.str());
  653. }
  654. else
  655. throw MakeStringException(-1, "The computer '%s' is undefined!", computer);
  656. }
  657. //---------------------------------------------------------------------------
  658. // getSSHAccountInfo
  659. //---------------------------------------------------------------------------
  660. void getSSHAccountInfo(const char* computer, StringAttr& user, StringAttr& sshKeyFile, StringAttr& sshKeyPassphrase) const
  661. {
  662. Owned<IConstMachineInfo> machine = m_environment.getMachine(computer);
  663. if (machine)
  664. {
  665. Owned<IConstDomainInfo> domain = machine->getDomain();
  666. if (!domain)
  667. throw MakeStringException(-1, "The computer '%s' does not have any domain information!", computer);
  668. StringBuffer x;
  669. if (machine->getOS() == MachineOsW2K)
  670. {
  671. domain->getName(StringBufferAdaptor(x));
  672. if (x.length())
  673. x.append(PATHSEPCHAR);
  674. }
  675. domain->getSSHAccountInfo(StringBufferAdaptor(x), StringAttrAdaptor(sshKeyFile), StringAttrAdaptor(sshKeyPassphrase));
  676. user.set(x.str());
  677. }
  678. else
  679. throw MakeStringException(-1, "The computer '%s' is undefined!", computer);
  680. }
  681. virtual void setSourceDaliAddress( const char* addr )
  682. {
  683. m_sSrcDaliAddress.set( addr );
  684. }
  685. virtual const char* getSourceDaliAddress()
  686. {
  687. return m_sSrcDaliAddress.get();
  688. }
  689. virtual IArrayOf<IDeploymentEngine>& queryProcesses() { return m_processes; }
  690. #ifdef _WINDOWS
  691. void NetErrorHandler(DWORD dwResult)
  692. {
  693. StringBuffer out;
  694. formatSystemError(out, dwResult);
  695. out.insert(0, "Failed to enumerate existing network connections:\n");
  696. while ( !m_pCallback->processException(NULL, NULL, NULL, NULL, out, "Network Error", NULL) )
  697. ;
  698. }
  699. bool EnumerateNetworkConnections()
  700. {
  701. DWORD dwResult;
  702. HANDLE hEnum;
  703. DWORD cbBuffer = 16384; // 16K is a good size
  704. DWORD cEntries = -1; // enumerate all possible entries
  705. LPNETRESOURCE lpnr; // pointer to enumerated structures
  706. //
  707. // Call the WNetOpenEnum function to begin the enumeration.
  708. //
  709. dwResult = WNetOpenEnum(RESOURCE_CONNECTED, // connected network resources
  710. RESOURCETYPE_ANY,// all resources
  711. 0, // enumerate all resources
  712. NULL, // NULL first time the function is called
  713. &hEnum); // handle to the resource
  714. if (dwResult != NO_ERROR)
  715. {
  716. NetErrorHandler(dwResult);
  717. return false;
  718. }
  719. //
  720. // Call the GlobalAlloc function to allocate resources.
  721. //
  722. lpnr = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
  723. do
  724. {
  725. ZeroMemory(lpnr, cbBuffer);
  726. // Call the WNetEnumResource function to continue
  727. // the enumeration.
  728. //
  729. dwResult = WNetEnumResource( hEnum, // resource handle
  730. &cEntries, // defined locally as -1
  731. lpnr, // LPNETRESOURCE
  732. &cbBuffer); // buffer size
  733. // If the call succeeds, loop through the structures.
  734. //
  735. if (dwResult == NO_ERROR)
  736. {
  737. StringBuffer networkPath;
  738. for (DWORD i = 0; i < cEntries; i++)
  739. if (lpnr[i].lpRemoteName)
  740. {
  741. // make a valid UNC path to connect to and see if we are not already connected
  742. if (CDeploymentEngine::stripTrailingDirsFromUNCPath(lpnr[i].lpRemoteName, networkPath.clear()) &&
  743. m_persistentConnections.find( networkPath.str() ) == m_persistentConnections.end())
  744. {
  745. //::MessageBox(NULL, networkPath.str(), lpnr[i].lpRemoteName, MB_OK);
  746. m_persistentConnections.insert( networkPath.str() );
  747. }
  748. }
  749. }
  750. else if (dwResult != ERROR_NO_MORE_ITEMS)
  751. {
  752. NetErrorHandler(dwResult);
  753. break;
  754. }
  755. }
  756. while (dwResult != ERROR_NO_MORE_ITEMS);
  757. GlobalFree((HGLOBAL)lpnr); // free the memory
  758. dwResult = WNetCloseEnum(hEnum); // end the enumeration
  759. if (dwResult != NO_ERROR)
  760. {
  761. NetErrorHandler(dwResult);
  762. return false;
  763. }
  764. return true;
  765. }
  766. #endif//WINDOWS
  767. virtual bool IsPersistentConnection(const char* networkPath) const
  768. {
  769. return m_persistentConnections.find( networkPath ) != m_persistentConnections.end();
  770. }
  771. protected:
  772. IArrayOf<IDeploymentEngine> m_processes;
  773. IConstEnvironment& m_environment;
  774. Owned<IDeploymentCallback> m_pCallback;
  775. Owned<IXslProcessor> m_processor;
  776. Owned<IXslTransform> m_transform;
  777. Owned<IXslFunction> m_externalFunction;
  778. Owned<IDeployLog> m_pDeployLog;
  779. set<string> m_persistentConnections;
  780. int m_espModuleCount;
  781. int m_tempFileCount;
  782. bool m_abort;
  783. bool m_bLinuxDeployment;
  784. bool m_bInteractiveMode;
  785. StringBuffer m_sSshUserid;
  786. StringBuffer m_sSshPassword;
  787. StringBuffer m_validateAllXsl;
  788. unsigned int m_nValidationErrors;
  789. StringBuffer m_sValidationErrors;
  790. StringArray m_tempFiles;
  791. StringArray m_tempDirs;
  792. StringAttr m_sDeployToFolder;
  793. StringAttr m_sDeployToUser;
  794. StringAttr m_sDeployToPswd;
  795. StringAttr m_sSrcDaliAddress;
  796. };
  797. class CConfigGenMgr : public CEnvironmentDeploymentEngine
  798. {
  799. public:
  800. IMPLEMENT_IINTERFACE;
  801. //---------------------------------------------------------------------------
  802. // CConfigGenMgr
  803. //---------------------------------------------------------------------------
  804. CConfigGenMgr(IConstEnvironment& environment, IDeploymentCallback& callback,
  805. IPropertyTree* pSelectedComponents, const char* inputDir, const char* outputDir, const char* compName, const char* compType, const char* ipAddr)
  806. : CEnvironmentDeploymentEngine(environment, callback, NULL),
  807. m_inDir(inputDir),
  808. m_outDir(outputDir),
  809. m_compName(compName),
  810. m_compType(compType),
  811. m_hostIpAddr(ipAddr)
  812. {
  813. m_validateAllXsl.clear().append(inputDir);
  814. if (m_validateAllXsl.length() > 0 &&
  815. m_validateAllXsl.charAt(m_validateAllXsl.length() - 1) != PATHSEPCHAR)
  816. m_validateAllXsl.append(PATHSEPCHAR);
  817. m_validateAllXsl.append("validateAll.xsl");
  818. Owned<IPropertyTree> pSelComps;
  819. if (!pSelectedComponents)
  820. {
  821. Owned<IPropertyTree> pEnvTree = &m_environment.getPTree();
  822. pSelComps.setown(getInstances(pEnvTree, compName, compType, ipAddr));
  823. pSelectedComponents = pSelComps;
  824. }
  825. initXML(pSelectedComponents);
  826. {
  827. Owned<IPropertyTreeIterator> it = pSelectedComponents->getElements("*");
  828. ForEach(*it)
  829. {
  830. IPropertyTree* pComponent = &it->query();
  831. IDeploymentEngine* pEngine = addProcess(pComponent->queryName(), pComponent->queryProp("@name"));
  832. Owned<IPropertyTreeIterator> iter = pComponent->getElements("*");
  833. if (iter->first())
  834. {
  835. pEngine->resetInstances();
  836. ForEach(*iter)
  837. {
  838. IPropertyTree* pChild = &iter->query();
  839. const char* tagName = pChild->queryName();
  840. const char* instName = pChild->queryProp("@name");
  841. pEngine->addInstance(tagName, instName);
  842. //determine if this is linux deployment
  843. if (!m_bLinuxDeployment)
  844. {
  845. const char* computer = pChild->queryProp("@computer");
  846. Owned<IConstMachineInfo> pMachine = environment.getMachine(computer);
  847. if (!pMachine)
  848. throw MakeStringException(0, "Invalid Environment file. Instance '%s' of '%s' references a computer '%s' that has not been defined!", pChild->queryProp("@name"), pComponent->queryProp("@name"), computer);
  849. else if (pMachine->getOS() == MachineOsLinux)
  850. m_bLinuxDeployment = true;
  851. }
  852. }
  853. }
  854. else if (!m_bLinuxDeployment)//another previously added engine already does not have linux instance
  855. {
  856. //some components like thor and hole clusters don't show their instances in the
  857. //deployment wizard so detect if they have any linux instance.
  858. const IArrayOf<IPropertyTree>& instances = pEngine->getInstances();
  859. if (instances.ordinality() > 0)
  860. {
  861. Owned<IConstMachineInfo> machine;// = m_environment.getMachine(instances.item(0).queryProp("@computer"));
  862. if (machine && machine->getOS() == MachineOsLinux)
  863. m_bLinuxDeployment = true;
  864. }
  865. }
  866. }
  867. }
  868. }
  869. //---------------------------------------------------------------------------
  870. // addProcess
  871. //---------------------------------------------------------------------------
  872. IDeploymentEngine* addProcess(const char* processType, const char* processName)
  873. {
  874. assertex(processType);
  875. assertex(processName);
  876. StringBuffer xpath;
  877. xpath.appendf("Software/%s[@name='%s']", processType, processName);
  878. Owned<IPropertyTree> tree = &m_environment.getPTree();
  879. IPropertyTree* pComponent = tree->queryPropTree(xpath.str());
  880. if (!pComponent)
  881. throw MakeStringException(0, "%s with name %s was not found!", processType, processName);
  882. IDeploymentEngine* deployEngine;
  883. if (strcmp(processType, "RoxieCluster")==0)
  884. deployEngine = new CConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir, "*");
  885. else if (strcmp(processType, "ThorCluster")==0)
  886. deployEngine = new CThorConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir);
  887. else if (strcmp(processType, "EspProcess")==0)
  888. deployEngine = new CEspConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir);
  889. else
  890. deployEngine = new CConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir, "Instance", true);
  891. assertex(deployEngine);
  892. deployEngine->setXsl(m_processor, m_transform);
  893. m_processes.append(*deployEngine); // array releases members when destroyed
  894. return deployEngine;
  895. }
  896. void deploy(unsigned flags, BackupMode backupMode, bool bStop, bool bStart)
  897. {
  898. switch (backupMode)
  899. {
  900. case DEBACKUP_NONE:
  901. check();
  902. CEnvironmentDeploymentEngine::deploy(flags, false);
  903. break;
  904. case DEBACKUP_COPY:
  905. throw MakeStringException(-1, "Invalid option Backup copy while generating configurations");
  906. case DEBACKUP_RENAME:
  907. throw MakeStringException(-1, "Invalid option Backup rename while generating configurations");
  908. default:
  909. throw MakeStringException(-1, "Invalid option while generating configurations");
  910. }
  911. }
  912. private:
  913. StringBuffer m_inDir;
  914. StringBuffer m_outDir;
  915. StringBuffer m_compName;
  916. StringBuffer m_compType;
  917. StringBuffer m_hostIpAddr;
  918. };
  919. //---------------------------------------------------------------------------
  920. // Factory functions
  921. //---------------------------------------------------------------------------
  922. IEnvDeploymentEngine* createEnvDeploymentEngine(IConstEnvironment& environment,
  923. IDeploymentCallback& callback,
  924. IPropertyTree* pSelectedComponents)
  925. {
  926. try
  927. {
  928. return new CEnvironmentDeploymentEngine(environment, callback, pSelectedComponents);
  929. }
  930. catch (IException* e)
  931. {
  932. throw e;
  933. }
  934. catch(...)
  935. {
  936. throw MakeStringException(-1, "Unknown exception!");
  937. }
  938. }
  939. IEnvDeploymentEngine* createConfigGenMgr(IConstEnvironment& env,
  940. IDeploymentCallback& callback,
  941. IPropertyTree* pSelectedComponents,
  942. const char* inputDir,
  943. const char* outputDir,
  944. const char* compName,
  945. const char* compType,
  946. const char* ipAddr)
  947. {
  948. try
  949. {
  950. StringBuffer inDir(inputDir);
  951. if (inDir.length() && inDir.charAt(inDir.length() - 1) != PATHSEPCHAR)
  952. inDir.append(PATHSEPCHAR);
  953. StringBuffer outDir(outputDir);
  954. if (outDir.length() && outDir.charAt(outDir.length() - 1) != PATHSEPCHAR)
  955. outDir.append(PATHSEPCHAR);
  956. return new CConfigGenMgr(env, callback, pSelectedComponents, inDir.str(), outDir.str(), compName, compType, ipAddr);
  957. }
  958. catch (IException* e)
  959. {
  960. throw e;
  961. }
  962. catch(...)
  963. {
  964. throw MakeStringException(-1, "Unknown exception!");
  965. }
  966. }
  967. bool matchDeployAddress(const char *searchIP, const char *envIP)
  968. {
  969. if (searchIP && envIP && *searchIP && *envIP)
  970. {
  971. IpAddress ip(envIP);
  972. if (strcmp(searchIP, ".")==0)
  973. return ip.isLocal();
  974. else
  975. {
  976. IpAddress ip2(searchIP);
  977. return ip.ipequals(ip2);
  978. }
  979. }
  980. return false;
  981. }
  982. /* Look into the topology section of the given environment.xml file. Parse Topology section
  983. * And extract RoxieServerProcess, ThorServerProcess, EclServerProcess component names and
  984. * Add them to the pTopologyComponents list.
  985. * Then search the software section. If the software components buildSet property matches
  986. * roxie, thor, or eclserver. We then check it against the unique list made from topology.
  987. * If the the unique list also has the name of the software component, we process it.
  988. * Otherwise we skip it and move on to the next component.*/
  989. IPropertyTree* getInstances(const IPropertyTree* pEnvRoot, const char* compName,
  990. const char* compType, const char* ipAddr, bool listall)
  991. {
  992. Owned<IPropertyTreeIterator> pClusterIter = pEnvRoot->getElements("Software/Topology/*");
  993. StringArray pTopologyComponents;
  994. ForEach(*pClusterIter)
  995. {
  996. IPropertyTree * pCluster = &pClusterIter->query();
  997. Owned<IPropertyTreeIterator> pClusterProcessIter = pCluster->getElements("*");
  998. ForEach(*pClusterProcessIter)
  999. {
  1000. IPropertyTree * pClusterProcess = &pClusterProcessIter->query();
  1001. if (!strcmp(pClusterProcess->queryName(),"RoxieCluster") || !strcmp(pClusterProcess->queryName(),"ThorCluster")
  1002. || !strcmp(pClusterProcess->queryName(),"EclServerProcess") || !strcmp(pClusterProcess->queryName(),"EclAgentProcess")
  1003. || !strcmp(pClusterProcess->queryName(),"EclCCServerProcess") || !strcmp(pClusterProcess->queryName(),"EclSchedulerProcess")
  1004. || !strcmp(pClusterProcess->queryName(),"EclSchedulerProcess"))
  1005. pTopologyComponents.appendUniq(pClusterProcess->queryProp("@process"));
  1006. }
  1007. }
  1008. Owned<IPropertyTree> pSelComps(createPTree("SelectedComponents"));
  1009. Owned<IPropertyTreeIterator> iter = pEnvRoot->getElements("Software/*");
  1010. const char* instanceNodeNames[] = { "Instance", "RoxieServerProcess" };
  1011. const char* logDirNames[] = { "@logDir", "@LogDir", "@dfuLogDir", "@eclLogDir" };
  1012. ForEach(*iter)
  1013. {
  1014. IPropertyTree* pComponent = &iter->query();
  1015. const char* type = pComponent->queryName();
  1016. if (stricmp(type, "Topology")!=0 && stricmp(type, "Directories")!=0 &&
  1017. pComponent->queryProp("@buildSet") && pComponent->queryProp("@name") &&
  1018. ((!compName && !compType) ||
  1019. (compName && !strcmp(pComponent->queryProp("@name"), compName)) ||
  1020. (!compName && compType && !strcmp(pComponent->queryProp("@buildSet"), compType))))
  1021. {
  1022. const char* name = pComponent->queryProp("@name");
  1023. const char* build = pComponent->queryProp("@build");
  1024. const char* buildSet= pComponent->queryProp("@buildSet");
  1025. const char* masterPort = pComponent->queryProp("@masterport");
  1026. const char* slavePort = pComponent->queryProp("@slaveport");
  1027. const char* slavesPerNode = pComponent->queryProp("@slavesPerNode");
  1028. const char* logDir = NULL;
  1029. /* If one of these components found isn't also declared in topology, skip it. */
  1030. if ((!strcmp(buildSet,"thor") || !strcmp(buildSet,"roxie") || !strcmp(buildSet,"eclserver") || !strcmp(buildSet,"eclagent")
  1031. || !strcmp(buildSet,"eclccserver") || !strcmp(buildSet,"eclscheduler")) && !pTopologyComponents.contains(name))
  1032. continue;
  1033. if (listall)
  1034. for (int i = 0; i < sizeof(logDirNames)/sizeof(char*); i++)
  1035. {
  1036. logDir = pComponent->queryProp(logDirNames[i]);
  1037. if (logDir)
  1038. break;
  1039. }
  1040. StringBuffer sXPath;
  1041. sXPath.appendf("Programs/Build[@name='%s']/BuildSet[@name='%s']/@deployable", build, buildSet);
  1042. const char* deployable = pEnvRoot->queryProp(sXPath.str());
  1043. //either the @deployable does not exist or it is not one of 'no', 'false' or '0'
  1044. if (!deployable ||
  1045. (strcmp(deployable, "no") != 0 && strcmp(deployable, "false") != 0 && strcmp(deployable, "0") != 0))
  1046. {
  1047. IPropertyTree* pSelComp = NULL;
  1048. Owned<IPropertyTreeIterator> iterInst = pComponent->getElements("*", iptiter_sort);
  1049. bool bAdded = false;
  1050. ForEach(*iterInst)
  1051. {
  1052. IPropertyTree* pInst = &iterInst->query();
  1053. const char* computer = pInst->queryProp("@computer");
  1054. const char* netAddr = pInst->queryProp("@netAddress");
  1055. if (!computer || !*computer || !strcmp("Notes", pInst->queryName()))
  1056. continue;
  1057. if (!strcmp(buildSet, "thor"))
  1058. {
  1059. sXPath.clear().appendf("Hardware/Computer[@name=\"%s\"]", computer);
  1060. IPropertyTree* pComputer = pEnvRoot->queryPropTree(sXPath.str());
  1061. if (pComputer == NULL)
  1062. throw MakeStringException(-1,"XPATH: %s is invalid.\n(Did you configure the Hardware?)", sXPath.str());
  1063. netAddr = pComputer->queryProp("@netAddress");
  1064. if (matchDeployAddress(ipAddr, netAddr) ||
  1065. (!ipAddr && netAddr && *netAddr))
  1066. {
  1067. if (!bAdded)
  1068. {
  1069. pSelComp = pSelComps->addPropTree(pComponent->queryName(), createPTree());
  1070. pSelComp->addProp("@name", name);
  1071. pSelComp->addProp("@buildSet", buildSet);
  1072. pSelComp->addProp("@logDir", logDir);
  1073. bAdded = true;
  1074. }
  1075. if (listall)
  1076. {
  1077. IPropertyTree* pInstance = pSelComp->addPropTree(pInst->queryName(), createPTree());
  1078. pInstance->addProp("@name", pInst->queryProp("@name"));
  1079. pInstance->addProp("@computer", computer);
  1080. pInstance->addProp("@netAddress", netAddr);
  1081. pInstance->addProp("@masterport", masterPort);
  1082. if(!strcmp(pInst->queryName(), "ThorSlaveProcess"))
  1083. {
  1084. pInstance->addProp("@slaveport", slavePort);
  1085. pInstance->addProp("@slavesPerNode", slavesPerNode);
  1086. }
  1087. }
  1088. }
  1089. }
  1090. else if (matchDeployAddress(ipAddr, netAddr) ||
  1091. (!ipAddr && netAddr && *netAddr))
  1092. {
  1093. if (!bAdded)
  1094. {
  1095. pSelComp = pSelComps->addPropTree(pComponent->queryName(), createPTree());
  1096. pSelComp->addProp("@name", name);
  1097. pSelComp->addProp("@buildSet", buildSet);
  1098. pSelComp->addProp("@logDir", logDir);
  1099. bAdded = true;
  1100. }
  1101. StringBuffer sb(pInst->queryName());
  1102. for (UINT i=0; i<sizeof(instanceNodeNames) / sizeof(instanceNodeNames[0]); i++)
  1103. if (!strcmp(sb.str(), instanceNodeNames[i]))
  1104. {
  1105. //allow multiple instances but do not allow roxie servers more than once per computer
  1106. if (listall || sb.str()[0] != 'R' || !pSelComp->queryPropTree(StringBuffer().appendf("*[@computer=\"%s\"]", computer)))
  1107. {
  1108. IPropertyTree* pInstance = pSelComp->addPropTree(sb.str(), createPTree());
  1109. pInstance->addProp("@name", pInst->queryProp("@name"));
  1110. pInstance->addProp("@computer", pInst->queryProp("@computer"));
  1111. pInstance->addProp("@port", pInst->queryProp("@port"));
  1112. pInstance->addProp("@netAddress", pInst->queryProp("@netAddress"));
  1113. const char* directory = pInst->queryProp(sb.str()[0]=='R' ? "@dataDirectory" : "@directory");
  1114. if (directory && *directory)
  1115. pInstance->addProp("@directory", directory);
  1116. }
  1117. break;
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. }
  1124. return pSelComps.getLink();
  1125. }
  1126. //---------------------------------------------------------------------------
  1127. // Module Globals
  1128. //---------------------------------------------------------------------------
  1129. const char* findFileExtension(const char* pszPath)
  1130. {
  1131. const char* lastSlash = pathTail(pszPath);
  1132. return strrchr(lastSlash ? lastSlash : pszPath, '.');
  1133. }
  1134. void removeTrailingPathSepChar(char* pszPath)
  1135. {
  1136. if (pszPath)
  1137. {
  1138. char* lastChar = pszPath + strlen(pszPath) - 1;
  1139. if (isPathSepChar(*lastChar))
  1140. *lastChar = '\0';
  1141. }
  1142. }
  1143. void stripNetAddr(const char* dir, StringBuffer& destpath, StringBuffer& destip, bool makeLinux)
  1144. {
  1145. destpath.clear().append(dir);
  1146. if (dir[0] == '\\' && dir[1] == '\\' && strlen(dir) > 2)
  1147. {
  1148. destip.clear().append(strchr(dir + 2, '\\') - (dir + 2), dir + 2);
  1149. destpath.clear().append(strchr(dir + 2, '\\'));
  1150. }
  1151. if (makeLinux)
  1152. destpath.replace('\\', '/');
  1153. }
  1154. //returns temp path that ends with path sep
  1155. //
  1156. #ifdef _WIN32
  1157. extern DWORD getLastError() { return ::GetLastError(); }
  1158. void getTempPath(char* tempPath, unsigned int bufsize, const char* subdir/*=NULL*/)
  1159. {
  1160. ::GetTempPath(bufsize, tempPath);
  1161. ::GetLongPathName(tempPath, tempPath, bufsize);
  1162. if (subdir && *subdir)
  1163. {
  1164. const int len = strlen(tempPath);
  1165. char* p = tempPath + len;
  1166. strcpy(p, subdir);
  1167. p += strlen(subdir);
  1168. *p++ = '\\';
  1169. *p = '\0';
  1170. }
  1171. }
  1172. #else//Linux specifics follow
  1173. extern DWORD getLastError() { return errno; }
  1174. void getTempPath(char* tempPath, unsigned int bufsize, const char* subdir/*=NULL*/)
  1175. {
  1176. assert(bufsize > 5);
  1177. strcpy(tempPath, "/tmp/");
  1178. if (subdir && *subdir)
  1179. {
  1180. strcat(tempPath, subdir);
  1181. strcat(tempPath, "/");
  1182. }
  1183. }
  1184. #endif