# Openstack has a newer version of rabbitmq
- name: Install RHOSP13 repo file
  copy: src="{{ files }}/common/rhos13.repo" dest=/etc/yum.repos.d/rhos13.repo
  tags:
  - rabbitmq_cluster
  - config
  - packages
  - yumrepos
  when: ansible_distribution_major_version|int == 7

- name: Install RHOSP16 repo file
  copy: src="{{ files }}/common/rhos16.repo" dest=/etc/yum.repos.d/rhos16.repo
  tags:
  - rabbitmq_cluster
  - config
  - packages
  - yumrepos
  when: ansible_distribution_major_version|int == 8

- name: install needed packages
  package:
    state: present
    name:
    - rabbitmq-server
    - nagios-plugins-rabbitmq
  tags:
  - rabbitmq_cluster
  - packages

- name: deploy CA certificate
  copy: src="{{private}}/files/rabbitmq/{{env}}/pki/ca.crt"
        dest=/etc/rabbitmq/ca.crt
        owner=root group=root mode=0644
  tags:
  - rabbitmq_cluster
  - config

- name: create node cert directory
  file: path=/etc/rabbitmq/nodecert/ owner=root group=root mode=0755 state=directory
  tags:
  - rabbitmq_cluster
  - config

- name: deploy node certificate
  copy: src="{{private}}/files/rabbitmq/{{env}}/pki/issued/{{inventory_hostname}}.crt"
        dest=/etc/rabbitmq/nodecert/node.crt
        owner=root group=root mode=0644
  tags:
  - rabbitmq_cluster
  - config

- name: deploy node private key
  copy: src="{{private}}/files/rabbitmq/{{env}}/pki/private/{{inventory_hostname}}.key"
        dest=/etc/rabbitmq/nodecert/node.key
        owner=rabbitmq group=rabbitmq mode=0600
  tags:
  - rabbitmq_cluster
  - config

- name: build combined node key
  assemble: src=/etc/rabbitmq/nodecert/ dest=/etc/rabbitmq/nodecert.combined.pem
            owner=rabbitmq group=rabbitmq mode=0600
  tags:
  - rabbitmq_cluster
  - config

- name: deploy configuration
  template: src={{item}} dest=/etc/rabbitmq/{{item}} owner=root group=root mode=0644
  with_items:
  - rabbitmq.config
  - rabbitmq-env.conf
  notify:
    - restart rabbitmq
  tags:
  - rabbitmq_cluster
  - config

- name: deploy staging cookie
  copy: content="{{rabbitmq_cluster_cookie_staging}}" dest=/var/lib/rabbitmq/.erlang.cookie
        owner=rabbitmq group=rabbitmq mode=0400
  when: "env == 'staging'"
  notify:
    - restart rabbitmq
  tags:
  - rabbitmq_cluster
  - config

- name: deploy production cookie
  copy: content="{{rabbitmq_cluster_cookie_production}}" dest=/var/lib/rabbitmq/.erlang.cookie
        owner=rabbitmq group=rabbitmq mode=0400
  when: "env == 'production'"
  notify:
    - restart rabbitmq
  tags:
  - rabbitmq_cluster
  - config

- name: Create RabbitMQ systemd override directory
  file:
    path: /etc/systemd/system/rabbitmq-server.service.d/
    state: directory
  tags:
  - rabbitmq_cluster
  - config

- name: Override file limit on rabbitmq
  copy:
    content: "[Service]\nLimitNOFILE={{rabbitmq_cluster_file_limit}}\n"
    dest: /etc/systemd/system/rabbitmq-server.service.d/override.conf
  notify:
    - restart rabbitmq
  tags:
  - rabbitmq_cluster
  - config

- name: Enable the HTTP management console and SSL authentication plugins
  rabbitmq_plugin:
    names: "rabbitmq_management,\
            rabbitmq_auth_mechanism_ssl,\
            rabbitmq_federation,\
            rabbitmq_federation_management"
  tags:
  - rabbitmq_cluster
  - config

- name: start rabbitmq
  service: name=rabbitmq-server state=started enabled=yes
  tags:
  - rabbitmq_cluster

- name: Nope. No standard users. Even if we use TLS auth
  rabbitmq_user: user=guest state=absent
  tags:
  - rabbitmq_cluster
  - config


- name: Configure the pubsub virtual host
  rabbitmq_vhost:
    name: /pubsub
    state: present
  tags:
  - rabbitmq_cluster
  - config

# This is the publicly accessible virtual host
- name: Configure the publicly accessible vhost
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_vhost:
    name: /public_pubsub
    state: present
  tags:
  - rabbitmq_cluster
  - config

- name: Configure the HA policy for queues on the pubsub virtual
  rabbitmq_policy:
    name: HA
    apply_to: queues
    pattern: .*
    tags:
      ha-mode: all
      ha-sync-mode: automatic  # Auto sync queues to new cluster members
      ha-sync-batch-size: 10000  # Larger is faster, but must finish in 1 net_ticktime
    vhost: /pubsub
  tags:
  - rabbitmq_cluster
  - config

- name: Add a policy to limit queues to 1GB and remove after a month of no use for /pubsub
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_policy:
    apply_to: queues
    name: pubsub_sweeper
    state: present
    pattern: ".*"
    tags:
      # Unused queues are killed after 1000 * 60 * 60 * 31 milliseconds (~a month)
      expires: 111600000
      # Queues can use at most 1GB of storage
      max-length-bytes: 1073741824
    vhost: /pubsub
  tags:
  - rabbitmq_cluster
  - config

- name: Add a policy to remove after a week of no use for /bodhi
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_policy:
    apply_to: queues
    name: bodhi_sweeper
    state: present
    pattern: ".*"
    tags:
      # Unused queues are killed after 1000 * 60 * 60 * 7 milliseconds (~a week)
      expires: 25200000
    vhost: /bodhi
  tags:
  - rabbitmq_cluster
  - config

- name: Create the admin user for the {{ item }} vhost
  rabbitmq_user:
    user: admin
    password: "{{ (env == 'production')|ternary(rabbitmq_admin_password_production, rabbitmq_admin_password_staging) }}"
    vhost: "{{ item }}"
    configure_priv: .*
    read_priv: .*
    write_priv: .*
    tags: administrator
  with_items:
  - /
  - /pubsub
  - /public_pubsub
  when: inventory_hostname.startswith('rabbitmq01')
  tags:
  - rabbitmq_cluster
  - config

- name: Dump the admin password in a file for administrative operations
  copy:
    dest: /root/.rabbitmqpass
    content: "{{ (env == 'production')|ternary(rabbitmq_admin_password_production, rabbitmq_admin_password_staging) }}"
    mode: 0600
    owner: root
    group: root
  tags:
  - rabbitmq_cluster
  - config

# Users with the "monitoring" tag have read-only access vhosts, connections,
# channels, node-level resource usage, and cluster stats.
- name: Create the Nagios monitoring user in staging
  rabbitmq_user:
    user: nagios-monitoring
    password: "{{ rabbitmq_monitoring_password_staging }}"
    update_password: always
    permissions:
      - vhost: /
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /pubsub
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /public_pubsub
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /mbs-private-queue
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /centos-odcs
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
    tags: monitoring
  when: env == "staging" and inventory_hostname.startswith('rabbitmq01')
  tags:
  - rabbitmq_cluster
  - config

- name: Create the Nagios monitoring user in production
  rabbitmq_user:
    user: nagios-monitoring
    password: "{{ rabbitmq_monitoring_password_production }}"
    update_password: always
    permissions:
      - vhost: /
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /pubsub
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /public_pubsub
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /mbs-private-queue
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
      - vhost: /centos-odcs
        configure_priv: "^$"
        read_priv: "^$"
        write_priv: "^$"
    tags: monitoring
  when: env == "production" and inventory_hostname.startswith('rabbitmq01')
  tags:
  - rabbitmq_cluster
  - config

- name: Create the zmq.topic exchange in the {{ item }} vhost
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_exchange:
    name: "zmq.topic"
    exchange_type: "topic"
    vhost: "/pubsub"
    login_user: admin
    login_password: "{{ (env == 'production')|ternary(rabbitmq_admin_password_production, rabbitmq_admin_password_staging) }}"
  tags:
  - rabbitmq_cluster
  - config

- name: Create the zmq.topic exchange in the {{ item }} vhost
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_exchange:
    name: "zmq.topic"
    exchange_type: "topic"
    vhost: "/public_pubsub"
    login_user: admin
    login_password: "{{ (env == 'production')|ternary(rabbitmq_admin_password_production, rabbitmq_admin_password_staging) }}"
  tags:
  - rabbitmq_cluster
  - config

# We keep them separated in /pubsub so we can bridge messages back to zmq
- name: Forward all zmq.topic to amq.topic in the public_pubsub vhost
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_binding:
    destination_type: exchange
    name: zmq.topic
    dest: amq.topic
    routing_key: "#"
    vhost: "/public_pubsub"
    login_user: admin
    login_password: "{{ (env == 'production')|ternary(rabbitmq_admin_password_production, rabbitmq_admin_password_staging) }}"
  tags:
  - rabbitmq_cluster
  - config

- name: Configure a policy to ensure the public vhost stays swept up and tidy
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_policy:
    apply_to: queues
    name: sweeper
    state: present
    pattern: ".*"
    tags:
      # Unused queues are killed after 1000 * 60 * 60 (1 hour in milliseconds)
      expires: 3600000
      # Queues can use at most 1024 * 1024 * 50 (50MB) to store messages
      max-length-bytes: 52428800
    vhost: /public_pubsub
  tags:
  - rabbitmq_cluster
  - config

# Create a user with:
#   * permission to configure and write to any uuidish-named objects
#   * permission to read anything since users need to read exchanges for bindings
#     read queues for consuming
- name: Create a user for public access
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_user:
    user: "fedora{{ env_suffix }}"
    permissions:
      - vhost: /public_pubsub
        # Matches, for example, de23804a-304a-4228-b239-35099c98bd1e
        # Regex is Erlang flavored: http://erlang.org/doc/man/re.html
        configure_priv: "^((\\w{8}(-\\w{4}){3}-\\w{12})|amq\\..*)$"
        write_priv: "^((\\w{8}(-\\w{4}){3}-\\w{12})|amq\\..*)$"
        read_priv: .*
    state: present
  tags:
  - rabbitmq_cluster
  - config

# User with permissions to shovel messages out of pubsub into the public vhost.
# This user needs permissions to create a new exchange, bind an exchange to an
# exchange, create a queue, and bind a queue to an exchange.
- name: Create a user for federation
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.{{ item }}.fedoraproject.org"
  with_items: "{{ datacenter }}"
  rabbitmq_user:
    user: pubsub_federation
    permissions:
      - vhost: /pubsub
        configure_priv: "^federation.*"
        write_priv: "^federation.*"
        read_priv: .*
    state: present
  tags:
  - rabbitmq_cluster
  - config

- name: create pubsub_federation cert directory
  file: path=/etc/rabbitmq/pubsub_federation/ owner=root group=root mode=0755 state=directory
  tags:
  - rabbitmq_cluster
  - config

- name: deploy pubsub_federation certificate
  copy: src="{{private}}/files/rabbitmq/{{env}}/pki/issued/pubsub_federation.crt"
        dest=/etc/rabbitmq/pubsub_federation/client_cert.pem
        owner=root group=root mode=0644
  tags:
  - rabbitmq_cluster
  - config

- name: deploy node private key
  copy: src="{{private}}/files/rabbitmq/{{env}}/pki/private/pubsub_federation.key"
        dest=/etc/rabbitmq/pubsub_federation/client_key.pem
        owner=rabbitmq group=rabbitmq mode=0600
  tags:
  - rabbitmq_cluster
  - config

# This is the connection from our public vhost to the private pubsub vhost.
# Note that at present they live on the same cluster, but they don't need to.
#
# Note that the reason there are two tasks here is that if you use a variable in
# the "value" json string, it causes Ansible to produce invalid JSON which will
# choke up rabbitmq_parameters.
- name: Configure federation upstream from pubsub to the public_pubsub vhost
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.iad2.fedoraproject.org"
  when: "env == 'staging'"
  rabbitmq_parameter:
    component: "federation-upstream"
    name: "pubsub-to-public_pubsub"
    value: '{"uri": "amqps://pubsub_federation:@rabbitmq01.stg.iad2.fedoraproject.org/%2Fpubsub?cacertfile=%2Fetc%2Frabbitmq%2Fca.crt&certfile=%2Fetc%2Frabbitmq%2Fpubsub_federation%2Fclient_cert.pem&keyfile=%2Fetc%2Frabbitmq%2Fpubsub_federation%2Fclient_key.pem&verify=verify_peer&fail_if_no_peer_cert=true&server_name_indication=rabbitmq.stg.fedoraproject.org&auth_mechanism=external", "ack-mode": "on-confirm"}'
    state: present
    vhost: /public_pubsub

- name: Configure federation upstream from pubsub to the public_pubsub vhost (iad2)
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.iad2.fedoraproject.org"
  when: "env == 'production' and datacenter == 'iad2'"
  rabbitmq_parameter:
    component: "federation-upstream"
    name: "pubsub-to-public_pubsub"
    value: '{"uri": "amqps://pubsub_federation:@rabbitmq01.iad2.fedoraproject.org/%2Fpubsub?cacertfile=%2Fetc%2Frabbitmq%2Fca.crt&certfile=%2Fetc%2Frabbitmq%2Fpubsub_federation%2Fclient_cert.pem&keyfile=%2Fetc%2Frabbitmq%2Fpubsub_federation%2Fclient_key.pem&verify=verify_peer&fail_if_no_peer_cert=true&server_name_indication=rabbitmq.fedoraproject.org&auth_mechanism=external", "ack-mode": "on-confirm"}'
    state: present
    vhost: /public_pubsub

- name: Configure a policy to federate the pubsub topic exchange to public_pubsub
  run_once: true
  delegate_to: "rabbitmq01{{ env_suffix }}.iad2.fedoraproject.org"
  rabbitmq_policy:
    apply_to: exchanges
    name: pubsub-to-public_pubsub
    state: present
    pattern: "^(amq|zmq)\\.topic$"
    tags:
      federation-upstream: "pubsub-to-public_pubsub"
    vhost: /public_pubsub

# SELinux: allow the Nagios NRPE plugin to access the management interface
- name: install the selinux module compilation script
  copy:
    src: selinux-load.sh
    dest: /etc/nagios/selinux-load.sh
    mode: 0755

- name: copy over our custom selinux module
  copy:
    src: nrpe_rabbitmq.te
    dest: /etc/nagios/nrpe_rabbitmq.te
  register: selinux_module

- name: compile and install our custom selinux module
  command: /etc/nagios/selinux-load.sh
  when: selinux_module is changed

# Individual applications accounts & queues
- import_tasks: apps.yml
  tags:
  - rabbitmq_cluster
  - config

# VirtualHost /centos-odcs
- import_tasks: vhost-centos-odcs.yml
  tags:
  - rabbitmq_cluster
  - config

# VirtualHost /mbs-private-queue
- import_tasks: vhost-mbs-private-queue.yml
  tags:
  - rabbitmq_cluster
  - config
