(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 arta  1.25         # Always create a Rules.mk and target.mk, even if no proj XML is provided. All builds should have the proj/example and
 613                    # proj/cookbook directories.
 614                    projRules.extend(list(RULESPREFIX))
 615                    projTarget.extend(list(TARGETPREFIX))
 616                    
 617 arta  1.6          if not xml is None:
 618                        # Process xml.
 619                        rv = processXML(xml, projRules, projTarget)
 620 arta  1.25         projRules.extend(RULESSUFFIX)
 621 arta  1.6  
 622                # Process addenda - these are parameters that are not configurable and must be set in the 
 623                # NetDRMS build.
 624                if not rv:
 625                    iscfg = bool(0)
 626                    for key in addenda:
 627                        item = key + ' ' + addenda[key]
 628 arta  1.25             ppRet = processParam(iscfg, item, regexpQuote, regexp, keymap, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection, platDict, machDict, 'defs')
 629 arta  1.6              if ppRet:
 630                            break;
 631            
 632 arta  1.4      # Put information collected in platDict and machDict into mDefs. Must do this here, and not in processParam, since
 633                # we need to parse all platform-specific make variables before grouping them into platform categories.
 634 arta  1.3      if not rv:
 635                    for plat in platDict:
 636 arta  1.4              mDefsMake.extend(list('\nifeq ($(JSOC_MACHINE), linux_' + plat.lower() + ')'))
 637 arta  1.3              for var in platDict[plat]:
 638 arta  1.4                  mDefsMake.extend(list('\n' + var + ' = ' + platDict[plat][var]))
 639                        mDefsMake.extend(list('\nendif\n'))
 640 arta  1.3                               
 641                if not rv:
 642                    for mach in machDict:
 643 arta  1.4              mDefsMake.extend(list('\nifeq ($(MACHTYPE), ' + mach + ')'))
 644 arta  1.7              for var in machDict[mach]:
 645                            mDefsMake.extend(list('\n' + var + ' = ' + machDict[mach][var]))
 646 arta  1.4              mDefsMake.extend(list('\nendif\n'))
 647 arta  1.1      return rv
 648            
 649            def getMgrUIDLine(defs, uidParam):
 650                rv = bool(0)
 651                
 652                cmd = 'id -u ' + defs['SUMS_MANAGER']
 653                try:
 654                    ret = check_output(cmd, shell=True)
 655                    uidParam['q:SUMS_MANAGER_UID'] = ret.decode("utf-8")
 656                except ValueError:
 657                    print('Unable to run cmd: ' + cmd + '.')
 658                    rv = bool(1)
 659                except CalledProcessError:
 660                    print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 661                    rv = bool(1)
 662            
 663                return rv
 664            
 665 arta  1.3  def isVersion(maj, min, majDef, minDef):
 666                res = 0
 667                
 668                if maj > majDef or (maj == majDef and min >= minDef):
 669                    res = 1
 670                
 671                return res
 672            
 673            def configureComps(defs, mDefs):
 674                rv = bool(0)
 675 arta  1.6      autoConfig = bool(1)
 676            
 677                if 'AUTOSELCOMP' in defs:
 678                    autoConfig = (not defs['AUTOSELCOMP'] == '0')
 679 arta  1.3      
 680                if autoConfig:
 681                    hasicc = bool(0)
 682                    hasgcc = bool(0)
 683                    hasifort = bool(0)
 684                    hasgfort = bool(0)
 685                    
 686                    # Try icc.
 687 arta  1.12         cmd = 'icc --version 2>&1'
 688 arta  1.3          try:
 689                        ret = check_output(cmd, shell=True)
 690                        ret = ret.decode("utf-8")
 691                    except CalledProcessError:
 692                        print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 693                        rv = bool(1)
 694                    
 695 arta  1.6          if not rv:
 696 arta  1.12             regexp = re.compile(r"\s*\S+\s+\S+\s+(\d+)[.](\d+)", re.DOTALL)
 697 arta  1.3              matchobj = regexp.match(ret)
 698                        if matchobj is None:
 699                            raise Exception('unexpectedIccRet', ret)
 700                        else:
 701                            major = matchobj.group(1)
 702                            minor = matchobj.group(2)
 703                            if isVersion(int(major), int(minor), ICC_MAJOR, ICC_MINOR):
 704                                hasicc = bool(1)
 705 arta  1.19 
 706 arta  1.3          # Try gcc.
 707                    if not hasicc:
 708 arta  1.19             rv = bool(0)
 709 arta  1.3              cmd = 'gcc -v 2>&1'
 710                        try:
 711                            ret = check_output(cmd, shell=True)
 712                            ret = ret.decode("utf-8")
 713                        except CalledProcessError:
 714                            print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 715                            rv = bool(1)
 716            
 717 arta  1.19             if not rv:
 718 arta  1.3                  regexp = re.compile(r".+gcc\s+version\s+(\d+)\.(\d+)", re.DOTALL)
 719                            matchobj = regexp.match(ret)
 720                            if matchobj is None:
 721                                raise Exception('unexpectedGccRet', ret)
 722                            else:
 723                                major = matchobj.group(1)
 724                                minor = matchobj.group(2)
 725                                if isVersion(int(major), int(minor), GCC_MAJOR, GCC_MINOR):
 726                                    hasgcc = bool(1)
 727            
 728                    # Try ifort.
 729 arta  1.19         rv = bool(0)
 730 arta  1.12         cmd = 'ifort --version 2>&1'
 731 arta  1.3          try:
 732                        ret = check_output(cmd, shell=True)
 733                        ret = ret.decode("utf-8")
 734                    except CalledProcessError:
 735                        print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 736                        rv = bool(1)
 737            
 738 arta  1.6          if not rv:
 739 arta  1.12             regexp = re.compile(r"\s*\S+\s+\S+\s+(\d+)\.(\d+)", re.DOTALL)
 740 arta  1.3              matchobj = regexp.match(ret)
 741                        if matchobj is None:
 742                            raise Exception('unexpectedIfortRet', ret)
 743                        else:
 744                            major = matchobj.group(1)
 745                            minor = matchobj.group(2)
 746                            if isVersion(int(major), int(minor), IFORT_MAJOR, IFORT_MINOR):
 747                                hasifort = bool(1)
 748                    
 749                    # Try gfortran
 750                    if not hasifort:
 751 arta  1.19             rv = bool(0)
 752 arta  1.3              cmd = 'gfortran -v 2>&1'
 753                        try:
 754                            ret = check_output(cmd, shell=True)
 755                            ret = ret.decode("utf-8")
 756                        except CalledProcessError:
 757                            print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 758                            rv = bool(1)
 759            
 760 arta  1.19             if not rv:
 761 arta  1.3                  regexp = re.compile(r".+gcc\s+version\s+(\d+)\.(\d+)", re.DOTALL)
 762                            matchobj = regexp.match(ret)
 763                            if matchobj is None:
 764                                raise Exception('unexpectedGfortranRet', ret)
 765                            else:
 766                                major = matchobj.group(1)
 767                                minor = matchobj.group(2)
 768                                if isVersion(int(major), int(minor), GFORT_MAJOR, GFORT_MINOR):
 769                                    hasgfort = bool(1)
 770                    
 771 arta  1.19         # Append the compiler make variables to the make file
 772                    rv = bool(0)
 773                    
 774 arta  1.3          if not hasicc and not hasgcc:
 775                        print('Fatal error: Acceptable C compiler not found! You will be unable to build the DRMS library.', file=sys.stderr)
 776                        rv = bool(1)
 777                    elif hasicc:
 778                        mDefs.extend(list('\nCOMPILER = icc'))
 779                    else:
 780                        mDefs.extend(list('\nCOMPILER = gcc'))
 781            
 782                    if not hasifort and not hasgfort:
 783                        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)
 784                    elif hasifort:
 785                        mDefs.extend(list('\nFCOMPILER = ifort'))
 786                    else:
 787                        mDefs.extend(list('\nFCOMPILER = gfortran'))
 788                
 789                    # Environment overrides. These get written, regardless of the disposition of auto-configuration.
 790 arta  1.9          mDefs.extend(list('\nifneq ($(JSOC_COMPILER),)\n  COMPILER = $(JSOC_COMPILER)\nendif'))
 791                    mDefs.extend(list('\nifneq ($(JSOC_FCOMPILER),)\n  FCOMPILER = $(JSOC_FCOMPILER)\nendif'))
 792 arta  1.3  
 793                return rv
 794            
 795 arta  1.25 def writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection):
 796 arta  1.1      rv = bool(0)
 797 arta  1.4  
 798                # Merge mDefsGen, mDefsMake, and mDefsComps into a single string with compiler configuration first, general parameters next, then
 799                # make-specific make variables (e.g., third-party library information) last.
 800                mDefs = '\n# Compiler Selection\n' + ''.join(mDefsComps) + '\n\n# General Parameters\n' + ''.join(mDefsGen) + '\n\n# Parameters to Configure make\n' + ''.join(mDefsMake)
 801 arta  1.1      
 802                try:
 803 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:
 804 arta  1.1              # C file of macros
 805 arta  1.2              print(C_PREFIX, file=cout)
 806                        print('/* This file contains a set of preprocessor macros - one for each configuration parameter. */\n', file=cout)
 807 arta  1.1              buf = '__' + base.upper() + '_H'
 808                        print('#ifndef ' + buf, file=cout)
 809                        print('#define ' + buf, file=cout)
 810                        print(''.join(cDefs), file=cout)
 811                        print('#endif', file=cout)
 812                        
 813                        # Make file of make variables
 814 arta  1.2              print(PREFIX, file=mout)
 815 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)
 816                        print(mDefs, file=mout)
 817 arta  1.1              
 818 arta  1.2              # Perl module
 819                        print(PERL_BINPATH, file=pout)
 820                        print(PREFIX, file=pout)
 821                        print('# This file contains a set of constants - one for each configuration parameter.\n', file=pout)
 822                        print(PERL_INTIAL, file=pout)
 823 arta  1.1              print(''.join(perlConstSection), file=pout)
 824 arta  1.2              print(PERL_FXNS_A, file=pout)
 825 arta  1.1              print('sub initialize', file=pout)
 826                        print('{', file=pout)
 827 arta  1.2              print('  my($self) = shift;', file=pout, end='')
 828 arta  1.1              print('', file=pout)
 829                        print(''.join(perlInitSection), file=pout)
 830 arta  1.2              print('}\n', file=pout)
 831                        print(PERL_FXNS_B, file=pout)
 832 arta  1.18 
 833                        # Python module
 834                        print(PY_BINPATH, file=pyout)
 835                        print(PREFIX, file=pyout)
 836                        print('# This file contains a set of constants - one for each configuration parameter.\n', file=pyout)
 837                        print(''.join(pyConstSection), file=pyout)
 838                        print(PY_FXNS_A, file=pyout, end='')
 839                        print(''.join(pyInitSection), file=pyout)
 840                        print(PY_FXNS_B, file=pyout)
 841 arta  1.22             print(PY_FXNS_C, file=pyout)
 842 arta  1.25             
 843                        # Shell (bash) source file
 844                        print(SH_BINPATH, file=shout)
 845                        print(PREFIX, file=shout)
 846                        print('# This file contains a set of variable assignments - one for each configuration parameter.\n', file=shout)
 847                        print(''.join(shConstSection), file=shout)
 848 arta  1.18 
 849 arta  1.1      except IOError as exc:
 850 arta  1.6          type, value, traceback = sys.exc_info()
 851                    print(exc.strerror, file=sys.stderr)
 852                    print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)        
 853                    rv = bool(1)
 854            
 855                return rv
 856            
 857            def writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget):
 858                rv = bool(0)
 859            
 860                try:
 861                    if projCfg:
 862                        with open(pCfile, 'w') as cout:
 863                            # configure
 864                            print(''.join(projCfg), file=cout)
 865                    
 866                    if projMkRules:
 867                        with open(pMfile, 'w') as mout:
 868                            # make_basic.mk
 869                            print(PREFIX, file=mout)
 870                            print(''.join(projMkRules), file=mout)
 871 arta  1.6      
 872                    if projRules:
 873                        with open(pRfile, 'w') as rout:
 874                            # Rules.mk
 875                            print(PREFIX, file=rout)
 876                            print(''.join(projRules), file=rout)
 877                    
 878                    if projTarget:
 879                        with open(pTfile, 'w') as tout:
 880                            # target.mk
 881                            print(PREFIX, file=tout)
 882 arta  1.10                 print(''.join(projTarget), file=tout)
 883 arta  1.6      except IOError as exc:
 884                    type, value, traceback = sys.exc_info()
 885                    print(exc.strerror, file=sys.stderr)
 886                    print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)
 887 arta  1.1          rv = bool(1)
 888            
 889 arta  1.6      if not rv:
 890 arta  1.10         if os.path.exists(pCfile):
 891                        try:
 892                            os.chmod(pCfile, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
 893                        except OSError as exc:
 894                            type, value, traceback = sys.exc_info()
 895                            print('Unable to chmod file ' + "'" + value.filename + "'.", file=sys.stderr)
 896                            print(exc.strerror, file=sys.stderr)
 897                            rv = bool(1)
 898 arta  1.6  
 899 arta  1.1      return rv
 900 arta  1.3  
 901 arta  1.13 def generateSumRmCfg(defs):
 902                rv = bool(0)
 903                # ACK! Remember that Rick renamed these parameters. The ones in config.local are the aliases - do not use those.
 904                # Use the ones that those map to (defined in config.local.map).
 905                cFileTmp = defs['SUMLOG_BASEDIR'] + '/' + '.sum_rm.cfg.tmp'
 906                cFile = defs['SUMLOG_BASEDIR'] + '/' + 'sum_rm.cfg'
 907            
 908                # Write a temporary file sum_rm configuration file.
 909                try:
 910                    with open(cFileTmp, 'w') as fout:
 911                        # Print comment at the top of the configuration file.
 912                        print(SUMRM_COMMENT, file=fout)
 913                        print(SUMRM_DOC, file=fout)
 914                        print(SUMRM_PARTN_PERCENT_FREE, file=fout)
 915                        if 'SUMRM_PART_PERCENT_FREE' in defs:
 916                            print('PART_PERCENT_FREE=' + defs['SUMRM_PART_PERCENT_FREE'], file=fout)
 917                        else:
 918                            print('PART_PERCENT_FREE=3', file=fout)
 919            
 920                        print(SUMRM_SLEEP, file=fout)
 921                        if 'SUMRM_SLEEP' in defs:
 922 arta  1.13                 print('SLEEP=' + defs['SUMRM_SLEEP'], file=fout)
 923                        else:
 924                            print('SLEEP=300', file=fout)
 925            
 926                        print(SUMRM_LOG, file=fout)
 927                        if 'SUMRM_LOG' in defs:
 928                            print('LOG=' + defs['SUMRM_LOG'], file=fout)
 929                        else:
 930                            print('LOG=/tmp/sum_rm.log', file=fout)
 931            
 932                        print(SUMRM_MAIL, file=fout)
 933                        # No default for mail - don't send nothing to nobody unless the operator has asked for notifications.
 934                        if 'SUMRM_MAIL' in defs:
 935                            print('MAIL=' + defs['SUMRM_MAIL'], file=fout)
 936                        else:
 937                            print('# MAIL=president@whitehouse.gov', file=fout)
 938            
 939                        print(SUMRM_NOOP, file=fout)
 940                        if 'SUMRM_NOOP' in defs:
 941                            print('NOOP=' + defs['SUMRM_NOOP'], file=fout)
 942                        else:
 943 arta  1.13                 print('NOOP=0', file=fout)
 944            
 945                        print(SUMRM_USER, file=fout)
 946                        if 'SUMRM_USER' in defs:
 947                            print('USER=' + defs['SUMRM_USER'], file=fout)
 948                        else:
 949                            print('USER=production', file=fout)
 950            
 951                        print(SUMRM_NORUN, file=fout)
 952                        # Default norun window is to have no such window. This can be accomplished by simply not providing either argument.
 953                        if 'SUMRM_NORUN_START' in defs or 'SUMRM_NORUN_STOP' in defs:
 954                            if 'SUMRM_NORUN_START' in defs:
 955                                print('NORUN_START=' + defs['SUMRM_NORUN_START'], file=fout)
 956                            else:
 957                                print('NORUN_START=0', file=fout)
 958                            if 'SUMRM_NORUN_STOP' in defs:
 959                                print('NORUN_STOP=' + defs['SUMRM_NORUN_STOP'], file=fout)
 960                            else:
 961                                print('NORUN_STOP=0', file=fout)
 962                        else:
 963                            print('# NORUN_START=0', file=fout)
 964 arta  1.13                 print('# NORUN_STOP=0', file=fout)
 965                        
 966                except OSError:
 967                    print('Unable to open sum_rm temporary configuration file ' + cFileTmp + 'for writing.', file=sys.stderr)
 968                    rv = bool(1)
 969            
 970                # If the content of the temporary file differs from the content of the existing configuration file, then overwrite
 971                # the original file. Otherwise, delete the temporary file
 972                if not rv:
 973                    try:
 974                        if filecmp.cmp(cFile, cFileTmp):
 975                            # Files identical - delete temporary file
 976                            try:
 977                                os.remove(cFileTmp)
 978                            
 979                            except OSError as exc:
 980                                print('Unable to remove temporary file ' + exc.filename + '.', file=sys.stderr)
 981                                print(exc.strerr, file=sys.stderr)
 982                        else:
 983                            # Replace original with temporary file
 984                            try:
 985 arta  1.13                     os.rename(cFileTmp, cFile)
 986            
 987                            except OSError as exc:
 988                                print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
 989                                print(exc.strerr, file=sys.stderr)
 990                                rv = bool(1)
 991                    except OSError as exc:
 992                        # One of the files doesn't exist.
 993                        if exc.filename == cFile:
 994                            # We are ok - there might be no configuration file yet.
 995                            # Replace original with temporary file
 996                            try:
 997                                os.rename(cFileTmp, cFile)
 998            
 999                            except OSError as exc:
1000                                print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
1001                                print(exc.strerr, file=sys.stderr)
1002                                rv = bool(1)
1003                        else:
1004                            # There is a problem with the temp file - bail.
1005                            print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
1006 arta  1.13                 print(exc.strerr, file=sys.stderr)
1007                            rv = bool(1)
1008            
1009                return rv
1010            
1011 arta  1.25 def configureNet(cfgfile, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, base, keymap, createSumRmCfg):
1012 arta  1.1      rv = bool(0)
1013                
1014                defs = {}
1015                cDefs = list()
1016 arta  1.4      mDefsGen = list()
1017                mDefsMake = list()
1018                mDefsComps = list()
1019 arta  1.6      projCfg = list()
1020                projMkRules = list()
1021                projRules = list()
1022                projTarget = list()
1023 arta  1.1      perlConstSection = list()
1024                perlInitSection = list()
1025 arta  1.18     pyConstSection = list()
1026                pyInitSection = list()
1027 arta  1.25     shConstSection = list()
1028 arta  1.2      addenda = {}
1029                
1030 arta  1.6      # There are three parameters that were not included in the original config.local parameter set, for some reason.
1031                # Due to this omission, then are not configurable, and must be set in the script.
1032 arta  1.2      addenda['a:USER'] = 'NULL'
1033                addenda['a:PASSWD'] = 'NULL'
1034                addenda['p:DSDS_SUPPORT'] = '0'
1035 arta  1.6      
1036                # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
1037 arta  1.2      addenda['a:BUILD_TYPE'] = 'NETDRMS' # Means a non-Stanford build. This will set two additional macros used by make:
1038                                                    #   __LOCALIZED_DEFS__ and NETDRMS_BUILD. The former is to support legacy code
1039                                                    #   which incorrectly used this macro, and the latter is for future use. 
1040                                                    #   __LOCALIZED_DEFS__ is deprecated and should not be used in new code.
1041 arta  1.1  
1042                try:
1043                    with open(cfgfile, 'r') as fin:
1044 arta  1.3              # Process configuration parameters
1045 arta  1.25             rv = parseConfig(fin, keymap, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1046 arta  1.6              if not rv:
1047 arta  1.3                  # Must add a parameter for the SUMS_MANAGER UID (for some reason). This must be done after the
1048                            # config file is processed since an input to getMgrUIDLine() is one of the config file's
1049                            # parameter values.
1050 arta  1.1                  uidParam = {}
1051                            rv = getMgrUIDLine(defs, uidParam)
1052                            if rv == bool(0):
1053 arta  1.25                     rv = parseConfig(None, keymap, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1054 arta  1.3              # Configure the compiler-selection make variables.
1055 arta  1.6              if not rv:
1056 arta  1.4                  rv = configureComps(defs, mDefsComps)
1057 arta  1.1  
1058 arta  1.3              # Write out the parameter files.
1059 arta  1.6              if not rv:
1060 arta  1.25                 rv = writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1061 arta  1.13 
1062 arta  1.6              # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
1063                        if not rv:
1064                            rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
1065 arta  1.13 
1066                        # Write out the sum_rm.cfg file.
1067                        if not rv and createSumRmCfg:
1068                            rv = generateSumRmCfg(defs)
1069 arta  1.1      except IOError as exc:
1070 arta  1.6          print(exc.strerror, file=sys.stderr)
1071                    print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
1072 arta  1.3      except Exception as exc:
1073 arta  1.16         if len(exc.args) >= 2:
1074 arta  1.14             type, msg = exc.args
1075                    else:
1076                        # re-raise the exception
1077                        raise
1078            
1079 arta  1.3          if type == 'unexpectedIccRet':
1080                        print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
1081                        rv = bool(1)
1082                    elif type == 'unexpectedGccRet':
1083                        print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
1084                        rv = bool(1)
1085                    elif type == 'unexpectedIfortRet':
1086                        print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
1087                        rv = bool(1)
1088                    elif type == 'unexpectedGfortranRet':
1089                        print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
1090                        rv = bool(1)
1091                    else:
1092                        # re-raise the exception
1093                        raise
1094 arta  1.1          
1095 arta  1.2      return rv
1096 arta  1.1  
1097 arta  1.25 def configureSdp(cfgfile, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, base):
1098 arta  1.1      rv = bool(0)
1099                
1100                defs = {}
1101                cDefs = list()
1102 arta  1.5      mDefsGen = list()
1103                mDefsMake = list()
1104 arta  1.6      projCfg = list()
1105                projMkRules = list()
1106                projRules = list()
1107                projTarget = list()
1108 arta  1.5      mDefsComps = list()
1109 arta  1.1      perlConstSection = list()
1110                perlInitSection = list()
1111 arta  1.18     pyConstSection = list()
1112                pyInitSection = list()
1113 arta  1.25     shConstSection = list()
1114 arta  1.18 
1115 arta  1.2      addenda = {}
1116                
1117 arta  1.6      # There are three parameters that were not included in the original config.local parameter set, for some reason.
1118                # Due to this omission, then are not configurable, and must be set in the script.
1119 arta  1.5      addenda['a:USER'] = 'NULL'
1120                addenda['a:PASSWD'] = 'NULL'
1121                addenda['p:DSDS_SUPPORT'] = '1'
1122 arta  1.6      
1123                # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
1124 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.
1125 arta  1.1      
1126                try:
1127                    with open(cfgfile, 'r') as fin:
1128 arta  1.25             rv = parseConfig(fin, None, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1129 arta  1.6              
1130                        if not rv:
1131 arta  1.2                  # Must add a parameter for the SUMS_MANAGER UID (for some reason)
1132                            uidParam = {}
1133                            rv = getMgrUIDLine(defs, uidParam)
1134 arta  1.6                  if not rv:
1135 arta  1.25                     rv = parseConfig(None, None, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1136 arta  1.6  
1137 arta  1.5                  # Configure the compiler-selection make variables.
1138 arta  1.6                  if not rv:
1139 arta  1.5                      rv = configureComps(defs, mDefsComps)
1140 arta  1.3                  
1141 arta  1.6                  # Write out the parameter files.
1142                            if not rv:
1143 arta  1.25                     rv = writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1144 arta  1.6  
1145                            # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
1146                            if not rv:
1147                                rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
1148 arta  1.13 
1149                            # At Stanford, skip the creation of the sum_rm configuration file. config.local will still
1150                            # have the SUMRM parameters, but they will not be used.
1151 arta  1.1      except IOError as exc:
1152 arta  1.6          print(exc.strerror, file=sys.stderr)
1153                    print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
1154 arta  1.5      except Exception as exc:
1155 arta  1.17         if len(exc.args) >= 2:
1156                        type = exc.args[0]
1157                    else:
1158                        # re-raise the exception
1159                        raise
1160                    
1161 arta  1.5          if type == 'unexpectedIccRet':
1162 arta  1.6              msg = exc.args[1]
1163 arta  1.5              print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
1164                        rv = bool(1)
1165                    elif type == 'unexpectedGccRet':
1166 arta  1.6              msg = exc.args[1]
1167 arta  1.5              print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
1168                        rv = bool(1)
1169                    elif type == 'unexpectedIfortRet':
1170 arta  1.6              msg = exc.args[1]
1171 arta  1.5              print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
1172                        rv = bool(1)
1173                    elif type == 'unexpectedGfortranRet':
1174 arta  1.6              msg = exc.args[1]
1175 arta  1.5              print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
1176                        rv = bool(1)
1177                    else:
1178                        # re-raise the exception
1179                        raise
1180                    
1181 arta  1.2      return rv
1182            
1183 arta  1.1  # Beginning of program
1184            rv = RET_SUCCESS
1185            net = bool(1)
1186            
1187            # Parse arguments
1188            if __name__ == "__main__":
1189                optD = GetArgs(sys.argv[1:])
1190            
1191            if not(optD is None):
1192                # Ensure we are configuring a DRMS tree
1193                cdir = os.path.realpath(os.getcwd())
1194                versfile = cdir + '/base/' + VERS_FILE
1195            
1196                if not os.path.isfile(versfile):
1197                    rv = RET_NOTDRMS
1198            
1199            # Determine whether we are localizing a Stanford build, or a NetDRMS build. If configsdp.txt exists, then
1200            # it is a Stanford build, otherwise it is a NetDRMS build.
1201            if rv == RET_SUCCESS:
1202                stanfordFile = cdir + '/' + SDP_CFG
1203                if os.path.isfile(stanfordFile):
1204 arta  1.1          net = bool(0)
1205                
1206                cfile = optD['dir'] + '/' + optD['base'] + '.h'
1207                mfile = optD['dir'] + '/' + optD['base'] + '.mk'
1208                pfile = optD['dir'] + '/' + optD['base'] + '.pm'
1209 arta  1.18     pyfile = optD['dir'] + '/' + optD['base'] + '.py'
1210 arta  1.25     shfile = optD['dir'] + '/' + optD['base'] + '.sh'
1211 arta  1.6      pCfile = optD['dir'] + '/configure'
1212                pMfile = optD['dir'] + '/make_basic.mk'
1213                pRfile = optD['dir'] + '/Rules.mk'
1214                pTfile = optD['dir'] + '/target.mk'
1215 arta  1.1  
1216                if net:
1217                    try:
1218                        with open(NET_CFGMAP, 'r') as fin:
1219                            regexpComm = re.compile(r"^\s*#")
1220                            regexp = re.compile(r"^\s*(\S+)\s+(\w:\S+)")
1221                            # Must map from config.local namespace to DRMS namespace (e.g., the names used for the C macros)
1222                            keymap = {}
1223                            for line in fin:
1224                                matchobj = regexpComm.match(line)
1225                                if not matchobj is None:
1226                                    # Skip comment line
1227                                    continue
1228            
1229                                matchobj = regexp.match(line)
1230                                if not(matchobj is None):
1231                                    # We have a key-value line
1232                                    key = matchobj.group(1)
1233                                    val = matchobj.group(2)
1234                                    keymap[key] = val
1235                    except OSError:
1236 arta  1.1              sys.stderr.write('Unable to read configuration map-file ' + NET_CFGMAP + '.')
1237                        rv = bool(1)
1238            
1239                    # We also need to set the UID of the SUMS manager. We have the name of the
1240                    # SUMS manager (it is in the configuration file)
1241 arta  1.25         configureNet(NET_CFG, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, optD['base'], keymap, 'server' in optD)
1242 arta  1.1      else:
1243 arta  1.8          # A Stanford user can override the parameters in configsdp.txt by copying that file to config.local, 
1244                    # and then editing config.local. So, if config.local exists, use that.
1245                    if os.path.isfile(cdir + '/' + NET_CFG):
1246 arta  1.25             configureSdp(NET_CFG, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, optD['base'])
1247 arta  1.8          else:
1248 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