summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/Server/Admin/Client.py20
-rw-r--r--src/lib/Server/Admin/Compare.py30
-rw-r--r--src/lib/Server/Admin/Fingerprint.py7
-rw-r--r--src/lib/Server/Admin/Init.py25
-rw-r--r--src/lib/Server/Admin/Minestruct.py27
-rw-r--r--src/lib/Server/Admin/Pull.py34
-rw-r--r--src/lib/Server/Admin/Query.py20
-rw-r--r--src/lib/Server/Admin/Tidy.py17
-rw-r--r--src/lib/Server/Admin/Viz.py28
-rw-r--r--src/lib/Server/Admin/__init__.py9
-rwxr-xr-xsrc/sbin/bcfg2-admin12
11 files changed, 157 insertions, 72 deletions
diff --git a/src/lib/Server/Admin/Client.py b/src/lib/Server/Admin/Client.py
index 1f784a4f2..a0b24a71b 100644
--- a/src/lib/Server/Admin/Client.py
+++ b/src/lib/Server/Admin/Client.py
@@ -2,20 +2,22 @@ import Bcfg2.Server.Admin
from Bcfg2.Server.Plugins.Metadata import MetadataConsistencyError
class Client(Bcfg2.Server.Admin.MetadataCore):
- __shorthelp__ = 'bcfg2-admin client add <client> attr1=val1 attr2=val2\nbcfg2-admin client del <client>'
- __longhelp__ = __shorthelp__ + '\n\tCreate or delete client entries'
+ __shorthelp__ = "Create or delete client entries"
+ __longhelp__ = (__shorthelp__ + "\n\nbcfg2-admin client add <client> "
+ "attr1=val1 attr2=val2\n"
+ "bcfg2-admin client del <client>")
+ __usage__ = ("bcfg2-admin client [options] [add|del] [attr=val]")
+
def __init__(self, configfile):
- Bcfg2.Server.Admin.MetadataCore.__init__(self, configfile)
+ Bcfg2.Server.Admin.MetadataCore.__init__(self, configfile,
+ self.__usage__)
def __call__(self, args):
Bcfg2.Server.Admin.MetadataCore.__call__(self, args)
if len(args) == 0:
- self.errExit("Client mode requires at least one argument: <add> or <delete>")
- if "-h" in args:
- print "Usage: "
- print self.__shorthelp__
- raise SystemExit(1)
- if args[0] == 'add':
+ self.errExit("No argument specified.\n"
+ "Please see bcfg2-admin client help for usage.")
+ if args[0] == 'add':
attr_d = {}
for i in args[2:]:
attr, val = i.split('=', 1)
diff --git a/src/lib/Server/Admin/Compare.py b/src/lib/Server/Admin/Compare.py
index 124c0c647..f97233b0e 100644
--- a/src/lib/Server/Admin/Compare.py
+++ b/src/lib/Server/Admin/Compare.py
@@ -1,13 +1,16 @@
-
import lxml.etree, os
import Bcfg2.Server.Admin
class Compare(Bcfg2.Server.Admin.Mode):
- __shorthelp__ = "bcfg2-admin compare <file1> <file2>\nbcfg2-admin compare -r <dir1> <dir2>"
- __longhelp__ = __shorthelp__ + '''\n\tCompare mode determines differences between directories of client specification instances'''
-
- def __init__(self):
- Bcfg2.Server.Admin.Mode.__init__(self)
+ __shorthelp__ = ("Determine differences between files or "
+ "directories of client specification instances")
+ __longhelp__ = (__shorthelp__ + "\n\nbcfg2-admin compare <file1> <file2>"
+ "\nbcfg2-admin compare -r <dir1> <dir2>")
+ __usage__ = ("bcfg2-admin compare <old> <new>\n\n"
+ " -r\trecursive")
+
+ def __init__(self, configfile):
+ Bcfg2.Server.Admin.Mode.__init__(self, configfile)
self.important = {'Package':['name', 'version'],
'Service':['name', 'status'],
'Directory':['name', 'owner', 'group', 'perms'],
@@ -15,15 +18,17 @@ class Compare(Bcfg2.Server.Admin.Mode):
'ConfigFile':['name', 'owner', 'group', 'perms'],
'Permissions':['name', 'perms'],
'PostInstall':['name']}
-
+
def compareStructures(self, new, old):
for child in new.getchildren():
- equiv = old.xpath('%s[@name="%s"]' % (child.tag, child.get('name')))
+ equiv = old.xpath('%s[@name="%s"]' %
+ (child.tag, child.get('name')))
if child.tag in self.important:
print "tag type %s not handled" % (child.tag)
continue
if len(equiv) == 0:
- print "didn't find matching %s %s" % (child.tag, child.get('name'))
+ print ("didn't find matching %s %s" %
+ (child.tag, child.get('name')))
continue
elif len(equiv) >= 1:
if child.tag == 'ConfigFile':
@@ -106,6 +111,9 @@ class Compare(Bcfg2.Server.Admin.Mode):
def __call__(self, args):
Bcfg2.Server.Admin.Mode.__call__(self, args)
+ if len(args) == 0:
+ self.errExit("No argument specified.\n"
+ "Please see bcfg2-admin compare help for usage.")
if '-r' in args:
args = list(args)
args.remove('-r')
@@ -126,6 +134,4 @@ class Compare(Bcfg2.Server.Admin.Mode):
(old, new) = args
except IndexError:
print self.__call__.__doc__
- raise SystemExit
-
-
+ raise SystemExit(1)
diff --git a/src/lib/Server/Admin/Fingerprint.py b/src/lib/Server/Admin/Fingerprint.py
index aff8d42bf..39a180d51 100644
--- a/src/lib/Server/Admin/Fingerprint.py
+++ b/src/lib/Server/Admin/Fingerprint.py
@@ -5,11 +5,12 @@ import Bcfg2.Server.Admin
class Fingerprint(Bcfg2.Server.Admin.Mode):
'''Produce server key fingerprint'''
- __shorthelp__ = 'bcfg2-admin fingerprint'
- __longhelp__ = __shorthelp__ + '\n\tPrint the server certificate fingerprint'
+ __shorthelp__ = "Print the server certificate fingerprint"
+ __longhelp__ = __shorthelp__ + "\n\nbcfg2-admin fingerprint"
+ __usage__ = "bcfg2-admin fingerprint"
def __init__(self, cfile):
- Bcfg2.Server.Admin.Mode.__init__(self, cfile)
+ Bcfg2.Server.Admin.Mode.__init__(self, cfile)
def __call__(self, args):
Bcfg2.Server.Admin.Mode.__call__(self, args)
diff --git a/src/lib/Server/Admin/Init.py b/src/lib/Server/Admin/Init.py
index c97d82133..941ef1596 100644
--- a/src/lib/Server/Admin/Init.py
+++ b/src/lib/Server/Admin/Init.py
@@ -70,8 +70,10 @@ os_list = [
class Init(Bcfg2.Server.Admin.Mode):
- __shorthelp__ = 'bcfg2-admin init'
- __longhelp__ = __shorthelp__ + '\n\tCompare two client specifications or directories of specifications' # FIXME
+ __shorthelp__ = ("Compare two client specifications or "
+ "directories of specifications") # FIXME
+ __longhelp__ = __shorthelp__ + "\n\nbcfg2-admin init"
+ __usage__ = "bcfg2-admin init"
options = {
'configfile': Bcfg2.Options.CFILE,
'gens' : Bcfg2.Options.SERVER_GENERATORS,
@@ -87,11 +89,13 @@ class Init(Bcfg2.Server.Admin.Mode):
opts.parse([])
# FIXME don't overwrite existing bcfg2.conf file
- configfile = raw_input("Store bcfg2 configuration in [%s]: " % opts['configfile'])
+ configfile = raw_input("Store bcfg2 configuration in [%s]: " %
+ opts['configfile'])
if configfile == '':
configfile = opts['configfile']
- repopath = raw_input("Location of bcfg2 repository [%s]: " % opts['repo'])
+ repopath = raw_input("Location of bcfg2 repository [%s]: " %
+ opts['repo'])
if repopath == '':
repopath = opts['repo']
@@ -112,7 +116,8 @@ class Init(Bcfg2.Server.Admin.Mode):
prompt += "%d: %s\n" % (os_list.index(entry) + 1, entry[0])
prompt += ': '
os_sel = os_list[int(raw_input(prompt))-1][1]
- self.initializeRepo(configfile, repopath, server, password, os_sel, opts)
+ self.initializeRepo(configfile, repopath, server,
+ password, os_sel, opts)
print "Repository created successfuly in %s" % (repopath)
def genPassword(self):
@@ -138,11 +143,11 @@ class Init(Bcfg2.Server.Admin.Mode):
except:
# FIXME how to handle
print "Failed to write configuration file to '%s'\n" % configfile
- pass
# FIXME automate ssl key generation
# FIXME key generation may fail as non-root user
- os.popen('openssl req -x509 -nodes -days 1000 -newkey rsa:1024 -out %s/bcfg2.key -keyout %s/bcfg2.key' % (keypath, keypath))
+ os.popen('openssl req -x509 -nodes -days 1000 -newkey rsa:1024 -out' \
+ '%s/bcfg2.key -keyout %s/bcfg2.key' % (keypath, keypath))
try:
os.chmod('%s/bcfg2.key'% keypath, 0600)
except:
@@ -161,5 +166,7 @@ class Init(Bcfg2.Server.Admin.Mode):
except:
continue
- open("%s/Metadata/groups.xml" % repo, "w").write(groups % os_selection)
- open("%s/Metadata/clients.xml" % repo, "w").write(clients % socket.getfqdn())
+ open("%s/Metadata/groups.xml" %
+ repo, "w").write(groups % os_selection)
+ open("%s/Metadata/clients.xml" %
+ repo, "w").write(clients % socket.getfqdn())
diff --git a/src/lib/Server/Admin/Minestruct.py b/src/lib/Server/Admin/Minestruct.py
index 0bf7a5797..cc2a25533 100644
--- a/src/lib/Server/Admin/Minestruct.py
+++ b/src/lib/Server/Admin/Minestruct.py
@@ -4,22 +4,32 @@ import lxml.etree, sys, getopt
class Minestruct(Bcfg2.Server.Admin.StructureMode):
'''Pull extra entries out of statistics'''
- __shorthelp__ = 'bcfg2-admin minestruct [-f file-name] [-g groups] client'
- __longhelp__ = __shorthelp__ + '\n\tExtract extra entry lists from statistics'
+ __shorthelp__ = "Extract extra entry lists from statistics"
+ __longhelp__ = (__shorthelp__ +
+ "\n\nbcfg2-admin minestruct [-f filename] "
+ "[-g groups] client")
+ __usage__ = ("bcfg2-admin minestruct [options] <client>\n\n"
+ " %-25s%s\n"
+ " %-25s%s\n" %
+ ("-f <filename>",
+ "build a particular file",
+ "-g <groups>",
+ "only build config for groups"))
+
+ def __init__(self, configfile):
+ Bcfg2.Server.Admin.MetadataCore.__init__(self, configfile,
+ self.__usage__)
def __call__(self, args):
Bcfg2.Server.Admin.Mode.__call__(self, args)
if len(args) == 0:
- self.errExit("No hostname specified (see bcfg2-admin minestruct -h for help)")
+ self.errExit("No argument specified.\n"
+ "Please see bcfg2-admin minestruct help for usage.")
try:
(opts, args) = getopt.getopt(args, 'f:g:h')
except:
self.log.error(self.__shorthelp__)
raise SystemExit(1)
- if "-h" in args or not args:
- print "Usage:"
- print self.__shorthelp__
- raise SystemExit(1)
client = args[0]
output = sys.stdout
@@ -38,7 +48,8 @@ class Minestruct(Bcfg2.Server.Admin.StructureMode):
try:
extra = self.statistics.GetExtra(client)
except:
- self.log.error("Failed to find extra entry info for client %s" % client)
+ self.log.error("Failed to find extra entry info for client %s" %
+ client)
raise SystemExit(1)
root = lxml.etree.Element("Base")
self.log.info("Found %d extra entries" % (len(extra)))
diff --git a/src/lib/Server/Admin/Pull.py b/src/lib/Server/Admin/Pull.py
index 6591cd604..6695ca715 100644
--- a/src/lib/Server/Admin/Pull.py
+++ b/src/lib/Server/Admin/Pull.py
@@ -1,14 +1,31 @@
-
import binascii, difflib, getopt, lxml.etree, time, ConfigParser
import Bcfg2.Server.Admin
class Pull(Bcfg2.Server.Admin.MetadataCore):
- '''Pull mode retrieves entries from clients and integrates the information into the repository'''
- __shorthelp__ = 'bcfg2-admin pull [-v] [-f] [-I] <client> <entry type> <entry name>'
- __longhelp__ = __shorthelp__ + '\n\tIntegrate configuration information from clients into the server repository'
+ '''
+ Pull mode retrieves entries from clients and
+ integrates the information into the repository
+ '''
+ __shorthelp__ = ("Integrate configuration information "
+ "from clients into the server repository")
+ __longhelp__ = (__shorthelp__ + "\n\nbcfg2-admin pull [-v] [-f][-I]"
+ "<client> <entry type> <entry name>")
+ __usage__ = ("bcfg2-admin pull [options] <client> <entry type> "
+ "<entry name>\n\n"
+ " %-25s%s\n"
+ " %-25s%s\n"
+ " %-25s%s\n" %
+ ("-v",
+ "be verbose",
+ "-f",
+ "force",
+ "-I",
+ "interactive"))
allowed = ['Metadata', 'BB', "DBStats", "Statistics", "Cfg", "SSHbase"]
+
def __init__(self, configfile):
- Bcfg2.Server.Admin.MetadataCore.__init__(self, configfile)
+ Bcfg2.Server.Admin.MetadataCore.__init__(self, configfile,
+ self.__usage__)
self.stats = self.bcore.stats
self.log = False
self.mode = 'interactive'
@@ -19,7 +36,7 @@ class Pull(Bcfg2.Server.Admin.MetadataCore):
opts, gargs = getopt.getopt(args, 'vfI')
except:
print self.__shorthelp__
- raise SystemExit(0)
+ raise SystemExit(1)
for opt in opts:
if opt[0] == '-v':
self.log = True
@@ -37,7 +54,7 @@ class Pull(Bcfg2.Server.Admin.MetadataCore):
self.stats.GetCurrentEntry(client, etype, ename)
except Bcfg2.Server.Plugin.PluginExecutionError:
print "Statistics plugin failure; could not fetch current state"
- raise SystemExit, 1
+ raise SystemExit(1)
data = {'owner':owner, 'group':group, 'perms':perms, 'text':contents}
for k, v in data.iteritems():
@@ -54,7 +71,8 @@ class Pull(Bcfg2.Server.Admin.MetadataCore):
if choices[0].all:
print " => global entry"
elif choices[0].group:
- print " => group entry: %s (prio %d)" % (choices[0].group, choices[0].prio)
+ print (" => group entry: %s (prio %d)" %
+ (choices[0].group, choices[0].prio))
else:
print " => host entry: %s" % (choices[0].hostname)
if raw_input("Use this entry? [yN]: ") in ['y', 'Y']:
diff --git a/src/lib/Server/Admin/Query.py b/src/lib/Server/Admin/Query.py
index 296749cf7..6df7021e5 100644
--- a/src/lib/Server/Admin/Query.py
+++ b/src/lib/Server/Admin/Query.py
@@ -1,8 +1,20 @@
import Bcfg2.Server.Admin, Bcfg2.Logger, logging
class Query(Bcfg2.Server.Admin.Mode):
- __shorthelp__ = 'bcfg2-admin query [-n] [-c] [-f filename] g=group p=profile'
- __longhelp__ = __shorthelp__ + '\n\tQuery clients'
+ __shorthelp__ = "Query clients"
+ __longhelp__ = (__shorthelp__ + "\nbcfg2-admin query [-n] [-c] "
+ "[-f filename] g=group p=profile")
+ __usage__ = ("bcfg2-admin query [options] <g=group> <p=profile>\n\n"
+ " %-25s%s\n"
+ " %-25s%s\n"
+ " %-25s%s\n" %
+ ("-n",
+ "query results delimited with newlines",
+ "-c",
+ "query results delimited with commas",
+ "-f filename",
+ "write query to file"))
+
def __init__(self, cfile):
logging.root.setLevel(100)
Bcfg2.Logger.setup_logging(100, to_console=False, to_syslog=False)
@@ -39,9 +51,9 @@ class Query(Bcfg2.Server.Admin.Mode):
print "Unknown argument %s" % arg
continue
if k == 'p':
- nc = self.meta.GetClientByProfile(v)
+ nc = self.meta.GetClientByProfile(v)
elif k == 'g':
- nc = self.meta.GetClientByGroup(v)
+ nc = self.meta.GetClientByGroup(v)
clients = [c for c in clients if c in nc]
if '-n' in args:
for client in clients:
diff --git a/src/lib/Server/Admin/Tidy.py b/src/lib/Server/Admin/Tidy.py
index 287b34310..b53bde5ef 100644
--- a/src/lib/Server/Admin/Tidy.py
+++ b/src/lib/Server/Admin/Tidy.py
@@ -2,11 +2,19 @@ import Bcfg2.Server.Admin
import re, os, socket
class Tidy(Bcfg2.Server.Admin.Mode):
- __shorthelp__ = 'bcfg2-admin tidy [-f] [-I]'
- __longhelp__ = __shorthelp__ + '\n\tClean up useless files in the repo'
+ __shorthelp__ = "Clean up useless files in the repo"
+ __longhelp__ = __shorthelp__ + "\nbcfg2-admin tidy [-f] [-I]"
+ __usage__ = ("bcfg2-admin tidy [options]\n\n"
+ " %-25s%s\n"
+ " %-25s%s\n"
+ " %-25s%s\n" %
+ ("-f",
+ "force",
+ "-I",
+ "interactive"))
def __init__(self, cfile):
- Bcfg2.Server.Admin.Mode.__init__(self, cfile)
+ Bcfg2.Server.Admin.Mode.__init__(self, cfile)
def __call__(self, args):
Bcfg2.Server.Admin.Mode.__call__(self, args)
@@ -49,7 +57,8 @@ class Tidy(Bcfg2.Server.Admin.Mode):
to_remove.append("%s/SSHbase/%s" % (self.get_repo_path(), name))
else:
if hostmatcher.match(name).group(1) in bad:
- to_remove.append("%s/SSHbase/%s" % (self.get_repo_path(), name))
+ to_remove.append("%s/SSHbase/%s" %
+ (self.get_repo_path(), name))
# clean up file~
# clean up files without parsable names in Cfg
return to_remove
diff --git a/src/lib/Server/Admin/Viz.py b/src/lib/Server/Admin/Viz.py
index 0afb6a121..0a5a8b9d6 100644
--- a/src/lib/Server/Admin/Viz.py
+++ b/src/lib/Server/Admin/Viz.py
@@ -1,17 +1,32 @@
-
-import getopt, popen2, lxml.etree
+import getopt, popen2
import Bcfg2.Server.Admin
class Viz(Bcfg2.Server.Admin.MetadataCore):
- __shorthelp__ = '''bcfg2-admin viz [--includehosts] [--includebundles] [--includekey] [-o output.png] [--raw]'''
- __longhelp__ = __shorthelp__ + '\n\tProduce graphviz diagrams of metadata structures'
+ __shorthelp__ = "Produce graphviz diagrams of metadata structures"
+ __longhelp__ = (__shorthelp__ + "\n\nbcfg2-admin viz [--includehosts] "
+ "[--includebundles] [--includekey] "
+ "[-o output.png] [--raw]")
+ __usage__ = ("bcfg2-admin viz [options]\n\n"
+ " %-25s%s\n"
+ " %-25s%s\n"
+ " %-25s%s\n"
+ " %-25s%s\n" %
+ ("-H, --includehosts",
+ "include hosts in the viz output",
+ "-b, --includebundles",
+ "include bundles in the viz output",
+ "-k, --includekey",
+ "show a key for different digraph shapes",
+ "-o, --outfile <file>",
+ "write viz output to an output file"))
colors = ['steelblue1', 'chartreuse', 'gold', 'magenta',
'indianred1', 'limegreen', 'orange1', 'lightblue2',
'green1', 'blue1', 'yellow1', 'darkturquoise', 'gray66']
def __init__(self, cfile):
- Bcfg2.Server.Admin.MetadataCore.__init__(self, cfile)
+ Bcfg2.Server.Admin.MetadataCore.__init__(self, cfile,
+ self.__usage__)
def __call__(self, args):
Bcfg2.Server.Admin.MetadataCore.__call__(self, args)
@@ -63,7 +78,8 @@ class Viz(Bcfg2.Server.Admin.MetadataCore):
print "write to dot process failed. Is graphviz installed?"
raise SystemExit(1)
dotpipe.tochild.write('\trankdir="LR";\n')
- dotpipe.tochild.write(self.metadata.viz(hosts, bundles, key, self.colors))
+ dotpipe.tochild.write(self.metadata.viz(hosts, bundles,
+ key, self.colors))
if key:
dotpipe.tochild.write("\tsubgraph cluster_key {\n")
dotpipe.tochild.write('''\tstyle="filled";\n''')
diff --git a/src/lib/Server/Admin/__init__.py b/src/lib/Server/Admin/__init__.py
index cd99cb801..ee06a33d0 100644
--- a/src/lib/Server/Admin/__init__.py
+++ b/src/lib/Server/Admin/__init__.py
@@ -40,7 +40,8 @@ class Mode(object):
return self.cfp.get('server', 'repository')
def load_stats(self, client):
- stats = lxml.etree.parse("%s/etc/statistics.xml" % (self.get_repo_path()))
+ stats = lxml.etree.parse("%s/etc/statistics.xml" %
+ (self.get_repo_path()))
hostent = stats.xpath('//Node[@name="%s"]' % client)
if not hostent:
self.errExit("Could not find stats for client %s" % (client))
@@ -49,12 +50,13 @@ class Mode(object):
class MetadataCore(Mode):
allowed = ['Metadata', 'BB']
'''Base class for admin-modes that handle metadata'''
- def __init__(self, configfile):
+ def __init__(self, configfile, usage):
Mode.__init__(self, configfile)
options = {'plugins': Bcfg2.Options.SERVER_PLUGINS,
'structures': Bcfg2.Options.SERVER_STRUCTURES,
'generators': Bcfg2.Options.SERVER_GENERATORS}
setup = Bcfg2.Options.OptionParser(options)
+ setup.hm = usage
setup.parse(sys.argv[1:])
plugins = [plugin for plugin in setup['plugins']
if plugin in self.allowed]
@@ -64,7 +66,8 @@ class MetadataCore(Mode):
if generator in self.allowed]
try:
self.bcore = Bcfg2.Server.Core.Core(self.get_repo_path(), plugins,
- structures, generators, 'foo', False, 'UTF-8')
+ structures, generators,
+ 'foo', False, 'UTF-8')
except Bcfg2.Server.Core.CoreInitError, msg:
self.errExit("Core load failed because %s" % msg)
[self.bcore.fam.Service() for _ in range(5)]
diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin
index 2a1fc233d..bf7296517 100755
--- a/src/sbin/bcfg2-admin
+++ b/src/sbin/bcfg2-admin
@@ -26,23 +26,23 @@ if __name__ == '__main__':
raise SystemExit(1)
- do_help = False
# First get the options...
for opt, arg in opts:
- if opt in ("-h", "--help"):
- do_help = True
if opt in ("-C", "--configfile"):
configfile = arg
modes = [x.lower() for x in Bcfg2.Server.Admin.__all__]
modes.remove('mode')
- if do_help or len(args) < 1 or args[0] == 'help':
+ if len(args) < 1 or args[0] == 'help':
+ sys.stdout.write("Usage: bcfg2-admin MODE [ARGS]\n\n"
+ "Available modes are:")
if len(args) > 1:
args = [args[1], args[0]]
else:
- for mod in [mode_import(mode) for mode in modes]:
- print mod.__shorthelp__
+ for mode in modes:
+ sys.stdout.write("\n %-12s %s" %
+ (mode, mode_import(mode).__shorthelp__))
raise SystemExit(0)
if args[0] in modes:
modname = args[0].capitalize()