
### CONFIG GOES HERE ###
$api_hostname            = 'bdbdev1-controller-node-1.infomaniak.ch'
$ssl                     = true
$volume_encryption       = false
$enable_vitrage          = false
$om_rpc                  = 'rabbit'
$om_host                 = $api_hostname
$om_notify               = 'rabbit'
$om_notify_host          = $api_hostname
$messaging_default_port  = '5671'
$messaging_notify_port   = '5671'
$notification_topics     = 'osnotify'
$ceph_mirror             = 'http://10.4.22.95:9999/ceph'
#$ceph_mirror             = 'http://download.ceph.com/debian-luminous/'

### COMPUTE NODE SPECIFICS ###
$libvirt_virt_type = 'qemu'
$libvirt_cpu_mode  = 'host-passthrough'

### SOME QUICK CALCULATION BASED ON CONFIG ###
if $ssl {
  $proto = 'https'
} else {
  $proto = 'http'
}
$rabbit_port             = $messaging_notify_port
$base_url                = "${proto}://${api_hostname}"
$keystone_auth_uri       = "${base_url}:5000"
$keystone_admin_uri      = "${base_url}:35357"
$rabbit_env              = {}
$ip_version              = '4'
$memcached_servers       = ["${::fqdn}:11211"]
$swift_memcached_servers = $memcached_servers
$tooz_url                = "redis://${api_hostname}:6379"

class cloud_repo {
  include ::apt
  class { '::openstack_extras::repo::debian::debian':
    release         => 'rocky',
    package_require => true,
  }
  apt::pin { 'ceph':
    priority => 1001,
    origin   => 'download.ceph.com',
  }
  $enable_sig  = false
  $enable_epel = false
  class { '::ceph::repo':
    enable_sig  => false,
    enable_epel => false,
    ceph_mirror => $ceph_mirror,
  }
}

class cloud_master {

  # Set python3 for mod-wsgi
  include ::apache::params
  class { '::apache':
    mod_packages => merge($::apache::params::mod_packages, {
      'wsgi' => 'libapache2-mod-wsgi-py3',
    })
  }

  # Copy cert in the correct location
  file { '/usr/local/share/ca-certificates/puppet_openstack.crt':
    ensure                  => present,
    owner                   => 'root',
    group                   => 'root',
    mode                    => '0444',
    source                  => "/etc/ssl/certs/ssl-cert-snakeoil.pem",
    selinux_ignore_defaults => true,
    replace                 => true,
  }

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

  # RabbitMQ
  file { '/etc/rabbitmq/ssl/private':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File["/etc/rabbitmq/ssl/private/${::fqdn}.pem"],
  }

  file { "/etc/rabbitmq/ssl/private/${::fqdn}.pem":
    ensure                  => present,
    owner                   => 'rabbitmq',
    source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
    selinux_ignore_defaults => true,
    mode                    => '0600',
  }

  class { '::rabbitmq':
    delete_guest_user     => true,
    ssl                   => true,
    ssl_only              => true,
#   ssl_cacert            => $::openstack_integration::params::ca_bundle_cert_path,
    ssl_cert              => '/usr/local/share/ca-certificates/puppet_openstack.crt',
    ssl_key               => "/etc/rabbitmq/ssl/private/${::fqdn}.pem",
    environment_variables => $rabbit_env,
    repos_ensure          => false,
  }

  rabbitmq_vhost { '/':
    provider => 'rabbitmqctl',
    require  => Class['::rabbitmq'],
  }

  # MySQL
  class { '::mysql::server': }

  # Keystone
  Exec { logoutput => 'on_failure' }

  class { '::keystone::db::mysql':
    password => 'keystone',
  }

  exec { 'update-ca-certificates':
    command     => '/usr/sbin/update-ca-certificates -f',
    subscribe   => File['/usr/local/share/ca-certificates/puppet_openstack.crt'],
    refreshonly => true,
  }
  Exec['update-ca-certificates'] ~> Service['httpd']


  class { '::keystone':
    debug               => true,
    database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
    catalog_type        => 'sql',
    admin_token         => 'admin_token',
    enabled             => false,
    enable_ssl          => $ssl,
    public_bind_host    => "${::fqdn}",
    admin_bind_host     => "${::fqdn}",
    rabbit_use_ssl      => $ssl,
  }
  class { '::keystone::roles::admin':
    email    => 'production@infomaniak.com',
    password => 'a_big_secret',
  }
  class { '::keystone::endpoint':
    public_url => "https://${::fqdn}:5000/",
    admin_url  => "https://${::fqdn}:35357/",
  }

  file { '/etc/keystone/ssl/private':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File["/etc/keystone/ssl/private/${::fqdn}.pem"],
  }

  file { "/etc/keystone/ssl/private/${::fqdn}.pem":
    ensure                  => present,
    owner                   => 'rabbitmq',
    source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
    selinux_ignore_defaults => true,
    mode                    => '0600',
  }

  include ::apache
  class { '::keystone::wsgi::apache':
    ssl             => true,
    ssl_cert        => '/usr/local/share/ca-certificates/puppet_openstack.crt',
    ssl_key         => '/etc/ssl/private/ssl-cert-snakeoil.key',
    workers         => 2,
  }

  # Glance
  file { '/etc/glance/ssl':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File['/etc/glance/ssl/private'],
  }

  file { '/etc/glance/ssl/private':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File["/etc/glance/ssl/private/${::fqdn}.pem"],
  }

  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',
    notify                  => Service['glance-api'],
  }

  Package<| tag == 'glance-package' |> -> File["/etc/glance/ssl/private/${::fqdn}.pem"]
  Exec['update-ca-certificates'] ~> Service['glance-api']

  rabbitmq_user { 'glance':
    admin    => true,
    password => 'glancerbpass',
    provider => 'rabbitmqctl',
    require  => Class['::rabbitmq'],
    before   => Anchor['glance::service::begin'],
  }
  rabbitmq_user_permissions { "glance@/":
    configure_permission => '.*',
    write_permission     => '.*',
    read_permission      => '.*',
    provider             => 'rabbitmqctl',
    require              => Class['::rabbitmq'],
    before               => Anchor['glance::service::begin'],
  }

  class { '::glance::db::mysql':
    password => 'glance',
  }

  class { '::glance::keystone::auth':
    public_url   => "${base_url}:9292",
    internal_url => "${base_url}:9292",
    admin_url    => "${base_url}:9292",
    password     => 'a_big_secret',
  }
  class { '::glance::api::authtoken':
    password             => 'a_big_secret',
    user_domain_name     => 'Default',
    project_domain_name  => 'Default',
    auth_url             => $keystone_auth_uri,
    www_authenticate_uri => $keystone_auth_uri,
    memcached_servers    => $memcached_servers,
  }

  include ::glance
  include ::glance::client

  class { '::glance::backend::file': }
  class { '::glance::api':
    debug               => true,
    database_connection => 'mysql+pymysql://glance:glance@127.0.0.1/glance?charset=utf8',
    stores              => ['file'],
    default_store       => 'file',
    bind_host           => "${::fqdn}",
    cert_file           => '/usr/local/share/ca-certificates/puppet_openstack.crt',
    key_file            => "/etc/glance/ssl/private/${::fqdn}.pem",
    enable_v1_api       => false,
    enable_v2_api       => true,
  }
  class { '::glance::registry::authtoken':
    password => 'a_big_secret',
    user_domain_name     => 'Default',
    project_domain_name  => 'Default',
    auth_url             => $keystone_auth_uri,
    www_authenticate_uri => $keystone_auth_uri,
    memcached_servers    => $memcached_servers,
  }
  class { '::glance::registry':
    database_connection => 'mysql+pymysql://glance:glance@127.0.0.1/glance?charset=utf8',
  }
  class { '::glance::notify::rabbitmq':
    default_transport_url      => os_transport_url({
      'transport' => $om_rpc,
      'host'      => $om_host,
      'port'      => $messaging_default_port,
      'username'  => 'glance',
      'password'  => 'glancerbpass',
    }),
    notification_transport_url => os_transport_url({
      'transport' => $om_notify,
      'host'      => $om_notify_host,
      'port'      => $messaging_notify_port,
      'username'  => 'glance',
      'password'  => 'glancerbpass',
    }),
    notification_driver        => 'messagingv2',
    rabbit_use_ssl             => $ssl,
    rabbit_notification_topic  => $notification_topics,
  }

  # Cinder

  rabbitmq_user { 'cinder':
    admin    => true,
    password => 'cinderrbpass',
    provider => 'rabbitmqctl',
    require  => Class['::rabbitmq'],
    before   => Anchor['cinder::service::begin'],
  }
  rabbitmq_user_permissions { "cinder@/":
    configure_permission => '.*',
    write_permission     => '.*',
    read_permission      => '.*',
    provider             => 'rabbitmqctl',
    require              => Class['::rabbitmq'],
    before               => Anchor['cinder::service::begin'],
  }

  file { '/etc/cinder/ssl':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File['/etc/cinder/ssl/private'],
    require                 => Package['cinder'],
  }

  file { '/etc/cinder/ssl/private':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File["/etc/cinder/ssl/private/${::fqdn}.pem"],
  }

  file { "/etc/cinder/ssl/private/${::fqdn}.pem":
    ensure                  => present,
    owner                   => 'cinder',
    source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
    selinux_ignore_defaults => true,
    mode                    => '0600',
    notify                  => Service['httpd'],
  }

  include ::cinder::client
  class { '::cinder::db::mysql':
    password => 'cinderdbpass',
  }

  class { '::cinder::keystone::auth':
    public_url      => "${base_url}:8776/v1/%(tenant_id)s",
    internal_url    => "${base_url}:8776/v1/%(tenant_id)s",
    admin_url       => "${base_url}:8776/v1/%(tenant_id)s",
    public_url_v2   => "${base_url}:8776/v2/%(tenant_id)s",
    internal_url_v2 => "${base_url}:8776/v2/%(tenant_id)s",
    admin_url_v2    => "${base_url}:8776/v2/%(tenant_id)s",
    public_url_v3   => "${base_url}:8776/v3/%(tenant_id)s",
    internal_url_v3 => "${base_url}:8776/v3/%(tenant_id)s",
    admin_url_v3    => "${base_url}:8776/v3/%(tenant_id)s",
    password        => 'a_big_secret',
  }

  class { '::cinder':
    default_transport_url => os_transport_url({
      'transport' => $om_rpc,
      'host'      => $om_host,
      'port'      => $messaging_default_port,
      'username'  => 'cinder',
      'password'  => 'cinderrbpass',
    }),
    database_connection  => 'mysql://cinder:cinderdbpass@127.0.0.1/cinder',
    rabbit_use_ssl       => $ssl,
    amqp_sasl_mechanisms => 'PLAIN',
    debug                => true,
  }

  class { '::cinder::ceilometer':
    notification_transport_url => os_transport_url({
      'transport' => $om_notify,
      'host'      => $om_notify_host,
      'port'      => $messaging_notify_port,
      'username'  => 'cinder',
      'password'  => 'an_even_bigger_secret',
    }),
    notification_topics        => $notification_topics,
    notification_driver        => 'messagingv2',
  }

  class { '::cinder::keystone::authtoken':
    password             => 'cinderkspass',
    user_domain_name     => 'Default',
    project_domain_name  => 'Default',
    auth_url             => $keystone_auth_uri,
    www_authenticate_uri => $keystone_auth_uri,
    memcached_servers    => $memcached_servers,
  }

  if $volume_encryption {
    $keymgr_backend             = 'castellan.key_manager.barbican_key_manager.BarbicanKeyManager'
    $keymgr_encryption_api_url  = "${base_url}:9311"
    $keymgr_encryption_auth_url = "${::keystone_auth_uri}/v3"
  } else {
    $keymgr_backend             = 'cinder.keymgr.conf_key_mgr.ConfKeyManager'
    $keymgr_encryption_api_url  = undef
    $keymgr_encryption_auth_url = undef
  }
  class { '::cinder::api':
    default_volume_type        => 'BACKEND_1',
    public_endpoint            => "${base_url}:8776",
    service_name               => 'httpd',
    keymgr_backend             => $keymgr_backend,
    keymgr_encryption_api_url  => $keymgr_encryption_api_url,
    keymgr_encryption_auth_url => $keymgr_encryption_auth_url,
  }
  include ::apache
  class { '::cinder::wsgi::apache':
    bind_host => '*',
    ssl       => $ssl,
    ssl_key   => "/etc/cinder/ssl/private/${::fqdn}.pem",
    ssl_cert  => '/usr/local/share/ca-certificates/puppet_openstack.crt',
    workers   => 4,
  }
  class { '::cinder::quota': }
  class { '::cinder::scheduler': }
  class { '::cinder::scheduler::filter': }
  class { '::cinder::cron::db_purge': }
  class { '::cinder::glance':
    glance_api_servers => "${base_url}:9292",
  }

  # Nova
  file { '/etc/nova/ssl':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File['/etc/nova/ssl/private'],
    require                 => Package['nova-common'],
  }

  file { '/etc/nova/ssl/private':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File["/etc/nova/ssl/private/${::fqdn}.pem"],
  }

  file { "/etc/nova/ssl/private/${::fqdn}.pem":
    ensure                  => present,
    owner                   => 'nova',
    source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
    selinux_ignore_defaults => true,
    mode                    => '0600',
    notify                  => Service['httpd'],
  }

  rabbitmq_user { 'nova':
    admin    => true,
    password => 'novarbpass',
    provider => 'rabbitmqctl',
    require  => Class['::rabbitmq'],
    before   => Anchor['nova::service::begin'],
  }
  rabbitmq_user_permissions { "nova@/":
    configure_permission => '.*',
    write_permission     => '.*',
    read_permission      => '.*',
    provider             => 'rabbitmqctl',
    require              => Class['::rabbitmq'],
    before               => Anchor['nova::service::begin'],
  }

  class { '::nova::db::mysql':
    password => 'novadbpass',
  }
  class { '::nova::db::mysql_api':
    password    => 'novaapidbpass',
  }
  class { '::nova::db::mysql_placement':
    password => 'novapldbpass',
  }
  include ::nova::cell_v2::simple_setup
  class { '::nova::keystone::auth':
    public_url   => "${base_url}:8774/v2.1",
    internal_url => "${base_url}:8774/v2.1",
    admin_url    => "${base_url}:8774/v2.1",
    password     => 'novakspass',
  }

  class { '::nova::keystone::auth_placement':
    public_url   => "${base_url}:8778",
    internal_url => "${base_url}:8778",
    admin_url    => "${base_url}:8778",
    password     => 'novaplacementkspass',
  }
  class { '::nova::keystone::authtoken':
    password             => 'novakspass',
    user_domain_name     => 'Default',
    project_domain_name  => 'Default',
    auth_url             => $keystone_auth_uri,
    www_authenticate_uri => $keystone_auth_uri,
    memcached_servers    => $memcached_servers,
  }
  class { '::nova':
    default_transport_url         => os_transport_url({
      'transport' => $om_rpc,
      'host'      => $om_host,
      'port'      => $messaging_default_port,
      'username'  => 'nova',
      'password'  => 'novarbpass',
    }),
    notification_transport_url    => os_transport_url({
      'transport' => $om_notify,
      'host'      => $om_notify_host,
      'port'      => $messaging_notify_port,
      'username'  => 'nova',
      'password'  => 'novarbpass',
    }),
    database_connection           => 'mysql+pymysql://nova:novadbpass@127.0.0.1/nova?charset=utf8',
    api_database_connection       => 'mysql+pymysql://nova_api:novaapidbpass@127.0.0.1/nova_api?charset=utf8',
    placement_database_connection => 'mysql+pymysql://nova_placement:novapldbpass@127.0.0.1/nova_placement?charset=utf8',
    rabbit_use_ssl                => $ssl,
    amqp_sasl_mechanisms          => 'PLAIN',
    use_ipv6                      => false,
    glance_api_servers            => "${base_url}:9292",
    debug                         => true,
    notification_driver           => 'messagingv2',
    notify_on_state_change        => 'vm_and_task_state',
    notification_topics           => $notification_topics,
  }
  class { '::nova::api':
    api_bind_address                     => '*',
    neutron_metadata_proxy_shared_secret => 'metadatasharedsecretpass',
    metadata_workers                     => 4,
    sync_db_api                          => true,
    service_name                         => 'httpd',
  }
  include ::apache
  class { '::nova::wsgi::apache_api':
    bind_host => '*',
    ssl_key   => "/etc/nova/ssl/private/${::fqdn}.pem",
    ssl_cert  => '/usr/local/share/ca-certificates/puppet_openstack.crt',
    ssl       => $ssl,
    workers   => '4',
  }
  class { '::nova::placement':
    auth_url => $keystone_auth_uri,
    password => 'novakspass',
  }
  class { '::nova::client': }
  class { '::nova::conductor': }
  class { '::nova::consoleauth': }
  class { '::nova::cron::archive_deleted_rows': }
  class { '::nova::scheduler': }
  class { '::nova::scheduler::filter': }
  class { '::nova::vncproxy': }

  # Neutron
  file { '/etc/neutron/ssl':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File['/etc/neutron/ssl/private'],
    require                 => Package['neutron-common'],
  }

  file { '/etc/neutron/ssl/private':
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
    before                  => File["/etc/neutron/ssl/private/${::fqdn}.pem"],
  }

  file { "/etc/neutron/ssl/private/${::fqdn}.pem":
    ensure                  => present,
    owner                   => 'neutron',
    source                  => "/etc/ssl/private/ssl-cert-snakeoil.key",
    selinux_ignore_defaults => true,
    mode                    => '0600',
    notify                  => Service['httpd'],
  }
  Exec['update-ca-certificates'] ~> Service['neutron-server']

  rabbitmq_user { 'neutron':
    admin    => true,
    password => 'neutronrbpass',
    provider => 'rabbitmqctl',
    require  => Class['::rabbitmq'],
    before   => Anchor['neutron::service::begin'],
  }
  rabbitmq_user_permissions { "neutron@/":
    configure_permission => '.*',
    write_permission     => '.*',
    read_permission      => '.*',
    provider             => 'rabbitmqctl',
    require              => Class['::rabbitmq'],
    before               => Anchor['neutron::service::begin'],
  }

  # Prepare openvswitch bridge
#  include ::vswitch::ovs

}

class cloud_compute {
  if $volume_encryption {
    $keymgr_api_class     = 'castellan.key_manager.barbican_key_manager.BarbicanKeyManager'
    $keymgr_auth_endpoint = "${keystone_auth_uri}/v3"
    $barbican_endpoint    = "${base_url}:9311"
  } else {
    $keymgr_api_class     = undef
    $keymgr_auth_endpoint = undef
    $barbican_endpoint    = undef
  }
  class { '::nova':
    default_transport_url         => os_transport_url({
      'transport' => $om_rpc,
      'host'      => $om_host,
      'port'      => $messaging_default_port,
      'username'  => 'nova',
      'password'  => 'novarbpass',
    }),
    notification_transport_url    => os_transport_url({
      'transport' => $om_notify,
      'host'      => $om_notify_host,
      'port'      => $messaging_notify_port,
      'username'  => 'nova',
      'password'  => 'novarbpass',
    }),
    rabbit_use_ssl                => $ssl,
    amqp_sasl_mechanisms          => 'PLAIN',
    use_ipv6                      => false,
    glance_api_servers            => "${base_url}:9292",
    debug                         => true,
    notification_driver           => 'messagingv2',
    notify_on_state_change        => 'vm_and_task_state',
    notification_topics           => $notification_topics,
  }
  class { '::nova::compute':
    vnc_enabled                 => true,
    instance_usage_audit        => true,
    instance_usage_audit_period => 'hour',
    keymgr_api_class            => $keymgr_api_class,
    barbican_auth_endpoint      => $keymgr_auth_endpoint,
    barbican_endpoint           => $barbican_endpoint,
  }
  class { '::nova::compute::libvirt':
    libvirt_virt_type     => $libvirt_virt_type,
    libvirt_cpu_mode      => $libvirt_cpu_mode,
    migration_support     => true,
    # virtlock and virtlog services resources are not idempotent
    # on Ubuntu, let's disable it for now.
    # https://tickets.puppetlabs.com/browse/PUP-6370
    virtlock_service_name => false,
    virtlog_service_name  => false,
  }

  class { '::nova::network::neutron':
    neutron_auth_url      => "${keystone_admin_uri}/v3",
    neutron_url           => "${base_url}:9696",
    neutron_password      => 'a_big_secret',
    default_floating_pool => 'public',
  }
  class { '::nova::placement':
    enabled        => false,
    ensure_package => absent,
    auth_url       => $keystone_auth_uri,
    password       => 'novakspass',
  }
}

class cloud_volume {
  class { '::cinder':
    default_transport_url => os_transport_url({
      'transport' => $om_rpc,
      'host'      => $om_host,
      'port'      => $messaging_default_port,
      'username'  => 'cinder',
      'password'  => 'cinderrbpass',
    }),
    rabbit_use_ssl       => $ssl,
    amqp_sasl_mechanisms => 'PLAIN',
    debug                => true,
  }
  class { '::cinder::volume':
    volume_clear => 'none',
  }
}

node 'bdbdev1-controller-node-1.infomaniak.ch' {
  include cloud_repo
  include cloud_master
}

node 'bdbdev1-compute-node-1.infomaniak.ch' {
  include cloud_repo
  include cloud_compute
}
