<commit_before>"""Class for verifying gip information"""

import os
import re
import pwd
import logging

from osg_configure.modules import subcluster
from osg_configure.modules import exceptions
from osg_configure.modules.configurationbase import BaseConfiguration
from osg_configure.modules import utilities
from osg_configure.modules import validation


__all__ = ['GipConfiguration']

from osg_configure.modules.subcluster import REQUIRED, OPTIONAL, STRING, POSITIVE_INT, POSITIVE_FLOAT, LIST, BOOLEAN

OSG_ENTRIES = {
   "Site Information": ["host_name", "site_name", "sponsor", "site_policy",
                        "contact", "email", "city", "longitude", "latitude"],
   "Storage": ["app_dir", "data_dir", "worker_node_temp"],
}

SE_ENTRIES = {
   "name": (REQUIRED, STRING),
   "unique_name": (OPTIONAL, STRING),
   "srm_endpoint": (REQUIRED, STRING),
   "srm_version": (OPTIONAL, STRING),
   "transfer_endpoints": (OPTIONAL, STRING),
   "provider_implementation": (OPTIONAL, STRING),
   "implementation": (REQUIRED, STRING),
   "version": (REQUIRED, STRING),
   "default_path": (REQUIRED, STRING),
   "allowed_vos": (OPTIONAL, LIST),
   "mount_point": (OPTIONAL, LIST),
}

SE_BANNED_ENTRIES = {
   "name": "SE_CHANGEME",
   "srm_endpoint": "httpg://srm.example.com:8443/srm/v2/server",
}

# Error messages
MOUNT_POINT_ERROR = """\
You have enabled the mount_point option, but your input, %(input)s, is invalid
because of:
%(reason)s

mount_point should be enabled for sites where the SE is mounted on the worker
nodes and provides a POSIX-like interface (POSIX-like includes Lustre, HDFS,
XrootDFS, but not dCache PNFS).
The value of `mount_point` should be two paths; first, the path where the
file system is mounted on the worker nodes, followed by the exported directory
of the file system.  If you mount your file system on the worker nodes with
the following command:
  $ mount -t nfs nfs.example.com:/exported/dir /mnt/nfs
then mount_point should look like this:
   mount_point = /mnt/nfs,/exported/dir

Paths are lightly validated; they must start with "/" and contain alphanumeric
characters plus "-" or "_".
"""

class GipConfiguration(BaseConfiguration):
  """
  Class to handle attributes related to GIP.
  """
  def __init__(self, *args, **kwargs):
    # pylint: disable-msg=W0142
    super(GipConfiguration, self).__init__(*args, **kwargs)
    self.log('GipConfiguration.__init__ started')
    self.config_section = "GIP"
    self.vo_dir = "VONAME"  # default to allowing substitution in vo_dir
    self._valid_batch_opt = ['pbs',
                             'lsf',
                             'condor',
                             'sge',
                             'slurm',
                             'forwarding']

    self.gip_user = None
    self.log('GipConfiguration.__init__ completed')

  _check_entry = staticmethod(subcluster.check_entry)

  def parseConfiguration(self, configuration):
    """
    Try to get configuration information from ConfigParser or SafeConfigParser
    object given by configuration and write recognized settings to attributes
    dict
    """
    self.log('GipConfiguration.parseConfiguration started')

    if not utilities.rpm_installed('gip'):
      self.log('GIP not installed, disabling GIP')
      self.log('GipConfiguration.parseConfiguration completed')
      self.enabled = False
      return
    else:
      self.enabled = True

    # TODO Do we want to force the user to have a GIP section? Uncomment the following if not.
    # if not configuration.has_section(self.config_section):
    #   self.log("%s section not in config file" % self.config_section)
    #   self.log('GipConfiguration.parseConfiguration completed')
    #   self.enabled = False
    #   return

    self.checkConfig(configuration)

    self._parseConfiguration(configuration)

    self.log('GipConfiguration.parseConfiguration completed')

  check_subclusters = staticmethod(subcluster.check_config)

  def _parseConfiguration(self, configuration):
    """
    The meat of parseConfiguration, runs after we've checked that GIP is
    enabled and we have the right RPMs installed.
    """
    # The following is to set the user that gip files need to belong to
    # This can be overridden by setting the 'user' option in the [GIP] section
    self.gip_user = 'tomcat'
    if configuration.has_option(self.config_section, 'batch'):
      batch_opt = configuration.get(self.config_section, 'batch').lower()
      if (not utilities.blank(batch_opt) and
              batch_opt not in self._valid_batch_opt):
        msg = "The batch setting in %s must be a valid option " \
              "(e.g. %s), %s was given" % (self.config_section,
                                           ",".join(self._valid_batch_opt),
                                           batch_opt)
        self.log(msg, level=logging.ERROR)
        raise exceptions.SettingError(msg)

    has_sc = self.check_subclusters(configuration)
    if not has_sc:
      try:
        self._check_entry(configuration, "GIP", "sc_number", REQUIRED,
                          POSITIVE_INT)
      except:
        msg = "There is no `subcluster` section and the old-style subcluster" + \
              "setup in GIP is not configured. " + \
              " Please see the configuration documentation."
        raise exceptions.SettingError(msg)


    # Check for the presence of the classic SE
    has_classic_se = True
    try:
      has_classic_se = configuration.getboolean("GIP", "advertise_gsiftp")
    # pylint: disable-msg=W0702
    # pylint: disable-msg=W0703
    # pylint: disable-msg=W0704
    except Exception:
      pass

    has_se = False
    for section in configuration.sections():
      if not section.lower().startswith('se'):
        continue
      has_se = True
      self.checkSE(configuration, section)
    if not has_se and not has_classic_se:
      try:
        self._check_entry(configuration, "GIP", "se_name", REQUIRED, STRING)
      except:<commit_msg>Only require subclusters to be defined if we are on a CE. (SOFTWARE-1912)<commit_after>"""Class for verifying gip information"""

import os
import re
import pwd
import logging

from osg_configure.modules import subcluster
from osg_configure.modules import exceptions
from osg_configure.modules.configurationbase import BaseConfiguration
from osg_configure.modules import utilities
from osg_configure.modules import validation


__all__ = ['GipConfiguration']

from osg_configure.modules.subcluster import REQUIRED, OPTIONAL, STRING, POSITIVE_INT, POSITIVE_FLOAT, LIST, BOOLEAN

OSG_ENTRIES = {
   "Site Information": ["host_name", "site_name", "sponsor", "site_policy",
                        "contact", "email", "city", "longitude", "latitude"],
   "Storage": ["app_dir", "data_dir", "worker_node_temp"],
}

SE_ENTRIES = {
   "name": (REQUIRED, STRING),
   "unique_name": (OPTIONAL, STRING),
   "srm_endpoint": (REQUIRED, STRING),
   "srm_version": (OPTIONAL, STRING),
   "transfer_endpoints": (OPTIONAL, STRING),
   "provider_implementation": (OPTIONAL, STRING),
   "implementation": (REQUIRED, STRING),
   "version": (REQUIRED, STRING),
   "default_path": (REQUIRED, STRING),
   "allowed_vos": (OPTIONAL, LIST),
   "mount_point": (OPTIONAL, LIST),
}

SE_BANNED_ENTRIES = {
   "name": "SE_CHANGEME",
   "srm_endpoint": "httpg://srm.example.com:8443/srm/v2/server",
}

# Error messages
MOUNT_POINT_ERROR = """\
You have enabled the mount_point option, but your input, %(input)s, is invalid
because of:
%(reason)s

mount_point should be enabled for sites where the SE is mounted on the worker
nodes and provides a POSIX-like interface (POSIX-like includes Lustre, HDFS,
XrootDFS, but not dCache PNFS).
The value of `mount_point` should be two paths; first, the path where the
file system is mounted on the worker nodes, followed by the exported directory
of the file system.  If you mount your file system on the worker nodes with
the following command:
  $ mount -t nfs nfs.example.com:/exported/dir /mnt/nfs
then mount_point should look like this:
   mount_point = /mnt/nfs,/exported/dir

Paths are lightly validated; they must start with "/" and contain alphanumeric
characters plus "-" or "_".
"""

class GipConfiguration(BaseConfiguration):
  """
  Class to handle attributes related to GIP.
  """
  def __init__(self, *args, **kwargs):
    # pylint: disable-msg=W0142
    super(GipConfiguration, self).__init__(*args, **kwargs)
    self.log('GipConfiguration.__init__ started')
    self.config_section = "GIP"
    self.vo_dir = "VONAME"  # default to allowing substitution in vo_dir
    self._valid_batch_opt = ['pbs',
                             'lsf',
                             'condor',
                             'sge',
                             'slurm',
                             'forwarding']

    self.gip_user = None
    self.log('GipConfiguration.__init__ completed')

  _check_entry = staticmethod(subcluster.check_entry)

  def parseConfiguration(self, configuration):
    """
    Try to get configuration information from ConfigParser or SafeConfigParser
    object given by configuration and write recognized settings to attributes
    dict
    """
    self.log('GipConfiguration.parseConfiguration started')

    if not utilities.rpm_installed('gip'):
      self.log('GIP not installed, disabling GIP')
      self.log('GipConfiguration.parseConfiguration completed')
      self.enabled = False
      return
    else:
      self.enabled = True

    # TODO Do we want to force the user to have a GIP section? Uncomment the following if not.
    # if not configuration.has_section(self.config_section):
    #   self.log("%s section not in config file" % self.config_section)
    #   self.log('GipConfiguration.parseConfiguration completed')
    #   self.enabled = False
    #   return

    self.checkConfig(configuration)

    self._parseConfiguration(configuration)

    self.log('GipConfiguration.parseConfiguration completed')

  check_subclusters = staticmethod(subcluster.check_config)

  def _parseConfiguration(self, configuration):
    """
    The meat of parseConfiguration, runs after we've checked that GIP is
    enabled and we have the right RPMs installed.
    """
    # The following is to set the user that gip files need to belong to
    # This can be overridden by setting the 'user' option in the [GIP] section
    self.gip_user = 'tomcat'
    if configuration.has_option(self.config_section, 'batch'):
      batch_opt = configuration.get(self.config_section, 'batch').lower()
      if (not utilities.blank(batch_opt) and
              batch_opt not in self._valid_batch_opt):
        msg = "The batch setting in %s must be a valid option " \
              "(e.g. %s), %s was given" % (self.config_section,
                                           ",".join(self._valid_batch_opt),
                                           batch_opt)
        self.log(msg, level=logging.ERROR)
        raise exceptions.SettingError(msg)

    if utilities.ce_installed():
      # All CEs must advertise subclusters
      has_sc = self.check_subclusters(configuration)
      if not has_sc:
        try:
          self._check_entry(configuration, "GIP", "sc_number", REQUIRED,
                            POSITIVE_INT)
        except (TypeError, ValueError, exceptions.SettingError):
          msg = "There is no `subcluster` section and the old-style subcluster" + \
                "setup in GIP is not configured. " + \
                " Please see the configuration documentation."
          raise exceptions.SettingError(msg)


    # Check for the presence of the classic SE
    has_classic_se = True
    try:
      has_classic_se = configuration.getboolean("GIP", "advertise_gsiftp")
    # pylint: disable-msg=W0702
    # pylint: disable-msg=W0703
    # pylint: disable-msg=W0704
    except Exception:
      pass

    has_se = False
    for section in configuration.sections():
      if not section.lower().startswith('se'):
        continue
      has_se = True
      self.checkSE(configuration, section)
    if not has_se and not has_classic_se:
      try:
        self._check_entry(configuration, "GIP", "se_name", REQUIRED, STRING)
      except:
{'fraction_non_alphanumeric': 0.09731240239993424, 'fraction_numerical': 0.003780718336483932, 'mean_word_length': 3.083221476510067, 'pattern_counts': {'":': 30, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4111509', 'n_tokens_mistral': 3623, 'n_tokens_neox': 3529, 'n_words': 1049}