From cb02309cc41fbae69e3ff3efcb3e3feb763189ff Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Tue, 27 Nov 2007 17:16:27 -0500 Subject: Changes to make "cobbler ___ report [___]" and "cobbler ___ list" work like they used to, which means adding a few subcommands, abstracting away the list logic, and writing some minor code to make the trailing names look like --name=x to please optparse. --- cobbler/action_sync.py | 1 + cobbler/commands.py | 105 ++++++++++++++++++++++++++++++++++++----- cobbler/modules/cli_distro.py | 11 +++-- cobbler/modules/cli_misc.py | 69 ++++++--------------------- cobbler/modules/cli_profile.py | 17 ++++--- cobbler/modules/cli_repo.py | 13 +++-- cobbler/modules/cli_system.py | 18 ++++--- 7 files changed, 145 insertions(+), 89 deletions(-) diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py index 00a9d80..ad4143d 100644 --- a/cobbler/action_sync.py +++ b/cobbler/action_sync.py @@ -553,6 +553,7 @@ class BootSync: self.apply_template(kfile, meta, dest) kfile.close() except: + traceback.print_exc() raise CX(_("Error templating file %(src)s to %(dest)s") % { "src" : meta["kickstart"], "dest" : dest }) def load_snippet_cache(self): diff --git a/cobbler/commands.py b/cobbler/commands.py index b2186f1..e34e05a 100644 --- a/cobbler/commands.py +++ b/cobbler/commands.py @@ -44,6 +44,8 @@ class FunctionLoader: Runs a command line sequence through the loader. """ + args = self.old_school_remap(args) + # if no args given, show all loaded fns if len(args) == 1: return self.show_options() @@ -66,6 +68,29 @@ class FunctionLoader: raise CX(_("Invalid arguments")) return fn.run() + def old_school_remap(self,args): + """ + Maps commands like: + # cobbler system report foo to cobbler report --name=foo + to: + # cobblerr system report --name=foo + for backwards compat and usability reasons + """ + if not "report" in args: + return args + ok = False + for x in ["distro","profile","system","repo"]: + if x in args: + ok = True + if not ok: + return args + idx = args.index("report") + if idx + 1 < len(args): + name = args[idx+1] + if name.find("--name") == -1: + args[idx+1] = "--name=%s" % name + return args + def show_options(self): """ Prints out all loaded functions. @@ -153,9 +178,22 @@ class CobblerFunction: """ if "remove" in self.args: + if not self.options.name: + raise CX(_("name is required")) collect_fn().remove(self.options.name,with_delete=True) return None # signal that we want no further processing on the object + if "list" in self.args: + self.list_list(collect_fn()) + return None + + if "report" in self.args: + if self.options.name is None: + self.reporting_print_sorted(collect_fn()) + else: + self.reporting_list_names2(collect_fn(),self.options.name) + return None + if "add" in self.args: obj = new_fn(is_subobject=subobject) else: @@ -190,20 +228,63 @@ class CobblerFunction: return rc + def reporting_sorter(self, a, b): + """ + Used for sorting cobbler objects for report commands + """ + return cmp(a.name, b.name) - #def no_args_handler(self): - # - # """ - # Used to accept/reject/explain subcommands. Do not override. - # """ - # - # subs = self.subcommands() - # if len(subs) == 0: - # return False - # for x in subs: - # print " cobbler %s %s [ARGS|--help]" % (self.command_name(), x) - # return True # stop here + def reporting_print_sorted(self, collection): + """ + Prints all objects in a collection sorted by name + """ + collection = [x for x in collection] + collection.sort(self.reporting_sorter) + for x in collection: + print x.printable() + return True + def reporting_list_names2(self, collection, name): + """ + Prints a specific object in a collection. + """ + obj = collection.find(name=name) + if obj is not None: + print obj.printable() + return True + + def list_tree(self,collection,level): + """ + Print cobbler object tree as a, well, tree. + """ + for item in collection: + print _("%(indent)s%(type)s %(name)s") % { + "indent" : " " * level, + "type" : item.TYPE_NAME, + "name" : item.name + } + kids = item.get_children() + if kids is not None and len(kids) > 0: + self.list_tree(kids,level+1) + + def list_list(self, collection): + """ + List all objects of a certain type. + """ + names = [ x.name for x in collection] + names.sort() # sorted() is 2.4 only + for name in names: + str = _(" %(name)s") % { "name" : name } + print str + return True + def matches_args(self, args, list_of): + """ + Used to simplify some code around which arguments to add when. + """ + for x in args: + if x in list_of: + return True + return False diff --git a/cobbler/modules/cli_distro.py b/cobbler/modules/cli_distro.py index 094961b..3cfa716 100644 --- a/cobbler/modules/cli_distro.py +++ b/cobbler/modules/cli_distro.py @@ -27,24 +27,27 @@ import cexceptions class DistroFunction(commands.CobblerFunction): def help_me(self): - return commands.HELP_FORMAT % ("cobbler distro", " [ARGS|--help]") + return commands.HELP_FORMAT % ("cobbler distro", " [ARGS|--help]") def command_name(self): return "distro" def subcommands(self): - return [ "add", "edit", "copy", "rename", "remove" ] + return [ "add", "edit", "copy", "rename", "remove", "list", "report" ] def add_options(self, p, args): - if not "remove" in args: + + if not self.matches_args(args,["remove","report","list"]): p.add_option("--arch", dest="arch", help="ex: x86, x86_64, ia64") p.add_option("--breed", dest="breed", help="ex: redhat, debian, suse") p.add_option("--initrd", dest="initrd", help="absolute path to initrd.img (REQUIRED)") p.add_option("--kernel", dest="kernel", help="absolute path to vmlinuz (REQUIRED)") p.add_option("--kopts", dest="kopts", help="ex: 'noipv6'") p.add_option("--ksmeta", dest="ksmeta", help="ex: 'blippy=7'") + p.add_option("--name", dest="name", help="ex: 'RHEL-5-i386' (REQUIRED)") - if "copy" in args or "rename" in args: + + if self.matches_args(args,["copy","rename"]): p.add_option("--newname", dest="newname", help="for copy/rename commands") def run(self): diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py index b3f6dfa..cf7adcb 100644 --- a/cobbler/modules/cli_misc.py +++ b/cobbler/modules/cli_misc.py @@ -121,35 +121,16 @@ class ListFunction(commands.CobblerFunction): if self.options.what not in [ "all", "distros", "profiles", "systems", "repos" ]: raise CX(_("invalid value for --what")) if self.options.what in [ "all" ]: - self.__tree(self.api.distros(),0) - self.__tree(self.api.repos(),0) + self.list_tree(self.api.distros(),0) + self.list_tree(self.api.repos(),0) if self.options.what in [ "distros"]: - self.__list(self.api.distros()) + self.list_list(self.api.distros()) if self.options.what in [ "profiles"]: - self.__list(self.api.profiles()) + self.list_list(self.api.profiles()) if self.options.what in [ "systems" ]: - self.__list(self.api.systems()) + self.list_list(self.api.systems()) if self.options.what in [ "repos"]: - self.__list(self.api.repos()) - - def __list(self, collection): - names = [ x.name for x in collection] - names.sort() # sorted() is 2.4 only - for name in names: - str = _(" %(name)s") % { "name" : name } - print str - return True - - def __tree(self,collection,level): - for item in collection: - print _("%(indent)s%(type)s %(name)s") % { - "indent" : " " * level, - "type" : item.TYPE_NAME, - "name" : item.name - } - kids = item.get_children() - if kids is not None and len(kids) > 0: - self.__tree(kids,level+1) + self.list_list(self.api.repos()) ######################################################## @@ -165,55 +146,33 @@ class ReportFunction(commands.CobblerFunction): p.add_option("--what", dest="what", default="all", help="distros/profiles/systems/repos") p.add_option("--name", dest="name", help="report on just this object") - def __list_names2(self, collection, name): - obj = collection.find(name=name) - if obj is not None: - print obj.printable() - return True - - def __sorter(self, a, b): - return cmp(a.name, b.name) - - def __print_sorted(self, collection): - collection = [x for x in collection] - collection.sort(self.__sorter) - for x in collection: - print x.printable() - return True - - def __list_names2(self, collection, name): - obj = collection.find(name=name) - if obj is not None: - print obj.printable() - return True - def run(self): if self.options.what not in [ "all", "distros", "profiles", "systems", "repos" ]: raise CX(_("Invalid value for --what")) if self.options.what in [ "all", "distros" ]: if self.options.name: - self.__list_names2(self.api.distros(),self.options.name) + self.reporting_list_names2(self.api.distros(),self.options.name) else: - self.__print_sorted(self.api.distros()) + self.reporting_print_sorted(self.api.distros()) if self.options.what in [ "all", "profiles" ]: if self.options.name: - self.__list_names2(self.api.profiles(),self.options.name) + self.reporting_list_names2(self.api.profiles(),self.options.name) else: - self.__print_sorted(self.api.profiles()) + self.reporting_print_sorted(self.api.profiles()) if self.options.what in [ "all", "systems" ]: if self.options.name: - self.__list_names2(self.api.systems(),self.options.name) + self.reporting_list_names2(self.api.systems(),self.options.name) else: - self.__print_sorted(self.api.systems()) + self.reporting_print_sorted(self.api.systems()) if self.options.what in [ "all", "repos" ]: if self.options.name: - self.__list_names2(self.api.repos(),self.options.name) + self.reporting_list_names2(self.api.repos(),self.options.name) else: - self.__print_sorted(self.api.repos()) + self.reporting_print_sorted(self.api.repos()) return True ## FIXME: add legacy command translator to keep things simple diff --git a/cobbler/modules/cli_profile.py b/cobbler/modules/cli_profile.py index 63c4270..8189e7c 100644 --- a/cobbler/modules/cli_profile.py +++ b/cobbler/modules/cli_profile.py @@ -27,16 +27,17 @@ import cexceptions class ProfileFunction(commands.CobblerFunction): def help_me(self): - return commands.HELP_FORMAT % ("cobbler profile"," [ARGS|--help]") + return commands.HELP_FORMAT % ("cobbler profile"," [ARGS|--help]") def command_name(self): return "profile" def subcommands(self): - return [ "add", "edit", "copy", "rename", "remove" ] + return [ "add", "edit", "copy", "rename", "remove", "list", "report" ] def add_options(self, p, args): - if not "remove" in args: + if not self.matches_args(args,["remove","report","list"]): + p.add_option("--distro", dest="distro", help="ex: 'RHEL-5-i386' (REQUIRED)") p.add_option("--dhcp-tag", dest="dhcp_tag", help="for use in advanced DHCP configuration") p.add_option("--inherit", dest="inherit", help="inherit from this profile name, defaults to no") @@ -44,9 +45,11 @@ class ProfileFunction(commands.CobblerFunction): p.add_option("--ksmeta", dest="ksmeta", help="ex: 'blippy=7'") p.add_option("--kopts", dest="kopts", help="ex: 'noipv6'") p.add_option("--name", dest="name", help="a name for the profile (REQUIRED)") + if "copy" in args or "rename" in args: p.add_option("--newname", dest="newname") - if not "remove" in args: + + if not self.matches_args(args,["remove","report","list"]): p.add_option("--repos", dest="repos", help="names of cobbler repos") p.add_option("--server-override", dest="server_override", help="overrides value in settings file") p.add_option("--virt-bridge", dest="virt_bridge", help="ex: 'virbr0'") @@ -59,10 +62,10 @@ class ProfileFunction(commands.CobblerFunction): def run(self): - if self.options.inherit: - obj = self.object_manipulator_start(self.api.new_profile,self.api.profiles,subobject=True) + if self.matches_args(self.args,["report","list","remove"]) or not self.options.inherit: + obj = self.object_manipulator_start(self.api.new_profile,self.api.profiles,subobject=False) else: - obj = self.object_manipulator_start(self.api.new_profile,self.api.profiles,subobject=False) + obj = self.object_manipulator_start(self.api.new_profile,self.api.profiles,subobject=True) if obj is None: return True diff --git a/cobbler/modules/cli_repo.py b/cobbler/modules/cli_repo.py index 3dd8f64..f1c61b3 100644 --- a/cobbler/modules/cli_repo.py +++ b/cobbler/modules/cli_repo.py @@ -27,23 +27,28 @@ import cexceptions class RepoFunction(commands.CobblerFunction): def help_me(self): - return commands.HELP_FORMAT % ("cobbler repo"," [ARGS|--help]") + return commands.HELP_FORMAT % ("cobbler repo"," [ARGS|--help]") def command_name(self): return "repo" def subcommands(self): - return [ "add", "edit", "copy", "rename", "remove" ] + return [ "add", "edit", "copy", "rename", "remove", "list", "report" ] def add_options(self, p, args): - if not "remove" in args: + + if not self.matches_args(args,["remove","report","list"]): + p.add_option("--arch", dest="arch", help="overrides repo arch if required") p.add_option("--createrepo-flags", dest="createrepo_flags", help="additional flags for createrepo") p.add_option("--rpm-list", dest="rpm_list", help="just mirror these rpms") p.add_option("--keep-updated", dest="keep_updated", help="update on each reposync, yes/no") p.add_option("--mirror", dest="mirror", help="source to mirror (REQUIRED)") + p.add_option("--name", dest="name", help="ex: 'Fedora-8-updates-i386' (REQUIRED)") - if "copy" in args or "rename" in args: + + if self.matches_args(args,["copy","rename"]): + p.add_option("--newname", dest="newname", help="used for copy/edit") def run(self): diff --git a/cobbler/modules/cli_system.py b/cobbler/modules/cli_system.py index 1e39669..dc7e6bc 100644 --- a/cobbler/modules/cli_system.py +++ b/cobbler/modules/cli_system.py @@ -27,17 +27,17 @@ import cexceptions class SystemFunction(commands.CobblerFunction): def help_me(self): - return commands.HELP_FORMAT % ("cobbler system"," [ARGS|--help]") + return commands.HELP_FORMAT % ("cobbler system"," [ARGS|--help]") def command_name(self): return "system" def subcommands(self): - return [ "add", "edit", "copy", "rename", "remove" ] - + return [ "add", "edit", "copy", "rename", "remove", "report", "list" ] def add_options(self, p, args): - if not "remove" in args: + + if not self.matches_args(args,["remove","report","list"]): p.add_option("--dhcp-tag", dest="dhcp_tag", help="for use in advanced DHCP configurations") p.add_option("--gateway", dest="gateway", help="for static IP / templating usage") p.add_option("--hostname", dest="hostname", help="ex: server.example.org") @@ -46,12 +46,16 @@ class SystemFunction(commands.CobblerFunction): p.add_option("--kopts", dest="kopts", help="ex: 'noipv6'") p.add_option("--ksmeta", dest="ksmeta", help="ex: 'blippy=7'") p.add_option("--mac", dest="mac", help="ex: 'AA:BB:CC:DD:EE:FF', (RECOMMENDED)") + p.add_option("--name", dest="name", help="a name for the system (REQUIRED)") - if not "remove" in args: + + if not self.matches_args(args,["remove","report","list"]): p.add_option("--netboot-enabled", dest="netboot_enabled", help="PXE on (1) or off (0)") - if "copy" in args or "rename" in args: + + if self.matches_args(args,["copy","rename"]): p.add_option("--newname", dest="newname", help="for use with copy/edit") - if not "remove" in args: + + if not self.matches_args(args,["remove","report","list"]): p.add_option("--profile", dest="profile", help="name of cobbler profile (REQUIRED)") p.add_option("--server-override", dest="server_override", help="overrides server value in settings file") p.add_option("--subnet", dest="subnet", help="for static IP / templating usage") -- cgit