espconfiggenengine.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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 "espconfiggenengine.hpp"
  19. #include <vector>
  20. #include <set>
  21. using std::set;
  22. using std::string;
  23. //---------------------------------------------------------------------------
  24. // CEspConfigGenEngine
  25. //---------------------------------------------------------------------------
  26. CEspConfigGenEngine::CEspConfigGenEngine(IEnvDeploymentEngine& envDepEngine,
  27. IDeploymentCallback& callback,
  28. IPropertyTree& process, const char* inputDir,
  29. const char* outputDir)
  30. : CConfigGenEngine(envDepEngine, callback, process, inputDir, outputDir, "./Instance")
  31. {
  32. }
  33. //---------------------------------------------------------------------------
  34. // check
  35. //---------------------------------------------------------------------------
  36. void CEspConfigGenEngine::check()
  37. {
  38. CConfigGenEngine::check();
  39. // Make sure all protocol and service referenced by bindings are valid
  40. Owned<IPropertyTreeIterator> iter = m_process.getElements("EspBinding");
  41. for (iter->first(); iter->isValid(); iter->next())
  42. {
  43. IPropertyTree* pBinding = &iter->query();
  44. const char* service = pBinding->queryProp("@service");
  45. if (service)
  46. {
  47. if (!lookupProcess("EspService", service))
  48. throw MakeStringException(0, "Process %s references unknown service %s", m_name.get(), service);
  49. }
  50. else
  51. throw MakeStringException(-1, "The ESP binding %s for ESP %s has missing service information!",
  52. pBinding->queryProp("@name"), m_name.get());
  53. }
  54. // Make sure DaliServers are valid
  55. iter.setown(m_process.getElements(".//*[@daliServers]"));
  56. ForEach(*iter)
  57. {
  58. const char* name = iter->query().queryProp("@daliServers");
  59. if (name && *name && !lookupProcess("DaliServerProcess", name))
  60. throw MakeStringException(0, "Process %s references unknown DaliServers %s", m_name.get(), name);
  61. }
  62. // Make sure EclServer is valid
  63. iter.setown(m_process.getElements(".//*[@eclServer]"));
  64. ForEach(*iter)
  65. {
  66. const char* name = iter->query().queryProp("@eclServer");
  67. if (name && *name && !lookupProcess("EclServerProcess", name))
  68. throw MakeStringException(0, "Process %s references unknown EclServer %s", m_name.get(), name);
  69. }
  70. // Make sure AttributeServer is valid
  71. iter.setown(m_process.getElements(".//*[@attributeServer]"));
  72. ForEach(*iter)
  73. {
  74. const char* name = iter->query().queryProp("@attributeServer");
  75. if (name && *name && !lookupProcess("AttrServerProcess", name))
  76. throw MakeStringException(0, "Process %s references unknown AttributeServer %s", m_name.get(), name);
  77. }
  78. }
  79. //---------------------------------------------------------------------------
  80. // createInstallFileMap
  81. //---------------------------------------------------------------------------
  82. int CEspConfigGenEngine::determineInstallFiles(IPropertyTree& node, CInstallFiles& installFiles) const
  83. {
  84. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Merging file lists for ESP server and its bound service(s) ...");
  85. const char* myBuild = m_process.queryProp("@build");
  86. //process bindings for this esp process and add files for each service used by
  87. //each binding before adding files for this esp process
  88. Owned<IPropertyTreeIterator> iBinding = m_process.getElements("EspBinding");
  89. ForEach(*iBinding)
  90. {
  91. IPropertyTree* pBinding = &iBinding->query();
  92. const char* szService = pBinding->queryProp("@service");
  93. // Lookup plugin process
  94. IPropertyTree* pService = lookupProcess("EspService", szService);
  95. if (!pService)
  96. throw MakeStringException(0, "Process %s references unknown esp service '%s'", m_name.get(), szService);
  97. const char* pszBuild = pService->queryProp("@build");
  98. if (!pszBuild || 0 != strcmp(pszBuild, myBuild))
  99. throw MakeStringException(0, "ESP service '%s' used by ESP process '%s'\n has a different build (%s) to its ESP process!",
  100. szService, m_name.get(), pszBuild);
  101. // Get plugin file list from the plugin process
  102. CConfigGenEngine::determineInstallFiles(*pService, installFiles);
  103. }
  104. int rc = CConfigGenEngine::determineInstallFiles(node, installFiles);
  105. m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "determineInstallFiles complete");
  106. return rc;
  107. }
  108. //---------------------------------------------------------------------------
  109. // processCustomMethod
  110. //---------------------------------------------------------------------------
  111. void CEspConfigGenEngine::processCustomMethod(const char *method, const char *source, const char *outputFile,
  112. const char *instanceName, EnvMachineOS os)
  113. {
  114. if (!stricmp(method, "ssl_certificate"))
  115. {
  116. //we only need to worry about SSL certificates and private keys if https is being used
  117. //by any of our bindings
  118. //
  119. Owned<IPropertyTreeIterator> it = m_process.getElements("EspBinding[@protocol='https']");
  120. if (!it->first())
  121. return;
  122. }
  123. CConfigGenEngine::processCustomMethod(method, source, outputFile, instanceName, os);
  124. }
  125. //---------------------------------------------------------------------------
  126. // xslTransform
  127. //---------------------------------------------------------------------------
  128. void CEspConfigGenEngine::xslTransform(
  129. const char *xslFilePath, const char *outputFilePath,
  130. const char* instanceName, EnvMachineOS os/*=MachineOsUnknown*/,
  131. const char* processName/*=NULL*/,
  132. bool isEspModuleOrPlugin/*=false*/)
  133. {
  134. m_createIni = false;
  135. // Skip if not processing config files
  136. checkAbort();
  137. if (!m_compare)
  138. ensurePath(outputFilePath);
  139. if (m_compare)
  140. outputFilePath = setCompare(outputFilePath);
  141. if (instanceName)
  142. {
  143. m_transform->setParameter("instance", StringBuffer("'").append(instanceName).append("'").str());
  144. const char* szXslFileName = pathTail(xslFilePath);
  145. if (!stricmp(szXslFileName, "esp.xsl"))
  146. {
  147. //disable compare since these transforms are needed by us in any case for esp.xml
  148. const bool bCompare = m_compare;
  149. m_compare = false;
  150. //we need to pass in a list of file names created as a result of individual esp service modules
  151. //running xslt using method xslt_esp_service on their own service specific XSL files as specified
  152. //in install set (created by release_<service>.bat
  153. //
  154. //esp.xsl merges these in the output under /Environment/Software/EspProcess
  155. //
  156. StringBuffer serviceXsltOutputFiles;
  157. processServiceModules("esp_plugin", serviceXsltOutputFiles, instanceName, os);
  158. processServiceModules("esp_service_module", serviceXsltOutputFiles, instanceName, os);
  159. m_compare = bCompare;
  160. IEnvDeploymentEngine& envDepEngine = getEnvDepEngine();
  161. const char* srcDaliAddress = envDepEngine.getSourceDaliAddress();
  162. m_transform->setParameter("espServiceName", "''");
  163. m_transform->setParameter("serviceFilesList", StringBuffer("'").append(serviceXsltOutputFiles.str()).append("'").str());
  164. m_transform->setParameter("deployedFromDali", StringBuffer("'").append(srcDaliAddress).append("'").str());
  165. }
  166. }
  167. if (m_deployFlags & DEFLAGS_CONFIGFILES) //are we processing config files?
  168. {
  169. Owned<IDeployTask> task =
  170. createDeployTask(*m_pCallback, "XSL Transform", m_process.queryName(), m_name.get(),
  171. instanceName, xslFilePath, outputFilePath, m_curSSHUser.str(), m_curSSHKeyFile.str(), m_curSSHKeyPassphrase.str(), 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 CEspConfigGenEngine::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 CConfigGenEngine::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. serviceNamesProcessed.insert(serviceName);
  216. serviceXsltOutputFiles.append(dest.c_str());
  217. serviceXsltOutputFiles.append(';');
  218. }
  219. else
  220. bProcess = false;
  221. }
  222. if (bProcess)
  223. {
  224. serviceName.insert(0, "\'");
  225. serviceName += '\'';
  226. m_transform->setParameter("espServiceName", serviceName.c_str());
  227. CConfigGenEngine::xslTransform(source, dest.c_str(), instanceName, os, NULL, true);
  228. }
  229. }
  230. }
  231. }