diff --git a/defaults/main.yml b/defaults/main.yml index ded6ebd..09f0c91 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -89,11 +89,13 @@ cloudkitty_collector: gnocchi cloudkitty_service_project_domain_id: default cloudkitty_service_project_name: "service" cloudkitty_service_user_domain_id: default +cloudkitty_system_service_name: "cloudkitty-api" cloudkitty_keystone_auth_plugin: password cloudkitty_output_backend: cloudkitty.backend.file.FileBackend cloudkitty_output_pipeline: osrf cloudkitty_output_basepath: /var/cloudkitty/reports +cloudkitty_log_dir: /var/log/cloudkitty cloudkitty_db_setup_host: "{{ ('galera_all' in groups) | ternary(groups['galera_all'][0], 'localhost') }}" cloudkitty_galera_address: "{{ galera_address | default('127.0.0.1') }}" @@ -102,6 +104,11 @@ cloudkitty_galera_user: cloudkitty cloudkitty_database_connection: >- mysql+pymysql://{{ cloudkitty_galera_user }}:{{ cloudkitty_container_mysql_password }}@{{ cloudkitty_galera_address }}/{{ cloudkitty_galera_database }}?charset=utf8 +cloudkitty_wsgi_threads: 1 +cloudkitty_wsgi_processes_max: 16 +cloudkitty_wsgi_processes: "{{ [[ansible_processor_vcpus|default(1), 1] | max * 2, cloudkitty_wsgi_processes_max] | min }}" +cloudkitty_uwsgi_bind_address: 0.0.0.0 + ## Service Type and Data cloudkitty_service_region: RegionOne cloudkitty_service_name: cloudkitty @@ -123,6 +130,7 @@ cloudkitty_api_paste_ini_overrides: {} cloudkitty_api_init_overrides: {} cloudkitty_processor_init_overrides: {} +cloudkitty_api_uwsgi_overrides: {} ## Service Name-Group Mapping cloudkitty_services: @@ -130,7 +138,8 @@ cloudkitty_services: group: cloudkitty_all service_name: cloudkitty-api init_config_overrides: "{{ cloudkitty_api_init_overrides }}" - execstarts: "{{ cloudkitty_bin }}/cloudkitty-api" + execstarts: "{{ cloudkitty_bin }}/uwsgi --ini /etc/uwsgi/cloudkitty-api.ini" + execreloads: "{{ cloudkitty_bin }}/uwsgi --reload /var/run/cloudkitty-api/cloudkitty-api.pid" start_order: 1 cloudkitty-processor: group: cloudkitty_all @@ -149,6 +158,7 @@ cloudkitty_pip_packages: - SQLAlchemy>=1.0.10 - systemd-python - tooz + - uwsgi ## (Qdrouterd) integration # TODO(ansmith): Change structure when more backends will be supported diff --git a/handlers/main.yml b/handlers/main.yml index 55ed38b..d1a2447 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -58,3 +58,14 @@ listen: - "Restart cloudkitty services" - "venv changed" + +- name: Restart cloudkitty-api + service: + name: "{{ cloudkitty_system_service_name }}" + enabled: yes + state: "restarted" + daemon_reload: "{{ (ansible_service_mgr == 'systemd') | ternary('yes', omit) }}" + register: _restart + until: _restart | success + retries: 5 + delay: 2 diff --git a/tasks/cloudkitty_wsgi.yml b/tasks/cloudkitty_wsgi.yml new file mode 100644 index 0000000..a2b360a --- /dev/null +++ b/tasks/cloudkitty_wsgi.yml @@ -0,0 +1,22 @@ +--- +- name: Ensure uWSGI directory exists + file: + path: "/etc/uwsgi/" + state: directory + mode: "0711" +- name: Copy cloudkitty wsgi to apache directory + template: + src: cloudkitty-wsgi.py.j2 + dest: "{{ cloudkitty_bin }}/cloudkitty-wsgi.py" + owner: "{{ cloudkitty_system_user_name }}" + group: "{{ cloudkitty_system_user_name }}" + mode: 0755 +- name: Apply uWSGI configuration + config_template: + src: cloudkitty-uwsgi.ini.j2 + dest: /etc/uwsgi/cloudkitty-api.ini + mode: 0744 + config_overrides: "{{ cloudkitty_api_uwsgi_overrides }}" + config_type: ini + notify: + - Restart cloudkitty-api \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml index 89ed84f..a615ad6 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -43,6 +43,8 @@ - include_tasks: cloudkitty_install.yml - include_tasks: cloudkitty_post_install.yml +- include_tasks: cloudkitty_wsgi.yml + - include_tasks: cloudkitty_service_setup.yml when: inventory_hostname == groups['cloudkitty_all'][0] diff --git a/templates/cloudkitty-uwsgi.ini.j2 b/templates/cloudkitty-uwsgi.ini.j2 new file mode 100644 index 0000000..8476204 --- /dev/null +++ b/templates/cloudkitty-uwsgi.ini.j2 @@ -0,0 +1,23 @@ +# {{ ansible_managed }} +[uwsgi] +uid = {{ cloudkitty_system_user_name }} +gid = {{ cloudkitty_system_group_name }} + +virtualenv = /openstack/venvs/cloudkitty-{{ cloudkitty_venv_tag }} +wsgi-file = {{ cloudkitty_bin }}/cloudkitty-wsgi.py +http = :{{ cloudkitty_service_port }} +logto = {{ cloudkitty_log_dir }}/cloudkitty-api.log + +master = true +enable-threads = true +processes = {{ cloudkitty_wsgi_processes }} +threads = {{ cloudkitty_wsgi_threads }} +exit-on-reload = true +die-on-term = true +lazy-apps = true +add-header = Connection: close +buffer-size = 65535 +thunder-lock = true + +# Avoid filling up the logs with health check requests from haproxy. +route-user-agent = ^osa-haproxy-healthcheck$ donotlog: diff --git a/templates/cloudkitty-wsgi.py.j2 b/templates/cloudkitty-wsgi.py.j2 new file mode 100644 index 0000000..3515119 --- /dev/null +++ b/templates/cloudkitty-wsgi.py.j2 @@ -0,0 +1,29 @@ +# -*- mode: python -*- +# +# Copyright 2013 New Dream Network, LLC (DreamHost) +# +# 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. + +"""Use this file for deploying the API under mod_wsgi. + +See http://pecan.readthedocs.org/en/latest/deployment.html for details. +""" + +import os + +activate_this = os.path.expanduser("{{ cloudkitty_bin }}/activate_this.py") +execfile(activate_this, dict(__file__=activate_this)) + +from cloudkitty.api import app + +application = app.build_wsgi_app(argv=[])