Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
init.pp 11.83 KiB
# This class is meant to install all you need to have your dirac server
# It manages both the dirac.cfg and the bashrc
#
# For the time being, quite a few assumptions are still hardcoded:
#   * installation path is /opt/dirac
#   * expects all the CA/fetch-crl RPMs are installed (https://wiki.nikhef.nl/grid/FetchCRL3, https://gitlab.cern.ch/ai/it-puppet-module-fetchcrl)
#   * requires a cron job to generate a bundle out of all the CAs
#
# @param dirac_user linux user of the dirac account (default:dirac)
# @param dirac_group linux group of the dirac account (default:dirac)
# @param master_cs boolean, if true, will install the server as a master CS (default: false)
#                  This is used inside the configuration files generated
# @param master_config_name Name of the configuration if the server is configured as a master CS
# @param webportal boolean, if true, will install the server as a web portal (default: false)
#                  This will add both WebApp to the list of extensions, but also setup nginx
# @param extensions list of extensions you want to install (e.g. LHCb)
# @param web_extensions list of Web extensions you want to install (e.g. LHCbWeb)
#
# @param dirac_tpl_path parameter to generate the dirac.cfg file
# @param web_tpl_path parameter to generate the site.conf used by nginx
# @param nginx_tpl_path parameter to generate the nginx conf used by nginx
# @param install_tpl_path parameter to generate the install.cfg file
#                         This file is a bootstrap file to install a new server (install_site.sh)
#                         (with the system administrator).
#                         Important: while running install_site.sh, you should remove the existing
#                         dirac.cfg
#
# @param teigi_keys list of keys that are used in the templates
# @param dirac_config_args dictionnary that can be used in the templates (e.g.  <%= @dirac_config_args['vo'] %>)
#
# @param logstash_server: install a logstash server
# @param logstash_config_args: dictionnary that can be used in the lostash templates (e.g. <%= logstash_config_args['mb_brokers'] %>)
# @param oracle_support: if set to true, ensures that the oracle RPM client libraries are installed
# @param tornado_processes: number of prcesses tornado is going to spown if the web app is used
#
#
# Although some parameters (like master_cs, master_config_name, extensions*, etc) could be part of the config_args,
# they are not.


class dirac ($dirac_user = 'dirac', $dirac_group = 'dirac',
            $master_cs = false, $master_config_name = false,
            $webportal = false,
            $extensions = [], $web_extensions = [],
            $dirac_tpl_path = 'dirac/dirac.cfg.erb',
            $web_tpl_path = 'dirac/site.conf.erb',
            $nginx_tpl_path = 'dirac/nginx.conf',
            $install_tpl_path = 'dirac/install.cfg.erb',
            $teigi_keys = [],
            $dirac_config_args = {},
            $logstash_server = false,
            $logstash_config_args = {},
            $oracle_support = false,
            $tornado_processes = 4){

  # Retrieve the fully qualified name
  # This is used in templates
  $server_name = hiera('server_name', $facts['networking']['fqdn'])

  # If we install the machine as a web portal, we have to add
  # 'WebApp' to the extensions
  if $webportal {
    $all_web_extensions = concat($web_extensions, 'WebApp')
    $all_extensions = concat($extensions, $all_web_extensions)
  }
  else {
    $all_extensions = $extensions
  }

  file {'/usr/local/bin/genAllCAs.sh':
    ensure => present,
    source => 'puppet:///modules/dirac/genAllCAs.sh',
    mode   => '0755',
  }  # The cron will run every 2 hours and 10 mn
  -> cron { 'genAllCAsCron':
    command => '/usr/local/bin/genAllCAs.sh &>/dev/null',
    user    => 'root',
    hour    => '*/2',
    minute  => '10',
  }

  # create the basic structure
  file { ['/opt/dirac/etc', '/opt/dirac/etc/grid-security', '/opt/dirac/sbin']:
    ensure => directory,
    owner  => $dirac_user,
    group  => $dirac_group,
  }
  # links the CA certificates used by DIRAC to the lcg-CA ones
  -> file { '/opt/dirac/etc/grid-security/certificates':
    ensure => link,
    target => '/etc/grid-security/certificates',
  }
  # NOTE: will require the cronjob
  -> file { '/opt/dirac/etc/grid-security/cas.pem':
    ensure => link,
    target => '/etc/grid-security/allCAs.pem',
  }


  # Collect the DNS alias to add them to the host certificate
  if $::landb_ip_aliases {
    $diraccertifalias = "${::landb_ip_aliases}.cern.ch"
  }
  else {
    $diraccertifalias = ''
  }
  certmgr::certificate {'dirac perm':
    hostcert      => '/opt/dirac/etc/grid-security/hostcert.pem',
    hostkey       => '/opt/dirac/etc/grid-security/hostkey.pem',
    owner         => $dirac_user,
    group         => $dirac_group,
    san           => $diraccertifalias,
    hostkey_mode  => '0400',
    hostcert_mode => '0440',
    # require       => File['/opt/dirac/etc/grid-security/hostkey.pem'],
  }

  # Copy the bashrc
  file {'/opt/dirac/bashrc':
    ensure => present,
    owner  => $dirac_user,
    group  => $dirac_group,
    mode   => '0755',
    source => 'puppet:///modules/dirac/bashrc',
  }

######################################### START RUNIT #########################################

  file {'/opt/dirac/sbin/runsvdir-start':
    ensure => present,
    owner  => $dirac_user,
    group  => $dirac_group,
    mode   => '0755',
    source => 'puppet:///modules/dirac/runsvdir-start',
  }

  yumrepo { 'repo-for-runit':
    descr    => 'Repo where LHCb store runit',
    baseurl  => 'http://cern.ch/diracproject/rpm',
    gpgcheck => 0,
    enabled  => 1,
    priority => 99,
  }

  package { 'runit':
    ensure  => present,
    require => Yumrepo['repo-for-runit'],
  }

  if versioncmp($facts['os']['release']['major'],'6') == 0 {
    file {'/etc/init/runsvdir.conf':
      ensure => present,
      owner  => 'root',
      group  => 'root',
      mode   => '0644',
      source => 'puppet:///modules/dirac/runsvdir.conf',
    }
  }
  elsif versioncmp($facts['os']['release']['major'], '7') == 0 {
    file {'/usr/lib/systemd/system/runsvdir-start.service':
      ensure => present,
      owner  => 'root',
      group  => 'root',
      mode   => '0644',
      source => 'puppet:///modules/dirac/runsvdir-start.service',
    }
    ~> service { 'dirac-runsvdir':
      ensure => 'running',
      name   => 'runsvdir-start',
      enable => true,
    }
  }

######################################### END RUNIT #########################################


###################################### START WEB PORTAL ######################################

  if $webportal {

    # Allow SELinux to connect to socket
    selinux::boolean { 'httpd_can_network_connect':
      ensure => 'on',
    }

    ensure_packages(['nginx16'])

    # This creates an array where each line will be
    # server 127.0.0.1:<port number>, starting at 8000
    $tornado_servers = range(8000, 8000 + $tornado_processes - 1).map |$port| {
      "server 127.0.0.1:${port}"
    }

    file { ['/var/spool/nginx','/usr/share/nginx','/opt/dirac/data','/opt/dirac/data/log'] :
      ensure => directory,
    }
    -> file {'/opt/dirac/data/log/nginx':
      ensure  => directory,
      owner   => 'nginx',
      group   => 'nginx',
      seltype => 'httpd_log_t', # This ensures that nginx can write in the file
    }

    # because very often, the static files served may be
    # on an external volume, we enter a rule in the SELinuxDB
    # and reapply it using exec_restorecon
    # For extra security, we can also specify the type in the mountpoint:
    # rootcontext=system_u:object_r:httpd_sys_content_t:s0
    selinux::fcontext { '/opt/dirac/webRoot':
      seltype  => 'httpd_sys_content_t',
      pathspec => '/opt/dirac/webRoot(/.*)?',
    }
    # If the webRoot is empty to start with, no problem
    # the new files will inherit the type
    file {'/opt/dirac/webRoot':
      ensure  => directory,
      owner   => $dirac_user,
      group   => $dirac_group,
      seltype => 'httpd_sys_content_t', # This ensures that nginx can serve these files
    }
    -> selinux::exec_restorecon{'/opt/dirac/webRoot':
    }

    file { '/opt/rh/nginx16/root/etc/nginx/site.conf':
      ensure  => present,
      content => template($web_tpl_path),
      require => Package['nginx16'],
    }

    file { '/opt/rh/nginx16/root/etc/nginx/nginx.conf':
      ensure  => present,
      require => Package['nginx16'],
      content => template('dirac/nginx.conf.erb'),
    }

    service { 'nginx16-nginx':
      ensure  => running,
      require => [Package['nginx16'],
                  File['/opt/rh/nginx16/root/etc/nginx/nginx.conf'],
                  File['/opt/rh/nginx16/root/etc/nginx/site.conf'],
                  ],
    }

  }
###################################### END WEB PORTAL ######################################

  ::teigi::secret::sub_file{"/home/${dirac_user}/install.cfg":
    # teigi_keys => ["${::environment}_dirac_key"],
    teigi_keys => $teigi_keys,
    content    => template($install_tpl_path),
    owner      => $dirac_user,
    group      => $dirac_group,
    mode       => '0640',
  }

  ::teigi::secret::sub_file{'/opt/dirac/etc/dirac.cfg':
    teigi_keys => $teigi_keys,
    content    => template($dirac_tpl_path),
    owner      => $dirac_user,
    group      => $dirac_group,
    mode       => '0640',
  }


  firewall {'100 allow ipv4 ports to the world':
    proto  => 'tcp',
    dport  => [80,443,'9130-9200'],
    action => 'accept',
    state  => 'NEW',
  }

  firewall {'100 allow ipv6 ports to the world':
    provider => 'ip6tables',
    proto    => 'tcp',
    dport    => [80,443,'9130-9200'],
    action   => 'accept',
  }

  ##################################################### START LOGSTASH ##################
  if $logstash_server {

    if versioncmp($facts['os']['release']['major'],'6') == 0 {
      notify { 'Cannot install logstash on SLC6':}
    }
    elsif versioncmp($facts['os']['release']['major'], '7') == 0 {
      yumrepo { 'logstash-6.x':
        descr    => 'CentOS/RHEL Logstash repository for 6.x packages',
        baseurl  => 'http://linuxsoft.cern.ch/mirror/artifacts.elastic.co/packages/6.x/yum/',
        gpgkey   => 'http://linuxsoft.cern.ch/mirror/artifacts.elastic.co/GPG-KEY-elasticsearch',
        gpgcheck => 1,
        enabled  => 1,
        priority => 99,
      }

      class {'logstash':
        status      => 'enabled',
        manage_repo => false,
      }


      # # # Because the low level ruby library used to connect to the message broker alias does not connect to all the host behind the alias
      # # # we need to resolve it ourselves. This is looking for trouble, but well... no choice
      # # # https://github.com/iande/onstomp/issues/31
      # $mb_brokers = unique(query_nodes('hostgroup_0="mig" and hostgroup_1="brokers" and lbaliases="lhcb-test-mb.cern.ch"', 'hostname'))

      # Generate the config file for logstash with Teigi,
      # and then declare it to logstash class
      teigi::secret::sub_file{'/tmp/logstashConfigTeigi.cfg':
        teigi_keys => $teigi_keys,
        content    => template('dirac/logstash.conf.erb'),
        mode       => '0640',
        owner      => 'logstash',
      }
      -> logstash::configfile { 'configname':
        source => '/tmp/logstashConfigTeigi.cfg',
      }


      # logstash::plugin { 'logstash-filter-prune': }
      logstash::plugin { 'logstash-input-stomp': }
    }
  }
  ################################ END LOGSTASH #####################################################

  ################################ START ORACLE #####################################################
  if $oracle_support{
    # We can't add these packages in DIRACOS for license reasons

    $pkgs_to_be_installed = ['oracle-instantclient12.1-basic',
                              'oracle-instantclient12.1-meta']

    package{$pkgs_to_be_installed:
      ensure => present,
    }

  }
  ################################  END ORACLE  #####################################################

}