PageRenderTime 1512ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/http/Provision/Service/http/nginx.php

https://gitlab.com/aegir/provision
PHP | 281 lines | 186 code | 33 blank | 62 comment | 28 complexity | d337680ad1bba116bd65e8709b051ef5 MD5 | raw file
  1. <?php
  2. class Provision_Service_http_nginx extends Provision_Service_http_public {
  3. // Define static socket file locations for various PHP versions.
  4. // These are dynamic in PHP 7.
  5. const SOCKET_PATH_PHP5 = '/var/run/php5-fpm.sock';
  6. const SOCKET_PATH_PHP7_BASE = '/var/run/php';
  7. protected $application_name = 'nginx';
  8. protected $has_restart_cmd = TRUE;
  9. function default_restart_cmd() {
  10. return Provision_Service_http_nginx::nginx_restart_cmd();
  11. }
  12. function cloaked_db_creds() {
  13. return TRUE;
  14. }
  15. function init_server() {
  16. parent::init_server();
  17. $this->configs['server'][] = 'Provision_Config_Nginx_Server';
  18. $this->configs['server'][] = 'Provision_Config_Nginx_Inc_Server';
  19. $this->configs['site'][] = 'Provision_Config_Nginx_Site';
  20. $this->server->setProperty('nginx_config_mode', 'extended');
  21. $this->server->setProperty('nginx_is_modern', FALSE);
  22. $this->server->setProperty('nginx_has_etag', FALSE);
  23. $this->server->setProperty('nginx_has_http2', FALSE);
  24. $this->server->setProperty('nginx_has_gzip', FALSE);
  25. $this->server->setProperty('nginx_has_upload_progress', FALSE);
  26. $this->server->setProperty('provision_db_cloaking', TRUE);
  27. $this->server->setProperty('phpfpm_mode', 'port');
  28. $this->server->setProperty('subdirs_support', FALSE);
  29. $this->server->setProperty('satellite_mode', 'vanilla');
  30. if (provision_hosting_feature_enabled('subdirs')) {
  31. $this->server->subdirs_support = TRUE;
  32. $this->configs['site'][] = 'Provision_Config_Nginx_Subdir';
  33. $this->configs['site'][] = 'Provision_Config_Nginx_SubdirVhost';
  34. }
  35. }
  36. function save_server() {
  37. // Set correct provision_db_cloaking value on server save.
  38. $this->server->provision_db_cloaking = TRUE;
  39. // Find nginx executable.
  40. if (provision_file()->exists('/usr/local/sbin/nginx')->status()) {
  41. $path = "/usr/local/sbin/nginx";
  42. }
  43. elseif (provision_file()->exists('/usr/sbin/nginx')->status()) {
  44. $path = "/usr/sbin/nginx";
  45. }
  46. elseif (provision_file()->exists('/usr/local/bin/nginx')->status()) {
  47. $path = "/usr/local/bin/nginx";
  48. }
  49. else {
  50. return;
  51. }
  52. // Check if some nginx features are supported and save them for later.
  53. $this->server->shell_exec($path . ' -V');
  54. $this->server->nginx_is_modern = preg_match("/nginx\/1\.((1\.(8|9|(1[0-9]+)))|((2|3|4|5|6|7|8|9|[1-9][0-9]+)\.))/", implode('', drush_shell_exec_output()), $match);
  55. $this->server->nginx_has_etag = preg_match("/nginx\/1\.([12][0-9]|[3]\.([12][0-9]|[3-9]))/", implode('', drush_shell_exec_output()), $match);
  56. $this->server->nginx_has_http2 = preg_match("/http_v2_module/", implode('', drush_shell_exec_output()), $match);
  57. $this->server->nginx_has_upload_progress = preg_match("/upload/", implode('', drush_shell_exec_output()), $match);
  58. $this->server->nginx_has_gzip = preg_match("/http_gzip_static_module/", implode('', drush_shell_exec_output()), $match);
  59. // Use basic nginx configuration if this control file exists.
  60. $nginx_config_mode_file = "/etc/nginx/basic_nginx.conf";
  61. if (provision_file()->exists($nginx_config_mode_file)->status()) {
  62. $this->server->nginx_config_mode = 'basic';
  63. drush_log(dt('Basic Nginx Config Active -SAVE- YES control file found @path.', array('@path' => $nginx_config_mode_file)));
  64. }
  65. else {
  66. $this->server->nginx_config_mode = 'extended';
  67. drush_log(dt('Extended Nginx Config Active -SAVE- NO control file found @path.', array('@path' => $nginx_config_mode_file)));
  68. }
  69. // Check if there is php-fpm listening on unix socket, otherwise use port 9000 to connect
  70. $this->server->phpfpm_mode = $this->getPhpFpmMode('save');
  71. // Check if there is BOA specific global.inc file to enable extra Nginx locations
  72. if (provision_file()->exists('/data/conf/global.inc')->status()) {
  73. $this->server->satellite_mode = 'boa';
  74. drush_log(dt('BOA mode detected -SAVE- YES file found @path.', array('@path' => '/data/conf/global.inc')));
  75. }
  76. else {
  77. $this->server->satellite_mode = 'vanilla';
  78. drush_log(dt('Vanilla mode detected -SAVE- NO file found @path.', array('@path' => '/data/conf/global.inc')));
  79. }
  80. // Set correct subdirs_support value on server save
  81. if (provision_hosting_feature_enabled('subdirs')) {
  82. $this->server->subdirs_support = TRUE;
  83. }
  84. }
  85. function verify_server_cmd() {
  86. // Set correct provision_db_cloaking value on server verify.
  87. $this->server->provision_db_cloaking = TRUE;
  88. // Find nginx executable.
  89. if (provision_file()->exists('/usr/local/sbin/nginx')->status()) {
  90. $path = "/usr/local/sbin/nginx";
  91. }
  92. elseif (provision_file()->exists('/usr/sbin/nginx')->status()) {
  93. $path = "/usr/sbin/nginx";
  94. }
  95. elseif (provision_file()->exists('/usr/local/bin/nginx')->status()) {
  96. $path = "/usr/local/bin/nginx";
  97. }
  98. else {
  99. return;
  100. }
  101. // Check if some nginx features are supported and save them for later.
  102. $this->server->shell_exec($path . ' -V');
  103. $this->server->nginx_is_modern = preg_match("/nginx\/1\.((1\.(8|9|(1[0-9]+)))|((2|3|4|5|6|7|8|9|[1-9][0-9]+)\.))/", implode('', drush_shell_exec_output()), $match);
  104. $this->server->nginx_has_etag = preg_match("/nginx\/1\.([12][0-9]|[3]\.([12][0-9]|[3-9]))/", implode('', drush_shell_exec_output()), $match);
  105. $this->server->nginx_has_http2 = preg_match("/http_v2_module/", implode('', drush_shell_exec_output()), $match);
  106. $this->server->nginx_has_upload_progress = preg_match("/upload/", implode('', drush_shell_exec_output()), $match);
  107. $this->server->nginx_has_gzip = preg_match("/http_gzip_static_module/", implode('', drush_shell_exec_output()), $match);
  108. // Use basic nginx configuration if this control file exists.
  109. $nginx_config_mode_file = "/etc/nginx/basic_nginx.conf";
  110. if (provision_file()->exists($nginx_config_mode_file)->status()) {
  111. $this->server->nginx_config_mode = 'basic';
  112. drush_log(dt('Basic Nginx Config Active -VERIFY- YES control file found @path.', array('@path' => $nginx_config_mode_file)));
  113. }
  114. else {
  115. $this->server->nginx_config_mode = 'extended';
  116. drush_log(dt('Extended Nginx Config Active -VERIFY- NO control file found @path.', array('@path' => $nginx_config_mode_file)));
  117. }
  118. // Check if there is php-fpm listening on unix socket, otherwise use port 9000 to connect
  119. $this->server->phpfpm_mode = $this->getPhpFpmMode('verify');
  120. // Check if there is BOA specific global.inc file to enable extra Nginx locations
  121. if (provision_file()->exists('/data/conf/global.inc')->status()) {
  122. $this->server->satellite_mode = 'boa';
  123. drush_log(dt('BOA mode detected -VERIFY- YES file found @path.', array('@path' => '/data/conf/global.inc')));
  124. }
  125. else {
  126. $this->server->satellite_mode = 'vanilla';
  127. drush_log(dt('Vanilla mode detected -VERIFY- NO file found @path.', array('@path' => '/data/conf/global.inc')));
  128. }
  129. // Set correct subdirs_support value on server verify
  130. if (provision_hosting_feature_enabled('subdirs')) {
  131. $this->server->subdirs_support = TRUE;
  132. }
  133. // Call the parent at the end. it will restart the server when it finishes.
  134. parent::verify_server_cmd();
  135. }
  136. /**
  137. * Determines the PHP FPM mode.
  138. *
  139. * @param string $server_task
  140. * The server task type for logging purposes. Leave blank to skip logging.
  141. * @return string
  142. * The mode, either 'socket' or 'port'.
  143. */
  144. public static function getPhpFpmMode($server_task = NULL) {
  145. // Search for socket files or fall back to port mode.
  146. switch (TRUE) {
  147. case provision_file()->exists(self::SOCKET_PATH_PHP5)->status():
  148. $mode = 'socket';
  149. $socket_path = self::SOCKET_PATH_PHP5;
  150. break;
  151. case provision_file()->exists(static::getPhp7FpmSocketPath())->status():
  152. $mode = 'socket';
  153. $socket_path = static::getPhp7FpmSocketPath();
  154. break;
  155. default:
  156. $mode = 'port';
  157. $socket_path = '';
  158. break;
  159. }
  160. // Report results in the log if requested.
  161. if (!empty($server_task)) {
  162. drush_log(dt('PHP-FPM @mode mode detected -' . '@task' . '- @yes_or_no socket found @path.', array(
  163. '@mode' => ($mode == 'socket') ? 'unix socket' : 'port',
  164. '@task' => strtoupper($server_task),
  165. '@yes_or_no' => ($mode == 'socket') ? 'YES' : 'NO',
  166. '@path' => ($socket_path ? $socket_path : self::SOCKET_PATH_PHP5 . ' or ' . static::getPhp7FpmSocketPath()),
  167. )));
  168. }
  169. // Return the discovered mode.
  170. return $mode;
  171. }
  172. /**
  173. * Gets the PHP FPM unix socket path.
  174. *
  175. * If we're running in port mode, there is no socket path. FALSE would be
  176. * returned in this case.
  177. *
  178. * @return string
  179. * The path, or FALSE if there isn't one.
  180. */
  181. public static function getPhpFpmSocketPath() {
  182. // Simply return FALSE if we're in port mode.
  183. if (self::getPhpFpmMode() == 'port') {
  184. return FALSE;
  185. }
  186. // Return the socket path based on the PHP version.
  187. if (strtok(phpversion(), '.') == 7) {
  188. return static::getPhp7FpmSocketPath();
  189. }
  190. else {
  191. return self::SOCKET_PATH_PHP5;
  192. }
  193. }
  194. /**
  195. * Gets the PHP FPM unix socket path for PHP 7.
  196. *
  197. * In PHP 7, there isn't a fixed socked path. It could be any one of the
  198. * following:
  199. * * php7.0-fpm.sock
  200. * * php7.2-fpm.sock
  201. * * ...
  202. *
  203. * @return string
  204. * The path, or FALSE if there isn't one.
  205. */
  206. public static function getPhp7FpmSocketPath() {
  207. foreach (scandir(static::SOCKET_PATH_PHP7_BASE, SCANDIR_SORT_DESCENDING) as $file) {
  208. if (strpos($file, 'fpm.sock')) {
  209. $path = static::SOCKET_PATH_PHP7_BASE . '/' . $file;
  210. # Confirm the socket file actually exists before returning it.
  211. if (file_exists($path)) {
  212. return $path;
  213. }
  214. }
  215. }
  216. return FALSE;
  217. }
  218. /**
  219. * Guess at the likely value of the http_restart_cmd.
  220. *
  221. * This method is a static so that it can be re-used by the nginx_ssl
  222. * service, even though it does not inherit this class.
  223. */
  224. public static function nginx_restart_cmd() {
  225. $command = '/etc/init.d/nginx'; // A proper default for most of the world
  226. $options[] = $command;
  227. // Try to detect the nginx restart command.
  228. foreach (explode(':', $_SERVER['PATH']) as $path) {
  229. $options[] = "$path/nginx";
  230. }
  231. $options[] = '/usr/sbin/nginx';
  232. $options[] = '/usr/local/sbin/nginx';
  233. $options[] = '/usr/local/bin/nginx';
  234. foreach ($options as $test) {
  235. if (is_executable($test)) {
  236. $command = ($test == '/etc/init.d/nginx') ? $test : $test . ' -s';
  237. break;
  238. }
  239. }
  240. return "sudo $command reload";
  241. }
  242. /**
  243. * Restart/reload nginx to pick up the new config files.
  244. */
  245. function parse_configs() {
  246. return $this->restart();
  247. }
  248. }