EspDeploymentEngine.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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 "jptree.hpp"
  14. #include "jmutex.hpp"
  15. #include "jexcept.hpp"
  16. #include "environment.hpp"
  17. #include "xslprocessor.hpp"
  18. #include "EspDeploymentEngine.hpp"
  19. #include <vector>
  20. #include <set>
  21. using std::set;
  22. using std::string;
  23. //---------------------------------------------------------------------------
  24. // CEspDeploymentEngine
  25. //---------------------------------------------------------------------------
  26. CEspDeploymentEngine::CEspDeploymentEngine(IEnvDeploymentEngine& envDepEngine,
  27. IDeploymentCallback& callback,
  28. IPropertyTree& process)
  29. : CDeploymentEngine(envDepEngine, callback, process, "./Instance")
  30. {
  31. }
  32. //---------------------------------------------------------------------------
  33. // check
  34. //---------------------------------------------------------------------------
  35. void CEspDeploymentEngine::check()
  36. {
  37. CDeploymentEngine::check();
  38. // Make sure all protocol and service referenced by bindings are valid
  39. Owned<IPropertyTreeIterator> iter = m_process.getElements("EspBinding");
  40. for (iter->first(); iter->isValid(); iter->next())
  41. {
  42. IPropertyTree* pBinding = &iter->query();
  43. const char* service = pBinding->queryProp("@service");
  44. if (service)
  45. {
  46. if (!lookupProcess("EspService", service))
  47. throw MakeStringException(0, "Process %s references unknown service %s", m_name.get(), service);
  48. }
  49. else
  50. throw MakeStringException(-1, "The ESP binding %s for ESP %s has missing service information!",
  51. pBinding->queryProp("@name"), m_name.get());
  52. }
  53. // Make sure DaliServers are valid
  54. iter.setown(m_process.getElements(".//*[@daliServers]"));
  55. ForEach(*iter)
  56. {
  57. const char* name = iter->query().queryProp("@daliServers");
  58. if (name && *name && !lookupProcess("DaliServerProcess", name))
  59. throw MakeStringException(0, "Process %s references unknown DaliServers %s", m_name.get(), name);
  60. }
  61. // Make sure EclServer is valid
  62. iter.setown(m_process.getElements(".//*[@eclServer]"));
  63. ForEach(*iter)
  64. {
  65. const char* name = iter->query().queryProp("@eclServer");
  66. if (name && *name && !lookupProcess("EclServerProcess", name))
  67. throw MakeStringException(0, "Process %s references unknown EclServer %s", m_name.get(), name);
  68. }
  69. // Make sure AttributeServer is valid
  70. iter.setown(m_process.getElements(".//*[@attributeServer]"));
  71. ForEach(*iter)
  72. {
  73. const char* name = iter->query().queryProp("@attributeServer");
  74. if (name && *name && !lookupProcess("AttrServerProcess", name))
  75. throw MakeStringException(0, "Process %s references unknown AttributeServer %s", m_name.get(), name);
  76. }
  77. }
  78. //---------------------------------------------------------------------------
  79. // createInstallFileMap
  80. //---------------------------------------------------------------------------
  81. int CEspDeploymentEngine::determineInstallFiles(IPropertyTree& node, CInstallFiles& installFiles) const
  82. {
  83. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Merging file lists for ESP server and its bound service(s) ...");
  84. const char* myBuild = m_process.queryProp("@build");
  85. //process bindings for this esp process and add files for each service used by
  86. //each binding before adding files for this esp process
  87. Owned<IPropertyTreeIterator> iBinding = m_process.getElements("EspBinding");
  88. ForEach(*iBinding)
  89. {
  90. IPropertyTree* pBinding = &iBinding->query();
  91. const char* szService = pBinding->queryProp("@service");
  92. // Lookup plugin process
  93. IPropertyTree* pService = lookupProcess("EspService", szService);
  94. if (!pService)
  95. throw MakeStringException(0, "Process %s references unknown esp service '%s'", m_name.get(), szService);
  96. const char* pszBuild = pService->queryProp("@build");
  97. if (!pszBuild || 0 != strcmp(pszBuild, myBuild))
  98. throw MakeStringException(0, "ESP service '%s' used by ESP process '%s'\n has a different build (%s) to its ESP process!",
  99. szService, m_name.get(), pszBuild);
  100. // Get plugin file list from the plugin process
  101. CDeploymentEngine::determineInstallFiles(*pService, installFiles);
  102. }
  103. int rc = CDeploymentEngine::determineInstallFiles(node, installFiles);
  104. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "determineInstallFiles complete");
  105. return rc;
  106. }
  107. //---------------------------------------------------------------------------
  108. // processCustomMethod
  109. //---------------------------------------------------------------------------
  110. void CEspDeploymentEngine::processCustomMethod(const char *method, const char *source, const char *outputFile,
  111. const char *instanceName, EnvMachineOS os)
  112. {
  113. if (!stricmp(method, "ssl_certificate"))
  114. {
  115. //we only need to worry about SSL certificates and private keys if https is being used
  116. //by any of our bindings
  117. //
  118. Owned<IPropertyTreeIterator> it = m_process.getElements("EspBinding[@protocol='https']");
  119. if (!it->first())
  120. return;
  121. }
  122. CDeploymentEngine::processCustomMethod(method, source, outputFile, instanceName, os);
  123. }
  124. //---------------------------------------------------------------------------
  125. // xslTransform
  126. //---------------------------------------------------------------------------
  127. void CEspDeploymentEngine::xslTransform(
  128. const char *xslFilePath, const char *outputFilePath,
  129. const char* instanceName, EnvMachineOS os/*=MachineOsUnknown*/,
  130. const char* processName/*=NULL*/,
  131. bool isEspModuleOrPlugin/*=false*/)
  132. {
  133. m_createIni = false;
  134. // Skip if not processing config files
  135. checkAbort();
  136. if (!m_compare)
  137. ensurePath(outputFilePath);
  138. if (m_compare)
  139. outputFilePath = setCompare(outputFilePath);
  140. if (instanceName)
  141. {
  142. m_transform->setParameter("instance", StringBuffer("'").append(instanceName).append("'").str());
  143. const char* szXslFileName = pathTail(xslFilePath);
  144. if (!stricmp(szXslFileName, "esp.xsl"))
  145. {
  146. //disable compare since these transforms are needed by us in any case for esp.xml
  147. const bool bCompare = m_compare;
  148. m_compare = false;
  149. //we need to pass in a list of file names created as a result of individual esp service modules
  150. //running xslt using method xslt_esp_service on their own service specific XSL files as specified
  151. //in install set (created by release_<service>.bat
  152. //
  153. //esp.xsl merges these in the output under /Environment/Software/EspProcess
  154. //
  155. StringBuffer serviceXsltOutputFiles;
  156. processServiceModules("esp_plugin", serviceXsltOutputFiles, instanceName, os);
  157. processServiceModules("esp_service_module", serviceXsltOutputFiles, instanceName, os);
  158. m_compare = bCompare;
  159. IEnvDeploymentEngine& envDepEngine = getEnvDepEngine();
  160. const char* srcDaliAddress = envDepEngine.getSourceDaliAddress();
  161. m_transform->setParameter("espServiceName", "''");
  162. m_transform->setParameter("serviceFilesList", StringBuffer("'").append(serviceXsltOutputFiles.str()).append("'").str());
  163. m_transform->setParameter("deployedFromDali", StringBuffer("'").append(srcDaliAddress).append("'").str());
  164. }
  165. }
  166. if (m_deployFlags & DEFLAGS_CONFIGFILES) //are we processing config files?
  167. {
  168. Owned<IDeployTask> task =
  169. createDeployTask(*m_pCallback, "XSL Transform", m_process.queryName(), m_name.get(),
  170. instanceName, xslFilePath, outputFilePath, m_curSSHUser.str(), m_curSSHKeyFile.str(), m_curSSHKeyPassphrase.str(),
  171. m_useSSHIfDefined, os, processName);
  172. m_pCallback->printStatus(task);
  173. task->transformFile(*m_processor, *m_transform, m_cachePath.get());
  174. m_pCallback->printStatus(task);
  175. checkAbort(task);
  176. }
  177. if (m_compare)
  178. compareFiles(os);
  179. }
  180. void CEspDeploymentEngine::processServiceModules(const char* moduleType,
  181. StringBuffer& serviceXsltOutputFiles,
  182. const char* instanceName,
  183. EnvMachineOS os)
  184. {
  185. set<string> serviceNamesProcessed;
  186. bool bEspServiceModule = !stricmp(moduleType, "esp_service_module");
  187. char tempPath[_MAX_PATH];
  188. getTempPath(tempPath, sizeof(tempPath), m_name);
  189. const CInstallFileList& fileList = m_installFiles.getInstallFileList();
  190. CInstallFileList::const_iterator i = fileList.begin();
  191. CInstallFileList::const_iterator iEnd = fileList.end();
  192. for (; i != iEnd; i++)
  193. {
  194. const CInstallFile& installFile = *(*i);
  195. const char* method = installFile.getMethod().c_str();
  196. if (!stricmp(method, moduleType))
  197. {
  198. const char* source = installFile.getSrcPath().c_str();
  199. std::string dest = installFile.getDestPath().c_str();
  200. //our base class method CDeploymentEngine::determineInstallFiles() encoded
  201. //dest is of the format <destpath>+<service name> so extract both of the parts
  202. //
  203. std::string::size_type pos = dest.find_last_of('+');
  204. std::string serviceName = dest.substr(pos+1);
  205. dest.erase(pos);
  206. if ((pos = dest.find("@temp" PATHSEPSTR)) != std::string::npos)
  207. dest.replace(pos, strlen("@temp" PATHSEPSTR), tempPath);
  208. //if method is esp_service_module then check to see if not processing config files
  209. //
  210. bool bProcess = true;
  211. if (bEspServiceModule)
  212. {
  213. if (m_deployFlags & DEFLAGS_CONFIGFILES)
  214. {
  215. //each esp_service_module for a given service name is expected to produce necessary
  216. //and sufficient information for itself (EspService node) and all its EspBindings
  217. //(we may have multiple bindings for the same service i.e. EspService[@name='xyz']).
  218. //Therefore, we only need to process one instance of EspService exactly once.
  219. if (serviceNamesProcessed.find(serviceName) != serviceNamesProcessed.end())
  220. continue;
  221. serviceNamesProcessed.insert(serviceName);
  222. serviceXsltOutputFiles.append(dest.c_str());
  223. serviceXsltOutputFiles.append(';');
  224. }
  225. else
  226. bProcess = false;
  227. }
  228. if (bProcess)
  229. {
  230. serviceName.insert(0, "\'");
  231. serviceName += '\'';
  232. m_transform->setParameter("espServiceName", serviceName.c_str());
  233. CDeploymentEngine::xslTransform(source, dest.c_str(), instanceName, os, NULL, true);
  234. }
  235. }
  236. }
  237. }