├── .travis.yml ├── LICENSE ├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── tasks ├── Debian.yml ├── RedHat.yml ├── django-admin.yml ├── main.yml └── manage.yml ├── templates ├── carbon.conf.j2 ├── carbon_cache_systemd.j2 ├── carbon_relay_systemd.j2 ├── createsuperuser.py.j2 ├── debian_carbon_cache.j2 ├── debian_carbon_relay.j2 ├── local_settings.py.j2 ├── redhat_uwsgi_default.ini.j2 ├── relay-rules.conf.j2 ├── storage-schemas.conf.j2 ├── uwsgi_graphite.ini.j2 ├── uwsgi_systemd.j2 ├── wsgi-1.0.x.py.j2 └── wsgi.py.j2 ├── tests ├── main.yml ├── post.yml ├── pre.yml └── templates │ └── graphite.conf.j2 └── vars └── main.yml /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | sudo: required 4 | dist: trusty 5 | language: python 6 | 7 | env: 8 | global: 9 | - CONTAINER_IMAGES="images:centos/7 images:debian/jessie images:debian/stretch ubuntu:16.04 ubuntu:18.04" 10 | matrix: 11 | 12 | - ANSIBLE_VERSIONS="2.7.0" ANSIBLE_EXTRA_VARS_LIST="version=1.0.2" 13 | - ANSIBLE_VERSIONS="2.6.5" ANSIBLE_EXTRA_VARS_LIST="version=1.0.2" 14 | - ANSIBLE_VERSIONS="2.5.9" ANSIBLE_EXTRA_VARS_LIST="version=1.0.2" 15 | 16 | - ANSIBLE_VERSIONS="2.7.0" ANSIBLE_EXTRA_VARS_LIST="version=1.1.3" 17 | - ANSIBLE_VERSIONS="2.6.5" ANSIBLE_EXTRA_VARS_LIST="version=1.1.3" 18 | - ANSIBLE_VERSIONS="2.5.9" ANSIBLE_EXTRA_VARS_LIST="version=1.1.3" 19 | 20 | - ANSIBLE_VERSIONS="2.7.0" ANSIBLE_EXTRA_VARS_LIST="version=1.1.5" 21 | - ANSIBLE_VERSIONS="2.6.5" ANSIBLE_EXTRA_VARS_LIST="version=1.1.5" 22 | - ANSIBLE_VERSIONS="2.5.9" ANSIBLE_EXTRA_VARS_LIST="version=1.1.5" 23 | 24 | install: 25 | # Download ansible-role-tester and setup the enviroment 26 | - wget https://raw.githubusercontent.com/nsg/ansible-role-tester/master/test.sh 27 | - chmod +x test.sh 28 | - ./test.sh install 29 | 30 | script: 31 | - ./test.sh test 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2017 Stefan Berggren 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | nsg.graphite 2 | ======== 3 | 4 | [![Build Status](https://travis-ci.org/nsg/ansible-graphite.svg?branch=master)](https://travis-ci.org/nsg/ansible-graphite) 5 | 6 | This role installs graphite, I choose to install graphite from pip because the packages in the distributions repositories are old and features are missing. I’m using apt/yum when possible. 7 | 8 | Galaxy 9 | ------ 10 | 11 | The Role in [Ansible Galaxy](https://galaxy.ansible.com/nsg/graphite/) is old and unmaintained because [invasive permissions asked by Ansible](https://github.com/ansible/galaxy-issues/issues/159). 12 | 13 | Requirements 14 | ------------ 15 | 16 | As usual, read the tasks and make sure this role will not breaks your installation, I will for example mess with django, twisted and uwsgi. 17 | 18 | This role exposes the graphite web interface with uwsgi at `localhost:3031`, you need to configure a web server your self to talk to that. For example, do this with nginx: 19 | 20 | ``` 21 | server { 22 | listen 8080; 23 | charset utf-8; 24 | access_log /var/log/nginx/graphite.access.log; 25 | error_log /var/log/nginx/graphite.error.log; 26 | 27 | location /static { 28 | alias /opt/graphite/webapp/content; 29 | expires max; 30 | } 31 | 32 | location / { 33 | include uwsgi_params; 34 | uwsgi_pass 127.0.0.1:3031; 35 | } 36 | } 37 | ``` 38 | 39 | The uwsgi socket can be configured through `uwsgi_graphite_socket`. 40 | 41 | Alternatively, you can define `uwsgi_graphite_extraopts` with additional uwsgi configuration, which can e.g. enable http on port 8080 or add basic auth: 42 | ```yaml 43 | uwsgi_graphite_extraopts: 44 | - option: http 45 | value: "{{ ansible_default_ipv4.address }}:8080" 46 | - option: plugins 47 | value: router_basicauth 48 | - option: route 49 | value: "^/ basicauth:myRealm,foo:bar" 50 | ``` 51 | 52 | Role Variables 53 | -------------- 54 | 55 | See: [defaults/main.yml](https://github.com/nsg/ansible-graphite/blob/master/defaults/main.yml) 56 | 57 | Supported Graphite versions 58 | --------------------------- 59 | 60 | 1.0.2 and 1.1.3, choose version with `graphite_install_version`. 61 | 62 | 63 | Example Playbook 64 | ------------------------- 65 | 66 | ``` 67 | - hosts: servers 68 | roles: 69 | - role: nsg.graphite 70 | graphite_secret_key: 'dgdgdfgasg' 71 | graphite_cache_graphite_url: 'http://127.0.0.1:8080' 72 | ``` 73 | 74 | License 75 | ------- 76 | 77 | MIT 78 | 79 | Author Information 80 | ------------------ 81 | 82 | Stefan Berggren, nsg@nsg.cc 83 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | graphite_install_version: 1.1.5 3 | 4 | graphite_user: graphite 5 | graphite_secret_key: UNSAFE_DEFAULT 6 | graphite_time_zone: UTC 7 | 8 | graphite_enable_uwsgi: True 9 | graphite_enable_carbon_cache: True 10 | graphite_enable_carbon_relay: False 11 | 12 | graphite_admin_date_joined: "2014-07-21T10:11:17.464" 13 | graphite_admin_email: "root@example.com" 14 | graphite_admin_first_name: "" 15 | graphite_admin_last_name: "" 16 | graphite_admin_last_login: "2014-07-21T10:11:17.464" 17 | graphite_admin_username: admin 18 | graphite_admin_password: admin 19 | 20 | graphite_service_carbon_open_files_limit: 4096 21 | 22 | # The default is "60s:1d" (1 day data), this will keep data for 5 years. 23 | # If you log a lot of data, you may need to restrict this to a shorter time. 24 | graphite_storage_schemas_default_retentions: "10s:14d,1m:90d,30m:1y,1h:5y" 25 | graphite_storage_schemas_carbon_retentions: 60:90d 26 | graphite_storage_schemas: [] 27 | 28 | graphite_cache_amqp_exchange: graphite 29 | graphite_cache_amqp_host: localhost 30 | graphite_cache_amqp_metric_name_in_body: false 31 | graphite_cache_amqp_password: guest 32 | graphite_cache_amqp_port: 5672 33 | graphite_cache_amqp_user: guest 34 | graphite_cache_amqp_verbose: false 35 | graphite_cache_amqp_vhost: / 36 | graphite_cache_bind_patterns: "#" 37 | graphite_cache_cache_query_interface: 0.0.0.0 38 | graphite_cache_cache_query_port: 7002 39 | graphite_cache_cache_write_strategy: sorted 40 | graphite_cache_carbon_metric_interval: 60 41 | graphite_cache_carbon_metric_prefix: carbon 42 | graphite_cache_database: whisper 43 | graphite_cache_enable_amqp: false 44 | graphite_cache_enable_log_rotation: true 45 | graphite_cache_enable_udp_listener: false 46 | graphite_cache_line_receiver_interface: 0.0.0.0 47 | graphite_cache_line_receiver_port: 2003 48 | graphite_cache_local_data_dir: /opt/graphite/storage/whisper 49 | graphite_cache_log_cache_hits: false 50 | graphite_cache_log_cache_queue_sorts: true 51 | graphite_cache_log_updates: false 52 | graphite_cache_log_creates: false 53 | graphite_cache_enable_manhole: false 54 | graphite_cache_manhole_interface: 127.0.0.1 55 | graphite_cache_manhole_port: 7222 56 | graphite_cache_manhole_public_key: ssh-rsa AAAAB3NzaC1y... 57 | graphite_cache_manhole_user: admin 58 | graphite_cache_max_cache_size: inf 59 | graphite_cache_max_creates_per_minute: 50 60 | graphite_cache_max_updates_per_second: 500 61 | graphite_cache_max_updates_per_second_on_shutdown: 1000 62 | graphite_cache_min_timestamp_resolution: 1 63 | graphite_cache_pickle_receiver_interface: 0.0.0.0 64 | graphite_cache_pickle_receiver_port: 2004 65 | graphite_cache_pickle_receiver_max_length: 1048576 66 | graphite_cache_udp_receiver_interface: 0.0.0.0 67 | graphite_cache_udp_receiver_port: 2003 68 | graphite_cache_graphite_url: false # Set to http://my-graphite-url:port 69 | graphite_cache_use_flow_control: true 70 | graphite_cache_use_insecure_unpickler: false 71 | graphite_cache_use_whitelist: false 72 | # graphite_cache_user: 73 | graphite_cache_whisper_autoflush: false 74 | graphite_cache_whisper_fallocate_create: true 75 | graphite_cache_whisper_lock_writes: false 76 | graphite_cache_whisper_sparse_create: false 77 | 78 | graphite_relay_carbon_metric_interval: 60 79 | graphite_relay_carbon_metric_prefix: carbon 80 | graphite_relay_destinations: 127.0.0.1:2004 81 | graphite_relay_line_receiver_interface: 0.0.0.0 82 | graphite_relay_line_receiver_port: 2013 83 | graphite_relay_pickle_receiver_max_length: 1048576 84 | graphite_relay_max_datapoints_per_message: 500 85 | graphite_relay_max_queue_size: 10000 86 | graphite_relay_min_reset_interval: 121 87 | graphite_relay_min_reset_ratio: '0.9' 88 | graphite_relay_min_reset_stat_flow: 1000 89 | graphite_relay_pickle_receiver_interface: 0.0.0.0 90 | graphite_relay_pickle_receiver_port: 2014 91 | graphite_relay_relay_method: rules 92 | graphite_relay_replication_factor: 1 93 | graphite_relay_time_to_defer_sending: '0.0001' 94 | graphite_relay_use_flow_control: true 95 | graphite_relay_use_ratio_reset: false 96 | graphite_relay_use_whitelist: false 97 | # graphite_relay_user: 98 | graphite_relay_queue_low_watermark_pct: '0.8' 99 | 100 | graphite_aggregator_carbon_metric_interval: 60 101 | graphite_aggregator_carbon_metric_prefix: carbon 102 | graphite_aggregator_destinations: 127.0.0.1:2004 103 | graphite_aggregator_forward_all: true 104 | graphite_aggregator_line_receiver_interface: 0.0.0.0 105 | graphite_aggregator_line_receiver_port: 2023 106 | graphite_aggregator_max_aggregation_intervals: 5 107 | graphite_aggregator_max_datapoints_per_message: 500 108 | graphite_aggregator_max_queue_size: 10000 109 | graphite_aggregator_pickle_receiver_interface: 0.0.0.0 110 | graphite_aggregator_pickle_receiver_port: 2024 111 | graphite_aggregator_replication_factor: 1 112 | graphite_aggregator_use_flow_control: true 113 | graphite_aggregator_use_whitelist: false 114 | # graphite_aggregator_user: 115 | graphite_aggregator_write_back_frequency: 0 116 | 117 | graphite_cluster_servers: [] 118 | 119 | # Optional extra options for uwsgi_graphite.ini 120 | uwsgi_graphite_extraopts: [] 121 | uwsgi_graphite_processes: 2 122 | uwsgi_graphite_socket: '127.0.0.1:3031' 123 | 124 | graphite_install_path: "/opt/graphite" 125 | graphite_install_requirements: 126 | # List based on requirements.txt from https://github.com/graphite-project/graphite-web 127 | # All versions are frozen to make it future-proof. 128 | 1.0.2: 129 | - Django==1.9.13 130 | - django-tagging==0.4.3 131 | - cairocffi==0.8.0 132 | - pytz==2017.2 133 | - scandir==1.5 134 | - python-memcached==1.47 135 | - txAMQP==0.6.2 136 | - gunicorn==19.7.0 137 | - graphite-web==1.0.2 138 | - carbon==1.0.2 139 | - whisper==1.0.2 140 | 1.1.3: 141 | - attrs==17.4.0 142 | - Automat==0.6.0 143 | - cachetools==2.0.1 144 | - cairocffi==0.8.0 145 | - carbon==1.1.3 146 | - constantly==15.1.0 147 | - Django==1.11.12 148 | - django-tagging==0.4.3 149 | - graphite-web==1.1.3 150 | - hyperlink==18.0.0 151 | - idna==2.6 152 | - incremental==17.5.0 153 | - scandir==1.7 154 | - six==1.11.0 155 | - urllib3==1.22 156 | - whisper==1.1.3 157 | 1.1.5: 158 | - attrs==18.2.0 159 | - Automat==0.7.0 160 | - cachetools==3.0.0 161 | - cairocffi==0.9.0 162 | - carbon==1.1.5 163 | - cffi==1.11.5 164 | - constantly==15.1.0 165 | - Django==1.11.18 166 | - django-tagging==0.4.3 167 | - graphite-web==1.1.5 168 | - hyperlink==18.0.0 169 | - idna==2.8 170 | - incremental==17.5.0 171 | - pycparser==2.19 172 | - PyHamcrest==1.9.0 173 | - pyparsing==2.3.1 174 | - pytz==2018.9 175 | - scandir==1.9.0 176 | - six==1.12.0 177 | - Twisted==18.9.0 178 | - txAMQP==0.8.2 179 | - urllib3==1.24.1 180 | - wheel==0.24.0 181 | - whisper==1.1.5 182 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: restart carbon-cache 4 | service: name=carbon-cache state=restarted 5 | when: graphite_enable_carbon_cache 6 | 7 | - name: restart carbon-relay 8 | service: name=carbon-relay state=restarted 9 | when: graphite_enable_carbon_relay 10 | 11 | - name: restart uwsgi 12 | service: name=uwsgi state=restarted 13 | when: graphite_enable_uwsgi 14 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Stefan Berggren 4 | description: Graphite ansible role 5 | company: 6 | license: MIT 7 | min_ansible_version: 2.5.9 8 | platforms: 9 | - name: EL 10 | versions: 11 | - 7 12 | # - name: Fedora 13 | # versions: 14 | # - all 15 | # - 16 16 | # - 17 17 | # - 18 18 | # - 19 19 | # - 20 20 | # - name: opensuse 21 | # versions: 22 | # - all 23 | # - 12.1 24 | # - 12.2 25 | # - 12.3 26 | # - 13.1 27 | # - 13.2 28 | - name: Ubuntu 29 | versions: 30 | - xenial 31 | - bionic 32 | - name: Debian 33 | versions: 34 | - jessie 35 | - stretch 36 | categories: 37 | - monitoring 38 | dependencies: [] 39 | -------------------------------------------------------------------------------- /tasks/Debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install packages with apt 4 | apt: 5 | name: "{{ packages }}" 6 | update_cache: yes 7 | vars: 8 | packages: 9 | - python-pip 10 | - python-dev 11 | - libcairo2-dev 12 | - python-cairo 13 | - fontconfig 14 | - uwsgi 15 | - uwsgi-plugin-python 16 | - sudo 17 | - libffi-dev 18 | 19 | - name: Debian Jessie and 1.0.2+ | cffi needs to be updated to a newer version 20 | pip: 21 | name: "cffi==1.10.0" 22 | environment: 23 | PYTHONPATH: "{{ graphite_install_path }}/lib:{{ graphite_install_path }}/webapp" 24 | when: > 25 | ansible_distribution_release == "jessie" and 26 | graphite_install_version is version_compare("1.0.2", ">=") 27 | 28 | - name: Install systemd unit carbon-cache.service 29 | template: 30 | src: carbon_cache_systemd.j2 31 | dest: /etc/systemd/system/carbon-cache.service 32 | register: ccunit 33 | 34 | - name: Reload systemd if unit file has changed 35 | shell: systemctl daemon-reload 36 | when: ccunit is changed 37 | notify: restart carbon-cache 38 | 39 | - name: Install systemd unit carbon-relay.service 40 | template: 41 | src: carbon_relay_systemd.j2 42 | dest: /etc/systemd/system/carbon-relay.service 43 | register: ccunit 44 | 45 | - name: Reload systemd if unit file has changed 46 | shell: systemctl daemon-reload 47 | when: ccunit is changed 48 | notify: restart carbon-relay 49 | 50 | - name: Install uwsgi graphite config 51 | template: 52 | src: uwsgi_graphite.ini.j2 53 | dest: /etc/uwsgi/apps-available/graphite.ini 54 | notify: restart uwsgi 55 | 56 | - name: Enable uwsgi graphite config 57 | file: 58 | src: /etc/uwsgi/apps-available/graphite.ini 59 | dest: /etc/uwsgi/apps-enabled/graphite.ini 60 | state: link 61 | notify: restart uwsgi 62 | 63 | - name: Make sure we have /run/uwsgi/graphite 64 | file: 65 | path: /run/uwsgi/graphite 66 | state: directory 67 | owner: "{{ graphite_user }}" 68 | group: "{{ graphite_user }}" 69 | -------------------------------------------------------------------------------- /tasks/RedHat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install EPEL repository from repo 4 | yum: 5 | name: epel-release 6 | 7 | - name: Install packages with yum 8 | yum: 9 | name: "{{ packages }}" 10 | vars: 11 | packages: 12 | - python-pip 13 | - python-devel 14 | - gcc 15 | - cairo-devel 16 | - pycairo 17 | - bitmap-fonts-compat 18 | - libselinux-python 19 | - fontconfig 20 | - sudo 21 | - libffi-devel 22 | 23 | - name: Install uwsgi with pip 24 | pip: 25 | name: uwsgi 26 | 27 | - name: Install systemd unit carbon-cache.service 28 | template: 29 | src: carbon_cache_systemd.j2 30 | dest: /etc/systemd/system/carbon-cache.service 31 | register: ccunit 32 | 33 | - name: Reload systemd if unit file has changed 34 | shell: systemctl daemon-reload 35 | when: ccunit is changed 36 | notify: restart carbon-cache 37 | 38 | - name: Install systemd unit carbon-relay.service 39 | template: 40 | src: carbon_relay_systemd.j2 41 | dest: /etc/systemd/system/carbon-relay.service 42 | register: ccunit 43 | 44 | - name: Reload systemd if unit file has changed 45 | shell: systemctl daemon-reload 46 | when: ccunit is changed 47 | notify: restart carbon-relay 48 | 49 | - name: Install uwsgi default settings 50 | template: 51 | src: redhat_uwsgi_default.ini.j2 52 | dest: /etc/uwsgi_default.ini 53 | notify: restart uwsgi 54 | 55 | - name: Install uwsgi graphite config 56 | template: 57 | src: uwsgi_graphite.ini.j2 58 | dest: /etc/uwsgi_graphite.ini 59 | notify: restart uwsgi 60 | 61 | - name: Install systemd unit uwsgi.service 62 | template: 63 | src: uwsgi_systemd.j2 64 | dest: /etc/systemd/system/uwsgi.service 65 | register: uwsgiunit 66 | 67 | - name: Reload systemd if unit file has changed 68 | shell: systemctl daemon-reload 69 | when: uwsgiunit is changed 70 | notify: restart uwsgi 71 | -------------------------------------------------------------------------------- /tasks/django-admin.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: django-admin.py - Inspect graphite db 4 | command: django-admin.py inspectdb 5 | environment: 6 | DJANGO_SETTINGS_MODULE: graphite.settings 7 | PYTHONPATH: "{{ graphite_install_path}}/webapp/" 8 | become: yes 9 | become_user: "{{ graphite_user }}" 10 | register: result 11 | changed_when: False 12 | 13 | - name: django-admin.py - Check for secret key warning 14 | command: echo SECRET_KEY is set to an unsafe default. 15 | failed_when: "'SECRET_KEY' in result.stderr" 16 | changed_when: False 17 | 18 | - name: django-admin.py - Sync/create database 19 | command: django-admin.py migrate --run-syncdb --noinput 20 | environment: 21 | DJANGO_SETTINGS_MODULE: graphite.settings 22 | PYTHONPATH: "{{ graphite_install_path}}/webapp/" 23 | become: yes 24 | become_user: "{{ graphite_user }}" 25 | when: result.stdout.find("AccountMygraph") == -1 26 | 27 | - name: django-admin.py - Create superuser account 28 | command: > 29 | django-admin.py createsuperuser 30 | --username={{ graphite_admin_username }} 31 | --email={{ graphite_admin_email }} 32 | --noinput 33 | environment: 34 | DJANGO_SETTINGS_MODULE: graphite.settings 35 | PYTHONPATH: "{{ graphite_install_path}}/webapp/" 36 | become: yes 37 | become_user: "{{ graphite_user }}" 38 | register: superuser_created 39 | args: 40 | creates: "{{ graphite_install_path }}/webapp/graphite/.superuser_created" 41 | 42 | - name: django-admin.py - Prepare to set up superuser password 43 | template: 44 | src: createsuperuser.py.j2 45 | dest: /tmp/createsuperuser.py 46 | when: superuser_created is changed 47 | register: debug2 48 | 49 | - name: django-admin.py - Set superuser password 50 | shell: > 51 | django-admin.py 52 | shell < /tmp/createsuperuser.py 53 | environment: 54 | DJANGO_SETTINGS_MODULE: graphite.settings 55 | PYTHONPATH: "{{ graphite_install_path}}/webapp/" 56 | become: yes 57 | become_user: "{{ graphite_user }}" 58 | when: superuser_created is changed 59 | 60 | - name: django-admin.py - Create lock file 61 | file: 62 | path: "{{ graphite_install_path }}/webapp/graphite/.superuser_created" 63 | state: touch 64 | when: superuser_created is changed 65 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Install graphite 4 | 5 | - name: Create user 6 | user: 7 | name: "{{ graphite_user }}" 8 | comment: "Graphite user" 9 | 10 | - name: "Run tasks on a RedHat based system" 11 | include: RedHat.yml 12 | when: ansible_os_family == "RedHat" 13 | 14 | - name: "Run tasks on a Debian based system" 15 | include: Debian.yml 16 | when: ansible_os_family == "Debian" 17 | 18 | # Newer versions of pip needs --no-binary=:all: for graphite 19 | # ref: https://github.com/graphite-project/graphite-web/issues/1508 20 | - name: Setup graphite with pip 21 | pip: 22 | name: "{{ graphite_install_requirements[graphite_install_version] }}" 23 | extra_args: "--no-binary=:all:" 24 | environment: 25 | PYTHONPATH: "{{ graphite_install_path }}/lib:{{ graphite_install_path }}/webapp" 26 | register: graphite_installed_new 27 | notify: 28 | - restart carbon-cache 29 | - restart carbon-relay 30 | when: > 31 | ansible_distribution_release == "bionic" 32 | or ansible_distribution_release == "xenial" 33 | or ansible_distribution_release == "stretch" 34 | 35 | - name: Setup graphite with pip 36 | pip: 37 | name: "{{ graphite_install_requirements[graphite_install_version] }}" 38 | environment: 39 | PYTHONPATH: "{{ graphite_install_path }}/lib:{{ graphite_install_path }}/webapp" 40 | register: graphite_installed_old 41 | notify: 42 | - restart carbon-cache 43 | - restart carbon-relay 44 | when: > 45 | ansible_distribution_release != "bionic" 46 | and ansible_distribution_release != "xenial" 47 | and ansible_distribution_release != "stretch" 48 | 49 | - name: Set perms for graphite storage 50 | file: 51 | path: "{{ graphite_install_path }}/storage" 52 | owner: "{{ graphite_user }}" 53 | recurse: yes 54 | state: directory 55 | when: graphite_installed_old is changed or graphite_installed_new is changed 56 | 57 | - name: Install webapp settings 58 | template: 59 | src: local_settings.py.j2 60 | dest: "{{ graphite_install_path }}/webapp/graphite/local_settings.py" 61 | notify: 62 | - restart carbon-cache 63 | - restart carbon-relay 64 | 65 | - name: Install carbon settings 66 | template: 67 | src: carbon.conf.j2 68 | dest: "{{ graphite_install_path }}/conf/carbon.conf" 69 | notify: 70 | - restart carbon-cache 71 | - restart carbon-relay 72 | 73 | - name: Install relay rules 74 | template: 75 | src: relay-rules.conf.j2 76 | dest: "{{ graphite_install_path }}/conf/relay-rules.conf" 77 | notify: 78 | - restart carbon-cache 79 | - restart carbon-relay 80 | 81 | - name: Install storage schemas 82 | template: 83 | src: storage-schemas.conf.j2 84 | dest: "{{ graphite_install_path }}/conf/storage-schemas.conf" 85 | notify: 86 | - restart carbon-cache 87 | - restart carbon-relay 88 | 89 | - name: Install 0.9 uwsgi configuration 90 | template: 91 | src: wsgi.py.j2 92 | dest: "{{ graphite_install_path }}/conf/wsgi.py" 93 | notify: restart uwsgi 94 | when: graphite_install_version is version_compare("1.0.0", "<") 95 | 96 | - name: Install 1.0 uwsgi configuration 97 | template: 98 | src: wsgi-1.0.x.py.j2 99 | dest: "{{ graphite_install_path }}/conf/wsgi.py" 100 | notify: restart uwsgi 101 | when: graphite_install_version is version_compare("1.0.0", ">=") 102 | 103 | - name: Use manage.py to run configuration tasks 104 | include: manage.yml 105 | when: graphite_install_version is version_compare("1.0.2", "<") 106 | 107 | - name: Use django-admin.py to run configuration tasks 108 | include: django-admin.yml 109 | when: graphite_install_version is version_compare("1.0.2", ">=") 110 | 111 | - name: Remove temp file 112 | file: 113 | path: /tmp/createsuperuser.py 114 | state: absent 115 | 116 | - name: Enable uwsgi service 117 | service: 118 | name: uwsgi 119 | enabled: yes 120 | when: graphite_enable_uwsgi 121 | 122 | - name: Enable carbon-cache service 123 | service: 124 | name: carbon-cache 125 | enabled: yes 126 | when: graphite_enable_carbon_cache 127 | 128 | - name: Enable carbon-relay service 129 | service: 130 | name: carbon-relay 131 | enabled: yes 132 | when: graphite_enable_carbon_relay 133 | -------------------------------------------------------------------------------- /tasks/manage.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: manage.py - Inspect graphite db 4 | command: python {{ graphite_install_path }}/webapp/graphite/manage.py inspectdb 5 | become: yes 6 | become_user: "{{ graphite_user }}" 7 | register: result 8 | changed_when: False 9 | 10 | - name: manage.py - Check for secret key warning 11 | command: echo SECRET_KEY is set to an unsafe default. 12 | failed_when: "'SECRET_KEY' in result.stderr" 13 | changed_when: False 14 | 15 | - name: manage.py - Sync/create database 16 | command: python {{ graphite_install_path }}/webapp/graphite/manage.py syncdb --noinput 17 | become: yes 18 | become_user: "{{ graphite_user }}" 19 | when: result.stdout.find("AccountMygraph") == -1 20 | 21 | - name: manage.py - Create superuser account 22 | command: > 23 | python {{ graphite_install_path }}/webapp/graphite/manage.py createsuperuser 24 | --username={{ graphite_admin_username }} 25 | --email={{ graphite_admin_email }} 26 | --noinput 27 | become: yes 28 | become_user: "{{ graphite_user }}" 29 | register: superuser_created 30 | args: 31 | creates: "{{ graphite_install_path }}/webapp/graphite/.superuser_created" 32 | 33 | - name: manage.py - Prepare to set up superuser password 34 | template: 35 | src: createsuperuser.py.j2 36 | dest: /tmp/createsuperuser.py 37 | when: superuser_created is changed 38 | register: debug2 39 | 40 | - name: manage.py - Set superuser password 41 | shell: > 42 | python {{ graphite_install_path }}/webapp/graphite/manage.py 43 | shell < /tmp/createsuperuser.py 44 | become: yes 45 | become_user: "{{ graphite_user }}" 46 | when: superuser_created is changed 47 | 48 | - name: manage.py - Create lock file 49 | file: 50 | path: "{{ graphite_install_path }}/webapp/graphite/.superuser_created" 51 | state: touch 52 | when: superuser_created is changed 53 | -------------------------------------------------------------------------------- /templates/carbon.conf.j2: -------------------------------------------------------------------------------- 1 | # See {{ graphite_install_path }}/conf/carbon.conf.example for more information. 2 | 3 | [cache] 4 | LOCAL_DATA_DIR = {{ graphite_cache_local_data_dir }} 5 | DATABASE = {{ graphite_cache_database }} 6 | ENABLE_LOGROTATION = {{ graphite_cache_enable_log_rotation }} 7 | USER = {{ graphite_cache_user|default("") }} 8 | MAX_CACHE_SIZE = {{ graphite_cache_max_cache_size }} 9 | MAX_UPDATES_PER_SECOND = {{ graphite_cache_max_updates_per_second }} 10 | MAX_UPDATES_PER_SECOND_ON_SHUTDOWN = {{ graphite_cache_max_updates_per_second_on_shutdown }} 11 | MAX_CREATES_PER_MINUTE = {{ graphite_cache_max_creates_per_minute }} 12 | MIN_TIMESTAMP_RESOLUTION = {{ graphite_cache_min_timestamp_resolution }} 13 | LINE_RECEIVER_INTERFACE = {{ graphite_cache_line_receiver_interface }} 14 | LINE_RECEIVER_PORT = {{ graphite_cache_line_receiver_port }} 15 | ENABLE_UDP_LISTENER = {{ graphite_cache_enable_udp_listener }} 16 | UDP_RECEIVER_INTERFACE = {{ graphite_cache_udp_receiver_interface }} 17 | UDP_RECEIVER_PORT = {{ graphite_cache_udp_receiver_port }} 18 | PICKLE_RECEIVER_INTERFACE = {{ graphite_cache_pickle_receiver_interface }} 19 | PICKLE_RECEIVER_PORT = {{ graphite_cache_pickle_receiver_port }} 20 | {% if graphite_install_version is version_compare('1.1.5', '>=') and graphite_cache_graphite_url %} 21 | PICKLE_RECEIVER_MAX_LENGTH = {{ graphite_cache_pickle_receiver_max_length }} 22 | {% endif %} 23 | USE_INSECURE_UNPICKLER = {{ graphite_cache_use_insecure_unpickler }} 24 | CACHE_QUERY_INTERFACE = {{ graphite_cache_cache_query_interface }} 25 | CACHE_QUERY_PORT = {{ graphite_cache_cache_query_port }} 26 | USE_FLOW_CONTROL = {{ graphite_cache_use_flow_control }} 27 | LOG_UPDATES = {{ graphite_cache_log_updates }} 28 | LOG_CREATES = {{ graphite_cache_log_creates }} 29 | LOG_CACHE_HITS = {{ graphite_cache_log_cache_hits }} 30 | LOG_CACHE_QUEUE_SORTS = {{ graphite_cache_log_cache_queue_sorts }} 31 | CACHE_WRITE_STRATEGY = {{ graphite_cache_cache_write_strategy }} 32 | WHISPER_AUTOFLUSH = {{ graphite_cache_whisper_autoflush }} 33 | WHISPER_SPARSE_CREATE = {{ graphite_cache_whisper_sparse_create }} 34 | WHISPER_FALLOCATE_CREATE = {{ graphite_cache_whisper_fallocate_create }} 35 | WHISPER_LOCK_WRITES = {{ graphite_cache_whisper_lock_writes }} 36 | USE_WHITELIST = {{ graphite_cache_use_whitelist }} 37 | CARBON_METRIC_PREFIX = {{ graphite_cache_carbon_metric_prefix }} 38 | CARBON_METRIC_INTERVAL = {{ graphite_cache_carbon_metric_interval }} 39 | ENABLE_AMQP = {{ graphite_cache_enable_amqp }} 40 | AMQP_VERBOSE = {{ graphite_cache_amqp_verbose }} 41 | AMQP_HOST = {{ graphite_cache_amqp_host }} 42 | AMQP_PORT = {{ graphite_cache_amqp_port }} 43 | AMQP_VHOST = {{ graphite_cache_amqp_vhost }} 44 | AMQP_USER = {{ graphite_cache_amqp_user }} 45 | AMQP_PASSWORD = {{ graphite_cache_amqp_password }} 46 | AMQP_EXCHANGE = {{ graphite_cache_amqp_exchange }} 47 | AMQP_METRIC_NAME_IN_BODY = {{ graphite_cache_amqp_metric_name_in_body }} 48 | ENABLE_MANHOLE = {{ graphite_cache_enable_manhole }} 49 | MANHOLE_INTERFACE = {{ graphite_cache_manhole_interface }} 50 | MANHOLE_PORT = {{ graphite_cache_manhole_port }} 51 | MANHOLE_USER = {{ graphite_cache_manhole_user }} 52 | MANHOLE_PUBLIC_KEY = {{ graphite_cache_manhole_public_key }} 53 | BIND_PATTERNS = {{ graphite_cache_bind_patterns }} 54 | {% if graphite_install_version is version_compare('1.1.3', '>=') and graphite_cache_graphite_url %} 55 | GRAPHITE_URL = {{ graphite_cache_graphite_url }} 56 | {% endif %} 57 | 58 | [relay] 59 | {% if graphite_relay_user is defined -%} 60 | USER = {{ graphite_relay_user }} 61 | {% endif -%} 62 | LINE_RECEIVER_INTERFACE = {{ graphite_relay_line_receiver_interface }} 63 | LINE_RECEIVER_PORT = {{ graphite_relay_line_receiver_port }} 64 | PICKLE_RECEIVER_INTERFACE = {{ graphite_relay_pickle_receiver_interface }} 65 | PICKLE_RECEIVER_PORT = {{ graphite_relay_pickle_receiver_port }} 66 | {% if graphite_install_version is version_compare('1.1.5', '>=') and graphite_cache_graphite_url %} 67 | PICKLE_RECEIVER_MAX_LENGTH = {{ graphite_relay_pickle_receiver_max_length }} 68 | {% endif %} 69 | RELAY_METHOD = {{ graphite_relay_relay_method }} 70 | REPLICATION_FACTOR = {{ graphite_relay_replication_factor }} 71 | DESTINATIONS = {{ graphite_relay_destinations }} 72 | MAX_DATAPOINTS_PER_MESSAGE = {{ graphite_relay_max_datapoints_per_message }} 73 | QUEUE_LOW_WATERMARK_PCT = {{ graphite_relay_queue_low_watermark_pct }} 74 | TIME_TO_DEFER_SENDING = {{ graphite_relay_time_to_defer_sending }} 75 | MAX_QUEUE_SIZE = {{ graphite_relay_max_queue_size }} 76 | USE_FLOW_CONTROL = {{ graphite_relay_use_flow_control }} 77 | USE_RATIO_RESET = {{ graphite_relay_use_ratio_reset }} 78 | MIN_RESET_STAT_FLOW = {{ graphite_relay_min_reset_stat_flow }} 79 | MIN_RESET_RATIO = {{ graphite_relay_min_reset_ratio }} 80 | MIN_RESET_INTERVAL = {{ graphite_relay_min_reset_interval }} 81 | 82 | USE_WHITELIST = {{ graphite_relay_use_whitelist }} 83 | CARBON_METRIC_PREFIX = {{ graphite_relay_carbon_metric_prefix }} 84 | CARBON_METRIC_INTERVAL = {{ graphite_relay_carbon_metric_interval }} 85 | 86 | [aggregator] 87 | {% if graphite_aggregator_user is defined -%} 88 | USER = {{ graphite_aggregator_user }} 89 | {% endif -%} 90 | LINE_RECEIVER_INTERFACE = {{ graphite_aggregator_line_receiver_interface }} 91 | LINE_RECEIVER_PORT = {{ graphite_aggregator_line_receiver_port }} 92 | PICKLE_RECEIVER_INTERFACE = {{ graphite_aggregator_pickle_receiver_interface }} 93 | PICKLE_RECEIVER_PORT = {{ graphite_aggregator_pickle_receiver_port }} 94 | FORWARD_ALL = {{ graphite_aggregator_forward_all }} 95 | DESTINATIONS = {{ graphite_aggregator_destinations }} 96 | REPLICATION_FACTOR = {{ graphite_aggregator_replication_factor }} 97 | MAX_QUEUE_SIZE = {{ graphite_aggregator_max_queue_size }} 98 | USE_FLOW_CONTROL = {{ graphite_aggregator_use_flow_control }} 99 | MAX_DATAPOINTS_PER_MESSAGE = {{ graphite_aggregator_max_datapoints_per_message }} 100 | MAX_AGGREGATION_INTERVALS = {{ graphite_aggregator_max_aggregation_intervals }} 101 | WRITE_BACK_FREQUENCY = {{ graphite_aggregator_write_back_frequency }} 102 | USE_WHITELIST = {{ graphite_aggregator_use_whitelist }} 103 | CARBON_METRIC_PREFIX = {{ graphite_aggregator_carbon_metric_prefix }} 104 | CARBON_METRIC_INTERVAL = {{ graphite_aggregator_carbon_metric_interval }} 105 | -------------------------------------------------------------------------------- /templates/carbon_cache_systemd.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=carbon-cache 3 | After=network.target 4 | 5 | [Service] 6 | Environment="PYTHONPATH={{ graphite_install_path }}/lib:{{ graphite_install_path }}/webapp" 7 | 8 | ExecStart={{ graphite_install_path }}/bin/carbon-cache.py --nodaemon start 9 | Restart=on-failure 10 | User={{ graphite_user }} 11 | Group={{ graphite_user }} 12 | NoNewPrivileges=true 13 | LimitNOFILE={{ graphite_service_carbon_open_files_limit }} 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /templates/carbon_relay_systemd.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=carbon-relay 3 | After=network.target 4 | 5 | [Service] 6 | Environment="PYTHONPATH={{ graphite_install_path }}/lib:{{ graphite_install_path }}/webapp" 7 | 8 | ExecStart={{ graphite_install_path }}/bin/carbon-relay.py --nodaemon start 9 | Restart=on-failure 10 | User={{ graphite_user }} 11 | Group={{ graphite_user }} 12 | NoNewPrivileges=true 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /templates/createsuperuser.py.j2: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import User 2 | 3 | u = User.objects.get(username__exact='{{ graphite_admin_username }}') 4 | u.set_password('{{ graphite_admin_password }}') 5 | u.save() 6 | -------------------------------------------------------------------------------- /templates/debian_carbon_cache.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: carbon-cache 5 | # Required-Start: $remote_fs $syslog 6 | # Required-Stop: $remote_fs $syslog 7 | # Default-Start: 2 3 4 5 8 | # Default-Stop: 9 | # Short-Description: carbon-cache server 10 | ### END INIT INFO 11 | 12 | set -e 13 | 14 | test -x {{ graphite_install_path }}/bin/carbon-cache.py || exit 0 15 | 16 | umask 022 17 | ulimit -n {{ graphite_service_carbon_open_files_limit }} 18 | 19 | . /lib/lsb/init-functions 20 | 21 | if [ "x$2" != "x2nd" ]; then 22 | sudo -u {{ graphite_user }} $0 $1 2nd 23 | exit 0 24 | fi 25 | 26 | export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" 27 | export PYTHONPATH="{{ graphite_install_path }}/lib:{{ graphite_install_path }}/webapp" 28 | 29 | case "$1" in 30 | start) 31 | log_daemon_msg "Starting carbon-cache daemon" "carbon-cache" || true 32 | if {{ graphite_install_path }}/bin/carbon-cache.py start; then 33 | log_end_msg 0 || true 34 | else 35 | log_end_msg 1 || true 36 | fi 37 | ;; 38 | stop) 39 | log_daemon_msg "Stopping carbon-cache daemon" "carbon-cache" || true 40 | if {{ graphite_install_path }}/bin/carbon-cache.py stop; then 41 | log_end_msg 0 || true 42 | else 43 | log_end_msg 1 || true 44 | fi 45 | ;; 46 | 47 | restart) 48 | log_daemon_msg "Restarting carbon-cache daemon" "carbon-cache" || true 49 | {{ graphite_install_path }}/bin/carbon-cache.py stop 50 | if {{ graphite_install_path }}/bin/carbon-cache.py start; then 51 | log_end_msg 0 || true 52 | else 53 | log_end_msg 1 || true 54 | fi 55 | ;; 56 | 57 | status) 58 | {{ graphite_install_path }}/bin/carbon-cache.py status && exit 0 || exit $? 59 | ;; 60 | 61 | *) 62 | log_action_msg "Usage: /etc/init.d/carbon-cache {start|stop|restart|status}" || true 63 | exit 1 64 | esac 65 | 66 | exit 0 67 | -------------------------------------------------------------------------------- /templates/debian_carbon_relay.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: carbon-relay 5 | # Required-Start: $remote_fs $syslog 6 | # Required-Stop: $remote_fs $syslog 7 | # Default-Start: 2 3 4 5 8 | # Default-Stop: 9 | # Short-Description: carbon-relay server 10 | ### END INIT INFO 11 | 12 | set -e 13 | 14 | test -x {{ graphite_install_path }}/bin/carbon-relay.py || exit 0 15 | 16 | umask 022 17 | 18 | . /lib/lsb/init-functions 19 | 20 | if [ "x$2" != "x2nd" ]; then 21 | sudo -u {{ graphite_user }} $0 $1 2nd 22 | exit 0 23 | fi 24 | 25 | export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" 26 | export PYTHONPATH="{{ graphite_install_path }}/lib:{{ graphite_install_path }}/webapp" 27 | 28 | case "$1" in 29 | start) 30 | log_daemon_msg "Starting carbon-relay daemon" "carbon-relay" || true 31 | if {{ graphite_install_path }}/bin/carbon-relay.py start; then 32 | log_end_msg 0 || true 33 | else 34 | log_end_msg 1 || true 35 | fi 36 | ;; 37 | stop) 38 | log_daemon_msg "Stopping carbon-relay daemon" "carbon-relay" || true 39 | if {{ graphite_install_path }}/bin/carbon-relay.py stop; then 40 | log_end_msg 0 || true 41 | else 42 | log_end_msg 1 || true 43 | fi 44 | ;; 45 | 46 | restart) 47 | log_daemon_msg "Restarting carbon-relay daemon" "carbon-relay" || true 48 | {{ graphite_install_path }}/bin/carbon-relay.py stop 49 | if {{ graphite_install_path }}/bin/carbon-relay.py start; then 50 | log_end_msg 0 || true 51 | else 52 | log_end_msg 1 || true 53 | fi 54 | ;; 55 | 56 | status) 57 | {{ graphite_install_path }}/bin/carbon-relay.py status && exit 0 || exit $? 58 | ;; 59 | 60 | *) 61 | log_action_msg "Usage: /etc/init.d/carbon-relay {start|stop|restart|status}" || true 62 | exit 1 63 | esac 64 | 65 | exit 0 66 | -------------------------------------------------------------------------------- /templates/local_settings.py.j2: -------------------------------------------------------------------------------- 1 | ## Graphite local_settings.py 2 | # Edit this file to customize the default Graphite webapp settings 3 | # 4 | # Additional customizations to Django settings can be added to this file as well 5 | 6 | ##################################### 7 | # General Configuration # 8 | ##################################### 9 | # Set this to a long, random unique string to use as a secret key for this 10 | # install. This key is used for salting of hashes used in auth tokens, 11 | # CRSF middleware, cookie storage, etc. This should be set identically among 12 | # instances if used behind a load balancer. 13 | SECRET_KEY = '{{ graphite_secret_key }}' 14 | 15 | # In Django 1.5+ set this to the list of hosts your graphite instances is 16 | # accessible as. See: 17 | # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-ALLOWED_HOSTS 18 | #ALLOWED_HOSTS = [ '*' ] 19 | 20 | # Set your local timezone (Django's default is America/Chicago) 21 | # If your graphs appear to be offset by a couple hours then this probably 22 | # needs to be explicitly set to your local timezone. 23 | TIME_ZONE = '{{ graphite_time_zone }}' 24 | 25 | # Override this to provide documentation specific to your Graphite deployment 26 | #DOCUMENTATION_URL = "http://graphite.readthedocs.org/" 27 | 28 | # Logging 29 | #LOG_RENDERING_PERFORMANCE = True 30 | #LOG_CACHE_PERFORMANCE = True 31 | #LOG_METRIC_ACCESS = True 32 | 33 | # Enable full debug page display on exceptions (Internal Server Error pages) 34 | #DEBUG = True 35 | 36 | # If using RRD files and rrdcached, set to the address or socket of the daemon 37 | #FLUSHRRDCACHED = 'unix:/var/run/rrdcached.sock' 38 | 39 | # This lists the memcached servers that will be used by this webapp. 40 | # If you have a cluster of webapps you should ensure all of them 41 | # have the *exact* same value for this setting. That will maximize cache 42 | # efficiency. Setting MEMCACHE_HOSTS to be empty will turn off use of 43 | # memcached entirely. 44 | # 45 | # You should not use the loopback address (127.0.0.1) here if using clustering 46 | # as every webapp in the cluster should use the exact same values to prevent 47 | # unneeded cache misses. Set to [] to disable caching of images and fetched data 48 | #MEMCACHE_HOSTS = ['10.10.10.10:11211', '10.10.10.11:11211', '10.10.10.12:11211'] 49 | #DEFAULT_CACHE_DURATION = 60 # Cache images and data for 1 minute 50 | 51 | 52 | ##################################### 53 | # Filesystem Paths # 54 | ##################################### 55 | # Change only GRAPHITE_ROOT if your install is merely shifted from /opt/graphite 56 | # to somewhere else 57 | #GRAPHITE_ROOT = '/opt/graphite' 58 | 59 | # Most installs done outside of a separate tree such as /opt/graphite will only 60 | # need to change these three settings. Note that the default settings for each 61 | # of these is relative to GRAPHITE_ROOT 62 | #CONF_DIR = '/opt/graphite/conf' 63 | #STORAGE_DIR = '/opt/graphite/storage' 64 | #CONTENT_DIR = '/opt/graphite/webapp/content' 65 | 66 | # To further or fully customize the paths, modify the following. Note that the 67 | # default settings for each of these are relative to CONF_DIR and STORAGE_DIR 68 | # 69 | ## Webapp config files 70 | #DASHBOARD_CONF = '/opt/graphite/conf/dashboard.conf' 71 | #GRAPHTEMPLATES_CONF = '/opt/graphite/conf/graphTemplates.conf' 72 | 73 | ## Data directories 74 | # NOTE: If any directory is unreadable in DATA_DIRS it will break metric browsing 75 | #WHISPER_DIR = '/opt/graphite/storage/whisper' 76 | #RRD_DIR = '/opt/graphite/storage/rrd' 77 | #DATA_DIRS = [WHISPER_DIR, RRD_DIR] # Default: set from the above variables 78 | #LOG_DIR = '/opt/graphite/storage/log/webapp' 79 | #INDEX_FILE = '/opt/graphite/storage/index' # Search index file 80 | 81 | 82 | ##################################### 83 | # Email Configuration # 84 | ##################################### 85 | # This is used for emailing rendered Graphs 86 | # Default backend is SMTP 87 | #EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' 88 | #EMAIL_HOST = 'localhost' 89 | #EMAIL_PORT = 25 90 | #EMAIL_HOST_USER = '' 91 | #EMAIL_HOST_PASSWORD = '' 92 | #EMAIL_USE_TLS = False 93 | # To drop emails on the floor, enable the Dummy backend: 94 | #EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' 95 | 96 | 97 | ##################################### 98 | # Authentication Configuration # 99 | ##################################### 100 | ## LDAP / ActiveDirectory authentication setup 101 | #USE_LDAP_AUTH = True 102 | #LDAP_SERVER = "ldap.mycompany.com" 103 | #LDAP_PORT = 389 104 | # OR 105 | #LDAP_URI = "ldaps://ldap.mycompany.com:636" 106 | #LDAP_SEARCH_BASE = "OU=users,DC=mycompany,DC=com" 107 | #LDAP_BASE_USER = "CN=some_readonly_account,DC=mycompany,DC=com" 108 | #LDAP_BASE_PASS = "readonly_account_password" 109 | #LDAP_USER_QUERY = "(username=%s)" #For Active Directory use "(sAMAccountName=%s)" 110 | # 111 | # If you want to further customize the ldap connection options you should 112 | # directly use ldap.set_option to set the ldap module's global options. 113 | # For example: 114 | # 115 | #import ldap 116 | #ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW) 117 | #ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, "/etc/ssl/ca") 118 | #ldap.set_option(ldap.OPT_X_TLS_CERTFILE, "/etc/ssl/mycert.pem") 119 | #ldap.set_option(ldap.OPT_X_TLS_KEYFILE, "/etc/ssl/mykey.pem") 120 | # See http://www.python-ldap.org/ for further details on these options. 121 | 122 | ## REMOTE_USER authentication. See: https://docs.djangoproject.com/en/dev/howto/auth-remote-user/ 123 | #USE_REMOTE_USER_AUTHENTICATION = True 124 | 125 | # Override the URL for the login link (e.g. for django_openid_auth) 126 | #LOGIN_URL = '/account/login' 127 | 128 | 129 | ########################## 130 | # Database Configuration # 131 | ########################## 132 | # By default sqlite is used. If you cluster multiple webapps you will need 133 | # to setup an external database (such as MySQL) and configure all of the webapp 134 | # instances to use the same database. Note that this database is only used to store 135 | # Django models such as saved graphs, dashboards, user preferences, etc. 136 | # Metric data is not stored here. 137 | # 138 | # DO NOT FORGET TO RUN 'manage.py syncdb' AFTER SETTING UP A NEW DATABASE 139 | # 140 | # The following built-in database engines are available: 141 | # django.db.backends.postgresql # Removed in Django 1.4 142 | # django.db.backends.postgresql_psycopg2 143 | # django.db.backends.mysql 144 | # django.db.backends.sqlite3 145 | # django.db.backends.oracle 146 | # 147 | # The default is 'django.db.backends.sqlite3' with file 'graphite.db' 148 | # located in STORAGE_DIR 149 | # 150 | #DATABASES = { 151 | # 'default': { 152 | # 'NAME': '/opt/graphite/storage/graphite.db', 153 | # 'ENGINE': 'django.db.backends.sqlite3', 154 | # 'USER': '', 155 | # 'PASSWORD': '', 156 | # 'HOST': '', 157 | # 'PORT': '' 158 | # } 159 | #} 160 | # 161 | 162 | 163 | ######################### 164 | # Cluster Configuration # 165 | ######################### 166 | # (To avoid excessive DNS lookups you want to stick to using IP addresses only in this entire section) 167 | # 168 | # This should list the IP address (and optionally port) of the webapp on each 169 | # remote server in the cluster. These servers must each have local access to 170 | # metric data. Note that the first server to return a match for a query will be 171 | # used. 172 | #CLUSTER_SERVERS = ["10.0.2.2:80", "10.0.2.3:80"] 173 | CLUSTER_SERVERS = {{ graphite_cluster_servers }} 174 | 175 | ## These are timeout values (in seconds) for requests to remote webapps 176 | #REMOTE_STORE_FETCH_TIMEOUT = 6 # Timeout to fetch series data 177 | #REMOTE_STORE_FIND_TIMEOUT = 2.5 # Timeout for metric find requests 178 | #REMOTE_STORE_RETRY_DELAY = 60 # Time before retrying a failed remote webapp 179 | #REMOTE_FIND_CACHE_DURATION = 300 # Time to cache remote metric find results 180 | 181 | ## Remote rendering settings 182 | # Set to True to enable rendering of Graphs on a remote webapp 183 | #REMOTE_RENDERING = True 184 | # List of IP (and optionally port) of the webapp on each remote server that 185 | # will be used for rendering. Note that each rendering host should have local 186 | # access to metric data or should have CLUSTER_SERVERS configured 187 | #RENDERING_HOSTS = [] 188 | #REMOTE_RENDER_CONNECT_TIMEOUT = 1.0 189 | 190 | # If you are running multiple carbon-caches on this machine (typically behind a relay using 191 | # consistent hashing), you'll need to list the ip address, cache query port, and instance name of each carbon-cache 192 | # instance on the local machine (NOT every carbon-cache in the entire cluster). The default cache query port is 7002 193 | # and a common scheme is to use 7102 for instance b, 7202 for instance c, etc. 194 | # 195 | # You *should* use 127.0.0.1 here in most cases 196 | #CARBONLINK_HOSTS = ["127.0.0.1:7002:a", "127.0.0.1:7102:b", "127.0.0.1:7202:c"] 197 | #CARBONLINK_TIMEOUT = 1.0 198 | 199 | ##################################### 200 | # Additional Django Settings # 201 | ##################################### 202 | # Uncomment the following line for direct access to Django settings such as 203 | # MIDDLEWARE_CLASSES or APPS 204 | #from graphite.app_settings import * 205 | -------------------------------------------------------------------------------- /templates/redhat_uwsgi_default.ini.j2: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | autoload = true 3 | master = true 4 | workers = 2 5 | no-orphans = true 6 | chmod-socket = 660 7 | log-date = true 8 | uid = {{ graphite_user }} 9 | gid = {{ graphite_user }} 10 | -------------------------------------------------------------------------------- /templates/relay-rules.conf.j2: -------------------------------------------------------------------------------- 1 | # Relay destination rules for carbon-relay. Entries are scanned in order, 2 | # and the first pattern a metric matches will cause processing to cease after sending 3 | # unless `continue` is set to true 4 | # 5 | # [name] 6 | # pattern = 7 | # destinations = 8 | # continue = # default: False 9 | # 10 | # name: Arbitrary unique name to identify the rule 11 | # pattern: Regex pattern to match against the metric name 12 | # destinations: Comma-separated list of destinations. 13 | # ex: 127.0.0.1:2004:a, 10.1.2.4:2004, myserver.mydomain.com:2004 14 | # continue: Continue processing rules if this rule matches (default: False) 15 | 16 | # You must have exactly one section with 'default = true' 17 | # Note that all destinations listed must also exist in carbon.conf 18 | # in the DESTINATIONS setting in the [relay] section 19 | [default] 20 | default = true 21 | destinations = 127.0.0.1:2004:a, 127.0.0.1:2104:b 22 | -------------------------------------------------------------------------------- /templates/storage-schemas.conf.j2: -------------------------------------------------------------------------------- 1 | # Schema definitions for Whisper files. Entries are scanned in order, 2 | # and first match wins. This file is scanned for changes every 60 seconds. 3 | # 4 | # [name] 5 | # pattern = regex 6 | # retentions = timePerPoint:timeToStore, timePerPoint:timeToStore, ... 7 | 8 | {% for schema in graphite_storage_schemas %} 9 | [{{ schema.name }}] 10 | pattern = {{ schema.pattern }} 11 | retentions = {{ schema.retentions }} 12 | {% endfor %} 13 | 14 | # Carbon's internal metrics. This entry should match what is specified in 15 | # CARBON_METRIC_PREFIX and CARBON_METRIC_INTERVAL settings 16 | [carbon] 17 | pattern = ^carbon\. 18 | retentions = {{ graphite_storage_schemas_carbon_retentions }} 19 | 20 | [default] 21 | pattern = .* 22 | retentions = {{ graphite_storage_schemas_default_retentions }} 23 | 24 | -------------------------------------------------------------------------------- /templates/uwsgi_graphite.ini.j2: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | processes = {{ uwsgi_graphite_processes }} 3 | socket = {{ uwsgi_graphite_socket }} 4 | gid = {{ graphite_user }} 5 | uid = {{ graphite_user }} 6 | chdir = /opt/graphite/conf 7 | module = wsgi:application 8 | {% if ansible_os_family == "RedHat" %} 9 | pidfile = /run/uwsgi/graphite/pid 10 | {% endif %} 11 | {% for opts in uwsgi_graphite_extraopts %} 12 | {{ opts.option }}={{ opts.value }} 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /templates/uwsgi_systemd.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=uwsgi 3 | Requires=network-online.target 4 | After=network-online.target 5 | 6 | [Service] 7 | ExecStartPre=/bin/mkdir -p /run/uwsgi/graphite 8 | ExecStartPre=/bin/chown {{ graphite_user }}:{{ graphite_user }} /run/uwsgi/graphite 9 | ExecStartPre=/bin/touch /var/log/uwsgi_graphite.log 10 | ExecStartPre=/bin/chown {{ graphite_user }}:{{ graphite_user }} /var/log/uwsgi_graphite.log 11 | 12 | ExecStart=/usr/bin/uwsgi \ 13 | --ini /etc/uwsgi_default.ini \ 14 | --ini /etc/uwsgi_graphite.ini 15 | 16 | ExecReload=/bin/kill -HUP $MAINPID 17 | KillSignal=SIGINT 18 | Restart=on-failure 19 | User={{ graphite_user }} 20 | Group={{ graphite_user }} 21 | PermissionsStartOnly=true 22 | NoNewPrivileges=true 23 | 24 | [Install] 25 | WantedBy=multi-user.target 26 | -------------------------------------------------------------------------------- /templates/wsgi-1.0.x.py.j2: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('/opt/graphite/webapp') 3 | 4 | from graphite.wsgi import application -------------------------------------------------------------------------------- /templates/wsgi.py.j2: -------------------------------------------------------------------------------- 1 | import os, sys 2 | sys.path.append('/opt/graphite/webapp') 3 | os.environ['DJANGO_SETTINGS_MODULE'] = 'graphite.settings' 4 | 5 | import django.core.handlers.wsgi 6 | 7 | application = django.core.handlers.wsgi.WSGIHandler() 8 | 9 | # READ THIS 10 | # Initializing the search index can be very expensive, please include 11 | # the WSGIImportScript directive pointing to this script in your vhost 12 | # config to ensure the index is preloaded before any requests are handed 13 | # to the process. 14 | from graphite.logger import log 15 | log.info("graphite.wsgi - pid %d - reloading search index" % os.getpid()) 16 | import graphite.metrics.search 17 | -------------------------------------------------------------------------------- /tests/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Tests executed from Travis 4 | 5 | - hosts: all 6 | roles: 7 | - role: ansible-graphite 8 | graphite_secret_key: testtest123 9 | graphite_install_version: "{{ version }}" 10 | graphite_cache_graphite_url: 'http://127.0.0.1:8080' 11 | -------------------------------------------------------------------------------- /tests/post.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | tasks: 5 | 6 | - name: Install nginx (Debian) 7 | apt: name=nginx 8 | when: ansible_os_family == "Debian" 9 | 10 | - name: Install nginx (RedHat) 11 | yum: name=nginx 12 | when: ansible_os_family == "RedHat" 13 | 14 | - name: Install nginx config 15 | template: 16 | src: templates/graphite.conf.j2 17 | dest: /etc/nginx/conf.d/graphite.conf 18 | 19 | - name: Start nginx 20 | service: 21 | name: nginx 22 | state: restarted 23 | 24 | - name: Make sure processes are running 25 | shell: "pgrep {{ item }}" 26 | with_items: 27 | - carbon-cache 28 | - uwsgi 29 | - nginx 30 | 31 | - name: Make sure that the carbon-cache process has the expected open file limit 32 | shell: "test $(awk '/^Max open files/ { print $4 }' /proc/$(pidof -x carbon-cache.py)/limits) -eq 4096" 33 | 34 | - name: Get sample config file parameters 35 | shell: "grep -vE '^#' /opt/graphite/conf/carbon.conf.example | awk -F '=' '/=/{ print $1 }'" 36 | register: carbon_conf_example_default_params 37 | 38 | - name: Make sure that we have set all default params in carbon.conf 39 | shell: "grep -E '^{{ item }}' /opt/graphite/conf/carbon.conf" 40 | with_items: "{{ carbon_conf_example_default_params.stdout_lines }}" 41 | 42 | - name: Get set config file parameters 43 | shell: "grep -vE '^#' /opt/graphite/conf/carbon.conf | awk '/=/{ print $1 }'" 44 | register: carbon_conf_params 45 | 46 | - name: Make sure that carbon.conf is not using params not found in the example file 47 | shell: "grep '{{ item }}' /opt/graphite/conf/carbon.conf.example" 48 | with_items: "{{ carbon_conf_params.stdout_lines }}" 49 | 50 | - name: "Make sure we have a Graphite install at localhost:8080" 51 | shell: "curl -s http://localhost:8080 | grep 'Graphite Browser'" 52 | 53 | - name: "Make sure that the static content works" 54 | shell: "curl -s http://localhost:8080/static/js/composer.js" 55 | 56 | - name: Download a sample graph 57 | shell: "curl -so out 'http://localhost:8080/render/?width=586&height=308&_salt=1448804805.156&target=carbon.agents.*-a.cache.size'" 58 | 59 | - name: Make sure that we got a image 60 | shell: file out | grep -i image 61 | 62 | - name: "Insert a metric to carbon" 63 | shell: echo "local.random.diceroll 4711 $(date +%s)" | nc -w 2 0.0.0.0 2003 64 | 65 | - name: Wait 5 sec 66 | command: sleep 5 # pause failes on centos 7 for some reason 67 | 68 | - name: Search for the value from graphite-web 69 | shell: "curl -s 'http://localhost:8080/render/?_salt=1448817576.96&target=local.random.diceroll&format=csv' | grep ',4711.0'" 70 | 71 | - name: Remove false positives from carbon creates.log 72 | lineinfile: 73 | dest: /opt/graphite/storage/log/carbon-cache/carbon-cache-a/creates.log 74 | line: "- REMOVED -" 75 | regexp: "{{ item }}" 76 | with_items: 77 | - "creating database file.*errors.wsp" 78 | - "creating database metric carbon.agents.*errors" 79 | - "new metric carbon.agents.*a.errors matched schema carbon" 80 | - "new metric carbon.agents.*a.errors matched aggregation schema default" 81 | failed_when: False 82 | 83 | - name: Search for errors in logs 84 | shell: test -f {{ item }} && cat {{ item }} 85 | register: logout 86 | failed_when: > 87 | 'error' in logout.stdout or 88 | 'Error' in logout.stdout or 89 | 'ERROR' in logout.stdout 90 | with_items: 91 | - /var/log/uwsgi_graphite.log 92 | - /var/log/uwsgi/app/graphite.log 93 | - /var/log/nginx/graphite.error.log 94 | - /var/log/nginx/error.log 95 | - /opt/graphite/storage/log/webapp/info.log 96 | - /opt/graphite/storage/log/webapp/exception.log 97 | - /opt/graphite/storage/log/carbon-cache/carbon-cache-a/query.log 98 | - /opt/graphite/storage/log/carbon-cache/carbon-cache-a/listener.log 99 | - /opt/graphite/storage/log/carbon-cache/carbon-cache-a/creates.log 100 | - /opt/graphite/storage/log/carbon-cache/carbon-cache-a/console.log 101 | -------------------------------------------------------------------------------- /tests/pre.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | pre_tasks: 5 | 6 | - name: RedHat | Install a few packages for the tests 7 | yum: name={{ packages }} 8 | vars: 9 | packages: 10 | - file 11 | - nc 12 | when: ansible_os_family == "RedHat" 13 | 14 | - name: Debian | Install a few packages for the tests 15 | apt: name={{ packages }} 16 | vars: 17 | packages: 18 | - curl 19 | - file 20 | - netcat 21 | when: ansible_os_family == "Debian" 22 | -------------------------------------------------------------------------------- /tests/templates/graphite.conf.j2: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8080; 3 | charset utf-8; 4 | access_log /var/log/nginx/graphite.access.log; 5 | error_log /var/log/nginx/graphite.error.log; 6 | 7 | location /static { 8 | alias /opt/graphite/webapp/content; 9 | expires max; 10 | } 11 | 12 | location / { 13 | include uwsgi_params; 14 | uwsgi_pass 127.0.0.1:3031; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | --------------------------------------------------------------------------------