(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 arta  1.27 def determineSection(line, regexpStyle, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg):
 451                matchobj = regexpStyle.match(line)
 452                if matchobj:
 453                    return 'style'
 454            
 455 arta  1.6      matchobj = regexpDefs.match(line)
 456                if not matchobj is None:
 457                    return 'defs'
 458                    
 459                matchobj = regexpMake.match(line)
 460                if not matchobj is None:
 461                    return 'make'
 462                    
 463                matchobj = regexpProjMkRules.match(line)
 464                if not matchobj is None:
 465                    return 'projmkrules'
 466                    
 467                matchobj = regexpProj.match(line)
 468                if not matchobj is None:
 469                    return 'proj'
 470                    
 471                matchobj = regexpProjCfg.match(line)
 472                if not matchobj is None:
 473                    return 'projcfg'
 474            
 475                return None
 476 arta  1.6  
 477 arta  1.1  # defs is a dictionary containing all parameters (should they be needed in this script)
 478 arta  1.6  # projCfg is the list containing the configure script content.
 479            # projMkRules is the list containing the make_basic.mk content.
 480            # projRules is the list containing the Rules.mk content.
 481            # projTargert is the list containing the target.mk content.
 482 arta  1.25 def parseConfig(fin, keymap, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection):
 483 arta  1.1      rv = bool(0)
 484                
 485                # Open required config file (config.local)
 486                try:
 487                    # Examine each line, looking for key=value pairs.
 488 arta  1.27         regexpStyle = re.compile(r"^__STYLE__")
 489 arta  1.1          regexpDefs = re.compile(r"^__DEFS__")
 490                    regexpMake = re.compile(r"^__MAKE__")
 491 arta  1.6          regexpProjMkRules = re.compile(r"__PROJ_MK_RULES__")
 492                    regexpProj = re.compile(r"^__PROJ__")
 493                    regexpProjCfg = re.compile(r"^__PROJCFG__")
 494 arta  1.1          regexpComm = re.compile(r"^\s*#")
 495 arta  1.6          regexpSp = re.compile(r"^s*$")
 496 arta  1.1          regexpQuote = re.compile(r"^\s*(\w):(.+)")
 497 arta  1.6          regexpCustMkBeg = re.compile(r"^_CUST_")
 498                    regexpCustMkEnd = re.compile(r"^_ENDCUST_")
 499                    regexpDiv = re.compile(r"^__")
 500 arta  1.11         regexp = re.compile(r"^\s*(\S+)\s+(\S.*)")
 501 arta  1.27 
 502                    ignoreKeymap = False
 503 arta  1.3          platDict = {}
 504                    machDict = {}
 505 arta  1.6          
 506                    xml = None
 507 arta  1.1          
 508                    # Process the parameters in the configuration file
 509                    if not fin is None:
 510                        for line in fin:
 511 arta  1.6                  matchobj = regexpComm.match(line)
 512                            if not matchobj is None:
 513                                # Skip comment line
 514                                continue
 515                            
 516                            matchobj = regexpSp.match(line)
 517                            if not matchobj is None:
 518                                # Skip whitespace line
 519                                continue
 520 arta  1.1              
 521 arta  1.27                 newSection = determineSection(line, regexpStyle, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 522 arta  1.6                  if not newSection is None:
 523                                section = newSection
 524 arta  1.27                     
 525                            if not section:
 526                                raise Exception('invalidConfigFile', 'line ' + line.strip() + ' is not in any section')
 527 arta  1.6      
 528 arta  1.27                 if section == 'style':
 529                                # if the config.local file has new in the __STYLE__ section, then ignore the keymap and treat config.local like configsdp.txt;
 530                                # do not map from NetDRMS config.local parameter names to configsdp.txt names
 531                                for line in fin:
 532                                    matchobj = regexpDiv.match(line)
 533                                    if matchobj:
 534                                        break;
 535                                    if line.strip(' \n').lower() == 'new' and keymap:
 536                                        ignoreKeymap = True
 537            
 538                                newSection = determineSection(line, regexpStyle, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 539                                if not newSection is None:
 540                                    section = newSection
 541                                continue
 542                            elif section == 'make':
 543 arta  1.10 
 544 arta  1.6                      # There are some blocks of lines in the __MAKE__ section that must be copied ver batim to the output make file. 
 545                                # The blocks are defined by _CUST_/_ENDCUST_ tags.
 546                                matchobj = regexpCustMkBeg.match(line)
 547                                    
 548                                if not matchobj is None:
 549                                    mDefsMake.extend(list('\n'))
 550                                    for line in fin:
 551                                        matchobj = regexpCustMkEnd.match(line)
 552                                        if not matchobj is None:
 553                                            break;
 554                                        mDefsMake.extend(list(line))
 555 arta  1.27                         newSection = determineSection(line, regexpStyle, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 556 arta  1.6                          if not newSection is None:
 557                                        section = newSection
 558                                    continue
 559                                # Intentional fall through to next if statement
 560                            if section == 'defs' or section == 'make':
 561                                iscfg = bool(1)
 562 arta  1.27                     if ignoreKeymap:
 563                                    keymapActual = None
 564                                else:
 565                                    keymapActual = keymap
 566                                ppRet = processParam(iscfg, line, regexpQuote, regexp, keymapActual, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection, platDict, machDict, section)
 567 arta  1.10                     
 568 arta  1.6                      if ppRet:
 569 arta  1.10                         break
 570 arta  1.6                  elif section == 'projcfg':
 571                                # Copy the line ver batim to the projCfg list (configure)
 572                                for line in fin:
 573                                    matchobj = regexpDiv.match(line)
 574                                    if not matchobj is None:
 575                                        break;
 576                                    projCfg.extend(list(line))
 577 arta  1.27                     newSection = determineSection(line, regexpStyle, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 578 arta  1.6                      if not newSection is None:
 579                                    section = newSection
 580                                continue
 581                            elif section == 'projmkrules':
 582                                # Copy the line ver batim to the projMkRules list (make_basic.mk)
 583                                for line in fin:
 584                                    matchobj = regexpDiv.match(line)
 585                                    if not matchobj is None:
 586                                        break;
 587                                    projMkRules.extend(list(line))
 588 arta  1.27                     newSection = determineSection(line, regexpStyle, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
 589 arta  1.6                      if not newSection is None:
 590                                    section = newSection
 591                                continue
 592                            elif section == 'proj':
 593                                # Must parse xml and use the project-specific information to populate the Rules.mk and target.mk files.
 594                                # Collect all xml lines for now, then process after file-read loop.
 595                                if xml is None:
 596 arta  1.21                         # The first time through this section, line is the config.local div, __PROJ__. Discard that.
 597                                    xml = ''
 598                                    continue
 599 arta  1.6                      else:
 600                                    xml += line
 601                            else:
 602 arta  1.10                     # Unknown section
 603 arta  1.6                      raise Exception('unknownSection', section)
 604 arta  1.1      except Exception as exc:
 605 arta  1.17         if len(exc.args) >= 2:
 606                        msg = exc.args[0]
 607                    else:
 608                        # re-raise the exception
 609                        raise
 610 arta  1.27             
 611                    if msg == 'invalidConfigFile':
 612                        violator = exc.args[1]
 613                        print(violator, file=sys.stderr)
 614                        rv = bool(1)
 615                    elif msg == 'badKeyMapKey':
 616 arta  1.1              # If we are here, then there was a non-empty keymap, and the parameter came from
 617                        # the configuration file.
 618 arta  1.6              violator = exc.args[1]
 619 arta  1.17             print('Unknown parameter name ' + "'" + violator + "'" + ' in ' + fin.name + '.', file=sys.stderr)
 620 arta  1.1              rv = bool(1)
 621                    elif msg == 'badQuoteQual':
 622                        # The bad quote qualifier came from the configuration file, not the addenda, since
 623                        # we will have fixed any bad qualifiers in the addenda (which is populated by code).
 624 arta  1.6              violator = exc.args[1]
 625 arta  1.17             print('Unknown quote qualifier ' + "'" + violator + "'" + ' in ' + fin.name + '.', file=sys.stderr)
 626 arta  1.1              rv = bool(1)
 627                    elif msg == 'missingQuoteQual':
 628 arta  1.6              violator = exc.args[1]
 629 arta  1.17             print('Missing quote qualifier for parameter ' + "'" + violator + "'" + ' in ' + fin.name + '.', file=sys.stderr)
 630 arta  1.1              rv = bool(1)
 631                    elif msg == 'paramNameTooLong':
 632 arta  1.6              violator = exc.args[1]
 633 arta  1.1              print('Macro name ' + "'" + violator + "' is too long.", file=sys.stderr)
 634                        rv = bool(1)
 635 arta  1.6          elif msg == 'unknownSection':
 636                        violator = exc.args[1]
 637                        print('Unknown section ' + "'" + violator + "' in configuration file.", file=sys.stderr)
 638                        rv = bool(1)
 639 arta  1.1          else:
 640                        # re-raise the exception
 641                        raise
 642            
 643 arta  1.6      if not rv:
 644                    if not xml is None:
 645                        # Process xml.
 646                        rv = processXML(xml, projRules, projTarget)
 647            
 648                # Process addenda - these are parameters that are not configurable and must be set in the 
 649                # NetDRMS build.
 650                if not rv:
 651                    iscfg = bool(0)
 652                    for key in addenda:
 653                        item = key + ' ' + addenda[key]
 654 arta  1.27             if ignoreKeymap:
 655                            keymapActual = None
 656                        else:
 657                            keymapActual = keymap
 658                        ppRet = processParam(iscfg, item, regexpQuote, regexp, keymapActual, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection, platDict, machDict, 'defs')
 659 arta  1.6              if ppRet:
 660                            break;
 661            
 662 arta  1.4      # Put information collected in platDict and machDict into mDefs. Must do this here, and not in processParam, since
 663                # we need to parse all platform-specific make variables before grouping them into platform categories.
 664 arta  1.3      if not rv:
 665                    for plat in platDict:
 666 arta  1.4              mDefsMake.extend(list('\nifeq ($(JSOC_MACHINE), linux_' + plat.lower() + ')'))
 667 arta  1.3              for var in platDict[plat]:
 668 arta  1.4                  mDefsMake.extend(list('\n' + var + ' = ' + platDict[plat][var]))
 669                        mDefsMake.extend(list('\nendif\n'))
 670 arta  1.3                               
 671                if not rv:
 672                    for mach in machDict:
 673 arta  1.4              mDefsMake.extend(list('\nifeq ($(MACHTYPE), ' + mach + ')'))
 674 arta  1.7              for var in machDict[mach]:
 675                            mDefsMake.extend(list('\n' + var + ' = ' + machDict[mach][var]))
 676 arta  1.4              mDefsMake.extend(list('\nendif\n'))
 677 arta  1.1      return rv
 678            
 679            def getMgrUIDLine(defs, uidParam):
 680                rv = bool(0)
 681                
 682                cmd = 'id -u ' + defs['SUMS_MANAGER']
 683                try:
 684                    ret = check_output(cmd, shell=True)
 685                    uidParam['q:SUMS_MANAGER_UID'] = ret.decode("utf-8")
 686                except ValueError:
 687                    print('Unable to run cmd: ' + cmd + '.')
 688                    rv = bool(1)
 689                except CalledProcessError:
 690                    print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 691                    rv = bool(1)
 692            
 693                return rv
 694            
 695 arta  1.3  def isVersion(maj, min, majDef, minDef):
 696                res = 0
 697                
 698                if maj > majDef or (maj == majDef and min >= minDef):
 699                    res = 1
 700                
 701                return res
 702            
 703            def configureComps(defs, mDefs):
 704                rv = bool(0)
 705 arta  1.6      autoConfig = bool(1)
 706            
 707                if 'AUTOSELCOMP' in defs:
 708                    autoConfig = (not defs['AUTOSELCOMP'] == '0')
 709 arta  1.3      
 710                if autoConfig:
 711                    hasicc = bool(0)
 712                    hasgcc = bool(0)
 713                    hasifort = bool(0)
 714                    hasgfort = bool(0)
 715                    
 716                    # Try icc.
 717 arta  1.12         cmd = 'icc --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('unexpectedIccRet', ret)
 730                        else:
 731                            major = matchobj.group(1)
 732                            minor = matchobj.group(2)
 733                            if isVersion(int(major), int(minor), ICC_MAJOR, ICC_MINOR):
 734                                hasicc = bool(1)
 735 arta  1.19 
 736 arta  1.3          # Try gcc.
 737                    if not hasicc:
 738 arta  1.19             rv = bool(0)
 739 arta  1.3              cmd = 'gcc -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('unexpectedGccRet', ret)
 752                            else:
 753                                major = matchobj.group(1)
 754                                minor = matchobj.group(2)
 755                                if isVersion(int(major), int(minor), GCC_MAJOR, GCC_MINOR):
 756                                    hasgcc = bool(1)
 757            
 758                    # Try ifort.
 759 arta  1.19         rv = bool(0)
 760 arta  1.12         cmd = 'ifort --version 2>&1'
 761 arta  1.3          try:
 762                        ret = check_output(cmd, shell=True)
 763                        ret = ret.decode("utf-8")
 764                    except CalledProcessError:
 765                        print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 766                        rv = bool(1)
 767            
 768 arta  1.6          if not rv:
 769 arta  1.12             regexp = re.compile(r"\s*\S+\s+\S+\s+(\d+)\.(\d+)", re.DOTALL)
 770 arta  1.3              matchobj = regexp.match(ret)
 771                        if matchobj is None:
 772                            raise Exception('unexpectedIfortRet', ret)
 773                        else:
 774                            major = matchobj.group(1)
 775                            minor = matchobj.group(2)
 776                            if isVersion(int(major), int(minor), IFORT_MAJOR, IFORT_MINOR):
 777                                hasifort = bool(1)
 778                    
 779                    # Try gfortran
 780                    if not hasifort:
 781 arta  1.19             rv = bool(0)
 782 arta  1.3              cmd = 'gfortran -v 2>&1'
 783                        try:
 784                            ret = check_output(cmd, shell=True)
 785                            ret = ret.decode("utf-8")
 786                        except CalledProcessError:
 787                            print('Command ' + "'" + cmd + "'" + ' ran improperly.')
 788                            rv = bool(1)
 789            
 790 arta  1.19             if not rv:
 791 arta  1.3                  regexp = re.compile(r".+gcc\s+version\s+(\d+)\.(\d+)", re.DOTALL)
 792                            matchobj = regexp.match(ret)
 793                            if matchobj is None:
 794                                raise Exception('unexpectedGfortranRet', ret)
 795                            else:
 796                                major = matchobj.group(1)
 797                                minor = matchobj.group(2)
 798                                if isVersion(int(major), int(minor), GFORT_MAJOR, GFORT_MINOR):
 799                                    hasgfort = bool(1)
 800                    
 801 arta  1.19         # Append the compiler make variables to the make file
 802                    rv = bool(0)
 803                    
 804 arta  1.3          if not hasicc and not hasgcc:
 805                        print('Fatal error: Acceptable C compiler not found! You will be unable to build the DRMS library.', file=sys.stderr)
 806                        rv = bool(1)
 807                    elif hasicc:
 808                        mDefs.extend(list('\nCOMPILER = icc'))
 809                    else:
 810                        mDefs.extend(list('\nCOMPILER = gcc'))
 811            
 812                    if not hasifort and not hasgfort:
 813                        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)
 814                    elif hasifort:
 815                        mDefs.extend(list('\nFCOMPILER = ifort'))
 816                    else:
 817                        mDefs.extend(list('\nFCOMPILER = gfortran'))
 818                
 819                    # Environment overrides. These get written, regardless of the disposition of auto-configuration.
 820 arta  1.9          mDefs.extend(list('\nifneq ($(JSOC_COMPILER),)\n  COMPILER = $(JSOC_COMPILER)\nendif'))
 821                    mDefs.extend(list('\nifneq ($(JSOC_FCOMPILER),)\n  FCOMPILER = $(JSOC_FCOMPILER)\nendif'))
 822 arta  1.3  
 823                return rv
 824            
 825 arta  1.25 def writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection):
 826 arta  1.1      rv = bool(0)
 827 arta  1.4  
 828                # Merge mDefsGen, mDefsMake, and mDefsComps into a single string with compiler configuration first, general parameters next, then
 829                # make-specific make variables (e.g., third-party library information) last.
 830                mDefs = '\n# Compiler Selection\n' + ''.join(mDefsComps) + '\n\n# General Parameters\n' + ''.join(mDefsGen) + '\n\n# Parameters to Configure make\n' + ''.join(mDefsMake)
 831 arta  1.1      
 832                try:
 833 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:
 834 arta  1.1              # C file of macros
 835 arta  1.2              print(C_PREFIX, file=cout)
 836                        print('/* This file contains a set of preprocessor macros - one for each configuration parameter. */\n', file=cout)
 837 arta  1.1              buf = '__' + base.upper() + '_H'
 838                        print('#ifndef ' + buf, file=cout)
 839                        print('#define ' + buf, file=cout)
 840                        print(''.join(cDefs), file=cout)
 841                        print('#endif', file=cout)
 842                        
 843                        # Make file of make variables
 844 arta  1.2              print(PREFIX, file=mout)
 845 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)
 846                        print(mDefs, file=mout)
 847 arta  1.1              
 848 arta  1.2              # Perl module
 849                        print(PERL_BINPATH, file=pout)
 850                        print(PREFIX, file=pout)
 851                        print('# This file contains a set of constants - one for each configuration parameter.\n', file=pout)
 852                        print(PERL_INTIAL, file=pout)
 853 arta  1.1              print(''.join(perlConstSection), file=pout)
 854 arta  1.2              print(PERL_FXNS_A, file=pout)
 855 arta  1.1              print('sub initialize', file=pout)
 856                        print('{', file=pout)
 857 arta  1.2              print('  my($self) = shift;', file=pout, end='')
 858 arta  1.1              print('', file=pout)
 859                        print(''.join(perlInitSection), file=pout)
 860 arta  1.2              print('}\n', file=pout)
 861                        print(PERL_FXNS_B, file=pout)
 862 arta  1.18 
 863                        # Python module
 864                        print(PY_BINPATH, file=pyout)
 865                        print(PREFIX, file=pyout)
 866                        print('# This file contains a set of constants - one for each configuration parameter.\n', file=pyout)
 867                        print(''.join(pyConstSection), file=pyout)
 868                        print(PY_FXNS_A, file=pyout, end='')
 869                        print(''.join(pyInitSection), file=pyout)
 870                        print(PY_FXNS_B, file=pyout)
 871 arta  1.22             print(PY_FXNS_C, file=pyout)
 872 arta  1.25             
 873                        # Shell (bash) source file
 874                        print(SH_BINPATH, file=shout)
 875                        print(PREFIX, file=shout)
 876                        print('# This file contains a set of variable assignments - one for each configuration parameter.\n', file=shout)
 877                        print(''.join(shConstSection), file=shout)
 878 arta  1.18 
 879 arta  1.1      except IOError as exc:
 880 arta  1.6          type, value, traceback = sys.exc_info()
 881                    print(exc.strerror, file=sys.stderr)
 882                    print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)        
 883                    rv = bool(1)
 884            
 885                return rv
 886            
 887            def writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget):
 888                rv = bool(0)
 889            
 890                try:
 891                    if projCfg:
 892                        with open(pCfile, 'w') as cout:
 893                            # configure
 894                            print(''.join(projCfg), file=cout)
 895                    
 896                    if projMkRules:
 897                        with open(pMfile, 'w') as mout:
 898                            # make_basic.mk
 899                            print(PREFIX, file=mout)
 900                            print(''.join(projMkRules), file=mout)
 901 arta  1.6      
 902                    if projRules:
 903                        with open(pRfile, 'w') as rout:
 904                            # Rules.mk
 905                            print(PREFIX, file=rout)
 906                            print(''.join(projRules), file=rout)
 907                    
 908                    if projTarget:
 909                        with open(pTfile, 'w') as tout:
 910                            # target.mk
 911                            print(PREFIX, file=tout)
 912 arta  1.10                 print(''.join(projTarget), file=tout)
 913 arta  1.6      except IOError as exc:
 914                    type, value, traceback = sys.exc_info()
 915                    print(exc.strerror, file=sys.stderr)
 916                    print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)
 917 arta  1.1          rv = bool(1)
 918            
 919 arta  1.6      if not rv:
 920 arta  1.10         if os.path.exists(pCfile):
 921                        try:
 922                            os.chmod(pCfile, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
 923                        except OSError as exc:
 924                            type, value, traceback = sys.exc_info()
 925                            print('Unable to chmod file ' + "'" + value.filename + "'.", file=sys.stderr)
 926                            print(exc.strerror, file=sys.stderr)
 927                            rv = bool(1)
 928 arta  1.6  
 929 arta  1.1      return rv
 930 arta  1.3  
 931 arta  1.13 def generateSumRmCfg(defs):
 932                rv = bool(0)
 933                # ACK! Remember that Rick renamed these parameters. The ones in config.local are the aliases - do not use those.
 934                # Use the ones that those map to (defined in config.local.map).
 935                cFileTmp = defs['SUMLOG_BASEDIR'] + '/' + '.sum_rm.cfg.tmp'
 936                cFile = defs['SUMLOG_BASEDIR'] + '/' + 'sum_rm.cfg'
 937            
 938                # Write a temporary file sum_rm configuration file.
 939                try:
 940                    with open(cFileTmp, 'w') as fout:
 941                        # Print comment at the top of the configuration file.
 942                        print(SUMRM_COMMENT, file=fout)
 943                        print(SUMRM_DOC, file=fout)
 944                        print(SUMRM_PARTN_PERCENT_FREE, file=fout)
 945                        if 'SUMRM_PART_PERCENT_FREE' in defs:
 946                            print('PART_PERCENT_FREE=' + defs['SUMRM_PART_PERCENT_FREE'], file=fout)
 947                        else:
 948                            print('PART_PERCENT_FREE=3', file=fout)
 949            
 950                        print(SUMRM_SLEEP, file=fout)
 951                        if 'SUMRM_SLEEP' in defs:
 952 arta  1.13                 print('SLEEP=' + defs['SUMRM_SLEEP'], file=fout)
 953                        else:
 954                            print('SLEEP=300', file=fout)
 955            
 956                        print(SUMRM_LOG, file=fout)
 957                        if 'SUMRM_LOG' in defs:
 958                            print('LOG=' + defs['SUMRM_LOG'], file=fout)
 959                        else:
 960                            print('LOG=/tmp/sum_rm.log', file=fout)
 961            
 962                        print(SUMRM_MAIL, file=fout)
 963                        # No default for mail - don't send nothing to nobody unless the operator has asked for notifications.
 964                        if 'SUMRM_MAIL' in defs:
 965                            print('MAIL=' + defs['SUMRM_MAIL'], file=fout)
 966                        else:
 967                            print('# MAIL=president@whitehouse.gov', file=fout)
 968            
 969                        print(SUMRM_NOOP, file=fout)
 970                        if 'SUMRM_NOOP' in defs:
 971                            print('NOOP=' + defs['SUMRM_NOOP'], file=fout)
 972                        else:
 973 arta  1.13                 print('NOOP=0', file=fout)
 974            
 975                        print(SUMRM_USER, file=fout)
 976                        if 'SUMRM_USER' in defs:
 977                            print('USER=' + defs['SUMRM_USER'], file=fout)
 978                        else:
 979                            print('USER=production', file=fout)
 980            
 981                        print(SUMRM_NORUN, file=fout)
 982                        # Default norun window is to have no such window. This can be accomplished by simply not providing either argument.
 983                        if 'SUMRM_NORUN_START' in defs or 'SUMRM_NORUN_STOP' in defs:
 984                            if 'SUMRM_NORUN_START' in defs:
 985                                print('NORUN_START=' + defs['SUMRM_NORUN_START'], file=fout)
 986                            else:
 987                                print('NORUN_START=0', file=fout)
 988                            if 'SUMRM_NORUN_STOP' in defs:
 989                                print('NORUN_STOP=' + defs['SUMRM_NORUN_STOP'], file=fout)
 990                            else:
 991                                print('NORUN_STOP=0', file=fout)
 992                        else:
 993                            print('# NORUN_START=0', file=fout)
 994 arta  1.13                 print('# NORUN_STOP=0', file=fout)
 995                        
 996                except OSError:
 997                    print('Unable to open sum_rm temporary configuration file ' + cFileTmp + 'for writing.', file=sys.stderr)
 998                    rv = bool(1)
 999            
1000                # If the content of the temporary file differs from the content of the existing configuration file, then overwrite
1001                # the original file. Otherwise, delete the temporary file
1002                if not rv:
1003                    try:
1004                        if filecmp.cmp(cFile, cFileTmp):
1005                            # Files identical - delete temporary file
1006                            try:
1007                                os.remove(cFileTmp)
1008                            
1009                            except OSError as exc:
1010                                print('Unable to remove temporary file ' + exc.filename + '.', file=sys.stderr)
1011                                print(exc.strerr, file=sys.stderr)
1012                        else:
1013                            # Replace original with temporary file
1014                            try:
1015 arta  1.13                     os.rename(cFileTmp, cFile)
1016            
1017                            except OSError as exc:
1018                                print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
1019                                print(exc.strerr, file=sys.stderr)
1020                                rv = bool(1)
1021                    except OSError as exc:
1022                        # One of the files doesn't exist.
1023                        if exc.filename == cFile:
1024                            # We are ok - there might be no configuration file yet.
1025                            # Replace original with temporary file
1026                            try:
1027                                os.rename(cFileTmp, cFile)
1028            
1029                            except OSError as exc:
1030                                print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
1031                                print(exc.strerr, file=sys.stderr)
1032                                rv = bool(1)
1033                        else:
1034                            # There is a problem with the temp file - bail.
1035                            print('Unable to update sum_rm configuration file ' + cFile + '.', file=sys.stderr)
1036 arta  1.13                 print(exc.strerr, file=sys.stderr)
1037                            rv = bool(1)
1038            
1039                return rv
1040            
1041 arta  1.25 def configureNet(cfgfile, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, base, keymap, createSumRmCfg):
1042 arta  1.1      rv = bool(0)
1043                
1044                defs = {}
1045                cDefs = list()
1046 arta  1.4      mDefsGen = list()
1047                mDefsMake = list()
1048                mDefsComps = list()
1049 arta  1.6      projCfg = list()
1050                projMkRules = list()
1051                projRules = list()
1052                projTarget = list()
1053 arta  1.1      perlConstSection = list()
1054                perlInitSection = list()
1055 arta  1.18     pyConstSection = list()
1056                pyInitSection = list()
1057 arta  1.25     shConstSection = list()
1058 arta  1.2      addenda = {}
1059                
1060 arta  1.6      # There are three parameters that were not included in the original config.local parameter set, for some reason.
1061                # Due to this omission, then are not configurable, and must be set in the script.
1062 arta  1.2      addenda['a:USER'] = 'NULL'
1063                addenda['a:PASSWD'] = 'NULL'
1064                addenda['p:DSDS_SUPPORT'] = '0'
1065 arta  1.6      
1066                # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
1067 arta  1.2      addenda['a:BUILD_TYPE'] = 'NETDRMS' # Means a non-Stanford build. This will set two additional macros used by make:
1068                                                    #   __LOCALIZED_DEFS__ and NETDRMS_BUILD. The former is to support legacy code
1069                                                    #   which incorrectly used this macro, and the latter is for future use. 
1070                                                    #   __LOCALIZED_DEFS__ is deprecated and should not be used in new code.
1071 arta  1.1  
1072                try:
1073                    with open(cfgfile, 'r') as fin:
1074 arta  1.3              # Process configuration parameters
1075 arta  1.26 
1076                        # Always create a Rules.mk and target.mk, even if no proj XML is provided. All builds should have the proj/example and
1077                        # proj/cookbook directories. The required make information is in RULESPREFIX, TARGETPREFIX, and RULESSUFFIX. RULESSUFFIX
1078                        # must be added after the xml has been parsed.
1079                        projRules.extend(list(RULESPREFIX))
1080                        projTarget.extend(list(TARGETPREFIX))
1081            
1082 arta  1.25             rv = parseConfig(fin, keymap, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1083 arta  1.6              if not rv:
1084 arta  1.26                 projRules.extend(RULESSUFFIX)
1085                        
1086 arta  1.3                  # Must add a parameter for the SUMS_MANAGER UID (for some reason). This must be done after the
1087                            # config file is processed since an input to getMgrUIDLine() is one of the config file's
1088                            # parameter values.
1089 arta  1.1                  uidParam = {}
1090                            rv = getMgrUIDLine(defs, uidParam)
1091                            if rv == bool(0):
1092 arta  1.25                     rv = parseConfig(None, keymap, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1093 arta  1.3              # Configure the compiler-selection make variables.
1094 arta  1.6              if not rv:
1095 arta  1.4                  rv = configureComps(defs, mDefsComps)
1096 arta  1.1  
1097 arta  1.3              # Write out the parameter files.
1098 arta  1.6              if not rv:
1099 arta  1.25                 rv = writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1100 arta  1.13 
1101 arta  1.6              # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
1102                        if not rv:
1103                            rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
1104 arta  1.13 
1105                        # Write out the sum_rm.cfg file.
1106                        if not rv and createSumRmCfg:
1107                            rv = generateSumRmCfg(defs)
1108 arta  1.1      except IOError as exc:
1109 arta  1.6          print(exc.strerror, file=sys.stderr)
1110                    print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
1111 arta  1.3      except Exception as exc:
1112 arta  1.16         if len(exc.args) >= 2:
1113 arta  1.14             type, msg = exc.args
1114                    else:
1115                        # re-raise the exception
1116                        raise
1117            
1118 arta  1.3          if type == 'unexpectedIccRet':
1119                        print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
1120                        rv = bool(1)
1121                    elif type == 'unexpectedGccRet':
1122                        print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
1123                        rv = bool(1)
1124                    elif type == 'unexpectedIfortRet':
1125                        print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
1126                        rv = bool(1)
1127                    elif type == 'unexpectedGfortranRet':
1128                        print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
1129                        rv = bool(1)
1130                    else:
1131                        # re-raise the exception
1132                        raise
1133 arta  1.1          
1134 arta  1.2      return rv
1135 arta  1.1  
1136 arta  1.25 def configureSdp(cfgfile, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, base):
1137 arta  1.1      rv = bool(0)
1138                
1139                defs = {}
1140                cDefs = list()
1141 arta  1.5      mDefsGen = list()
1142                mDefsMake = list()
1143 arta  1.6      projCfg = list()
1144                projMkRules = list()
1145                projRules = list()
1146                projTarget = list()
1147 arta  1.5      mDefsComps = list()
1148 arta  1.1      perlConstSection = list()
1149                perlInitSection = list()
1150 arta  1.18     pyConstSection = list()
1151                pyInitSection = list()
1152 arta  1.25     shConstSection = list()
1153 arta  1.18 
1154 arta  1.2      addenda = {}
1155                
1156 arta  1.6      # There are three parameters that were not included in the original config.local parameter set, for some reason.
1157                # Due to this omission, then are not configurable, and must be set in the script.
1158 arta  1.5      addenda['a:USER'] = 'NULL'
1159                addenda['a:PASSWD'] = 'NULL'
1160                addenda['p:DSDS_SUPPORT'] = '1'
1161 arta  1.6      
1162                # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
1163 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.
1164 arta  1.1      
1165                try:
1166                    with open(cfgfile, 'r') as fin:
1167 arta  1.26         
1168                        # Always create a Rules.mk and target.mk, even if no proj XML is provided. All builds should have the proj/example and
1169                        # proj/cookbook directories. The required make information is in RULESPREFIX, TARGETPREFIX, and RULESSUFFIX. RULESSUFFIX
1170                        # must be added after the xml has been parsed.
1171                        projRules.extend(list(RULESPREFIX))
1172                        projTarget.extend(list(TARGETPREFIX))
1173                        
1174 arta  1.25             rv = parseConfig(fin, None, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1175 arta  1.6              
1176                        if not rv:
1177 arta  1.26                 projRules.extend(RULESSUFFIX)
1178                        
1179 arta  1.2                  # Must add a parameter for the SUMS_MANAGER UID (for some reason)
1180                            uidParam = {}
1181                            rv = getMgrUIDLine(defs, uidParam)
1182 arta  1.6                  if not rv:
1183 arta  1.25                     rv = parseConfig(None, None, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1184 arta  1.6  
1185 arta  1.5                  # Configure the compiler-selection make variables.
1186 arta  1.6                  if not rv:
1187 arta  1.5                      rv = configureComps(defs, mDefsComps)
1188 arta  1.3                  
1189 arta  1.6                  # Write out the parameter files.
1190                            if not rv:
1191 arta  1.25                     rv = writeParamsFiles(base, cfile, mfile, pfile, pyfile, shfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection, pyConstSection, pyInitSection, shConstSection)
1192 arta  1.6  
1193                            # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
1194                            if not rv:
1195                                rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
1196 arta  1.13 
1197                            # At Stanford, skip the creation of the sum_rm configuration file. config.local will still
1198                            # have the SUMRM parameters, but they will not be used.
1199 arta  1.1      except IOError as exc:
1200 arta  1.6          print(exc.strerror, file=sys.stderr)
1201                    print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
1202 arta  1.5      except Exception as exc:
1203 arta  1.17         if len(exc.args) >= 2:
1204                        type = exc.args[0]
1205                    else:
1206                        # re-raise the exception
1207                        raise
1208                    
1209 arta  1.5          if type == 'unexpectedIccRet':
1210 arta  1.6              msg = exc.args[1]
1211 arta  1.5              print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
1212                        rv = bool(1)
1213                    elif type == 'unexpectedGccRet':
1214 arta  1.6              msg = exc.args[1]
1215 arta  1.5              print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
1216                        rv = bool(1)
1217                    elif type == 'unexpectedIfortRet':
1218 arta  1.6              msg = exc.args[1]
1219 arta  1.5              print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
1220                        rv = bool(1)
1221                    elif type == 'unexpectedGfortranRet':
1222 arta  1.6              msg = exc.args[1]
1223 arta  1.5              print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
1224                        rv = bool(1)
1225                    else:
1226                        # re-raise the exception
1227                        raise
1228                    
1229 arta  1.2      return rv
1230            
1231 arta  1.1  # Beginning of program
1232            rv = RET_SUCCESS
1233            net = bool(1)
1234            
1235            # Parse arguments
1236            if __name__ == "__main__":
1237                optD = GetArgs(sys.argv[1:])
1238            
1239            if not(optD is None):
1240                # Ensure we are configuring a DRMS tree
1241                cdir = os.path.realpath(os.getcwd())
1242                versfile = cdir + '/base/' + VERS_FILE
1243            
1244                if not os.path.isfile(versfile):
1245                    rv = RET_NOTDRMS
1246            
1247            # Determine whether we are localizing a Stanford build, or a NetDRMS build. If configsdp.txt exists, then
1248            # it is a Stanford build, otherwise it is a NetDRMS build.
1249            if rv == RET_SUCCESS:
1250                stanfordFile = cdir + '/' + SDP_CFG
1251                if os.path.isfile(stanfordFile):
1252 arta  1.1          net = bool(0)
1253                
1254                cfile = optD['dir'] + '/' + optD['base'] + '.h'
1255                mfile = optD['dir'] + '/' + optD['base'] + '.mk'
1256                pfile = optD['dir'] + '/' + optD['base'] + '.pm'
1257 arta  1.18     pyfile = optD['dir'] + '/' + optD['base'] + '.py'
1258 arta  1.25     shfile = optD['dir'] + '/' + optD['base'] + '.sh'
1259 arta  1.6      pCfile = optD['dir'] + '/configure'
1260                pMfile = optD['dir'] + '/make_basic.mk'
1261                pRfile = optD['dir'] + '/Rules.mk'
1262                pTfile = optD['dir'] + '/target.mk'
1263 arta  1.1  
1264                if net:
1265                    try:
1266                        with open(NET_CFGMAP, 'r') as fin:
1267                            regexpComm = re.compile(r"^\s*#")
1268                            regexp = re.compile(r"^\s*(\S+)\s+(\w:\S+)")
1269                            # Must map from config.local namespace to DRMS namespace (e.g., the names used for the C macros)
1270                            keymap = {}
1271                            for line in fin:
1272                                matchobj = regexpComm.match(line)
1273                                if not matchobj is None:
1274                                    # Skip comment line
1275                                    continue
1276            
1277                                matchobj = regexp.match(line)
1278                                if not(matchobj is None):
1279                                    # We have a key-value line
1280                                    key = matchobj.group(1)
1281                                    val = matchobj.group(2)
1282                                    keymap[key] = val
1283                    except OSError:
1284 arta  1.1              sys.stderr.write('Unable to read configuration map-file ' + NET_CFGMAP + '.')
1285                        rv = bool(1)
1286            
1287                    # We also need to set the UID of the SUMS manager. We have the name of the
1288                    # SUMS manager (it is in the configuration file)
1289 arta  1.25         configureNet(NET_CFG, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, optD['base'], keymap, 'server' in optD)
1290 arta  1.1      else:
1291 arta  1.8          # A Stanford user can override the parameters in configsdp.txt by copying that file to config.local, 
1292                    # and then editing config.local. So, if config.local exists, use that.
1293                    if os.path.isfile(cdir + '/' + NET_CFG):
1294 arta  1.25             configureSdp(NET_CFG, cfile, mfile, pfile, pyfile, shfile, pCfile, pMfile, pRfile, pTfile, optD['base'])
1295 arta  1.8          else:
1296 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