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

  1 arta  1.1 #!/home/jsoc/bin/linux_x86_64/activepython
  2           
  3           import os.path
  4           import sys
  5           import getopt
  6           import re
  7           from subprocess import check_output, CalledProcessError
  8           
  9           # Constants
 10           VERS_FILE = 'jsoc_version.h'
 11           SDP_CFG = 'configsdp.txt'
 12           NET_CFG = 'config.local'
 13           NET_CFGMAP = 'config.local.map'
 14           RET_SUCCESS = 0
 15           RET_NOTDRMS = 1
 16           
 17           PERL_PREFIX = """
 18           #!/usr/bin/perl
 19           
 20           package drmsparams;
 21           """
 22 arta  1.1 
 23           PERL_FXNS = """
 24           sub new
 25           {
 26               my($clname) = shift;
 27               
 28               my($self) = 
 29               {
 30                   _paramsH => undef
 31               };
 32               
 33               bless($self, $clname);
 34               $self->{_paramsH} = $self->initialize();
 35               
 36               return $self;
 37           }
 38               
 39           sub DESTROY
 40           {
 41               my($self) = shift;
 42           }
 43 arta  1.1     
 44           """
 45           
 46           # Read arguments
 47           #  d - localization directory
 48           #  b - base name of all parameter files (e.g., -b drmsparams --> drmsparams.h, drmsparams.mk, drmsparams.pm, etc.)
 49           #  m - make file
 50           def GetArgs(args):
 51               rv = bool(0)
 52               optD = {}
 53               
 54               try:
 55                   opts, remainder = getopt.getopt(args, "hd:b:",["dir=", "base="])
 56               except getopt.GetoptError:
 57                   print('Usage:')
 58                   print('localize.py [-h] -d <localization directory> -b <parameter file base>')
 59                   rv = bool(1)
 60               
 61               if rv == bool(0):
 62                   for opt, arg in opts:
 63                       if opt == '-h':
 64 arta  1.1                 print('localize.py [-h] -d <localization directory> -b <parameter file base>')
 65                       elif opt in ("-d", "--dir"):
 66                           regexp = re.compile(r"(\S+)/?")
 67                           matchobj = regexp.match(arg)
 68                           if matchobj is None:
 69                               rv = bool(1)
 70                           else:
 71                               optD['dir'] = matchobj.group(1)
 72                       elif opt in ("-b", "--base"):
 73                           optD['base'] = arg
 74                       else:
 75                           optD[opt] = arg
 76           	
 77               return optD
 78           
 79           def createMacroStr(key, val, keyColLen, status):
 80               if keyColLen < len(key):
 81                   status = bool(1)
 82                   return None
 83               else:
 84                   nsp = keyColLen - len(key)
 85 arta  1.1         spaces = str()
 86                   for isp in range(nsp):
 87                       spaces += ' '
 88                   status = bool(0)
 89                   return '#define ' + key + spaces + val + '\n'
 90           
 91           def createPerlConst(key, val, keyColLen, status):
 92               if keyColLen < len(key):
 93                   status = bool(1)
 94                   return None
 95               else:
 96                   nsp = keyColLen - len(key)
 97                   spaces = str()
 98                   for isp in range(nsp):
 99                       spaces += ' '
100                   status = bool(0)
101                   return 'use constant ' + key + ' => ' + spaces + val + ';\n'
102           
103           def processParam(cfgfile, line, regexpComm, regexpDefs, regexpMake, regexpQuote, regexp, keymap, defs, cDefs, mDefs, perlConstSection, perlInitSection, section):
104               status = 0
105               
106 arta  1.1     matchobj = regexpComm.match(line)
107               if not matchobj is None:
108                   # Skip comment line
109                   return bool(0)
110               
111               matchobj = regexpDefs.match(line)
112               if not matchobj is None:
113                   section.extend(list('defs'))
114                   return bool(0)
115               
116               matchobj = regexpMake.match(line)
117               if not matchobj is None:
118                   section = 'make'
119                   return bool(1)
120                       
121               if ''.join(section) == 'defs' or not cfgfile:
122                   matchobj = regexp.match(line)
123                   if not matchobj is None:
124                       # We have a key-value line
125                       keyCfgSp = matchobj.group(1)
126                       val = matchobj.group(2)
127 arta  1.1             
128                       # Must map the indirect name to the actual name
129                       if keymap:
130                           # Map to actual name only if the keymap is not empty (which signifies NA).
131                           if keyCfgSp in keymap:
132                               key = keymap[keyCfgSp]
133                           elif keyCfgSp == 'LOCAL_CONFIG_SET' or keyCfgSp == 'DRMS_SAMPLE_NAMESPACE':
134                               # Ignore parameters that are not useful and shouldn't have been there in the first place
135                               return bool(0)
136                           elif not cfgfile:
137                               # Should not be doing mapping for addenda
138                               key = keyCfgSp
139                           else:
140                               raise Exception('badKeyMapKey', keyCfgSp)
141                       else:
142                           key = keyCfgSp
143                       
144                       matchobj = regexpQuote.match(key)
145                       if not matchobj is None:
146                           quote = matchobj.group(1)
147                           key = matchobj.group(2)
148 arta  1.1 
149                           # master defs dictionary
150                           defs[key] = val
151                           
152                           # C header file
153                           if quote == "q":
154                               # Add double-quotes
155                               cDefs.extend(list(createMacroStr(key, '"' + val + '"', 40, status)))
156                           elif quote == "p":
157                               # Add parentheses
158                               cDefs.extend(list(createMacroStr(key, '(' + val + ')', 40, status)))
159                           elif quote == "a":
160                               # Leave as-is
161                               cDefs.extend(list(createMacroStr(key, val, 40, status)))
162                           else:
163                               # Unknown quote type
164                               raise Exception('badQuoteQual', key)
165                           
166                           if status:
167                               raise Exception('paramNameTooLong', key)
168                           
169 arta  1.1                 # Make file - val should never be quoted; just use as is
170                           mDefs.extend(list(key + ' = ' + val + '\n'))
171                           
172                           # Perl file - val should ALWAYS be single-quote quoted
173                           # Save const info to a string
174                           perlConstSection.extend(list(createPerlConst(key, "'" + val + "'", 40, status)))
175                           
176                           if status:
177                               raise Exception('paramNameTooLong', key)
178                           
179                           # Save initialization information as a string. Now that we've defined
180                           # constants (the names of which are the parameter names) 
181                           # we can refer to those in the init section. The key variable holds the
182                           # name of the constant.
183                           perlInitSection.extend(list('  $self->{_paramsH}->{' + key + '} = ' + key + ';\n'))
184                       else:
185                           # No quote qualifier
186                           raise Exception('missingQuoteQual', key)
187               
188               return bool(0)
189           
190 arta  1.1 # We have some extraneous line or a newline - ignore.
191           
192           # defs is a dictionary containing all parameters (should they be needed in this script)
193           def parseConfig(fin, cfile, mfile, pfile, keymap, addenda, defs, cDefs, mDefs, perlConstSection, perlInitSection):
194               rv = bool(0)
195               
196               # Open required config file (config.local)
197               try:
198                   # Examine each line, looking for key=value pairs.
199                   regexpDefs = re.compile(r"^__DEFS__")
200                   regexpMake = re.compile(r"^__MAKE__")
201                   regexpComm = re.compile(r"^\s*#")
202                   regexpQuote = re.compile(r"^\s*(\w):(.+)")
203                   regexp = re.compile(r"^\s*(\S+)\s+(.+)")
204                   
205                   section = list()
206                   
207                   # Process the parameters in the configuration file
208                   iscfg = bool(1)
209                   if not fin is None:
210                       for line in fin:
211 arta  1.1                 ppRet = processParam(iscfg, line, regexpComm, regexpDefs, regexpMake, regexpQuote, regexp, keymap, defs, cDefs, mDefs, perlConstSection, perlInitSection, section)
212                           if ppRet:
213                               break;
214                       
215                   # Process addenda - these are parameters that are not configurable and must be set in the 
216                   # NetDRMS build.
217                   iscfg = bool(0)
218                   for key in addenda:
219                       item = key + ' ' + addenda[key]
220                       ppRet = processParam(iscfg, item, regexpComm, regexpDefs, regexpMake, regexpQuote, regexp, keymap, defs, cDefs, mDefs, perlConstSection, perlInitSection, section)
221                       if ppRet:
222                           break;
223           
224               except Exception as exc:
225                   msg, violator = exc.args
226                   if msg == 'badKeyMapKey':
227                       # If we are here, then there was a non-empty keymap, and the parameter came from
228                       # the configuration file.
229                       print('Unknown parameter name ' + "'" + violator + "'" + ' in ' + cfgfile + '.', file=sys.stderr)
230                       rv = bool(1)
231                   elif msg == 'badQuoteQual':
232 arta  1.1             # The bad quote qualifier came from the configuration file, not the addenda, since
233                       # we will have fixed any bad qualifiers in the addenda (which is populated by code).
234                       print('Unknown quote qualifier ' + "'" + violator + "'" + ' in ' + cfgfile + '.', file=sys.stderr)
235                       rv = bool(1)
236                   elif msg == 'missingQuoteQual':
237                       print('Missing quote qualifier for parameter ' + "'" + violator + "'" + ' in ' + cfgfile + '.', file=sys.stderr)
238                       rv = bool(1)
239                   elif msg == 'paramNameTooLong':
240                       print('Macro name ' + "'" + violator + "' is too long.", file=sys.stderr)
241                       rv = bool(1)
242                   else:
243                       # re-raise the exception
244                       raise
245           
246               return rv
247           
248           def getMgrUIDLine(defs, uidParam):
249               rv = bool(0)
250               
251               cmd = 'id -u ' + defs['SUMS_MANAGER']
252               try:
253 arta  1.1         ret = check_output(cmd, shell=True)
254                   uidParam['q:SUMS_MANAGER_UID'] = ret.decode("utf-8")
255               except ValueError:
256                   print('Unable to run cmd: ' + cmd + '.')
257                   rv = bool(1)
258               except CalledProcessError:
259                   print('Command ' + "'" + cmd + "'" + ' ran improperly.')
260                   rv = bool(1)
261           
262               return rv
263           
264           def writeFiles(base, cfile, mfile, pfile, cDefs, mDefs, perlConstSection, perlInitSection):
265               rv = bool(0)
266               
267               try:
268                   with open(cfile, 'w') as cout, open(mfile, 'w') as mout, open(pfile, 'w') as pout:
269                       # C file of macros
270                       buf = '__' + base.upper() + '_H'
271                       print('#ifndef ' + buf, file=cout)
272                       print('#define ' + buf, file=cout)
273                       print(''.join(cDefs), file=cout)
274 arta  1.1             print('#endif', file=cout)
275                       
276                       # Make file of make variables
277                       print('# This file contains a set of make-variable values - one for each configuration parameter.', file=mout)
278                       print(''.join(mDefs), file=mout)
279                       
280                       # Create the constants in the Perl file (mapping parameter name from config.local namespace to
281                       # DRMS-module namespace
282                       print(PERL_PREFIX, file=pout)
283                       print(''.join(perlConstSection), file=pout)
284                       print(PERL_FXNS, file=pout)
285                       print('sub initialize', file=pout)
286                       print('{', file=pout)
287                       print('  my($self) = shift;', file=pout)
288                       print('', file=pout)
289                       print(''.join(perlInitSection), file=pout)
290                       print('}', file=pout)
291                       
292               except IOError as exc:
293                   sys.stderr.write(exc.strerror)
294                   sys.stderr.write('Unable to open a parameter vile.')
295 arta  1.1         rv = bool(1)
296           
297               return rv
298                       
299           def configureNet(cfgfile, cfile, mfile, pfile, base, keymap, addenda):
300               rv = bool(0)
301               
302               defs = {}
303               cDefs = list()
304               mDefs = list()
305               perlConstSection = list()
306               perlInitSection = list()
307           
308               try:
309                   with open(cfgfile, 'r') as fin:
310                       rv = parseConfig(fin, cfile, mfile, pfile, keymap, addenda, defs, cDefs, mDefs, perlConstSection, perlInitSection)
311                       if rv == bool(0):
312                           # Must add a parameter for the SUMS_MANAGER UID (for some reason)
313                           uidParam = {}
314                           rv = getMgrUIDLine(defs, uidParam)
315                           if rv == bool(0):
316 arta  1.1                     rv = parseConfig(None, cfile, mfile, pfile, keymap, uidParam, defs, cDefs, mDefs, perlConstSection, perlInitSection)
317           
318                           if rv == bool(0):
319                               rv = writeFiles(base, cfile, mfile, pfile, cDefs, mDefs, perlConstSection, perlInitSection)
320               except IOError as exc:
321                   sys.stderr.write(exc.strerror)
322                   sys.stderr.write('Unable to read configuration file ' + cfgfile + '.')
323                   
324           
325           def configureSdp(cfgfile, cfile, mfile, pfile, base, keymap, addenda):
326               rv = bool(0)
327               
328               defs = {}
329               cDefs = list()
330               mDefs = list()
331               perlConstSection = list()
332               perlInitSection = list()
333               
334               try:
335                   with open(cfgfile, 'r') as fin:
336                       rv = parseConfig(cfgfile, cfile, mfile, pfile, keymap, addenda, defs, cDefs, mDefs, perlConstSection, perlInitSection)
337 arta  1.1             if rv == bool(0):
338                           rv = writeFiles(base, cfile, mfile, pfile, cDefs, mDefs, perlConstSection, perlInitSection)
339               except IOError as exc:
340                   sys.stderr.write(exc.strerror)
341                   sys.stderr.write('Unable to read configuration file ' + cfgfile + '.')
342           
343           # Beginning of program
344           rv = RET_SUCCESS
345           net = bool(1)
346           
347           # Parse arguments
348           if __name__ == "__main__":
349               optD = GetArgs(sys.argv[1:])
350           
351           if not(optD is None):
352               # Ensure we are configuring a DRMS tree
353               cdir = os.path.realpath(os.getcwd())
354               versfile = cdir + '/base/' + VERS_FILE
355           
356               if not os.path.isfile(versfile):
357                   rv = RET_NOTDRMS
358 arta  1.1 
359           # Determine whether we are localizing a Stanford build, or a NetDRMS build. If configsdp.txt exists, then
360           # it is a Stanford build, otherwise it is a NetDRMS build.
361           if rv == RET_SUCCESS:
362               stanfordFile = cdir + '/' + SDP_CFG
363               if os.path.isfile(stanfordFile):
364                   net = bool(0)
365               
366               cfile = optD['dir'] + '/' + optD['base'] + '.h'
367               mfile = optD['dir'] + '/' + optD['base'] + '.mk'
368               pfile = optD['dir'] + '/' + optD['base'] + '.pm'
369           
370               if net:
371                   addenda = {}
372           
373                   try:
374                       with open(NET_CFGMAP, 'r') as fin:
375                           regexpComm = re.compile(r"^\s*#")
376                           regexp = re.compile(r"^\s*(\S+)\s+(\w:\S+)")
377                           # Must map from config.local namespace to DRMS namespace (e.g., the names used for the C macros)
378                           keymap = {}
379 arta  1.1                 for line in fin:
380                               matchobj = regexpComm.match(line)
381                               if not matchobj is None:
382                                   # Skip comment line
383                                   continue
384           
385                               matchobj = regexp.match(line)
386                               if not(matchobj is None):
387                                   # We have a key-value line
388                                   key = matchobj.group(1)
389                                   val = matchobj.group(2)
390                                   keymap[key] = val
391                   except OSError:
392                       sys.stderr.write('Unable to read configuration map-file ' + NET_CFGMAP + '.')
393                       rv = bool(1)
394                       
395                   # There are three parameters that are not configurable and must be set.
396                   addenda['a:USER'] = 'NULL'
397                   addenda['a:PASSWD'] = 'NULL'
398                   addenda['p:DSDS_SUPPORT'] = '0'
399           
400 arta  1.1         # We also need to set the UID of the SUMS manager. We have the name of the
401                   # SUMS manager (it is in the configuration file)
402                   configureNet(NET_CFG, cfile, mfile, pfile, optD['base'], keymap, addenda)
403               else:
404                   configureSdp(SDP_CFG, cfile, mfile, pfile, optD['base'], {}, addenda)
405               
406               
407           

Karen Tian
Powered by
ViewCVS 0.9.4