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

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