diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml index 3d70edf635..d24df918fb 100644 --- a/ansible/group_vars/all.yml +++ b/ansible/group_vars/all.yml @@ -317,6 +317,8 @@ opendaylight_openflow_port: "6653" opendaylight_ovsdb_port: "6641" opendaylight_haproxy_ovsdb_port: "6642" +vitrage_api_port: "8999" + public_protocol: "{{ 'https' if kolla_enable_tls_external | bool else 'http' }}" internal_protocol: "http" admin_protocol: "http" @@ -457,6 +459,7 @@ enable_tacker: "no" enable_telegraf: "no" enable_tempest: "no" enable_trove: "no" +enable_vitrage: "no" enable_vmtp: "no" enable_watcher: "no" enable_zun: "no" diff --git a/ansible/inventory/all-in-one b/ansible/inventory/all-in-one index 16d04f6798..23cf786987 100644 --- a/ansible/inventory/all-in-one +++ b/ansible/inventory/all-in-one @@ -185,6 +185,9 @@ control [tacker:children] control +[vitrage:children] +control + # Tempest [tempest:children] control @@ -593,3 +596,19 @@ tacker [tacker-conductor:children] tacker + +# Vitrage +[vitrage-api:children] +vitrage + +[vitrage-notifier:children] +vitrage + +[vitrage-graph:children] +vitrage + +[vitrage-collector:children] +vitrage + +[vitrage-ml:children] +vitrage diff --git a/ansible/inventory/multinode b/ansible/inventory/multinode index 9dd45d6bc7..533ec560a3 100644 --- a/ansible/inventory/multinode +++ b/ansible/inventory/multinode @@ -216,6 +216,9 @@ control [vmtp:children] control +[vitrage:children] +control + [watcher:children] control @@ -611,3 +614,19 @@ tacker [tacker-conductor:children] tacker + +# Vitrage +[vitrage-api:children] +vitrage + +[vitrage-notifier:children] +vitrage + +[vitrage-graph:children] +vitrage + +[vitrage-collector:children] +vitrage + +[vitrage-ml:children] +vitrage diff --git a/ansible/roles/common/tasks/config.yml b/ansible/roles/common/tasks/config.yml index 1e89d48eb4..e48b98fd0f 100644 --- a/ansible/roles/common/tasks/config.yml +++ b/ansible/roles/common/tasks/config.yml @@ -193,6 +193,7 @@ - { name: "tacker", enabled: "{{ enable_tacker }}" } - { name: "tempest", enabled: "{{ enable_tempest }}" } - { name: "trove", enabled: "{{ enable_trove }}" } + - { name: "vitrage", enabled: "{{ enable_vitrage }}" } - { name: "watcher", enabled: "{{ enable_watcher }}" } - { name: "zun", enabled: "{{ enable_zun }}" } notify: diff --git a/ansible/roles/common/templates/conf/filter/01-rewrite-0.12.conf.j2 b/ansible/roles/common/templates/conf/filter/01-rewrite-0.12.conf.j2 index 8fcb7435d0..d998ef630b 100644 --- a/ansible/roles/common/templates/conf/filter/01-rewrite-0.12.conf.j2 +++ b/ansible/roles/common/templates/conf/filter/01-rewrite-0.12.conf.j2 @@ -2,7 +2,7 @@ @type rewrite_tag_filter capitalize_regex_backreference yes rewriterule1 programname ^(cinder-api-access|cloudkitty-api-access|gnocchi-api-access|horizon-access|keystone-apache-admin-access|keystone-apache-public-access|placement-api-access|panko-api-access)$ apache_access - rewriterule2 programname ^(aodh_wsgi_access|barbican-api|zun_api_wsgi_access)$ wsgi_access + rewriterule2 programname ^(aodh_wsgi_access|barbican-api|zun_api_wsgi_access|vitrage_wsgi_access)$ wsgi_access rewriterule3 programname ^(nova-api|nova-compute|nova-compute-ironic|nova-conductor|nova-consoleauth|nova-manage|nova-novncproxy|nova-scheduler|nova-placement-api|placement-api|privsep-helper)$ openstack_python rewriterule4 programname ^(sahara-api|sahara-engine)$ openstack_python rewriterule5 programname ^(neutron-server|neutron-openvswitch-agent|neutron-ns-metadata-proxy|neutron-metadata-agent|neutron-l3-agent|neutron-dhcp-agent)$ openstack_python @@ -31,4 +31,5 @@ rewriterule28 programname ^(ironic-api|ironic-conductor)$ openstack_python rewriterule29 programname ^(panko-api|panko-dbsync)$ openstack_python rewriterule30 programname ^(tacker-server|tacker-conductor)$ openstack_python + rewriterule31 programname ^(vitrage-collector|vitrage-ml|vitrage-notifier|vitrage-graph)$ openstack_python diff --git a/ansible/roles/common/templates/conf/filter/01-rewrite-0.14.conf.j2 b/ansible/roles/common/templates/conf/filter/01-rewrite-0.14.conf.j2 index 30467357a4..7d93201ceb 100644 --- a/ansible/roles/common/templates/conf/filter/01-rewrite-0.14.conf.j2 +++ b/ansible/roles/common/templates/conf/filter/01-rewrite-0.14.conf.j2 @@ -8,7 +8,7 @@ key programname - pattern ^(aodh_wsgi_access|barbican-api|zun_api_wsgi_access)$ + pattern ^(aodh_wsgi_access|barbican-api|zun_api_wsgi_access|vitrage_wsgi_access)$ tag wsgi_access @@ -151,4 +151,9 @@ pattern ^(tacker-server|tacker-conductor)$ tag openstack_python + + key programname + pattern ^(vitrage-collector|vitrage-ml|vitrage-notifier|vitrage-graph)$ + tag openstack_python + diff --git a/ansible/roles/common/templates/cron-logrotate-vitrage.conf.j2 b/ansible/roles/common/templates/cron-logrotate-vitrage.conf.j2 new file mode 100644 index 0000000000..08409f080f --- /dev/null +++ b/ansible/roles/common/templates/cron-logrotate-vitrage.conf.j2 @@ -0,0 +1,3 @@ +"/var/log/kolla/vitrage/*.log" +{ +} diff --git a/ansible/roles/common/templates/cron.json.j2 b/ansible/roles/common/templates/cron.json.j2 index 59f50fc2bb..e8a071d2bb 100644 --- a/ansible/roles/common/templates/cron.json.j2 +++ b/ansible/roles/common/templates/cron.json.j2 @@ -50,6 +50,7 @@ ( 'tacker', enable_tacker ), ( 'tempest', enable_tempest ), ( 'trove', enable_trove ), + ( 'vitrage', enable_vitrage ), ( 'watcher', enable_watcher ), ( 'zun', enable_zun ) ] %} diff --git a/ansible/roles/haproxy/tasks/precheck.yml b/ansible/roles/haproxy/tasks/precheck.yml index 3e5973205a..c8bba75587 100644 --- a/ansible/roles/haproxy/tasks/precheck.yml +++ b/ansible/roles/haproxy/tasks/precheck.yml @@ -697,3 +697,14 @@ - enable_zun | bool - inventory_hostname in groups['haproxy'] - haproxy_stat.find('zun_api') == -1 + +- name: Checking free port for Vitrage API HAProxy + wait_for: + host: "{{ kolla_internal_vip_address }}" + port: "{{ vitrage_api_port }}" + connect_timeout: 1 + state: stopped + when: + - enable_vitrage | bool + - inventory_hostname in groups['haproxy'] + - haproxy_stat.find('vitrage_api') == -1 diff --git a/ansible/roles/haproxy/templates/haproxy.cfg.j2 b/ansible/roles/haproxy/templates/haproxy.cfg.j2 index 726fa7f742..74072bc014 100644 --- a/ansible/roles/haproxy/templates/haproxy.cfg.j2 +++ b/ansible/roles/haproxy/templates/haproxy.cfg.j2 @@ -843,6 +843,25 @@ listen skydive_server_external {% endif %} {% endif %} +{% if enable_vitrage | bool %} +listen vitrage_api + bind {{ kolla_internal_vip_address }}:{{ vitrage_api_port }} + http-request del-header X-Forwarded-Proto +{% for host in groups['vitrage-api'] %} + server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ vitrage_api_port }} check inter 2000 rise 2 fall 5 +{% endfor %} +{% if haproxy_enable_external_vip | bool %} + +listen vitrage_api_external + bind {{ kolla_external_vip_address }}:{{ vitrage_api_port }} {{ tls_bind_info }} + http-request del-header X-Forwarded-Proto + http-request set-header X-Forwarded-Proto https if { ssl_fc } +{% for host in groups['vitrage-api'] %} + server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ vitrage_api_port }} check inter 2000 rise 2 fall 5 +{% endfor %} +{% endif %} +{% endif %} + # (NOTE): This defaults section deletes forwardfor as recommended by: # https://marc.info/?l=haproxy&m=141684110710132&w=1 diff --git a/ansible/roles/vitrage/defaults/main.yml b/ansible/roles/vitrage/defaults/main.yml new file mode 100644 index 0000000000..51996e37d6 --- /dev/null +++ b/ansible/roles/vitrage/defaults/main.yml @@ -0,0 +1,129 @@ +--- +project_name: "vitrage" + +vitrage_services: + vitrage-api: + container_name: vitrage_api + group: vitrage-api + enabled: true + image: "{{ vitrage_api_image_full }}" + volumes: + - "{{ node_config_directory }}/vitrage-api/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" + vitrage-collector: + container_name: vitrage_collector + group: vitrage-collector + enabled: true + image: "{{ vitrage_collector_image_full }}" + volumes: + - "{{ node_config_directory }}/vitrage-collector/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" + vitrage-notifier: + container_name: vitrage_notifier + group: vitrage-notifier + enabled: true + image: "{{ vitrage_notifier_image_full }}" + volumes: + - "{{ node_config_directory }}/vitrage-notifier/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" + vitrage-graph: + container_name: vitrage_graph + group: vitrage-graph + enabled: true + image: "{{ vitrage_graph_image_full }}" + volumes: + - "{{ node_config_directory }}/vitrage-graph/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" + vitrage-ml: + container_name: vitrage_ml + group: vitrage-ml + enabled: true + image: "{{ vitrage_ml_image_full }}" + volumes: + - "{{ node_config_directory }}/vitrage-ml/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" + +#################### +## Database +##################### +vitrage_database_name: "vitrage" +vitrage_database_user: "vitrage" +vitrage_database_address: "{{ kolla_internal_fqdn }}:{{ database_port }}" + +#################### +# Docker +#################### + +vitrage_install_type: "{{ kolla_install_type }}" +vitrage_tag: "{{ openstack_release }}" + +vitrage_graph_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ vitrage_install_type }}-vitrage-graph" +vitrage_graph_tag: "{{ vitrage_tag }}" +vitrage_graph_image_full: "{{ vitrage_graph_image }}:{{ vitrage_graph_tag }}" + +vitrage_api_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ vitrage_install_type }}-vitrage-api" +vitrage_api_tag: "{{ vitrage_tag }}" +vitrage_api_image_full: "{{ vitrage_api_image }}:{{ vitrage_api_tag }}" + +vitrage_notifier_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ vitrage_install_type }}-vitrage-notifier" +vitrage_notifier_tag: "{{ vitrage_tag }}" +vitrage_notifier_image_full: "{{ vitrage_notifier_image }}:{{ vitrage_notifier_tag }}" + +vitrage_collector_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ vitrage_install_type }}-vitrage-collector" +vitrage_collector_tag: "{{ vitrage_tag }}" +vitrage_collector_image_full: "{{ vitrage_collector_image }}:{{ vitrage_collector_tag }}" + +vitrage_ml_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ vitrage_install_type }}-vitrage-ml" +vitrage_ml_tag: "{{ vitrage_tag }}" +vitrage_ml_image_full: "{{ vitrage_ml_image }}:{{ vitrage_ml_tag }}" + +#################### +# OpenStack +#################### +vitrage_admin_endpoint: "{{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ vitrage_api_port }}" +vitrage_internal_endpoint: "{{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ vitrage_api_port }}" +vitrage_public_endpoint: "{{ public_protocol }}://{{ kolla_external_fqdn }}:{{ vitrage_api_port }}" + +vitrage_logging_debug: "{{ openstack_logging_debug }}" + +vitrage_keystone_user: "vitrage" + +openstack_vitrage_auth: "{{ openstack_auth }}" + +##################### +# Datasources +##################### +vitrage_notifier: + - name: "aodh" + enabled: "{{ enable_aodh | bool }}" + - name: "mistral" + enabled: "{{ enable_mistral | bool }}" + - name: "nova" + enabled: "{{ enable_nova | bool }}" + +vitrage_notifiers: "{{ vitrage_notifier | selectattr('enabled', 'equalto', true) | list }}" + +vitrage_datasource: + - name: "static" + enabled: true + - name: "nova.host,nova.instance,nova.zone" + enabled: "{{ enable_nova | bool }}" + - name: "aodh" + enabled: "{{ enable_aodh | bool }}" + - name: "collectd" + enabled: "{{ enable_collectd | bool }}" + - name: "cinder.volume" + enabled: "{{ enable_cinder | bool }}" + - name: "neutron.network,neutron.port" + enabled: "{{ enable_neutron | bool }}" +#TODO(egonzalez) Heat cannot be used with default policy.json due stacks:global_index=rule:deny_everybody. +# Document process to deploy vitrage+heat. + - name: "heat.stack" + enabled: "no" + +vitrage_datasources: "{{ vitrage_datasource | selectattr('enabled', 'equalto', true) | list }}" diff --git a/ansible/roles/vitrage/handlers/main.yml b/ansible/roles/vitrage/handlers/main.yml new file mode 100644 index 0000000000..24b9c067bf --- /dev/null +++ b/ansible/roles/vitrage/handlers/main.yml @@ -0,0 +1,115 @@ +--- +- name: Restart vitrage-api container + vars: + service_name: "vitrage-api" + service: "{{ vitrage_services[service_name] }}" + config_json: "{{ vitrage_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_conf: "{{ vitrage_confs.results|selectattr('item.key', 'equalto', service_name)|first }}" + policy_json: "{{ vitrage_policy_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_api_container: "{{ check_vitrage_containers.results|selectattr('item.key', 'equalto', service_name)|first }}" + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes }}" + when: + - action != "config" + - inventory_hostname in groups[service.group] + - service.enabled | bool + - config_json.changed | bool + or vitrage_conf.changed | bool + or policy_json.changed | bool + or vitrage_api_container.changed | bool + +- name: Restart vitrage-collector container + vars: + service_name: "vitrage-collector" + service: "{{ vitrage_services[service_name] }}" + config_json: "{{ vitrage_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_conf: "{{ vitrage_confs.results|selectattr('item.key', 'equalto', service_name)|first }}" + policy_json: "{{ vitrage_policy_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_collector_container: "{{ check_vitrage_containers.results|selectattr('item.key', 'equalto', service_name)|first }}" + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes }}" + when: + - action != "config" + - inventory_hostname in groups[service.group] + - service.enabled | bool + - config_json.changed | bool + or vitrage_conf.changed | bool + or policy_json.changed | bool + or vitrage_collector_container.changed | bool + +- name: Restart vitrage-notifier container + vars: + service_name: "vitrage-notifier" + service: "{{ vitrage_services[service_name] }}" + config_json: "{{ vitrage_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_conf: "{{ vitrage_confs.results|selectattr('item.key', 'equalto', service_name)|first }}" + policy_json: "{{ vitrage_policy_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_notifier_container: "{{ check_vitrage_containers.results|selectattr('item.key', 'equalto', service_name)|first }}" + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes }}" + when: + - action != "config" + - inventory_hostname in groups[service.group] + - service.enabled | bool + - config_json.changed | bool + or vitrage_conf.changed | bool + or policy_json.changed | bool + or vitrage_notifier_container.changed | bool + +- name: Restart vitrage-graph container + vars: + service_name: "vitrage-graph" + service: "{{ vitrage_services[service_name] }}" + config_json: "{{ vitrage_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_conf: "{{ vitrage_confs.results|selectattr('item.key', 'equalto', service_name)|first }}" + policy_json: "{{ vitrage_policy_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_graph_container: "{{ check_vitrage_containers.results|selectattr('item.key', 'equalto', service_name)|first }}" + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes }}" + when: + - action != "config" + - inventory_hostname in groups[service.group] + - service.enabled | bool + - config_json.changed | bool + or vitrage_conf.changed | bool + or policy_json.changed | bool + or vitrage_graph_container.changed | bool + +- name: Restart vitrage-ml container + vars: + service_name: "vitrage-ml" + service: "{{ vitrage_services[service_name] }}" + config_json: "{{ vitrage_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_conf: "{{ vitrage_confs.results|selectattr('item.key', 'equalto', service_name)|first }}" + policy_json: "{{ vitrage_policy_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}" + vitrage_ml_container: "{{ check_vitrage_containers.results|selectattr('item.key', 'equalto', service_name)|first }}" + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes }}" + when: + - action != "config" + - inventory_hostname in groups[service.group] + - service.enabled | bool + - config_json.changed | bool + or vitrage_conf.changed | bool + or policy_json.changed | bool + or vitrage_ml_container.changed | bool diff --git a/ansible/roles/vitrage/meta/main.yml b/ansible/roles/vitrage/meta/main.yml new file mode 100644 index 0000000000..6b4fff8fef --- /dev/null +++ b/ansible/roles/vitrage/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: common } diff --git a/ansible/roles/vitrage/tasks/bootstrap.yml b/ansible/roles/vitrage/tasks/bootstrap.yml new file mode 100644 index 0000000000..cbe16a1ba3 --- /dev/null +++ b/ansible/roles/vitrage/tasks/bootstrap.yml @@ -0,0 +1,33 @@ +--- +- name: Creating vitrage database + kolla_toolbox: + module_name: mysql_db + module_args: + login_host: "{{ database_address }}" + login_port: "{{ database_port }}" + login_user: "{{ database_user }}" + login_password: "{{ database_password }}" + name: "{{ vitrage_database_name }}" + register: database + run_once: True + delegate_to: "{{ groups['vitrage-api'][0] }}" + +- name: Creating vitrage database user and setting permissions + kolla_toolbox: + module_name: mysql_user + module_args: + login_host: "{{ database_address }}" + login_port: "{{ database_port }}" + login_user: "{{ database_user }}" + login_password: "{{ database_password }}" + name: "{{ vitrage_database_user }}" + password: "{{ vitrage_database_password }}" + host: "%" + priv: "{{ vitrage_database_name }}.*:ALL" + append_privs: "yes" + run_once: True + delegate_to: "{{ groups['vitrage-api'][0] }}" + +- include: bootstrap_service.yml + when: database.changed + diff --git a/ansible/roles/vitrage/tasks/bootstrap_service.yml b/ansible/roles/vitrage/tasks/bootstrap_service.yml new file mode 100644 index 0000000000..ab64f2866f --- /dev/null +++ b/ansible/roles/vitrage/tasks/bootstrap_service.yml @@ -0,0 +1,19 @@ +--- +- name: Running Vitrage bootstrap container + vars: + vitrage_api: "{{ vitrage_services['vitrage-api'] }}" + kolla_docker: + action: "start_container" + common_options: "{{ docker_common_options }}" + detach: False + environment: + KOLLA_BOOTSTRAP: + KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}" + image: "{{ vitrage_api.image }}" + labels: + BOOTSTRAP: + name: "bootstrap_vitrage" + restart_policy: "never" + volumes: "{{ vitrage_api.volumes }}" + run_once: True + delegate_to: "{{ groups[vitrage_api.group][0] }}" diff --git a/ansible/roles/vitrage/tasks/config.yml b/ansible/roles/vitrage/tasks/config.yml new file mode 100644 index 0000000000..63cc3d4d9d --- /dev/null +++ b/ansible/roles/vitrage/tasks/config.yml @@ -0,0 +1,100 @@ +--- +- name: Ensuring config directories exist + file: + path: "{{ node_config_directory }}/{{ item.key }}" + state: "directory" + recurse: yes + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ vitrage_services }}" + +- name: Copying over config.json files for services + template: + src: "{{ item.key }}.json.j2" + dest: "{{ node_config_directory }}/{{ item.key }}/config.json" + register: vitrage_config_jsons + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ vitrage_services }}" + notify: + - Restart vitrage-api container + - Restart vitrage-collector container + - Restart vitrage-notifier container + - Restart vitrage-graph container + - Restart vitrage-ml container + +- name: Copying over vitrage.conf + vars: + service_name: "{{ item.key }}" + merge_configs: + sources: + - "{{ role_path }}/templates/vitrage.conf.j2" + - "{{ node_config_directory }}/config/global.conf" + - "{{ node_config_directory }}/config/messaging.conf" + - "{{ node_config_directory }}/config/vitrage.conf" + - "{{ node_config_directory }}/config/vitrage/{{ item.key }}.conf" + - "{{ node_config_directory }}/config/vitrage/{{ inventory_hostname }}/vitrage.conf" + dest: "{{ node_config_directory }}/{{ item.key }}/vitrage.conf" + register: vitrage_confs + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ vitrage_services }}" + notify: + - Restart vitrage-api container + - Restart vitrage-collector container + - Restart vitrage-notifier container + - Restart vitrage-graph container + - Restart vitrage-ml container + +- name: Copying over wsgi-vitrage files for services + template: + src: "wsgi-vitrage.conf.j2" + dest: "{{ node_config_directory }}/{{ item }}/wsgi-vitrage.conf" + with_items: + - "vitrage-api" + notify: + - Restart vitrage-api container + +- name: Check if policies shall be overwritten + local_action: stat path="{{ node_custom_config }}/vitrage/policy.json" + register: vitrage_policy + +- name: Copying over existing policy.json + template: + src: "{{ node_custom_config }}/vitrage/policy.json" + dest: "{{ node_config_directory }}/{{ item.key }}/policy.json" + register: vitrage_policy_jsons + when: + - vitrage_policy.stat.exists + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ vitrage_services }}" + notify: + - Restart vitrage-api container + - Restart vitrage-collector container + - Restart vitrage-graph container + - Restart vitrage-notifier container + - Restart vitrage-ml container + +- name: Check vitrage containers + kolla_docker: + action: "compare_container" + common_options: "{{ docker_common_options }}" + name: "{{ item.value.container_name }}" + image: "{{ item.value.image }}" + volumes: "{{ item.value.volumes }}" + register: check_vitrage_containers + when: + - action != "config" + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ vitrage_services }}" + notify: + - Restart vitrage-api container + - Restart vitrage-collector container + - Restart vitrage-graph container + - Restart vitrage-notifier container + - Restart vitrage-ml container diff --git a/ansible/roles/vitrage/tasks/deploy.yml b/ansible/roles/vitrage/tasks/deploy.yml new file mode 100644 index 0000000000..ebb653b500 --- /dev/null +++ b/ansible/roles/vitrage/tasks/deploy.yml @@ -0,0 +1,16 @@ +--- +- include: register.yml + when: inventory_hostname in groups['vitrage-api'] + +- include: config.yml + when: inventory_hostname in groups['vitrage-api'] or + inventory_hostname in groups['vitrage-ml'] or + inventory_hostname in groups['vitrage-graph'] or + inventory_hostname in groups['vitrage-notifier'] or + inventory_hostname in groups['vitrage-collector'] + +- include: bootstrap.yml + when: inventory_hostname in groups['vitrage-api'] + +- name: Flush handlers + meta: flush_handlers diff --git a/ansible/roles/vitrage/tasks/main.yml b/ansible/roles/vitrage/tasks/main.yml new file mode 100644 index 0000000000..b017e8b4ad --- /dev/null +++ b/ansible/roles/vitrage/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- include: "{{ action }}.yml" diff --git a/ansible/roles/vitrage/tasks/precheck.yml b/ansible/roles/vitrage/tasks/precheck.yml new file mode 100644 index 0000000000..e91ab4d8d8 --- /dev/null +++ b/ansible/roles/vitrage/tasks/precheck.yml @@ -0,0 +1,16 @@ +--- +- name: Get container facts + kolla_container_facts: + name: + - vitrage_api + register: container_facts + +- name: Checking free port for vitrage API + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ vitrage_api_port }}" + connect_timeout: 1 + state: stopped + when: + - container_facts['vitrage_api'] is not defined + - inventory_hostname in groups['vitrage-api'] diff --git a/ansible/roles/vitrage/tasks/pull.yml b/ansible/roles/vitrage/tasks/pull.yml new file mode 100644 index 0000000000..efe5b97f9c --- /dev/null +++ b/ansible/roles/vitrage/tasks/pull.yml @@ -0,0 +1,10 @@ +--- +- name: Pulling vitrage images + kolla_docker: + action: "pull_image" + common_options: "{{ docker_common_options }}" + image: "{{ item.value.image }}" + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ vitrage_services }}" diff --git a/ansible/roles/vitrage/tasks/reconfigure.yml b/ansible/roles/vitrage/tasks/reconfigure.yml new file mode 100644 index 0000000000..e078ef1318 --- /dev/null +++ b/ansible/roles/vitrage/tasks/reconfigure.yml @@ -0,0 +1,2 @@ +--- +- include: deploy.yml diff --git a/ansible/roles/vitrage/tasks/register.yml b/ansible/roles/vitrage/tasks/register.yml new file mode 100644 index 0000000000..a805075819 --- /dev/null +++ b/ansible/roles/vitrage/tasks/register.yml @@ -0,0 +1,42 @@ +--- +- name: Creating the Vitrage service and endpoint + kolla_toolbox: + module_name: "kolla_keystone_service" + module_args: + service_name: "vitrage" + service_type: "rca" + description: "Root Cause Analysis Service" + endpoint_region: "{{ openstack_region_name }}" + url: "{{ item.url }}" + interface: "{{ item.interface }}" + region_name: "{{ openstack_region_name }}" + auth: "{{ '{{ openstack_vitrage_auth }}' }}" + module_extra_vars: + openstack_vitrage_auth: "{{ openstack_vitrage_auth }}" + register: vitrage_endpoint + until: vitrage_endpoint|success + retries: 10 + delay: 5 + run_once: True + with_items: + - {'interface': 'admin', 'url': '{{ vitrage_admin_endpoint }}'} + - {'interface': 'internal', 'url': '{{ vitrage_internal_endpoint }}'} + - {'interface': 'public', 'url': '{{ vitrage_public_endpoint }}'} + +- name: Creating the Vitrage project, user, and role + kolla_toolbox: + module_name: "kolla_keystone_user" + module_args: + project: "service" + user: "{{ vitrage_keystone_user }}" + password: "{{ vitrage_keystone_password }}" + role: "admin" + region_name: "{{ openstack_region_name }}" + auth: "{{ '{{ openstack_vitrage_auth }}' }}" + module_extra_vars: + openstack_vitrage_auth: "{{ openstack_vitrage_auth }}" + register: vitrage_user + until: vitrage_user|success + retries: 10 + delay: 5 + run_once: True diff --git a/ansible/roles/vitrage/tasks/upgrade.yml b/ansible/roles/vitrage/tasks/upgrade.yml new file mode 100644 index 0000000000..c38db1adf4 --- /dev/null +++ b/ansible/roles/vitrage/tasks/upgrade.yml @@ -0,0 +1,7 @@ +--- +- include: config.yml + +- include: bootstrap_service.yml + +- name: Flush handlers + meta: flush_handlers diff --git a/ansible/roles/vitrage/templates/vitrage-api.json.j2 b/ansible/roles/vitrage/templates/vitrage-api.json.j2 new file mode 100644 index 0000000000..7f670f5078 --- /dev/null +++ b/ansible/roles/vitrage/templates/vitrage-api.json.j2 @@ -0,0 +1,34 @@ +{% set apache_cmd = 'apache2' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd' %} +{% set apache_dir = 'apache2/conf-enabled' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd/conf.d' %} +{% set apache_file = '000-default.conf' if kolla_base_distro in ['ubuntu', 'debian'] else 'vitrage-api.conf' %} +{ + "command": "/usr/sbin/{{ apache_cmd }} -DFOREGROUND", + "config_files": [ + { + "source": "{{ container_config_directory }}/vitrage.conf", + "dest": "/etc/vitrage/vitrage.conf", + "owner": "vitrage", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/wsgi-vitrage.conf", + "dest": "/etc/{{ apache_dir }}/{{ apache_file }}", + "owner": "vitrage", + "perm": "0644" + }, + { + "source": "{{ container_config_directory }}/policy.json", + "dest": "/etc/vitrage/policy.json", + "owner": "vitrage", + "perm": "0600", + "optional": true + } + ], + "permissions": [ + { + "path": "/var/log/kolla/vitrage", + "owner": "vitrage:vitrage", + "recurse": true + } + ] +} diff --git a/ansible/roles/vitrage/templates/vitrage-collector.json.j2 b/ansible/roles/vitrage/templates/vitrage-collector.json.j2 new file mode 100644 index 0000000000..1a6c262ea9 --- /dev/null +++ b/ansible/roles/vitrage/templates/vitrage-collector.json.j2 @@ -0,0 +1,25 @@ +{ + "command": "vitrage-collector --config-file /etc/vitrage/vitrage.conf", + "config_files": [ + { + "source": "{{ container_config_directory }}/vitrage.conf", + "dest": "/etc/vitrage/vitrage.conf", + "owner": "vitrage", + "perm": "0644" + }, + { + "source": "{{ container_config_directory }}/policy.json", + "dest": "/etc/vitrage/policy.json", + "owner": "vitrage", + "perm": "0600", + "optional": true + } + ], + "permissions": [ + { + "path": "/var/log/kolla/vitrage", + "owner": "vitrage:vitrage", + "recurse": true + } + ] +} diff --git a/ansible/roles/vitrage/templates/vitrage-graph.json.j2 b/ansible/roles/vitrage/templates/vitrage-graph.json.j2 new file mode 100644 index 0000000000..ebbbb201b4 --- /dev/null +++ b/ansible/roles/vitrage/templates/vitrage-graph.json.j2 @@ -0,0 +1,25 @@ +{ + "command": "vitrage-graph --config-file /etc/vitrage/vitrage.conf", + "config_files": [ + { + "source": "{{ container_config_directory }}/vitrage.conf", + "dest": "/etc/vitrage/vitrage.conf", + "owner": "vitrage", + "perm": "0644" + }, + { + "source": "{{ container_config_directory }}/policy.json", + "dest": "/etc/vitrage/policy.json", + "owner": "vitrage", + "perm": "0600", + "optional": true + } + ], + "permissions": [ + { + "path": "/var/log/kolla/vitrage", + "owner": "vitrage:vitrage", + "recurse": true + } + ] +} diff --git a/ansible/roles/vitrage/templates/vitrage-ml.json.j2 b/ansible/roles/vitrage/templates/vitrage-ml.json.j2 new file mode 100644 index 0000000000..dd8847af42 --- /dev/null +++ b/ansible/roles/vitrage/templates/vitrage-ml.json.j2 @@ -0,0 +1,25 @@ +{ + "command": "vitrage-ml --config-file /etc/vitrage/vitrage.conf", + "config_files": [ + { + "source": "{{ container_config_directory }}/vitrage.conf", + "dest": "/etc/vitrage/vitrage.conf", + "owner": "vitrage", + "perm": "0644" + }, + { + "source": "{{ container_config_directory }}/policy.json", + "dest": "/etc/vitrage/policy.json", + "owner": "vitrage", + "perm": "0600", + "optional": true + } + ], + "permissions": [ + { + "path": "/var/log/kolla/vitrage", + "owner": "vitrage:vitrage", + "recurse": true + } + ] +} diff --git a/ansible/roles/vitrage/templates/vitrage-notifier.json.j2 b/ansible/roles/vitrage/templates/vitrage-notifier.json.j2 new file mode 100644 index 0000000000..4ebcbcc644 --- /dev/null +++ b/ansible/roles/vitrage/templates/vitrage-notifier.json.j2 @@ -0,0 +1,25 @@ +{ + "command": "vitrage-notifier --config-file /etc/vitrage/vitrage.conf", + "config_files": [ + { + "source": "{{ container_config_directory }}/vitrage.conf", + "dest": "/etc/vitrage/vitrage.conf", + "owner": "vitrage", + "perm": "0644" + }, + { + "source": "{{ container_config_directory }}/policy.json", + "dest": "/etc/vitrage/policy.json", + "owner": "vitrage", + "perm": "0600", + "optional": true + } + ], + "permissions": [ + { + "path": "/var/log/kolla/vitrage", + "owner": "vitrage:vitrage", + "recurse": true + } + ] +} diff --git a/ansible/roles/vitrage/templates/vitrage.conf.j2 b/ansible/roles/vitrage/templates/vitrage.conf.j2 new file mode 100644 index 0000000000..52dad4eab5 --- /dev/null +++ b/ansible/roles/vitrage/templates/vitrage.conf.j2 @@ -0,0 +1,72 @@ +[DEFAULT] +debug = {{ vitrage_logging_debug }} +log_dir = /var/log/kolla/vitrage + +{% if service_name == 'vitrage-api' %} +# Force vitrage-api.log or will use app.wsgi +log_file = /var/log/kolla/vitrage/vitrage-api.log +{% endif %} + +{% if vitrage_notifiers %} +notifiers = {{ vitrage_notifiers|map(attribute='name')|join(',') }} +{% endif %} + +transport_url = rabbit://{% for host in groups['rabbitmq'] %}{{ rabbitmq_user }}:{{ rabbitmq_password }}@{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ rabbitmq_port }}{% if not loop.last %},{% endif %}{% endfor %} + +[api] +host = {{ api_interface_address }} +port = {{ vitrage_api_port }} +workers = {{ openstack_service_workers }} + +[keystone_authtoken] +auth_uri = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_public_port }} +auth_url = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }} +auth_type = password +project_domain_id = default +user_domain_id = default +project_name = service +username = {{ vitrage_keystone_user }} +password = {{ vitrage_keystone_password }} + +memcache_security_strategy = ENCRYPT +memcache_secret_key = {{ memcache_secret_key }} +memcached_servers = {% for host in groups['memcached'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ memcached_port }}{% if not loop.last %},{% endif %}{% endfor %} + +[database] +connection = mysql+pymysql://{{ vitrage_database_user }}:{{ vitrage_database_password }}@{{ vitrage_database_address }}/{{ vitrage_database_name }} + +{% if vitrage_datasources %} +[datasources] +types = {{ vitrage_datasources|map(attribute='name')|join(',') }} +{% endif %} + +[machine_learning] +plugins = jaccard_correlation + +[service_credentials] +auth_url = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }} +region_name = {{ openstack_region_name }} +auth_type = password +project_domain_id = default +user_domain_id = default +project_name = service +password = {{ vitrage_keystone_password }} +username = {{ vitrage_keystone_user }} +interface = internal + +[oslo_messaging_notifications] +topics = notifications,vitrage_notifications +driver = messagingv2 + +[oslo_concurrency] +lock_path = /var/lib/vitrage/tmp + +{% if enable_osprofiler | bool %} +[profiler] +enabled = true +trace_sqlalchemy = true +hmac_keys = {{ osprofiler_secret }} +{% if enable_elasticsearch | bool %} +connection_string = elasticsearch://{{ elasticsearch_address }}:{{ elasticsearch_port }} +{% endif %} +{% endif %} diff --git a/ansible/roles/vitrage/templates/wsgi-vitrage.conf.j2 b/ansible/roles/vitrage/templates/wsgi-vitrage.conf.j2 new file mode 100644 index 0000000000..280ce5fdb2 --- /dev/null +++ b/ansible/roles/vitrage/templates/wsgi-vitrage.conf.j2 @@ -0,0 +1,25 @@ +{% set python_path = '/usr/lib/python2.7/site-packages' if kolla_install_type == 'binary' else '/var/lib/kolla/venv/lib/python2.7/site-packages' %} +Listen {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}:{{ vitrage_api_port }} + + + + ## Vhost docroot + DocumentRoot "/var/www/cgi-bin/vitrage" + + ## Directories, there should at least be a declaration for /var/www/cgi-bin/vitrage + + + Options Indexes FollowSymLinks MultiViews + AllowOverride None + Require all granted + + + ## Logging + ErrorLog "/var/log/kolla/vitrage/vitrage_wsgi_error.log" + ServerSignature Off + CustomLog "/var/log/kolla/vitrage/vitrage_wsgi_access.log" combined + WSGIApplicationGroup %{GLOBAL} + WSGIDaemonProcess vitrage group=vitrage processes={{ openstack_service_workers }} threads=1 user=vitrage python-path={{ python_path }} + WSGIProcessGroup vitrage + WSGIScriptAlias / "/var/www/cgi-bin/vitrage/app.wsgi" + diff --git a/ansible/site.yml b/ansible/site.yml index 47a365d27c..b0ebba24f8 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -716,3 +716,17 @@ - { role: skydive, tags: skydive, when: enable_skydive | bool } + +- name: Apply role vitrage + gather_facts: false + hosts: + - vitrage-api + - vitrage-graph + - vitrage-notifier + - vitrage-collector + - vitrage-ml + serial: '{{ serial|default("0") }}' + roles: + - { role: vitrage, + tags: vitrage, + when: enable_vitrage | bool } diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml index 570c66aee2..92aa3c847d 100644 --- a/etc/kolla/globals.yml +++ b/etc/kolla/globals.yml @@ -224,6 +224,7 @@ kolla_internal_vip_address: "10.10.10.254" #enable_tacker: "no" #enable_tempest: "no" #enable_trove: "no" +#enable_vitrage: "no" #enable_vmtp: "no" #enable_watcher: "no" #enable_zun: "no" diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml index 1b659da29d..500520e6eb 100644 --- a/etc/kolla/passwords.yml +++ b/etc/kolla/passwords.yml @@ -160,6 +160,9 @@ tacker_keystone_password: zun_database_password: zun_keystone_password: +vitrage_database_password: +vitrage_keystone_password: + memcache_secret_key: #HMAC secret key diff --git a/releasenotes/notes/add-vitrage-6b8da2c81a68b01b.yaml b/releasenotes/notes/add-vitrage-6b8da2c81a68b01b.yaml new file mode 100644 index 0000000000..d7bab65cc8 --- /dev/null +++ b/releasenotes/notes/add-vitrage-6b8da2c81a68b01b.yaml @@ -0,0 +1,3 @@ +--- +features: + - Add vitrage ansible role