deploy.cpp 50 KB

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