PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/Resources/Companion/AdminRole/VMManagerService/PHPRuntimeInstaller.cs

https://bitbucket.org/zgramana/azure-accelerators-project
C# | 191 lines | 154 code | 18 blank | 19 comment | 12 complexity | bce7d11b457ce9c52a6b10c022850619 MD5 | raw file
Possible License(s): LGPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net;
  6. using System.Diagnostics;
  7. using System.IO;
  8. using System.ServiceModel.Syndication;
  9. using System.Xml;
  10. using System.Xml.Linq;
  11. using System.Text.RegularExpressions;
  12. using Microsoft.WindowsAzure.ServiceRuntime;
  13. namespace WindowsAzureCompanion.VMManagerService
  14. {
  15. public class PHPRuntimeInstaller : IInstaller
  16. {
  17. private SyndicationItem product = null;
  18. private string productVersion = null;
  19. private string downloadFolder = null;
  20. private string downloadUrl = null;
  21. private string downloadFileName = null;
  22. private string installationFolder = null;
  23. public PHPRuntimeInstaller(string installationFolder, string downloadFolder, SyndicationItem product, string productVersion)
  24. {
  25. this.product = product;
  26. this.productVersion = productVersion;
  27. this.downloadFolder = downloadFolder;
  28. this.downloadUrl = WindowsAzureVMManager.GetDownloadUrlFromProductVersion(product, productVersion);
  29. this.downloadFileName = WindowsAzureVMManager.GetAttributeValueFromProductVersion(product, productVersion, "downloadFileName");
  30. this.installationFolder = installationFolder;
  31. }
  32. // Install PHP Runtime
  33. public void Install()
  34. {
  35. try
  36. {
  37. WindowsAzureVMManager.DownloadAndExtractWebArchive(downloadUrl, downloadFileName, downloadFolder, installationFolder, null);
  38. // Configure PHP runtime
  39. ConfigurePHPRuntime();
  40. Trace.TraceInformation("Successfully installed {0}", product.Title.Text);
  41. }
  42. catch (Exception ex)
  43. {
  44. Trace.TraceError("Unable to install PHP Runtime: {0}", downloadUrl);
  45. throw ex;
  46. }
  47. }
  48. // Configure PHP runtime
  49. private void ConfigurePHPRuntime()
  50. {
  51. // Create php.ini from standard template file provided in runtime
  52. string phpIniFileName = Path.Combine(installationFolder, "php.ini");
  53. if (File.Exists(Path.Combine(installationFolder, "php.ini-recommended")))
  54. {
  55. File.Copy(Path.Combine(installationFolder, @"php.ini-recommended"), phpIniFileName);
  56. }
  57. else if (File.Exists(Path.Combine(installationFolder , @"php.ini-production")))
  58. {
  59. File.Copy(Path.Combine(installationFolder, @"php.ini-production"), phpIniFileName);
  60. }
  61. else if (File.Exists(Path.Combine(installationFolder , @"php.ini-development")))
  62. {
  63. File.Copy(Path.Combine(installationFolder, @"php.ini-development"), phpIniFileName);
  64. }
  65. else
  66. {
  67. Trace.TraceError("php.ini template not found. Unable to install PHP Runtime.");
  68. return;
  69. }
  70. // Set extension dir
  71. string extensionDir = Path.Combine(installationFolder, WindowsAzureVMManager.ExtensionsFolderForPHP);
  72. FileUtils.AppendToFile(phpIniFileName, "extension_dir = \"" + extensionDir + "\"");
  73. // Set log folder and file name
  74. string logFolderName = Path.Combine(installationFolder, "logs");
  75. Directory.CreateDirectory(logFolderName);
  76. string logFileName = Path.Combine(logFolderName, "log.txt");
  77. // Set library/framwwork directory
  78. string includePath = Path.Combine(installationFolder, WindowsAzureVMManager.LibraryFolderForPHP);
  79. // Set session path dir
  80. string tmpPath = Directory.CreateDirectory(Path.Combine(installationFolder, "tmp")).FullName;
  81. FileUtils.AppendToFile(phpIniFileName, "session.save_path = \"" + tmpPath + "\"");
  82. // Add and enable extensions
  83. // Update php.ini and enabled all extension dll specified
  84. XElement downloadUrlsElement = product.ElementExtensions.Where<SyndicationElementExtension>
  85. (x => x.OuterName == "installerFileChoices").FirstOrDefault().GetObject<XElement>();
  86. // TODO: Use Linq Query instead of foreach loop
  87. foreach (XElement extension in downloadUrlsElement.Elements())
  88. {
  89. if (extension.Attribute("version").Value.Equals(productVersion))
  90. {
  91. // Iterate through properties
  92. foreach (XElement propertyExtension in extension.Elements().First().Elements())
  93. {
  94. if (propertyExtension.Attribute("name").Value.Equals("extensions"))
  95. {
  96. string dllNames = propertyExtension.Attribute("value").Value;
  97. // Add each extension to php.ini
  98. foreach (string dllName in dllNames.Split(','))
  99. {
  100. // Enable extension only if dll is available
  101. if (File.Exists(Path.Combine(extensionDir, dllName)))
  102. {
  103. FileUtils.AppendToFile(phpIniFileName, "extension = " + dllName);
  104. Trace.TraceInformation("Enabled PHP extension {0}", dllName);
  105. }
  106. else
  107. {
  108. Trace.TraceWarning("Ignored PHP extension as {0} is not available.", dllName);
  109. }
  110. }
  111. break;
  112. }
  113. }
  114. }
  115. }
  116. // Set time zone
  117. FileUtils.AppendToFile(phpIniFileName, "date.timezone = UTC");
  118. FileUtils.AppendToFile(phpIniFileName, "max_execution_time = 900");
  119. FileUtils.AppendToFile(phpIniFileName, "max_input_time = 900");
  120. FileUtils.AppendToFile(phpIniFileName, "mysql.connect_timeout = 600");
  121. FileUtils.AppendToFile(phpIniFileName, "display_errors = On");
  122. FileUtils.AppendToFile(phpIniFileName, "display_startup_errors = On");
  123. FileUtils.AppendToFile(phpIniFileName, "post_max_size = 200M");
  124. FileUtils.AppendToFile(phpIniFileName, "upload_max_filesize = 200M");
  125. FileUtils.AppendToFile(phpIniFileName, "default_socket_timeout = 600");
  126. FileUtils.AppendToFile(phpIniFileName, "error_log = \"" + logFileName + "\"");
  127. FileUtils.AppendToFile(phpIniFileName, "error_reporting = E_ALL");
  128. FileUtils.AppendToFile(phpIniFileName, "cgi.force_redirect = 0");
  129. FileUtils.AppendToFile(phpIniFileName, "cgi.fix_pathinfo = 1");
  130. FileUtils.AppendToFile(phpIniFileName, "fastcgi.impersonate = 1");
  131. FileUtils.AppendToFile(phpIniFileName, "fastcgi.logging = 0");
  132. FileUtils.AppendToFile(phpIniFileName, "include_path = \".;" + includePath + "\"");
  133. FileUtils.AppendToFile(phpIniFileName, "variables_order=EGPCS");
  134. }
  135. // Re-configure PHP runtime
  136. public static void ReConfigurePHPRuntime(string installationFolder)
  137. {
  138. // Do not reconfigure in devfabric as we do not have xdrive path in php.ini
  139. if (RoleEnvironment.DeploymentId.StartsWith("deployment"))
  140. {
  141. return;
  142. }
  143. if (!Directory.Exists(installationFolder))
  144. {
  145. throw new System.ArgumentException(
  146. String.Format("Directory does not exist: {0}", installationFolder),
  147. "installationFolder"
  148. );
  149. }
  150. StreamReader streamReader = null;
  151. StreamWriter streamWriter = null;
  152. // Read file content
  153. string phpIniFileName = Path.Combine(installationFolder, "php.ini");
  154. if (!File.Exists(phpIniFileName))
  155. {
  156. throw new System.InvalidOperationException(
  157. String.Format("File 'php.ini' does not exist within this Directory: {0}", installationFolder)
  158. );
  159. }
  160. streamReader = File.OpenText(phpIniFileName);
  161. string contents = streamReader.ReadToEnd();
  162. streamReader.Close();
  163. // Replace old XDrive letter with new XDrive letter
  164. string letter = Path.GetPathRoot(installationFolder).Substring(0, 1);
  165. contents = Regex.Replace(contents, "\"[a-zA-Z]:\\\\", "\"" + letter + @":\");
  166. contents = Regex.Replace(contents, "\"[a-zA-Z]:/", "\"" + letter + ":/");
  167. File.Delete(phpIniFileName);
  168. streamWriter = File.CreateText(phpIniFileName);
  169. streamWriter.Write(contents);
  170. streamWriter.Close();
  171. }
  172. }
  173. }