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

Karen Tian
Powered by
ViewCVS 0.9.4