diff options
Diffstat (limited to 'src/lib/Bcfg2/Server/Info.py')
-rw-r--r-- | src/lib/Bcfg2/Server/Info.py | 97 |
1 files changed, 63 insertions, 34 deletions
diff --git a/src/lib/Bcfg2/Server/Info.py b/src/lib/Bcfg2/Server/Info.py index 6af561089..044dcdf0c 100644 --- a/src/lib/Bcfg2/Server/Info.py +++ b/src/lib/Bcfg2/Server/Info.py @@ -1,5 +1,5 @@ -""" Subcommands and helpers for bcfg2-info """ # -*- coding: utf-8 -*- +""" Subcommands and helpers for bcfg2-info """ import os import sys @@ -12,6 +12,7 @@ import fnmatch import argparse import operator import lxml.etree +import traceback from code import InteractiveConsole import Bcfg2.Logger import Bcfg2.Options @@ -142,9 +143,7 @@ class Debug(InfoCmd): if setup.cmd_list: console = InteractiveConsole(locals()) for command in setup.cmd_list.readlines(): - command = command.strip() - if command: - console.push(command) + console.push(command.rstrip()) if not setup.non_interactive: print("Dropping to interpreter; press ^D to resume") self.interpreters[setup.interpreter](self.core.get_locals()) @@ -369,6 +368,7 @@ class Automatch(InfoCmd): class ExpireCache(InfoCmd): """ Expire the metadata cache """ + only_interactive = True options = [ Bcfg2.Options.PositionalArgument( @@ -376,12 +376,20 @@ class ExpireCache(InfoCmd): help="Expire cache for the given host(s)")] def run(self, setup): - if setup.clients: - for client in self.get_client_list(setup.clients): - self.core.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata, - key=client) + if setup.hostname: + for client in self.get_client_list(setup.hostname): + self.core.metadata_cache.expire(client) else: - self.core.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata) + self.core.metadata_cache.expire() + + +class EventDebug(InfoCmd): + """ Enable debugging output for FAM events """ + only_interactive = True + aliases = ['event_debug'] + + def run(self, _): + self.core.fam.set_debug(True) class Bundles(InfoCmd): @@ -672,18 +680,35 @@ class Query(InfoCmd): print("\n".join(res)) +class Quit(InfoCmd): + """ Exit program """ + only_interactive = True + aliases = ['exit', 'EOF'] + + def run(self, _): + raise SystemExit(0) + + class Shell(InfoCmd): """ Open an interactive shell to run multiple bcfg2-info commands """ interactive = False def run(self, setup): try: - self.core.cmdloop('Welcome to bcfg2-info\n' - 'Type "help" for more information') + self.core.cli.cmdloop('Welcome to bcfg2-info\n' + 'Type "help" for more information') except KeyboardInterrupt: print("\nCtrl-C pressed, exiting...") +class Update(InfoCmd): + """ Process pending filesystem events """ + only_interactive = True + + def run(self, _): + self.core.fam.handle_events_in_interval(0.1) + + class ProfileTemplates(InfoCmd): """ Benchmark template rendering times """ @@ -796,36 +821,18 @@ if HAS_PROFILE: display_trace(prof) -class InfoCore(cmd.Cmd, Bcfg2.Server.Core.Core): +class InfoCore(Bcfg2.Server.Core.Core): """Main class for bcfg2-info.""" - def __init__(self): - cmd.Cmd.__init__(self) + def __init__(self, cli): Bcfg2.Server.Core.Core.__init__(self) - self.prompt = 'bcfg2-info> ' + self.cli = cli def get_locals(self): """ Expose the local variables of the core to subcommands that need to reference them (i.e., the interactive interpreter) """ return locals() - def do_quit(self, _): - """ quit|exit - Exit program """ - raise SystemExit(0) - - do_EOF = do_quit - do_exit = do_quit - - def do_eventdebug(self, _): - """ eventdebug - Enable debugging output for FAM events """ - self.fam.set_debug(True) - - do_event_debug = do_eventdebug - - def do_update(self, _): - """ update - Process pending filesystem events """ - self.fam.handle_events_in_interval(0.1) - def run(self): self.load_plugins() self.block_for_fam_events(handle_events=True) @@ -840,12 +847,15 @@ class InfoCore(cmd.Cmd, Bcfg2.Server.Core.Core): Bcfg2.Server.Core.Core.shutdown(self) -class CLI(Bcfg2.Options.CommandRegistry): +class CLI(cmd.Cmd, Bcfg2.Options.CommandRegistry): """ The bcfg2-info CLI """ options = [Bcfg2.Options.BooleanOption("-p", "--profile", help="Profile")] def __init__(self): + cmd.Cmd.__init__(self) Bcfg2.Options.CommandRegistry.__init__(self) + self.prompt = 'bcfg2-info> ' + self.register_commands(globals().values(), parent=InfoCmd) parser = Bcfg2.Options.get_parser( description="Inspect a running Bcfg2 server", @@ -860,7 +870,7 @@ class CLI(Bcfg2.Options.CommandRegistry): else: if Bcfg2.Options.setup.profile: print("Profiling functionality not available.") - self.core = InfoCore() + self.core = InfoCore(self) for command in self.commands.values(): command.core = self.core @@ -877,3 +887,22 @@ class CLI(Bcfg2.Options.CommandRegistry): def shutdown(self): Bcfg2.Options.CommandRegistry.shutdown(self) self.core.shutdown() + + def get_names(self): + """ Overwrite cmd.Cmd.get_names to use the instance to get the + methods and not the class, because the CommandRegistry + dynamically adds methods for the registed subcommands. """ + return dir(self) + + def onecmd(self, line): + """ Overwrite cmd.Cmd.onecmd to catch all exceptions (except + SystemExit) print an error message and continue cmdloop. """ + try: + cmd.Cmd.onecmd(self, line) + except SystemExit: + raise + except: # pylint: disable=W0702 + exc_type, exc_value, exc_traceback = sys.exc_info() + lines = traceback.format_exception(exc_type, exc_value, + exc_traceback) + self.stdout.write(''.join(lines)) |