# Here's an example parameter that will recieve
# a controller node through the OCI's ENC:
#
#---
#classes:
#   oci_controller:
#      is_first_master: true
#      first_master: zigo-controller-node-3.infomaniak.ch
#      first_master_ip: 192.168.100.40
#      vip_hostname: zigo-api.infomaniak.ch
#      vip_ipaddr: 192.168.101.2
#      network_ipaddr: 192.168.101.0
#      network_cidr: 24
#      other_masters:
#         - zigo-controller-node-4.infomaniak.ch
#         - zigo-controller-node-5.infomaniak.ch
#      other_masters_ip:
#         - 192.168.100.41
#         - 192.168.100.32
#      all_masters:
#         - zigo-controller-node-3.infomaniak.ch
#         - zigo-controller-node-4.infomaniak.ch
#         - zigo-controller-node-5.infomaniak.ch
#      all_masters_ip:
#         - 192.168.100.40
#         - 192.168.100.41
#         - 192.168.100.32
#
# This is re-used in the oci_controller class below
#
class oci::controller(
  $machine_hostname         = undef,
  $machine_ip               = undef,
  $is_first_master          = false,
  $first_master             = undef,
  $first_master_ip          = undef,
  $other_masters            = undef,
  $other_masters_ip         = undef,
  $vip_hostname             = undef,
  $vip_ipaddr               = undef,
  $vip_netmask              = undef,
  $swiftproxy_hostname      = 'none',
  $network_ipaddr           = undef,
  $network_cidr             = undef,
  $all_masters              = undef,
  $all_masters_ip           = undef,
  $all_masters_ids          = undef,
  $has_subrole_db           = true,
  $has_subrole_messaging    = true,
  $has_subrole_api_keystone = true,
  $has_subrole_heat         = true,
  $has_subrole_glance       = false,
  $has_subrole_swift        = true,
  $use_ssl                  = true,
  $rabbit_env               = {},
  $all_swiftproxy           = undef,
  $all_swiftproxy_ip        = undef,
  $pass_keystone_db         = undef,
  $pass_keystone_messaging  = undef,
  $pass_keystone_adminuser  = undef,
  $pass_keystone_credkey1   = undef,
  $pass_keystone_credkey2   = undef,
  $pass_keystone_fernkey1   = undef,
  $pass_keystone_fernkey2   = undef,
  $pass_nova_db             = undef,
  $pass_nova_messaging      = undef,
  $pass_nova_authtoken      = undef,
  $pass_glance_db           = undef,
  $pass_glance_messaging    = undef,
  $pass_glance_authtoken    = undef,
  $pass_cinder_db           = undef,
  $pass_cinder_messaging    = undef,
  $pass_cinder_authtoken    = undef,
  $pass_neutron_db          = undef,
  $pass_neutron_messaging   = undef,
  $pass_neutron_authtoken   = undef,
  $pass_heat_db             = undef,
  $pass_heat_messaging      = undef,
  $pass_heat_authtoken      = undef,
  $pass_heat_keystone_domain = undef,
  $pass_swift_authtoken     = undef,
){

  if $use_ssl {
    $proto = 'https'
    $messaging_default_port = '5671'
    $messaging_notify_port = '5671'
    $api_port = 443
  } else {
    $proto = 'http'
    $messaging_default_port = '5672'
    $messaging_notify_port = '5672'
    $api_port = 80
  }
  $messaging_default_proto = 'rabbit'
  $messaging_notify_proto = 'rabbit'

  $base_url = "${proto}://${vip_hostname}"
  $keystone_auth_uri  = "${base_url}:${api_port}/identity"
  $keystone_admin_uri = "${base_url}:${api_port}/identity-admin"
  #$memcached_servers  = ["127.0.0.1:11211"]
  $memcached_string = join([join($all_masters_ip,':11211,'), ':11211'],'')
  $memcached_servers  = ["${memcached_string}"]

    ensure_resource('file', '/root/oci-openrc', {
      'ensure'  => 'present',
      'content' => "
export OS_PROJECT_DOMAIN_NAME='default'
export OS_USER_DOMAIN_NAME='default'
export OS_PROJECT_NAME='admin'
export OS_USERNAME='admin'
export OS_PASSWORD='${pass_keystone_adminuser}'
export OS_AUTH_URL='https://${vip_hostname}/identity-admin/v3'
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export OS_CACERT=/etc/ssl/certs/oci-pki-oci-ca-chain.pem
",
    })

  if $vip_netmask == 32 {
    $vip_iface = 'lo'
  } else {
    $vip_iface = 'eth0'
  }

  ################################
  ### Add a virtual IP address ###
  ################################
  class { 'corosync':
    authkey                  => '/var/lib/puppet/ssl/certs/ca.pem',
    bind_address             => $machine_ip,
    unicast_addresses        => $all_masters_ip,
    cluster_name             => 'mycluster',
    enable_secauth           => true,
    set_votequorum           => true,
    quorum_members           => $all_masters_ip,
    quorum_members_ids       => $all_masters_ids,
    log_stderr               => false,
    log_function_name        => true,
    syslog_priority          => 'debug',
    debug                    => true,
  }
  corosync::service { 'pacemaker':
    version => '0',
  }->
  cs_property { 'stonith-enabled':
    value   => 'false',
  }->
  cs_property { 'no-quorum-policy':
    value   => 'stop',
  }->
  cs_primitive { 'openstack-api-vip':
    primitive_class => 'ocf',
    primitive_type  => 'IPaddr2',
    provided_by     => 'heartbeat',
    parameters      => { 'ip' => $vip_ipaddr, 'cidr_netmask' => $vip_netmask, 'nic' => $vip_iface },
    operations      => { 'monitor' => { 'interval' => '10s' } },
  }

  # Add haproxy that will listen on that virtual IP, and load balance
  # to the different API daemons using tcp mode (as the APIs will do
  # full SSL already).

  # First, we accept binding on non-local IPs:
  sysctl::value { 'net.ipv4.ip_nonlocal_bind':
    value => "1",
    target => '/etc/sysctl.d/ip-nonlocal-bind.conf',
  }->
  # Then we setup HA proxy to bind on that IP
  if $use_ssl {
    file { "/etc/haproxy/ssl":
      ensure                  => directory,
      owner                   => 'root',
      mode                    => '0755',
      selinux_ignore_defaults => true,
      require       => Package['haproxy'],
    }->
    file { "/etc/haproxy/ssl/private":
      ensure                  => directory,
      owner                   => 'root',
      mode                    => '0755',
      selinux_ignore_defaults => true,
    }->
    file { "/etc/haproxy/ssl/private/oci-pki-api.pem":
      ensure                  => present,
      owner                   => "haproxy",
      source                  => "/etc/ssl/private/oci-pki-api.pem",
      selinux_ignore_defaults => true,
      mode                    => '0600',
    }
  }
  class { 'haproxy':
    global_options   => {
      'maxconn' => '40960',
      'user'    => 'haproxy',
      'group'   => 'haproxy',
      'daemon'  => '',
    },
    defaults_options => {
      'mode'    => 'http',
    }
  }
# TODO: For security, we want this in the global section:
# global
#   ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
#   ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
#   ssl-default-server-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
#   ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
# frontend ft_test
#   mode    http
#   bind    :443 ssl crt /path/to/<cert+privkey+intermediate+dhparam>
#   option forwardfor
#   http-request set-header X-Forwarded-Port %[dst_port]
#   http-request add-header X-Forwarded-Proto https if { ssl_fc }

  $haproxy_options_keystone = [
    { 'acl'         => 'url_keystone_admin path_beg -i /identity-admin'},
    { 'use_backend' => 'keystoneadmbe if url_keystone_admin'},
    { 'acl'         => 'url_keystone path_beg -i /identity'},
    { 'use_backend' => 'keystonepubbe if url_keystone'},
  ]

  $glance_haproxy_options = [
    { 'acl'         => 'url_glance path_beg -i /image'},
    { 'use_backend' => 'glancebe if url_glance'},
  ]

  $swift_haproxy_options = [
    { 'acl'         => 'url_swift path_beg -i /object'},
    { 'use_backend' => 'swiftbe if url_swift'},
  ]

  $heat_haproxy_options = [
    { 'acl'         => 'url_heatcfn path_beg -i /orchestration-cfn'},
    { 'use_backend' => 'heatcfnbe if url_heatcfn'},
    { 'acl'         => 'url_heat path_beg -i /orchestration'},
    { 'use_backend' => 'heatbe if url_heat'},
  ]

  if $has_subrole_glance {
    $haproxy_options_with_glance = concat($haproxy_options_keystone, $glance_haproxy_options)
  } else {
    $haproxy_options_with_glance = $haproxy_options_keystone
  }

  if $has_subrole_swift and $swiftproxy_hostname == 'none' {
    $haproxy_options_with_swift = concat($haproxy_options_with_glance, $swift_haproxy_options)
  } else {
    $haproxy_options_with_swift = $haproxy_options_with_glance
  }

  if $has_subrole_heat {
    $haproxy_options_with_heat = concat($haproxy_options_with_swift, $heat_haproxy_options)
  } else {
    $haproxy_options_with_heat = $haproxy_options_with_swift
  }

  # Global frontend for all services with dispatch depending on the URL
  haproxy::frontend { 'openstackfe':
    mode      => 'http',
    bind      => { "${vip_ipaddr}:${api_port}" => ['ssl', 'crt', '/etc/haproxy/ssl/private/oci-pki-api.pem'] },
    options   => $haproxy_options_with_heat,
  }

  # Keystone public
  haproxy::backend { 'keystonepubbe':
    options => [
       { 'option' => 'forwardfor' },
       { 'mode' => 'http' },
       { 'balance' => 'source' },
       { 'reqrep'  => '^([^\ ]*\ /)identity[/]?(.*)     \1\2'},
    ],
  }
  haproxy::balancermember { 'keystonepubbm':
    listening_service => 'keystonepubbe',
    ipaddresses       => $all_masters_ip,
    server_names      => $all_masters,
    ports             => 5000,
    options           => 'check ssl verify none',
  }
# TODO: haproxy::balancermember needs an option like this one:
#  ssl verify required ca-file /etc/haproxy/cert.d/key1.pem check

  # keystone admin
  haproxy::backend { 'keystoneadmbe':
    options => [
       { 'option' => 'forwardfor' },
       { 'mode' => 'http' },
       { 'balance' => 'source' },
       { 'reqrep'  => '^([^\ ]*\ /)identity-admin[/]?(.*)     \1\2'},
    ],
  }
  haproxy::balancermember { 'keystoneadmbm':
    listening_service => 'keystoneadmbe',
    ipaddresses       => $all_masters_ip,
    server_names      => $all_masters,
    ports             => 35357,
    options           => 'check ssl verify none',
  }

  # glance API
  if $has_subrole_glance {
    haproxy::backend { 'glancebe':
      options => [
         { 'option' => 'forwardfor' },
         { 'mode' => 'http' },
         { 'balance' => 'source' },
         { 'reqrep'  => '^([^\ ]*\ /)image[/]?(.*)     \1\2'},
      ],
    }
    haproxy::balancermember { 'glancebm':
      listening_service => 'glancebe',
      ipaddresses       => $all_masters_ip,
      server_names      => $all_masters,
      ports             => 9292,
      options           => 'check ssl verify none',
    }
  }

  # swift proxy
  if $has_subrole_swift and $swiftproxy_hostname == 'none' {
    haproxy::backend { 'swiftbe':
      options => [
         { 'option' => 'httpchk GET /healthcheck' },
         { 'option' => 'forwardfor' },
         { 'mode' => 'http' },
         { 'balance' => 'source' },
         { 'reqrep'  => '^([^\ ]*\ /)object[/]?(.*)     \1\2'},
      ],
    }
    haproxy::balancermember { 'swiftbm':
      listening_service => 'swiftbe',
      ipaddresses       => $all_swiftproxy_ip,
      server_names      => $all_swiftproxy,
      ports             => 8080,
      options           => 'check',
    }
  }

  # heat
  if $has_subrole_heat {
    haproxy::backend { 'heatbe':
      options => [
         { 'option' => 'forwardfor' },
         { 'mode' => 'http' },
         { 'balance' => 'source' },
         { 'reqrep'  => '^([^\ ]*\ /)orchestration[/]?(.*)     \1\2'},
      ],
    }
    haproxy::balancermember { 'heatbm':
      listening_service => 'heatbe',
      ipaddresses       => $all_masters_ip,
      server_names      => $all_masters,
      ports             => 8004,
      options           => 'check ssl verify none',
    }
    haproxy::backend { 'heatcfnbe':
      options => [
         { 'option' => 'forwardfor' },
         { 'mode' => 'http' },
         { 'balance' => 'source' },
         { 'reqrep'  => '^([^\ ]*\ /)orchestration-cfn[/]?(.*)     \1\2'},
      ],
    }
    haproxy::balancermember { 'heatcfnbm':
      listening_service => 'heatcfnbe',
      ipaddresses       => $all_masters_ip,
      server_names      => $all_masters,
      ports             => 8000,
      options           => 'check ssl verify none',
    }
  }

  # Setup databases
  if $has_subrole_db {

    class { 'galera':
      galera_servers      => $all_masters_ip,
      galera_master       => $first_master,
      package_ensure      => 'latest',
      mysql_package_name  => 'mariadb-server',
      client_package_name => 'default-mysql-client',
      vendor_type         => 'mariadb',
      root_password       => 'a_big_secret',
      status_password     => 'a_big_secret',
      configure_repo      => false,
      configure_firewall  => false,
      galera_package_name => 'galera-3',
      override_options => {
        'mysqld' => {
          'bind_address'                    => '0.0.0.0',
          'wait_timeout'                    => '28800',
          'interactive_timeout'             => '30',
          'connect_timeout'                 => '30',
          'character_set_server'            => 'utf8',
          'collation_server'                => 'utf8_general_ci',
        }
      }
    }->
    class { '::keystone::db::mysql':
      dbname   => 'keystonedb',
      password => $pass_keystone_db,
    }
    if $has_subrole_glance {
      class { '::glance::db::mysql':
        dbname   => 'glancedb',
        password => $pass_glance_db,
      }
    }
    if $has_subrole_heat {
      class { '::heat::db::mysql':
        dbname   => 'heatdb',
        password => $pass_heat_db,
      }
    }
  }

  # RabbitMQ
  if $has_subrole_messaging {
    if $use_ssl {
      $ssl_cert = "/etc/ssl/certs/ssl-cert-snakeoil.pem"
      $ssl_key  = "/etc/ssl/private/ssl-cert-snakeoil.key"
    } else {
      $ssl_cert = 'UNSET'
      $ssl_key  = 'UNSET'
    }

    class { '::rabbitmq':
      package_ensure           => 'latest',
      delete_guest_user        => true,
      ssl                      => $use_ssl,
      ssl_only                 => $use_ssl,
      ssl_cert                 => $ssl_cert,
      ssl_key                  => $ssl_key,
      environment_variables    => $rabbit_env,
      repos_ensure             => false,
      # Clustering options...
      config_cluster           => true,
      cluster_nodes            => $all_masters,
      cluster_node_type        => 'ram',
      erlang_cookie            => 'XAFSRAFNNFJOFSHLEUFT',
      wipe_db_on_cookie_change => true,
    }->
    rabbitmq_vhost { '/':
      provider => 'rabbitmqctl',
      require  => Class['::rabbitmq'],
    }->
    rabbitmq_user { 'keystone':
      admin    => true,
      password => $pass_keystone_messaging,
    }->
    rabbitmq_user_permissions { "keystone@/":
      configure_permission => '.*',
      write_permission     => '.*',
      read_permission      => '.*',
      provider             => 'rabbitmqctl',
      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'],
        before               => Anchor['glance::service::begin'],
      }
    }

    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'],
        before               => Anchor['heat::service::begin'],
      }
    }
  }

  # Get memcached
  class { '::memcached':
    listen_ip => $machine_ip,
    udp_port  => 0,
  }

  # Configure Apache to use mod-wsgi-py3, not mod-wsgi
  if $has_subrole_api_keystone {
    # Set python3 for mod-wsgi
    include ::apache::params
    class { '::apache':
      mod_packages => merge($::apache::params::mod_packages, {
        'wsgi' => 'libapache2-mod-wsgi-py3',
      })
    }
  }

  if $has_subrole_api_keystone {
    ##############################
    ### Setup keystone cluster ###
    ##############################
    class { '::keystone::client': }
    class { '::keystone::cron::token_flush': }

    if $use_ssl {
      file { "/etc/keystone/ssl":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
        require       => Package['keystone'],
      }->
      file { "/etc/keystone/ssl/private":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
      }->
      file { "/etc/keystone/ssl/public":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
      }->
      file { "/etc/keystone/ssl/private/${::fqdn}.key":
        ensure                  => present,
        owner                   => "keystone",
        source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
        selinux_ignore_defaults => true,
        mode                    => '0600',
      }->
      file { "/etc/keystone/ssl/public/${::fqdn}.crt":
        ensure                  => present,
        owner                   => "keystone",
        source                  => '/etc/ssl/certs/ssl-cert-snakeoil.pem',
        selinux_ignore_defaults => true,
        mode                    => '0644',
        notify        => Service['httpd'],
      }
    }

    ensure_resource('file', '/etc/apache2/sites-available/wsgi-keystone.conf', {
      'ensure'  => 'present',
      'content' => '',
      require   => Package['keystone'],
    })

    class { '::keystone':
      debug                      => true,
      database_connection        => "mysql://keystone:${pass_keystone_db}@127.0.0.1/keystonedb",
      catalog_type               => 'sql',
      admin_token                => $pass_keystone_adminuser,
      admin_password             => $pass_keystone_adminuser,
      enabled                    => true,
      service_name               => 'httpd',
      enable_ssl                 => $use_ssl,
      public_bind_host           => "${::fqdn}",
      admin_bind_host            => "${::fqdn}",
      manage_policyrcd           => true,
      enable_credential_setup    => true,
      credential_key_repository  => '/etc/keystone/credential-keys',
      credential_keys            => { '/etc/keystone/credential-keys/0' => { 'content' => $pass_keystone_credkey1 },
                                      '/etc/keystone/credential-keys/1' => { 'content' => $pass_keystone_credkey2 },
                                    },
      enable_fernet_setup        => true,
      fernet_key_repository      => '/etc/keystone/fernet-keys',
      fernet_max_active_keys     => 4,
      fernet_keys                => { '/etc/keystone/fernet-keys/0' => { 'content' => $pass_keystone_fernkey1 },
                                      '/etc/keystone/fernet-keys/1' => { 'content' => $pass_keystone_fernkey1 },
                                    },
      token_expiration           => 604800,
      admin_endpoint             => "https://${vip_hostname}:${api_port}/identity-admin",
      public_endpoint            => "https://${vip_hostname}:${api_port}/identity",
      default_transport_url      => os_transport_url({
        'transport' => 'rabbit',
        'host'      => $::fqdn,
        'port'      => '5671',
        'username'  => 'keystone',
        'password'  => $pass_keystone_messaging,
      }),
      notification_transport_url => os_transport_url({
        'transport' => 'rabbit',
        'host'      => $::fqdn,
        'port'      => '5671',
        'username'  => 'keystone',
        'password'  => $pass_keystone_messaging,
      }),
      rabbit_use_ssl             => $use_ssl,
      rabbit_ha_queues           => true,
      memcache_servers           => $memcached_servers,
    }
    include ::apache
    class { '::keystone::wsgi::apache':
      bind_host       => $machine_ip,
      admin_bind_host => $machine_ip,
      ssl             => $use_ssl,
      ssl_key         => "/etc/keystone/ssl/private/${::fqdn}.key",
      ssl_cert        => "/etc/keystone/ssl/public/${::fqdn}.crt",
      workers         => 2,
    }
    class { '::keystone::roles::admin':
      email    => 'production@infomaniak.com',
      password => $pass_keystone_adminuser,
    }->
    class { '::keystone::endpoint':
      public_url => "${base_url}/identity",
      admin_url  => "${base_url}/identity-admin",
    }
    class { '::keystone::disable_admin_token_auth': }
    class { '::openstack_extras::auth_file':
      password       => $pass_keystone_adminuser,
      project_domain => 'default',
      user_domain    => 'default',
      auth_url       => "${base_url}:${api_port}/identity/v3/",
    }
    keystone_role { 'creator':
      ensure => present,
    }
    keystone_role { 'member':
      ensure => present,
    }
  }
  ####################
  ### Setup Glance ###
  ####################
  if $has_subrole_glance {
    if $use_ssl {
      file { "/etc/glance/ssl":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
        require                 => Package['glance-api'],
      }->
      file { "/etc/glance/ssl/private":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
      }->
      file { "/etc/glance/ssl/public":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
      }->
      file { "/etc/glance/ssl/private/${::fqdn}.pem":
        ensure                  => present,
        owner                   => "glance",
        source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
        selinux_ignore_defaults => true,
        mode                    => '0600',
      }->
      file { "/etc/glance/ssl/public/${::fqdn}.crt":
        ensure                  => present,
        owner                   => "glance",
        source                  => '/etc/ssl/certs/ssl-cert-snakeoil.pem',
        selinux_ignore_defaults => true,
        mode                    => '0644',
        notify                  => Service['glance-api'],
      }

      $glance_key_file = "/etc/glance/ssl/private/${::fqdn}.pem"
      $glance_crt_file = "/etc/glance/ssl/public/${::fqdn}.crt"
    } else {
      $glance_key_file = undef
      $glance_crt_file = undef
    }

    include ::glance
    include ::glance::client
    if $is_first_master {
      class { '::glance::keystone::auth':
        public_url   => "${base_url}/image",
        internal_url => "${base_url}/image",
        admin_url    => "${base_url}/image",
        password     => $pass_glance_authtoken,
      }
    }

    class { '::glance::api::authtoken':
      password             => $pass_glance_authtoken,
      auth_url             => $keystone_admin_uri,
      www_authenticate_uri => $keystone_auth_uri,
      memcached_servers    => $memcached_servers,
      cafile               => '/etc/ssl/certs/oci-pki-oci-ca-chain.pem',
    }

    # Let's use the file backend for now...
    include ::glance::backend::file
    $backend_store = ['file']

    class { '::glance::api':
      debug               => true,
      database_connection => "mysql+pymysql://glance:${pass_glance_db}@127.0.0.1/glancedb?charset=utf8",
      workers             => 2,
      stores              => $glance_stores,
      default_store       => 'file',
      bind_host           => $machine_hostname,
      cert_file           => $glance_crt_file,
      key_file            => $glance_key_file,
      enable_v1_api       => false,
      enable_v2_api       => true,
    }

    class { '::glance::notify::rabbitmq':
      default_transport_url      => os_transport_url({
        'transport' => $messaging_default_proto,
        'host'      => $machine_hostname,
        'port'      => $messaging_default_port,
        'username'  => 'glance',
        'password'  => $pass_glance_messaging,
      }),
      notification_transport_url => os_transport_url({
        'transport' => $messaging_notify_proto,
        'host'      => $machine_hostname,
        'port'      => $messaging_notify_port,
        'username'  => 'glance',
        'password'  => $pass_glance_messaging,
      }),
      notification_driver        => 'messagingv2',
      rabbit_use_ssl             => $use_ssl,
    }
  }

  ###################
  ### Setup Swift ###
  ###################
  if $has_subrole_swift  {
    if $swiftproxy_hostname == 'none' {
      $swiftproxy_baseurl = $base_url
    } else {
      $swiftproxy_baseurl = "${proto}://${swiftproxy_hostname}"
    }
    class { '::swift::keystone::auth':
      public_url            => "${swiftproxy_baseurl}/object/v1/AUTH_%(tenant_id)s",
      admin_url             => "${swiftproxy_baseurl}/object",
      internal_url          => "${swiftproxy_baseurl}/object/v1/AUTH_%(tenant_id)s",
      password              => $pass_swift_authtoken,
      operator_roles        => ['admin', 'SwiftOperator', 'ResellerAdmin'],
      configure_s3_endpoint => false,
    }
  }

  ##################
  ### Setup Heat ###
  ##################
  if $has_subrole_heat {
    if $use_ssl {
      file { "/etc/heat/ssl":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
        require                 => Package['heat-api'],
      }->
      file { "/etc/heat/ssl/private":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
      }->
      file { "/etc/heat/ssl/public":
        ensure                  => directory,
        owner                   => 'root',
        mode                    => '0755',
        selinux_ignore_defaults => true,
      }->
      file { "/etc/heat/ssl/private/${::fqdn}.pem":
        ensure                  => present,
        owner                   => "heat",
        source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
        selinux_ignore_defaults => true,
        mode                    => '0600',
      }->
      file { "/etc/heat/ssl/public/${::fqdn}.crt":
        ensure                  => present,
        owner                   => "heat",
        source                  => '/etc/ssl/certs/ssl-cert-snakeoil.pem',
        selinux_ignore_defaults => true,
        mode                    => '0644',
        notify                  => Service['heat-api'],
      }

      $heat_key_file = "/etc/heat/ssl/private/${::fqdn}.pem"
      $heat_crt_file = "/etc/heat/ssl/public/${::fqdn}.crt"
    } else {
      $heat_key_file = undef
      $heat_crt_file = undef
    }
    class { '::heat::keystone::authtoken':
      password             => $pass_heat_authtoken,
      auth_url             => $keystone_admin_uri,
      www_authenticate_uri => $keystone_auth_uri,
      memcached_servers    => $memcached_servers,
      cafile               => '/etc/ssl/certs/oci-pki-oci-ca-chain.pem',
    }
    if $is_first_master {
      class { '::heat::keystone::auth':
        public_url   => "${base_url}/orchestration/v1/%(tenant_id)s",
        internal_url => "${base_url}/orchestration/v1/%(tenant_id)s",
        admin_url    => "${base_url}/orchestration/v1/%(tenant_id)s",
        password     => $pass_heat_authtoken,
      }
      class { '::heat::keystone::auth_cfn':
        public_url   => "${base_url}/orchestration-cfn/v1",
        internal_url => "${base_url}/orchestration-cfn/v1",
        admin_url    => "${base_url}/orchestration-cfn/v1",
        password     => $pass_heat_authtoken,
      }
    }

    class { '::heat':
      default_transport_url      => os_transport_url({
        'transport' => $messaging_default_proto,
        'host'      => $machine_hostname,
        'port'      => $messaging_default_port,
        'username'  => 'heat',
        'password'  => $pass_heat_messaging,
      }),
      notification_transport_url => os_transport_url({
        'transport' => $messaging_notify_proto,
        'host'      => $machine_hostname,
        'port'      => $messaging_notify_port,
        'username'  => 'heat',
        'password'  => $pass_heat_messaging,
      }),
      rabbit_use_ssl             => $use_ssl,
      database_connection        => "mysql+pymysql://heat:${pass_heat_db}@127.0.0.1/heatdb?charset=utf8",
      debug                      => true,
      notification_driver        => 'messagingv2',
    }
    class { '::heat::keystone::domain':
      domain_password => $pass_heat_keystone_domain,
    }
    class { '::heat::client': }
    class { '::heat::api':
      service_name => 'httpd',
    }
    class { '::heat::wsgi::apache_api':
      bind_host       => $machine_ip,
      ssl             => $use_ssl,
      ssl_key         => $heat_key_file,
      ssl_cert        => $heat_crt_file,
      workers         => 2,
    }

    class { '::heat::engine':
      auth_encryption_key           => '1234567890AZERTYUIOPMLKJHGFDSQ12',
#      heat_metadata_server_url      => "${base_url}:8000/orchestration-cfn",
#      heat_waitcondition_server_url => "${base_url}:8000/orchestration-cfn/v1/waitcondition",
    }
    class { '::heat::api_cfn':
      service_name => 'httpd',
    }
    class { '::heat::wsgi::apache_api_cfn':
      bind_host => $machine_ip,
      ssl       => $use_ssl,
      ssl_key   => $heat_key_file,
      ssl_cert  => $heat_crt_file,
      workers   => 2,
    }
    class { '::heat::cron::purge_deleted': }

  }
}
