PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/common/environment/dalienv.cpp

http://github.com/hpcc-systems/HPCC-Platform
C++ | 416 lines | 341 code | 48 blank | 27 comment | 40 complexity | da090f4cc3ebbd25fb4dbf7d3db263ba MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT
  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 "platform.h"
  14. #include "jlib.hpp"
  15. #include "jio.hpp"
  16. #include "jmutex.hpp"
  17. #include "jfile.hpp"
  18. #include "jptree.hpp"
  19. #include "dasds.hpp"
  20. #include "daclient.hpp"
  21. #include "environment.hpp"
  22. #include "dalienv.hpp"
  23. #include "rmtfile.hpp"
  24. struct CIpInstance
  25. {
  26. unsigned hash;
  27. IpAddress ip;
  28. CIpInstance(const IpAddress &_ip)
  29. : ip(_ip)
  30. {
  31. hash = ip.iphash();
  32. }
  33. static unsigned getHash(const char *key)
  34. {
  35. return ((const IpAddress *)key)->iphash();
  36. }
  37. bool eq(const char *key)
  38. {
  39. return ((const IpAddress *)key)->ipequals(ip);
  40. }
  41. };
  42. struct CIpPasswordInstance: public CIpInstance
  43. {
  44. StringAttr password;
  45. StringAttr user;
  46. bool matched;
  47. CIpPasswordInstance(const IpAddress &_ip)
  48. : CIpInstance(_ip)
  49. {
  50. matched = false;
  51. }
  52. static void destroy(CIpPasswordInstance *i) { delete i; }
  53. static CIpPasswordInstance *create(const char *key) { return new CIpPasswordInstance(*(const IpAddress *)key); }
  54. };
  55. struct CIpPasswordHashTable: public CMinHashTable<CIpPasswordInstance>
  56. {
  57. };
  58. struct CIpOsInstance: public CIpInstance
  59. {
  60. EnvMachineOS os;
  61. CIpOsInstance(const IpAddress &key)
  62. : CIpInstance(key)
  63. {
  64. os=MachineOsUnknown;
  65. }
  66. static void destroy(CIpOsInstance *i) { delete i; }
  67. static CIpOsInstance *create(const char *key) { return new CIpOsInstance(*(const IpAddress *)key); }
  68. };
  69. class CIpOsHashTable: public CMinHashTable<CIpOsInstance>
  70. {
  71. };
  72. //---------------------------------------------------------------------------
  73. static CriticalSection ipcachesect;
  74. static CIpOsHashTable *ipToOsCache = NULL;
  75. EnvMachineOS queryOS(const IpAddress & ip)
  76. {
  77. if (ip.isLocal()) { // we know!
  78. #ifdef _WIN32
  79. return MachineOsW2K;
  80. #else
  81. return MachineOsLinux;
  82. #endif
  83. }
  84. CriticalBlock block(ipcachesect);
  85. EnvMachineOS ret = MachineOsUnknown;
  86. if (!ipToOsCache)
  87. ipToOsCache = new CIpOsHashTable;
  88. CIpOsInstance * match = ipToOsCache->find((const char *)&ip,false);
  89. if (match)
  90. ret = match->os;
  91. else {
  92. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  93. Owned<IConstEnvironment> env = factory->openEnvironment();
  94. StringBuffer ipText;
  95. ip.getIpText(ipText);
  96. Owned<IConstMachineInfo> machine = env->getMachineByAddress(ipText.str());
  97. if (machine)
  98. ret = machine->getOS();
  99. if (ret==MachineOsUnknown) { // lets try asking dafilesrv
  100. SocketEndpoint ep(0,ip);
  101. switch (getDaliServixOs(ep)) {
  102. case DAFS_OSwindows: ret = MachineOsW2K; break;
  103. case DAFS_OSlinux: ret = MachineOsLinux; break;
  104. case DAFS_OSsolaris: ret = MachineOsSolaris; break;
  105. }
  106. }
  107. match = new CIpOsInstance(ip);
  108. match->os = ret;
  109. ipToOsCache->add(match);
  110. }
  111. return ret;
  112. }
  113. bool canAccessFilesDirectly(const IpAddress & ip)
  114. {
  115. if (ip.isLocal()||ip.isNull()) // the isNull check is probably an error but saves time
  116. return true; // I think usually already checked, but another can't harm
  117. #ifdef _WIN32
  118. EnvMachineOS os = queryOS(ip);
  119. if (os==MachineOsW2K)
  120. return true;
  121. if ((os==MachineOsUnknown)&&!testDaliServixPresent(ip))
  122. return true; // maybe lucky if windows
  123. #endif
  124. return false;
  125. }
  126. bool canSpawnChildProcess(const IpAddress & ip)
  127. {
  128. //MORE: This isn't the correct implementation, but at least the calls now have the
  129. //correct name.
  130. return canAccessFilesDirectly(ip);
  131. }
  132. bool canAccessFilesDirectly(const char * ipText)
  133. {
  134. IpAddress ip(ipText);
  135. return canAccessFilesDirectly(ip);
  136. }
  137. bool canAccessFilesDirectly(const RemoteFilename & file)
  138. {
  139. if (file.queryEndpoint().port!=0)
  140. return false;
  141. #ifdef _WIN32
  142. if (!file.isUnixPath()) // assume any windows path can be accessed using windows share
  143. return true;
  144. #endif
  145. return canAccessFilesDirectly(file.queryIP());
  146. }
  147. void setCanAccessDirectly(RemoteFilename & file)
  148. {
  149. setCanAccessDirectly(file,canAccessFilesDirectly(file));
  150. }
  151. class CDaliEnvIntercept: public CInterface, implements IRemoteFileCreateHook
  152. {
  153. bool active;
  154. CriticalSection crit;
  155. public:
  156. IMPLEMENT_IINTERFACE;
  157. CDaliEnvIntercept() { active = false; }
  158. virtual IFile * createIFile(const RemoteFilename & filename)
  159. {
  160. CriticalBlock block(crit);
  161. if (active||!daliClientActive())
  162. return NULL;
  163. active = true;
  164. IFile * ret;
  165. if (canAccessFilesDirectly(filename))
  166. ret = NULL;
  167. else
  168. ret = createDaliServixFile(filename);
  169. active = false;
  170. return ret;
  171. }
  172. } *DaliEnvIntercept;
  173. MODULE_INIT(INIT_PRIORITY_ENV_DALIENV)
  174. {
  175. DaliEnvIntercept = new CDaliEnvIntercept;
  176. addIFileCreateHook(DaliEnvIntercept);
  177. return true;
  178. }
  179. MODULE_EXIT()
  180. {
  181. removeIFileCreateHook(DaliEnvIntercept);
  182. ::Release(DaliEnvIntercept);
  183. delete ipToOsCache;
  184. ipToOsCache = NULL;
  185. }
  186. //---------------------------------------------------------------------------
  187. const char * querySlaveExecutable(const char * keyName, const char * exeName, const char * version, const IpAddress &ip, StringBuffer &progpath, StringBuffer &workdir)
  188. {
  189. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  190. Owned<IConstEnvironment> env = factory->openEnvironment();
  191. StringBuffer addr;
  192. ip.getIpText(addr);
  193. StringBufferAdaptor spp(progpath);
  194. StringBufferAdaptor swd(workdir);
  195. if (!env->getRunInfo(spp, swd, keyName, version, addr.str(), exeName)) {
  196. #ifdef _DEBUG
  197. //printf("slave path not found\n");
  198. progpath.append(exeName);
  199. #ifdef _WIN32
  200. progpath.append(".exe");
  201. #endif
  202. #else
  203. throw MakeStringException(1, "Could not find the location of the slave program %s for machine %s", keyName, addr.str());
  204. #endif
  205. }
  206. // on linux check that file exists where it is supposed to be
  207. #ifndef _WIN32
  208. if (progpath.length()) {
  209. RemoteFilename rfn;
  210. SocketEndpoint ep;
  211. ep.ipset(ip);
  212. rfn.setPath(ep,progpath.str());
  213. Owned<IFile> file = createIFile(rfn);
  214. if (!file->exists()) {
  215. WARNLOG("Could not find the the slave program %s for machine %s at %s", keyName, addr.str(), progpath.str());
  216. throw MakeStringException(1, "Could not find the slave program %s for machine %s at %s", keyName, addr.str(), progpath.str());
  217. }
  218. }
  219. #endif
  220. return progpath.str();
  221. }
  222. bool getRemoteRunInfo(const char * keyName, const char * exeName, const char * version, const IpAddress &ip, StringBuffer &progpath, StringBuffer &workdir, INode *remotedali, unsigned timeout)
  223. {
  224. // use dafilesrv to work out OS
  225. StringBuffer dalis;
  226. if (remotedali)
  227. remotedali->endpoint().getUrlStr(dalis);
  228. // first get machine by IP
  229. StringBuffer ips;
  230. ip.getIpText(ips);
  231. //Cannot use getEnvironmentFactory() since it is using a remotedali
  232. StringBuffer xpath;
  233. xpath.appendf("Environment/Hardware/Computer[@netAddress=\"%s\"]", ips.str());
  234. Owned<IPropertyTreeIterator> iter = querySDS().getElementsRaw(xpath,remotedali,timeout);
  235. if (!iter->first()) {
  236. ERRLOG("Unable to find machine for %s on dali %s", ips.str(),dalis.str());
  237. return false;
  238. }
  239. Owned<IPropertyTree> machine;
  240. machine.setown(&iter->get());
  241. const char *domainname = machine->queryProp("@domain");
  242. if (!domainname||!*domainname) {
  243. ERRLOG("Unable to find domain for %s on dali %s", ips.str(),dalis.str());
  244. return false;
  245. }
  246. xpath.clear().appendf("Environment/Software/%s",keyName);
  247. if (version)
  248. xpath.appendf("[@version='%s']",version);
  249. xpath.append("/Instance");
  250. iter.clear();
  251. iter.setown(querySDS().getElementsRaw(xpath,remotedali,timeout));
  252. ForEach(*iter) {
  253. IPropertyTree *inst = &iter->query();
  254. const char * comp = inst->queryProp("@computer");
  255. if (comp) {
  256. xpath.clear().appendf("Environment/Hardware/Computer[@name=\"%s\"]", comp);
  257. Owned<IPropertyTreeIterator> iter2 = querySDS().getElementsRaw(xpath,remotedali,timeout);
  258. if (iter2->first()) {
  259. Owned<IPropertyTree> machine2= &iter2->get();
  260. const char *domainname2 = machine2->queryProp("@domain");
  261. const char *ips2 = machine2->queryProp("@netAddress");
  262. if (ips2&&*ips2&&domainname2&&*domainname2&&(strcmp(domainname,domainname2)==0)) {
  263. bool appendexe;
  264. char psep;
  265. SocketEndpoint ep(ips2);
  266. if (getDaliServixOs(ep)==DAFS_OSwindows) {
  267. psep = '\\';
  268. appendexe = true;
  269. }
  270. else {
  271. psep = '/';
  272. appendexe = false;
  273. }
  274. StringBuffer tmp;
  275. const char *program = inst->queryProp("@program"); // if program specified assume absolute
  276. if (!program||!*program) {
  277. tmp.append(psep).append(psep).append(ips2).append(psep).append(inst->queryProp("@directory")).append(psep).append(exeName);
  278. size32_t l = strlen(exeName);
  279. if (appendexe&&((l<5)||(stricmp(exeName+l-4,".exe")!=0)))
  280. tmp.append(".exe");
  281. program = tmp.str();
  282. }
  283. progpath.set(program);
  284. const char *workd = inst->queryProp("@workdir"); // if program specified assume absolute
  285. workdir.set(workd?workd:"");
  286. return true;
  287. }
  288. }
  289. }
  290. }
  291. return false;
  292. }
  293. bool envGetConfigurationDirectory(const char *category, const char *component,const char *instance, StringBuffer &dirout)
  294. {
  295. SessionId sessid = myProcessSession();
  296. if (!sessid)
  297. return false;
  298. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  299. Owned<IConstEnvironment> env = factory->openEnvironment();
  300. Owned<IPropertyTree> root = &env->getPTree();
  301. IPropertyTree * child = root->queryPropTree("Software/Directories");
  302. if (child)
  303. return getConfigurationDirectory(child,category,component,instance,dirout);
  304. return false;
  305. }
  306. IPropertyTree *envGetNASConfiguration(IPropertyTree *source)
  307. {
  308. if ((NULL==source) || !source->hasProp("NAS"))
  309. return NULL;
  310. // check for NAS node : <Hardware><NAS><Filter ....><Filter ....>..</NAS></Hardware>
  311. if (source->hasProp("NAS/Filter"))
  312. return createPTreeFromIPT(source->queryPropTree("NAS"));
  313. else
  314. {
  315. // check for 'flat' format : <Hardware><NAS ...../><NAS ..../>....</Hardware>
  316. Owned<IPropertyTreeIterator> nasIter = source->getElements("NAS");
  317. if (!nasIter->first())
  318. return NULL;
  319. Owned<IPropertyTree> nas = createPTree("NAS");
  320. do
  321. {
  322. IPropertyTree *filter = &nasIter->query();
  323. nas->addPropTree("Filter", LINK(filter));
  324. }
  325. while (nasIter->next());
  326. return nas.getClear();
  327. }
  328. }
  329. IPropertyTree *envGetNASConfiguration()
  330. {
  331. SessionId sessid = myProcessSession();
  332. if (!sessid)
  333. return NULL;
  334. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  335. Owned<IConstEnvironment> env = factory->openEnvironment();
  336. Owned<IPropertyTree> root = &env->getPTree();
  337. IPropertyTree * hardware = root->queryPropTree("Hardware");
  338. if (hardware)
  339. return envGetNASConfiguration(hardware);
  340. return NULL;
  341. }
  342. IPropertyTree *envGetInstallNASHooks(SocketEndpoint *myEp)
  343. {
  344. Owned<IPropertyTree> nasPTree = envGetNASConfiguration();
  345. return envGetInstallNASHooks(nasPTree, myEp);
  346. }
  347. IPropertyTree *envGetInstallNASHooks(IPropertyTree *nasPTree, SocketEndpoint *myEp)
  348. {
  349. IDaFileSrvHook *daFileSrvHook = queryDaFileSrvHook();
  350. if (!daFileSrvHook) // probably always installed
  351. return NULL;
  352. daFileSrvHook->clearFilters();
  353. if (!nasPTree)
  354. return NULL;
  355. return daFileSrvHook->addMyFilters(nasPTree, myEp);
  356. }
  357. void envInstallNASHooks(SocketEndpoint *myEp)
  358. {
  359. Owned<IPropertyTree> installedFilters = envGetInstallNASHooks(myEp);
  360. }
  361. void envInstallNASHooks(IPropertyTree *nasPTree, SocketEndpoint *myEp)
  362. {
  363. Owned<IPropertyTree> installedFilters = envGetInstallNASHooks(nasPTree, myEp);
  364. }