Example #1
0
 def __init__(self,inifile,optionsDict=None):
   global valid_options
   self.inifile = inifile
   self.ini_section = "Factory"
   if optionsDict != None:
     valid_options = optionsDict
   Condor.__init__(self,self.inifile,self.ini_section,valid_options[self.ini_section])
   self.glidein = Glidein(self.inifile,self.ini_section,valid_options[self.ini_section])
   self.config_entries_list = {} # Config file entries elements
   self.wms      = None
   self.frontend = None
   self.get_wms()
   self.not_validated = True
Example #2
0
class Factory(Condor):

  def __init__(self,inifile,optionsDict=None):
    global valid_options
    self.inifile = inifile
    self.ini_section = "Factory"
    if inifile == "template":  # for creating actions not requiring ini file
      return
    if optionsDict != None:
      valid_options = optionsDict
    Condor.__init__(self,self.inifile,self.ini_section,valid_options[self.ini_section])
    self.glidein = Glidein(self.inifile,self.ini_section,valid_options[self.ini_section])
    self.config_entries_list = {} # Config file entries elements
    self.wms      = None
    self.frontend = None
    self.get_wms()
    self.not_validated = True

  #-- get service instances --------
  def get_wms(self):
    if self.wms == None:
      self.wms = WMSCollector.WMSCollector(self.inifile,valid_options)

  def get_frontend(self):
    if self.frontend == None:
      self.frontend = VOFrontend.VOFrontend(self.inifile,valid_options)

  #---------------------
  def glideinwms_location(self):
    return self.glidein.glideinwms_location()
  #---------------------
  def install_location(self):
    return self.glidein.install_location()
  #---------------------
  def config_dir(self):
    return "%s/glidein_%s.cfg" % (self.install_location(),self.glidein.instance_name())
  #---------------------
  def config_file(self):
    return "%s/glideinWMS.xml" % (self.config_dir())
  #---------------------
  def logs_dir(self):
     return self.option_value(self.ini_section,"logs_dir")
  #---------------------
  def glidein_dir(self):
    # this directory is hardcoded in the createglidein script
    return "%s/glidein_%s" % (self.glidein.install_location(),self.glidein.instance_name())
  #---------------------
  def username(self):
    return self.glidein.username()
  #---------------------
  def hostname(self):
    return self.glidein.hostname()
  #---------------------
  def env_script(self):
    return "%s/factory.sh" % self.glidein.install_location()
  #---------------------
  def service_name(self):
    return self.glidein.service_name()
  #---------------------
  def client_log_dir(self):
    return self.option_value(self.ini_section,"client_log_dir")
  #---------------------
  def client_proxy_dir(self):
    return self.option_value(self.ini_section,"client_proxy_dir")

  #----------------------------
  def get_new_config_entries(self):
    """This method is intended to retrieve new configuration file entry
       element after the initial installation is complete.  It will 
       create a file containing the selected entry points that can be
       merged into the existing Factory configuration file.
    """
    self.get_config_entries_data()
    filename = "%s/new_entries.%s" % (self.config_dir(),common.time_suffix())
    common.write_file("w",0644,filename,self.config_entries_data())

  #-----------------------
  def validate(self):
    if self.not_validated:
      common.logit( "Verifying Factory options")
      if os.getuid() <> pwd.getpwnam(self.username())[2]:
        common.logerr("""You need to install this as the Factory unix acct (%s) so
files and directories can be created correctly""" % self.username())
      self.install_vdtclient()
      self.install_certificates()
      common.logit( "\nVerifying Factory options")
      common.validate_hostname(self.hostname())
      common.validate_user(self.username())
      common.validate_installer_user(self.username())
      self.glidein.validate_software_requirements()
      self.validate_needed_directories()
      common.logit( "Factory verification complete\n")
      time.sleep(3)
    self.not_validated = False

  #---------------------
  def install(self):
    common.logit ("======== %s install starting ==========\n" % self.ini_section)
    self.get_wms()
    self.get_frontend()
    common.ask_continue("Continue")
    self.validate()
    self.clean_directories()
    self.configure()
    common.logit ("\n======== %s install complete ==========\n" % self.ini_section)
    self.create_glideins()
    if os.path.isdir(self.glidein_dir()): #indicates the glideins have been created
      common.start_service(self.glideinwms_location(),self.ini_section,self.inifile)

  #-----------------------------
  def validate_needed_directories(self):
    self.glidein.validate_web_location()
    self.validate_logs_dir()
    self.validate_client_log_dir()
    self.validate_client_proxy_dir()
    common.validate_install_location(self.install_location())

  #-----------------------------
  def clean_directories(self):
    """ This method attempts to clean up all directories so a fresh install
        can be accomplished successfully.  
        It is consoldiated in a single check so as to only ask once and
        not for each directory.
        When privilege separation is in effect, the condor_root_switchboard
        must be used to clean out the client log and proxy files 
        as the owners are different and permissions problems will occur.
    """
    instance_dir = "glidein_%(instance)s" % \
                     { "instance" : self.glidein.instance_name(), }
    dirs = {}
    dirs["logs"] = os.path.join(self.logs_dir(),instance_dir)
    dirs["install"] = os.path.join(self.install_location(),instance_dir)
#    dirs["config"] = self.config_dir()
    for frontend in self.wms.frontend_users().keys():
      dirs["client logs"]    = self.client_log_dir()
      dirs["client proxies"] = self.client_proxy_dir()
    for subdir in ["monitor","stage"]:
      dirs["web %s" % subdir] = os.path.join(self.glidein.web_location(),subdir,instance_dir)

    #--- check them --
    dirs = self.verify_directories_empty(dirs)

    #--- if all are empty, return 
    if len(dirs) == 0:
      time.sleep(3)
      return  # all directories are empty

    #--- See if we can remove them ---
    common.logit("""The following directories must be empty for the install to succeed: """)
    types = dirs.keys()
    types.sort()
    for type in types:
      common.logit("""  %(type)s: %(dir)s""" % \
                        { "type" : type, "dir" : dirs[type] })
    common.ask_continue("... can we remove their contents")
    if self.wms.privilege_separation() == "y":
      self.delete_ps_directories(dirs)
    else:
      self.delete_nps_directories(dirs)

    #--- double check them --
    dirs = self.verify_directories_empty(dirs)
    if len(dirs) > 0:
      common.logerr("""We seem to have had a problems deleting the contents of these directories:
%s """ % dirs)

    time.sleep(3)
    return  # all directories are empty

  #------------------------------------
  def delete_ps_directories(self,dirs):
    """ Delete the contents of directories with privilege separation in effect."""
    for type in dirs.keys():
      if type not in ["client logs", "client proxies",]: 
        common.remove_dir_path(dirs[type])
        continue
      #-- Factory create requires client logs/proxies directories be empty
      #-- when privspep is in effect
      condor_sbin = "%s/sbin" % self.wms.condor_location()
      condor_bin  = "%s/bin"  % self.wms.condor_location()
      condorExe.set_path(condor_bin,condor_sbin)
      parent_dir = dirs[type]
      subdirs = os.listdir(parent_dir)
      for base_dir in subdirs:
        if os.path.isdir("%s/%s" % (parent_dir,base_dir)): 
          try:
            condorPrivsep.rmtree(parent_dir,base_dir)
          except Exception,e:
            common.logerr("""Encountered a problem in executing condor_root_switchboard 
to remove this client's sub-directories:
  %(dir)s

  %(error)s
Check your /etc/condor/privsep.conf file to verify.
You may need to configure/install your WMS Collector to resolve or correct
the ini file for the %(type)s attribute.  Be careful now.
""" % { "dir"    : parent_dir,
        "type" : type, 
        "error"  : e, } )
          common.logit("Files in %s deleted" % parent_dir) 
Example #3
0
class Factory(Condor):

  def __init__(self,inifile,optionsDict=None):
    global valid_options
    self.inifile = inifile
    self.ini_section = "Factory"
    if optionsDict != None:
      valid_options = optionsDict
    Condor.__init__(self,self.inifile,self.ini_section,valid_options[self.ini_section])
    self.glidein = Glidein(self.inifile,self.ini_section,valid_options[self.ini_section])
    self.config_entries_list = {} # Config file entries elements
    self.wms      = None
    self.frontend = None
    self.get_wms()
    self.not_validated = True

  #-- get service instances --------
  def get_wms(self):
    if self.wms == None:
      self.wms = WMSCollector.WMSCollector(self.inifile,valid_options)

  def get_frontend(self):
    if self.frontend == None:
      self.frontend = VOFrontend.VOFrontend(self.inifile,valid_options)

  #---------------------
  def glideinwms_location(self):
    return self.glidein.glideinwms_location()
  #---------------------
  def install_location(self):
    return self.glidein.install_location()
  #---------------------
  def logs_dir(self):
     return self.option_value(self.ini_section,"logs_dir")
  #---------------------
  def glidein_dir(self):
    # this directory is hardcoded in the createglidein script
    return "%s/glidein_%s" % (self.glidein.install_location(),self.glidein.instance_name())
  #---------------------
  def username(self):
    return self.glidein.username()
  #---------------------
  def hostname(self):
    return self.glidein.hostname()
  #---------------------
  def use_vofrontend_proxy(self):
    return self.option_value(self.ini_section,"use_vofrontend_proxy")
  #---------------------
  def x509_proxy(self):
    return self.option_value(self.ini_section,"x509_proxy")
  #---------------------
  def x509_gsi_dn(self):
    return self.option_value(self.ini_section,"x509_gsi_dn")
  #---------------------
  def env_script(self):
    return "%s/factory.sh" % self.glidein.install_location()
  #---------------------
  def service_name(self):
    return self.glidein.service_name()
  #---------------------
  def client_log_dir(self):
    return self.option_value(self.ini_section,"client_log_dir")
  #---------------------
  def client_proxy_dir(self):
    return self.option_value(self.ini_section,"client_proxy_dir")

  #----------------------------
  def get_new_config_entries(self):
    """This method is intended to retrieve new configuration file entry
       element after the initial installation is complete.  It will 
       create a file containing the selected entry points that can be
       merged into the existing Factory configuration file.
    """
    self.get_config_entries_data()
    filename = "%s/new_entries.%s" % (self.glidein.config_dir(),common.time_suffix())
    common.write_file("w",0644,filename,self.config_entries_data())

  #-----------------------
  def validate(self):
    if self.not_validated:
      common.logit( "Verifying Factory options")
      if os.getuid() <> pwd.getpwnam(self.username())[2]:
        common.logerr("""You need to install this as the Factory unix acct (%s) so
files and directories can be created correctly""" % self.username())
      self.install_vdtclient()
      self.install_certificates()
      common.logit( "\nVerifying Factory options")
      common.validate_hostname(self.hostname())
      common.validate_user(self.username())
      common.validate_installer_user(self.username())
      self.validate_use_vofrontend_proxy()
      self.glidein.validate_software_requirements()
      self.validate_needed_directories()
      common.logit( "Verification complete\n")
    self.not_validated = False

  #---------------------
  def install(self):
    common.logit ("======== %s install starting ==========\n" % self.ini_section)
    self.get_wms()
    self.get_frontend()
    common.ask_continue("Continue")
    self.validate()
    self.verify_directories_empty()
    self.configure()
    common.logit ("\n======== %s install complete ==========\n" % self.ini_section)
    self.create_glideins()
    if os.path.isdir(self.glidein_dir()): #indicates the glideins have been created
      common.start_service(self.glideinwms_location(),self.ini_section,self.inifile)

  #-----------------------------
  def validate_needed_directories(self):
    self.glidein.validate_web_location()
    self.validate_logs_dir()
    self.validate_client_log_dir()
    self.validate_client_proxy_dir()
    common.validate_install_location(self.install_location())

  #-----------------------------
  def verify_directories_empty(self):
    """ This method attempts to clean up all directories so a fresh install
        can be accomplished successfully.  
        It is consoldiated in a single check so as to only ask once and
        not for each directory.
        It also (attempts) to insure that if directories are nested, it 
        does not create a problem.  Not an easy task.
        When privilege separation is in effect, the condor_root_switchboard
        must be used to clean out the client log and proxy files 
        as the owners are different and permissions problems will occur.
    """
    dirs = {}
    if len(os.listdir(self.client_log_dir())) > 0:
      dirs["client_log_dir"] = self.client_log_dir()
    if len(os.listdir(self.client_proxy_dir())) > 0:
      dirs["client_proxy_dir"] = self.client_proxy_dir()
    if len(os.listdir(self.logs_dir())) > 0:
      dirs["logs_dir"] = self.logs_dir()
    for dir in ["monitor","stage"]:
      subdir = os.path.join(self.glidein.web_location(),dir)
      if os.path.isdir(subdir) and len(os.listdir(subdir)) > 0:
        dirs["web_location/%s" % dir] = subdir
    if len(os.listdir(self.install_location())) > 0:
      if len(os.listdir(self.install_location())) > self.nbr_of_nested_dirs():
        dirs["install_location"] = self.install_location()
    if len(dirs) == 0:
      return  # all directories are empty
    common.logit("""The following directories must be empty for the install to succeed: """)
    for option in dirs.keys():
      common.logit("""  %(option)s: %(dir)s""" % \
                        { "option" : option, "dir" : dirs[option] })
    common.ask_continue("... can we remove their contents")
    for option in dirs.keys():
      if self.wms.privilege_separation() == "y":
        if option in ["client_log_dir","client_proxy_dir",]:
          #-- Factory create requires these directories be empty
          #-- when privspep is in effect
          condor_sbin = "%s/sbin" % self.wms.condor_location()
          condor_bin  = "%s/bin" % self.wms.condor_location()
          condorExe.set_path(condor_bin,condor_sbin)
          parent_dir = dirs[option]
          subdirs = os.listdir(parent_dir)
          for base_dir in subdirs:
            if os.path.isdir("%s/%s" % (parent_dir,base_dir)): 
              condorPrivsep.rmtree(parent_dir,base_dir)
        else: 
          common.remove_dir_contents(dirs[option])
      else: 
        common.remove_dir_contents(dirs[option])
    # this re-validation is performed to resolve problem of nesting some dirs
    self.validate_needed_directories()

  #-----------------------------
  def nbr_of_nested_dirs(self):
    # Determines if any of the directories are subdirectories of the install 
    # location.  We are trying to avoid deleting teh contents if we do not have to.
    cnt = 0
    for dir in  [self.logs_dir(), 
                 self.client_log_dir(),
                 self.client_proxy_dir(),
                 self.glidein.web_location() ]:
      if dir.find(self.install_location()) == 0:
        cnt = cnt + 1
    return cnt
    
 
  #----------------------------
  def configure(self):
    self.validate()
    self.get_config_entries_data()
    self.create_env_script()
    self.create_config()

  #---------------------------------
  def validate_use_vofrontend_proxy(self):
    option =  self.use_vofrontend_proxy()
    common.logit("... validating use_vofrontend_proxy: %s" % option)
    if option not in ("y",):
      common.logerr("use_vofrontend_proxy must be 'y'.  This option will be depreated fully in V3.")
    if option == "y":  # using vofrontend 
      if len(self.x509_proxy())  > 0 or \
         len(self.x509_gsi_dn()) > 0:
        common.logerr("""You have said you want to use the Frontend proxies only.
The x509_proxy and x509_gsi_dn option must be empty.""")

    else:  # use factory proxy if no vofrontend proxy provided
      self.validate_factory_proxy()

  #---------------------------------
  def validate_factory_proxy(self):
    #--- using factory and vofrontend ---
    if len(self.x509_proxy())  == 0 or \
       len(self.x509_gsi_dn()) == 0:
      common.logerr("""You have said you want to use a Frontend and Factory proxies.
The x509_proxy and x509_gsi_dn option must be populated.""")
    proxy_file = self.x509_proxy()
    common.logit("... validating x509_proxy: %s" % proxy_file)
    if not os.path.exists(proxy_file):
      common.logerr("""File specified does not exist.""")
    common.logit("... validating x509_gsi_dn: %s" % self.x509_gsi_dn())
    type = "proxy"
    dn_to_validate = self.x509_gsi_dn()
    dn_in_file = common.get_gsi_dn(type,proxy_file)
    if dn_in_file <> dn_to_validate:
      common.logerr("""The DN of the %(type)s in %(file)s 
does not match the x509_gsi_dn attribute in your ini file:
%(type)8s dn: %(file_dn)s
%(ini)11s: %(ini_dn)s
This may cause a problem in other services.
Are you sure this is a proxy and not a certificate?""" % \
              { "type"    : type,
                "ini"     : "x509_gsi_dn",
                "file"    : proxy_file,
                "file_dn" : dn_in_file,
                "ini_dn"  : dn_to_validate},)

    
      
  #---------------------------------
  def validate_logs_dir(self):
    common.logit("... validating logs_dir: %s" % self.logs_dir())
    common.make_directory(self.logs_dir(),self.username(),0755)

  #---------------------------------
  def validate_client_log_dir(self):
    common.logit("... validating client_log_dir: %s" % self.client_log_dir())
    if self.wms.privilege_separation() == "y":
      #-- done in WMS collector install if privilege separation is used --
      if not os.path.isdir(self.client_log_dir()):
        common.logerr("""Privilege separation is in effect. This should have been
created by the WMS Collector installation or you did not start the service 
or you changed the ini file and did not reinstall that service.""")
    else:
      common.make_directory(self.client_log_dir(),self.username(),0755)

  #---------------------------------
  def validate_client_proxy_dir(self):
    common.logit("... validating client_proxy_dir: %s" % self.client_proxy_dir())
    if self.wms.privilege_separation() == "y":
      #-- done in WMS collector install if privilege separation is used --
      if not os.path.isdir(self.client_proxy_dir()):
        common.logerr("""Privilege separation is in effect. This should have been
created by the WMS Collector installation or you did not start the service 
or you changed the ini file and did not reinstall that service.""")
    else:
      common.make_directory(self.client_proxy_dir(),self.username(),0755)

  #-----------------------
  def create_env_script(self):
    """This creates an "env" type script that must be used before starting the
       factory.
    """
    common.logit("Creating environment script...")
    data = """#!/bin/bash
export X509_CERT_DIR=%(x509_cert_dir)s
source %(condor_location)s/condor.sh
""" % { "x509_cert_dir"   : self.wms.x509_cert_dir(), 
        "condor_location" : self.wms.condor_location(),}
    if self.use_vofrontend_proxy() == "n":
      data += "export X509_USER_PROXY=%s" % self.x509_proxy()
    common.write_file("w",0644,self.env_script(),data)
    common.logit("%s\n" % data)


  #-----------------------
  def create_glideins(self):
    yn=raw_input("\nDo you want to create the glideins now? (y/n) [n]: ")
    cmd1 = "source %s" % self.env_script()
    cmd2 = "%s/creation/create_glidein %s" % (self.glidein.glideinwms_location(),self.glidein.config_file())
    if yn=='y':
      common.run_script("%s;%s" % (cmd1,cmd2))
    else:
      common.logit("\nTo create the glideins, you need to run the following:\n  %s\n  %s" % (cmd1,cmd2))

  #-----------------------
  def schedds(self):
    collector_hostname = self.wms.hostname()
    schedd_list = [self.wms.hostname(),]
    for filename in os.listdir(self.wms.condor_local()):
      if filename[0:6] == "schedd":
        schedd_list.append("%s@%s" % (filename,collector_hostname))
    return schedd_list

  #-------------------------
  def create_config(self):
    config_xml = self.config_data()
    common.logit("\nCreating configuration file: %s" % self.glidein.config_file())
    common.make_directory(self.glidein.config_dir(),self.username(),0755)
    common.write_file("w",0644,self.glidein.config_file(),config_xml)

  #-------------------------
  def config_data(self):
    data = """ 
<glidein factory_name="%(service_name)s" 
         glidein_name="%(instance_name)s"
         loop_delay="60" 
         advertise_delay="5"
         restart_attempts="3" 
         restart_interval="1800"
         schedd_name="%(schedds)s">
""" % \
{ "service_name"  : self.glidein.service_name(), 
  "instance_name" : self.glidein.instance_name(), 
  "schedds"       : string.join(self.schedds(),',')
}
    data = data + """\
%(condor)s
%(submit)s
%(stage)s
%(monitor)s
%(security)s
%(default_attr)s
%(entries)s
  <files>
  </files>
</glidein>
""" % \
{ "condor"       : self.config_condor_data(),
  "submit"       : self.config_submit_data(),
  "stage"        : self.config_stage_data(),
  "monitor"      : self.config_monitor_data(),
  "security"     : self.config_security_data(),
  "default_attr" : self.config_default_attr_data(),
  "entries"      : self.config_entries_data(),
}
    return data
  #---------------
  def config_condor_data(self): 
    return """
%(indent1)s<condor_tarballs>
%(indent2)s<condor_tarball arch="default" os="default" base_dir="%(condor_location)s"/>
%(indent1)s</condor_tarballs> """ % \
{ "indent1"          : common.indent(1),
  "indent2"          : common.indent(2),
  "condor_location"  : self.wms.condor_location(),
}
  #---------------
  def config_submit_data(self): 
    return """
%(indent1)s<submit base_dir="%(install_location)s" 
%(indent1)s        base_log_dir="%(factory_logs)s" 
%(indent1)s        base_client_log_dir="%(client_log_dir)s" 
%(indent1)s        base_client_proxies_dir="%(client_proxy_dir)s"/> """ % \
{ "indent1"          : common.indent(1),
  "install_location" : self.install_location(),
  "factory_logs"     : self.logs_dir(),
  "client_log_dir"   : self.client_log_dir(),
  "client_proxy_dir" : self.client_proxy_dir(),
}
  #---------------
  def config_stage_data(self): 
    return """
%(indent1)s<stage web_base_url="%(web_url)s/%(web_dir)s/stage" 
%(indent1)s       use_symlink="True" 
%(indent1)s       base_dir="%(web_location)s/stage"/>""" % \
{ "indent1"       : common.indent(1),
  "web_url"       : self.glidein.web_url(),
  "web_location"  : self.glidein.web_location(),
  "web_dir"  : os.path.basename(self.glidein.web_location()),
}
  #---------------
  def config_monitor_data(self): 
    indent = common.indent(1)
    return """
%(indent1)s<monitor base_dir="%(web_location)s/monitor" 
%(indent1)s        javascriptRRD_dir="%(javascriptrrd)s" 
%(indent1)s        flot_dir="%(flot)s" 
%(indent1)s        jquery_dir="%(jquery)s"/>"""  % \
{ "indent1"       : common.indent(1),
  "web_location"  : self.glidein.web_location(),  
  "javascriptrrd" : self.glidein.javascriptrrd_dir, 
  "jquery"        : self.glidein.jquery_dir,
  "flot"          : self.glidein.flot_dir,
}

  #---------------
  def config_security_data(self): 
    if self.use_vofrontend_proxy() == "y": # disable factory proxy
      allow_proxy = "frontend"
    else: # allow both factory proxy and VO proxy
      allow_proxy = "factory,frontend"

    data = """
%(indent1)s<security allow_proxy="%(allow_proxy)s" key_length="2048" pub_key="RSA" >
%(indent2)s<frontends>""" % \
{ "indent1":common.indent(1),
  "indent2":common.indent(2),
  "allow_proxy": allow_proxy,
}

    frontend_users_dict =  self.wms.frontend_users()
    for frontend in frontend_users_dict.keys():
      data = data + """
%(indent3)s<frontend name="%(frontend)s" identity="%(frontend)s@%(hostname)s">
%(indent4)s<security_classes>
%(indent5)s<security_class name="frontend" username="******"/>
""" %  \
{ "indent3" : common.indent(3),
  "indent4" : common.indent(4),
  "indent5" : common.indent(5),
  "frontend": frontend,
  "hostname"      : self.hostname(),
  "frontend_user" : frontend_users_dict[frontend],
}
      if self.use_vofrontend_proxy() == "n":
        data = data + """\
%(indent5)s<security_class name="factory"  username="******"/>
""" % \
{ "indent5"       : common.indent(5),
  "factory_user"  : self.username(),
}

      data = data + """
%(indent4)s</security_classes>
%(indent3)s</frontend>""" %  \
{ "indent3" : common.indent(3),
  "indent4" : common.indent(4),
}

    data = data + """
%(indent2)s</frontends>
%(indent1)s</security>""" % \
{ "indent1":common.indent(1),
  "indent2":common.indent(2),
}
    return data

  #---------------
  def config_default_attr_data(self):
    indent = common.indent(1)
    data = """
%s<attrs>""" % (indent)
    indent = common.indent(2)

    if self.glidein.use_ccb()  == "n":
      data = data + """
%s<attr name="USE_CCB" value="False" const="True" type="string" glidein_publish="True" publish="True" job_publish="False" parameter="True"/>"""  % (indent)

    # -- glexec --
    data = data + """
%(indent2)s<attr name="GLEXEC_JOB" value="True" const="True" type="string" glidein_publish="False" publish="True" job_publish="False" parameter="True"/>
%(indent2)s<attr name="USE_MATCH_AUTH" value="%(match_authentication)s" const="False" type="string" glidein_publish="False" publish="True" job_publish="False" parameter="True"/>
%(indent2)s<attr name="CONDOR_VERSION" value="default" const="True" type="string" glidein_publish="False" publish="False" job_publish="False" parameter="True"/>
%(indent1)s</attrs>
""" % \
{ "indent1" : common.indent(1),
  "indent2" : common.indent(2),
  "match_authentication" : self.glidein.match_authentication() == "y",
}
    return data


  #---------------
  def config_entries_data(self):
    data = """\
%(indent1)s<entries>""" % { "indent1" : common.indent(1), }

    sorted_entry_names =self.config_entries_list.keys()
    sorted_entry_names.sort()
    for entry_name in sorted_entry_names:
      entry_el=self.config_entries_list[entry_name]
      if entry_el['rsl']!="":
        rsl_str='rsl=%s' % xml.sax.saxutils.quoteattr(entry_el['rsl'])
      else:
        rsl_str=""

      data = data + """
%(indent2)s<!-- %(entry_name)s -->
%(indent2)s<entry name="%(entry_name)s" gridtype="%(gridtype)s" gatekeeper="%(gatekeeper)s" %(rsl)s work_dir="%(workdir)s">
%(indent3)s<infosys_refs>
%(infosys_ref)s
%(indent3)s</infosys_refs> 
%(indent3)s<attrs>
%(indent4)s<attr name="GLIDEIN_Site" value="%(site_name)s"   const="True" type="string" glidein_publish="True"  publish="True"  job_publish="True"  parameter="True"/>
%(indent4)s<attr name="CONDOR_OS"    value="default"         const="True" type="string" glidein_publish="False" publish="False" job_publish="False" parameter="True"/>
%(indent4)s<attr name="CONDOR_ARCH"  value="default"         const="True" type="string" glidein_publish="False" publish="False" job_publish="False" parameter="True"/>
%(indent4)s<attr name="GLEXEC_BIN"   value="%(glexec_path)s" const="True" type="string" glidein_publish="False" publish="True"  job_publish="False" parameter="True"/>
%(ccb_attr)s
%(indent3)s</attrs>
%(indent3)s<files>
%(indent3)s</files>
%(indent2)s</entry> 
""" % { "indent2"     : common.indent(2),
  "indent3"     : common.indent(3), 
  "indent4"     : common.indent(4),
  "entry_name"  : entry_name,
  "rsl"         : rsl_str,
  "gridtype"    : entry_el['gridtype'],
  "gatekeeper"  : entry_el['gatekeeper'],
  "workdir"     : entry_el['work_dir'],
  "infosys_ref" : self.entry_infosys_ref_data(entry_el['is_ids']),
  "ccb_attr"    : self.entry_ccb_attrs(),
  "site_name"   : entry_el['site_name'],
  "glexec_path" : entry_el['glexec_path'],
}

    #--- end of entry element --
    data = data + """%(indent1)s</entries> """ % \
{ "indent1" : common.indent(1), 
}
    return data

   #-----------------
  def entry_ccb_attrs(self):
    data = ""
    if self.glidein.use_ccb() == "y":
      # Put USE_CCB in the entries so that it is easy to disable it selectively
      data = data + """%s<attr name="USE_CCB" value="True" const="True" type="string" glidein_publish="True" publish="True" job_publish="False" parameter="True"/>""" % (common.indent(1))
    return data

  #-------------
  def entry_infosys_ref_data(self,is_els):
    data = ""
    for is_el in is_els:
      data = data + """%(indent4)s<infosys_ref type="%(type)s" server="%(server)s" ref="%(name)s"/>
""" % \
{ "indent4" : common.indent(4),
  "type"    : is_el['type'],
  "server"  : is_el['server'],
  "name"    : is_el['name'],
}
    return data

  #----------------------------
  def get_config_entries_data(self):
    common.logit("\nCollecting  configuration file data. It will be question/answer time.")
    os.environ["PATH"] = "%s/bin:%s" %(self.wms.condor_location(),os.environ["PATH"])
    os.environ["CONDOR_CONFIG"] = self.wms.condor_config()
    common.logit("Using %s" % (os.environ["CONDOR_CONFIG"])) 
    self.config_entries_list = {}  # config files entries elements
    while 1:
      yn = common.ask_yn("Do you want to fetch entries from RESS")
      if yn == 'y':
        ress_data     = self.get_ress_data()
        filtered_data = self.apply_filters_to_ress(ress_data)
        self.ask_user(filtered_data)
      ## - tmp/permanent removal of BDII query as too may results occur 12/14/10 -
      ## yn = common.ask_yn("Do you want to fetch entries from BDII")
      ## if yn == 'y':
      ##   bdii_data     = self.get_bdii_data()
      ##   filtered_data = self.apply_filters_to_bdii(bdii_data)
      ##   self.ask_user(filtered_data)
      yn = common.ask_yn("Do you want to add manual entries")
      if yn == 'y':
        self.additional_entry_points()
      if len(self.config_entries_list) > 0:
        break
      common.logerr("You have no entry points. You need at least 1. Check your ini file's entry_vos and entry_filters attributes..")
    common.logit("Configuration file questioning complete.\n")
   

  #----------------------------
  def ask_user(self,ress_entries):
    ress_keys=ress_entries.keys()
    ress_keys.sort()

    print "Found %i additional entries" % len(ress_keys)
    if len(ress_keys) == 0:
      return
    yn = common.ask_yn("Do you want to use them all")
    if yn == "y":
        # simply copy all of them
        for key in ress_keys:
            self.config_entries_list[key] = ress_entries[key]
        return

    print "This is the list of entries found in RESS:"
    for key in ress_keys:
        print "[%s] %s(%s)"%(string.ljust(key,20),ress_entries[key]['gatekeeper'],ress_entries[key]['rsl'])

    print "Select the indexes you want to include"
    print "Use a , separated list to include more than one"
    while 1:
      idxes = raw_input("Please select: ")
      idx_arr = idxes.split(',')
      problems = 0
      for idx in idx_arr:
        if not (idx in ress_keys):
          print "'%s' is not a valid index!" % idx
          problems=1
          break
      if problems:
        continue

      # got them
      break

    yn = common.ask_yn("Do you want to customize them")
    if yn == "y":
      # customize them
      for idx in idx_arr:
        work_dir = raw_input("Work dir for '%s': [%s] " % (idx,ress_entries[idx]['work_dir']))
        if work_dir != "":
          ress_entries[idx]['work_dir'] = work_dir
        site_name=raw_input("Site name for '%s': [%s] " % (idx,ress_entries[idx]['site_name']))
        if site_name != "":
          ress_entries[idx]['site_name'] = site_name

      if self.glidein.use_glexec() == "y":
        glexec_path = raw_input("gLExec path for '%s': [%s] "%(idx,ress_entries[idx]['glexec_path']))
        if glexec_path != "":
          ress_entries[idx]['glexec_path'] = glexec_path

    for idx in idx_arr:
      self.config_entries_list[idx] = ress_entries[idx]

    return

  #----------------------------
  def apply_filters_to_ress(self,condor_data):
    #-- set up the  python filter ---
    common.logit("Filters: %s" % self.glidein.entry_filters())

    #-- using glexec? ---
    if self.glidein.use_glexec() == "y":
        def_glexec_bin='OSG'
    else:
        def_glexec_bin='NONE'

    cluster_count={}
    ress_entries={}
    python_filter_obj = self.get_python_filter(self.glidein.entry_filters())
    for condor_id in condor_data.keys():
      condor_el = condor_data[condor_id]

      if not self.passed_python_filter(python_filter_obj,condor_el):
        continue # has not passed the filter

      cluster_name    = condor_el['GlueClusterName']
      gatekeeper_name = condor_el['GlueCEInfoContactString']
      rsl = '(queue=%s)(jobtype=single)'%condor_el['GlueCEName']
      site_name=condor_el['GlueSiteName']

      work_dir = "OSG"
      ress_id  = {'type':'RESS','server':self.glidein.ress_host(),'name':condor_id}
      entry_el = {'gatekeeper':gatekeeper_name,'rsl':rsl,'gridtype':'gt2',
        'work_dir':work_dir,'site_name':site_name,'glexec_path':def_glexec_bin,
        'is_ids':[ress_id]}

      cluster_arr = cluster_name.split('.')
      if len(cluster_arr)<2:
        continue # something is wrong here, at least a.b expected

      t_found = False
      for t in ress_entries.keys():
        test_el = ress_entries[t]
        if self.compare_entry_els(test_el,entry_el):
          # found a duplicate entry, just add the additional ress entry to the list
          test_el['is_ids'].append(ress_id)
          t_found = True
          break
      if t_found:
        # found a duplicate entry, see next el
        continue

      cluster_id = "ress_%s"%site_name

      count = 1
      if cluster_count.has_key(cluster_id):
        count = cluster_count[cluster_id] + 1
      cluster_count[cluster_id] = count

      if count == 1:
        key_name = cluster_id
      else:
        key_name="%s_%i" % (cluster_id,count)

        if count == 2: # rename id -> id_1
          key_name_tmp = "%s_1" % cluster_id
          ress_entries[key_name_tmp] = ress_entries[cluster_id]
          del ress_entries[cluster_id]

      ress_entries[key_name]=entry_el
    # -- end for loop --

    entries = self.discard_duplicate_entries(ress_entries)
    return entries

  #----------------------------
  def apply_filters_to_bdii(self,bdii_data):
    #-- set up the  python filter ---
    common.logit("Filters: %s" % self.glidein.entry_filters())

    #-- using glexec? ---
    if self.glidein.use_glexec() == "y":
        def_glexec_bin='/opt/glite/sbin/glexec'
    else:
        def_glexec_bin='NONE'

    cluster_count={}
    bdii_entries={}
    python_filter_obj = self.get_python_filter(self.glidein.entry_filters())
    for ldap_id in bdii_data.keys():
      el2=bdii_data[ldap_id]

      # LDAP returns everything in lists... convert to values (i.e. get first element from list)
      scalar_el={}
      for k in el2.keys():
        scalar_el[k]=el2[k][0]

      if not self.passed_python_filter(python_filter_obj,scalar_el):
        continue # has not passed the filter

      work_dir="."
      #-- some entries do not have all the attributes --
      try:
        gatekeeper="%s:%s/jobmanager-%s" %\
           (el2['GlueCEHostingCluster'][0],
            el2['GlueCEInfoGatekeeperPort'][0],
            el2['GlueCEInfoJobManager'][0])
        rsl="(queue=%s)(jobtype=single)" % el2['GlueCEName'][0]
      except Exception, e:
        common.logwarn("This entry point (%s/%s) is being skipped.  A required schema attribute missing: %s" % (el2['GlueCEName'][0],el2['GlueCEHostingCluster'][0],e))

      site_name  = el2['Mds-Vo-name'][0]
      cluster_id  ="bdii_%s" % site_name

      bdii_id={'type':'BDII','server':self.glidein.bdii_host(),'name':ldap_id}

      count=1
      if cluster_count.has_key(cluster_id):
        count = cluster_count[cluster_id] + 1
      cluster_count[cluster_id] = count

      if count == 1:
        key_name = cluster_id
      else:
        key_name = "%s_%i" % (cluster_id,count)

        if count == 2: # rename id -> id_1
          key_name_tmp               = "%s_1"%cluster_id
          bdii_entries[key_name_tmp] = bdii_entries[cluster_id]
          del bdii_entries[cluster_id]

      guess_glexec_bin = def_glexec_bin
      if guess_glexec_bin != 'NONE':
        if el2['GlueCEHostingCluster'][0][-3:] in ('gov','edu'):
          # these should be OSG
          guess_glexec_bin = 'OSG'
        else:
          # I assume everybody else uses glite software
          guess_glexec_bin = '/opt/glite/sbin/glexec'

      bdii_entries[key_name] = {'gatekeeper':gatekeeper,
                                'rsl':rsl,'gridtype':'gt2',
                                'work_dir':work_dir, 
                                'site_name':site_name,
                                'glexec_path':guess_glexec_bin, 
                                'is_ids':[bdii_id]}
    #-- end for loop --

    entries = self.discard_duplicate_entries(bdii_entries)
    return entries