def command_manager(self): """ Return instance of ``CommandManager``. It's initialized when first needed. :rtype: (``CommandManager``) """ if self._command_manager is None: self._command_manager = CommandManager() self._command_manager.add_command('help', Help) return self._command_manager
class MetaCommand(object): """ Main application class. It instantiates configuration object, logging and then it passes control to commands. Example usage: MetaCommand().run() """ def __init__(self): # allow exceptions in lmi shell LMIUtil.lmi_set_use_exceptions(True) # instance of CommandManager, created when first needed self._command_manager = None self.stdout = sys.stdout self.stderr = sys.stderr self.stdin = sys.stdin # instance of Session, created when needed self._session = None # instance of Configuration, created in setup() self.config = None # dictionary of not yet processed options, it's created in setup() self._options = None self._active_command = None def _configure_logging(self): """ Setup logging. It expects Configuration object to be already initialized. Logging can be tuned in various ways: * In configuration file with options: * [Main] Verbosity * [Log] OutputFile * [Log] FileFormat * [Log] ConsoleFormat * [Log] ConsoleInfoFormat * [Log] LogToConsole * With command line options: ``-v`` flags : Each such flag increases logging level of what is logged into console. This overrides `[Main] Verbosity` option. ``-q`` : Causes supression of any output made to stdout except for error messages. This overrides ``[Main] Verbosity``. option and ``-v`` flags. ``--log-file`` : Output file for logging messages. This overrides ``[Log] OutputFile`` option. Implicitly only warnings and errors are logged to the standard error stream without any tracebacks. """ util.setup_logging(self.config, self.stderr) @property def command_manager(self): """ Return instance of ``CommandManager``. It's initialized when first needed. :rtype: (``CommandManager``) """ if self._command_manager is None: self._command_manager = CommandManager() self._command_manager.add_command('help', Help) return self._command_manager @property def session(self): """ Return instance of Session. Instantiated when first needed. :rtype: (``Session``) """ if self._session is None: if ( not self._options['--host'] and not self._options['--hosts-file']): self._options['--host'] = [util.get_default_hostname()] LOG().info('No hosts given, using "%s".', self._options['--host'][0]) hostnames = [] # credentials loaded from file credentials = {} def add_hosts(hosts, creds): """ Update hostnames and credentials for new data. """ hostnames.extend(hosts) credentials.update(creds) if self._options['--hosts-file']: hosts_path = self._options['--hosts-file'] try: with open(hosts_path, 'r') as hosts_file: add_hosts(*util.parse_hosts_file(hosts_file)) except (OSError, IOError) as err: LOG().critical('Could not read hosts file "%s": %s', hosts_path, err) sys.exit(1) add_hosts(*util.get_hosts_credentials(self._options['--host'])) if self._options['--user']: credentials.update( # credentials in file has precedence over --user option dict((h, credentials.get(h, (self._options['--user'], ''))) for h in hostnames if h not in credentials )) self._session = Session(self, hostnames, credentials, same_credentials=self._options['--same-credentials']) return self._session @property def active_command(self): return self._active_command @active_command.setter def active_command(self, cmd): if not isinstance(cmd, LmiBaseCommand): raise TypeError("cmd must be an instance of LmiBaseCommand") self._active_command = cmd def print_version(self): """ Print version of this egg to stdout. """ self.stdout.write("%s\n" % util.get_version()) def setup(self, options): """ Initialise global Configuration object and set up logging. :param options: (``dict``) Dictionary of options parsed from command line by docopt. """ conf_kwargs = {} if options['--config-file']: conf_kwargs['user_config_file_path'] = options.pop('--config-file') self.config = Configuration.get_instance(**conf_kwargs) # two mutually exclusive options if options['--trace'] or options['--notrace']: self.config.trace = bool(options['--trace']) if options.pop('--quiet', False): self.config.verbosity = Configuration.OUTPUT_SILENT elif options['-v'] and options['-v'] > 0: self.config.verbosity = options['-v'] if options.pop('--noverify', False): self.config.verify_server_cert = False self.config.log_file = options.pop('--log-file', None) self._configure_logging() del options['--trace'] del options['--notrace'] del options['-v'] self.config.namespace = options.pop('--namespace', None) self.config.human_friendly = options.pop('--human-friendly', None) self.config.no_headings = options.pop('--no-headings', None) self.config.lister_format = options.pop('--lister-format', None) # unhandled options may be used later (for session creation), # so let's save them self._options = options def run(self, argv): """ Equivalent to the main program for the application. :param argv: (``list``) Input arguments and options. Contains all arguments but the application name. """ retval = exit.EXIT_CODE_FAILURE cmd = TopLevelCommand(self) try: retval = cmd.run(argv) except Exception as exc: if isinstance(exc, errors.LmiUnsatisfiedDependencies): retval = exit.EXIT_CODE_UNSATISFIED_DEPENDENCIES LOG().exception(str(exc)) if isinstance(retval, bool) or not isinstance(retval, (int, long)): return ( exit.EXIT_CODE_SUCCESS if bool(retval) or retval is None else exit.EXIT_CODE_FAILURE) return retval
class MetaCommand(object): """ Main application class. It instantiates configuration object, logging and then it passes control to commands. Example usage: MetaCommand().run() """ def __init__(self): # allow exceptions in lmi shell LMIUtil.lmi_set_use_exceptions(True) # instance of CommandManager, created when first needed self._command_manager = None self.stdout = sys.stdout self.stderr = sys.stderr self.stdin = sys.stdin # instance of Session, created when needed self._session = None # instance of Configuration, created in setup() self.config = None # dictionary of not yet processed options, it's created in setup() self._options = None def _configure_logging(self): """ Setup logging. It expects Configuration object to be already initialized. Logging can be tuned in various ways: * In configuration file with options: * [Log] OutputFile * [Log] FileFormat * [Log] ConsoleFormat * With command line options: * -v flags - each such flag increases logging level of what is logged into console * -q - supress any output made to stdout * --trace - whether exception tracebacks are shown Implicitly only warnings and errors are logged to the standard error stream without any tracebacks. """ util.setup_logging(self.config, self.stderr) if self.config.silent: self.stdout = NullFile() @property def command_manager(self): """ Return instance of ``CommandManager``. It's initialized when first needed. :rtype: (``CommandManager``) """ if self._command_manager is None: self._command_manager = CommandManager() self._command_manager.add_command('help', Help) return self._command_manager @property def session(self): """ Return instance of Session. Instantiated when first needed. :rtype: (``Session``) """ if self._session is None: if ( not self._options['--host'] and not self._options['--hosts-file']): LOG().critical( "missing one of (--host | --hosts-file) arguments") sys.exit(1) hostnames = [] # credentials loaded from file credentials = {} def add_hosts(hosts, creds): """ Update hostnames and credentials for new data. """ hostnames.extend(hosts) credentials.update(creds) if self._options['--hosts-file']: hosts_path = self._options['--hosts-file'] try: with open(hosts_path, 'r') as hosts_file: add_hosts(*util.parse_hosts_file(hosts_file)) except (OSError, IOError) as err: LOG().critical('could not read hosts file "%s": %s', hosts_path, err) sys.exit(1) add_hosts(*util.get_hosts_credentials(self._options['--host'])) if self._options['--user']: credentials.update({ # credentials in file has precedence over --user option h : credentials.get(h, (self._options['--user'], '')) for h in hostnames if h not in credentials }) self._session = Session(self, hostnames, credentials, same_credentials=self._options['--same-credentials']) return self._session def print_version(self): """ Print version of this egg to stdout. """ self.stdout.write("%s\n" % util.get_version()) def setup(self, options): """ Initialise global Configuration object and set up logging. :param options: (``dict``) Dictionary of options parsed from command line by docopt. """ conf_kwargs = {} if options['--config-file']: conf_kwargs['user_config_file_path'] = options.pop('--config-file') self.config = Configuration.get_instance(**conf_kwargs) self.config.trace = options.pop('--trace', False) if options['--quiet']: self.config.verbosity = Configuration.OUTPUT_SILENT elif options['-v'] and options['-v'] > 0: self.config.verbosity = options['-v'] if options['--noverify']: self.config.verify_server_cert = False self._configure_logging() del options['--quiet'] del options['-v'] del options['--noverify'] self.config.namespace = options.pop('--namespace', None) self.config.human_friendly = options.pop('--human-friendly', None) self.config.no_headings = options.pop('--no-headings', None) self.config.lister_format = options.pop('--lister-format', None) # unhandled options may be used later (for session creation), # so let's save them self._options = options def run(self, argv): """ Equivalent to the main program for the application. :param argv: (``list``) Input arguments and options. Contains all arguments but the application name. """ cmd = TopLevelCommand(self) try: return cmd.run(argv) except Exception as exc: trace = True if self.config is None else self.config.trace if isinstance(exc, errors.LmiError) or not trace: LOG().error(exc) else: LOG().exception("fatal") return 1