# a messaging node (for notifications)
#
class oci::messaging(
  $openstack_release         = undef,
  $cluster_name              = undef,
  $machine_hostname          = undef,
  $machine_ip                = undef,

  $all_masters               = undef,
  $all_masters_ip            = undef,
  $first_master              = undef,
  $first_master_ip           = undef,

  $vip_hostname              = undef,
  $vip_ipaddr                = undef,
  $vip_netmask               = undef,

  $sql_vip_ip                = undef,
  $sql_vip_netmask           = undef,
  $sql_vip_iface             = undef,

  $is_first_rabbit           = false,
  $first_rabbit              = undef,
  $all_rabbits               = [],
  $all_rabbits_ips           = [],

  $initial_cluster_setup     = false,

  $has_subrole_heat          = true,
  $has_subrole_glance        = false,
  $has_subrole_nova          = false,
  $has_subrole_neutron       = false,
  $has_subrole_swift         = true,
  $has_subrole_horizon       = true,
  $has_subrole_barbican      = true,
  $has_subrole_cinder        = false,
  $has_subrole_gnocchi       = false,
  $has_subrole_ceilometer    = false,
  $has_subrole_panko         = false,
  $has_subrole_cloudkitty    = false,
  $has_subrole_aodh          = false,
  $has_subrole_octavia       = false,
  $has_subrole_magnum        = false,
  $has_subrole_designate     = false,

  $use_ssl                   = true,
  $rabbit_env                = {},
  $pass_rabbitmq_cookie      = undef,
  $pass_rabbitmq_monitoring  = undef,
  $pass_keystone_messaging   = undef,
  $pass_nova_messaging       = undef,
  $pass_glance_messaging     = undef,
  $pass_cinder_messaging     = undef,
  $pass_neutron_messaging    = undef,
  $pass_heat_messaging       = undef,
  $pass_barbican_messaging   = undef,
  $pass_gnocchi_messaging    = undef,
  $pass_panko_messaging      = undef,
  $pass_ceilometer_messaging = undef,
  $pass_cloudkitty_messaging = undef,
  $pass_aodh_messaging       = undef,
  $pass_octavia_messaging    = undef,
  $pass_magnum_messaging     = undef,
  $pass_designate_messaging  = undef,

  $pass_gnocchi_db           = undef,
  $pass_gnocchi_authtoken    = undef,

  $ceph_fsid                 = undef,
  $ceph_bootstrap_osd_key    = undef,
  $ceph_admin_key            = undef,
  $ceph_openstack_key        = undef,
  $ceph_mon_key              = undef,
  $ceph_mon_initial_members  = undef,
  $ceph_mon_host             = undef,
){
  # Generic performances tweak (will default to throughput-performance)
  # class { '::oci::tuned': }

  $proto = 'https'
  $messaging_default_port = '5671'
  $messaging_notify_port = '5671'
  $api_port = 443
  $base_url = "${proto}://${vip_hostname}"

  $keystone_auth_uri  = "${base_url}:${api_port}/identity"
  $keystone_admin_uri = "${base_url}:${api_port}/identity"
  $memcached_string = join([join($all_masters_ip,':11211,'), ':11211'],'')
  $memcached_servers  = ["${memcached_string}"]

  if $self_signed_api_cert {
    $api_endpoint_ca_file = "/etc/ssl/certs/oci-pki-oci-ca-chain.pem"
  }else{
    $api_endpoint_ca_file = ''
  }
  $oci_pki_root_ca_file = '/etc/ssl/certs/oci-pki-oci-ca-chain.pem'

  class { '::oci::puppet_oci_ca_cert':
    self_signed_api_cert => $self_signed_api_cert,
  }

  if $has_subrole_db {
    $sql_host = $vip_ipaddr
  }else{
    $sql_host = $sql_vip_ip
  }

  ##################
  ### Setup Ceph ###
  ##################
  class { 'ceph':
    fsid                => $ceph_fsid,
    ensure              => 'present',
    authentication_type => 'cephx',
    mon_initial_members => $ceph_mon_initial_members,
    mon_host            => $ceph_mon_host,
  }->
  ceph::key { 'client.admin':
    secret  => $ceph_admin_key,
    cap_mon => 'allow *',
    cap_osd => 'allow *',
    cap_mds => 'allow',
  }->
  ceph::key { 'client.openstack':
    secret  => $ceph_openstack_key,
    mode    => '0644',
    cap_mon => 'profile rbd',
    cap_osd => 'profile rbd pool=gnocchi',
  }
  $ceph_pools = ['gnocchi']
  ceph::pool { $ceph_pools: }
  class { '::ceph::profile::params':
    fsid                => $ceph_fsid,
    manage_repo         => false,
    release             => 'nautilus',
    authentication_type => 'cephx',
    mon_host            => $ceph_mon_host,
    mon_initial_members => $ceph_mon_initial_members,
    client_keys         => {
      'client.admin' => {
        secret  => $ceph_admin_key,
        cap_mon => 'allow *',
        cap_osd => 'allow *',
        cap_mds => 'allow',
      },
      'client.openstack' => {
        secret  => $ceph_openstack_key,
        mode    => '0644',
        cap_mon => 'profile rbd',
        cap_osd => 'profile rbd pool=gnocchi',
      }
    }
  }

  #####################
  ### Setup Gnocchi ###
  #####################
  oci::sslkeypair {'gnocchi':
    notify_service_name => 'gnocchi-api',
  }
  $gnocchi_key_file = "/etc/gnocchi/ssl/private/${::fqdn}.pem"
  $gnocchi_crt_file = "/etc/gnocchi/ssl/public/${::fqdn}.crt"
  if $openstack_release == 'rocky'{
    class { '::gnocchi':
      debug                 => true,
      database_connection   => "mysql+pymysql://gnocchi:${pass_gnocchi_db}@${sql_host}/gnocchidb?charset=utf8",
    }
  }else{
    if ($openstack_release == 'stein' or $openstack_release == 'train' or $openstack_release == 'ussuri') {
      class { '::gnocchi':
        database_connection   => "mysql+pymysql://gnocchi:${pass_gnocchi_db}@${sql_host}/gnocchidb?charset=utf8",
      }
    } else {
      class { '::gnocchi':
        coordination_url => "zookeeper://${first_master_ip}:2181/",
      }
      class { 'gnocchi::db':
        database_connection => "mysql+pymysql://gnocchi:${pass_gnocchi_db}@${sql_host}/gnocchidb?charset=utf8",
      }
    }
    class { '::gnocchi::logging':
      debug => true,
    }
  }

  class { '::gnocchi::keystone::authtoken':
    password             => $pass_gnocchi_authtoken,
    auth_url             => $keystone_admin_uri,
    www_authenticate_uri => $keystone_auth_uri,
    memcached_servers    => $memcached_servers,
    cafile               => $api_endpoint_ca_file,
  }
  class { '::gnocchi::api':
    enabled                      => true,
    service_name                 => 'gnocchi-api',
    sync_db                      => true,
    enable_proxy_headers_parsing => true,
  }
  class { '::gnocchi::client': }
  class { '::gnocchi::metricd':
    workers       => 2,
    cleanup_delay => 20,
  }
  class { '::gnocchi::storage':
    metric_processing_delay => 10,
    coordination_url        => "zookeeper://${first_master_ip}:2181/",
  }
  class { '::gnocchi::storage::ceph':
    ceph_username => 'openstack',
    ceph_keyring  => '/etc/ceph/ceph.client.openstack.keyring',
    manage_cradox => false,
    manage_rados  => true,
  }

  gnocchi_config {
    'database/connection': value => "mysql+pymysql://gnocchi:${pass_gnocchi_db}@${sql_host}/gnocchidb?charset=utf8", secret => true;
  }

  class { '::gnocchi::statsd':
    archive_policy_name => 'high',
    flush_delay         => '100',
    # random datas:
    resource_id         => $pass_gnocchi_rscuuid,
  }

  ######################
  ### Setup RabbitMQ ###
  ######################
  if $use_ssl {
    file { "/etc/rabbitmq/ssl/private":
      ensure                  => directory,
      owner                   => 'root',
      mode                    => '0755',
      require                 => File['/etc/rabbitmq/ssl'],
      selinux_ignore_defaults => true,
    }->
    file { "/etc/rabbitmq/ssl/public":
      ensure                  => directory,
      owner                   => 'root',
      mode                    => '0755',
      selinux_ignore_defaults => true,
    }->
    file { "/etc/rabbitmq/ssl/private/${::fqdn}.key":
      ensure                  => present,
      owner                   => "rabbitmq",
      source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
      selinux_ignore_defaults => true,
      mode                    => '0600',
    }->
    file { "/etc/rabbitmq/ssl/public/${::fqdn}.crt":
      ensure                  => present,
      owner                   => "rabbitmq",
      source                  => '/etc/ssl/certs/ssl-cert-snakeoil.pem',
      selinux_ignore_defaults => true,
      mode                    => '0644',
      notify        => Service['rabbitmq-server'],
    }
    $rabbit_ssl_cert = "/etc/rabbitmq/ssl/public/${::fqdn}.crt"
    $rabbit_ssl_key  = "/etc/rabbitmq/ssl/private/${::fqdn}.key"
    $rabbit_ssl_ca   = $oci_pki_root_ca_file
  } else {
    $rabbit_ssl_cert = UNSET
    $rabbit_ssl_key  = UNSET
    $rabbit_ssl_ca   = UNSET
  }

  class { '::rabbitmq':
    delete_guest_user        => true,
    node_ip_address          => $machine_ip,
    ssl_interface            => $machine_ip,
    ssl                      => $use_ssl,
    ssl_only                 => $use_ssl,
    ssl_cacert               => $rabbit_ssl_ca,
    ssl_cert                 => $rabbit_ssl_cert,
    ssl_key                  => $rabbit_ssl_key,
    environment_variables    => $rabbit_env,
    repos_ensure             => false,
    # Clustering options...
    config_cluster           => true,
    cluster_nodes            => $all_rabbits,
    cluster_node_type        => 'ram',
    erlang_cookie            => $pass_rabbitmq_cookie,
    wipe_db_on_cookie_change => true,
    config_variables         => {
        'vm_memory_high_watermark'   => '0.9',
        'vm_memory_limit'            => '107729721752',
        'cluster_partition_handling' => 'autoheal',
      },
  }->
  rabbitmq_vhost { '/':
    provider => 'rabbitmqctl',
    require  => Class['::rabbitmq'],
  }

  if $initial_cluster_setup {
    if $is_first_rabbit {
      rabbitmq_user { 'keystone':
        admin    => true,
        password => $pass_keystone_messaging,
        require  => Class['::rabbitmq'],
      }->
      rabbitmq_user_permissions { "keystone@/":
        configure_permission => '.*',
        write_permission     => '.*',
        read_permission      => '.*',
        provider             => 'rabbitmqctl',
        require              => Class['::rabbitmq'],
      }

      rabbitmq_user { 'monitoring':
        admin    => true,
        password => $pass_rabbitmq_monitoring,
        require  => Class['::rabbitmq'],
      }->
      rabbitmq_user_permissions { "monitoring@/":
        configure_permission => '.*',
        write_permission     => '.*',
        read_permission      => '.*',
        provider             => 'rabbitmqctl',
      }

      exec { 'auto-join-rabbit-cluster':
        command => "/usr/bin/oci-auto-join-rabbitmq-cluster ${first_rabbit}",
        unless  => "/bin/false",
        require => Class['::rabbitmq'],
      }

      if $has_subrole_glance {
        rabbitmq_user { 'glance':
          admin    => true,
          password => $pass_glance_messaging,
        }->
        rabbitmq_user_permissions { "glance@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }

      if $has_subrole_heat {
        rabbitmq_user { 'heat':
          admin    => true,
          password => $pass_heat_messaging,
        }->
        rabbitmq_user_permissions { "heat@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }

      if $has_subrole_barbican {
        rabbitmq_user { 'barbican':
          admin    => true,
          password => $pass_barbican_messaging,
        }->
        rabbitmq_user_permissions { "barbican@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }

      if $has_subrole_nova {
        rabbitmq_user { 'nova':
          admin    => true,
          password => $pass_nova_messaging,
        }->
        rabbitmq_user_permissions { "nova@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_neutron {
        rabbitmq_user { 'neutron':
          admin    => true,
          password => $pass_neutron_messaging,
        }->
        rabbitmq_user_permissions { "neutron@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_cinder {
        rabbitmq_user { 'cinder':
          admin    => true,
          password => $pass_cinder_messaging,
        }->
        rabbitmq_user_permissions { "cinder@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_gnocchi {
        rabbitmq_user { 'gnocchi':
          admin    => true,
          password => $pass_gnocchi_messaging,
        }->
        rabbitmq_user_permissions { "gnocchi@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_panko {
        rabbitmq_user { 'panko':
          admin    => true,
          password => $pass_panko_messaging,
        }->
        rabbitmq_user_permissions { "panko@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_ceilometer {
        rabbitmq_user { 'ceilometer':
          admin    => true,
          password => $pass_ceilometer_messaging,
        }->
        rabbitmq_user_permissions { "ceilometer@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_cloudkitty {
        rabbitmq_user { 'cloudkitty':
          admin    => true,
          password => $pass_cloudkitty_messaging,
        }->
        rabbitmq_user_permissions { "cloudkitty@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_aodh {
        rabbitmq_user { 'aodh':
          admin    => true,
          password => $pass_aodh_messaging,
        }->
        rabbitmq_user_permissions { "aodh@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_octavia {
        rabbitmq_user { 'octavia':
          admin    => true,
          password => $pass_octavia_messaging,
        }->
        rabbitmq_user_permissions { "octavia@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_magnum {
        rabbitmq_user { 'magnum':
          admin    => true,
          password => $pass_magnum_messaging,
        }->
        rabbitmq_user_permissions { "magnum@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
      if $has_subrole_designate {
        rabbitmq_user { 'designate':
          admin    => true,
          password => $pass_designate_messaging,
        }->
        rabbitmq_user_permissions { "designate@/":
          configure_permission => '.*',
          write_permission     => '.*',
          read_permission      => '.*',
          provider             => 'rabbitmqctl',
          require              => Class['::rabbitmq'],
        }
      }
    }
  }
}
