summaryrefslogtreecommitdiffstats
path: root/src/sbin/bcfg2-build-reports
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbin/bcfg2-build-reports')
-rwxr-xr-xsrc/sbin/bcfg2-build-reports142
1 files changed, 82 insertions, 60 deletions
diff --git a/src/sbin/bcfg2-build-reports b/src/sbin/bcfg2-build-reports
index 231f52105..6b3e24e84 100755
--- a/src/sbin/bcfg2-build-reports
+++ b/src/sbin/bcfg2-build-reports
@@ -14,7 +14,9 @@ import socket
import sys
from time import asctime, strptime
from ConfigParser import ConfigParser, NoSectionError, NoOptionError
-from lxml.etree import XML, XSLT, parse, Element, ElementTree, SubElement, tostring, XMLSyntaxError
+from lxml.etree import XML, XSLT, parse, Element, ElementTree, \
+ SubElement, tostring, XMLSyntaxError
+
def generatereport(rspec, nrpt):
"""
@@ -24,12 +26,12 @@ def generatereport(rspec, nrpt):
reportspec = copy.deepcopy(rspec)
nodereprt = copy.deepcopy(nrpt)
- reportgood = reportspec.get("good", default = 'Y')
- reportmodified = reportspec.get("modified", default = 'Y')
+ 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')]))
+ 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'))):
@@ -40,25 +42,27 @@ def generatereport(rspec, nrpt):
# 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"))))
+ 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")
+ 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")
+ SubElement(stats, "Stale")
node.append(stats)
return nodereprt
+
def mail(mailbody, confi):
"""mail mails a previously generated report."""
@@ -72,7 +76,8 @@ def mail(mailbody, confi):
pipe.write(mailbody)
exitcode = pipe.close()
if exitcode:
- print "Exit code: %s" % exitcode
+ print("Exit code: %s" % exitcode)
+
def rss(reportxml, delivery, report):
"""rss appends a new report to the specified rss file
@@ -98,7 +103,7 @@ def rss(reportxml, delivery, report):
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"
@@ -115,17 +120,19 @@ def rss(reportxml, delivery, report):
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?
+ # 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'):
@@ -134,25 +141,29 @@ def fileout(reportxml, delivery):
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 element.attrib.iteritems()])),
+ 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 element.attrib.iteritems()]),)
- data += tuple([pretty_print(entry, level+2) for entry in element._children]) + (element.tag, )
+ 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 element.attrib.iteritems()]))
+ data = (element.tag, " ".join(["%s='%s'" % keyval for keyval in
+ list(element.attrib.items())]))
return fmt % data
if __name__ == '__main__':
- ping=True
- all=False
+ ping = True
+ all = False
if '-C' in sys.argv:
cfpath = sys.argv[sys.argv.index('-C') + 1]
else:
@@ -171,17 +182,24 @@ if __name__ == '__main__':
#websrcspath = "/usr/share/bcfg2/web-rprt-srcs/"
try:
- opts, args = getopt.getopt(sys.argv[1:], "C:hAc:Ns:", ["help", "all", "config=","no-ping", "stats="])
+ opts, args = getopt.getopt(sys.argv[1:],
+ "C:hAc:Ns:",
+ ["help", "all", "config=", "no-ping",
+ "stats="])
except getopt.GetoptError, mesg:
# Print help information and exit:
- print "%s\nUsage:\nbcfg2-build-reports [-h][-A (include ALL clients)] [-c <configuration-file>] [-s <statistics-file>][-N (do not ping clients)]" % (mesg)
- raise SystemExit, 2
+ print("%s\nUsage:\n"
+ "bcfg2-build-reports [-h] [-A (include ALL clients)] "
+ "[-c <configuration-file>] [-s <statistics-file>] "
+ "[-N (do not ping clients)]" % (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>]"
+ print("Usage:\nbcfg2-build-reports [-h] [-c <configuration-file>] "
+ "[-s <statistics-file>]")
raise SystemExit
if o in ("-A", "--all"):
- all=True
+ all = True
if o in ("-c", "--config"):
configpath = a
if o in ("-N", "--no-ping"):
@@ -189,94 +207,96 @@ if __name__ == '__main__':
if o in ("-s", "--stats"):
statpath = a
-
# See if hostinfo.xml exists, and is less than 23.5 hours old
#try:
#hostinstat = os.stat(hostinfopath)
#if (time() - hostinstat[9])/(60*60) > 23.5:
if ping:
- os.system('bcfg2-ping-sweep -C %s' % cfpath) # bcfg2-ping-sweep needs to be in path
+ os.system('bcfg2-ping-sweep -C %s' % cfpath) # bcfg2-ping-sweep needs to be in path
#except OSError:
# os.system('GenerateHostInfo')#Generate HostInfo needs to be in path
-
"""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
+ 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
+ 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
+ print("bcfg2-build-reports: Failed to parse %s" % (clientsdatapath))
+ raise SystemExit(1)
# Merge data from three sources.
- nodereport = Element("Report", attrib={"time" : asctime()})
+ 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 = 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 = 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"))
+ 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(), encoding='UTF-8', xml_declaration=True), deliv)
+ if deliverymechanism == 'null-operator': # Special Cases
+ fileout(tostring(ElementTree(procnodereport).getroot(),
+ encoding='UTF-8',
+ xml_declaration=True),
+ deliv)
break
transform = delivtype + '-' + deliverymechanism + '.xsl'
- try: # Make sure valid stylesheet is selected.
+ 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
+ raise SystemExit(1)
- try: # Try to parse stylesheet.
+ try: # Try to parse stylesheet.
stylesheet = XSLT(parse(transformpath + transform))
except:
print("bcfg2-build-reports: invalid XSLT transform file.")
- raise SystemExit, 1
-
+ raise SystemExit(1)
+
if deliverymechanism == 'mail':
if delivtype == 'nodes-individual':
reportdata = copy.deepcopy(procnodereport)
@@ -285,35 +305,37 @@ if __name__ == '__main__':
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"% \
+ outputstring = "To: %s\nFrom: root@%s\n%s" % \
(toastring, socket.getfqdn(), outputstring)
- mail(outputstring, c) #call function to send
-
+ 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"% \
+ outputstring = "To: %s\nFrom: root@%s\n%s" % \
(toastring, socket.getfqdn(), outputstring)
- mail(outputstring, c) #call function to send
+ mail(outputstring, c) # call function to send
else:
- outputstring = tostring(stylesheet.apply(ElementTree(procnodereport)).getroot(), encoding='UTF-8', xml_declaration=True)
+ outputstring = tostring(stylesheet.apply(ElementTree(procnodereport)).getroot(),
+ encoding='UTF-8',
+ xml_declaration=True)
if deliverymechanism == 'rss':
rss(outputstring, deliv, reprt)
- else: # Must be deliverymechanism == 'www':
+ else: # Must be deliverymechanism == 'www':
www(outputstring, deliv)