class oci::swiftproxy(
  $region_name                = 'RegionOne',
  $openstack_release          = undef,
  $machine_hostname           = undef,
  $machine_ip                 = undef,
  $first_master               = undef,
  $first_master_ip            = undef,
  $vip_hostname               = undef,
  $vip_ipaddr                 = undef,
  $vip_netmask                = undef,
  $self_signed_api_cert       = true,
  $network_ipaddr             = undef,
  $network_cidr               = undef,
  $all_masters                = undef,
  $all_masters_ip             = undef,
  $all_swiftstore_ip          = undef,
  $all_swiftstore             = undef,
  $all_swiftproxy             = undef,
  $all_swiftproxy_ip          = undef,
  $swiftproxy_hostname        = 'none',
  $swiftregion_id             = undef,
  $statsd_hostname            = undef,
  $monitoring_graphite_host   = undef,
  $monitoring_graphite_port   = undef,
  $pass_swift_authtoken       = undef,
  $pass_swift_hashpathsuffix  = undef,
  $pass_swift_hashpathprefix  = undef,
  $pass_swift_messaging       = undef,
  $swift_encryption_key_id    = undef,
  $max_containers_per_account = 0,
  $max_containers_whitelist   = undef,
  $use_ssl                    = true,
  $swift_disable_encryption   = undef,
  $pass_haproxy_stats         = undef,
  $object_expirer_enable      = false,

  $swift_public_cloud_middlewares = false,

  # These are if we're setting-up account + containers on the proxy hosts
  $swift_object_replicator_concurrency = undef,
  $swift_rsync_connection_limit        = undef,
  $block_devices                       = undef,
  $use_oci_sort_dev           = false,

  $messaging_nodes_for_notifs = false,
  $all_rabbits                = [],
  $all_rabbits_ips            = [],

  $swift_store_account        = false,
  $swift_store_container      = false,
  $swift_store_object         = false,

  $servers_per_port           = 1,
  $network_chunk_size         = 65535,
  $disk_chunk_size            = 524288,
  $bulk_delete_concurrency    = 10,

  $swift_storage_allowed_networks = undef,

  $enable_ceilometer_middleware = false,
  $swift_storage_domain       = undef,
  $no_api_rate_limit_networks = [],
  $swift_proxy_disable_rate_limit  = false,
  $swift_proxy_iptables_rate_limit = 100,
  $swift_proxy_haproxy_rate_limit = 80,
  $swift_proxy_meta_version_to_write = 3,
  $swift_proxy_memcache_max_connections = 20,

  ### Comming from variables.json ###
  # EC policy
  $swift_ec_enable               = false,
  $swift_ec_policy_index         = 1,
  $swift_ec_policy_name          = 'pyeclib-12-4',
  $swift_ec_type                 = 'liberasurecode_rs_vand',
  $swift_ec_num_data_fragments   = 12,
  $swift_ec_num_parity_fragments = 4,
  $swift_ec_object_segment_size  = 1048576,

  $swift_rsync_io_limit_activate  = false,
  $swift_rsync_io_limit_megabytes = 80,
  $swift_rsync_io_limit_iops      = 100,

  $kernel_from_backports    = false,
  $install_telemetry             = true,

  $haproxy_timeout_http_request = '10s',
  $haproxy_timeout_queue        = '1m',
  $haproxy_timeout_connect      = '10s',
  $haproxy_timeout_client       = '1m',
  $haproxy_timeout_server       = '1m',
  $haproxy_timeout_check        = '10s',
){

  if $swift_storage_domain {
    $swift_storage_domain_real = $swift_storage_domain
  }else{
    $swift_storage_domain_real = "${vip_hostname},${swiftproxy_hostname}"
  }

  if $facts['os']['lsb'] != undef{
    $mycodename = $facts['os']['lsb']['distcodename']
  }else{
    $mycodename = $facts['os']['distro']['codename']
  }

  if $mycodename == 'stretch' or $mycodename == 'buster' {
    # This used to work with haproxy 1.8,
    # let's see if we can get rid of it
    $haproxy_replace_path = 'reqrep'
    $haproxy_replace_head = 'rspirep'
    $use_haproxy_21_format = false
  }else{
    # This works with haproxy >= 2.1
    $haproxy_replace_path  = 'http-request replace-path'
    $haproxy_replace_head  = 'http-response replace-header'
    $use_haproxy_21_format = true
  }

  # Generic performances tweak (will default to throughput-performance)
  # class { '::oci::tuned': }

  if $messaging_nodes_for_notifs {
    $notif_rabbit_servers = $all_rabbits
  }else{
    $notif_rabbit_servers = $all_masters
  }

  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}/identity"
  $keystone_admin_uri = "${base_url}/identity"
  $memcached_servers  = ["${machine_ip}:11211"]

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

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

  if $openstack_release == 'rocky' or $openstack_release == 'stein'{
    package { 'python-keystonemiddleware':
      ensure => present,
      notify => Service['swift-proxy'],
    }
  }else{
    package { 'python3-keystonemiddleware':
      ensure => present,
      notify => Service['swift-proxy'],
    }
  }

  class { '::oci::swiftcommon':
    swift_store_account   => $swift_store_account,
    swift_store_container => $swift_store_container,
    swift_store_object    => $swift_store_object,
  }

  # Get memcached
  class { '::memcached':
    listen_ip  => "0.0.0.0",
    udp_port   => 0,
    max_memory => '20%',
    pidfile    => '/var/run/memcached/memcached.pid',
    user       => 'memcache',
  }

  resources { "firewall":
    purge   => true
  }
  class { 'firewall': }

  firewall { '010 accept all icmp':
    proto  => 'icmp',
    action => 'accept',
  }->
  firewall { '011 accept all to lo interface':
    proto   => 'all',
    iniface => 'lo',
    action  => 'accept',
  }->
  firewall { '012 accept related established rules':
    proto  => 'all',
    state  => ['RELATED', 'ESTABLISHED'],
    action => 'accept',
  }->
  firewall { "050 Allow memcached on $machine_ip TCP":
    proto       => tcp,
    action      => accept,
    destination => "$machine_ip",
    dport       => '11211',
  }->
  firewall { "051 Allow memcached on 127.0.0.1 TCP":
    proto       => tcp,
    action      => accept,
    destination => "127.0.0.1",
    dport       => '11211',
  }->
  firewall { "052 Drop memcached on public TCP":
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '11211',
  }->
  firewall { "053 Allow memcached on $machine_ip UDP":
    proto       => udp,
    action      => accept,
    destination => "${machine_ip}",
    dport       => '11211',
  }->
  firewall { "054 Allow memcached on 127.0.0.1 UDP":
    proto       => udp,
    action      => accept,
    destination => "127.0.0.1",
    dport       => '11211',
  }->
  firewall { "055 Drop memcached on public UDP":
    proto       => udp,
    jump        => 'LOGDROP',
    dport       => '11211',
  }->
  firewall { "056 Allow SMTP on 127.0.0.1 TCP":
    proto       => tcp,
    action      => accept,
    destination => "127.0.0.1",
    dport       => '25',
  }->
  firewall { "057 Allow SMTP from ${machine_ip} to ${machine_ip} TCP":
    proto       => tcp,
    action      => accept,
    source      => "${machine_ip}",
    destination => "${machine_ip}",
    dport       => '25',
  }->
  firewall { '058 Jump to LOGDROP for SMTP':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '25',
  }->
  firewall { '059 Jump to LOGDROP for RPCBIND':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '111',
  }->
  firewall { '059 Jump to LOGDROP for RPCBIND UDP':
    proto       => udp,
    jump        => 'LOGDROP',
    dport       => '111',
  }

  $swift_storage_allowed_networks.each |Integer $index, String $value| {
    $val1 = $index*4+100
    $val2 = $index*4+101
    $val3 = $index*4+102
    $val4 = $index*4+103
    firewall { "${val1} Allow ${value} to access to swift container and account servers":
      proto       => tcp,
      action      => accept,
      source      => "${value}",
      dport       => '6001-6002',
    }->
    firewall { "${val2} Allow ${value} to access to swift object servers":
      proto       => tcp,
      action      => accept,
      source      => "${value}",
      dport       => '6200-6229',
    }->
    firewall { "${val3} Allow ${value} to access rsync":
      proto       => tcp,
      action      => accept,
      source      => "${value}",
      dport       => '873',
    }->
    firewall { "${val4} Allow ${value} to access 8080":
      proto       => tcp,
      action      => accept,
      source      => "${value}",
      dport       => '8080',
    }
  }

  firewall { '801 Jump to LOGDROP for container and account servers':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '6001-6002',
  }

  firewall { '802 Jump to LOGDROP for object servers':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '6200-6229',
  }

  firewall { '803 Jump to LOGDROP for rsync':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '873',
  }

  firewall { '804 Jump to LOGDROP for SMTP':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '25',
  }

  firewall { '805 Jump to LOGDROP for RPCBIND':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '111',
  }

  firewall { '806 Jump to LOGDROP for RPCBIND UDP':
    proto       => udp,
    jump        => 'LOGDROP',
    dport       => '111',
  }

  firewall { '807 Jump to LOGDROP for BGP':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => [179, 2159],
  }

  firewall { '808 Jump to LOGDROP for xinetd':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '9200',
  }

  firewall { '809 Jump to LOGDROP for 8080':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '8080',
  }

  firewallchain { 'LOGDROP:filter:IPv4':
    ensure  => present,
  }

  firewall { '901 LOG rule for dropped packets':
    chain       => 'LOGDROP',
    proto       => tcp,
    jump        => 'LOG',
    log_level   => '6',
    log_prefix  => 'swift dropped packet',
    limit       => '1/sec',
  }
  firewall { "902 Deny all access to container and account server":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '6001-6002',
  }
  firewall { "903 Deny all access to object server":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '6200-6229',
  }
  firewall { '904 Deny all access to rsync':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '873',
  }
  firewall { '905 Deny all access to SMTP':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '25',
  }
  firewall { '906 Deny all access to RPCBIND':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '111',
  }
  firewall { '907 Deny all access to RPCBIND UDP':
    chain       => 'LOGDROP',
    proto       => udp,
    action      => reject,
    dport       => '111',
  }
  firewall { '908 Deny all access to BGP':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [179, 2159],
  }
  firewall { '909 Deny all access to memcached':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '11211',
  }
  firewall { '910 Deny all access to xinetd':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '9200',
  }
  firewall { '911 Deny all access to swiftproxy without haproxy':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '8080',
  }
  firewall { '912 Deny all access to BGP':
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '179',
  }

  $net_whitelist = concat($no_api_rate_limit_networks, $vip_ipaddr)

  if $swift_proxy_disable_rate_limit {
    firewall { "791 rate limit to ${swift_proxy_iptables_rate_limit} queries/s marked new":
      ensure          => absent,
      chain           => 'INPUT',
      dport           => 443,
      proto           => tcp,
      connlimit_above => $swift_proxy_iptables_rate_limit,
      connlimit_mask  => 24,
      jump            => 'LOGDROP',
    }
  }else{
    firewall { "791 rate limit to ${swift_proxy_iptables_rate_limit} queries/s marked new":
      chain           => 'INPUT',
      dport           => 443,
      proto           => tcp,
      connlimit_above => $swift_proxy_iptables_rate_limit,
      connlimit_mask  => 24,
      jump            => 'LOGDROP',
    }
  }

  if $swiftproxy_hostname == "none" {
    debug("OCI will *NOT* setup a swiftproxy direct access.")
  } else {
    debug("OCI now setting-up a swiftproxy direct access.")
    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-swiftproxy.pem":
        ensure                  => present,
        owner                   => "haproxy",
        source                  => "/etc/ssl/private/oci-pki-swiftproxy.pem",
        selinux_ignore_defaults => true,
        mode                    => '0600',
        notify                  => Service['haproxy'],
      }
    }

    class { 'haproxy':
      global_options   => {
        'tune.bufsize' =>  '32768',
        'log'      => '/dev/log local0',
        'chroot'  => '/var/lib/haproxy',
        'pidfile' => '/var/run/haproxy.pid',
        'maxconn'  => '40960',
        'user'     => 'haproxy',
        'group'    => 'haproxy',
        'daemon'   => '',
        'stats'   => 'socket /var/lib/haproxy/stats',
        'nbthread' => '8',
        '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',
      },
      defaults_options => {
        'log'     => 'global',
        'mode'    => 'http',
        'retries' => '3',
        'maxconn' => '40960',
        'timeout' => [
          "http-request ${haproxy_timeout_http_request}",
          "queue ${haproxy_timeout_queue}",
          "connect ${haproxy_timeout_connect}",
          "client ${haproxy_timeout_client}",
          "server ${haproxy_timeout_server}",
          "check ${haproxy_timeout_check}",
        ],
        'option'  => [
          'httplog',
          'logasap',
         ],
      },
      merge_options => false,
    }->
    haproxy::listen { 'hapstats':
      section_name => 'statshttp',
      bind         => { "${machine_ip}:8088" => 'user root'},
      mode         => 'http',
      options      => {
          'stats' => [ 'uri /', "auth admin:${pass_haproxy_stats}", 'refresh 15', 'admin if TRUE', 'realm Haproxy Statistics', ],
        },
    }

    $swift_proxy_haproxy_rate_limit_real = $swift_proxy_haproxy_rate_limit * 10

    # Global frontend for all services with dispatch depending on the URL
    if $swift_proxy_disable_rate_limit {
      haproxy::frontend { 'openstackfe':
        mode      => 'http',
        bind      => { "0.0.0.0:${api_port}" => ['ssl', 'crt', '/etc/haproxy/ssl/private/oci-pki-swiftproxy.pem', 'crt', '/etc/haproxy/ssl/private/'] },
        options   => [
          { 'acl'         => 'url_swift path_beg -i /object'},
          { 'use_backend' => 'swiftbe if url_swift'},
          { 'use_backend' => 'swiftbe_always'},
          # Set HSTS (63072000 seconds = 2 years)
          { 'http-response' => 'set-header Strict-Transport-Security max-age=63072000'},
          { 'option'      => [
              'httplog',
              'logasap',
            ],
          }
        ]
      }
    } else {
      $haproxy_network_whitelist = $net_whitelist.join(' ')
      haproxy::frontend { 'openstackfe':
        mode      => 'http',
        bind      => { "0.0.0.0:${api_port}" => ['ssl', 'crt', '/etc/haproxy/ssl/private/oci-pki-swiftproxy.pem', 'crt', '/etc/haproxy/ssl/private/'] },
        options   => [
          {'acl'          => "network_allowed src ${haproxy_network_whitelist}"},
          {'stick-table'  => 'type ip size 10k expire 30s store http_req_rate(10s)'},
          {'http-request' => 'track-sc0 src'},
          {'http-request' => "deny deny_status 429 if { sc_http_req_rate(0) gt ${swift_proxy_haproxy_rate_limit_real} } !network_allowed"},
          { 'acl'         => 'url_swift path_beg -i /object'},
          { 'use_backend' => 'swiftbe if url_swift'},
          { 'use_backend' => 'swiftbe_always'},
          # Set HSTS (63072000 seconds = 2 years)
          { 'http-response' => 'set-header Strict-Transport-Security max-age=63072000'},
          { 'option'      => [
              'httplog',
              'logasap',
            ],
          }
        ]
      }
    }

    # This backend + backend-member is for the /object version, as
    # advertized in our endpoints.
    if $use_haproxy_21_format {
      $tweak_path_object = '^/object/?(.*) /\1'
    }else{
      $tweak_path_object = '^([^\ ]*\ /)object[/]?(.*)     \1\2'
    }
    haproxy::backend { 'swiftbe':
      options => [
         { 'option'              => 'httpchk GET /healthcheck' },
         { 'option'              => 'forwardfor' },
         { 'mode'                => 'http' },
         { 'balance'             => 'source' },
         { $haproxy_replace_path => $tweak_path_object},
      ],
    }

    haproxy::balancermember { 'swiftbm':
      listening_service => 'swiftbe',
      ipaddresses       => [ $machine_ip ],
      server_names      => [ $machine_hostname ],
      ports             => 8080,
      options           => 'check',
    }

    $other_swift_proxies = $all_swiftproxy - $machine_hostname
    $other_swift_proxies_ip = $all_swiftproxy_ip - $machine_ip
    haproxy::balancermember { 'swiftbmbackup':
      listening_service => 'swiftbe',
      ipaddresses       => $other_swift_proxies_ip,
      server_names      => $other_swift_proxies,
      ports             => 8080,
      options           => "check backup",
    }

    # This backend + backend-member is for without the /object version, as
    # per what will S3 clients use.
    haproxy::backend { 'swiftbe_always':
      options => [
         { 'option' => 'httpchk GET /healthcheck' },
         { 'option' => 'forwardfor' },
         { 'mode' => 'http' },
         { 'balance' => 'source' },
      ],
    }

    haproxy::balancermember { 'swiftbm_always':
      listening_service => 'swiftbe_always',
      ipaddresses       => [ $machine_ip ],
      server_names      => [ $machine_hostname ],
      ports             => 8080,
      options           => 'check',
    }
    # Other swift if the local machine one fails.
    haproxy::balancermember { 'swiftbm_alwaysbackup':
      listening_service => 'swiftbe_always',
      ipaddresses       => $other_swift_proxies_ip,
      server_names      => $other_swift_proxies,
      ports             => 8080,
      options           => "check backup",
    }
  }


  class { '::swift':
    swift_hash_path_suffix => $pass_swift_hashpathsuffix,
    swift_hash_path_prefix => $pass_swift_hashpathprefix,
  }

  class { '::swift::proxy::s3api':
    max_upload_part_num => 10000,
  }
  class { 'swift::proxy::s3token':
    secret_cache_duration => "30",
    auth_uri => "${keystone_auth_uri}/v3",
    auth_url => "${keystone_auth_uri}/v3",
    username  => "swift",
    password  => "$pass_swift_authtoken",
    project_name  => 'services',
  }

  if $enable_ceilometer_middleware and $install_telemetry {
    file { '/etc/swift/swift-proxy.enviroment':
      ensure                  => present,
      owner                   => 'root',
      content                 => "OS_OSLO_MESSAGING_RABBIT__SSL=${use_ssl}
OS_OSLO_MESSAGING_RABBIT__SSL_CA_FILE=/etc/ssl/certs/oci-pki-oci-ca-chain.pem
OS_OSLO_MESSAGING_NOTIFICATIONS__DRIVER=messagingv2
OS_OSLO_MESSAGING_NOTIFICATIONS__SSL_CA_FILE=/etc/ssl/certs/oci-pki-oci-ca-chain.pem
",
      selinux_ignore_defaults => true,
      mode                    => '0640',
      require                 => Package['swift-proxy'],
    }->
    systemd::dropin_file { 'swift-proxy-enviroment-file.conf':
      unit    => 'swift-proxy.service',
      notify  => Service['swift-proxy'],
      content => "[Service]
EnvironmentFile=/etc/swift/swift-proxy.enviroment",
    }

    group { 'ceilometer':
      ensure => present,
    }->
    class { '::swift::proxy::ceilometer':
      default_transport_url    => os_transport_url({
                                   'transport' => $messaging_notify_proto,
                                   'hosts'     => fqdn_rotate($notif_rabbit_servers),
                                   'port'      => $messaging_notify_port,
                                   'username'  => 'swift',
                                   'password'  => $pass_swift_messaging,
                                 }),
      driver                   => 'messagingv2',
      nonblocking_notify       => true,
      auth_url                 => "${keystone_auth_uri}/v3",
      password                 => $pass_swift_authtoken,
      region_name              => $cluster_region_name,
# Looks like ceilometermiddleware doesn't support SSL with a root_ca file.
# Need that patch to support it correctly:
# https://salsa.debian.org/openstack-team/libs/python-ceilometermiddleware/-/blob/debian/wallaby/debian/patches/rabbit-over-ssl.patch
      notification_ssl_ca_file => '/etc/ssl/certs/oci-pki-oci-ca-chain.pem',
      rabbit_use_ssl           => $use_ssl,
    }
    $pipeline_ceilometer = [ 'ceilometer' ]
  }else{
    $pipeline_ceilometer = []
  }

  # Because there's no ca_file option in castellan, we must
  # allow swiftproxy to run without encryption  in case we're
  # running on a PoC without a real certificate for the API
  if($swift_disable_encryption =='yes' or $swift_encryption_key_id == ''){
    $disable_encryption = true
  }

  if $swift_public_cloud_middlewares {
    $pipeline_tempurl = [ 'tempurl' ]
    $pipeline_symlink = [ 'symlink' ]
    $pipeline_staticweb = [ 'staticweb' ]
    $pipeline_crossdomain = [ 'crossdomain' ]
    $pipeline_domain_remap = [ 'domain_remap' ]
    $pipeline_cname_lookup = [ 'cname_lookup' ]
    class { '::swift::proxy::tempurl':
      methods => [ 'GET', 'HEAD', 'PUT', 'POST', 'DELETE', ],
      incoming_remove_headers => 'x-timestamp-*',
    }
    swift_proxy_config {
      'filter:tempurl/path_prefix': value => '/object';
    }
    class { '::swift::proxy::staticweb': }
    if ($openstack_release != 'rocky' and $openstack_release != 'stein' and $openstack_release != 'train' and $openstack_release != 'ussuri') {
      class { '::swift::proxy::symlink': }
    }
    class { '::swift::proxy::crossdomain': }
    class { '::swift::proxy::domain_remap':
      storage_domain => $swift_storage_domain_real,
      default_reseller_prefix => 'AUTH',
    }
    class { '::swift::proxy::cname_lookup':
      storage_domain => $swift_storage_domain_real,
    }
  }else{
    class { '::swift::proxy::symlink': }
    $pipeline_tempurl = [ ]
    $pipeline_symlink = [ 'symlink' ]
    $pipeline_staticweb = [ ]
    $pipeline_crossdomain = [ ]
    $pipeline_domain_remap = [ ]
    $pipeline_cname_lookup = [ ]
    swift_proxy_config {
        'filter:versioned_writes/allow_object_versioning': value => 'True';
    }
  }

  class { '::swift::proxy::gatekeeper': }

  $pipeline_start = concat(['catch_errors', 'gatekeeper', 'healthcheck', 'proxy-logging', 'cache'], $pipeline_cname_lookup, $pipeline_domain_remap, ['container_sync', 'bulk'], $pipeline_tempurl, ['ratelimit'], $pipeline_crossdomain, ['authtoken', 's3api', 's3token', 'keystone'], $pipeline_staticweb, ['copy', 'container-quotas', 'account-quotas', 'slo', 'dlo', 'versioned_writes' ], $pipeline_symlink)

  if $swift_encryption_key_id == "" {
    $pipeline_kms = $pipeline_start
  } else {
    $pipeline_kms = concat($pipeline_start, [ 'kms_keymaster', 'encryption' ])
  }
  $pipeline_with_kms = concat($pipeline_kms, [ 'proxy-logging', 'proxy-server' ])

  $pipeline = concat($pipeline_ceilometer, $pipeline_with_kms)

  if $openstack_release == 'rocky' or $openstack_release == 'stein'{
    package { 'barbicanclient':
      name   => 'python-barbicanclient',
      ensure => installed,
    }->
    package { 'castellan':
      name   => 'python3-castellan',
      ensure => installed,
    }->
    class { '::swift::proxy':
      proxy_local_net_ip         => $machine_ip,
      port                       => '8080',
      account_autocreate         => true,
      pipeline                   => $pipeline,
      node_timeout               => 50,
  #    read_affinity              => "r${swiftregion_id}=100",
  #    write_affinity             => "r${swiftregion_id}",
      max_containers_per_account => $max_containers_per_account,
      max_containers_whitelist   => $max_containers_whitelist,
      workers                    => 20,
      client_timeout             => 340,
    }
  }else{
    package { 'barbicanclient':
      name   => 'python3-barbicanclient',
      ensure => installed,
    }->
    package { 'castellan':
      name   => 'python3-castellan',
      ensure => installed,
    }->
    class { '::swift::proxy':
      proxy_local_net_ip         => $machine_ip,
      port                       => '8080',
      account_autocreate         => true,
      pipeline                   => $pipeline,
      node_timeout               => 50,
  #    read_affinity              => "r${swiftregion_id}=100",
  #    write_affinity             => "r${swiftregion_id}",
      max_containers_per_account => $max_containers_per_account,
      max_containers_whitelist   => $max_containers_whitelist,
      workers                    => 20,
      client_timeout             => 340,
    }
  }
  swift_config {
    'swift-constraints/container_listing_limit': value => '100000';
  }
  swift_proxy_config {
    'app:proxy-server/conn_timeout': value               => '2';
    'app:proxy-server/error_suppression_interval': value => '1800';
    'app:proxy-server/error_suppression_limit': value    => '2';
    'DEFAULT/max_clients':           value               => '2048';
  }
  swift_proxy_uwsgi_config {
    'uwsgi/disable-logging': value => true;
  }
  include ::swift::proxy::catch_errors
  include ::swift::proxy::healthcheck
  include ::swift::proxy::kms_keymaster
  class { '::swift::proxy::encryption':
    disable_encryption => $disable_encryption,
  }
  class { '::swift::proxy::cache':
    memcache_servers => $memcached_servers,
    memcache_max_connections => $swift_proxy_memcache_max_connections,
  }
  include ::swift::proxy::encryption
  include ::swift::proxy::proxy_logging
  include ::swift::proxy::container_sync
  if $openstack_release == 'rocky' or $openstack_release == 'stein' or $openstack_release == 'train' or $openstack_release == 'ussuri' or $openstack_release == 'victoria' or $openstack_release == 'wallaby' or $openstack_release == 'xena' or $openstack_release == 'yoga'{
    include ::swift::proxy::bulk
    swift_proxy_config {
      'filter:bulk/delete_concurrency': value => $bulk_delete_concurrency;
    }
  }else{
    class { '::swift::proxy::bulk':
      delete_concurrency => $bulk_delete_concurrency,
    }
  }
  include ::swift::proxy::ratelimit
  include ::swift::proxy::keystone
  include ::swift::proxy::copy
  include ::swift::proxy::container_quotas
  include ::swift::proxy::account_quotas
  class { '::swift::proxy::slo':
    max_manifest_segments => '10000',
  }
  class { '::swift::proxy::dlo':
    rate_limit_segments_per_sec => '0',
  }

  class { '::swift::proxy::versioned_writes':
    allow_versioned_writes => true,
  }

  if ($openstack_release == 'rocky' or $openstack_release == 'stein' or $openstack_release == 'train' or $openstack_release == 'ussuri') {
    class { '::swift::proxy::authtoken':
      auth_uri                => "${keystone_auth_uri}/v3",
      auth_url                => "${keystone_auth_uri}/v3",
      password                => $pass_swift_authtoken,
      delay_auth_decision     => 'True',
      cache                   => 'swift.cache',
      include_service_catalog => 'False',
    }
  }else{
    class { '::swift::proxy::authtoken':
      www_authenticate_uri    => "${keystone_auth_uri}/v3",
      auth_url                => "${keystone_auth_uri}/v3",
      password                => $pass_swift_authtoken,
      delay_auth_decision     => 'True',
      cache                   => 'swift.cache',
      include_service_catalog => 'False',
    }
  }

  if $statsd_hostname == ''{
    swift_proxy_config {
      'filter:authtoken/cafile': value => $api_endpoint_ca_file;
    }
  } else {
    swift_proxy_config {
      'filter:authtoken/cafile':          value => $api_endpoint_ca_file;
      'DEFAULT/log_statsd_host':          value => $statsd_hostname;
      'DEFAULT/log_statsd_metric_prefix': value => $machine_hostname;
    }
  }

  if $statsd_hostname == '' and $monitoring_graphite_host == ''{
    notice("Please defile statsd_hostname and monitoring_graphite_host to enable Collectd")
  }else{
    # Collected
    class { '::collectd':
      purge           => true,
      recurse         => true,
      purge_config    => true,
      minimum_version => '5.4',
    }
    class { 'collectd::plugin::statsd':
      host            => '127.0.0.1',
      port            => 8125,
      timersum        => 'true',
      timercount      => 'true',
    }
    collectd::plugin::write_graphite::carbon { "${monitoring_graphite_host}-carbon":
      graphitehost   => $monitoring_graphite_host,
      graphiteport   => 2003,
      protocol       => 'tcp'
    }
  }

  class { '::swift::keymaster':
    api_class             => 'barbican',
    key_id                => $swift_encryption_key_id,
    password              => $pass_swift_authtoken,
    auth_endpoint         => "${keystone_auth_uri}/v3",
    project_name          => 'services',
    meta_version_to_write => $swift_proxy_meta_version_to_write,
  }

  # We setup *one* object-expirer per cluster
  if $object_expirer_enable {
    class { 'swift::objectexpirer':
      pipeline         => ['catch_errors', 'cache', 'proxy-server'],
      memcache_servers => $memcached_servers,
    }
  }else{
    package { 'swift-object-expirer':
      ensure => absent,
    }
  }
  if $swift_store_account or $swift_store_container or $swift_store_object{
    if $statsd_hostname == ''{
      $statsd_enabled = false
    } else {
      $statsd_enabled = true
    }

    if $swift_rsync_io_limit_activate {
      package { 'cgroup-tools':
        ensure => present,
      }
      ::systemd::dropin_file {'io-limit-slice.conf':
        unit    => 'rsync.service',
        content => '[Service]
Slice=rsync.slice
IOSchedulingClass=best-effort
IOSchedulingPriority=7',
        notify  => Service['rsync'],
      }->
      ::systemd::unit_file {'rsync.slice':
        content => "[Slice]
IOAccounting=1
IOWriteBandwidthMax=/srv/node/sda ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdb ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdc ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdd ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sde ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdf ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdg ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdh ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdi ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdj ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdk ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdl ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdm ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdn ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdo ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdp ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdq ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdr ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sds ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdt ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdu ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdv ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdw ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdx ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdy ${swift_rsync_io_limit_megabytes}M
IOWriteBandwidthMax=/srv/node/sdz ${swift_rsync_io_limit_megabytes}M
IOWriteIOPSMax=/srv/node/sda ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdb ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdc ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdd ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sde ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdf ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdg ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdh ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdi ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdj ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdk ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdl ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdm ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdn ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdo ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdp ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdq ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdr ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sds ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdt ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdu ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdv ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdw ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdx ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdy ${swift_rsync_io_limit_iops}
IOWriteIOPSMax=/srv/node/sdz ${swift_rsync_io_limit_iops}
  ",
        notify  => Service['rsync'],
      }
      file {'/etc/xinetd.d/rsync':
        ensure => absent,
        notify => Service['rsync'],
      }->
      exec {'reload-xinetd':
        command => '/usr/bin/systemctl restart xinetd.service',
        onlyif  => "/usr/bin/ss -ltne | grep ${machine_ip}:873 | grep -q xinetd.service",
        notify  => Service['rsync'],
      }->
      class { '::swift::storage':
        storage_local_net_ip => $machine_ip,
        rsync_use_xinetd     => false,
        require              => Systemd::Unit_file['rsync.slice'],
      }
    }else{
      file {'/etc/systemd/system/rsync.slice':
        ensure => absent,
        notify => Service['rsync'],
      }->
      file {'/etc/systemd/system/rsync.service.d/io-limit-slice.conf':
        ensure => absent,
        notify => Service['rsync'],
      }->
      file {'/etc/xinetd.d/rsync':
        ensure => absent,
        notify => Service['rsync'],
      }->
      exec {'reload-xinetd':
        command => '/usr/bin/systemctl restart xinetd.service',
        onlyif  => "/usr/bin/ss -ltne | grep ${machine_ip}:873 | grep -q xinetd.service",
      }->
      class { '::swift::storage':
        storage_local_net_ip => $machine_ip,
        rsync_use_xinetd     => false,
      }
    }

    if $swift_store_container {
      include swift::storage::container

      # This must be manually called, as otherwise, $memcache_servers is wrong
      # Currently desactivated, because it overwrites all of the file, but to
      # be done at some point...
#      class { '::swift::containerreconciler':
#        memcache_servers => $memcached_servers,
#      }
    }
    if $swift_store_account {
      include swift::storage::account
    }
    if $swift_store_object {
      include swift::storage::object
    }

    if $swift_store_account {
      swift::storage::server { '6002':
        type                     => 'account',
        devices                  => '/srv/node',
        rsync_module_per_device  => true,
        device_names             => $block_devices,
        config_file_path         => 'account-server.conf',
        storage_local_net_ip     => "${machine_ip}",
        pipeline                 => ['healthcheck', 'recon', 'account-server'],
        max_connections          => $swift_rsync_connection_limit,
        statsd_enabled           => $statsd_enabled,
        log_statsd_host          => $statsd_hostname,
        log_statsd_metric_prefix => $machine_hostname,
      }
      swift_account_uwsgi_config {
        'uwsgi/disable-logging': value => true;
      }
    }else{
      package { 'swift-account':
        ensure => absent,
      }
    }

    if $swift_store_container {
      swift::storage::server { '6001':
        type                     => 'container',
        devices                  => '/srv/node',
        rsync_module_per_device  => true,
        device_names             => $block_devices,
        config_file_path         => 'container-server.conf',
        storage_local_net_ip     => "${machine_ip}",
        pipeline                 => ['healthcheck', 'recon', 'container-server'],
        max_connections          => $swift_rsync_connection_limit,
        statsd_enabled           => $statsd_enabled,
        log_statsd_host          => $statsd_hostname,
        log_statsd_metric_prefix => $machine_hostname,
      }
      swift_container_config {
        'container-replicator/node_timeout': value => 120;
      }
      swift_container_uwsgi_config {
        'uwsgi/disable-logging': value => true;
      }
    }else{
      package { 'swift-container':
        ensure => absent,
      }
    }

    if $swift_store_object {
      swift::storage::server { '6200':
        type                     => 'object',
        devices                  => '/srv/node',
        rsync_module_per_device  => true,
        device_names             => $block_devices,
        config_file_path         => 'object-server.conf',
        storage_local_net_ip     => "${machine_ip}",
        pipeline                 => ['healthcheck', 'recon', 'object-server'],
        max_connections          => $swift_rsync_connection_limit,
        servers_per_port         => $servers_per_port,
        replicator_concurrency   => $swift_object_replicator_concurrency,
        statsd_enabled           => $statsd_enabled,
        log_statsd_host          => $statsd_hostname,
        log_statsd_metric_prefix => $machine_hostname,
        network_chunk_size       => $network_chunk_size,
        disk_chunk_size          => $disk_chunk_size,
      }
    }else{
      package { 'swift-object':
        ensure => absent,
      }
    }

    # With this, we use the OCI's udev rule to order drives
    if $use_oci_sort_dev {
      $base_dir = '/dev/disk/oci-sort'
    }else{
      $base_dir = '/dev'
    }

    $block_devices.each |Integer $index, String $value| {
      swift::storage::disk { "${value}":
        base_dir          => $base_dir,
        mount_type        => 'uuid',
        require           => Class['swift'],
        manage_partition  => false,
        manage_filesystem => false,
      }
    }

    if $swift_ec_enable {
      swift::storage::policy { "${swift_ec_policy_index}":
        policy_name             => $swift_ec_policy_name,
        default_policy          => false,
        policy_type             => 'erasure_coding',
        ec_type                 => $swift_ec_type,
        ec_num_data_fragments   => $swift_ec_num_data_fragments,
        ec_num_parity_fragments => $swift_ec_num_parity_fragments,
        ec_object_segment_size  => $swift_ec_object_segment_size,
      }
    }

    # update Rsyslog HAProxy priority to avoid log mess between HAProxy & Swift proxy
    exec { 'move-haproxy-rsyslog-priority':
      command => 'cp /etc/rsyslog.d/49-haproxy.conf /etc/rsyslog.d/15-haproxy.conf',
      onlyif  => 'test -e /etc/rsyslog.d/49-haproxy.conf',
      creates => '/etc/rsyslog.d/15-haproxy.conf',
      path    => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
    }

    exec { 'remove-default-configuration':
      command => 'rm /etc/rsyslog.d/49-haproxy.conf',
      onlyif  => 'test -e /etc/rsyslog.d/49-haproxy.conf',
      path    => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
      notify  => Service['rsyslog'],
    }

    if $swift_store_account {
      $rings1 = [ 'account' ]
    }else{
      $rings1 = [ ]
    }
    if $swift_store_object {
      $rings2 = concat($rings1, ['object'])
    }else{
      $rings2 = $rings1
    }
    if $swift_store_container {
      $rings3 = concat($rings2, ['container'])
    }else{
      $rings3 = $rings2
    }
    swift::storage::filter::recon { $rings3: }
    swift::storage::filter::healthcheck { $rings3: }
  }else{
    package { 'swift-drive-audit':
      ensure => absent,
    }
    package { 'swift-account':
      ensure => absent,
    }
    package { 'swift-container':
      ensure => absent,
    }
    package { 'swift-object':
      ensure => absent,
    }
  }
}
