Module PluginRunner
[hide private]
[frames] | no frames]

Source Code for Module PluginRunner

  1  #!/usr/bin/env python 
  2   
  3  """ 
  4  @copyright: Copyright (C) 2008, 2010 Oracle and/or its affiliates. All rights reserved. 
  5   
  6  @license:   See the file COPYING for redistribution information. 
  7   
  8  @summary:   Very simple interpreter used to test a Oracle VM Storage Connect 
  9              plugins in isolation. 
 10  """ 
 11   
 12  import os 
 13  import sys 
 14   
 15  if "/opt/storage-connect" not in sys.path: sys.path.append("/opt/storage-connect") 
 16   
 17  # PyDev remote debugging setup 
 18  if os.environ.has_key('PYDEV_DEBUG') and os.path.exists('/opt/pydev/pysrc'): 
 19      sys.path.append('/opt/pydev/pysrc') 
 20      try: 
 21          import pydevd #@UnresolvedImport 
 22          if os.environ['PYDEV_DEBUG'].lower() in ['o', 'on', 'y',  'yes', 't', 'true', '1']: 
 23              pydevd.settrace()  
 24       
 25          else: 
 26              pydevd.settrace(os.environ['PYDEV_DEBUG']) 
 27   
 28      except: 
 29          pass 
 30   
 31  import cmd 
 32  import gettext 
 33  import optparse 
 34  import logging #@UnusedImport 
 35  import logging.handlers 
 36  import traceback 
 37   
 38  import OSCPlugin 
 39   
 40  from optparse import OptionParser 
 41  from PluginManager import PluginManager 
 42   
 43  _ = gettext.gettext 
 44   
 45  __revision__="15" 
46 47 -class PluginError(Exception):
48 - def __init__(self, msg):
49 self.msg = msg
50
51 - def __str__(self):
52 return repr(self.msg)
53
54 -class PluginInstallError(PluginError):
55 - def __init__(self, msg):
56 self.msg = msg
57
58 -class PluginInvalidOption(PluginError):
59 - def __init__(self, msg):
60 self.msg = msg
61
62 -class ScriptError(Exception):
63 - def __init__(self, message):
64 self.message = message 65 self.args = message
66
67 - def __repr__(self):
68 return self.message
69
70 - def __str__(self):
71 return self.message
72
73 -class TestFailed(Exception):
74 - def __init__(self, test, message):
75 self.test = test 76 self.message = message 77 self.args = (test, message)
78
79 - def __repr__(self):
80 return "%s: %s" % (self.test, self.message)
81
82 - def __str__(self):
83 return "%s: %s" % (self.test, self.message)
84
85 -class Interpreter(cmd.Cmd):
86 - def __init__(self, histfile):
87 cmd.Cmd.__init__(self) 88 self.prompt = "OSCPR>>> " 89 self.intro = "Welcome to the Oracle Storage Connect Plugin Runner.\n\n" \ 90 "Type help for more command information.\n\n" 91 92 import readline 93 import rlcompleter #@UnusedImport 94 95 if histfile: 96 try: 97 readline.read_history_file(histfile) 98 99 except IOError: 100 pass 101 102 import atexit 103 atexit.register(readline.write_history_file, histfile) 104 105 self._quit_ = False 106 self._stdoutHandler_ = None 107 self._indent_ = 0 108 self._hist_ = [] 109 self._locals_ = {} 110 self._globals_ = { 111 "getPlugin": self.getPlugin, 112 "ScriptError": ScriptError, 113 "TestFailed": TestFailed, 114 } 115 self._logger_ = None 116 self._plugin_ = None 117 self._plugin_mgr_ = PluginManager()
118
119 - def cmdloop(self, handle_exceptions = False, intro = None):
120 self.preloop() 121 if self.use_rawinput and self.completekey: 122 try: 123 import readline 124 self.old_completer = readline.get_completer() 125 readline.set_completer(self.complete) 126 readline.parse_and_bind(self.completekey + ": complete") 127 128 except ImportError: 129 pass 130 131 try: 132 if intro is not None: 133 self.intro = intro 134 135 if self.intro: 136 self.stdout.write(str(self.intro) + "\n") 137 138 stop = None 139 while stop is None: 140 if self.cmdqueue: 141 line = self.cmdqueue.pop(0) 142 143 else: 144 use_prompt = self.prompt 145 doexec = False 146 multiline = '' 147 if self.use_rawinput: 148 while not doexec: 149 try: 150 line = raw_input(use_prompt) 151 152 except EOFError: 153 line = 'EOF' 154 155 if not len(line) or line == 'EOF': 156 doexec = True 157 158 else: 159 if line[-1:] in ['\\', ':'] or len(multiline): 160 if line[-1:] in ['\\', ':']: 161 use_prompt = '.' * len(self.prompt) 162 163 multiline += line + '\n' 164 165 else: 166 doexec = True 167 168 if len(multiline): 169 line = multiline 170 171 else: 172 self.stdout.write(use_prompt) 173 self.stdout.flush() 174 while not doexec: 175 line = self.stdin.readline() 176 if not len(line): 177 doexec = True 178 179 else: 180 if line[-1:] in ['\\', ':'] or len(multiline): 181 if line[-1:] in ['\\', ':']: 182 use_prompt = '.' * len(self.prompt) 183 184 multiline += line + '\n' 185 186 else: 187 doexec = True 188 189 if len(multiline): 190 line = multiline 191 192 line = self.precmd(line) 193 try: 194 stop = self.onecmd(line) 195 196 except Exception, e: 197 if handle_exceptions: 198 print "%s: %s" % (e.__class__.__name__, e) 199 continue 200 201 else: 202 raise 203 204 stop = self.postcmd(stop, line) 205 206 self.postloop() 207 208 finally: 209 if self.use_rawinput and self.completekey: 210 try: 211 import readline 212 readline.set_completer(self.old_completer) 213 214 except ImportError: 215 pass
216
217 - def get_names(self):
218 # The cmd one is just plain broken! 219 return dir(self)
220
221 - def completenames(self, text, line, begidx, endidx):
222 if len(text) == 0: 223 names = [a[3:] for a in dir(self) if not a.startswith('_')] + \ 224 [b for b in self._globals_ if not b.startswith('_')] + \ 225 [c for c in dir(__builtins__) if not c.startswith('_')] 226 227 elif text.rfind('.') > 0: 228 dir_text = text[:text.rfind('.')] 229 tab_text = text[text.rfind('.') + 1:] 230 exec "__dirKW_list__ = dir(%s)" % dir_text in self._locals_, self._globals_ 231 if self._globals_.has_key("__dirKW_list__"): 232 dir_list = self._globals_.pop("__dirKW_list__") 233 if len(tab_text) == 0: 234 names = [dir_text + '.' + a for a in dir_list if not a.startswith('_')] 235 236 else: 237 names = [dir_text + '.' + a for a in dir_list if a.startswith(tab_text)] 238 239 else: 240 names = [a[3:] for a in dir(self) if a.startswith("do_" + text)] + \ 241 [b for b in self._globals_ if b.startswith(text)] + \ 242 [c for c in dir(__builtins__) if c.startswith(text)] 243 244 return names
245
246 - def preloop(self):
247 cmd.Cmd.preloop(self) 248 if self._plugin_: 249 self._globals_["plugin"] = self._plugin_
250
251 - def postloop(self):
252 cmd.Cmd.postloop(self) 253 if not self._quit_: 254 print "\n\nExiting...\n"
255
256 - def precmd(self, line):
257 self._hist_ += [line.strip()] 258 return line
259
260 - def postcmd(self, stop, line):
261 return stop
262
263 - def emptyline(self):
264 pass
265
266 - def default(self, line):
267 verbose = True 268 try: 269 if line.startswith('@'): 270 if line.startswith('@@'): 271 verbose = False 272 if self._stdoutHandler_: 273 self._logger_.removeHandler(self._stdoutHandler_) 274 275 line = line[1:] 276 277 else: 278 if not self._stdoutHandler_: 279 self._stdoutHandler_ = logging.StreamHandler() 280 self._stdoutHandler_.setLevel(logging.INFO) 281 self._logger_.addHandler(self._stdoutHandler_) 282 283 self.do_script(line[1:]) 284 285 if self._stdoutHandler_: 286 self._logger_.removeHandler(self._stdoutHandler_) 287 288 else: 289 exec line in self._locals_, self._globals_ 290 291 except TestFailed, e: 292 if self._stdoutHandler_: 293 self._logger_.removeHandler(self._stdoutHandler_) 294 295 self._logger_.fatal("%s" % e.__repr__()) 296 297 if not verbose: 298 sys.stderr.write("\n\n") 299 traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback) 300 301 else: 302 raise 303 304 except Exception, e: 305 if self._stdoutHandler_: 306 self._logger_.removeHandler(self._stdoutHandler_) 307 308 self._logger_.fatal("%s: %s" % (e.__class__.__name__, e)) 309 310 if not verbose: 311 sys.stderr.write("\n\n") 312 traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback) 313 314 else: 315 raise
316
317 - def do_hist(self, args):
318 """ 319 Print the list of commands that have been entered 320 """ 321 print '\n'.join(self._hist_)
322
323 - def do_exit(self, args):
324 """ 325 Exit from the interpreter 326 """ 327 return True
328
329 - def do_quit(self, args):
330 """ 331 Quit from the interpreter 332 """ 333 self._quit_ = True 334 return self._quit_
335
336 - def do_help(self, args):
337 """ 338 Get help on commands 339 'help' or '?' with no arguments prints a list of commands for which help 340 is available 341 'help <command>' or '? <command>' gives help on the specific <command> 342 """ 343 if args == '@': 344 args = "atsign" 345 if args == "@@": 346 args = "atatsign" 347 cmd.Cmd.do_help(self, args)
348
349 - def do_EOF(self, args):
350 """ 351 Exit from the interpreter 352 """ 353 return True
354
355 - def do_script(self, line):
356 """ 357 Execute a script (Same as @@) 358 """ 359 line = line.strip() 360 if len(line) > 0: 361 if os.path.exists(line): 362 file_path = os.path.abspath(line) 363 file_name = os.path.basename(file_path) 364 sys.modules["PluginRunner"] = sys.modules["__main__"] 365 sys.modules["PluginRunner"].__name__ = "PluginRunner" 366 367 from imp import new_module 368 _mod = new_module("__main__") 369 sys.modules["__main__"] = _mod 370 _mod.__file__ = file_path 371 globals = _mod.__dict__ 372 globals["SCRIPT_NAME"] = file_name 373 if _mod.__file__.startswith(sys.path[0]): 374 del sys.path[0] 375 376 sys.path.insert(0, os.path.split(file_path)[0]) 377 for gkey in self._globals_.keys(): 378 globals[gkey] = self._globals_[gkey] 379 380 __argv = sys.argv[:] 381 sys.argv = [file_path] 382 if self._globals_.get("argv", None) is not None: 383 sys.argv.append(self._globals_["argv"]) 384 385 execfile(file_path, globals) 386 387 sys.argv = __argv 388 389 else: 390 print "Script file '%s' does not exist" % line 391 392 else: 393 print "*** No script name supplied"
394
395 - def help_atsign(self):
396 """ 397 Execute script duplicating logs to terminal for monitoring 398 """ 399 print "Execute script duplicating logs to terminal for monitoring"
400
401 - def help_atatsign(self):
402 """ 403 Execute script without duplicating logging to terminal 404 """ 405 print "Execute script without duplicating logging to terminal"
406
407 - def help_script(self):
408 """ 409 Execute script without duplicating logging to terminal 410 """ 411 print "Execute script without duplicating logging to terminal"
412
413 - def help_logger(self):
414 """ 415 Log the text to the log file 416 """ 417 exec "import logging\nhelp(logging)" in self._locals_, self._globals_
418
419 - def help_getPlugin(self):
420 self.stdout.write("\n%s\n\n" % 421 " Get the Plugin Manager class for the named plugin.\n\n" 422 " Returns the Plugin Manager class for the named Storage Connect plugin.")
423
424 - def setLogger(self, logger):
425 self._logger_ = logger 426 self._globals_["logger"] = logger 427 if self._plugin_mgr_: 428 self._plugin_mgr_.setLogger(logger)
429
430 - def getPlugin(self, plugin_impl_name):
431 if not self._logger_: 432 raise PluginInstallError(_("No logger have been setup yet")) 433 434 self._plugin_ = self._plugin_mgr_.getPlugin(plugin_impl_name) 435 if not self._plugin_: 436 raise PluginInstallError(_("Unable to locate plugin %s" % plugin_impl_name)) 437 438 return self._plugin_
439
440 - def setAdminHostName(self, admin_host):
441 self._globals_["adminHostName"] = admin_host 442 self._globals_["initialiseVariables"] = True
443
444 - def setAdminUserName(self, admin_user):
445 self._globals_["adminUserName"] = admin_user 446 self._globals_["initialiseVariables"] = True
447
448 - def setAdminPassword(self, admin_pass):
449 self._globals_["adminPassword"] = admin_pass 450 self._globals_["initialiseVariables"] = True
451
452 - def setExtraInfo(self, extra_info):
453 self._globals_["extraInfo"] = extra_info 454 self._globals_["initialiseVariables"] = True
455
456 - def setAccessHostName(self, access_host):
457 self._globals_["accessHostName"] = access_host 458 self._globals_["initialiseVariables"] = True
459
460 - def setUserName(self, user_name):
461 self._globals_["userName"] = user_name 462 self._globals_["initialiseVariables"] = True
463
464 - def setPassword(self, password):
465 self._globals_["password"] = password 466 self._globals_["initialiseVariables"] = True
467
468 - def setCHAPMode(self, chap_mode):
469 self._globals_["CHAP"] = chap_mode
470
471 - def setStorageType(self, storage_type):
472 self._globals_["storageType"] = storage_type 473 self._globals_["initialiseVariables"] = True
474
475 - def setVolumeGroupName(self, vol_group_name):
476 self._globals_["volGroupName"] = vol_group_name 477 self._globals_["initialiseVariables"] = True
478
479 - def setPluginImplName(self, plugin_impl_name):
480 self._globals_["pluginImplName"] = plugin_impl_name 481 self._globals_["initialiseVariables"] = True
482
483 - def setScriptOptions(self, scriptOptions):
484 self._globals_["argv"] = scriptOptions
485
486 - def setOKToRun(self, noQuestionsAsked):
487 self._globals_["okToRun"] = noQuestionsAsked
488
489 -class CmdLineOptions:
490 - def __init__(self, program_name, version):
491 self.parser = OptionParser(usage = "%prog [options] ...", 492 version = "Oracle VM Storage Connect " 493 "Plugin Runner version %s" % version, 494 prog = program_name, 495 add_help_option = False) 496 497 self.parser.disable_interspersed_args() 498 499 self.parser.add_option("-h", "--help", 500 action = "callback", 501 callback = CmdLineOptions._help_opt_callback_, 502 callback_args = (self, "exit", 0)) 503 504 self.parser.add_option("--show-plugins", 505 dest = "show_plugins", 506 action = "store_true", 507 default = False, 508 help = "Display all the installed Storage Connect plugins on the" 509 "system.") 510 511 self.parser.add_option("--ignore-discover-errors", 512 dest = "ignore_discover_errors", 513 action = "store_true", 514 default = False, 515 help = optparse.SUPPRESS_HELP) 516 517 self.parser.add_option("--plugin", 518 dest = "plugin_impl_name", 519 metavar = "IPlugin", 520 help = "Implementation name of the Storage Connect plugin to use") 521 522 self.parser.add_option("--admin-host", 523 dest = "admin_host", 524 metavar = "adminHostName", 525 help = "Storage Server Administrator Hostname") 526 527 self.parser.add_option("--admin-user", 528 dest = "admin_user", 529 metavar = "adminUserName", 530 help = "Storage Server Administration Username") 531 532 self.parser.add_option("--admin-passwd", 533 dest = "admin_pass", 534 metavar = "adminPassword", 535 help = "Storage Server Administration Password") 536 537 self.parser.add_option("--extra-info", 538 dest = "extra_info", 539 metavar = "extraInfo", 540 help = "Storage Server Extra Info field") 541 542 self.parser.add_option("--access-host", 543 dest = "access_host", 544 metavar = "accessHostName", 545 help = "Storage Server iSCSI Access Hostname") 546 547 self.parser.add_option("--username", 548 dest = "user_name", 549 metavar = "userName", 550 help = "Storage Server iSCSI Username") 551 552 self.parser.add_option("--password", 553 dest = "password", 554 metavar = "password", 555 help = "Storage Server iSCSI Password") 556 557 self.parser.add_option("--enable-chap", 558 dest = "chap", 559 metavar = "CHAP", 560 help = "Enable Storage Server iSCSI CHAP", 561 action = "store_true", 562 default = False) 563 564 self.parser.add_option("--storage-type", 565 dest = "storage_type", 566 metavar = "storageType", 567 help = "Storage Server Storage Type (SAN/iSCSI/NFS/OCFS2)") 568 569 self.parser.add_option("--vol-group-name", 570 dest = "vol_group_name", 571 metavar = "volumeGroupName", 572 help = "Volume group name to be used when creating LUNs") 573 574 self.parser.add_option("--script", 575 dest = "script_name", 576 metavar = "scriptName", 577 help = "Non-interactive execution of script scriptName") 578 579 self.parser.add_option("--script-options", 580 dest = "script_options", 581 metavar = "scriptOptions", 582 help = "Options to supply to the script (e.g. clean-first)") 583 584 self.parser.add_option("--verbose", 585 dest = "verbose", 586 action = "store_true", 587 help = "In non-interactive script execution, the log output " 588 "will be duplicated on the terminal.") 589 590 self.parser.add_option("--log-dir", 591 dest = "log_dir", 592 default = ".", 593 metavar = "LogFileDir", 594 help = "Set the directory where the log file should be created" 595 " (Defaults to .)") 596 597 self.parser.add_option("--log-name", 598 dest = "log_file_name", 599 metavar = "LogFileName", 600 help = "Set the name of the log file " 601 "(Defaults to pluginrunner_<implname>.log)") 602 603 self.parser.add_option("--overwrite-log", 604 dest = "overwrite_log", 605 action = "store_true", 606 help = "Overwrite any old log file instead of" 607 "appending to it.") 608 609 self.parser.add_option("--yes-to-all", 610 dest = "yes_to_all", 611 action = "store_true", 612 help = "The tests are DESTRUCTIVE, this will allow tests to be run" 613 "WITHOUT ASKING ANY confirmation.")
614 615 @staticmethod
616 - def _help_opt_callback_(option, opt, value, parser, *xargs):
617 xargs[0].printHelp() 618 if xargs[1] == "exit": 619 import sys #@Reimport 620 sys.exit(xargs[2])
621
622 - def parse(self, args):
623 (self.options, self.xtra_args) = self.parser.parse_args(args) 624 return (self.options, self.xtra_args)
625
626 - def getParsedOptions(self):
627 return (self.options, self.xtra_args)
628
629 - def printHelp(self):
630 self.parser.print_help() 631 print "\n" 632 print "for example:\n" 633 print "%s \\" % self.parser.prog 634 print " --plugin=oracle.sample.SCSIPlugin.SamplePlugin \\" 635 print " --admin-host=myarray.example.com \\" 636 print " --admin-user=admin \\" 637 print " --admin-passwd=password \\" 638 print " --storage-type=SAN \\" 639 print " --vol-group-name=MyVolGroup \\" 640 print " --script=MyTestScript.pscr \\" 641 print " --script-options=clean-first \\" 642 print " --log-dir=/tmp \\" 643 print " --log-name=pluginrunner_sampleplugin.log \\" 644 print " --overwrite-log\n" 645 print "OR" 646 print "%s --show-plugins" % self.parser.prog 647 print "\n"
648
649 -def main(args):
650 program_name = os.path.basename(sys.argv[0]) 651 if program_name.rfind(".") > 0: 652 program_name = program_name[:program_name.rfind(".")] 653 654 version = "" 655 for vers_sect in OSCPlugin.IPlugin.plugin_api_version: 656 version = version + vers_sect + "." 657 658 version = version[:-1] + __revision__ 659 histfile = os.path.join(os.environ["HOME"], ".%s_hist" % program_name.lower()) 660 661 try: 662 cmd_line_opts = CmdLineOptions(program_name, version) 663 options, xtra_args = cmd_line_opts.parse(args) #@UnusedVariable 664 665 if options.show_plugins: 666 pluginManager = PluginManager() 667 print "\nInstalled Storage Connect plugins:\n" 668 for pluginName in pluginManager.discoverPlugins(ignore_failed = options.ignore_discover_errors): 669 print " %s" % pluginName 670 671 print "\n" 672 sys.exit(0) 673 674 if options.overwrite_log: 675 mode = "w" 676 677 else: 678 mode = "a" 679 680 if not options.log_file_name: 681 if options.plugin_impl_name: 682 name_pfxm, plugin_base_name = options.plugin_impl_name.rsplit('.', 1) #@UnusedVariable 683 log_name = "%s/%s_%s.log" % (options.log_dir, 684 program_name.lower(), 685 plugin_base_name) 686 687 else: 688 log_name = "%s/%s.log" % (options.log_dir, program_name) 689 690 else: 691 log_name = "%s/%s" % (options.log_dir, options.log_file_name) 692 693 log_format = logging.Formatter("<%(asctime)s %(levelname)s> %(message)s", 694 "%y/%m/%d %H:%M:%S") 695 696 logger = logging.getLogger(program_name) 697 default_handler = logging.handlers.RotatingFileHandler(log_name, 698 mode = mode, 699 backupCount = 7) 700 default_handler.setFormatter(log_format) 701 logger.addHandler(default_handler) 702 703 if options.verbose: 704 logger.setLevel(logging.DEBUG) 705 default_handler.setLevel(logging.DEBUG) 706 707 else: 708 logger.setLevel(logging.INFO) 709 default_handler.setLevel(logging.INFO) 710 711 interpreter = Interpreter(histfile) 712 interpreter.setLogger(logger) 713 logger.info("%s Start %s" % ('=' * 15, '=' * 15)) 714 if options.plugin_impl_name: 715 if options.verbose: 716 logger.info('pluginImplName = "%s"', options.plugin_impl_name) 717 interpreter.setPluginImplName(options.plugin_impl_name) 718 interpreter.getPlugin(options.plugin_impl_name) 719 720 if options.admin_host: 721 if options.verbose: 722 logger.info('adminHostName = "%s"', options.admin_host) 723 interpreter.setAdminHostName(options.admin_host) 724 725 if options.admin_user: 726 if options.verbose: 727 logger.info('adminUserName = "%s"', options.admin_user) 728 interpreter.setAdminUserName(options.admin_user) 729 730 if options.admin_pass: 731 if options.verbose: 732 logger.info('adminPassword = "********"') 733 interpreter.setAdminPassword(options.admin_pass) 734 735 if options.extra_info: 736 if options.verbose: 737 logger.info('extraInfo = "%s"', options.extra_info) 738 interpreter.setExtraInfo(options.extra_info) 739 740 if options.access_host: 741 if options.verbose: 742 logger.info('accessHostName = "%s"', options.access_host) 743 interpreter.setAccessHostName(options.access_host) 744 745 if options.user_name: 746 if options.verbose: 747 logger.info('userName = "%s"', options.user_name) 748 interpreter.setUserName(options.user_name) 749 750 if options.password: 751 if options.verbose: 752 logger.info('password = "%s"', options.password) 753 interpreter.setPassword(options.access_host) 754 755 if options.chap is not None: 756 if options.verbose: 757 logger.info('CHAP = "%s"', options.chap) 758 interpreter.setCHAPMode(options.chap) 759 760 if options.storage_type: 761 if options.verbose: 762 logger.info('storageType = "%s"', options.storage_type) 763 interpreter.setStorageType(options.storage_type) 764 765 if options.vol_group_name: 766 if options.verbose: 767 logger.info('volGroupName = "%s"', options.vol_group_name) 768 interpreter.setVolumeGroupName(options.vol_group_name) 769 770 if options.yes_to_all: 771 if options.verbose: 772 logger.info("okToRun = True") 773 interpreter.setOKToRun(options.yes_to_all) 774 775 if options.script_options: 776 if options.verbose: 777 logger.info('scriptOptions = "%s"', options.script_options) 778 interpreter.setScriptOptions(options.script_options) 779 780 if options.script_name: 781 if options.verbose: 782 logger.info('scriptName = "%s"', options.script_name) 783 interpreter.cmdqueue.append("@ %s" % options.script_name) 784 785 else: 786 interpreter.cmdqueue.append("@@ %s" % options.script_name) 787 788 interpreter.cmdqueue.append("quit") 789 790 logger.debug("Start interpreter...") 791 if options.verbose: 792 interpreter.cmdloop(False) 793 794 else: 795 interpreter.cmdloop(True) 796 797 logger.info("%s End %s" % ('=' * 15, '=' * 15)) 798 799 except PluginError, e: 800 sys.stderr.write("\nERROR: %s\n" % e.msg) 801 sys.exit(1) 802 803 except PluginInvalidOption, e: 804 sys.stderr.write("\nERROR: %s\n" % e.msg) 805 if cmd_line_opts: 806 cmd_line_opts.printHelp() 807 808 sys.exit(2)
809 810 # 811 # Entry point... 812 # 813 if __name__ == '__main__': main(sys.argv[1:]) 814