From 8f8a84f15cfce8cef71a3e0fea4c49cb5f533206 Mon Sep 17 00:00:00 2001 From: Kevin Carter Date: Wed, 7 Sep 2022 21:44:22 -0500 Subject: [PATCH] Add uwsgi option to horizon This change provides the horizon role the ability to deploy its services using uWSGI instead of apache. This feature produces a minimal horizon deployment which is perfectly functional in cases where capabilities like federation and SSL terminated all the way through are not needed. Change-Id: I457a111511543731746d868ae7f7184743e5703b Signed-off-by: Kevin Carter --- defaults/main.yml | 7 ++++ handlers/main.yml | 2 +- .../notes/horizon_uwsgi-28d22fc08594ecb3.yaml | 15 +++++++++ tasks/horizon_apache.yml | 16 +++++----- tasks/horizon_install.yml | 2 +- tasks/horizon_post_install.yml | 10 +++--- tasks/horizon_post_install_source.yml | 2 +- tasks/horizon_ssl_key_create.yml | 2 +- tasks/horizon_ssl_user_provided.yml | 6 ++-- tasks/horizon_translations_update.yml | 2 +- tasks/horizon_uwsgi.yml | 32 +++++++++++++++++++ tasks/main.yml | 2 +- vars/debian.yml | 8 +++-- vars/distro_install.yml | 10 +++++- vars/main.yml | 18 +++++++++++ vars/redhat.yml | 12 ++++--- vars/source_install.yml | 9 +++++- 17 files changed, 123 insertions(+), 32 deletions(-) create mode 100644 releasenotes/notes/horizon_uwsgi-28d22fc08594ecb3.yaml create mode 100644 tasks/horizon_uwsgi.yml diff --git a/defaults/main.yml b/defaults/main.yml index a6c47f81..e5108534 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -39,6 +39,9 @@ horizon_git_repo: https://opendev.org/openstack/horizon horizon_git_track_branch: master horizon_git_install_branch: "{{ horizon_git_track_branch }}" +# Enable or disable apache. If disabled a basic uwsgi deployment will be setup for this service. +horizon_use_uwsgi: false + ## The git source/branch for the Adjutant UI plugin adjutant_dashboard_git_repo: https://opendev.org/openstack/adjutant-ui adjutant_dashboard_git_install_branch: "{{ horizon_git_track_branch }}" @@ -153,6 +156,7 @@ horizon_lib_wsgi_file: "{{ horizon_lib_dir }}/openstack_dashboard/wsgi.py" horizon_endpoint_type: internalURL horizon_server_name: "{{ ansible_facts['fqdn'] | default('horizon') }}" + horizon_apache_servertokens: "Prod" horizon_apache_serversignature: "Off" horizon_log_level: info @@ -505,6 +509,9 @@ horizon_config_overrides: {} # "volume:create": "rule:admin_or_owner" horizon_policy_overrides: {} +horizon_init_overrides: {} +horizon_uwsgi_ini_overrides: {} + horizon_keystone_admin_roles: - admin diff --git a/handlers/main.yml b/handlers/main.yml index f16fb8f1..291fbf78 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -22,7 +22,7 @@ listen: - "venv changed" -- name: Restart apache2 +- name: Restart wsgi process service: name: "{{ horizon_system_service_name }}" enabled: yes diff --git a/releasenotes/notes/horizon_uwsgi-28d22fc08594ecb3.yaml b/releasenotes/notes/horizon_uwsgi-28d22fc08594ecb3.yaml new file mode 100644 index 00000000..5af12dff --- /dev/null +++ b/releasenotes/notes/horizon_uwsgi-28d22fc08594ecb3.yaml @@ -0,0 +1,15 @@ +--- +features: + - | + Horizon now has the ability to run directly from uWSGI. To support + this feature the new Boolean variable `horizon_use_uwsgi` has + been added. The new variable, when set to **true**, will omit the + apache2 install process and instead run horizon from a uWSGI process + leveraging a systemd service file. +other: + - | + When the option `horizon_use_uwsgi` is enabled, operators need + to be aware that not all horizon capabilities will be present. The + minimal uSGI process is just that, minimal, and not full featured. + If the deployment requires full featured capabilities, the apache + based deployment should remain enabled. diff --git a/tasks/horizon_apache.yml b/tasks/horizon_apache.yml index 5277f002..198fded1 100644 --- a/tasks/horizon_apache.yml +++ b/tasks/horizon_apache.yml @@ -23,7 +23,7 @@ - "{{ horizon_apache_modules }}" when: - ansible_facts['pkg_mgr'] == 'apt' - notify: Restart apache2 + notify: Restart wsgi process - name: Drop apache2 configs template: @@ -32,14 +32,14 @@ owner: "{{ item.owner | default(horizon_system_user_name) }}" group: "{{ item.group | default(horizon_system_group_name) }}" with_items: "{{ horizon_apache_configs }}" - notify: Restart apache2 + notify: Restart wsgi process - name: Disable default apache site file: path: "{{ item }}" state: "absent" with_items: "{{ horizon_apache_default_sites }}" - notify: Restart apache2 + notify: Restart wsgi process - name: Enable Horizon Site file: @@ -49,27 +49,27 @@ when: - horizon_apache_site_available is defined - horizon_apache_site_enabled is defined - notify: Restart apache2 + notify: Restart wsgi process - name: Ensure Apache ServerName lineinfile: dest: "{{ horizon_apache_conf }}" line: "ServerName {{ horizon_server_name }}" - notify: Restart apache2 + notify: Restart wsgi process - name: Ensure Apache ServerTokens lineinfile: dest: "{{ horizon_apache_security_conf }}" regexp: '^ServerTokens' line: "ServerTokens {{ horizon_apache_servertokens }}" - notify: Restart apache2 + notify: Restart wsgi process - name: Ensure Apache ServerSignature lineinfile: dest: "{{ horizon_apache_security_conf }}" regexp: '^ServerSignature' line: "ServerSignature {{ horizon_apache_serversignature }}" - notify: Restart apache2 + notify: Restart wsgi process # Removing the Listen (or listen.conf inclusion) from apache config to prevent # conflicts with ports.conf on CentOS and openSUSE @@ -79,4 +79,4 @@ regexp: '^(Listen.*)' backrefs: yes line: '#\1' - notify: Restart apache2 + notify: Restart wsgi process diff --git a/tasks/horizon_install.yml b/tasks/horizon_install.yml index 3367ef44..6c166311 100644 --- a/tasks/horizon_install.yml +++ b/tasks/horizon_install.yml @@ -37,7 +37,7 @@ delay: 2 notify: - Compile messages - - Restart apache2 + - Restart wsgi process - name: Install horizon packages from PIP include_tasks: horizon_install_source.yml diff --git a/tasks/horizon_post_install.yml b/tasks/horizon_post_install.yml index c71f8ab2..92b1a07e 100644 --- a/tasks/horizon_post_install.yml +++ b/tasks/horizon_post_install.yml @@ -63,7 +63,7 @@ - src: "80_admin_default_panel.py.j2" dest: "{{ horizon_lib_dir }}/openstack_dashboard/local/enabled/_80_admin_default_panel.py" mode: "0755" - notify: Restart apache2 + notify: Restart wsgi process - name: Retrieve horizon policy files slurp: @@ -113,7 +113,7 @@ owner: "{{ horizon_system_user_name }}" group: "{{ horizon_system_group_name }}" mode: "0644" - notify: Restart apache2 + notify: Restart wsgi process when: horizon_customization_module is defined - name: Creating horizon custom theme path @@ -133,21 +133,21 @@ group: "{{ horizon_system_group_name }}" with_dict: "{{ horizon_custom_themes }}" when: item.value.theme_src_archive is defined - notify: Restart apache2 + notify: Restart wsgi process - name: Collect static files command: "{{ horizon_manage }} collectstatic --noinput" become: yes become_user: "{{ horizon_system_user_name }}" changed_when: false - notify: Restart apache2 + notify: Restart wsgi process - name: Compress static files command: "{{ horizon_manage }} compress --force" become: yes become_user: "{{ horizon_system_user_name }}" changed_when: false - notify: Restart apache2 + notify: Restart wsgi process register: async_compress_static_files async: 600 poll: 0 diff --git a/tasks/horizon_post_install_source.yml b/tasks/horizon_post_install_source.yml index b4e419b2..6c8983bd 100644 --- a/tasks/horizon_post_install_source.yml +++ b/tasks/horizon_post_install_source.yml @@ -82,4 +82,4 @@ with_items: "{{ found_panels.files }}" notify: - Compile messages - - Restart apache2 + - Restart wsgi process diff --git a/tasks/horizon_ssl_key_create.yml b/tasks/horizon_ssl_key_create.yml index df02a2eb..c02aee29 100644 --- a/tasks/horizon_ssl_key_create.yml +++ b/tasks/horizon_ssl_key_create.yml @@ -28,4 +28,4 @@ -out {{ horizon_ssl_cert }} -extensions v3_ca creates={{ horizon_ssl_cert }} - notify: Restart apache2 + notify: Restart wsgi process diff --git a/tasks/horizon_ssl_user_provided.yml b/tasks/horizon_ssl_user_provided.yml index 1a7ccda0..59151835 100644 --- a/tasks/horizon_ssl_user_provided.yml +++ b/tasks/horizon_ssl_user_provided.yml @@ -21,7 +21,7 @@ group: "root" mode: "0644" when: horizon_user_ssl_cert is defined - notify: Restart apache2 + notify: Restart wsgi process - name: Drop user provided ssl key copy: @@ -31,7 +31,7 @@ group: "root" mode: "0640" when: horizon_user_ssl_key is defined - notify: Restart apache2 + notify: Restart wsgi process - name: Drop user provided ssl CA cert copy: @@ -41,4 +41,4 @@ group: "root" mode: "0644" when: horizon_user_ssl_ca_cert is defined - notify: Restart apache2 + notify: Restart wsgi process diff --git a/tasks/horizon_translations_update.yml b/tasks/horizon_translations_update.yml index cffd2762..a9916b8b 100644 --- a/tasks/horizon_translations_update.yml +++ b/tasks/horizon_translations_update.yml @@ -24,4 +24,4 @@ - (translation.enabled | default("True")) | bool notify: - Compile messages - - Restart apache2 + - Restart wsgi process diff --git a/tasks/horizon_uwsgi.yml b/tasks/horizon_uwsgi.yml new file mode 100644 index 00000000..b3eac8fe --- /dev/null +++ b/tasks/horizon_uwsgi.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2022, Cloudnull +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: Ensure uwsgi can bind to privledged ports + ansible.posix.sysctl: + name: net.ipv4.ip_unprivileged_port_start + value: "0" + sysctl_set: yes + state: present + reload: yes + +- name: Import uwsgi role + include_role: + name: uwsgi + vars: + uwsgi_services: "{{ uwsgi_horizon_services }}" + uwsgi_install_method: "{{ horizon_install_method }}" + tags: + - horizon-config + - uwsgi diff --git a/tasks/main.yml b/tasks/main.yml index 12c59f18..411c5eed 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -103,7 +103,7 @@ tags: - horizon-config -- import_tasks: horizon_apache.yml +- import_tasks: "{{ (horizon_use_uwsgi | bool) | ternary('horizon_uwsgi.yml', 'horizon_apache.yml') }}" tags: - horizon-config diff --git a/vars/debian.yml b/vars/debian.yml index 689b55b2..eda4fa34 100644 --- a/vars/debian.yml +++ b/vars/debian.yml @@ -16,7 +16,7 @@ ## APT Cache options cache_timeout: 600 -horizon_system_service_name: apache2 +horizon_system_service_name: "{{ (horizon_use_uwsgi | bool) | ternary('horizon-dashboard', 'apache2') }}" horizon_devel_distro_packages: - git @@ -25,12 +25,14 @@ horizon_devel_distro_packages: - openssl - libpcre3-dev -horizon_distro_packages: +horizon_apache_distro_packages: - apache2 - apache2-utils + - libapache2-mod-wsgi-py3 + +horizon_distro_packages: - cron # required by the Ansible cron module - gettext - - libapache2-mod-wsgi-py3 horizon_service_distro_packages: - python3-django-openstack-auth diff --git a/vars/distro_install.yml b/vars/distro_install.yml index ffdd3bb2..9fffdbda 100644 --- a/vars/distro_install.yml +++ b/vars/distro_install.yml @@ -13,6 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -horizon_package_list: "{{ horizon_distro_packages + horizon_service_distro_packages }}" +horizon_package_list: "{{ + horizon_distro_packages | union( + ( + (horizon_use_uwsgi | bool) | ternary([], horizon_apache_distro_packages) + ) + ) | union( + horizon_service_distro_packages + ) + }}" _horizon_bin: "/usr/bin" diff --git a/vars/main.yml b/vars/main.yml index aeeb6c2b..5c09c1f7 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -48,3 +48,21 @@ _horizon_translations_pull: horizon_dashboard_panel_dir: "{{ horizon_lib_dir }}/openstack_dashboard/local/enabled" horizon_manage: "{{ horizon_bin }}/horizon-manage.py" + +_horizon_uwsgi_ini_requirements: + uwsgi: + static-map: "/static={{ horizon_lib_dir }}/static/" + +_horizon_uwsgi_ini_overrides: "{{ _horizon_uwsgi_ini_requirements | combine(horizon_uwsgi_ini_overrides, recursive=True) }}" + +uwsgi_horizon_services: + horizon-dashboard: + wsgi_path: "{{ horizon_lib_wsgi_file }}" + wsgi_venv: "{{ horizon_bin | dirname }}" + uwsgi_uid: "{{ horizon_system_user_name }}" + uwsgi_guid: "{{ horizon_system_group_name }}" + uwsgi_processes: 1 + uwsgi_threads: "{{ horizon_wsgi_threads }}" + uwsgi_bind_address: "{{ horizon_bind_address }}" + uwsgi_port: 80 + uwsgi_overrides: "{{ _horizon_uwsgi_ini_overrides }}" diff --git a/vars/redhat.yml b/vars/redhat.yml index fa4b15bb..6d6d9bde 100644 --- a/vars/redhat.yml +++ b/vars/redhat.yml @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -horizon_system_service_name: httpd +horizon_system_service_name: "{{ (horizon_use_uwsgi | bool) | ternary('horizon-dashboard', 'httpd') }}" horizon_devel_distro_packages: - git @@ -22,14 +22,16 @@ horizon_devel_distro_packages: - openssl-libs - pcre-devel -horizon_distro_packages: - - cronie - - cronie-anacron - - gettext +horizon_apache_distro_packages: - httpd - httpd-tools - mod_ssl - python3-mod_wsgi + +horizon_distro_packages: + - cronie + - cronie-anacron + - gettext - which horizon_service_distro_packages: diff --git a/vars/source_install.yml b/vars/source_install.yml index 4235832d..b6f5e049 100644 --- a/vars/source_install.yml +++ b/vars/source_install.yml @@ -13,7 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -horizon_package_list: "{{ horizon_distro_packages }}" +horizon_package_list: "{{ + horizon_distro_packages | union( + ( + (horizon_use_uwsgi | bool) | ternary([], horizon_apache_distro_packages) + ) + ) + }}" + _horizon_bin: "/openstack/venvs/horizon-{{ horizon_venv_tag }}/bin" _dashboard_panels_location: