summaryrefslogtreecommitdiffstats
path: root/src/sbin/StatReports
diff options
context:
space:
mode:
authorNarayan Desai <desai@mcs.anl.gov>2006-09-15 02:44:58 +0000
committerNarayan Desai <desai@mcs.anl.gov>2006-09-15 02:44:58 +0000
commit40367f6cb0e69b8b993317149d824d9bf489a4f2 (patch)
tree5dff53deafc9eef64c5a75dec9b26a5b5fff4a72 /src/sbin/StatReports
parent3f71d210c63e46b79b0f04a0463d0a218a3a8862 (diff)
downloadbcfg2-40367f6cb0e69b8b993317149d824d9bf489a4f2.tar.gz
bcfg2-40367f6cb0e69b8b993317149d824d9bf489a4f2.tar.bz2
bcfg2-40367f6cb0e69b8b993317149d824d9bf489a4f2.zip
Rename StatReports to bcfg2-build-reports
git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@2257 ce84e21b-d406-0410-9b95-82705330c041
Diffstat (limited to 'src/sbin/StatReports')
-rwxr-xr-xsrc/sbin/StatReports290
1 files changed, 0 insertions, 290 deletions
diff --git a/src/sbin/StatReports b/src/sbin/StatReports
deleted file mode 100755
index 722c563c0..000000000
--- a/src/sbin/StatReports
+++ /dev/null
@@ -1,290 +0,0 @@
-#!/usr/bin/env python
-
-'''bcfg2-build-reports Generates & distributes reports of statistic information
-for bcfg2'''
-__revision__ = '$Revision$'
-
-from ConfigParser import ConfigParser, NoSectionError, NoOptionError
-from lxml.etree import XML, XSLT, parse, Element, ElementTree, SubElement, tostring, XMLSyntaxError
-from time import asctime, strptime
-import copy, getopt, re, os, socket, sys
-
-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() == None]
- [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 (NoSectionError, 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 = "<?xml version=\"1.0\"?>" + tostring(rssdata)
- 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 element.attrib.iteritems()])),
- 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, )
- else:
- fmt = "%s<%%s %%s/>\n" % (level * " ")
- data = (element.tag, " ".join(["%s='%s'" % keyval for keyval in element.attrib.iteritems()]))
- return fmt % data
-
-
-if __name__ == '__main__':
- if '-C' in sys.argv:
- cfpath = sys.argv[sys.argv.index('-C') + 1]
- else:
- cfpath = '/etc/bcfg2.conf'
- c = 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 (NoSectionError, 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:hc:s:", ["help", "config=", "stats="])
- except getopt.GetoptError, mesg:
- # print help information and exit:
- print "%s\nUsage:\nbcfg2-build-reports [-h] [-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 ("-c", "--config"):
- configpath = a
- 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:
- os.system('bcfg2-ping-sweep') # 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
- 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)
-
-
- 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()), 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())
- if deliverymechanism == 'rss':
- rss(outputstring, deliv, reprt)
- else: # must be deliverymechanism == 'www':
- www(outputstring, deliv)