summaryrefslogtreecommitdiffstats
path: root/src/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbin')
-rwxr-xr-xsrc/sbin/bcfg27
-rwxr-xr-xsrc/sbin/bcfg2-admin4
-rwxr-xr-xsrc/sbin/bcfg2-build-reports306
-rwxr-xr-xsrc/sbin/bcfg2-crypt48
-rwxr-xr-xsrc/sbin/bcfg2-info190
-rwxr-xr-xsrc/sbin/bcfg2-lint40
l---------src/sbin/bcfg2-repo-validate1
-rwxr-xr-xsrc/sbin/bcfg2-report-collector4
-rwxr-xr-xsrc/sbin/bcfg2-server2
-rwxr-xr-xsrc/sbin/bcfg2-test3
10 files changed, 147 insertions, 458 deletions
diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2
index 444e86a7c..62f749b80 100755
--- a/src/sbin/bcfg2
+++ b/src/sbin/bcfg2
@@ -3,8 +3,8 @@
import sys
import signal
-import Bcfg2.Options
from Bcfg2.Client.Client import Client
+from Bcfg2.Options import load_option_parser, CLIENT_COMMON_OPTIONS
def cb_sigint_handler(signum, frame):
@@ -13,8 +13,7 @@ def cb_sigint_handler(signum, frame):
def main():
- optinfo = Bcfg2.Options.CLIENT_COMMON_OPTIONS
- setup = Bcfg2.Options.OptionParser(optinfo)
+ setup = load_option_parser(CLIENT_COMMON_OPTIONS)
setup.parse(sys.argv[1:])
if setup['args']:
@@ -23,7 +22,7 @@ def main():
raise SystemExit(1)
signal.signal(signal.SIGINT, cb_sigint_handler)
- return Client(setup).run()
+ return Client().run()
if __name__ == '__main__':
sys.exit(main())
diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin
index 14d188342..0e1e34c60 100755
--- a/src/sbin/bcfg2-admin
+++ b/src/sbin/bcfg2-admin
@@ -42,7 +42,7 @@ def main():
optinfo = dict()
optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS)
optinfo.update(Bcfg2.Options.SERVER_COMMON_OPTIONS)
- setup = Bcfg2.Options.OptionParser(optinfo)
+ setup = Bcfg2.Options.load_option_parser(optinfo)
# override default help message to include description of all modes
setup.hm = "Usage:\n\n%s\n%s" % (setup.buildHelpMessage(),
create_description())
@@ -81,7 +81,7 @@ def main():
err = sys.exc_info()[1]
log.error("Failed to load admin mode %s: %s" % (modname, err))
raise SystemExit(1)
- mode = mode_cls(setup)
+ mode = mode_cls()
try:
return mode(setup['args'][1:])
finally:
diff --git a/src/sbin/bcfg2-build-reports b/src/sbin/bcfg2-build-reports
deleted file mode 100755
index 1c9e9ad97..000000000
--- a/src/sbin/bcfg2-build-reports
+++ /dev/null
@@ -1,306 +0,0 @@
-#!/usr/bin/env python
-
-"""
-bcfg2-build-reports generates & distributes reports of statistic
-information for Bcfg2."""
-
-import copy
-import getopt
-import re
-import os
-import socket
-import sys
-from time import asctime, strptime
-from lxml.etree import XML, XSLT, parse, Element, ElementTree, SubElement, tostring, XMLSyntaxError
-# Compatibility imports
-from Bcfg2.Compat import ConfigParser, cmp
-
-def generatereport(rspec, nrpt):
- """
- generatereport creates and returns an ElementTree representation
- of a report adhering to the XML spec for intermediate reports.
- """
- reportspec = copy.deepcopy(rspec)
- nodereprt = copy.deepcopy(nrpt)
-
- reportgood = reportspec.get("good", default = 'Y')
- reportmodified = reportspec.get("modified", default = 'Y')
- current_date = asctime()[:10]
-
- """Build regex of all the nodes we are reporting about."""
- pattern = re.compile( '|'.join([item.get("name") for item in reportspec.findall('Machine')]))
-
- for node in nodereprt.findall('Node'):
- if not (node.findall("Statistics") and pattern.match(node.get('name'))):
- # Don't know enough about node.
- nodereprt.remove(node)
- continue
-
- # Reduce to most recent Statistics entry.
- statisticslist = node.findall('Statistics')
- # This line actually sorts from most recent to oldest.
- statisticslist.sort(lambda y, x: cmp(strptime(x.get("time")), strptime(y.get("time"))))
- stats = statisticslist[0]
-
- [node.remove(item) for item in node.findall('Statistics')]
-
- # Add a good tag if node is good and we wnat to report such.
- if reportgood == 'Y' and stats.get('state') == 'clean':
- SubElement(stats,"Good")
-
- [stats.remove(item) for item in stats.findall("Bad") + stats.findall("Modified") if \
- item.getchildren() == []]
- [stats.remove(item) for item in stats.findall("Modified") if reportmodified == 'N']
-
- # Test for staleness -if stale add Stale tag.
- if stats.get("time").find(current_date) == -1:
- SubElement(stats,"Stale")
- node.append(stats)
- return nodereprt
-
-def mail(mailbody, confi):
- """mail mails a previously generated report."""
-
- try:
- mailer = confi.get('statistics', 'sendmailpath')
- except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
- mailer = "/usr/sbin/sendmail"
- # Open a pipe to the mail program and
- # write the data to the pipe.
- pipe = os.popen("%s -t" % mailer, 'w')
- pipe.write(mailbody)
- exitcode = pipe.close()
- if exitcode:
- print("Exit code: %s" % exitcode)
-
-def rss(reportxml, delivery, report):
- """rss appends a new report to the specified rss file
- keeping the last 9 articles.
- """
- # Check and see if rss file exists.
- for destination in delivery.findall('Destination'):
- try:
- fil = open(destination.attrib['address'], 'r')
- olddoc = XML(fil.read())
-
- # Defines the number of recent articles to keep.
- items = olddoc.find("channel").findall("item")[0:9]
- fil.close()
- fil = open(destination.attrib['address'], 'w')
- except (IOError, XMLSyntaxError):
- fil = open(destination.attrib['address'], 'w')
- items = []
-
- rssdata = Element("rss")
- channel = SubElement(rssdata, "channel")
- rssdata.set("version", "2.0")
- chantitle = SubElement(channel, "title")
- chantitle.text = report.attrib['name']
- chanlink = SubElement(channel, "link")
-
- # This can later link to WWW report if one gets published
- # simultaneously?
- chanlink.text = "http://www.mcs.anl.gov/cobalt/bcfg2"
- chandesc = SubElement(channel, "description")
- chandesc.text = "Information regarding the 10 most recent bcfg2 runs."
-
- channel.append(XML(reportxml))
-
- if items != []:
- for item in items:
- channel.append(item)
-
- tree = tostring(rssdata, xml_declaration=False).decode('UTF-8')
- fil.write(tree)
- fil.close()
-
-def www(reportxml, delivery):
- """www outputs report to."""
-
- # This can later link to WWW report if one gets published
- # simultaneously?
- for destination in delivery.findall('Destination'):
- fil = open(destination.attrib['address'], 'w')
-
- fil.write(reportxml)
- fil.close()
-
-def fileout(reportxml, delivery):
- """Outputs to plain text file."""
- for destination in delivery.findall('Destination'):
- fil = open(destination.attrib['address'], 'w')
-
- fil.write(reportxml)
- fil.close()
-
-def pretty_print(element, level=0):
- """Produce a pretty-printed text representation of element."""
- if element.text:
- fmt = "%s<%%s %%s>%%s</%%s>" % (level*" ")
- data = (element.tag, (" ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())])),
- element.text, element.tag)
- if element._children:
- fmt = "%s<%%s %%s>\n" % (level*" ",) + (len(element._children) * "%s") + "%s</%%s>\n" % (level*" ")
- data = (element.tag, ) + (" ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())]),)
- data += tuple([pretty_print(entry, level+2) for entry in element._children]) + (element.tag, )
- else:
- fmt = "%s<%%s %%s/>\n" % (level * " ")
- data = (element.tag, " ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())]))
- return fmt % data
-
-
-if __name__ == '__main__':
- all=False
- if '-C' in sys.argv:
- cfpath = sys.argv[sys.argv.index('-C') + 1]
- else:
- cfpath = '/etc/bcfg2.conf'
- c = ConfigParser.ConfigParser()
- c.read([cfpath])
- configpath = "%s/etc/report-configuration.xml" % c.get('server', 'repository')
- statpath = "%s/etc/statistics.xml" % c.get('server', 'repository')
- clientsdatapath = "%s/Metadata/clients.xml" % c.get('server', 'repository')
- try:
- prefix = c.get('server', 'prefix')
- except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
- prefix = '/usr'
-
- transformpath = "/%s/share/bcfg2/xsl-transforms/" % (prefix)
- #websrcspath = "/usr/share/bcfg2/web-rprt-srcs/"
-
- try:
- opts, args = getopt.getopt(sys.argv[1:], "C:hAc:Ns:", ["help", "all", "config=", "stats="])
- except getopt.GetoptError:
- mesg = sys.exc_info()[1]
- # Print help information and exit:
- print("%s\nUsage:\nbcfg2-build-reports [-h][-A (include ALL clients)] [-c <configuration-file>] [-s <statistics-file>]" % (mesg))
- raise SystemExit(2)
- for o, a in opts:
- if o in ("-h", "--help"):
- print("Usage:\nbcfg2-build-reports [-h] [-c <configuration-file>] [-s <statistics-file>]")
- raise SystemExit
- if o in ("-A", "--all"):
- all=True
- if o in ("-c", "--config"):
- configpath = a
- if o in ("-s", "--stats"):
- statpath = a
-
-
- """Reads data & config files."""
- try:
- statsdata = XML(open(statpath).read())
- except (IOError, XMLSyntaxError):
- print("bcfg2-build-reports: Failed to parse %s"%(statpath))
- raise SystemExit(1)
- try:
- configdata = XML(open(configpath).read())
- except (IOError, XMLSyntaxError):
- print("bcfg2-build-reports: Failed to parse %s"%(configpath))
- raise SystemExit(1)
- try:
- clientsdata = XML(open(clientsdatapath).read())
- except (IOError, XMLSyntaxError):
- print("bcfg2-build-reports: Failed to parse %s"%(clientsdatapath))
- raise SystemExit(1)
-
- # Merge data from three sources.
- nodereport = Element("Report", attrib={"time" : asctime()})
- # Should all of the other info in Metadata be appended?
- # What about all of the package stuff for other types of reports?
- for client in clientsdata.findall("Client"):
- nodel = Element("Node", attrib={"name" : client.get("name")})
- nodel.append(client)
- for nod in statsdata.findall("Node"):
- if client.get('name').find(nod.get('name')) == 0:
- for statel in nod.findall("Statistics"):
- nodel.append(statel)
- nodereport.append(nodel)
-
- if all:
- for nod in statsdata.findall("Node"):
- for client in clientsdata.findall("Client"):
- if client.get('name').find(nod.get('name')) == 0:
- break
- else:
- nodel = Element("Node", attrib={"name" : nod.get("name")})
- client = Element("Client", attrib={"name" : nod.get("name"), "profile" : "default"})
- nodel.append(client)
- for statel in nod.findall("Statistics"):
- nodel.append(statel)
- nodereport.append(nodel)
-
-
- for reprt in configdata.findall('Report'):
- nodereport.set("name", reprt.get("name", default="BCFG Report"))
-
- if reprt.get('refresh-time') != None:
- nodereport.set("refresh-time", reprt.get("refresh-time", default="600"))
-
- procnodereport = generatereport(reprt, nodereport)
-
- for deliv in reprt.findall('Delivery'):
- # Is a deepcopy of procnodereport necessary?
-
- delivtype = deliv.get('type', default='nodes-digest')
- deliverymechanism = deliv.get('mechanism', default='www')
-
- # Apply XSLT, different ones based on report type, and options
- if deliverymechanism == 'null-operator': # Special Cases
- fileout(tostring(ElementTree(procnodereport).getroot(), xml_declaration=False).decode('UTF-8'), deliv)
- break
- transform = delivtype + '-' + deliverymechanism + '.xsl'
-
- try: # Make sure valid stylesheet is selected.
- os.stat(transformpath + transform)
- except:
- print("bcfg2-build-reports: Invalid report type or delivery mechanism.\n Can't find: "\
- + transformpath + transform)
- raise SystemExit(1)
-
- try: # Try to parse stylesheet.
- stylesheet = XSLT(parse(transformpath + transform))
- except:
- print("bcfg2-build-reports: invalid XSLT transform file.")
- raise SystemExit(1)
-
- if deliverymechanism == 'mail':
- if delivtype == 'nodes-individual':
- reportdata = copy.deepcopy(procnodereport)
- for noden in reportdata.findall("Node"):
- [reportdata.remove(y) for y in reportdata.findall("Node")]
- reportdata.append(noden)
- result = stylesheet.apply(ElementTree(reportdata))
- outputstring = stylesheet.tostring(result)
-
- if not outputstring == None:
- toastring = ''
- for desti in deliv.findall("Destination"):
- toastring = "%s%s " % \
- (toastring, desti.get('address'))
- # Prepend To: and From:
- outputstring = "To: %s\nFrom: root@%s\n%s"% \
- (toastring, socket.getfqdn(), outputstring)
- mail(outputstring, c) #call function to send
-
- else:
- reportdata = copy.deepcopy(procnodereport)
-
- result = stylesheet.apply(ElementTree(reportdata))
- outputstring = stylesheet.tostring(result)
-
- if not outputstring == None:
- toastring = ''
- for desti in deliv.findall("Destination"):
- toastring = "%s%s " % \
- (toastring, desti.get('address'))
- # Prepend To: and From:
- outputstring = "To: %s\nFrom: root@%s\n%s"% \
- (toastring, socket.getfqdn(), outputstring)
- mail(outputstring, c) #call function to send
- else:
- outputstring = tostring(stylesheet.apply(ElementTree(procnodereport)).getroot(), xml_declaration=False).decode('UTF-8')
- if deliverymechanism == 'rss':
- rss(outputstring, deliv, reprt)
- else: # Must be deliverymechanism == 'www':
- www(outputstring, deliv)
diff --git a/src/sbin/bcfg2-crypt b/src/sbin/bcfg2-crypt
index 0ba84fa0a..9190f1390 100755
--- a/src/sbin/bcfg2-crypt
+++ b/src/sbin/bcfg2-crypt
@@ -12,7 +12,7 @@ import Bcfg2.Options
from Bcfg2.Server import XMLParser
from Bcfg2.Compat import input # pylint: disable=W0622
try:
- import Bcfg2.Encryption
+ import Bcfg2.Server.Encryption
except ImportError:
print("Could not import %s. Is M2Crypto installed?" % sys.exc_info()[1])
raise SystemExit(1)
@@ -28,7 +28,7 @@ class CryptoTool(object):
def __init__(self, filename, setup):
self.setup = setup
self.logger = logging.getLogger(self.__class__.__name__)
- self.passphrases = Bcfg2.Encryption.get_passphrases(self.setup)
+ self.passphrases = Bcfg2.Server.Encryption.get_passphrases(self.setup)
self.filename = filename
try:
@@ -43,8 +43,9 @@ class CryptoTool(object):
def _get_passphrase(self):
""" get the passphrase for the current file """
- if (not self.setup.cfp.has_section(Bcfg2.Encryption.CFG_SECTION) or
- len(Bcfg2.Encryption.get_passphrases(self.setup)) == 0):
+ if (not self.setup.cfp.has_section(
+ Bcfg2.Server.Encryption.CFG_SECTION) or
+ len(Bcfg2.Server.Encryption.get_passphrases(self.setup)) == 0):
raise PassphraseError("No passphrases available in %s" %
self.setup['configfile'])
@@ -53,10 +54,10 @@ class CryptoTool(object):
pname = self.setup['passphrase']
if pname:
- if self.setup.cfp.has_option(Bcfg2.Encryption.CFG_SECTION,
+ if self.setup.cfp.has_option(Bcfg2.Server.Encryption.CFG_SECTION,
pname):
- passphrase = self.setup.cfp.get(Bcfg2.Encryption.CFG_SECTION,
- pname)
+ passphrase = self.setup.cfp.get(
+ Bcfg2.Server.Encryption.CFG_SECTION, pname)
self.logger.debug("Using passphrase %s specified on command "
"line" % pname)
return (pname, passphrase)
@@ -64,7 +65,7 @@ class CryptoTool(object):
raise PassphraseError("Could not find passphrase %s in %s" %
(pname, self.setup['configfile']))
else:
- pnames = Bcfg2.Encryption.get_passphrases(self.setup)
+ pnames = Bcfg2.Server.Encryption.get_passphrases()
if len(pnames) == 1:
pname = pnames.keys()[0]
passphrase = pnames[pname]
@@ -123,9 +124,9 @@ class CfgEncryptor(Encryptor):
self.setup['configfile'])
def encrypt(self):
- return Bcfg2.Encryption.ssl_encrypt(
+ return Bcfg2.Server.Encryption.ssl_encrypt(
self.data, self.passphrase,
- Bcfg2.Encryption.get_algorithm(self.setup))
+ Bcfg2.Server.Encryption.get_algorithm(self.setup))
def get_destination_filename(self, original_filename):
return original_filename + ".crypt"
@@ -138,10 +139,10 @@ class CfgDecryptor(Decryptor):
""" decrypt the given file, returning the plaintext data """
if self.passphrase:
try:
- return Bcfg2.Encryption.ssl_decrypt(
+ return Bcfg2.Server.Encryption.ssl_decrypt(
self.data, self.passphrase,
- Bcfg2.Encryption.get_algorithm(self.setup))
- except Bcfg2.Encryption.EVPError:
+ Bcfg2.Server.Encryption.get_algorithm(self.setup))
+ except Bcfg2.Server.Encryption.EVPError:
self.logger.info("Could not decrypt %s with the "
"specified passphrase" % self.filename)
return False
@@ -152,10 +153,11 @@ class CfgDecryptor(Decryptor):
return False
else: # no passphrase given, brute force
try:
- return Bcfg2.Encryption.bruteforce_decrypt(
+ return Bcfg2.Server.Encryption.bruteforce_decrypt(
self.data, passphrases=self.passphrases.values(),
- algorithm=Bcfg2.Encryption.get_algorithm(self.setup))
- except Bcfg2.Encryption.EVPError:
+ algorithm=Bcfg2.Server.Encryption.get_algorithm(
+ self.setup))
+ except Bcfg2.Server.Encryption.EVPError:
self.logger.info("Could not decrypt %s with any passphrase" %
self.filename)
return False
@@ -245,9 +247,9 @@ class PropertiesEncryptor(Encryptor, PropertiesCryptoMixin):
except PassphraseError:
self.logger.error(str(sys.exc_info()[1]))
return False
- elt.text = Bcfg2.Encryption.ssl_encrypt(
+ elt.text = Bcfg2.Server.Encryption.ssl_encrypt(
elt.text, passphrase,
- Bcfg2.Encryption.get_algorithm(self.setup)).strip()
+ Bcfg2.Server.Encryption.get_algorithm(self.setup)).strip()
elt.set("encrypted", pname)
return xdata
@@ -267,9 +269,9 @@ class PropertiesDecryptor(Decryptor, PropertiesCryptoMixin):
except PassphraseError:
self.logger.error(str(sys.exc_info()[1]))
return False
- decrypted = Bcfg2.Encryption.ssl_decrypt(
+ decrypted = Bcfg2.Server.Encryption.ssl_decrypt(
elt.text, passphrase,
- Bcfg2.Encryption.get_algorithm(self.setup)).strip()
+ Bcfg2.Server.Encryption.get_algorithm(self.setup)).strip()
try:
elt.text = decrypted.encode('ascii', 'xmlcharrefreplace')
elt.set("encrypted", pname)
@@ -291,10 +293,10 @@ def main(): # pylint: disable=R0912,R0915
optinfo = dict(interactive=Bcfg2.Options.INTERACTIVE)
optinfo.update(Bcfg2.Options.CRYPT_OPTIONS)
optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS)
- setup = Bcfg2.Options.OptionParser(optinfo)
+ setup = Bcfg2.Options.load_option_parser(optinfo)
setup.hm = " bcfg2-crypt [options] <filename>\nOptions:\n%s" % \
setup.buildHelpMessage()
- setup.parse(sys.argv[1:])
+ setup.parse()
if not setup['args']:
print(setup.hm)
@@ -431,7 +433,7 @@ def main(): # pylint: disable=R0912,R0915
tool.write(data)
if (setup['remove'] and
- tool.get_destination_filename(fname) != fname):
+ tool.get_destination_filename(fname) != fname):
try:
os.unlink(fname)
except IOError:
diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info
index 6008f8896..9e3a671da 100755
--- a/src/sbin/bcfg2-info
+++ b/src/sbin/bcfg2-info
@@ -16,6 +16,7 @@ import Bcfg2.Options
import Bcfg2.Server.Core
import Bcfg2.Server.Plugin
import Bcfg2.Client.Tools.POSIX
+from Bcfg2.Compat import unicode # pylint: disable=W0622
try:
try:
@@ -115,11 +116,15 @@ def load_interpreters():
class InfoCore(cmd.Cmd, Bcfg2.Server.Core.BaseCore):
"""Main class for bcfg2-info."""
- def __init__(self, setup):
+ doc_header = "bcfg2-info commands (type help <command>):"
+ prompt = 'bcfg2-info> '
+
+ def __init__(self):
cmd.Cmd.__init__(self)
- Bcfg2.Server.Core.BaseCore.__init__(self, setup=setup)
- self.prompt = '> '
- self.cont = True
+ self.setup = Bcfg2.Options.get_option_parser()
+ self.setup.update(Bcfg2.Options.SERVER_COMMON_OPTIONS)
+ self.setup.update(dict(interpreter=Bcfg2.Options.INTERPRETER))
+ Bcfg2.Server.Core.BaseCore.__init__(self)
def _get_client_list(self, hostglobs):
""" given a host glob, get a list of clients that match it """
@@ -144,37 +149,15 @@ class InfoCore(cmd.Cmd, Bcfg2.Server.Core.BaseCore):
clist.difference_update(rv)
return list(rv)
- def _get_usage(self, func):
- """ get the short usage message for a given function """
- return "Usage: " + re.sub(r'\s+', ' ', func.__doc__).split(" - ", 1)[0]
-
- def do_loop(self):
- """Looping."""
- self.cont = True
- while self.cont:
- try:
- self.cmdloop('Welcome to bcfg2-info\n'
- 'Type "help" for more information')
- except SystemExit:
- raise
- except Bcfg2.Server.Plugin.PluginExecutionError:
- continue
- except KeyboardInterrupt:
- print("Ctrl-C pressed exiting...")
- self.do_exit([])
- except:
- self.logger.error("Command failure", exc_info=1)
-
def do_debug(self, args):
- """ debug [-n] [-f <command list>] - Shell out to native
- python interpreter """
+ """debug [-n] [-f <command list>]
+ Shell out to native python interpreter"""
try:
opts, _ = getopt.getopt(args.split(), 'nf:')
except getopt.GetoptError:
print(str(sys.exc_info()[1]))
- print(self._get_usage(self.do_debug))
+ print(self.do_debug.__doc__)
return
- self.cont = False
scriptmode = False
interactive = True
for opt in opts:
@@ -201,24 +184,23 @@ class InfoCore(cmd.Cmd, Bcfg2.Server.Core.BaseCore):
", ".join(interpreters.keys()))
def do_quit(self, _):
- """ quit|exit - Exit program """
+ """quit|exit
+ Exit program"""
+ print("") # put user's prompt on a new line
self.shutdown()
os._exit(0) # pylint: disable=W0212
do_EOF = do_quit
do_exit = do_quit
- def do_help(self, _):
- """ help - Print this list of available commands """
- print(USAGE)
-
def do_update(self, _):
- """ update - Process pending filesystem events"""
+ """update
+ Process pending filesystem events"""
self.fam.handle_events_in_interval(0.1)
def do_build(self, args):
- """ build [-f] <hostname> <filename> - Build config for
- hostname, writing to filename"""
+ """build [-f] <hostname> <filename>
+ Build config for hostname, writing to filename"""
alist = args.split()
path_force = False
for arg in alist:
@@ -240,7 +222,7 @@ class InfoCore(cmd.Cmd, Bcfg2.Server.Core.BaseCore):
err = sys.exc_info()[1]
print("Failed to write File %s: %s" % (ofile, err))
else:
- print(self._get_usage(self.do_build))
+ print(self.do_build.__doc__)
def help_builddir(self):
"""Display help for builddir command."""
@@ -258,8 +240,8 @@ could be much more permissive than would be created by the
Bcfg2 client itself.""")
def do_builddir(self, args):
- """ builddir [-f] <hostname> <dirname> - Build config for
- hostname, writing separate files to dirname"""
+ """ builddir [-f] <hostname> <dirname>
+ Build config for hostname, writing separate files to dirname"""
alist = args.split()
path_force = False
if '-f' in args:
@@ -284,19 +266,18 @@ Bcfg2 client itself.""")
posix = Bcfg2.Client.Tools.POSIX.POSIX(MockLog(),
self.setup,
client_config)
- states = dict()
- posix.Inventory(states)
- posix.Install(list(states.keys()), states)
+ states = posix.Inventory()
+ posix.Install(list(states.keys()))
else:
print('Error: Incorrect number of parameters.')
- self.help_builddir()
+ print(self.do_builddir.__doc__)
def do_buildall(self, args):
- """ buildall <directory> [<hostnames*>] - Build configs for
- all clients in directory """
+ """buildall <directory> [<hostnames*>]
+ Build configs for all clients in directory"""
alist = args.split()
if len(alist) < 1:
- print(self._get_usage(self.do_buildall))
+ print(self.do_buildall.__doc__)
return
destdir = alist[0]
@@ -315,20 +296,20 @@ Bcfg2 client itself.""")
client + ".xml")))
def do_buildallfile(self, args):
- """ buildallfile <directory> <filename> [<hostnames*>] - Build
- config file for all clients in directory """
+ """ buildallfile <directory> <filename> [<hostnames*>]
+ Build config file for all clients in directory"""
try:
opts, args = getopt.gnu_getopt(args.split(), '', ['altsrc='])
except getopt.GetoptError:
print(str(sys.exc_info()[1]))
- print(self._get_usage(self.do_buildallfile))
+ print(self.do_buildallfile.__doc__)
return
altsrc = None
for opt in opts:
if opt[0] == '--altsrc':
altsrc = opt[1]
if len(args) < 2:
- print(self._get_usage(self.do_buildallfile))
+ print(self.do_buildallfile.__doc__)
return
destdir = args[0]
@@ -352,9 +333,8 @@ Bcfg2 client itself.""")
filename, client))
def do_buildfile(self, args):
- """ buildfile [-f <outfile>] [--altsrc=<altsrc>] <filename>
- <hostname> - Build config file for hostname (not written to
- disk)"""
+ """buildfile [-f <outfile>] [--altsrc=<altsrc>] <filename> <hostname>
+ Build config file for hostname (not written to disk)"""
try:
opts, alist = getopt.gnu_getopt(args.split(), 'f:', ['altsrc='])
except getopt.GetoptError:
@@ -396,11 +376,11 @@ Bcfg2 client itself.""")
print(data)
def do_buildbundle(self, args):
- """ buildbundle <bundle> <hostname> - Render a templated
- bundle for hostname (not written to disk) """
+ """buildbundle <bundle> <hostname>
+ Render a templated bundle for hostname (not written to disk)"""
if len(args.split()) != 2:
- print(self._get_usage(self.do_buildbundle))
- return 1
+ print(self.do_buildbundle.__doc__)
+ return
bname, client = args.split()
try:
@@ -418,8 +398,8 @@ Bcfg2 client itself.""")
err))
def do_automatch(self, args):
- """ automatch [-f] <propertyfile> <hostname> - Perform automatch on
- a Properties file """
+ """automatch [-f] <propertyfile> <hostname>
+ Perform automatch on a Properties file"""
alist = args.split()
force = False
for arg in alist:
@@ -427,7 +407,7 @@ Bcfg2 client itself.""")
alist.remove('-f')
force = True
if len(alist) != 2:
- print(self._get_usage(self.do_automatch))
+ print(self.do_automatch.__doc__)
return
if 'Properties' not in self.plugins:
@@ -449,7 +429,8 @@ Bcfg2 client itself.""")
pretty_print=True).decode('UTF-8'))
def do_bundles(self, _):
- """ bundles - Print out group/bundle info """
+ """bundles
+ Print out group/bundle info"""
data = [('Group', 'Bundles')]
groups = list(self.metadata.groups.keys())
groups.sort()
@@ -459,7 +440,8 @@ Bcfg2 client itself.""")
print_tabular(data)
def do_clients(self, _):
- """ clients - Print out client/profile info """
+ """clients
+ Print out client/profile info"""
data = [('Client', 'Profile')]
for client in sorted(self.metadata.list_clients()):
imd = self.metadata.get_initial_metadata(client)
@@ -467,7 +449,8 @@ Bcfg2 client itself.""")
print_tabular(data)
def do_config(self, _):
- """ config - Print out the current configuration of Bcfg2"""
+ """config
+ Print out the current configuration of Bcfg2"""
output = [
('Description', 'Value'),
('Path Bcfg2 repository', self.setup['repo']),
@@ -494,16 +477,16 @@ Bcfg2 client itself.""")
self.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata)
def do_probes(self, args):
- """ probes [-p] <hostname> - Get probe list for the given
- host, in XML (the default) or human-readable pretty (with -p)
- format"""
+ """probes [-p] <hostname>
+ Get probe list for the given host, in XML (the default) \
+or human-readable pretty (with -p) format"""
alist = args.split()
pretty = False
if '-p' in alist:
pretty = True
alist.remove('-p')
if len(alist) != 1:
- print(self._get_usage(self.do_probes))
+ print(self.do_probes.__doc__)
return
hostname = alist[0]
if pretty:
@@ -529,11 +512,11 @@ Bcfg2 client itself.""")
pretty_print=True).decode('UTF-8'))
def do_showentries(self, args):
- """ showentries <hostname> <type> - Show abstract
- configuration entries for a given host """
+ """showentries <hostname> <type>
+ Show abstract configuration entries for a given host"""
arglen = len(args.split())
if arglen not in [1, 2]:
- print(self._get_usage(self.do_showentries))
+ print(self.do_showentries.__doc__)
return
client = args.split()[0]
try:
@@ -556,7 +539,8 @@ Bcfg2 client itself.""")
print_tabular(output)
def do_groups(self, _):
- """ groups - Print out group info """
+ """groups
+ Print out group info"""
data = [("Groups", "Profile", "Category")]
grouplist = list(self.metadata.groups.keys())
grouplist.sort()
@@ -570,10 +554,10 @@ Bcfg2 client itself.""")
print_tabular(data)
def do_showclient(self, args):
- """ showclient <client> [<client> ...] - Show metadata for the
- given hosts """
+ """showclient <client> [<client> ...]
+ Show metadata for the given hosts"""
if not len(args):
- print(self._get_usage(self.do_showclient))
+ print(self.do_showclient.__doc__)
return
for client in args.split():
try:
@@ -612,8 +596,8 @@ Bcfg2 client itself.""")
print("=" * 80)
def do_mappings(self, args):
- """ mappings <type*> <name*> - Print generator mappings for
- optional type and name """
+ """mappings <type*> <name*>
+ Print generator mappings for optional type and name"""
# Dump all mappings unless type specified
data = [('Plugin', 'Type', 'Name')]
arglen = len(args.split())
@@ -636,17 +620,17 @@ Bcfg2 client itself.""")
print_tabular(data)
def do_event_debug(self, _):
- """ event_debug - Display filesystem events as they are
- processed """
+ """event_debug
+ Display filesystem events as they are processed"""
self.fam.debug = True
def do_packageresolve(self, args):
- """ packageresolve <hostname> [<package> [<package>...]] -
- Resolve packages for the given host, optionally specifying a
- set of packages """
+ """packageresolve <hostname> [<package> [<package>...]]
+ Resolve packages for the given host, optionally specifying a \
+set of packages"""
arglist = args.split(" ")
if len(arglist) < 1:
- print(self._get_usage(self.do_packageresolve))
+ print(self.do_packageresolve.__doc__)
return
try:
@@ -671,13 +655,15 @@ Bcfg2 client itself.""")
structures)
print("%d new packages added" % len(indep.getchildren()))
if len(indep.getchildren()):
- print(" %s" % "\n ".join(lxml.etree.tostring(p)
- for p in indep.getchildren()))
+ print(" %s" % "\n ".join(
+ lxml.etree.tostring(p, encoding=unicode)
+ for p in indep.getchildren()))
def do_packagesources(self, args):
- """ packagesources <hostname> - Show package sources """
+ """packagesources <hostname>
+ Show package sources"""
if not args:
- print(self._get_usage(self.do_packagesources))
+ print(self.do_packagesources.__doc__)
return
if 'Packages' not in self.plugins:
print("Packages plugin not enabled")
@@ -691,13 +677,14 @@ Bcfg2 client itself.""")
print(collection.sourcelist())
def do_query(self, args):
- """ query <-g group|-p profile|-b bundle> - Query clients """
+ """query <-g group|-p profile|-b bundle>
+ Query clients"""
if len(args) == 0:
print("\n".join(self.metadata.clients))
return
arglist = args.split(" ")
if len(arglist) != 2:
- print(self._get_usage(self.do_query))
+ print(self.do_query.__doc__)
return
qtype, qparam = arglist
@@ -708,18 +695,18 @@ Bcfg2 client itself.""")
elif qtype == '-b':
res = self.metadata.get_client_names_by_bundles(qparam.split(','))
else:
- print(self._get_usage(self.do_query))
+ print(self.do_query.__doc__)
return
print("\n".join(res))
def do_profile(self, arg):
- """ profile <command> <args> - Profile a single bcfg2-info
- command """
+ """profile <command> <args>
+ Profile a single bcfg2-info command"""
if not HAS_PROFILE:
print("Profiling functionality not available.")
return
if len(arg) == 0:
- print(self._get_usage(self.do_profile))
+ print(self.do_profile.__doc__)
return
prof = profile.Profile()
prof.runcall(self.onecmd, arg)
@@ -732,7 +719,14 @@ Bcfg2 client itself.""")
if args:
self.onecmd(" ".join(args))
else:
- self.do_loop()
+ try:
+ self.cmdloop('Welcome to bcfg2-info\n'
+ 'Type "help" for more information')
+ except KeyboardInterrupt:
+ print("\nCtrl-C pressed exiting...")
+ self.do_exit([])
+ except Bcfg2.Server.Plugin.PluginExecutionError:
+ pass
finally:
self.shutdown()
@@ -747,7 +741,7 @@ Bcfg2 client itself.""")
def build_usage():
- """ build usage message """
+ """build usage message"""
cmd_blacklist = ["do_loop", "do_EOF"]
usage = dict()
for attrname in dir(InfoCore):
@@ -773,7 +767,7 @@ def main():
command_timeout=Bcfg2.Options.CLIENT_COMMAND_TIMEOUT)
optinfo.update(Bcfg2.Options.INFO_COMMON_OPTIONS)
setup = Bcfg2.Options.OptionParser(optinfo)
- setup.hm = "\n".join([" bcfg2-info [options] [command <command args>]",
+ setup.hm = "\n".join(["bcfg2-info [options] [command <command args>]",
"Options:",
setup.buildHelpMessage(),
USAGE])
@@ -793,12 +787,12 @@ def main():
sys.exit(0)
elif setup['profile'] and HAS_PROFILE:
prof = profile.Profile()
- loop = prof.runcall(InfoCore, setup)
+ loop = prof.runcall(InfoCore)
display_trace(prof)
else:
if setup['profile']:
print("Profiling functionality not available.")
- loop = InfoCore(setup)
+ loop = InfoCore()
loop.run(setup['args'])
diff --git a/src/sbin/bcfg2-lint b/src/sbin/bcfg2-lint
index 9ceb1dd04..27d8d4291 100755
--- a/src/sbin/bcfg2-lint
+++ b/src/sbin/bcfg2-lint
@@ -14,37 +14,36 @@ import Bcfg2.Server.Lint
LOGGER = logging.getLogger('bcfg2-lint')
-def run_serverless_plugins(plugins, setup=None, errorhandler=None, files=None):
+def run_serverless_plugins(plugins, errorhandler=None, files=None):
""" Run serverless plugins """
LOGGER.debug("Running serverless plugins")
for plugin_name, plugin in list(plugins.items()):
- run_plugin(plugin, plugin_name, errorhandler=errorhandler,
- setup=setup, files=files)
+ run_plugin(plugin, plugin_name, errorhandler=errorhandler, files=files)
-def run_server_plugins(plugins, setup=None, errorhandler=None, files=None):
+def run_server_plugins(plugins, errorhandler=None, files=None):
""" run plugins that require a running server to run """
- core = load_server(setup)
+ core = load_server()
try:
LOGGER.debug("Running server plugins")
for plugin_name, plugin in list(plugins.items()):
run_plugin(plugin, plugin_name, args=[core],
- errorhandler=errorhandler, setup=setup, files=files)
+ errorhandler=errorhandler, files=files)
finally:
core.shutdown()
-def run_plugin(plugin, plugin_name, setup=None, errorhandler=None,
- args=None, files=None):
+def run_plugin(plugin, plugin_name, errorhandler=None, args=None, files=None):
""" run a single plugin, server-ful or serverless. """
LOGGER.debug(" Running %s" % plugin_name)
if args is None:
args = []
if errorhandler is None:
- errorhandler = get_errorhandler(setup)
+ errorhandler = get_errorhandler()
- if setup is not None and setup.cfp.has_section(plugin_name):
+ setup = Bcfg2.Options.get_option_parser()
+ if setup.cfp.has_section(plugin_name):
arg = setup
for key, val in setup.cfp.items(plugin_name):
arg[key] = val
@@ -60,8 +59,9 @@ def run_plugin(plugin, plugin_name, setup=None, errorhandler=None,
return rv
-def get_errorhandler(setup):
+def get_errorhandler():
""" get a Bcfg2.Server.Lint.ErrorHandler object """
+ setup = Bcfg2.Options.get_option_parser()
if setup.cfp.has_section("errors"):
errors = dict(setup.cfp.items("errors"))
else:
@@ -69,9 +69,9 @@ def get_errorhandler(setup):
return Bcfg2.Server.Lint.ErrorHandler(errors=errors)
-def load_server(setup):
+def load_server():
""" load server """
- core = Bcfg2.Server.Core.BaseCore(setup)
+ core = Bcfg2.Server.Core.BaseCore()
core.load_plugins()
core.block_for_fam_events(handle_events=True)
return core
@@ -89,8 +89,9 @@ def load_plugin(module, obj_name=None):
return getattr(mod, obj_name)
-def load_plugins(setup):
+def load_plugins():
""" get list of plugins to run """
+ setup = Bcfg2.Options.get_option_parser()
if setup['args']:
plugin_list = setup['args']
elif "bcfg2-repo-validate" in sys.argv[0]:
@@ -152,7 +153,7 @@ def main():
lint_plugins=Bcfg2.Options.LINT_PLUGINS)
optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS)
optinfo.update(Bcfg2.Options.SERVER_COMMON_OPTIONS)
- setup = Bcfg2.Options.OptionParser(optinfo)
+ setup = Bcfg2.Options.load_option_parser(optinfo)
setup.parse(sys.argv[1:])
log_args = dict(to_syslog=setup['syslog'], to_console=logging.WARNING)
@@ -168,9 +169,8 @@ def main():
else:
files = None
- (serverlessplugins, serverplugins) = load_plugins(setup)
-
- errorhandler = get_errorhandler(setup)
+ (serverlessplugins, serverplugins) = load_plugins()
+ errorhandler = get_errorhandler()
if setup['showerrors']:
for plugin in serverplugins.values() + serverlessplugins.values():
@@ -182,7 +182,7 @@ def main():
raise SystemExit(0)
run_serverless_plugins(serverlessplugins, errorhandler=errorhandler,
- setup=setup, files=files)
+ files=files)
if serverplugins:
if errorhandler.errors:
@@ -198,7 +198,7 @@ def main():
"plugins")
else:
run_server_plugins(serverplugins, errorhandler=errorhandler,
- setup=setup, files=files)
+ files=files)
if errorhandler.errors or errorhandler.warnings or setup['verbose']:
print("%d errors" % errorhandler.errors)
diff --git a/src/sbin/bcfg2-repo-validate b/src/sbin/bcfg2-repo-validate
deleted file mode 120000
index cea09cda3..000000000
--- a/src/sbin/bcfg2-repo-validate
+++ /dev/null
@@ -1 +0,0 @@
-bcfg2-lint \ No newline at end of file
diff --git a/src/sbin/bcfg2-report-collector b/src/sbin/bcfg2-report-collector
index 594be13bf..ae6d3b167 100755
--- a/src/sbin/bcfg2-report-collector
+++ b/src/sbin/bcfg2-report-collector
@@ -18,8 +18,8 @@ def main():
web_configfile=Bcfg2.Options.WEB_CFILE)
optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS)
optinfo.update(Bcfg2.Options.REPORTING_COMMON_OPTIONS)
- setup = Bcfg2.Options.OptionParser(optinfo)
- setup.parse(sys.argv[1:])
+ setup = Bcfg2.Options.load_option_parser(optinfo)
+ setup.parse()
# run collector
try:
diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server
index 4c4a71fa7..beb19cef6 100755
--- a/src/sbin/bcfg2-server
+++ b/src/sbin/bcfg2-server
@@ -17,7 +17,7 @@ def main():
optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS)
optinfo.update(Bcfg2.Options.SERVER_COMMON_OPTIONS)
optinfo.update(Bcfg2.Options.DAEMON_COMMON_OPTIONS)
- setup = Bcfg2.Options.OptionParser(optinfo)
+ setup = Bcfg2.Options.load_option_parser(optinfo)
setup.parse(sys.argv[1:])
# check whether the specified bcfg2.conf exists
if not os.path.exists(setup['configfile']):
diff --git a/src/sbin/bcfg2-test b/src/sbin/bcfg2-test
index 7c38a65d8..564ddec49 100755
--- a/src/sbin/bcfg2-test
+++ b/src/sbin/bcfg2-test
@@ -137,6 +137,7 @@ class ClientTest(TestCase):
"Configuration contains unknown packages: %s" % \
", ".join(unknown_pkgs)
+ # check for render failures
failures = []
msg = output + ["Failures:"]
for failure in config.xpath('//*[@failure]'):
@@ -210,7 +211,7 @@ def parse_args():
optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS)
optinfo.update(Bcfg2.Options.SERVER_COMMON_OPTIONS)
- setup = Bcfg2.Options.OptionParser(optinfo)
+ setup = Bcfg2.Options.load_option_parser(optinfo)
setup.hm = \
"bcfg2-test [options] [client] [client] [...]\nOptions:\n %s" % \
setup.buildHelpMessage()