class oci::swiftstore(
  $machine_hostname          = undef,
  $machine_ip                = undef,
  $network_ipaddr            = undef,
  $network_cidr              = undef,
  $block_devices             = undef,
  $statsd_hostname           = undef,
  $pass_swift_hashpathsuffix = undef,
  $pass_swift_hashpathprefix = undef,
  $zoneid                    = undef,
  $use_ssl                   = true,
  $all_swiftstore_ip         = undef,
  $all_swiftstore            = undef,
  $all_swiftproxy            = undef,
  $all_swiftproxy_ip         = undef,
  $monitoring_host           = undef,
  $monitoring_graphite_host  = undef,
  $monitoring_graphite_port  = undef,
  $swift_object_replicator_concurrency = 5,
  $swift_rsync_connection_limit        = 25,
  $self_signed_api_cert      = true,

  $swift_store_account       = true,
  $swift_store_container     = true,
  $swift_store_object        = true,

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

  $swift_storage_allowed_networks = undef,
){

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

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

  # rsyslog correctly
  package { 'rsyslog':
    ensure => present,
  }
  service { 'rsyslog':
    ensure  => running,
    enable  => true,
    require => Package['rsyslog'],
  }

  file { '/var/log/swift':
    ensure => directory,
    mode   => '0750',
  }

  file { "/etc/systemd/system/local-fs.target.d":
    ensure                  => directory,
    owner                   => 'root',
    mode                    => '0755',
    selinux_ignore_defaults => true,
  }

  $str = "# Clear OnFailure= (set it to nothing)
# so the server continues to boot on mount failures
[Unit]
OnFailure=
"

  file { "/etc/systemd/system/local-fs.target.d/nofail.conf":
    ensure                  => present,
    owner                   => 'root',
    mode                    => '0644',
    content                 => $str,
    selinux_ignore_defaults => true,
  }

  file { '/etc/rsyslog.d/10-swift.conf':
    ensure  => present,
    source  => "puppet:///modules/${module_name}/rsyslog-swift.conf",
    require => [Package['rsyslog'], File['/var/log/swift']],
    notify  => Service['rsyslog'],
  }

  File<| title == '/var/log/swift' |> {
    owner => 'swift',
    group => 'adm'
  }

  # Install memcache
  class { '::memcached':
    listen_ip => '127.0.0.1',
    udp_port  => 0,
    max_memory => '20%',
  }

  # Fireall object, account and container servers,
  # so that only our management network has access to it.
  # First, general definirion (could be in global site.pp)
  resources { "firewall":
    purge   => true
  }
  class { 'firewall': }

  $all_allowed_ips = concat($all_swiftproxy_ip, $all_swiftstore_ip)

  $swift_storage_allowed_networks.each |Integer $index, String $value| {
    $val1 = $index*2+100
    $val2 = $index*2+101
    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 { '801 Jump to LOGDROP for container and account servers':
    proto       => tcp,
    jump        => 'LOGDROP',
    dport       => '6001-6002',
  }

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

  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',
  }

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

  class { '::swift::storage':
    storage_local_net_ip => $machine_ip,
  }
  if $swift_store_container {
    include swift::storage::container
  }
  if $swift_store_account {
    include swift::storage::account
  }
  if $swift_store_object {
    include swift::storage::object
  }

  if $statsd_hostname == ''{
    $statsd_enabled = false
  } else {
    $statsd_enabled = true
  }

  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'
    }
  }

  if $swift_store_account {
    swift::storage::server { '6002':
      type                 => 'account',
      devices              => '/srv/node',
      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,
    }
  }else{
    package { 'swift-account':
      ensure => absent,
    }
  }

  if $swift_store_container {
    swift::storage::server { '6001':
      type                 => 'container',
      devices              => '/srv/node',
      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,
    }
  }else{
    package { 'swift-container':
      ensure => absent,
    }
  }

  if $swift_store_object {
    swift::storage::server { '6200':
      type                   => 'object',
      devices                => '/srv/node',
      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,
      object_server_mb_per_sync => 16,
      client_timeout            => 345,
    }
  }else{
    package { 'swift-object':
      ensure => absent,
    }
  }

  $block_devices.each |Integer $index, String $value| {
    swift::storage::disk { "${value}":
      mount_type => 'uuid',
      require    => Class['swift'],
    }->
    exec { "fix-unix-right-of-${value}":
      path    => "/bin",
      command => "chown swift:swift /srv/node/${value}",
      unless  => "cat /proc/mounts | grep -E ^/dev/${value}",
    }
  }

  package { 'swift-drive-audit':
    ensure => present,
  }

  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: }

  Swift::Ringsync<<||>>
}
