(file) Return to localize.py CVS log (file) (dir) Up to [Development] / JSOC

   1 arta  1.15 #!/usr/bin/python
   2 arta  1.1  
   3 arta  1.13 # When run with the -s flag, localize.py configures the SUMS-server component of NetDRMS.
   4 arta  1.15 from __future__ import print_function
   5 arta  1.1  import sys
   6            import getopt
   7            import re
   8 arta  1.6  import os
   9            import stat
  10 arta  1.13 import filecmp
  11 arta  1.6  import xml.etree.ElementTree as ET
  12 arta  1.1  from subprocess import check_output, CalledProcessError
  13            
  14 arta  1.24 if sys.version_info < (2, 7):
  15                raise Exception("You must run the 2.7 release, or a more recent release, of Python.")
  16            
  17 arta  1.1  # Constants
  18            VERS_FILE = 'jsoc_version.h'
  19            SDP_CFG = 'configsdp.txt'
  20            NET_CFG = 'config.local'
  21            NET_CFGMAP = 'config.local.map'
  22            RET_SUCCESS = 0
  23            RET_NOTDRMS = 1
  24            
  25 arta  1.2  PREFIX = """# This file was auto-generated by localize.py. Please do not edit it directly (running
  26            # configure will run localize.py, which will then overwrite any edits manually performed).
  27            """
  28 arta  1.1  
  29 arta  1.2  C_PREFIX = """/* This file was auto-generated by localize.py. Please do not edit it directly (running
  30             * configure will run localize.py, which will then overwrite any edits manually performed). */
  31 arta  1.1  """
  32            
  33 arta  1.2  PERL_BINPATH = '#!/usr/bin/perl\n'
  34            
  35            PERL_INTIAL = """package drmsparams;
  36                
  37            use warnings;
  38            use strict;
  39            """
  40            
  41            PERL_FXNS_A = """sub new
  42 arta  1.1  {
  43                my($clname) = shift;
  44                
  45                my($self) = 
  46                {
  47                    _paramsH => undef
  48                };
  49                
  50                bless($self, $clname);
  51 arta  1.9      $self->{_paramsH} = {};
  52                $self->initialize();
  53 arta  1.1      
  54                return $self;
  55            }
  56                
  57            sub DESTROY
  58            {
  59                my($self) = shift;
  60            }
  61 arta  1.2  """
  62            
  63            PERL_FXNS_B = """sub get
  64            {
  65                my($self) = shift;
  66                my($name) = shift;
  67                my($rv);
  68 arta  1.1      
  69 arta  1.2      if (exists($self->{_paramsH}->{$name}))
  70                {
  71                    return $self->{_paramsH}->{$name};
  72                }
  73                else
  74                {
  75                    return undef;
  76                }
  77            }
  78            1;"""
  79 arta  1.1  
  80 arta  1.25 PY_BINPATH = '#!/usr/bin/python\n'
  81 arta  1.18 
  82            PY_FXNS_A = """
  83 arta  1.23 class DRMSParams(object):
  84 arta  1.18     def __init__(self):
  85                    self.params = {}
  86                    self.initialize()
  87                    
  88                def __del__(self):
  89                    del self.params
  90                    
  91                def initialize(self):
  92            """
  93            
  94            PY_FXNS_B = """    def get(self, name):
  95                    if name in self.params:
  96 arta  1.20             return self.params[name]
  97 arta  1.18         else:
  98                        return None
  99            """
 100            
 101 arta  1.22 PY_FXNS_C = """    def getBool(self, name):
 102                    if name in self.params:
 103                        return bool(self.params[name] == '1')
 104                    else:
 105                        return None
 106            """
 107            
 108 arta  1.25 SH_BINPATH = '#!/bin/bash\n'
 109            
 110 arta  1.22 
 111 arta  1.13 SUMRM_COMMENT = """# This is the configuration file for the sum_rm program. It was auto-generated by the DRMS master configure script.
 112            # It controls the behavior of the sum_rm program, and is loaded each time sum_rm runs. To change the
 113            # parameter values in this configuration file, modify config.local, then re-run configure. This configuration
 114            # file will be updated only if parameters affecting it are modified. If such changes are made to config.local,
 115            # please make sure that the sum_rm service is disabled while configure in running.
 116            """
 117            
 118            SUMRM_DOC = """# sum_rm removes end-of-life SUMS data files to prevent disk-partitions from becomming 100% full. 
 119            # sum_svc, the main SUMS service, starts this daemon when it is launched. Within an infinite loop, sum_rm sleeps
 120            # for SLEEP number of seconds (defined below). When it awakes, it loads the sum_rm configuration file. For each SU,
 121            # it then examines the 'effective_date' column within the sum_partn_alloc table of the SUMS database. It does so by
 122            # sorting all SUs by effective date (this date is actually an expiration date - the SU is good until the end of that day),
 123            # and then, starting with the SU with the oldest effective date, it deletes the SUs. It continues deleting SUs until one
 124            # of three conditions is met:
 125            #
 126            #   (a) The disk has at least PART_PERCENT_FREE percent free space.
 127            #   (b) All SUs have effective_date values in the future.
 128            #   (c) At least 600 SUs have been deleted (this is defined in the LIMIT statement in the file SUMLIB_RmDoX.pgc).
 129            #
 130            # After sum_rm stops deleteing SUs, it then sleeps for SLEEP seconds, completing the first iteration of the
 131            # infinite loop.
 132 arta  1.13 """
 133            
 134            SUMRM_PARTN_PERCENT_FREE = """
 135            # This is the percentage at which all disk partitions are to be kept free.
 136            # If not specified, this defaults to 3. For example, setting PART_PERCENT_FREE = 5 will allow all partitions to
 137            # fill to 95% full. Dividing the number of unused blocks by the total number of blocks, and rounding up,
 138            # will result in the number specified by PART_PERCENT_FREE.
 139            #
 140            # NOTE : This behavior was previously controlled by the MAX_FREE_{n} family of parameters. {n} referred to the
 141            # disk-partition number and the value of parameter MAX_FREE_{n} was the MINIMUM number of free MB in the
 142            # partition [No clue why the word MAX was used]. As of NetDRMS 7.0, MAX_FREE_{n} has no effect."""
 143            
 144            SUMRM_SLEEP = """
 145            # The value is the number of seconds to sleep between iterations of the main loop in sum_rm."""
 146            
 147            SUMRM_LOG = """
 148            # The value is the log file (opened only at sum_rm startup; the sum_rm pid is appended to this file name)."""
 149            
 150            SUMRM_MAIL = """
 151            # The value is the email address of the recipient to be notified in case of a problem."""
 152            
 153 arta  1.13 SUMRM_NOOP = """
 154            # If the value is set to anything other than 0, then sum_rm is rendered inactive. Otherwise, sum_rm is active."""
 155            
 156            SUMRM_USER = """
 157            # The value designates the linux user who is allowed to run sum_rm."""
 158            
 159            SUMRM_NORUN = """
 160            # This pair of paramters defines a window of time, during which sum_rm will become torpid - in this
 161            # window, sum_rm will not scan for SUs to delete, not will it delete any SUs. Each value is an integer, 0-23, that
 162            # represents an hour of the day. For example, if NORUN_START=8 and NORUN_STOP=10, then between 8am and 10am
 163            # local time, sum_rm will be dormant. To disable this behavior, set both parameters to the same value."""
 164 arta  1.6  
 165            RULESPREFIX = """# Standard things
 166            sp 		:= $(sp).x
 167            dirstack_$(sp)	:= $(d)
 168            d		:= $(dir)
 169            """
 170            
 171            RULESSUFFIX = """dir	:= $(d)/example
 172            -include		$(SRCDIR)/$(dir)/Rules.mk
 173            dir	:= $(d)/cookbook
 174            -include		$(SRCDIR)/$(dir)/Rules.mk
 175            dir	:= $(d)/myproj
 176            -include		$(SRCDIR)/$(dir)/Rules.mk
 177            
 178            # Standard things
 179            d		:= $(dirstack_$(sp))
 180            sp		:= $(basename $(sp))
 181            """
 182            
 183            TARGETPREFIX = """$(PROJOBJDIR):\n\t+@[ -d $@ ] || mkdir -p $@"""
 184            
 185 arta  1.3  ICC_MAJOR = 9
 186            ICC_MINOR = 0
 187            GCC_MAJOR = 3
 188            GCC_MINOR = 0
 189            IFORT_MAJOR = 9
 190            IFORT_MINOR = 0
 191            GFORT_MAJOR = 4
 192            GFORT_MINOR = 2
 193            
 194            
 195 arta  1.1  # Read arguments
 196            #  d - localization directory
 197            #  b - base name of all parameter files (e.g., -b drmsparams --> drmsparams.h, drmsparams.mk, drmsparams.pm, etc.)
 198 arta  1.13 #  s - configure a NetDRMS server (i.e., SUMS server). Otherwise, do client configuration only. A server
 199            #      configuration will modify something that only the production user has access to. An example is the sum_rm.cfg
 200            #      file. To modify that file, the user running configure must be running configure on the SUMS-server host, and
 201            #      must have write permission on sum_rm.cfg.
 202 arta  1.1  def GetArgs(args):
 203                rv = bool(0)
 204                optD = {}
 205                
 206                try:
 207 arta  1.13         opts, remainder = getopt.getopt(args, "hd:b:s",["dir=", "base="])
 208 arta  1.1      except getopt.GetoptError:
 209                    print('Usage:')
 210                    print('localize.py [-h] -d <localization directory> -b <parameter file base>')
 211                    rv = bool(1)
 212                
 213                if rv == bool(0):
 214                    for opt, arg in opts:
 215                        if opt == '-h':
 216                            print('localize.py [-h] -d <localization directory> -b <parameter file base>')
 217                        elif opt in ("-d", "--dir"):
 218                            regexp = re.compile(r"(\S+)/?")
 219                            matchobj = regexp.match(arg)
 220                            if matchobj is None:
 221                                rv = bool(1)
 222                            else:
 223                                optD['dir'] = matchobj.group(1)
 224                        elif opt in ("-b", "--base"):
 225                            optD['base'] = arg
 226 arta  1.13             elif opt in ("-s"):
 227                            optD['server'] = ""
 228 arta  1.1              else:
 229                            optD[opt] = arg
 230            	
 231                return optD
 232            
 233            def createMacroStr(key, val, keyColLen, status):
 234                if keyColLen < len(key):
 235                    status = bool(1)
 236                    return None
 237                else:
 238                    nsp = keyColLen - len(key)
 239                    spaces = str()
 240                    for isp in range(nsp):
 241                        spaces += ' '
 242                    status = bool(0)
 243                    return '#define ' + key + spaces + val + '\n'
 244            
 245            def createPerlConst(key, val, keyColLen, status):
 246                if keyColLen < len(key):
 247                    status = bool(1)
 248                    return None
 249 arta  1.1      else:
 250                    nsp = keyColLen - len(key)
 251                    spaces = str()
 252                    for isp in range(nsp):
 253                        spaces += ' '
 254                    status = bool(0)
 255                    return 'use constant ' + key + ' => ' + spaces + val + ';\n'
 256            
 257 arta  1.18 def createPyConst(key, val, keyColLen, status):
 258                if keyColLen < len(key):
 259                    status = bool(1)
 260                    return None
 261                else:
 262                    nsp = keyColLen - len(key)
 263                    spaces = str()
 264                    for isp in range(nsp):
 265                        spaces += ' '
 266                    status = bool(0)
 267                    return key + ' = ' + spaces + val + '\n'
 268 arta  1.25         
 269            def createShConst(key, val, status):
 270                status = bool(0)
 271                return key + '=' + val + '\n'
 272                    
 273 arta  1.18 
 274 arta  1.3  def isSupportedPlat(plat):
 275                regexp = re.compile(r"\s*(^x86_64|^ia32|^ia64|^avx)", re.IGNORECASE)
 276                matchobj = regexp.match(plat);
 277                    
 278                if not matchobj is None:
 279                    return bool(1);
 280                else:
 281                    return bool(0);
 282            
 283 arta  1.6  def processMakeParam(mDefs, key, val, platDict, machDict):
 284 arta  1.3      varMach = None
 285                regexp = re.compile(r"(\S+):(\S+)")
 286                matchobj = regexp.match(key)
 287                if not matchobj is None:
 288                    varName = matchobj.group(1)
 289                    varMach = matchobj.group(2)
 290                else:
 291                    varName = key
 292                
 293                varValu = val
 294                    
 295                if varMach is None:
 296                    mDefs.extend(list('\n' + varName + ' = ' + varValu))
 297                else:
 298                    if isSupportedPlat(varMach):
 299                        # The guard will compare varValu to $JSOC_MACHINE.
 300                        if not varMach in platDict:
 301                            platDict[varMach] = {}
 302                        platDict[varMach][varName] = varValu
 303                    else:
 304                        # The guard will compare varValu to $MACHINETYPE (this is just the hostname of the machine on which localize.py is running).
 305 arta  1.3              if not varMach in machDict:
 306                            machDict[varMach] = {}
 307                        machDict[varMach][varName] = varValu
 308            
 309 arta  1.25 def processParam(cfgfile, line, regexpQuote, regexp, keymap, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection, platDict, machDict, section):
 310 arta  1.1      status = 0
 311                        
 312                if ''.join(section) == 'defs' or not cfgfile:
 313                    matchobj = regexp.match(line)
 314                    if not matchobj is None:
 315                        # We have a key-value line
 316                        keyCfgSp = matchobj.group(1)
 317                        val = matchobj.group(2)
 318                        
 319                        # Must map the indirect name to the actual name
 320                        if keymap:
 321                            # Map to actual name only if the keymap is not empty (which signifies NA).
 322                            if keyCfgSp in keymap:
 323                                key = keymap[keyCfgSp]
 324                            elif keyCfgSp == 'LOCAL_CONFIG_SET' or keyCfgSp == 'DRMS_SAMPLE_NAMESPACE':
 325 arta  1.6                      # Ignore parameters that are not useful and shouldn't have been there in the first place. But
 326                                # they have been released to the world, so we have to account for them.
 327 arta  1.1                      return bool(0)
 328                            elif not cfgfile:
 329                                # Should not be doing mapping for addenda
 330                                key = keyCfgSp
 331                            else:
 332                                raise Exception('badKeyMapKey', keyCfgSp)
 333                        else:
 334                            key = keyCfgSp
 335                        
 336                        matchobj = regexpQuote.match(key)
 337                        if not matchobj is None:
 338                            quote = matchobj.group(1)
 339                            key = matchobj.group(2)
 340            
 341                            # master defs dictionary
 342                            defs[key] = val
 343                            
 344                            # C header file
 345                            if quote == "q":
 346                                # Add double-quotes
 347                                cDefs.extend(list(createMacroStr(key, '"' + val + '"', 40, status)))
 348 arta  1.1                  elif quote == "p":
 349                                # Add parentheses
 350                                cDefs.extend(list(createMacroStr(key, '(' + val + ')', 40, status)))
 351                            elif quote == "a":
 352                                # Leave as-is
 353                                cDefs.extend(list(createMacroStr(key, val, 40, status)))
 354                            else:
 355                                # Unknown quote type
 356                                raise Exception('badQuoteQual', key)
 357                            
 358                            if status:
 359                                raise Exception('paramNameTooLong', key)
 360                            
 361                            # Make file - val should never be quoted; just use as is
 362 arta  1.4                  mDefsGen.extend(list('\n' + key + ' = ' + val))
 363 arta  1.1                  
 364                            # Perl file - val should ALWAYS be single-quote quoted
 365                            # Save const info to a string
 366                            perlConstSection.extend(list(createPerlConst(key, "'" + val + "'", 40, status)))
 367                            
 368 arta  1.18                 # Python file
 369                            pyConstSection.extend(list(createPyConst(key, "'" + val + "'", 40, status)))
 370                            
 371 arta  1.25                 # Shell source file
 372                            shConstSection.extend(list(createShConst(key, "'" + val + "'", status)))
 373                            
 374 arta  1.1                  if status:
 375                                raise Exception('paramNameTooLong', key)
 376                            
 377                            # Save initialization information as a string. Now that we've defined
 378                            # constants (the names of which are the parameter names) 
 379                            # we can refer to those in the init section. The key variable holds the
 380                            # name of the constant.
 381 arta  1.9                  perlInitSection.extend(list("\n  $self->{_paramsH}->{'" + key + "'} = " + key + ';'))
 382 arta  1.18                 
 383                            # The amount of indenting matters! This is Python.
 384                            pyInitSection.extend(list("        self.params['" + key + "'] = " + key + '\n'))
 385 arta  1.1              else:
 386                            # No quote qualifier
 387                            raise Exception('missingQuoteQual', key)
 388 arta  1.3      elif ''.join(section) == 'make' and cfgfile:
 389                    # Configure the remaining make variables defined in the __MAKE__ section of the configuration file. Third-party
 390                    # library make variables are specified in the __MAKE__ section.
 391                    matchobj = regexp.match(line)
 392                    if not matchobj is None:
 393                        # We have a key-value line
 394                        key = matchobj.group(1)
 395                        val = matchobj.group(2)
 396            
 397                        # This information is for making make variables only. We do not need to worry about quoting any values
 398                        defs[key] = val
 399 arta  1.4              processMakeParam(mDefsMake, key, val, platDict, machDict)
 400 arta  1.1      
 401                return bool(0)
 402            
 403            # We have some extraneous line or a newline - ignore.
 404            
 405 arta  1.6  def processXML(xml, projRules, projTarget):
 406                rv = bool(0)
 407                
 408                # <projects>
 409                root = ET.fromstring(xml)
 410                
 411                # Iterate through each proj child.
 412                for proj in root.iter('proj'):
 413                    # Rules.mk
 414                    nameElem = proj.find('name')
 415                    rulesStr = 'dir     := $(d)/' + nameElem.text + '\n-include          $(SRCDIR)/$(dir)/Rules.mk\n'
 416                    
 417                    # make doesn't support logical operations in ifeq conditionals (you can't do ifeq (A AND B)), 
 418                    # so we need to write:
 419                    #   ifeq (A)
 420                    #      ifeq (B)
 421                    #        <do something>
 422                    #      endif
 423                    #   endif
 424                        
 425                    rulesPref = '';
 426 arta  1.6          rulesSuff = '';
 427                
 428                    filters = proj.find('filters')
 429                    if filters is not None:
 430                        for filter in filters.findall('filter'):
 431                            rulesPref += 'ifeq ($(' + filter.find('name').text + '),' + filter.find('value').text + ')\n'
 432                            rulesSuff += 'endif\n'
 433                        
 434                    if len(rulesPref) > 0 and len(rulesSuff) > 0:
 435                        projRules.extend(list(rulesPref))
 436                        projRules.extend(list(rulesStr))
 437                        projRules.extend(list(rulesSuff))
 438                    else:
 439                        projRules.extend(list(rulesStr))
 440                    
 441                    # target.mk
 442                    subdirs = proj.find('subdirs')
 443                    if subdirs is not None:
 444                        for subdir in subdirs.findall('subdir'):
 445                            targetStr = '\n\t+@[ -d $@/' + nameElem.text + '/' + subdir.text + ' ] || mkdir -p $@/' + nameElem.text + '/' + subdir.text
 446                            projTarget.extend(list(targetStr))
 447 arta  1.6  
 448                return rv
 449            
 450            def determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg):
 451                matchobj = regexpDefs.match(line)
 452                if not matchobj is None:
 453                    return 'defs'
 454                    
 455                matchobj = regexpMake.match(line)
 456                if not matchobj is None:
 457                    return 'make'
 458                    
 459                matchobj = regexpProjMkRules.match(line)
 460                if not matchobj is None:
 461                    return 'projmkrules'
 462                    
 463                matchobj = regexpProj.match(line)
 464                if not matchobj is None:
 465                    return 'proj'
 466                    
 467                matchobj = regexpProjCfg.match(line)
 468 arta  1.6      if not matchobj is None:
 469                    return 'projcfg'
 470            
 471                return None
 472            
 473 arta  1.1  # defs is a dictionary containing all parameters (should they be needed in this script)
 474 arta  1.6  # projCfg is the list containing the configure script content.
 475            # projMkRules is the list containing the make_basic.mk content.
 476            # projRules is the list containing the Rules.mk content.
 477            # projTargert is the list containing the target.mk content.
 478 arta  1.25 def parseConfig(fin, keymap, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection):
 479 arta  1.1      rv = bool(0)
 480                
 481                # Open required config file (config.local)
 482                try:
 483                    # Examine each line, looking for key=value pairs.
 484                    regexpDefs = re.compile(r"^__DEFS__")
 485                    regexpMake = re.compile(r"^__MAKE__")
 486 arta  1.6          regexpProjMkRules = re.compile(r"__PROJ_MK_RULES__")
 487                    regexpProj = re.compile(r"^__PROJ__")
 488                    regexpProjCfg = re.compile(r"^__PROJCFG__")
 489 arta  1.1          regexpComm = re.compile(r"^\s*#")
 490 arta  1.6          regexpSp = re.compile(r"^s*$")
 491 arta  1.1          regexpQuote = re.compile(r"^\s*(\w):(.+)")
 492 arta  1.6          regexpCustMkBeg = re.compile(r"^_CUST_")
 493                    regexpCustMkEnd = re.compile(r"^_ENDCUST_")
 494                    regexpDiv = re.compile(r"^__")
 495 arta  1.11         regexp = re.compile(r"^\s*(\S+)\s+(\S.*)")
 496 arta  1.1          
 497 arta  1.3          platDict = {}
 498                    machDict = {}
 499 arta  1.6          
 500                    xml = None
 501 arta  1.1          
 502                    # Process the parameters in the configuration file
 503                    if not fin is None:
 504                        for line in fin:
 505 arta  1.6                  matchobj = regexpComm.match(line)
 506                            if not matchobj is None:
 507                                # Skip comment line
 508                                continue
 509                            
 510                            matchobj = regexpSp.match(line)
 511                            if not matchobj is None:
 512                                # Skip whitespace line
 513                                continue
 514 arta  1.1              
 515 arta  1.6                  newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 516                            if not newSection is None:
 517                                section = newSection
 518                
 519                            if section == 'make':
 520 arta  1.10 
 521 arta  1.6                      # There are some blocks of lines in the __MAKE__ section that must be copied ver batim to the output make file. 
 522                                # The blocks are defined by _CUST_/_ENDCUST_ tags.
 523                                matchobj = regexpCustMkBeg.match(line)
 524                                    
 525                                if not matchobj is None:
 526                                    mDefsMake.extend(list('\n'))
 527                                    for line in fin:
 528                                        matchobj = regexpCustMkEnd.match(line)
 529                                        if not matchobj is None:
 530                                            break;
 531                                        mDefsMake.extend(list(line))
 532                                    newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 533                                    if not newSection is None:
 534                                        section = newSection
 535                                    continue
 536                                # Intentional fall through to next if statement
 537                            if section == 'defs' or section == 'make':
 538                                iscfg = bool(1)
 539 arta  1.25                     ppRet = processParam(iscfg, line, regexpQuote, regexp, keymap, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection, platDict, machDict, section)
 540 arta  1.10                     
 541 arta  1.6                      if ppRet:
 542 arta  1.10                         break
 543 arta  1.6                  elif section == 'projcfg':
 544                                # Copy the line ver batim to the projCfg list (configure)
 545                                for line in fin:
 546                                    matchobj = regexpDiv.match(line)
 547                                    if not matchobj is None:
 548                                        break;
 549                                    projCfg.extend(list(line))
 550                                newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 551                                if not newSection is None:
 552                                    section = newSection
 553                                continue
 554                            elif section == 'projmkrules':
 555                                # Copy the line ver batim to the projMkRules list (make_basic.mk)
 556                                for line in fin:
 557                                    matchobj = regexpDiv.match(line)
 558                                    if not matchobj is None:
 559                                        break;
 560                                    projMkRules.extend(list(line))
 561                                newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 562                                if not newSection is None:
 563                                    section = newSection
 564 arta  1.6                      continue
 565                            elif section == 'proj':
 566                                # Must parse xml and use the project-specific information to populate the Rules.mk and target.mk files.
 567                                # Collect all xml lines for now, then process after file-read loop.
 568                                if xml is None:
 569 arta  1.21                         # The first time through this section, line is the config.local div, __PROJ__. Discard that.
 570                                    xml = ''
 571                                    continue
 572 arta  1.6                      else:
 573                                    xml += line
 574                            else:
 575 arta  1.10                     # Unknown section
 576 arta  1.6                      raise Exception('unknownSection', section)
 577 arta  1.1      except Exception as exc:
 578 arta  1.17         if len(exc.args) >= 2:
 579                        msg = exc.args[0]
 580                    else:
 581                        # re-raise the exception
 582                        raise
 583 arta  1.1          if msg == 'badKeyMapKey':
 584                        # If we are here, then there was a non-empty keymap, and the parameter came from
 585                        # the configuration file.
 586 arta  1.6              violator = exc.args[1]
 587 arta  1.17             print('Unknown parameter name ' + "'" + violator + "'" + ' in ' + fin.name + '.', file=sys.stderr)
 588 arta  1.1              rv = bool(1)
 589                    elif msg == 'badQuoteQual':
 590                        # The bad quote qualifier came from the configuration file, not the addenda, since
 591                        # we will have fixed any bad qualifiers in the addenda (which is populated by code).
 592 arta  1.6              violator = exc.args[1]
 593 arta  1.17             print('Unknown quote qualifier ' + "'" + violator + "'" + ' in ' + fin.name + '.', file=sys.stderr)
 594 arta  1.1              rv = bool(1)
 595                    elif msg == 'missingQuoteQual':
 596 arta  1.6              violator = exc.args[1]
 597 arta  1.17             print('Missing quote qualifier for parameter ' + "'" + violator + "'" + ' in ' + fin.name + '.', file=sys.stderr)
 598 arta  1.1              rv = bool(1)
 599                    elif msg == 'paramNameTooLong':
 600 arta  1.6              violator = exc.args[1]
 601 arta  1.1              print('Macro name ' + "'" + violator + "' is too long.", file=sys.stderr)
 602                        rv = bool(1)
 603 arta  1.6          elif msg == 'unknownSection':
 604                        violator = exc.args[1]
 605                        print('Unknown section ' + "'" + violator + "' in configuration file.", file=sys.stderr)
 606                        rv = bool(1)
 607 arta  1.1          else:
 608                        # re-raise the exception
 609                        raise
 610            
 611 arta  1.6      if not rv:
 612                    if not xml is None:
 613                        # Process xml.
 614                        rv = processXML(xml, projRules, projTarget)
 615            
 616                # Process addenda - these are parameters that are not configurable and must be set in the 
 617                # NetDRMS build.
 618                if not rv:
 619                    iscfg = bool(0)
 620                    for key in addenda:
 621                        item = key + ' ' + addenda[key]
 622 arta  1.25             ppRet = processParam(iscfg, item, regexpQuote, regexp, keymap, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection, platDict, machDict, 'defs')
 623 arta  1.6              if ppRet:
 624                            break;
 625            
 626 arta  1.4      # Put information collected in platDict and machDict into mDefs. Must do this here, and not in processParam, since
 627                # we need to parse all platform-specific make variables before grouping them into platform categories.
 628 arta  1.3      if not rv:
 629                    for plat in platDict:
 630 arta  1.4              mDefsMake.extend(list('\nifeq ($(JSOC_MACHINE), linux_' + plat.lower() + ')'))
 631 arta  1.3              for var in platDict[plat]:
 632 arta  1.4                  mDefsMake.extend(list('\n' + var + ' = ' + platDict[plat][var]))
 633                        mDefsMake.extend(list('\nendif\n'))
 634 arta  1.3                               
 635                if not rv:
 636                    for mach in machDict:
 637 arta  1.4              mDefsMake.extend(list('\nifeq ($(MACHTYPE), ' + mach + ')'))
 638 arta  1.7              for var in machDict[mach]:
 639                            mDefsMake.extend(list('\n' + var + ' = ' + machDict[mach][var]))
 640 arta  1.4              mDefsMake.extend(list('\nendif\n'))
 641 arta  1.1      return rv
 642            
 643            def getMgrUIDLine(defs, uidParam):
 644                rv = bool(0)
 645                
 646                cmd = 'id -u ' + defs['SUMS_MANAGER']
 647                try:
 648                    ret = check_output(cmd, shell=True)
 649                    uidParam['q:SUMS_MANAGER_UID'] = ret.decode("utf-8")
 650                except ValueError:
 651                    print('Unable to run cmd: ' + cmd + '.')
 652                    rv = bool(1)
 653                except CalledProcessError:
 654                    print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 655                    rv = bool(1)
 656            
 657                return rv
 658            
 659 arta  1.3  def isVersion(maj, min, majDef, minDef):
 660                res = 0
 661                
 662                if maj > majDef or (maj == majDef and min >= minDef):
 663                    res = 1
 664                
 665                return res
 666            
 667            def configureComps(defs, mDefs):
 668                rv = bool(0)
 669 arta  1.6      autoConfig = bool(1)
 670            
 671                if 'AUTOSELCOMP' in defs:
 672                    autoConfig = (not defs['AUTOSELCOMP'] == '0')
 673 arta  1.3      
 674                if autoConfig:
 675                    hasicc = bool(0)
 676                    hasgcc = bool(0)
 677                    hasifort = bool(0)
 678                    hasgfort = bool(0)
 679                    
 680                    # Try icc.
 681 arta  1.12         cmd = 'icc --version 2>&1'
 682 arta  1.3          try:
 683                        ret = check_output(cmd, shell=True)
 684                        ret = ret.decode("utf-8")
 685                    except CalledProcessError:
 686                        print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 687                        rv = bool(1)
 688                    
 689 arta  1.6          if not rv:
 690 arta  1.12             regexp = re.compile(r"\s*\S+\s+\S+\s+(\d+)[.](\d+)", re.DOTALL)
 691 arta  1.3              matchobj = regexp.match(ret)
 692                        if matchobj is None:
 693                            raise Exception('unexpectedIccRet', ret)
 694                        else:
 695                            major = matchobj.group(1)
 696                            minor = matchobj.group(2)
 697                            if isVersion(int(major), int(minor), ICC_MAJOR, ICC_MINOR):
 698                                hasicc = bool(1)
 699 arta  1.19 
 700 arta  1.3          # Try gcc.
 701                    if not hasicc:
 702 arta  1.19             rv = bool(0)
 703 arta  1.3              cmd = 'gcc -v 2>&1'
 704                        try:
 705                            ret = check_output(cmd, shell=True)
 706                            ret = ret.decode("utf-8")
 707                        except CalledProcessError:
 708                            print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 709                            rv = bool(1)
 710            
 711 arta  1.19             if not rv:
 712 arta  1.3                  regexp = re.compile(r".+gcc\s+version\s+(\d+)\.(\d+)", re.DOTALL)
 713                            matchobj = regexp.match(ret)
 714                            if matchobj is None:
 715                                raise Exception('unexpectedGccRet', ret)
 716                            else:
 717                                major = matchobj.group(1)
 718                                minor = matchobj.group(2)
 719                                if isVersion(int(major), int(minor), GCC_MAJOR, GCC_MINOR):
 720                                    hasgcc = bool(1)
 721            
 722                    # Try ifort.
 723 arta  1.19         rv = bool(0)
 724 arta  1.12         cmd = 'ifort --version 2>&1'
 725 arta  1.3          try:
 726                        ret = check_output(cmd, shell=True)
 727                        ret = ret.decode("utf-8")
 728                    except CalledProcessError:
 729                        print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 730                        rv = bool(1)
 731            
 732 arta  1.6          if not rv:
 733 arta  1.12             regexp = re.compile(r"\s*\S+\s+\S+\s+(\d+)\.(\d+)", re.DOTALL)
 734 arta  1.3              matchobj = regexp.match(ret)
 735                        if matchobj is None:
 736                            raise Exception('unexpectedIfortRet', ret)
 737                        else:
 738                            major = matchobj.group(1)
 739                            minor = matchobj.group(2)
 740                            if isVersion(int(major), int(minor), IFORT_MAJOR, IFORT_MINOR):
 741                                hasifort = bool(1)
 742                    
 743                    # Try gfortran
 744                    if not hasifort:
 745 arta  1.19             rv = bool(0)
 746 arta  1.3              cmd = 'gfortran -v 2>&1'
 747                        try:
 748                            ret = check_output(cmd, shell=True)
 749                            ret = ret.decode("utf-8")
 750                        except CalledProcessError:
 751                            print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 752                            rv = bool(1)
 753            
 754 arta  1.19             if not rv:
 755 arta  1.3                  regexp = re.compile(r".+gcc\s+version\s+(\d+)\.(\d+)", re.DOTALL)
 756                            matchobj = regexp.match(ret)
 757                            if matchobj is None:
 758                                raise Exception('unexpectedGfortranRet', ret)
 759                            else:
 760                                major = matchobj.group(1)
 761                                minor = matchobj.group(2)
 762                                if isVersion(int(major), int(minor), GFORT_MAJOR, GFORT_MINOR):
 763                                    hasgfort = bool(1)
 764                    
 765 arta  1.19         # Append the compiler make variables to the make file
 766                    rv = bool(0)
 767                    
 768 arta  1.3          if not hasicc and not hasgcc:
 769                        print('Fatal error: Acceptable C compiler not found! You will be unable to build the DRMS library.', file=sys.stderr)
 770                        rv = bool(1)
 771                    elif hasicc:
 772                        mDefs.extend(list('\nCOMPILER = icc'))
 773                    else:
 774                        mDefs.extend(list('\nCOMPILER = gcc'))
 775            
 776                    if not hasifort and not hasgfort:
 777                        print('Warning: Acceptable Fortran compiler not found! Fortran interface will not be built, and you will be unable to build Fortran modules.', file=sys.stderr)
 778                    elif hasifort:
 779                        mDefs.extend(list('\nFCOMPILER = ifort'))
 780                    else:
 781                        mDefs.extend(list('\nFCOMPILER = gfortran'))
 782                
 783                    # Environment overrides. These get written, regardless of the disposition of auto-configuration.
 784 arta  1.9          mDefs.extend(list('\nifneq ($(JSOC_COMPILER),)\n  COMPILER = $(JSOC_COMPILER)\nendif'))
 785                    mDefs.extend(list('\nifneq ($(JSOC_FCOMPILER),)\n  FCOMPILER = $(JSOC_FCOMPILER)\nendif'))
 786 arta  1.3  
 787                return rv
 788            
 789 arta  1.25 def writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection):
 790 arta  1.1      rv = bool(0)
 791 arta  1.4  
 792                # Merge mDefsGen, mDefsMake, and mDefsComps into a single string with compiler configuration first, general parameters next, then
 793                # make-specific make variables (e.g., third-party library information) last.
 794                mDefs = '\n# Compiler Selection\n' + ''.join(mDefsComps) + '\n\n# General Parameters\n' + ''.join(mDefsGen) + '\n\n# Parameters to Configure make\n' + ''.join(mDefsMake)
 795 arta  1.1      
 796                try:
 797 arta  1.25         with open(cfile, 'w') as cout, open(mfile, 'w') as mout, open(pfile, 'w') as pout, open(pyfile, 'w') as pyout, open(shfile, 'w') as shout:
 798 arta  1.1              # C file of macros
 799 arta  1.2              print(C_PREFIX, file=cout)
 800                        print('/* This file contains a set of preprocessor macros - one for each configuration parameter. */\n', file=cout)
 801 arta  1.1              buf = '__' + base.upper() + '_H'
 802                        print('#ifndef ' + buf, file=cout)
 803                        print('#define ' + buf, file=cout)
 804                        print(''.join(cDefs), file=cout)
 805                        print('#endif', file=cout)
 806                        
 807                        # Make file of make variables
 808 arta  1.2              print(PREFIX, file=mout)
 809 arta  1.4              print('# This file contains a set of make-variable values. The first section contains compiler-selection variables, the second contains general configuration variables, and the third section contains variables that configure how make is run.', file=mout)
 810                        print(mDefs, file=mout)
 811 arta  1.1              
 812 arta  1.2              # Perl module
 813                        print(PERL_BINPATH, file=pout)
 814                        print(PREFIX, file=pout)
 815                        print('# This file contains a set of constants - one for each configuration parameter.\n', file=pout)
 816                        print(PERL_INTIAL, file=pout)
 817 arta  1.1              print(''.join(perlConstSection), file=pout)
 818 arta  1.2              print(PERL_FXNS_A, file=pout)
 819 arta  1.1              print('sub initialize', file=pout)
 820                        print('{', file=pout)
 821 arta  1.2              print('  my($self) = shift;', file=pout, end='')
 822 arta  1.1              print('', file=pout)
 823                        print(''.join(perlInitSection), file=pout)
 824 arta  1.2              print('}\n', file=pout)
 825                        print(PERL_FXNS_B, file=pout)
 826 arta  1.18 
 827                        # Python module
 828                        print(PY_BINPATH, file=pyout)
 829                        print(PREFIX, file=pyout)
 830                        print('# This file contains a set of constants - one for each configuration parameter.\n', file=pyout)
 831                        print(''.join(pyConstSection), file=pyout)
 832                        print(PY_FXNS_A, file=pyout, end='')
 833                        print(''.join(pyInitSection), file=pyout)
 834                        print(PY_FXNS_B, file=pyout)
 835 arta  1.22             print(PY_FXNS_C, file=pyout)
 836 arta  1.25             
 837                        # Shell (bash) source file
 838                        print(SH_BINPATH, file=shout)
 839                        print(PREFIX, file=shout)
 840                        print('# This file contains a set of variable assignments - one for each configuration parameter.\n', file=shout)
 841                        print(''.join(shConstSection), file=shout)
 842 arta  1.18 
 843 arta  1.1      except IOError as exc:
 844 arta  1.6          type, value, traceback = sys.exc_info()
 845                    print(exc.strerror, file=sys.stderr)
 846                    print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)        
 847                    rv = bool(1)
 848            
 849                return rv
 850            
 851            def writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget):
 852                rv = bool(0)
 853            
 854                try:
 855                    if projCfg:
 856                        with open(pCfile, 'w') as cout:
 857                            # configure
 858                            print(''.join(projCfg), file=cout)
 859                    
 860                    if projMkRules:
 861                        with open(pMfile, 'w') as mout:
 862                            # make_basic.mk
 863                            print(PREFIX, file=mout)
 864                            print(''.join(projMkRules), file=mout)
 865 arta  1.6      
 866                    if projRules:
 867                        with open(pRfile, 'w') as rout:
 868                            # Rules.mk
 869                            print(PREFIX, file=rout)
 870                            print(''.join(projRules), file=rout)
 871                    
 872                    if projTarget:
 873                        with open(pTfile, 'w') as tout:
 874                            # target.mk
 875                            print(PREFIX, file=tout)
 876 arta  1.10                 print(''.join(projTarget), file=tout)
 877 arta  1.6      except IOError as exc:
 878                    type, value, traceback = sys.exc_info()
 879                    print(exc.strerror, file=sys.stderr)
 880                    print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)
 881 arta  1.1          rv = bool(1)
 882            
 883 arta  1.6      if not rv:
 884 arta  1.10         if os.path.exists(pCfile):
 885                        try:
 886                            os.chmod(pCfile, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
 887                        except OSError as exc:
 888                            type, value, traceback = sys.exc_info()
 889                            print('Unable to chmod file ' + "'" + value.filename + "'.", file=sys.stderr)
 890                            print(exc.strerror, file=sys.stderr)
 891                            rv = bool(1)
 892 arta  1.6  
 893 arta  1.1      return rv
 894 arta  1.3  
 895 arta  1.13 def generateSumRmCfg(defs):
 896                rv = bool(0)
 897                # ACK! Remember that Rick renamed these parameters. The ones in config.local are the aliases - do not use those.
 898                # Use the ones that those map to (defined in config.local.map).
 899                cFileTmp = defs['SUMLOG_BASEDIR'] + '/' + '.sum_rm.cfg.tmp'
 900                cFile = defs['SUMLOG_BASEDIR'] + '/' + 'sum_rm.cfg'
 901            
 902                # Write a temporary file sum_rm configuration file.
 903                try:
 904                    with open(cFileTmp, 'w') as fout:
 905                        # Print comment at the top of the configuration file.
 906                        print(SUMRM_COMMENT, file=fout)
 907                        print(SUMRM_DOC, file=fout)
 908                        print(SUMRM_PARTN_PERCENT_FREE, file=fout)
 909                        if 'SUMRM_PART_PERCENT_FREE' in defs:
 910                            print('PART_PERCENT_FREE=' + defs['SUMRM_PART_PERCENT_FREE'], file=fout)
 911                        else:
 912                            print('PART_PERCENT_FREE=3', file=fout)
 913            
 914                        print(SUMRM_SLEEP, file=fout)
 915                        if 'SUMRM_SLEEP' in defs:
 916 arta  1.13                 print('SLEEP=' + defs['SUMRM_SLEEP'], file=fout)
 917                        else:
 918                            print('SLEEP=300', file=fout)
 919            
 920                        print(SUMRM_LOG, file=fout)
 921                        if 'SUMRM_LOG' in defs:
 922                            print('LOG=' + defs['SUMRM_LOG'], file=fout)
 923                        else:
 924                            print('LOG=/tmp/sum_rm.log', file=fout)
 925            
 926                        print(SUMRM_MAIL, file=fout)
 927                        # No default for mail - don't send nothing to nobody unless the operator has asked for notifications.
 928                        if 'SUMRM_MAIL' in defs:
 929                            print('MAIL=' + defs['SUMRM_MAIL'], file=fout)
 930                        else:
 931                            print('# MAIL=president@whitehouse.gov', file=fout)
 932            
 933                        print(SUMRM_NOOP, file=fout)
 934                        if 'SUMRM_NOOP' in defs:
 935                            print('NOOP=' + defs['SUMRM_NOOP'], file=fout)
 936                        else:
 937 arta  1.13                 print('NOOP=0', file=fout)
 938            
 939                        print(SUMRM_USER, file=fout)
 940                        if 'SUMRM_USER' in defs:
 941                            print('USER=' + defs['SUMRM_USER'], file=fout)
 942                        else:
 943                            print('USER=production', file=fout)
 944            
 945                        print(SUMRM_NORUN, file=fout)
 946                        # Default norun window is to have no such window. This can be accomplished by simply not providing either argument.
 947                        if 'SUMRM_NORUN_START' in defs or 'SUMRM_NORUN_STOP' in defs:
 948                            if 'SUMRM_NORUN_START' in defs:
 949                                print('NORUN_START=' + defs['SUMRM_NORUN_START'], file=fout)
 950                            else:
 951                                print('NORUN_START=0', file=fout)
 952                            if 'SUMRM_NORUN_STOP' in defs:
 953                                print('NORUN_STOP=' + defs['SUMRM_NORUN_STOP'], file=fout)
 954                            else:
 955                                print('NORUN_STOP=0', file=fout)
 956                        else:
 957                            print('# NORUN_START=0', file=fout)
 958 arta  1.13                 print('# NORUN_STOP=0', file=fout)
 959                        
 960                except OSError:
 961                    print('Unable to open sum_rm temporary configuration file ' + cFileTmp + 'for writing.', file=sys.stderr)
 962                    rv = bool(1)
 963            
 964                # If the content of the temporary file differs from the content of the existing configuration file, then overwrite
 965                # the original file. Otherwise, delete the temporary file
 966                if not rv:
 967                    try:
 968                        if filecmp.cmp(cFile, cFileTmp):
 969                            # Files identical - delete temporary file
 970                            try:
 971                                os.remove(cFileTmp)
 972                            
 973                            except OSError as exc:
 974                                print('Unable to remove temporary file ' + exc.filename + '.', file=sys.stderr)
 975                                print(exc.strerr, file=sys.stderr)
 976                        else:
 977                            # Replace original with temporary file
 978                            try:
 979 arta  1.13                     os.rename(cFileTmp, cFile)
 980            
 981                            except OSError as exc:
 982                                print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
 983                                print(exc.strerr, file=sys.stderr)
 984                                rv = bool(1)
 985                    except OSError as exc:
 986                        # One of the files doesn't exist.
 987                        if exc.filename == cFile:
 988                            # We are ok - there might be no configuration file yet.
 989                            # Replace original with temporary file
 990                            try:
 991                                os.rename(cFileTmp, cFile)
 992            
 993                            except OSError as exc:
 994                                print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
 995                                print(exc.strerr, file=sys.stderr)
 996                                rv = bool(1)
 997                        else:
 998                            # There is a problem with the temp file - bail.
 999                            print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
1000 arta  1.13                 print(exc.strerr, file=sys.stderr)
1001                            rv = bool(1)
1002            
1003                return rv
1004            
1005 arta  1.25 def configureNet(cfgfile, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, base, keymap, createSumRmCfg):
1006 arta  1.1      rv = bool(0)
1007                
1008                defs = {}
1009                cDefs = list()
1010 arta  1.4      mDefsGen = list()
1011                mDefsMake = list()
1012                mDefsComps = list()
1013 arta  1.6      projCfg = list()
1014                projMkRules = list()
1015                projRules = list()
1016                projTarget = list()
1017 arta  1.1      perlConstSection = list()
1018                perlInitSection = list()
1019 arta  1.18     pyConstSection = list()
1020                pyInitSection = list()
1021 arta  1.25     shConstSection = list()
1022 arta  1.2      addenda = {}
1023                
1024 arta  1.6      # There are three parameters that were not included in the original config.local parameter set, for some reason.
1025                # Due to this omission, then are not configurable, and must be set in the script.
1026 arta  1.2      addenda['a:USER'] = 'NULL'
1027                addenda['a:PASSWD'] = 'NULL'
1028                addenda['p:DSDS_SUPPORT'] = '0'
1029 arta  1.6      
1030                # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
1031 arta  1.2      addenda['a:BUILD_TYPE'] = 'NETDRMS' # Means a non-Stanford build. This will set two additional macros used by make:
1032                                                    #   __LOCALIZED_DEFS__ and NETDRMS_BUILD. The former is to support legacy code
1033                                                    #   which incorrectly used this macro, and the latter is for future use. 
1034                                                    #   __LOCALIZED_DEFS__ is deprecated and should not be used in new code.
1035 arta  1.1  
1036                try:
1037                    with open(cfgfile, 'r') as fin:
1038 arta  1.3              # Process configuration parameters
1039 arta  1.26 
1040                        # Always create a Rules.mk and target.mk, even if no proj XML is provided. All builds should have the proj/example and
1041                        # proj/cookbook directories. The required make information is in RULESPREFIX, TARGETPREFIX, and RULESSUFFIX. RULESSUFFIX
1042                        # must be added after the xml has been parsed.
1043                        projRules.extend(list(RULESPREFIX))
1044                        projTarget.extend(list(TARGETPREFIX))
1045            
1046 arta  1.25             rv = parseConfig(fin, keymap, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1047 arta  1.6              if not rv:
1048 arta  1.26                 projRules.extend(RULESSUFFIX)
1049                        
1050 arta  1.3                  # Must add a parameter for the SUMS_MANAGER UID (for some reason). This must be done after the
1051                            # config file is processed since an input to getMgrUIDLine() is one of the config file's
1052                            # parameter values.
1053 arta  1.1                  uidParam = {}
1054                            rv = getMgrUIDLine(defs, uidParam)
1055                            if rv == bool(0):
1056 arta  1.25                     rv = parseConfig(None, keymap, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1057 arta  1.3              # Configure the compiler-selection make variables.
1058 arta  1.6              if not rv:
1059 arta  1.4                  rv = configureComps(defs, mDefsComps)
1060 arta  1.1  
1061 arta  1.3              # Write out the parameter files.
1062 arta  1.6              if not rv:
1063 arta  1.25                 rv = writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1064 arta  1.13 
1065 arta  1.6              # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
1066                        if not rv:
1067                            rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
1068 arta  1.13 
1069                        # Write out the sum_rm.cfg file.
1070                        if not rv and createSumRmCfg:
1071                            rv = generateSumRmCfg(defs)
1072 arta  1.1      except IOError as exc:
1073 arta  1.6          print(exc.strerror, file=sys.stderr)
1074                    print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
1075 arta  1.3      except Exception as exc:
1076 arta  1.16         if len(exc.args) >= 2:
1077 arta  1.14             type, msg = exc.args
1078                    else:
1079                        # re-raise the exception
1080                        raise
1081            
1082 arta  1.3          if type == 'unexpectedIccRet':
1083                        print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
1084                        rv = bool(1)
1085                    elif type == 'unexpectedGccRet':
1086                        print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
1087                        rv = bool(1)
1088                    elif type == 'unexpectedIfortRet':
1089                        print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
1090                        rv = bool(1)
1091                    elif type == 'unexpectedGfortranRet':
1092                        print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
1093                        rv = bool(1)
1094                    else:
1095                        # re-raise the exception
1096                        raise
1097 arta  1.1          
1098 arta  1.2      return rv
1099 arta  1.1  
1100 arta  1.25 def configureSdp(cfgfile, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, base):
1101 arta  1.1      rv = bool(0)
1102                
1103                defs = {}
1104                cDefs = list()
1105 arta  1.5      mDefsGen = list()
1106                mDefsMake = list()
1107 arta  1.6      projCfg = list()
1108                projMkRules = list()
1109                projRules = list()
1110                projTarget = list()
1111 arta  1.5      mDefsComps = list()
1112 arta  1.1      perlConstSection = list()
1113                perlInitSection = list()
1114 arta  1.18     pyConstSection = list()
1115                pyInitSection = list()
1116 arta  1.25     shConstSection = list()
1117 arta  1.18 
1118 arta  1.2      addenda = {}
1119                
1120 arta  1.6      # There are three parameters that were not included in the original config.local parameter set, for some reason.
1121                # Due to this omission, then are not configurable, and must be set in the script.
1122 arta  1.5      addenda['a:USER'] = 'NULL'
1123                addenda['a:PASSWD'] = 'NULL'
1124                addenda['p:DSDS_SUPPORT'] = '1'
1125 arta  1.6      
1126                # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
1127 arta  1.5      addenda['a:BUILD_TYPE'] = 'JSOC_SDP' # Means a Stanford build. This will set one additional macro used by make: JSOC_SDP_BUILD.
1128 arta  1.1      
1129                try:
1130                    with open(cfgfile, 'r') as fin:
1131 arta  1.26         
1132                        # Always create a Rules.mk and target.mk, even if no proj XML is provided. All builds should have the proj/example and
1133                        # proj/cookbook directories. The required make information is in RULESPREFIX, TARGETPREFIX, and RULESSUFFIX. RULESSUFFIX
1134                        # must be added after the xml has been parsed.
1135                        projRules.extend(list(RULESPREFIX))
1136                        projTarget.extend(list(TARGETPREFIX))
1137                        
1138 arta  1.25             rv = parseConfig(fin, None, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1139 arta  1.6              
1140                        if not rv:
1141 arta  1.26                 projRules.extend(RULESSUFFIX)
1142                        
1143 arta  1.2                  # Must add a parameter for the SUMS_MANAGER UID (for some reason)
1144                            uidParam = {}
1145                            rv = getMgrUIDLine(defs, uidParam)
1146 arta  1.6                  if not rv:
1147 arta  1.25                     rv = parseConfig(None, None, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1148 arta  1.6  
1149 arta  1.5                  # Configure the compiler-selection make variables.
1150 arta  1.6                  if not rv:
1151 arta  1.5                      rv = configureComps(defs, mDefsComps)
1152 arta  1.3                  
1153 arta  1.6                  # Write out the parameter files.
1154                            if not rv:
1155 arta  1.25                     rv = writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1156 arta  1.6  
1157                            # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
1158                            if not rv:
1159                                rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
1160 arta  1.13 
1161                            # At Stanford, skip the creation of the sum_rm configuration file. config.local will still
1162                            # have the SUMRM parameters, but they will not be used.
1163 arta  1.1      except IOError as exc:
1164 arta  1.6          print(exc.strerror, file=sys.stderr)
1165                    print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
1166 arta  1.5      except Exception as exc:
1167 arta  1.17         if len(exc.args) >= 2:
1168                        type = exc.args[0]
1169                    else:
1170                        # re-raise the exception
1171                        raise
1172                    
1173 arta  1.5          if type == 'unexpectedIccRet':
1174 arta  1.6              msg = exc.args[1]
1175 arta  1.5              print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
1176                        rv = bool(1)
1177                    elif type == 'unexpectedGccRet':
1178 arta  1.6              msg = exc.args[1]
1179 arta  1.5              print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
1180                        rv = bool(1)
1181                    elif type == 'unexpectedIfortRet':
1182 arta  1.6              msg = exc.args[1]
1183 arta  1.5              print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
1184                        rv = bool(1)
1185                    elif type == 'unexpectedGfortranRet':
1186 arta  1.6              msg = exc.args[1]
1187 arta  1.5              print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
1188                        rv = bool(1)
1189                    else:
1190                        # re-raise the exception
1191                        raise
1192                    
1193 arta  1.2      return rv
1194            
1195 arta  1.1  # Beginning of program
1196            rv = RET_SUCCESS
1197            net = bool(1)
1198            
1199            # Parse arguments
1200            if __name__ == "__main__":
1201                optD = GetArgs(sys.argv[1:])
1202            
1203            if not(optD is None):
1204                # Ensure we are configuring a DRMS tree
1205                cdir = os.path.realpath(os.getcwd())
1206                versfile = cdir + '/base/' + VERS_FILE
1207            
1208                if not os.path.isfile(versfile):
1209                    rv = RET_NOTDRMS
1210            
1211            # Determine whether we are localizing a Stanford build, or a NetDRMS build. If configsdp.txt exists, then
1212            # it is a Stanford build, otherwise it is a NetDRMS build.
1213            if rv == RET_SUCCESS:
1214                stanfordFile = cdir + '/' + SDP_CFG
1215                if os.path.isfile(stanfordFile):
1216 arta  1.1          net = bool(0)
1217                
1218                cfile = optD['dir'] + '/' + optD['base'] + '.h'
1219                mfile = optD['dir'] + '/' + optD['base'] + '.mk'
1220                pfile = optD['dir'] + '/' + optD['base'] + '.pm'
1221 arta  1.18     pyfile = optD['dir'] + '/' + optD['base'] + '.py'
1222 arta  1.25     shfile = optD['dir'] + '/' + optD['base'] + '.sh'
1223 arta  1.6      pCfile = optD['dir'] + '/configure'
1224                pMfile = optD['dir'] + '/make_basic.mk'
1225                pRfile = optD['dir'] + '/Rules.mk'
1226                pTfile = optD['dir'] + '/target.mk'
1227 arta  1.1  
1228                if net:
1229                    try:
1230                        with open(NET_CFGMAP, 'r') as fin:
1231                            regexpComm = re.compile(r"^\s*#")
1232                            regexp = re.compile(r"^\s*(\S+)\s+(\w:\S+)")
1233                            # Must map from config.local namespace to DRMS namespace (e.g., the names used for the C macros)
1234                            keymap = {}
1235                            for line in fin:
1236                                matchobj = regexpComm.match(line)
1237                                if not matchobj is None:
1238                                    # Skip comment line
1239                                    continue
1240            
1241                                matchobj = regexp.match(line)
1242                                if not(matchobj is None):
1243                                    # We have a key-value line
1244                                    key = matchobj.group(1)
1245                                    val = matchobj.group(2)
1246                                    keymap[key] = val
1247                    except OSError:
1248 arta  1.1              sys.stderr.write('Unable to read configuration map-file ' + NET_CFGMAP + '.')
1249                        rv = bool(1)
1250            
1251                    # We also need to set the UID of the SUMS manager. We have the name of the
1252                    # SUMS manager (it is in the configuration file)
1253 arta  1.25         configureNet(NET_CFG, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, optD['base'], keymap, 'server' in optD)
1254 arta  1.1      else:
1255 arta  1.8          # A Stanford user can override the parameters in configsdp.txt by copying that file to config.local, 
1256                    # and then editing config.local. So, if config.local exists, use that.
1257                    if os.path.isfile(cdir + '/' + NET_CFG):
1258 arta  1.25             configureSdp(NET_CFG, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, optD['base'])
1259 arta  1.8          else:
1260 arta  1.25             configureSdp(SDP_CFG, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, optD['base'])

Karen Tian
Powered by
ViewCVS 0.9.4