daserver.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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 <unordered_map>
  14. #include <string>
  15. #include "platform.h"
  16. #include "thirdparty.h"
  17. #include "jlib.hpp"
  18. #include "jlog.ipp"
  19. #include "jptree.hpp"
  20. #include "jmisc.hpp"
  21. #include "jutil.hpp"
  22. #include "mpbase.hpp"
  23. #include "mpcomm.hpp"
  24. #include "mplog.hpp" //MORE: deprecated feature, not used by any new clients, remove once all deployed clients that depend on it are upgraded
  25. #include "rmtfile.hpp"
  26. #include "dacoven.hpp"
  27. #include "dadfs.hpp"
  28. #include "dasess.hpp"
  29. #include "daaudit.hpp"
  30. #include "dasds.hpp"
  31. #include "daclient.hpp"
  32. #include "dasubs.ipp"
  33. #include "danqs.hpp"
  34. #include "dadiags.hpp"
  35. #ifdef _DEBUG
  36. //#define DALI_MIN
  37. #endif
  38. #ifdef DALI_MIN
  39. #define _NO_LDAP
  40. #endif
  41. #include "daserver.hpp"
  42. #ifndef _NO_LDAP
  43. #include "daldap.hpp"
  44. #endif
  45. Owned<IPropertyTree> serverConfig;
  46. static IArrayOf<IDaliServer> servers;
  47. static CriticalSection *stopServerCrit;
  48. MODULE_INIT(INIT_PRIORITY_DALI_DASERVER)
  49. {
  50. stopServerCrit = new CriticalSection;
  51. return true;
  52. }
  53. MODULE_EXIT()
  54. {
  55. servers.kill(); // should already be clear when stopped
  56. serverConfig.clear();
  57. delete stopServerCrit;
  58. }
  59. #define DEFAULT_PERF_REPORT_DELAY 60
  60. #define DEFAULT_MOUNT_POINT "/mnt/dalimirror/"
  61. void setMsgLevel(ILogMsgHandler * fileMsgHandler, unsigned level)
  62. {
  63. ILogMsgFilter *filter = getSwitchLogMsgFilterOwn(getComponentLogMsgFilter(3), getCategoryLogMsgFilter(MSGAUD_all, MSGCLS_all, level, true), getDefaultLogMsgFilter());
  64. queryLogMsgManager()->changeMonitorFilter(queryStderrLogMsgHandler(), filter);
  65. queryLogMsgManager()->changeMonitorFilterOwn(fileMsgHandler, filter);
  66. }
  67. void AddServers(const char *auditdir)
  68. {
  69. // order significant
  70. servers.append(*createDaliSessionServer());
  71. servers.append(*createDaliPublisherServer());
  72. servers.append(*createDaliSDSServer(serverConfig));
  73. servers.append(*createDaliNamedQueueServer());
  74. servers.append(*createDaliDFSServer(serverConfig));
  75. servers.append(*createDaliAuditServer(auditdir));
  76. servers.append(*createDaliDiagnosticsServer());
  77. // add new coven servers here
  78. }
  79. static bool serverStopped = false;
  80. static void stopServer()
  81. {
  82. CriticalBlock b(*stopServerCrit); // NB: will not protect against abort handler, which will interrupt thread and be on same TID.
  83. if (serverStopped) return;
  84. serverStopped = true;
  85. ForEachItemInRev(h,servers)
  86. {
  87. IDaliServer &server=servers.item(h);
  88. LOG(MCprogress, unknownJob, "Suspending %d",h);
  89. server.suspend();
  90. }
  91. ForEachItemInRev(i,servers)
  92. {
  93. IDaliServer &server=servers.item(i);
  94. LOG(MCprogress, unknownJob, "Stopping %d",i);
  95. server.stop();
  96. }
  97. closeCoven();
  98. ForEachItemInRev(j,servers)
  99. {
  100. servers.remove(j); // ensure correct order for destruction
  101. }
  102. stopLogMsgReceivers(); //MORE: deprecated feature, not used by any new clients, remove once all deployed clients that depend on it are upgraded
  103. stopMPServer();
  104. }
  105. bool actionOnAbort()
  106. {
  107. stopServer();
  108. return true;
  109. }
  110. USE_JLIB_ALLOC_HOOK;
  111. void usage(void)
  112. {
  113. printf("daserver (option)\n");
  114. printf("--rank|-r <value>\t: dali ranking value\n");
  115. printf("--server|-s <value>\t: server ip if not local host\n");
  116. printf("--port|-p <value>\t: server port only effective if --server set\n");
  117. printf("--daemon|-d <instanceName>\t: run daemon as instance\n");
  118. }
  119. static IPropertyTree *getSecMgrPluginPropTree(const IPropertyTree *configTree)
  120. {
  121. Owned<IPropertyTree> foundTree;
  122. #ifdef _CONTAINERIZED
  123. // TODO
  124. #else
  125. Owned<IRemoteConnection> conn = querySDS().connect("/Environment", 0, 0, INFINITE);
  126. if (conn)
  127. {
  128. const IPropertyTree *proptree = conn->queryRoot()->queryPropTree("Software/DaliServerProcess[1]");
  129. if (proptree)
  130. {
  131. const char* authMethod = proptree->queryProp("@authMethod");
  132. if (strisame(authMethod, "secmgrPlugin"))
  133. {
  134. const char* authPluginType = proptree->queryProp("@authPluginType");
  135. if (authPluginType)
  136. {
  137. VStringBuffer xpath("SecurityManagers/SecurityManager[@name='%s']", authPluginType);
  138. foundTree.setown(configTree->getPropTree(xpath));
  139. if (!foundTree.get())
  140. {
  141. WARNLOG("secmgPlugin '%s' not defined in configuration", authPluginType);
  142. }
  143. }
  144. }
  145. }
  146. }
  147. #endif
  148. return foundTree.getClear();
  149. }
  150. /* NB: Ideally this belongs within common/environment,
  151. * however, that would introduce a circular dependency.
  152. */
  153. static bool populateAllowListFromEnvironment(IAllowListWriter &writer)
  154. {
  155. Owned<IRemoteConnection> conn = querySDS().connect("/Environment", 0, 0, INFINITE);
  156. assertex(conn);
  157. if (!conn->queryRoot()->hasProp("Software/DaliServerProcess"))
  158. return false;
  159. // only ever expecting 1 DaliServerProcess and 1 AllowList
  160. const IPropertyTree *allowListTree = conn->queryRoot()->queryPropTree("Software/DaliServerProcess[1]/AllowList[1]");
  161. if (!allowListTree)
  162. {
  163. // deprecated, but for backward compatibility..
  164. allowListTree = conn->queryRoot()->queryPropTree("Software/DaliServerProcess[1]/WhiteList[1]");
  165. }
  166. bool enabled = true;
  167. if (allowListTree)
  168. {
  169. enabled = allowListTree->getPropBool("@enabled", true); // on by default
  170. // Default for now is to allow clients that send no role (legacy) to connect if their IP is in allowlist.
  171. writer.setAllowAnonRoles(allowListTree->getPropBool("@allowAnonRoles", true));
  172. }
  173. std::unordered_map<std::string, std::string> machineMap;
  174. auto populateMachineMap = [&machineMap](const IPropertyTree &environment)
  175. {
  176. Owned<IPropertyTreeIterator> machineIter = environment.getElements("Hardware/Computer");
  177. ForEach(*machineIter)
  178. {
  179. const IPropertyTree &machine = machineIter->query();
  180. const char *name = machine.queryProp("@name");
  181. const char *host = machine.queryProp("@netAddress");
  182. machineMap.insert({name, host});
  183. }
  184. };
  185. auto resolveComputer = [&machineMap](const char *compName, const char *defaultValue, StringBuffer &result) -> const char *
  186. {
  187. const auto &it = machineMap.find(compName);
  188. if (it == machineMap.end())
  189. return defaultValue;
  190. IpAddress ip(it->second.c_str());
  191. if (ip.isNull())
  192. return defaultValue;
  193. return ip.getIpText(result);
  194. };
  195. auto addRoles = [&writer, &resolveComputer](const IPropertyTree &component, const std::initializer_list<unsigned __int64> &roles)
  196. {
  197. Owned<IPropertyTreeIterator> instanceIter = component.getElements("Instance");
  198. ForEach(*instanceIter)
  199. {
  200. const char *compName = instanceIter->query().queryProp("@computer");
  201. StringBuffer ipSB;
  202. const char *ip = resolveComputer(compName, component.queryProp("@netAddress"), ipSB);
  203. if (ip)
  204. {
  205. for (const auto &role: roles)
  206. writer.add(ip, role);
  207. }
  208. }
  209. };
  210. populateMachineMap(*conn->queryRoot());
  211. enum SoftwareComponentType
  212. {
  213. RoxieCluster,
  214. ThorCluster,
  215. EclAgentProcess,
  216. DfuServerProcess,
  217. EclCCServerProcess,
  218. EspProcess,
  219. SashaServerProcess,
  220. EclSchedulerProcess,
  221. DaliServerProcess,
  222. BackupNodeProcess,
  223. EclServerProcess,
  224. SparkThorProcess,
  225. };
  226. std::unordered_map<std::string, SoftwareComponentType> softwareTypeRoleMap = {
  227. { "RoxieCluster", RoxieCluster },
  228. { "ThorCluster", ThorCluster },
  229. { "EclAgentProcess", EclAgentProcess },
  230. { "DfuServerProcess", DfuServerProcess },
  231. { "EclCCServerProcess", EclCCServerProcess },
  232. { "EspProcess", EspProcess },
  233. { "SashaServerProcess", SashaServerProcess },
  234. { "EclSchedulerProcess", EclSchedulerProcess },
  235. { "DaliServerProcess", DaliServerProcess },
  236. { "BackupNodeProcess", BackupNodeProcess },
  237. { "EclServerProcess", EclServerProcess },
  238. { "SparkThorProcess", SparkThorProcess },
  239. };
  240. Owned<IPropertyTreeIterator> softwareIter = conn->queryRoot()->getElements("Software/*");
  241. ForEach(*softwareIter)
  242. {
  243. const IPropertyTree &component = softwareIter->query();
  244. const char *compProcess = component.queryName();
  245. const auto &it = softwareTypeRoleMap.find(compProcess);
  246. if (it != softwareTypeRoleMap.end())
  247. {
  248. switch (it->second)
  249. {
  250. case RoxieCluster:
  251. {
  252. Owned<IPropertyTreeIterator> serverIter = component.getElements("RoxieServerProcess");
  253. ForEach(*serverIter)
  254. {
  255. const IPropertyTree &server = serverIter->query();
  256. const char *serverCompName = server.queryProp("@computer");
  257. StringBuffer ipSB;
  258. const char *ip = resolveComputer(serverCompName, server.queryProp("@netAddress"), ipSB);
  259. if (ip)
  260. writer.add(ip, DCR_Roxie);
  261. }
  262. break;
  263. }
  264. case ThorCluster:
  265. {
  266. const char *masterCompName = component.queryProp("ThorMasterProcess/@computer");
  267. StringBuffer ipSB;
  268. const char *ip = resolveComputer(masterCompName, nullptr, ipSB);
  269. if (ip)
  270. {
  271. writer.add(ip, DCR_ThorMaster);
  272. writer.add(ip, DCR_DaliAdmin);
  273. }
  274. // NB: slaves are currently seen as foreign clients and are only used by Std.File.GetUniqueInteger (which calls Dali v. occassionally)
  275. Owned<IPropertyTreeIterator> slaveIter = component.getElements("ThorSlaveProcess");
  276. ForEach(*slaveIter)
  277. {
  278. const char *slaveCompName = slaveIter->query().queryProp("@computer");
  279. const char *ip = resolveComputer(slaveCompName, nullptr, ipSB.clear());
  280. if (ip)
  281. writer.add(ip, DCR_ThorSlave);
  282. }
  283. break;
  284. }
  285. case EclAgentProcess:
  286. addRoles(component, { DCR_EclAgent, DCR_AgentExec });
  287. break;
  288. case DfuServerProcess:
  289. addRoles(component, { DCR_DfuServer });
  290. break;
  291. case EclCCServerProcess:
  292. addRoles(component, { DCR_EclCCServer, DCR_EclCC });
  293. break;
  294. case EclServerProcess:
  295. addRoles(component, { DCR_EclServer, DCR_EclCC });
  296. break;
  297. case EspProcess:
  298. addRoles(component, { DCR_EspServer });
  299. break;
  300. case SashaServerProcess:
  301. addRoles(component, { DCR_SashaServer, DCR_XRef });
  302. break;
  303. case EclSchedulerProcess:
  304. addRoles(component, { DCR_EclScheduler });
  305. break;
  306. case BackupNodeProcess:
  307. addRoles(component, { DCR_BackupGen, DCR_DaliAdmin });
  308. break;
  309. case DaliServerProcess:
  310. addRoles(component, { DCR_DaliServer, DCR_DaliDiag, DCR_SwapNode, DCR_UpdateEnv, DCR_DaliAdmin, DCR_TreeView, DCR_Testing, DCR_DaFsControl, DCR_XRef, DCR_Config, DCR_ScheduleAdmin, DCR_Monitoring, DCR_DaliStop });
  311. break;
  312. case SparkThorProcess:
  313. addRoles(component, { DCR_DaliAdmin });
  314. break;
  315. }
  316. }
  317. }
  318. if (allowListTree)
  319. {
  320. Owned<IPropertyTreeIterator> allowListIter = allowListTree->getElements("Entry");
  321. ForEach(*allowListIter)
  322. {
  323. const IPropertyTree &entry = allowListIter->query();
  324. StringArray hosts, roles;
  325. hosts.appendListUniq(entry.queryProp("@hosts"), ",");
  326. roles.appendListUniq(entry.queryProp("@roles"), ",");
  327. ForEachItemIn(h, hosts)
  328. {
  329. IpAddress ip(hosts.item(h));
  330. if (!ip.isNull())
  331. {
  332. StringBuffer ipStr;
  333. ip.getIpText(ipStr);
  334. ForEachItemIn(r, roles)
  335. {
  336. const char *roleStr = roles.item(r);
  337. char *endPtr;
  338. long numericRole = strtol(roleStr, &endPtr, 10);
  339. if (endPtr != roleStr && (numericRole>0 && numericRole<DCR_Max)) // in case legacy role needs adding
  340. writer.add(ipStr.str(), numericRole);
  341. else
  342. writer.add(ipStr.str(), queryRole(roleStr));
  343. }
  344. }
  345. }
  346. }
  347. }
  348. return enabled;
  349. }
  350. static StringBuffer &formatDaliRole(StringBuffer &out, unsigned __int64 role)
  351. {
  352. return out.append(queryRoleName((DaliClientRole)role));
  353. }
  354. static constexpr const char * defaultYaml = R"!!(
  355. version: 1.0
  356. dali:
  357. name: dali
  358. dataPath: "/var/lib/HPCCSystems/dalistorage"
  359. logging:
  360. detail: 100
  361. )!!";
  362. int main(int argc, const char* argv[])
  363. {
  364. rank_t myrank = 0;
  365. const char *server = nullptr;
  366. int port = 0;
  367. InitModuleObjects();
  368. NoQuickEditSection x;
  369. try
  370. {
  371. EnableSEHtoExceptionMapping();
  372. #ifndef __64BIT__
  373. // Restrict stack sizes on 32-bit systems
  374. Thread::setDefaultStackSize(0x20000);
  375. #endif
  376. setAllocHook(true);
  377. serverConfig.setown(loadConfiguration(defaultYaml, argv, "dali", "DALI", DALICONF, nullptr));
  378. Owned<IFile> sentinelFile = createSentinelTarget();
  379. removeSentinelFile(sentinelFile);
  380. #ifndef _CONTAINERIZED
  381. for (unsigned i=1;i<(unsigned)argc;i++) {
  382. if (streq(argv[i],"--daemon") || streq(argv[i],"-d")) {
  383. if (daemon(1,0) || write_pidfile(argv[++i])) {
  384. perror("Failed to daemonize");
  385. return EXIT_FAILURE;
  386. }
  387. }
  388. else if (streq(argv[i],"--server") || streq(argv[i],"-s"))
  389. server = argv[++i];
  390. else if (streq(argv[i],"--port") || streq(argv[i],"-p"))
  391. port = atoi(argv[++i]);
  392. else if (streq(argv[i],"--rank") || streq(argv[i],"-r"))
  393. myrank = atoi(argv[++i]);
  394. else if (!startsWith(argv[i],"--config"))
  395. {
  396. usage();
  397. return EXIT_FAILURE;
  398. }
  399. }
  400. #endif
  401. #ifndef _CONTAINERIZED
  402. ILogMsgHandler * fileMsgHandler;
  403. {
  404. Owned<IComponentLogFileCreator> lf = createComponentLogFileCreator(serverConfig, "dali");
  405. lf->setLogDirSubdir("server");//add to tail of config log dir
  406. lf->setName("DaServer");//override default filename
  407. fileMsgHandler = lf->beginLogging();
  408. }
  409. #else
  410. setupContainerizedLogMsgHandler();
  411. #endif
  412. PROGLOG("Build %s", hpccBuildTag);
  413. StringBuffer dataPath;
  414. StringBuffer mirrorPath;
  415. #ifdef _CONTAINERIZED
  416. serverConfig->getProp("@dataPath", dataPath);
  417. /* NB: mirror settings are unlikely to be used in a container setup
  418. If detected, set in to legacy location under SDS/ for backward compatibility */
  419. serverConfig->getProp("@remoteBackupLocation", mirrorPath);
  420. if (mirrorPath.length())
  421. serverConfig->setProp("SDS/@remoteBackupLocation", mirrorPath);
  422. #else
  423. if (getConfigurationDirectory(serverConfig->queryPropTree("Directories"),"dali","dali",serverConfig->queryProp("@name"),dataPath))
  424. serverConfig->setProp("@dataPath",dataPath.str());
  425. else if (getConfigurationDirectory(serverConfig->queryPropTree("Directories"),"data","dali",serverConfig->queryProp("@name"),dataPath))
  426. serverConfig->setProp("@dataPath",dataPath.str());
  427. else
  428. serverConfig->getProp("@dataPath",dataPath);
  429. if (dataPath.length())
  430. {
  431. RemoteFilename rfn;
  432. rfn.setRemotePath(dataPath);
  433. if (!rfn.isLocal())
  434. {
  435. OERRLOG("if a dataPath is specified, it must be on local machine");
  436. return 0;
  437. }
  438. }
  439. // JCSMORE remoteBackupLocation should not be a property of SDS section really.
  440. if (!getConfigurationDirectory(serverConfig->queryPropTree("Directories"),"mirror","dali",serverConfig->queryProp("@name"),mirrorPath))
  441. serverConfig->getProp("SDS/@remoteBackupLocation",mirrorPath);
  442. #endif
  443. if (dataPath.length())
  444. {
  445. addPathSepChar(dataPath); // ensures trailing path separator
  446. serverConfig->setProp("@dataPath", dataPath.str());
  447. recursiveCreateDirectory(dataPath.str());
  448. }
  449. if (mirrorPath.length())
  450. {
  451. try
  452. {
  453. addPathSepChar(mirrorPath);
  454. try
  455. {
  456. StringBuffer backupURL;
  457. if (mirrorPath.length()<=2 || !isPathSepChar(mirrorPath.charAt(0)) || !isPathSepChar(mirrorPath.charAt(1)))
  458. { // local machine path, convert to url
  459. const char *backupnode = serverConfig->queryProp("SDS/@backupComputer");
  460. RemoteFilename rfn;
  461. if (backupnode&&*backupnode) {
  462. SocketEndpoint ep(backupnode);
  463. rfn.setPath(ep,mirrorPath.str());
  464. }
  465. else {
  466. OWARNLOG("Local path used for backup url: %s", mirrorPath.str());
  467. rfn.setLocalPath(mirrorPath.str());
  468. }
  469. rfn.getRemotePath(backupURL);
  470. mirrorPath.clear().append(backupURL);
  471. }
  472. else
  473. backupURL.append(mirrorPath);
  474. recursiveCreateDirectory(backupURL.str());
  475. addPathSepChar(backupURL);
  476. serverConfig->setProp("SDS/@remoteBackupLocation", backupURL.str());
  477. PROGLOG("Backup URL = %s", backupURL.str());
  478. }
  479. catch (IException *e)
  480. {
  481. EXCLOG(e, "Failed to create remote backup directory, disabling backups", MSGCLS_warning);
  482. serverConfig->removeProp("SDS/@remoteBackupLocation");
  483. mirrorPath.clear();
  484. e->Release();
  485. }
  486. if (mirrorPath.length())
  487. {
  488. PROGLOG("Checking backup location: %s", mirrorPath.str());
  489. #if defined(__linux__)
  490. if (serverConfig->getPropBool("@useNFSBackupMount", false))
  491. {
  492. RemoteFilename rfn;
  493. if (mirrorPath.length()<=2 || !isPathSepChar(mirrorPath.charAt(0)) || !isPathSepChar(mirrorPath.charAt(1)))
  494. rfn.setLocalPath(mirrorPath.str());
  495. else
  496. rfn.setRemotePath(mirrorPath.str());
  497. if (!rfn.getPort() && !rfn.isLocal())
  498. {
  499. StringBuffer mountPoint;
  500. serverConfig->getProp("@mountPoint", mountPoint);
  501. if (!mountPoint.length())
  502. mountPoint.append(DEFAULT_MOUNT_POINT);
  503. addPathSepChar(mountPoint);
  504. recursiveCreateDirectory(mountPoint.str());
  505. PROGLOG("Mounting url \"%s\" on mount point \"%s\"", mirrorPath.str(), mountPoint.str());
  506. bool ub = unmountDrive(mountPoint.str());
  507. if (!mountDrive(mountPoint.str(), rfn))
  508. {
  509. if (!ub)
  510. PROGLOG("Failed to remount mount point \"%s\", possibly in use?", mountPoint.str());
  511. else
  512. PROGLOG("Failed to mount \"%s\"", mountPoint.str());
  513. return 0;
  514. }
  515. else
  516. serverConfig->setProp("SDS/@remoteBackupLocation", mountPoint.str());
  517. mirrorPath.clear().append(mountPoint);
  518. }
  519. }
  520. #endif
  521. StringBuffer backupCheck(dataPath);
  522. backupCheck.append("bakchk.").append((unsigned)GetCurrentProcessId());
  523. OwnedIFile iFileDataDir = createIFile(backupCheck.str());
  524. OwnedIFileIO iFileIO = iFileDataDir->open(IFOcreate);
  525. iFileIO.clear();
  526. try
  527. {
  528. backupCheck.clear().append(mirrorPath).append("bakchk.").append((unsigned)GetCurrentProcessId());
  529. OwnedIFile iFileBackup = createIFile(backupCheck.str());
  530. if (iFileBackup->exists())
  531. {
  532. PROGLOG("remoteBackupLocation and dali data path point to same location! : %s", mirrorPath.str());
  533. iFileDataDir->remove();
  534. return 0;
  535. }
  536. }
  537. catch (IException *)
  538. {
  539. try { iFileDataDir->remove(); } catch (IException *e) { EXCLOG(e, NULL); e->Release(); }
  540. throw;
  541. }
  542. iFileDataDir->remove();
  543. #ifndef _CONTAINERIZED
  544. StringBuffer dest(mirrorPath.str());
  545. dest.append(DALICONF);
  546. copyFile(dest.str(), DALICONF);
  547. StringBuffer covenPath(dataPath);
  548. OwnedIFile ifile = createIFile(covenPath.append(DALICOVEN).str());
  549. if (ifile->exists())
  550. {
  551. dest.clear().append(mirrorPath.str()).append(DALICOVEN);
  552. copyFile(dest.str(), covenPath.str());
  553. }
  554. #endif
  555. }
  556. if (serverConfig->getPropBool("@daliServixCaching", true))
  557. setDaliServixSocketCaching(true);
  558. }
  559. catch (IException *e)
  560. {
  561. StringBuffer s("Failure whilst preparing dali backup location: ");
  562. LOG(MCoperatorError, unknownJob, e, s.append(mirrorPath).append(". Backup disabled").str());
  563. serverConfig->removeProp("SDS/@remoteBackupLocation");
  564. e->Release();
  565. }
  566. }
  567. #ifndef _CONTAINERIZED
  568. write_pidfile(serverConfig->queryProp("@name"));
  569. NamedMutex globalNamedMutex("DASERVER");
  570. if (!serverConfig->getPropBool("allowMultipleDalis"))
  571. {
  572. PROGLOG("Checking for existing daserver instances");
  573. if (!globalNamedMutex.lockWait(0))
  574. {
  575. OWARNLOG("Another DASERVER process is currently running");
  576. return 0;
  577. }
  578. }
  579. #endif
  580. SocketEndpoint ep;
  581. SocketEndpointArray epa;
  582. if (!server)
  583. {
  584. ep.setLocalHost(DALI_SERVER_PORT);
  585. epa.append(ep);
  586. }
  587. else
  588. {
  589. if (!port)
  590. ep.set(server,DALI_SERVER_PORT);
  591. else
  592. ep.set(server,port);
  593. epa.append(ep);
  594. }
  595. unsigned short myport = epa.item(myrank).port;
  596. startMPServer(DCR_DaliServer, myport, true, true);
  597. #ifndef _CONTAINERIZED
  598. Owned<IMPServer> mpServer = getMPServer();
  599. Owned<IAllowListHandler> allowListHandler = createAllowListHandler(populateAllowListFromEnvironment, formatDaliRole);
  600. mpServer->installAllowListCallback(allowListHandler);
  601. setMsgLevel(fileMsgHandler, serverConfig->getPropInt("SDS/@msgLevel", 100));
  602. #endif
  603. startLogMsgChildReceiver();
  604. startLogMsgParentReceiver();
  605. IGroup *group = createIGroup(epa);
  606. initCoven(group,serverConfig);
  607. group->Release();
  608. epa.kill();
  609. // Audit logging
  610. StringBuffer auditDir;
  611. {
  612. Owned<IComponentLogFileCreator> lf = createComponentLogFileCreator(serverConfig, "dali");
  613. lf->setLogDirSubdir("audit");//add to tail of config log dir
  614. lf->setName("DaAudit");//override default filename
  615. lf->setCreateAliasFile(false);
  616. lf->setMsgFields(MSGFIELD_timeDate | MSGFIELD_code | MSGFIELD_job);
  617. lf->setMsgAudiences(MSGAUD_audit);
  618. lf->setMaxDetail(TopDetail);
  619. lf->beginLogging();
  620. auditDir.set(lf->queryLogDir());
  621. }
  622. // SNMP logging
  623. bool enableSNMP = serverConfig->getPropBool("SDS/@enableSNMP");
  624. if (serverConfig->getPropBool("SDS/@enableSysLog",true))
  625. UseSysLogForOperatorMessages();
  626. AddServers(auditDir.str());
  627. addAbortHandler(actionOnAbort);
  628. #ifndef _CONTAINERIZED
  629. startPerformanceMonitor(serverConfig->getPropInt("Coven/@perfReportDelay", DEFAULT_PERF_REPORT_DELAY)*1000);
  630. #endif
  631. StringBuffer absPath;
  632. makeAbsolutePath(dataPath.str(), absPath);
  633. setPerformanceMonitorPrimaryFileSystem(absPath.str());
  634. if (mirrorPath.length())
  635. {
  636. absPath.clear();
  637. makeAbsolutePath(mirrorPath.str(), absPath);
  638. setPerformanceMonitorSecondaryFileSystem(absPath.str());
  639. }
  640. try
  641. {
  642. ForEachItemIn(i1,servers)
  643. {
  644. IDaliServer &server=servers.item(i1);
  645. server.start();
  646. }
  647. }
  648. catch (IException *e)
  649. {
  650. EXCLOG(e, "Failed whilst starting servers");
  651. stopServer();
  652. #ifndef _CONTAINERIZED
  653. stopPerformanceMonitor();
  654. #endif
  655. throw;
  656. }
  657. try {
  658. #ifndef _NO_LDAP
  659. Owned<IPropertyTree> secMgrPropTree = getSecMgrPluginPropTree(serverConfig);
  660. if (secMgrPropTree.get())
  661. {
  662. setLDAPconnection(createDaliSecMgrPluginConnection(secMgrPropTree));
  663. }
  664. else
  665. {
  666. setLDAPconnection(createDaliLdapConnection(serverConfig->getPropTree("Coven/ldapSecurity")));
  667. }
  668. #endif
  669. }
  670. catch (IException *e) {
  671. EXCLOG(e, "LDAP initialization error");
  672. stopServer();
  673. #ifndef _CONTAINERIZED
  674. stopPerformanceMonitor();
  675. #endif
  676. throw;
  677. }
  678. PROGLOG("DASERVER[%d] starting - listening to port %d",myrank,queryMyNode()->endpoint().port);
  679. startMPServer(DCR_DaliServer, myport, false, true);
  680. bool ok = true;
  681. ForEachItemIn(i2,servers)
  682. {
  683. IDaliServer &server=servers.item(i2);
  684. try {
  685. server.ready();
  686. }
  687. catch (IException *e) {
  688. EXCLOG(e,"Exception starting Dali Server");
  689. ok = false;
  690. }
  691. }
  692. if (ok) {
  693. writeSentinelFile(sentinelFile);
  694. covenMain();
  695. removeAbortHandler(actionOnAbort);
  696. }
  697. stopServer();
  698. #ifndef _CONTAINERIZED
  699. stopPerformanceMonitor();
  700. #endif
  701. }
  702. catch (IException *e) {
  703. EXCLOG(e, "Exception");
  704. }
  705. UseSysLogForOperatorMessages(false);
  706. return 0;
  707. }