diff --git a/playbooks/os-horizon-install.yml b/playbooks/os-horizon-install.yml
index 4ede07b00d..3c314d0b74 100644
--- a/playbooks/os-horizon-install.yml
+++ b/playbooks/os-horizon-install.yml
@@ -72,7 +72,12 @@
tags:
- horizon-logs
roles:
- - { role: "os_horizon", tags: [ "os-horizon" ] }
+ - role: "os_horizon"
+ horizon_galera_address: "{{ galera_address }}"
+ horizon_server_name: "{{ container_name }}"
+ horizon_venv_tag: "{{ openstack_release }}"
+ tags:
+ - "os-horizon"
- role: "rsyslog_client"
rsyslog_client_log_rotate_file: horizon_log_rotate
rsyslog_client_log_dir: "/var/log/apache2"
@@ -85,7 +90,5 @@
- "system-crontab-coordination"
vars:
galera_address: "{{ internal_lb_vip_address }}"
- horizon_galera_address: "{{ internal_lb_vip_address }}"
ansible_hostname: "{{ container_name }}"
- horizon_server_name: "{{ container_name }}"
is_metal: "{{ properties.is_metal|default(false) }}"
diff --git a/playbooks/roles/os_horizon/defaults/main.yml b/playbooks/roles/os_horizon/defaults/main.yml
index 9b3390a4f1..65fe32bc71 100644
--- a/playbooks/roles/os_horizon/defaults/main.yml
+++ b/playbooks/roles/os_horizon/defaults/main.yml
@@ -13,13 +13,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Defines that the role will be deployed on a host machine
-is_metal: true
-
## Verbosity Options
debug: False
verbose: True
+# Name of the virtual env to deploy into
+horizon_venv_tag: untagged
+horizon_venv_bin: "/openstack/venvs/horizon-{{ horizon_venv_tag }}/bin"
+
+# Set this to enable or disable installing in a venv
+horizon_venv_enabled: true
+
+# The bin path defaults to the venv path however if installation in a
+# venv is disabled the bin path will be dynamically set based on the
+# system path used when the installing.
+horizon_bin: "{{ horizon_venv_bin }}"
+
## System info
horizon_system_user_name: horizon
horizon_system_group_name: www-data
@@ -44,7 +53,10 @@ horizon_session_timeout: 1800
horizon_help_url: http://docs.openstack.org
## Installation directories
-horizon_lib_dir: /usr/local/lib/python2.7/dist-packages
+horizon_venv_lib_dir: "{{ horizon_bin | dirname }}/lib/python2.7/dist-packages"
+horizon_non_venv_lib_dir: "/usr/local/lib/python2.7/dist-packages"
+horizon_lib_dir: "{{ (horizon_venv_enabled | bool) | ternary(horizon_venv_lib_dir, horizon_non_venv_lib_dir) }}"
+horizon_lib_wsgi_file: "{{ horizon_lib_dir }}/openstack_dashboard/wsgi/django.wsgi"
horizon_endpoint_type: internalURL
@@ -121,6 +133,11 @@ horizon_apt_packages:
- libxslt1.1
- openssl
+# horizon packages that must be installed before anything else
+horizon_requires_pip_packages:
+ - virtualenv
+ - python-keystoneclient # Keystoneclient needed to OSA keystone lib
+
horizon_pip_packages:
- django-appconf
- greenlet
diff --git a/playbooks/roles/os_horizon/tasks/horizon_db_setup.yml b/playbooks/roles/os_horizon/tasks/horizon_db_setup.yml
index 675991a196..74562d1d8d 100644
--- a/playbooks/roles/os_horizon/tasks/horizon_db_setup.yml
+++ b/playbooks/roles/os_horizon/tasks/horizon_db_setup.yml
@@ -40,19 +40,21 @@
- horizon-db-setup
- name: Perform a horizon DB sync
- command: horizon-manage.py syncdb --noinput
+ command: "{{ horizon_bin }}/horizon-manage.py syncdb --noinput"
sudo: yes
sudo_user: "{{ horizon_system_user_name }}"
tags:
+ - horizon-db-setup
- horizon-db-sync
- horizon-setup
+ - horizon-command-bin
- name: Register DB session cleanup cron
cron:
name: "Clear out expired sessions"
minute: "{{ 58 | random(start=2) }}"
hour: 21
- job: "/usr/local/bin/horizon-manage.py clearsessions"
+ job: "{{ horizon_bin }}/horizon-manage.py clearsessions"
user: "{{ horizon_system_user_name }}"
state: present
tags:
diff --git a/playbooks/roles/os_horizon/tasks/horizon_install.yml b/playbooks/roles/os_horizon/tasks/horizon_install.yml
index 674a0cb276..beb6a70b0c 100644
--- a/playbooks/roles/os_horizon/tasks/horizon_install.yml
+++ b/playbooks/roles/os_horizon/tasks/horizon_install.yml
@@ -37,7 +37,24 @@
- horizon-install
- horizon-apt-packages
-- name: Install pip packages
+- name: Install pip packages (venv)
+ pip:
+ name: "{{ item }}"
+ state: present
+ virtualenv: "{{ horizon_venv_bin | dirname }}"
+ virtualenv_site_packages: "no"
+ extra_args: "{{ pip_install_options|default('') }}"
+ register: install_packages
+ until: install_packages|success
+ retries: 5
+ delay: 2
+ with_items:
+ - "{{ horizon_pip_packages }}"
+ when: horizon_venv_enabled | bool
+ tags:
+ - horizon-pip-packages
+
+- name: Install pip packages (no venv)
pip:
name: "{{ item }}"
state: present
@@ -48,6 +65,6 @@
delay: 2
with_items:
- "{{ horizon_pip_packages }}"
+ when: not horizon_venv_enabled | bool
tags:
- - horizon-install
- horizon-pip-packages
diff --git a/playbooks/roles/os_horizon/tasks/horizon_post_install.yml b/playbooks/roles/os_horizon/tasks/horizon_post_install.yml
index 4dd5cacd24..ea82206d29 100644
--- a/playbooks/roles/os_horizon/tasks/horizon_post_install.yml
+++ b/playbooks/roles/os_horizon/tasks/horizon_post_install.yml
@@ -13,6 +13,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Because there is no specific "horizon" command this method
+# is looking for the "keystone" command to set the horizon
+# command path.
+- name: Get horizon command path
+ command: which keystone
+ register: horizon_command_path
+ when:
+ - not horizon_venv_enabled | bool
+ tags:
+ - horizon-command-bin
+
+- name: Set horizon command path
+ set_fact:
+ horizon_bin: "{{ horizon_command_path.stdout | dirname }}"
+ when:
+ - not horizon_venv_enabled | bool
+ tags:
+ - horizon-command-bin
+
- name: Setup Horizon config(s)
template:
src: "{{ item.src }}"
@@ -22,22 +41,11 @@
mode: "{{ item.mode }}"
with_items:
- { src: "horizon_local_settings.py.j2", dest: "/etc/horizon/local_settings.py", mode: "0644" }
+ - { src: "horizon-manage.py.j2", dest: "{{ horizon_bin }}/horizon-manage.py", mode: "0755" }
notify: Restart apache2
tags:
- horizon-configs
-- name: Setup Horizon config(s)
- copy:
- src: "{{ item.src }}"
- dest: "{{ item.dest }}"
- owner: "{{ horizon_system_user_name }}"
- group: "{{ horizon_system_group_name }}"
- mode: "{{ item.mode }}"
- with_items:
- - { src: "horizon-manage.py", dest: "/usr/local/bin/horizon-manage.py", mode: "0755" }
- tags:
- - horizon-configs
-
- name: Create horizon links
file:
src: "{{ item.src }}"
@@ -55,8 +63,22 @@
sudo: yes
sudo_user: "{{ horizon_system_user_name }}"
with_items:
- - horizon-manage.py collectstatic --noinput
- - horizon-manage.py compress --force
+ - "{{ horizon_bin }}/horizon-manage.py collectstatic --noinput"
+ - "{{ horizon_bin }}/horizon-manage.py compress --force"
tags:
- horizon-configs
- horizon-static-collect
+ - horizon-command-bin
+
+- name: Setup Horizon config(s)
+ template:
+ src: "{{ item.src }}"
+ dest: "{{ item.dest }}"
+ owner: "{{ horizon_system_user_name }}"
+ group: "{{ horizon_system_group_name }}"
+ with_items:
+ - { src: "horizon_django.wsgi.j2", dest: "{{ horizon_lib_wsgi_file }}" }
+ notify: Restart apache2
+ tags:
+ - horizon-configs
+ - horizon-wsgi-venv
diff --git a/playbooks/roles/os_horizon/tasks/horizon_pre_install.yml b/playbooks/roles/os_horizon/tasks/horizon_pre_install.yml
index f06d01ec98..60053d0116 100644
--- a/playbooks/roles/os_horizon/tasks/horizon_pre_install.yml
+++ b/playbooks/roles/os_horizon/tasks/horizon_pre_install.yml
@@ -34,16 +34,82 @@
- horizon-user
- name: Create horizon dir
+ file:
+ path: "{{ item.path }}"
+ state: "directory"
+ owner: "{{ item.owner|default(horizon_system_user_name) }}"
+ group: "{{ item.group|default(horizon_system_group_name) }}"
+ with_items:
+ - { path: "/openstack", mode: "0755", owner: "root", group: "root" }
+ - { path: "/etc/horizon", mode: "2755" }
+ - { path: "{{ horizon_system_user_home }}", mode: "2755" }
+ tags:
+ - horizon-dirs
+
+- name: Create horizon venv dir
file:
path: "{{ item.path }}"
state: directory
owner: "{{ item.owner|default(horizon_system_user_name) }}"
group: "{{ item.group|default(horizon_system_group_name) }}"
with_items:
- - { path: "/etc/horizon" }
- - { path: "{{ horizon_system_user_home }}" }
- - { path: "/usr/local/lib/python2.7/dist-packages/static" }
- - { path: "/usr/local/lib/python2.7/dist-packages/openstack_dashboard/local" }
+ - { path: "/openstack/venvs", mode: "0755", owner: "root", group: "root" }
+ - { path: "{{ horizon_venv_bin }}" }
+ when: horizon_venv_enabled | bool
+ tags:
+ - horizon-dirs
+
+- name: Install requires pip packages
+ pip:
+ name: "{{ item }}"
+ state: present
+ extra_args: "{{ pip_install_options|default('') }}"
+ register: install_packages
+ until: install_packages|success
+ retries: 5
+ delay: 2
+ with_items:
+ - "{{ horizon_requires_pip_packages }}"
+ tags:
+ - horizon-pip-packages
+
+- name: Create horizon venv
+ pip:
+ name: "{{ item }}"
+ state: present
+ virtualenv: "{{ horizon_venv_bin | dirname }}"
+ virtualenv_site_packages: "no"
+ extra_args: "{{ pip_install_options|default('') }}"
+ with_items:
+ - "{{ horizon_requires_pip_packages }}"
+ when: horizon_venv_enabled | bool
+ tags:
+ - horizon-pip-packages
+
+- name: Create horizon links for venv
+ file:
+ src: "{{ item.src }}"
+ dest: "{{ item.dest }}"
+ owner: "{{ horizon_system_user_name }}"
+ group: "{{ horizon_system_group_name }}"
+ state: "link"
+ with_items:
+ - src: "{{ horizon_lib_dir | dirname }}/site-packages"
+ dest: "{{ horizon_lib_dir }}"
+ when: horizon_venv_enabled | bool
+ tags:
+ - horizon-configs
+
+- name: Create static horizon dir
+ file:
+ path: "{{ item.path }}"
+ state: "directory"
+ owner: "{{ item.owner|default(horizon_system_user_name) }}"
+ group: "{{ item.group|default(horizon_system_group_name) }}"
+ with_items:
+ - { path: "{{ horizon_lib_dir }}/static", mode: "2755" }
+ - { path: "{{ horizon_lib_dir }}/openstack_dashboard", mode: "2755" }
+ - { path: "{{ horizon_lib_dir }}/openstack_dashboard/local", mode: "2755" }
tags:
- horizon-dirs
diff --git a/playbooks/roles/os_horizon/files/horizon-manage.py b/playbooks/roles/os_horizon/templates/horizon-manage.py.j2
similarity index 81%
rename from playbooks/roles/os_horizon/files/horizon-manage.py
rename to playbooks/roles/os_horizon/templates/horizon-manage.py.j2
index 5818a6de38..b0fd422baf 100644
--- a/playbooks/roles/os_horizon/files/horizon-manage.py
+++ b/playbooks/roles/os_horizon/templates/horizon-manage.py.j2
@@ -13,6 +13,14 @@
# under the License.
import os
+
+{% if horizon_venv_enabled | bool %}
+
+activate_this = os.path.expanduser("{{ horizon_venv_bin }}/activate_this.py")
+execfile(activate_this, dict(__file__=activate_this))
+
+{% endif %}
+
import sys
from django.core.management import execute_from_command_line # noqa
diff --git a/playbooks/roles/os_horizon/templates/horizon_django.wsgi.j2 b/playbooks/roles/os_horizon/templates/horizon_django.wsgi.j2
new file mode 100644
index 0000000000..60edb1e5ed
--- /dev/null
+++ b/playbooks/roles/os_horizon/templates/horizon_django.wsgi.j2
@@ -0,0 +1,22 @@
+import logging
+import os
+
+{% if horizon_venv_enabled | bool %}
+
+activate_this = os.path.expanduser("{{ horizon_venv_bin }}/activate_this.py")
+execfile(activate_this, dict(__file__=activate_this))
+
+{% endif %}
+
+import sys
+from django.core.wsgi import get_wsgi_application
+from django.conf import settings
+
+# Add this file path to sys.path in order to import settings
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '../..'))
+os.environ['DJANGO_SETTINGS_MODULE'] = 'openstack_dashboard.settings'
+sys.stdout = sys.stderr
+
+DEBUG = False
+
+application = get_wsgi_application()
\ No newline at end of file
diff --git a/playbooks/roles/os_horizon/templates/openstack_dashboard.conf.j2 b/playbooks/roles/os_horizon/templates/openstack_dashboard.conf.j2
index f8d8f9624b..ed77df24eb 100644
--- a/playbooks/roles/os_horizon/templates/openstack_dashboard.conf.j2
+++ b/playbooks/roles/os_horizon/templates/openstack_dashboard.conf.j2
@@ -29,13 +29,12 @@
SSLCipherSuite {{ horizon_ssl_cipher_suite }}
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
- WSGIScriptAlias / {{ horizon_lib_dir }}/openstack_dashboard/wsgi/django.wsgi
+ WSGIScriptAlias / {{ horizon_lib_wsgi_file }}
WSGIDaemonProcess horizon user={{ horizon_system_user_name }} group={{ horizon_system_group_name }} processes={{ ansible_processor_cores }} threads={{ threads if threads > 0 else 1 }}
WSGIProcessGroup horizon
WSGIApplicationGroup horizon
- Alias /static {{ horizon_lib_dir }}/static/
-
+
Order allow,deny
allow from all
@@ -43,6 +42,8 @@
+ Alias /static {{ horizon_lib_dir }}/static/
+
Options -FollowSymlinks
AllowOverride None