summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2007-11-19 17:39:15 -0500
committerMichael DeHaan <mdehaan@redhat.com>2007-11-19 17:39:15 -0500
commit995bf878e03aabd8036498b641253a2c419e3c01 (patch)
tree38301f5c0300f721185b08a398be29a7f93eca85
parent5883ca6b1b8fe371f98db68ac71982affed8b974 (diff)
downloadthird_party-cobbler-995bf878e03aabd8036498b641253a2c419e3c01.tar.gz
third_party-cobbler-995bf878e03aabd8036498b641253a2c419e3c01.tar.xz
third_party-cobbler-995bf878e03aabd8036498b641253a2c419e3c01.zip
Further work on CLI modularization. All commands implemented now, except for old
school compatibility translation for list/report. All commands will then need to be tested...
-rw-r--r--cobbler/action_reposync.py6
-rw-r--r--cobbler/api.py4
-rwxr-xr-xcobbler/cobbler.py14
-rw-r--r--cobbler/commands.py16
-rw-r--r--cobbler/modules/cli_distro.py3
-rw-r--r--cobbler/modules/cli_misc.py291
-rw-r--r--cobbler/modules/cli_profile.py3
-rw-r--r--cobbler/modules/cli_repo.py3
-rw-r--r--cobbler/modules/cli_system.py3
9 files changed, 328 insertions, 15 deletions
diff --git a/cobbler/action_reposync.py b/cobbler/action_reposync.py
index 1cbb6e2..e67317a 100644
--- a/cobbler/action_reposync.py
+++ b/cobbler/action_reposync.py
@@ -49,16 +49,16 @@ class RepoSync:
# ===================================================================
- def run(self, args=[], verbose=True):
+ def run(self, name=None, verbose=True):
"""
Syncs the current repo configuration file with the filesystem.
"""
self.verbose = verbose
for repo in self.repos:
- if args != [] and repo.name not in args:
+ if name is not None and repo.name != name:
continue
- elif args == [] and not repo.keep_updated:
+ elif name is None and not repo.keep_updated:
print _("- %s is set to not be updated") % repo.name
continue
diff --git a/cobbler/api.py b/cobbler/api.py
index cecaa74..1a26385 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -189,13 +189,13 @@ class BootAPI:
sync = action_sync.BootSync(self._config)
return sync.run()
- def reposync(self, args=[]):
+ def reposync(self, name):
"""
Take the contents of /var/lib/cobbler/repos and update them --
or create the initial copy if no contents exist yet.
"""
reposync = action_reposync.RepoSync(self._config)
- return reposync.run(args)
+ return reposync.run(name)
def status(self,mode):
statusifier = action_status.BootStatusReport(self._config, mode)
diff --git a/cobbler/cobbler.py b/cobbler/cobbler.py
index bbfed97..fb9b273 100755
--- a/cobbler/cobbler.py
+++ b/cobbler/cobbler.py
@@ -21,7 +21,7 @@ import os.path
import traceback
import optparse
import commands
-import cexceptions
+from cexceptions import *
from rhpl.translate import _, N_, textdomain, utf8
I18N_DOMAIN = "cobbler"
@@ -52,13 +52,15 @@ def main():
try:
# FIXME: redo locking code?
return BootCLI().run(sys.argv)
- except cexceptions.CX, exc:
- if str(type(exc)).find("CX") != -1:
- print str(exc)[1:-1] # remove framing air quotes
+ except CX, exc:
+ print str(exc)[1:-1] # remove framing air quotes
+ except Exception, exc2:
+ if str(type(exc2)).find("CX") == -1:
+ traceback.print_exc()
else:
- (t, val, tb) = sys.exc_info()
- print tb.extract_tb().join("\n")
+ print str(exc2)[1:-1] # remove framing air quotes
return 1
+ return 1
if __name__ == "__main__":
diff --git a/cobbler/commands.py b/cobbler/commands.py
index 88d92b7..e5eb2de 100644
--- a/cobbler/commands.py
+++ b/cobbler/commands.py
@@ -17,6 +17,8 @@ from cexceptions import *
from rhpl.translate import _, N_, textdomain, utf8
import sys
+HELP_FORMAT = "%-25s%s"
+
#=============================================================
class FunctionLoader:
@@ -69,10 +71,16 @@ class FunctionLoader:
Prints out all loaded functions.
"""
- print "usage:"
- print "======"
- for name in self.functions.keys():
- print "cobbler %s --help]" % name
+ print "commands:"
+ print "========="
+
+ names = self.functions.keys()
+ names.sort()
+
+ for name in names:
+ help = self.functions[name].help_me()
+ if help != "":
+ print help
#=============================================================
diff --git a/cobbler/modules/cli_distro.py b/cobbler/modules/cli_distro.py
index ff08e8c..860df90 100644
--- a/cobbler/modules/cli_distro.py
+++ b/cobbler/modules/cli_distro.py
@@ -26,6 +26,9 @@ import cexceptions
class DistroFunction(commands.CobblerFunction):
+ def help_me(self):
+ return commands.HELP_FORMAT % ("cobbler distro", "<add|edit|copy|rename|delete> [ARGS|--help]")
+
def command_name(self):
return "distro"
diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py
new file mode 100644
index 0000000..eb66fb0
--- /dev/null
+++ b/cobbler/modules/cli_misc.py
@@ -0,0 +1,291 @@
+"""
+Misc CLI functions.
+
+Copyright 2007, Red Hat, Inc
+Michael DeHaan <mdehaan@redhat.com>
+
+This software may be freely redistributed under the terms of the GNU
+general public license.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+"""
+
+import distutils.sysconfig
+import sys
+
+plib = distutils.sysconfig.get_python_lib()
+mod_path="%s/cobbler" % plib
+sys.path.insert(0, mod_path)
+
+from rhpl.translate import _, N_, textdomain, utf8
+import commands
+from cexceptions import *
+HELP_FORMAT = commands.HELP_FORMAT
+
+# TO DO list
+# cobbler check
+# cobbler import (--name, --mirror, --available-as)
+# cobbler reserialize
+# cobbler --type=[profile|system|distro|repo] [--name=list]
+# cobbler --type=[profile|system|distro|profile] [--name=report]
+# cobbler status
+# cobbler reposync --name=$name
+# cobbler sync
+# cobbler validateks
+# elsewhere: repo auto-add
+
+########################################################
+
+class CheckFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler check","")
+
+ def command_name(self):
+ return "check"
+
+ def add_options(self, p, args):
+ pass
+
+ def run(self):
+ status = self.api.check()
+ if len(status) == 0:
+ print _("No setup problems found")
+ print _("Manual review and editing of /var/lib/cobbler/settings is recommended to tailor cobbler to your particular configuration.")
+ print _("Good luck.")
+ return True
+ else:
+ print _("The following potential problems were detected:")
+ for i,x in enumerate(status):
+ print _("#%(number)d: %(problem)s") % { "number" : i, "problem" : x }
+ return False
+
+########################################################
+
+class ImportFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler import","[ARGS|--help]")
+
+ def command_name(self):
+ return "import"
+
+ def add_options(self, p, args):
+ p.add_option("--mirror", dest="mirror", help="local path or rsync location (REQUIRED)")
+ p.add_option("--name", dest="name", help="name, ex 'RHEL-5', (REQUIRED)")
+ p.add_option("--available-as", dest="available_as", help="do not mirror, use this as install tree")
+
+ def run(self):
+ if not self.options.mirror:
+ raise CX(_("mirror is required"))
+ if not self.options.name:
+ raise CX(_("name is required"))
+ return self.api.import_tree(
+ self.options.mirror,
+ self.options.name,
+ network_root=self.options.available_as
+ )
+
+
+########################################################
+
+class ReserializeFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return "" # hide
+
+ def command_name(self):
+ return "reserialize"
+
+ def run(self):
+ return self.api.reserialize()
+
+########################################################
+
+class ListFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler list","[ARGS|--help]")
+
+ def command_name(self):
+ return "list"
+
+ def add_options(self, p, args):
+ p.add_option("--what", dest="what", default="all", help="all/distros/profiles/systems/repos")
+
+ 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" ]:
+ self.__tree(self.api.distros(),0)
+ self.__tree(self.api.repos(),0)
+ if self.options.what in [ "distros"]:
+ self.__list(self.api.distros())
+ if self.options.what in [ "profiles"]:
+ self.__list(self.api.profiles())
+ if self.options.what in [ "systems" ]:
+ self.__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)
+
+########################################################
+
+class ReportFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler report","[ARGS|--help]")
+
+ def command_name(self):
+ return "report"
+
+ def add_options(self, p, args):
+ p.add_option("--what", dest="what", default="all", help="distros/profiles/systems/repos (REQUIRED)")
+ 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)
+ else:
+ self.__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)
+ else:
+ self.__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)
+ else:
+ self.__print_sorted(self.api.sytems())
+
+ if self.options.what in [ "all", "repos" ]:
+ if self.options.name:
+ self.__list_names2(self.api.repos(),self.options.name)
+ else:
+ self.__print_sorted(self.api.repos())
+ return True
+
+## FIXME: add legacy command translator to keep things simple
+## cobbler system report foo --> cobbler report --what=systems --name=foo
+## cobbler system report --> cobbler report --what=systems
+## ditto for "cobbler list"
+
+########################################################
+
+class StatusFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler status","[ARGS|--help]")
+
+ def command_name(self):
+ return "status"
+
+ def run(self):
+ return self.api.status("text") # no other output modes supported yet
+
+########################################################
+
+class SyncFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler sync","")
+
+ def command_name(self):
+ return "sync"
+
+########################################################
+
+class RepoSyncFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler reposync","[ARGS|--help]")
+
+ def command_name(self):
+ return "reposync"
+
+ def add_options(self, p, args):
+ p.add_options("--only", dest="only", help="update only this repository name")
+
+ def run(self):
+ return self.api.reposync(self.options.only)
+
+########################################################
+
+class ValidateKsFunction(commands.CobblerFunction):
+
+ def help_me(self):
+ return HELP_FORMAT % ("cobbler validateks","")
+
+ def command_name(self):
+ return "validateks"
+
+ def run(self):
+ return self.api.validateks()
+
+########################################################
+# MODULE HOOKS
+
+def register():
+ """
+ The mandatory cobbler module registration hook.
+ """
+ return "cli"
+
+def cli_functions(api):
+ return [
+ CheckFunction(api), ImportFunction(api), ReserializeFunction(api),
+ ListFunction(api), ReportFunction(api), StatusFunction(api),
+ SyncFunction(api), RepoSyncFunction(api), ValidateKsFunction(api)
+ ]
+ return []
+
+
diff --git a/cobbler/modules/cli_profile.py b/cobbler/modules/cli_profile.py
index 8385986..a733534 100644
--- a/cobbler/modules/cli_profile.py
+++ b/cobbler/modules/cli_profile.py
@@ -26,6 +26,9 @@ import cexceptions
class ProfileFunction(commands.CobblerFunction):
+ def help_me(self):
+ return commands.HELP_FORMAT % ("cobbler profile","<add|edit|copy|rename|delete> [ARGS|--help]")
+
def command_name(self):
return "profile"
diff --git a/cobbler/modules/cli_repo.py b/cobbler/modules/cli_repo.py
index 09fa234..555b76a 100644
--- a/cobbler/modules/cli_repo.py
+++ b/cobbler/modules/cli_repo.py
@@ -26,6 +26,9 @@ import cexceptions
class RepoFunction(commands.CobblerFunction):
+ def help_me(self):
+ return commands.HELP_FORMAT % ("cobbler repo","<add|edit|copy|rename|delete> [ARGS|--help]")
+
def command_name(self):
return "repo"
diff --git a/cobbler/modules/cli_system.py b/cobbler/modules/cli_system.py
index bfc5c2f..65c0625 100644
--- a/cobbler/modules/cli_system.py
+++ b/cobbler/modules/cli_system.py
@@ -26,6 +26,9 @@ import cexceptions
class SystemFunction(commands.CobblerFunction):
+ def help_me(self):
+ return commands.HELP_FORMAT % ("cobbler system","<add|edit|copy|rename|delete> [ARGS|--help]")
+
def command_name(self):
return "system"