System for quickly installing an OpenStack cloud from upstream git for testing and development.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

392 lines
14 KiB

  1. #!/bin/bash
  2. #
  3. # lib/apache
  4. # Functions to control configuration and operation of apache web server
  5. # Dependencies:
  6. #
  7. # - ``functions`` file
  8. # - ``STACK_USER`` must be defined
  9. #
  10. # lib/apache exports the following functions:
  11. #
  12. # - install_apache_wsgi
  13. # - apache_site_config_for
  14. # - enable_apache_site
  15. # - disable_apache_site
  16. # - start_apache_server
  17. # - stop_apache_server
  18. # - restart_apache_server
  19. # Save trace setting
  20. _XTRACE_LIB_APACHE=$(set +o | grep xtrace)
  21. set +o xtrace
  22. # Allow overriding the default Apache user and group, default to
  23. # current user and his default group.
  24. APACHE_USER=${APACHE_USER:-$STACK_USER}
  25. APACHE_GROUP=${APACHE_GROUP:-$(id -gn $APACHE_USER)}
  26. # Set up apache name and configuration directory
  27. # Note that APACHE_CONF_DIR is really more accurately apache's vhost
  28. # configuration dir but we can't just change this because public interfaces.
  29. if is_ubuntu; then
  30. APACHE_NAME=apache2
  31. APACHE_CONF_DIR=${APACHE_CONF_DIR:-/etc/$APACHE_NAME/sites-available}
  32. APACHE_SETTINGS_DIR=${APACHE_SETTINGS_DIR:-/etc/$APACHE_NAME/conf-enabled}
  33. elif is_fedora; then
  34. APACHE_NAME=httpd
  35. APACHE_CONF_DIR=${APACHE_CONF_DIR:-/etc/$APACHE_NAME/conf.d}
  36. APACHE_SETTINGS_DIR=${APACHE_SETTINGS_DIR:-/etc/$APACHE_NAME/conf.d}
  37. elif is_suse; then
  38. APACHE_NAME=apache2
  39. APACHE_CONF_DIR=${APACHE_CONF_DIR:-/etc/$APACHE_NAME/vhosts.d}
  40. APACHE_SETTINGS_DIR=${APACHE_SETTINGS_DIR:-/etc/$APACHE_NAME/conf.d}
  41. fi
  42. APACHE_LOG_DIR="/var/log/${APACHE_NAME}"
  43. # Functions
  44. # ---------
  45. # Enable apache mod and restart apache if it isn't already enabled.
  46. function enable_apache_mod {
  47. local mod=$1
  48. # Apache installation, because we mark it NOPRIME
  49. if is_ubuntu; then
  50. # Skip mod_version as it is not a valid mod to enable
  51. # on debuntu, instead it is built in.
  52. if [[ "$mod" != "version" ]] && ! a2query -m $mod ; then
  53. sudo a2enmod $mod
  54. restart_apache_server
  55. fi
  56. elif is_suse; then
  57. if ! a2enmod -q $mod ; then
  58. sudo a2enmod $mod
  59. restart_apache_server
  60. fi
  61. elif is_fedora; then
  62. # pass
  63. true
  64. else
  65. exit_distro_not_supported "apache enable mod"
  66. fi
  67. }
  68. # NOTE(sdague): Install uwsgi including apache module, we need to get
  69. # to 2.0.6+ to get a working mod_proxy_uwsgi. We can probably build a
  70. # check for that and do it differently for different platforms.
  71. function install_apache_uwsgi {
  72. local apxs="apxs2"
  73. if is_fedora; then
  74. apxs="apxs"
  75. fi
  76. # This varies based on packaged/installed. If we've
  77. # pip_installed, then the pip setup will only build a "python"
  78. # module that will be either python2 or python3 depending on what
  79. # it was built with.
  80. #
  81. # For package installs, the distro ships both plugins and you need
  82. # to select the right one ... it will not be autodetected.
  83. UWSGI_PYTHON_PLUGIN=python3
  84. if is_ubuntu; then
  85. local pkg_list="uwsgi uwsgi-plugin-python3 libapache2-mod-proxy-uwsgi"
  86. if [[ "$DISTRO" == 'bionic' ]]; then
  87. pkg_list="${pkg_list} uwsgi-plugin-python"
  88. fi
  89. install_package ${pkg_list}
  90. elif is_fedora; then
  91. # Note httpd comes with mod_proxy_uwsgi and it is loaded by
  92. # default; the mod_proxy_uwsgi package actually conflicts now.
  93. # See:
  94. # https://bugzilla.redhat.com/show_bug.cgi?id=1574335
  95. #
  96. # Thus there is nothing else to do after this install
  97. install_package uwsgi \
  98. uwsgi-plugin-python3
  99. elif [[ $os_VENDOR =~ openSUSE ]]; then
  100. install_package uwsgi \
  101. uwsgi-python3 \
  102. apache2-mod_uwsgi
  103. else
  104. # Compile uwsgi from source.
  105. local dir
  106. dir=$(mktemp -d)
  107. pushd $dir
  108. pip_install uwsgi
  109. pip download uwsgi -c $REQUIREMENTS_DIR/upper-constraints.txt
  110. local uwsgi
  111. uwsgi=$(ls uwsgi*)
  112. tar xvf $uwsgi
  113. cd uwsgi*/apache2
  114. sudo $apxs -i -c mod_proxy_uwsgi.c
  115. popd
  116. # delete the temp directory
  117. sudo rm -rf $dir
  118. UWSGI_PYTHON_PLUGIN=python
  119. fi
  120. if is_ubuntu || is_suse ; then
  121. # we've got to enable proxy and proxy_uwsgi for this to work
  122. sudo a2enmod proxy
  123. sudo a2enmod proxy_uwsgi
  124. elif is_fedora; then
  125. # redhat is missing a nice way to turn on/off modules
  126. echo "LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so" \
  127. | sudo tee /etc/httpd/conf.modules.d/02-proxy-uwsgi.conf
  128. fi
  129. restart_apache_server
  130. }
  131. # install_apache_wsgi() - Install Apache server and wsgi module
  132. function install_apache_wsgi {
  133. # Apache installation, because we mark it NOPRIME
  134. if is_ubuntu; then
  135. # Install apache2, which is NOPRIME'd
  136. install_package apache2
  137. if is_package_installed libapache2-mod-wsgi; then
  138. uninstall_package libapache2-mod-wsgi
  139. fi
  140. install_package libapache2-mod-wsgi-py3
  141. elif is_fedora; then
  142. sudo rm -f /etc/httpd/conf.d/000-*
  143. install_package httpd mod_wsgi
  144. # For consistency with Ubuntu, switch to the worker mpm, as
  145. # the default is event
  146. sudo sed -i '/mod_mpm_prefork.so/s/^/#/g' /etc/httpd/conf.modules.d/00-mpm.conf
  147. sudo sed -i '/mod_mpm_event.so/s/^/#/g' /etc/httpd/conf.modules.d/00-mpm.conf
  148. sudo sed -i '/mod_mpm_worker.so/s/^#//g' /etc/httpd/conf.modules.d/00-mpm.conf
  149. elif is_suse; then
  150. install_package apache2 apache2-mod_wsgi
  151. else
  152. exit_distro_not_supported "apache wsgi installation"
  153. fi
  154. # WSGI isn't enabled by default, enable it
  155. enable_apache_mod wsgi
  156. }
  157. # apache_site_config_for() - The filename of the site's configuration file.
  158. # This function uses the global variables APACHE_NAME and APACHE_CONF_DIR.
  159. #
  160. # On Ubuntu 14.04+, the site configuration file must have a .conf suffix for a2ensite and a2dissite to
  161. # recognise it. a2ensite and a2dissite ignore the .conf suffix used as parameter. The default sites'
  162. # files are 000-default.conf and default-ssl.conf.
  163. #
  164. # On Fedora and openSUSE, any file in /etc/httpd/conf.d/ whose name ends with .conf is enabled.
  165. #
  166. # On RHEL and CentOS, things should hopefully work as in Fedora.
  167. #
  168. # The table below summarizes what should happen on each distribution:
  169. # +----------------------+--------------------+--------------------------+--------------------------+
  170. # | Distribution | File name | Site enabling command | Site disabling command |
  171. # +----------------------+--------------------+--------------------------+--------------------------+
  172. # | Ubuntu 14.04 | site.conf | a2ensite site | a2dissite site |
  173. # | Fedora, RHEL, CentOS | site.conf.disabled | mv site.conf{.disabled,} | mv site.conf{,.disabled} |
  174. # +----------------------+--------------------+--------------------------+--------------------------+
  175. function apache_site_config_for {
  176. local site=$@
  177. if is_ubuntu; then
  178. # Ubuntu 14.04 - Apache 2.4
  179. echo $APACHE_CONF_DIR/${site}.conf
  180. elif is_fedora || is_suse; then
  181. # fedora conf.d is only imported if it ends with .conf so this is approx the same
  182. local enabled_site_file="$APACHE_CONF_DIR/${site}.conf"
  183. if [ -f $enabled_site_file ]; then
  184. echo ${enabled_site_file}
  185. else
  186. echo ${enabled_site_file}.disabled
  187. fi
  188. fi
  189. }
  190. # enable_apache_site() - Enable a particular apache site
  191. function enable_apache_site {
  192. local site=$@
  193. # Many of our sites use mod version. Just enable it.
  194. enable_apache_mod version
  195. if is_ubuntu; then
  196. sudo a2ensite ${site}
  197. elif is_fedora || is_suse; then
  198. local enabled_site_file="$APACHE_CONF_DIR/${site}.conf"
  199. # Do nothing if site already enabled or no site config exists
  200. if [[ -f ${enabled_site_file}.disabled ]] && [[ ! -f ${enabled_site_file} ]]; then
  201. sudo mv ${enabled_site_file}.disabled ${enabled_site_file}
  202. fi
  203. fi
  204. }
  205. # disable_apache_site() - Disable a particular apache site
  206. function disable_apache_site {
  207. local site=$@
  208. if is_ubuntu; then
  209. sudo a2dissite ${site} || true
  210. elif is_fedora || is_suse; then
  211. local enabled_site_file="$APACHE_CONF_DIR/${site}.conf"
  212. # Do nothing if no site config exists
  213. if [[ -f ${enabled_site_file} ]]; then
  214. sudo mv ${enabled_site_file} ${enabled_site_file}.disabled
  215. fi
  216. fi
  217. }
  218. # start_apache_server() - Start running apache server
  219. function start_apache_server {
  220. start_service $APACHE_NAME
  221. }
  222. # stop_apache_server() - Stop running apache server
  223. function stop_apache_server {
  224. if [ -n "$APACHE_NAME" ]; then
  225. stop_service $APACHE_NAME
  226. else
  227. exit_distro_not_supported "apache configuration"
  228. fi
  229. }
  230. # restart_apache_server
  231. function restart_apache_server {
  232. # Apache can be slow to stop, doing an explicit stop, sleep, start helps
  233. # to mitigate issues where apache will claim a port it's listening on is
  234. # still in use and fail to start.
  235. restart_service $APACHE_NAME
  236. }
  237. function write_uwsgi_config {
  238. local file=$1
  239. local wsgi=$2
  240. local url=$3
  241. local http=$4
  242. local name=""
  243. name=$(basename $wsgi)
  244. # create a home for the sockets; note don't use /tmp -- apache has
  245. # a private view of it on some platforms.
  246. local socket_dir='/var/run/uwsgi'
  247. # /var/run will be empty on ubuntu after reboot, so we can use systemd-temptiles
  248. # to automatically create $socket_dir.
  249. sudo mkdir -p /etc/tmpfiles.d/
  250. echo "d $socket_dir 0755 $STACK_USER root" | sudo tee /etc/tmpfiles.d/uwsgi.conf
  251. sudo systemd-tmpfiles --create /etc/tmpfiles.d/uwsgi.conf
  252. local socket="$socket_dir/${name}.socket"
  253. # always cleanup given that we are using iniset here
  254. rm -rf $file
  255. iniset "$file" uwsgi wsgi-file "$wsgi"
  256. iniset "$file" uwsgi processes $API_WORKERS
  257. # This is running standalone
  258. iniset "$file" uwsgi master true
  259. # Set die-on-term & exit-on-reload so that uwsgi shuts down
  260. iniset "$file" uwsgi die-on-term true
  261. iniset "$file" uwsgi exit-on-reload false
  262. # Set worker-reload-mercy so that worker will not exit till the time
  263. # configured after graceful shutdown
  264. iniset "$file" uwsgi worker-reload-mercy $WORKER_TIMEOUT
  265. iniset "$file" uwsgi enable-threads true
  266. iniset "$file" uwsgi plugins http,${UWSGI_PYTHON_PLUGIN}
  267. # uwsgi recommends this to prevent thundering herd on accept.
  268. iniset "$file" uwsgi thunder-lock true
  269. # Set hook to trigger graceful shutdown on SIGTERM
  270. iniset "$file" uwsgi hook-master-start "unix_signal:15 gracefully_kill_them_all"
  271. # Override the default size for headers from the 4k default.
  272. iniset "$file" uwsgi buffer-size 65535
  273. # Make sure the client doesn't try to re-use the connection.
  274. iniset "$file" uwsgi add-header "Connection: close"
  275. # This ensures that file descriptors aren't shared between processes.
  276. iniset "$file" uwsgi lazy-apps true
  277. # If we said bind directly to http, then do that and don't start the apache proxy
  278. if [[ -n "$http" ]]; then
  279. iniset "$file" uwsgi http $http
  280. else
  281. local apache_conf=""
  282. apache_conf=$(apache_site_config_for $name)
  283. iniset "$file" uwsgi socket "$socket"
  284. iniset "$file" uwsgi chmod-socket 666
  285. echo "ProxyPass \"${url}\" \"unix:${socket}|uwsgi://uwsgi-uds-${name}/\" retry=0 " | sudo tee -a $apache_conf
  286. enable_apache_site $name
  287. restart_apache_server
  288. fi
  289. }
  290. # For services using chunked encoding, the only services known to use this
  291. # currently are Glance and Swift, we need to use an http proxy instead of
  292. # mod_proxy_uwsgi because the chunked encoding gets dropped. See:
  293. # https://github.com/unbit/uwsgi/issues/1540 You can workaround this on python2
  294. # but that involves having apache buffer the request before sending it to
  295. # uwsgi.
  296. function write_local_uwsgi_http_config {
  297. local file=$1
  298. local wsgi=$2
  299. local url=$3
  300. name=$(basename $wsgi)
  301. # create a home for the sockets; note don't use /tmp -- apache has
  302. # a private view of it on some platforms.
  303. # always cleanup given that we are using iniset here
  304. rm -rf $file
  305. iniset "$file" uwsgi wsgi-file "$wsgi"
  306. port=$(get_random_port)
  307. iniset "$file" uwsgi http-socket "127.0.0.1:$port"
  308. iniset "$file" uwsgi processes $API_WORKERS
  309. # This is running standalone
  310. iniset "$file" uwsgi master true
  311. # Set die-on-term & exit-on-reload so that uwsgi shuts down
  312. iniset "$file" uwsgi die-on-term true
  313. iniset "$file" uwsgi exit-on-reload false
  314. iniset "$file" uwsgi enable-threads true
  315. iniset "$file" uwsgi plugins http,${UWSGI_PYTHON_PLUGIN}
  316. # uwsgi recommends this to prevent thundering herd on accept.
  317. iniset "$file" uwsgi thunder-lock true
  318. # Set hook to trigger graceful shutdown on SIGTERM
  319. iniset "$file" uwsgi hook-master-start "unix_signal:15 gracefully_kill_them_all"
  320. # Set worker-reload-mercy so that worker will not exit till the time
  321. # configured after graceful shutdown
  322. iniset "$file" uwsgi worker-reload-mercy $WORKER_TIMEOUT
  323. # Override the default size for headers from the 4k default.
  324. iniset "$file" uwsgi buffer-size 65535
  325. # Make sure the client doesn't try to re-use the connection.
  326. iniset "$file" uwsgi add-header "Connection: close"
  327. # This ensures that file descriptors aren't shared between processes.
  328. iniset "$file" uwsgi lazy-apps true
  329. iniset "$file" uwsgi chmod-socket 666
  330. iniset "$file" uwsgi http-raw-body true
  331. iniset "$file" uwsgi http-chunked-input true
  332. iniset "$file" uwsgi http-auto-chunked true
  333. iniset "$file" uwsgi http-keepalive false
  334. # Increase socket timeout for slow chunked uploads
  335. iniset "$file" uwsgi socket-timeout 30
  336. enable_apache_mod proxy
  337. enable_apache_mod proxy_http
  338. local apache_conf=""
  339. apache_conf=$(apache_site_config_for $name)
  340. echo "KeepAlive Off" | sudo tee $apache_conf
  341. echo "SetEnv proxy-sendchunked 1" | sudo tee -a $apache_conf
  342. echo "ProxyPass \"${url}\" \"http://127.0.0.1:$port\" retry=0 " | sudo tee -a $apache_conf
  343. enable_apache_site $name
  344. restart_apache_server
  345. }
  346. function remove_uwsgi_config {
  347. local file=$1
  348. local wsgi=$2
  349. local name=""
  350. name=$(basename $wsgi)
  351. rm -rf $file
  352. disable_apache_site $name
  353. }
  354. # Restore xtrace
  355. $_XTRACE_LIB_APACHE
  356. # Tell emacs to use shell-script-mode
  357. ## Local variables:
  358. ## mode: shell-script
  359. ## End: