-import migrate
-import massmigrate
-import info
-import summary
-import upgrade
+import logging
+import os
+import sys
+import optparse
+import errno
+
+import wizard
+
+logging_setup = False
+
+class Error(wizard.Error):
+ """Base error class for all command errors"""
+ pass
+
+class PermissionsError(Error):
+ def __init__(self, dir):
+ self.dir = dir
+ def __str__(self):
+ return """
+
+ERROR: You don't have permissions to access this directory.
+Do you have tokens for AFS with your root instance, and
+is your root instance on scripts-security-upd?
+
+You can check by running the commands 'klist' and
+'blanche scripts-security-upd'.
+"""
+
+class NoSuchDirectoryError(Error):
+ def __init__(self, dir):
+ self.dir = dir
+ def __str__(self):
+ return """
+
+ERROR: No such directory... check your typing
+"""
+
+def chdir(dir):
+ try:
+ os.chdir(dir)
+ except OSError as e:
+ if e.errno == errno.EACCES:
+ raise PermissionsError(dir)
+ elif e.errno == errno.ENOENT:
+ raise NoSuchDirectoryError(dir)
+ else: raise e
+
+def makeLogger(options, numeric_args):
+ global logging_setup
+ if logging_setup: return logging.getLogger()
+ context = " ".join(numeric_args)
+ logger = logging.getLogger()
+ logger.setLevel(logging.INFO)
+ stderr = logging.StreamHandler(sys.stderr)
+ stderr.setFormatter(logging.Formatter(" " * int(options.indent) + '%(levelname)s: %(message)s'))
+ dateFormat = "%H:%M:%S"
+ if options.context:
+ logformatter = logging.Formatter("%(asctime)s %(levelname)s -- " + context + ": %(message)s", dateFormat)
+ else:
+ logformatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s", dateFormat)
+ if not options.quiet: logger.addHandler(stderr)
+ else: logger.addHandler(NullLogHandler()) # prevent default
+ if options.log_file:
+ file = logging.FileHandler(options.log_file)
+ file.setFormatter(logformatter)
+ logger.addHandler(file)
+ if options.log_file_chmod:
+ os.chmod(options.log_file, int(options.log_file_chmod, 8))
+ if options.debug:
+ logger.setLevel(logging.DEBUG)
+ else:
+ stderr.setLevel(logging.WARNING)
+ if options.verbose or hasattr(options, "dry_run"):
+ stderr.setLevel(logging.INFO)
+ if options.log_file:
+ file.setLevel(logging.INFO)
+ logging_setup = True
+ return logger
+
+def makeBaseArgs(options, **grab):
+ """Takes parsed options, and breaks them back into a command
+ line string that we can pass into a subcommand"""
+ args = []
+ grab["log_file"]= "--log-file"
+ grab["debug"] = "--debug"
+ grab["verbose"] = "--verbose"
+ grab["indent"] = "--indent"
+ grab["quiet"] = "--quiet"
+ #grab["log_db"] = "--log-db"
+ for k,flag in grab.items():
+ value = getattr(options, k)
+ if not value and k != "indent": continue
+ args.append(flag)
+ if type(value) is not bool:
+ if k == "indent":
+ value += 4
+ args.append(str(value))
+ args.append("--context") # always have context for a subcommand
+ return args
+
+class NullLogHandler(logging.Handler):
+ """Log handler that doesn't do anything"""
+ def emit(self, record):
+ pass
+
+class WizardOptionParser(optparse.OptionParser):
+ """Configures some default user-level options"""
+ def __init__(self, *args, **kwargs):
+ kwargs["add_help_option"] = False
+ optparse.OptionParser.__init__(self, *args, **kwargs)
+ def parse_all(self, argv):
+ self.add_option("-h", "--help", action="help", help=optparse.SUPPRESS_HELP)
+ group = optparse.OptionGroup(self, "Common Options")
+ group.add_option("-v", "--verbose", dest="verbose", action="store_true",
+ default=False, help="Turns on verbose output")
+ group.add_option("--debug", dest="debug", action="store_true",
+ default=False, help="Turns on debugging output")
+ group.add_option("-q", "--quiet", dest="quiet", action="store_true",
+ default=False, help="Turns off output to stdout")
+ group.add_option("--log-file", dest="log_file",
+ default=None, help="Logs verbose output to file")
+ group.add_option("--log-file-chmod", dest="log_file_chmod",
+ default=None, help="Chmod the log file after opening. Number is octal. You must chmod the log file 666 and place the file in /tmp if subprocesses are running as different users.")
+ group.add_option("--indent", dest="indent",
+ default=0, help="Indents stdout, useful for nested calls")
+ group.add_option("--context", dest="context", action="store_true",
+ default=False, help="Adds context to logs, useful for parallel processing")
+ self.add_option_group(group)
+ options, numeric_args = self.parse_args(argv)
+ makeLogger(options, numeric_args)
+ return options, numeric_args
+
+class OptionBaton(object):
+ """Command classes may define options that they sub-commands may
+ use. Since wizard --global-command subcommand is not a supported
+ mode of operation, these options have to be passed down the command
+ chain until a option parser is ready to take it; this baton is
+ what is passed down."""
+ def __init__(self):
+ self.store = {}
+ def add(self, *args, **kwargs):
+ key = kwargs["dest"] # require this to be set
+ self.store[key] = optparse.make_option(*args, **kwargs)
+ def push(self, option_parser, *args):
+ """Hands off parameters to option parser"""
+ for key in args:
+ option_parser.add_option(self.store[key])