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

Karen Tian
Powered by
ViewCVS 0.9.4