setup.py 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. #Licensed to the Apache Software Foundation (ASF) under one
  2. #or more contributor license agreements. See the NOTICE file
  3. #distributed with this work for additional information
  4. #regarding copyright ownership. The ASF licenses this file
  5. #to you under the Apache License, Version 2.0 (the
  6. #"License"); you may not use this file except in compliance
  7. #with the License. You may obtain a copy of the License at
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #Unless required by applicable law or agreed to in writing, software
  10. #distributed under the License is distributed on an "AS IS" BASIS,
  11. #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. #See the License for the specific language governing permissions and
  13. #limitations under the License.
  14. # $Id:setup.py 5158 2007-04-09 00:14:35Z zim $
  15. # $Id:setup.py 5158 2007-04-09 00:14:35Z zim $
  16. #
  17. #------------------------------------------------------------------------------
  18. """'setup' provides for reading and verifing configuration files based on
  19. Python's SafeConfigParser class."""
  20. import sys, os, re, pprint
  21. from ConfigParser import SafeConfigParser
  22. from optparse import OptionParser, IndentedHelpFormatter, OptionGroup
  23. from util import get_perms, replace_escapes
  24. from types import typeValidator, is_valid_type, typeToString
  25. from hodlib.Hod.hod import hodHelp
  26. reEmailAddress = re.compile("^.*@.*$")
  27. reEmailDelimit = re.compile("@")
  28. reComma = re.compile("\s*,\s*")
  29. reDot = re.compile("\.")
  30. reCommentHack = re.compile("^.*?\s+#|;.*", flags=re.S)
  31. reCommentNewline = re.compile("\W$")
  32. reKeyVal = r"(?<!\\)="
  33. reKeyVal = re.compile(reKeyVal)
  34. reKeyValList = r"(?<!\\),"
  35. reKeyValList = re.compile(reKeyValList)
  36. errorPrefix = 'error'
  37. requiredPerms = '0660'
  38. class definition:
  39. def __init__(self):
  40. """Generates a configuration definition object."""
  41. self.__def = {}
  42. self.__defOrder = []
  43. def __repr__(self):
  44. return pprint.pformat(self.__def)
  45. def __getitem__(self, section):
  46. return self.__def[section]
  47. def __iter__(self):
  48. return iter(self.__def)
  49. def sections(self):
  50. """Returns a list of sections/groups."""
  51. if len(self.__defOrder):
  52. return self.__defOrder
  53. else:
  54. return self.__def.keys()
  55. def add_section(self, section):
  56. """Add a configuration section / option group."""
  57. if self.__def.has_key(section):
  58. raise Exception("Section already exists: '%s'" % section)
  59. else:
  60. self.__def[section] = {}
  61. def add_def(self, section, var, type, desc, help = True, default = None,
  62. req = True, validate = True, short = None):
  63. """ Add a variable definition.
  64. section - section name
  65. var - variable name
  66. type - valid hodlib.types
  67. desc - description of variable
  68. help - display help for this variable
  69. default - default value
  70. req - bool, requried?
  71. validate - bool, validate type value?
  72. short - short symbol (1 character),
  73. help - bool, display help?"""
  74. if self.__def.has_key(section):
  75. if not is_valid_type(type):
  76. raise Exception("Type (type) is invalid: %s.%s - '%s'" % (section, var,
  77. type))
  78. if not isinstance(desc, str):
  79. raise Exception("Description (desc) must be a string: %s.%s - '%s'" % (
  80. section, var, desc))
  81. if not isinstance(req, bool):
  82. raise Exception("Required (req) must be a bool: %s.%s - '%s'" % (section,
  83. var,
  84. req))
  85. if not isinstance(validate, bool):
  86. raise Exception("Validate (validate) must be a bool: %s.%s - '%s'" % (
  87. section, var, validate))
  88. if self.__def[section].has_key(var):
  89. raise Exception("Variable name already defined: '%s'" % var)
  90. else:
  91. self.__def[section][var] = { 'type' : type,
  92. 'desc' : desc,
  93. 'help' : help,
  94. 'default' : default,
  95. 'req' : req,
  96. 'validate' : validate,
  97. 'short' : short }
  98. else:
  99. raise Exception("Section does not exist: '%s'" % section)
  100. def add_defs(self, defList, defOrder=None):
  101. """ Add a series of definitions.
  102. defList = { section0 : ((name0,
  103. type0,
  104. desc0,
  105. help0,
  106. default0,
  107. req0,
  108. validate0,
  109. short0),
  110. ....
  111. (nameN,
  112. typeN,
  113. descN,
  114. helpN,
  115. defaultN,
  116. reqN,
  117. validateN,
  118. shortN)),
  119. ....
  120. sectionN : ... }
  121. Where the short synmbol is optional and can only be one char."""
  122. for section in defList.keys():
  123. self.add_section(section)
  124. for defTuple in defList[section]:
  125. if isinstance(defTuple, tuple):
  126. if len(defTuple) < 7:
  127. raise Exception(
  128. "section %s is missing an element: %s" % (
  129. section, pprint.pformat(defTuple)))
  130. else:
  131. raise Exception("section %s of defList is not a tuple" %
  132. section)
  133. if len(defTuple) == 7:
  134. self.add_def(section, defTuple[0], defTuple[1],
  135. defTuple[2], defTuple[3], defTuple[4],
  136. defTuple[5], defTuple[6])
  137. else:
  138. self.add_def(section, defTuple[0], defTuple[1],
  139. defTuple[2], defTuple[3], defTuple[4],
  140. defTuple[5], defTuple[6], defTuple[7])
  141. if defOrder:
  142. for section in defOrder:
  143. if section in self.__def:
  144. self.__defOrder.append(section)
  145. for section in self.__def:
  146. if not section in defOrder:
  147. raise Exception(
  148. "section %s is missing from specified defOrder." %
  149. section)
  150. class baseConfig:
  151. def __init__(self, configDef, originalDir=None):
  152. self.__toString = typeToString()
  153. self.__validated = False
  154. self._configDef = configDef
  155. self._options = None
  156. self._mySections = []
  157. self._dict = {}
  158. self.configFile = None
  159. self.__originalDir = originalDir
  160. if self._configDef:
  161. self._mySections = configDef.sections()
  162. def __repr__(self):
  163. """Returns a string representation of a config object including all
  164. normalizations."""
  165. print_string = '';
  166. for section in self._mySections:
  167. print_string = "%s[%s]\n" % (print_string, section)
  168. options = self._dict[section].keys()
  169. for option in options:
  170. print_string = "%s%s = %s\n" % (print_string, option,
  171. self._dict[section][option])
  172. print_string = "%s\n" % (print_string)
  173. print_string = re.sub("\n\n$", "", print_string)
  174. return print_string
  175. def __getitem__(self, section):
  176. """ Returns a dictionary of configuration name and values by section.
  177. """
  178. return self._dict[section]
  179. def __setitem__(self, section, value):
  180. self._dict[section] = value
  181. def __iter__(self):
  182. return iter(self._dict)
  183. def has_key(self, section):
  184. status = False
  185. if section in self._dict:
  186. status = True
  187. return status
  188. # 'private' method which prints an configuration error messages
  189. def var_error(self, section, option, *addData):
  190. errorStrings = []
  191. if not self._dict[section].has_key(option):
  192. self._dict[section][option] = None
  193. errorStrings.append("%s: invalid '%s' specified in section %s (--%s.%s): %s" % (
  194. errorPrefix, option, section, section, option, self._dict[section][option]))
  195. if addData:
  196. errorStrings.append("%s: additional info: %s\n" % (errorPrefix,
  197. addData[0]))
  198. return errorStrings
  199. def var_error_suggest(self, errorStrings):
  200. if self.configFile:
  201. errorStrings.append("Check your command line options and/or " + \
  202. "your configuration file %s" % self.configFile)
  203. def __get_args(self, section):
  204. def __dummyToString(type, value):
  205. return value
  206. toString = __dummyToString
  207. if self.__validated:
  208. toString = self.__toString
  209. args = []
  210. if isinstance(self._dict[section], dict):
  211. for option in self._dict[section]:
  212. if section in self._configDef and \
  213. option in self._configDef[section]:
  214. if self._configDef[section][option]['type'] == 'bool':
  215. if self._dict[section][option] == 'True' or \
  216. self._dict[section][option] == True:
  217. args.append("--%s.%s" % (section, option))
  218. else:
  219. args.append("--%s.%s" % (section, option))
  220. args.append(toString(
  221. self._configDef[section][option]['type'],
  222. self._dict[section][option]))
  223. else:
  224. if section in self._configDef:
  225. if self._configDef[section][option]['type'] == 'bool':
  226. if self._dict[section] == 'True' or \
  227. self._dict[section] == True:
  228. args.append("--%s" % section)
  229. else:
  230. if self._dict[section] != 'config':
  231. args.append("--%s" % section)
  232. args.append(toString(self._configDef[section]['type'],
  233. self._dict[section]))
  234. return args
  235. def values(self):
  236. return self._dict.values()
  237. def keys(self):
  238. return self._dict.keys()
  239. def get_args(self, exclude=None, section=None):
  240. """Retrieve a tuple of config arguments."""
  241. args = []
  242. if section:
  243. args = self.__get_args(section)
  244. else:
  245. for section in self._dict:
  246. if exclude:
  247. if not section in exclude:
  248. args.extend(self.__get_args(section))
  249. else:
  250. args.extend(self.__get_args(section))
  251. return tuple(args)
  252. def verify(self):
  253. """Verifies each configuration variable, using the configValidator
  254. class, based on its type as defined by the dictionary configDef.
  255. Upon encountering a problem an error is printed to STDERR and
  256. false is returned."""
  257. oldDir = os.getcwd()
  258. if self.__originalDir:
  259. os.chdir(self.__originalDir)
  260. status = True
  261. statusMsgs = []
  262. if self._configDef:
  263. errorCount = 0
  264. configValidator = typeValidator()
  265. # foreach section and option by type string as defined in configDef
  266. # add value to be validated to validator
  267. for section in self._mySections:
  268. for option in self._configDef[section].keys():
  269. configVarName = "%s.%s" % (section, option)
  270. if self._dict[section].has_key(option):
  271. if self._configDef[section][option].has_key('validate'):
  272. if self._configDef[section][option]['validate']:
  273. # is the section.option needed to be validated?
  274. configValidator.add(configVarName,
  275. self._configDef[section][option]['type'],
  276. self._dict[section][option])
  277. elif self._configDef[section][option]['type'] \
  278. != 'file' and \
  279. self._configDef[section][option]['type'] != \
  280. 'directory':
  281. self[section][option] = \
  282. configValidator.normalize(
  283. self._configDef[section][option]['type'],
  284. self._dict[section][option])
  285. if self._configDef[section][option]['default'] != \
  286. None:
  287. self._configDef[section][option]['default'] = \
  288. configValidator.normalize(
  289. self._configDef[section][option]['type'],
  290. self._configDef[section][option]['default']
  291. )
  292. self._configDef[section][option]['default'] = \
  293. self.__toString(
  294. self._configDef[section][option]['type'],
  295. self._configDef[section][option]['default']
  296. )
  297. else:
  298. configValidator.add(configVarName,
  299. self._configDef[section][option]['type'],
  300. self._dict[section][option])
  301. elif self._configDef[section][option]['req']:
  302. statusMsgs.append("%s: %s.%s is not defined."
  303. % (errorPrefix, section, option))
  304. errorCount = errorCount + 1
  305. configValidator.validate()
  306. for valueInfo in configValidator.validatedInfo:
  307. sectionsOptions = reDot.split(valueInfo['name'])
  308. if valueInfo['isValid'] == 1:
  309. self._dict[sectionsOptions[0]][sectionsOptions[1]] = \
  310. valueInfo['normalized']
  311. else:
  312. if valueInfo['errorData']:
  313. statusMsgs.extend(self.var_error(sectionsOptions[0],
  314. sectionsOptions[1], valueInfo['errorData']))
  315. else:
  316. statusMsgs.extend(self.var_error(sectionsOptions[0],
  317. sectionsOptions[1]))
  318. errorCount = errorCount + 1
  319. if errorCount > 1:
  320. statusMsgs.append( "%s: %s problems found." % (
  321. errorPrefix, errorCount))
  322. self.var_error_suggest(statusMsgs)
  323. status = False
  324. elif errorCount > 0:
  325. statusMsgs.append( "%s: %s problem found." % (
  326. errorPrefix, errorCount))
  327. self.var_error_suggest(statusMsgs)
  328. status = False
  329. self.__validated = True
  330. if self.__originalDir:
  331. os.chdir(oldDir)
  332. return status,statusMsgs
  333. class config(SafeConfigParser, baseConfig):
  334. def __init__(self, configFile, configDef=None, originalDir=None,
  335. options=None, checkPerms=False):
  336. """Constructs config object.
  337. configFile - configuration file to read
  338. configDef - definition object
  339. options - options object
  340. checkPerms - check file permission on config file, 0660
  341. sample configuration file:
  342. [snis]
  343. modules_dir = modules/ ; location of infoModules
  344. md5_defs_dir = etc/md5_defs ; location of infoTree md5 defs
  345. info_store = var/info ; location of nodeInfo store
  346. cam_daemon = localhost:8200 ; cam daemon address"""
  347. SafeConfigParser.__init__(self)
  348. baseConfig.__init__(self, configDef, originalDir)
  349. if(os.path.exists(configFile)):
  350. self.configFile = configFile
  351. else:
  352. raise IOError
  353. self._options = options
  354. ## UNUSED CODE : checkPerms is never True
  355. ## zim: this code is used if one instantiates config() with checkPerms set to
  356. ## True.
  357. if checkPerms: self.__check_perms()
  358. self.read(configFile)
  359. self._configDef = configDef
  360. if not self._configDef:
  361. self._mySections = self.sections()
  362. self.__initialize_config_dict()
  363. def __initialize_config_dict(self):
  364. """ build a dictionary of config vars keyed by section name defined in
  365. configDef, if options defined override config"""
  366. for section in self._mySections:
  367. items = self.items(section)
  368. self._dict[section] = {}
  369. # First fill self._dict with whatever is given in hodrc.
  370. # Going by this, options given at the command line either override
  371. # options in hodrc, or get appended to the list, like for
  372. # hod.client-params. Note that after this dict has _only_ hodrc
  373. # params
  374. for keyValuePair in items:
  375. # stupid commenting bug in ConfigParser class, lines without an
  376. # option value pair or section required that ; or # are at the
  377. # beginning of the line, :(
  378. newValue = reCommentHack.sub("", keyValuePair[1])
  379. newValue = reCommentNewline.sub("", newValue)
  380. self._dict[section][keyValuePair[0]] = newValue
  381. # end of filling with options given in hodrc
  382. # now start filling in command line options
  383. if self._options:
  384. for option in self._configDef[section].keys():
  385. if self._options[section].has_key(option):
  386. # the user has given an option
  387. compoundOpt = "%s.%s" %(section,option)
  388. if ( compoundOpt == \
  389. 'gridservice-mapred.final-server-params' \
  390. or compoundOpt == \
  391. 'gridservice-hdfs.final-server-params' \
  392. or compoundOpt == \
  393. 'gridservice-mapred.server-params' \
  394. or compoundOpt == \
  395. 'gridservice-hdfs.server-params' \
  396. or compoundOpt == \
  397. 'hod.client-params' ):
  398. if ( compoundOpt == \
  399. 'gridservice-mapred.final-server-params' \
  400. or compoundOpt == \
  401. 'gridservice-hdfs.final-server-params' ):
  402. overwrite = False
  403. else: overwrite = True
  404. # Append to the current list of values in self._dict
  405. if not self._dict[section].has_key(option):
  406. self._dict[section][option] = ""
  407. dictOpts = reKeyValList.split(self._dict[section][option])
  408. dictOptsKeyVals = {}
  409. for opt in dictOpts:
  410. if opt != '':
  411. # when dict _has_ params from hodrc
  412. if reKeyVal.search(opt):
  413. (key, val) = reKeyVal.split(opt,1)
  414. # we only consider the first '=' for splitting
  415. # we do this to support passing params like
  416. # mapred.child.java.opts=-Djava.library.path=some_dir
  417. # Even in case of an invalid error like unescaped '=',
  418. # we don't want to fail here itself. We leave such errors
  419. # to be caught during validation which happens after this
  420. dictOptsKeyVals[key] = val
  421. else:
  422. # this means an invalid option. Leaving it
  423. #for config.verify to catch
  424. dictOptsKeyVals[opt] = None
  425. cmdLineOpts = reKeyValList.split(self._options[section][option])
  426. for opt in cmdLineOpts:
  427. if reKeyVal.search(opt):
  428. # Same as for hodrc options. only consider
  429. # the first =
  430. ( key, val ) = reKeyVal.split(opt,1)
  431. else:
  432. key = opt
  433. val = None
  434. # whatever is given at cmdline overrides
  435. # what is given in hodrc only for non-final params
  436. if dictOptsKeyVals.has_key(key):
  437. if overwrite:
  438. dictOptsKeyVals[key] = val
  439. else: dictOptsKeyVals[key] = val
  440. self._dict[section][option] = ""
  441. for key in dictOptsKeyVals:
  442. if self._dict[section][option] == "":
  443. if dictOptsKeyVals[key]:
  444. self._dict[section][option] = key + "=" + \
  445. dictOptsKeyVals[key]
  446. else: #invalid option. let config.verify catch
  447. self._dict[section][option] = key
  448. else:
  449. if dictOptsKeyVals[key]:
  450. self._dict[section][option] = \
  451. self._dict[section][option] + "," + key + \
  452. "=" + dictOptsKeyVals[key]
  453. else: #invalid option. let config.verify catch
  454. self._dict[section][option] = \
  455. self._dict[section][option] + "," + key
  456. else:
  457. # for rest of the options, that don't need
  458. # appending business.
  459. # options = cmdline opts + defaults
  460. # dict = hodrc opts only
  461. # only non default opts can overwrite any opt
  462. # currently in dict
  463. if not self._dict[section].has_key(option):
  464. # options not mentioned in hodrc
  465. self._dict[section][option] = \
  466. self._options[section][option]
  467. elif self._configDef[section][option]['default'] != \
  468. self._options[section][option]:
  469. # option mentioned in hodrc but user has given a
  470. # non-default option
  471. self._dict[section][option] = \
  472. self._options[section][option]
  473. ## UNUSED METHOD
  474. ## zim: is too :)
  475. def __check_perms(self):
  476. perms = None
  477. if self._options:
  478. try:
  479. perms = get_perms(self.configFile)
  480. except OSError, data:
  481. self._options.print_help()
  482. raise Exception("*** could not find config file: %s" % data)
  483. sys.exit(1)
  484. else:
  485. perms = get_perms(self.configFile)
  486. if perms != requiredPerms:
  487. error = "*** '%s' has invalid permission: %s should be %s\n" % \
  488. (self.configFile, perms, requiredPerms)
  489. raise Exception( error)
  490. sys.exit(1)
  491. def replace_escape_seqs(self):
  492. """ replace any escaped characters """
  493. replace_escapes(self)
  494. class formatter(IndentedHelpFormatter):
  495. def format_option_strings(self, option):
  496. """Return a comma-separated list of option strings & metavariables."""
  497. if option.takes_value():
  498. metavar = option.metavar or option.dest.upper()
  499. short_opts = [sopt
  500. for sopt in option._short_opts]
  501. long_opts = [self._long_opt_fmt % (lopt, metavar)
  502. for lopt in option._long_opts]
  503. else:
  504. short_opts = option._short_opts
  505. long_opts = option._long_opts
  506. if self.short_first:
  507. opts = short_opts + long_opts
  508. else:
  509. opts = long_opts + short_opts
  510. return ", ".join(opts)
  511. class options(OptionParser, baseConfig):
  512. def __init__(self, optionDef, usage, version, originalDir=None,
  513. withConfig=False, defaultConfig=None, defaultLocation=None,
  514. name=None):
  515. """Constructs and options object.
  516. optionDef - definition object
  517. usage - usage statement
  518. version - version string
  519. withConfig - used in conjunction with a configuration file
  520. defaultConfig - default configuration file
  521. """
  522. OptionParser.__init__(self, usage=usage)
  523. baseConfig.__init__(self, optionDef, originalDir)
  524. self.formatter = formatter(4, max_help_position=100, width=180,
  525. short_first=1)
  526. self.__name = name
  527. self.__version = version
  528. self.__withConfig = withConfig
  529. self.__defaultConfig = defaultConfig
  530. self.__defaultLoc = defaultLocation
  531. self.args = []
  532. self.__optionList = []
  533. self.__compoundOpts = []
  534. self.__shortMap = {}
  535. self.__alphaString = 'abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ1234567890'
  536. self.__alpha = []
  537. self.__parsedOptions = {}
  538. self.__reserved = [ 'h' ]
  539. self.__orig_grps = []
  540. self.__orig_grp_lists = {}
  541. self.__orig_option_list = []
  542. self.__display_grps = []
  543. self.__display_grp_lists = {}
  544. self.__display_option_list = []
  545. self.config = None
  546. if self.__withConfig:
  547. self.__reserved.append('c')
  548. self.__reserved.append('v')
  549. self.__gen_alpha()
  550. # build self.__optionList, so it contains all the options that are
  551. # possible. the list elements are of the form section.option
  552. for section in self._mySections:
  553. if self.__withConfig and section == 'config':
  554. raise Exception(
  555. "withConfig set 'config' cannot be used as a section name")
  556. for option in self._configDef[section].keys():
  557. if '.' in option:
  558. raise Exception("Options cannot contain: '.'")
  559. elif self.__withConfig and option == 'config':
  560. raise Exception(
  561. "With config set, option config is not allowed.")
  562. elif self.__withConfig and option == 'verbose-help':
  563. raise Exception(
  564. "With config set, option verbose-help is not allowed.")
  565. self.__optionList.append(self.__splice_compound(section,
  566. option))
  567. self.__build_short_map()
  568. self.__add_options()
  569. self.__init_display_options()
  570. (self.__parsedOptions, self.args) = self.parse_args()
  571. # Now process the positional arguments only for the client side
  572. if self.__name == 'hod':
  573. hodhelp = hodHelp()
  574. _operation = getattr(self.__parsedOptions,'hod.operation')
  575. _script = getattr(self.__parsedOptions, 'hod.script')
  576. nArgs = self.args.__len__()
  577. if _operation:
  578. # -o option is given
  579. if nArgs != 0:
  580. self.error('invalid syntax : command and operation(-o) cannot coexist')
  581. elif nArgs == 0 and _script:
  582. # for a script option, without subcommand: hod -s script ...
  583. pass
  584. elif nArgs == 0:
  585. print "Usage: ",hodhelp.help()
  586. sys.exit(0)
  587. else:
  588. # subcommand is given
  589. cmdstr = self.args[0] # the subcommand itself
  590. cmdlist = hodhelp.ops
  591. if cmdstr not in cmdlist:
  592. print "Usage: ", hodhelp.help()
  593. sys.exit(2)
  594. numNodes = None
  595. clusterDir = None
  596. # Check which subcommand. cmdstr = subcommand itself now.
  597. if cmdstr == "allocate":
  598. clusterDir = getattr(self.__parsedOptions, 'hod.clusterdir')
  599. numNodes = getattr(self.__parsedOptions, 'hod.nodecount')
  600. if not clusterDir or not numNodes:
  601. print getattr(hodhelp, "help_%s" % cmdstr)()
  602. sys.exit(3)
  603. cmdstr = cmdstr + ' ' + clusterDir + ' ' + numNodes
  604. setattr(self.__parsedOptions,'hod.operation', cmdstr)
  605. elif cmdstr == "deallocate" or cmdstr == "info":
  606. clusterDir = getattr(self.__parsedOptions, 'hod.clusterdir')
  607. if not clusterDir:
  608. print getattr(hodhelp, "help_%s" % cmdstr)()
  609. sys.exit(3)
  610. cmdstr = cmdstr + ' ' + clusterDir
  611. setattr(self.__parsedOptions,'hod.operation', cmdstr)
  612. elif cmdstr == "list":
  613. setattr(self.__parsedOptions,'hod.operation', cmdstr)
  614. pass
  615. elif cmdstr == "script":
  616. clusterDir = getattr(self.__parsedOptions, 'hod.clusterdir')
  617. numNodes = getattr(self.__parsedOptions, 'hod.nodecount')
  618. if not _script or not clusterDir or not numNodes:
  619. print getattr(hodhelp, "help_%s" % cmdstr)()
  620. sys.exit(3)
  621. pass
  622. elif cmdstr == "help":
  623. if nArgs == 1:
  624. self.print_help()
  625. sys.exit(0)
  626. elif nArgs != 2:
  627. self.print_help()
  628. sys.exit(3)
  629. elif self.args[1] == 'options':
  630. self.print_options()
  631. sys.exit(0)
  632. cmdstr = cmdstr + ' ' + self.args[1]
  633. setattr(self.__parsedOptions,'hod.operation', cmdstr)
  634. # end of processing for arguments on the client side
  635. if self.__withConfig:
  636. self.config = self.__parsedOptions.config
  637. if not self.config:
  638. self.error("configuration file must be specified")
  639. if not os.path.isabs(self.config):
  640. # A relative path. Append the original directory which would be the
  641. # current directory at the time of launch
  642. try:
  643. origDir = getattr(self.__parsedOptions, 'hod.original-dir')
  644. if origDir is not None:
  645. self.config = os.path.join(origDir, self.config)
  646. self.__parsedOptions.config = self.config
  647. except AttributeError, e:
  648. self.error("hod.original-dir is not defined.\
  649. Cannot get current directory")
  650. if not os.path.exists(self.config):
  651. if self.__defaultLoc and not re.search("/", self.config):
  652. self.__parsedOptions.config = os.path.join(
  653. self.__defaultLoc, self.config)
  654. self.__build_dict()
  655. def __init_display_options(self):
  656. self.__orig_option_list = self.option_list[:]
  657. optionListTitleMap = {}
  658. for option in self.option_list:
  659. optionListTitleMap[option._long_opts[0]] = option
  660. self.__orig_grps = self.option_groups[:]
  661. for group in self.option_groups:
  662. self.__orig_grp_lists[group.title] = group.option_list[:]
  663. groupTitleMap = {}
  664. optionTitleMap = {}
  665. for group in self.option_groups:
  666. groupTitleMap[group.title] = group
  667. optionTitleMap[group.title] = {}
  668. for option in group.option_list:
  669. (sectionName, optionName) = \
  670. self.__split_compound(option._long_opts[0])
  671. optionTitleMap[group.title][optionName] = option
  672. for section in self._mySections:
  673. for option in self._configDef[section]:
  674. if self._configDef[section][option]['help']:
  675. if groupTitleMap.has_key(section):
  676. if not self.__display_grp_lists.has_key(section):
  677. self.__display_grp_lists[section] = []
  678. self.__display_grp_lists[section].append(
  679. optionTitleMap[section][option])
  680. try:
  681. self.__display_option_list.append(
  682. optionListTitleMap["--" + self.__splice_compound(
  683. section, option)])
  684. except KeyError:
  685. pass
  686. try:
  687. self.__display_option_list.append(optionListTitleMap['--config'])
  688. except KeyError:
  689. pass
  690. self.__display_option_list.append(optionListTitleMap['--help'])
  691. self.__display_option_list.append(optionListTitleMap['--verbose-help'])
  692. self.__display_option_list.append(optionListTitleMap['--version'])
  693. self.__display_grps = self.option_groups[:]
  694. for section in self._mySections:
  695. if self.__display_grp_lists.has_key(section):
  696. self.__orig_grp_lists[section] = \
  697. groupTitleMap[section].option_list
  698. else:
  699. try:
  700. self.__display_grps.remove(groupTitleMap[section])
  701. except KeyError:
  702. pass
  703. def __gen_alpha(self):
  704. assignedOptions = []
  705. for section in self._configDef:
  706. for option in self._configDef[section]:
  707. if self._configDef[section][option]['short']:
  708. assignedOptions.append(
  709. self._configDef[section][option]['short'])
  710. for symbol in self.__alphaString:
  711. if not symbol in assignedOptions:
  712. self.__alpha.append(symbol)
  713. def __splice_compound(self, section, option):
  714. return "%s.%s" % (section, option)
  715. def __split_compound(self, compound):
  716. return compound.split('.')
  717. def __build_short_map(self):
  718. """ build a short_map of parametername : short_option. This is done
  719. only for those parameters that don't have short options already
  720. defined in configDef.
  721. If possible, the first letter in the option that is not already
  722. used/reserved as a short option is allotted. Otherwise the first
  723. letter in __alpha that isn't still used is allotted.
  724. e.g. { 'hodring.java-home': 'T', 'resource_manager.batch-home': 'B' }
  725. """
  726. optionsKey = {}
  727. for compound in self.__optionList:
  728. (section, option) = self.__split_compound(compound)
  729. if not optionsKey.has_key(section):
  730. optionsKey[section] = []
  731. optionsKey[section].append(option)
  732. for section in self._configDef.sections():
  733. options = optionsKey[section]
  734. options.sort()
  735. for option in options:
  736. if not self._configDef[section][option]['short']:
  737. compound = self.__splice_compound(section, option)
  738. shortOptions = self.__shortMap.values()
  739. for i in range(0, len(option)):
  740. letter = option[i]
  741. letter = letter.lower()
  742. if letter in self.__alpha:
  743. if not letter in shortOptions and \
  744. not letter in self.__reserved:
  745. self.__shortMap[compound] = letter
  746. break
  747. if not self.__shortMap.has_key(compound):
  748. for i in range(0, len(self.__alpha)):
  749. letter = self.__alpha[i]
  750. if not letter in shortOptions and \
  751. not letter in self.__reserved:
  752. self.__shortMap[compound] = letter
  753. def __add_option(self, config, compoundOpt, section, option, group=None):
  754. addMethod = self.add_option
  755. if group: addMethod=group.add_option
  756. self.__compoundOpts.append(compoundOpt)
  757. if compoundOpt == 'gridservice-mapred.final-server-params' or \
  758. compoundOpt == 'gridservice-hdfs.final-server-params' or \
  759. compoundOpt == 'gridservice-mapred.server-params' or \
  760. compoundOpt == 'gridservice-hdfs.server-params' or \
  761. compoundOpt == 'hod.client-params':
  762. _action = 'append'
  763. elif config[section][option]['type'] == 'bool':
  764. _action = 'store_true'
  765. else:
  766. _action = 'store'
  767. if self.__shortMap.has_key(compoundOpt):
  768. addMethod("-" + self.__shortMap[compoundOpt],
  769. "--" + compoundOpt, dest=compoundOpt,
  770. action= _action,
  771. metavar=config[section][option]['type'],
  772. default=config[section][option]['default'],
  773. help=config[section][option]['desc'])
  774. else:
  775. if config[section][option]['short']:
  776. addMethod("-" + config[section][option]['short'],
  777. "--" + compoundOpt, dest=compoundOpt,
  778. action= _action,
  779. metavar=config[section][option]['type'],
  780. default=config[section][option]['default'],
  781. help=config[section][option]['desc'])
  782. else:
  783. addMethod('', "--" + compoundOpt, dest=compoundOpt,
  784. action= _action,
  785. metavar=config[section][option]['type'],
  786. default=config[section][option]['default'],
  787. help=config[section][option]['desc'])
  788. def __add_options(self):
  789. if self.__withConfig:
  790. self.add_option("-c", "--config", dest='config',
  791. action='store', default=self.__defaultConfig,
  792. metavar='config_file',
  793. help="Full path to configuration file.")
  794. self.add_option("", "--verbose-help",
  795. action='help', default=None,
  796. metavar='flag',
  797. help="Display verbose help information.")
  798. self.add_option("-v", "--version",
  799. action='version', default=None,
  800. metavar='flag',
  801. help="Display version information.")
  802. self.version = self.__version
  803. if len(self._mySections) > 1:
  804. for section in self._mySections:
  805. group = OptionGroup(self, section)
  806. for option in self._configDef[section]:
  807. compoundOpt = self.__splice_compound(section, option)
  808. self.__add_option(self._configDef, compoundOpt, section,
  809. option, group)
  810. self.add_option_group(group)
  811. else:
  812. for section in self._mySections:
  813. for option in self._configDef[section]:
  814. compoundOpt = self.__splice_compound(section, option)
  815. self.__add_option(self._configDef, compoundOpt, section,
  816. option)
  817. def __build_dict(self):
  818. if self.__withConfig:
  819. self._dict['config'] = str(getattr(self.__parsedOptions, 'config'))
  820. for compoundOption in dir(self.__parsedOptions):
  821. if compoundOption in self.__compoundOpts:
  822. (section, option) = self.__split_compound(compoundOption)
  823. if not self._dict.has_key(section):
  824. self._dict[section] = {}
  825. if getattr(self.__parsedOptions, compoundOption):
  826. _attr = getattr(self.__parsedOptions, compoundOption)
  827. # when we have multi-valued parameters passed separately
  828. # from command line, python optparser pushes them into a
  829. # list. So converting all such lists to strings
  830. if type(_attr) == type([]):
  831. import string
  832. _attr = string.join(_attr,',')
  833. self._dict[section][option] = _attr
  834. for section in self._configDef:
  835. for option in self._configDef[section]:
  836. if self._configDef[section][option]['type'] == 'bool':
  837. compoundOption = self.__splice_compound(section, option)
  838. if not self._dict.has_key(section):
  839. self._dict[section] = {}
  840. if option not in self._dict[section]:
  841. self._dict[section][option] = False
  842. def __set_display_groups(self):
  843. if not '--verbose-help' in sys.argv:
  844. self.option_groups = self.__display_grps
  845. self.option_list = self.__display_option_list
  846. for group in self.option_groups:
  847. group.option_list = self.__display_grp_lists[group.title]
  848. def __unset_display_groups(self):
  849. if not '--verbose-help' in sys.argv:
  850. self.option_groups = self.__orig_grps
  851. self.option_list = self.__orig_option_list
  852. for group in self.option_groups:
  853. group.option_list = self.__orig_grp_lists[group.title]
  854. def print_help(self, file=None):
  855. self.__set_display_groups()
  856. OptionParser.print_help(self, file)
  857. self.__unset_display_groups()
  858. def print_options(self):
  859. _usage = self.usage
  860. self.set_usage('')
  861. self.print_help()
  862. self.set_usage(_usage)
  863. def verify(self):
  864. return baseConfig.verify(self)
  865. def replace_escape_seqs(self):
  866. replace_escapes(self)