1
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
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
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
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"
53
57
61
64 self.message = message
65 self.args = message
66
69
72
75 self.test = test
76 self.message = message
77 self.args = (test, message)
78
80 return "%s: %s" % (self.test, self.message)
81
83 return "%s: %s" % (self.test, self.message)
84
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
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
220
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
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
257 self._hist_ += [line.strip()]
258 return line
259
260 - def postcmd(self, stop, line):
262
265
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
318 """
319 Print the list of commands that have been entered
320 """
321 print '\n'.join(self._hist_)
322
324 """
325 Exit from the interpreter
326 """
327 return True
328
330 """
331 Quit from the interpreter
332 """
333 self._quit_ = True
334 return self._quit_
335
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
350 """
351 Exit from the interpreter
352 """
353 return True
354
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
396 """
397 Execute script duplicating logs to terminal for monitoring
398 """
399 print "Execute script duplicating logs to terminal for monitoring"
400
402 """
403 Execute script without duplicating logging to terminal
404 """
405 print "Execute script without duplicating logging to terminal"
406
408 """
409 Execute script without duplicating logging to terminal
410 """
411 print "Execute script without duplicating logging to terminal"
412
414 """
415 Log the text to the log file
416 """
417 exec "import logging\nhelp(logging)" in self._locals_, self._globals_
418
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
429
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
441 self._globals_["adminHostName"] = admin_host
442 self._globals_["initialiseVariables"] = True
443
445 self._globals_["adminUserName"] = admin_user
446 self._globals_["initialiseVariables"] = True
447
449 self._globals_["adminPassword"] = admin_pass
450 self._globals_["initialiseVariables"] = True
451
453 self._globals_["extraInfo"] = extra_info
454 self._globals_["initialiseVariables"] = True
455
457 self._globals_["accessHostName"] = access_host
458 self._globals_["initialiseVariables"] = True
459
461 self._globals_["userName"] = user_name
462 self._globals_["initialiseVariables"] = True
463
465 self._globals_["password"] = password
466 self._globals_["initialiseVariables"] = True
467
469 self._globals_["CHAP"] = chap_mode
470
472 self._globals_["storageType"] = storage_type
473 self._globals_["initialiseVariables"] = True
474
476 self._globals_["volGroupName"] = vol_group_name
477 self._globals_["initialiseVariables"] = True
478
480 self._globals_["pluginImplName"] = plugin_impl_name
481 self._globals_["initialiseVariables"] = True
482
484 self._globals_["argv"] = scriptOptions
485
487 self._globals_["okToRun"] = noQuestionsAsked
488
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
617 xargs[0].printHelp()
618 if xargs[1] == "exit":
619 import sys
620 sys.exit(xargs[2])
621
623 (self.options, self.xtra_args) = self.parser.parse_args(args)
624 return (self.options, self.xtra_args)
625
627 return (self.options, self.xtra_args)
628
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
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)
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)
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
812
813 if __name__ == '__main__': main(sys.argv[1:])
814