#!/usr/bin/python # Author: Tristn Suerink # Version: QuatView 1.0 # Licence: GPL import getopt, sys import ConfigParser if sys.hexversion >= 0x020500F0: import xml.etree.ElementTree as ET else: import elementtree.ElementTree as ET import os, glob import time, csv import MySQLdb # code to deal with (un)escaping items in the XML import re def hexdecode(match): return "%s" % (match.group(1)).decode("hex") def hexencode(match): return "_%s" % (match.group(1)).encode("hex") def unescape(str): rx=re.compile('_([0-9a-f]{2})') return rx.sub(hexdecode,str) def escapeifnotstar(str): if str != '*': return escape(str) else: return str def escape(str): rx=re.compile('(^[0-9]|[^a-zA-Z0-9])') return rx.sub(hexencode,str) # Global variables VERBOSE = False CONFIG = "/etc/quatview.conf" CONFIGSECTION = "quattor" BEGINCREATEQUERY = "CREATE TABLE quatview (id INT( 255 ) NOT NULL AUTO_INCREMENT, file varchar(255) " BEGININSERTQUERY = "INSERT INTO quatview (" ENDCREATEQUERY = ", PRIMARY KEY ( id ))" DATASET = [] GLOB = "profile_*" def usage(): print """Usage: quatview.py [-h] [-v] [--cfg=CONFIGFILE] [--auto] [--clean] [XML FILES] -h, --help See this help -v, --verbose Verbose --cfg=CONFIGFILE Alternative configfile --auto Efficient way of processing --clean Processing from scratch XML FILES are optional. When there aren't any XML FILES given, the standard directory will be used.""" # Database connection def database(configuration): try: db=MySQLdb.connect(configuration.get("database", "hostname"),configuration.get("database", "username"),configuration.get("database", "password"),configuration.get("database", "database")) if VERBOSE == True: print "Database connection succesfully connected." return db.cursor() except MySQLdb.Error, err: print "MySQL error, check your configuration." print str(err) sys.exit(2) # For checking and filling some variables def init(): # Check if configfile exists if os.path.isfile(CONFIG) != True: print "Configfile doesn't exists!" sys.exit(2) # Get the list of xml files from the standard xmllocation global DATASET if DATASET == []: configuration = ConfigParser.ConfigParser() configuration.read(CONFIG) global GLOB try: GLOB=configuration.get("config","glob") except ConfigParser.NoOptionError, err: if VERBOSE == True: print "No glob defined, using default %s" %GLOB xmlloc=configuration.get("config", "xmllocation") profilepath=os.path.join(xmlloc, GLOB) DATASET = glob.glob(profilepath) if VERBOSE == True: print "Read %d profiles from %s" %(len(DATASET), profilepath) # Final check if the DATASET is filled if DATASET == []: print "Dataset is still empty, maybe the wrong directory in the config?" sys.exit(2) # Get the last time that this script has run succesfully def gettimestamp(cursor): # If the config table doesn't exists then create it. cursor.execute("show tables like 'config'") if cursor.rowcount == 0: cursor.execute("CREATE TABLE IF NOT EXISTS `config` (`name` varchar(255) NOT NULL,`information` varchar(255) NOT NULL,UNIQUE KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `config` (`name`, `information`) VALUES('timestamp', '6');") if VERBOSE == True: print "Creating the configuration table" try: cursor.execute("select information from config where name = 'timestamp' LIMIT 1") row = cursor.fetchone() return float(row[0]) except MySQLdb.Error, err: print "MySQL error, check your configuration." print str(err) sys.exit(2) # Set the time that this script had run succesfully def updatetimestamp(cursor): try: cursor.execute("update config set information = '%s' where name = 'timestamp'" % time.time()) print "Timestamp updated." except MySQLdb.Error, err: print "MySQL error, check your configuration." print str(err) sys.exit(2) # Get the information from the xml files def getinfo(xmlfile,configuration,cursor,insertquery,orderlist): # Check if the xml file exists if os.path.isfile(xmlfile) != True: print "Xmlfile: %s doesn't exists!" % xmlfile sys.exit(2) if VERBOSE == True: print "Processing %s" % xmlfile tree = ET.parse(xmlfile) elem = tree.getroot() tijdquery = "%s '%s'," % (insertquery,xmlfile) for option in orderlist: prefix = "" # Processing plugins if configuration.get(CONFIGSECTION, option)[:1] == "@": if configuration.get(CONFIGSECTION, option)[1] != "/": prefix = os.popen('pwd').readline()[:-1] if os.path.isfile(configuration.get(CONFIGSECTION, option)[1:]) != True: print "Plugin %s does not exists!" % configuration.get(CONFIGSECTION, option)[1:] sys.exit(2) tijdquery += "'%s'," % os.popen("%s/%s %s" % (prefix,configuration.get(CONFIGSECTION, option)[1:],xmlfile)).readline()[:-1] elif configuration.get(CONFIGSECTION, option).find('*') != -1: tempsubelem = "" optionpath=(configuration.get(CONFIGSECTION, option)[1:]) # split option path into sub-components and escape each one! optionpathlist=optionpath.split('/') optionpathlistnew=map(escapeifnotstar, optionpathlist) optionpath='/'.join(optionpathlistnew) for subelem in elem.findall(optionpath): if subelem.text != '' and subelem.text != '\n': tempsubelem += "%s, " % subelem.text else: tempsubelem += "%s, " % unescape(subelem.tag) tijdquery += "'%s'," % tempsubelem[:-2] else: # look for path in the XML thiselem=elem.find(configuration.get(CONFIGSECTION, option)[1:]) if thiselem == None: elemstring='None' else: elemstring=thiselem.text if elemstring=='\n': elemstring=thiselem.tag tijdquery += "'%s'," % elemstring cursor.execute("%s);" % tijdquery[:-1]) def clean(): # Setup the configuration parser and making the database connection. configuration = ConfigParser.ConfigParser() configuration.read(CONFIG) cursor = database(configuration) gettimestamp(cursor) listorder = csv.reader([configuration.get("config", "display")]) orderlist = listorder.next() # Dropping the table null = cursor.execute("DROP TABLE IF EXISTS quatview") if VERBOSE == True: print "Quatview table is dropped." # Creating database queries createquery = BEGINCREATEQUERY insertquery = "%s file," % BEGININSERTQUERY # Getting the names of the database fields for option in orderlist: createquery += ", %s varchar(255)" % option insertquery += "%s," % option if VERBOSE == True: print "Database create query: %s" % createquery # Executing the create query try: cursor.execute("%s %s" % (createquery,ENDCREATEQUERY)) if VERBOSE == True: print "Table succesfully created." except MySQLdb.Error, err: print "MySQL error, check your configuration." print str(err) sys.exit(2) # Setting the insertquery insertquery = "%s) VALUES (" % insertquery[:-1] # Processing the xml files for xmlfile in DATASET: getinfo(xmlfile,configuration,cursor,insertquery,orderlist) updatetimestamp(cursor) sys.exit(0) def auto(): # Setup the configuration parser and making the database connection. configuration = ConfigParser.ConfigParser() configuration.read(CONFIG) cursor = database(configuration) listorder = csv.reader([configuration.get("config", "display")]) orderlist = listorder.next() # Check the last time the configuration has been edited timestamp = gettimestamp(cursor) if os.path.getmtime(CONFIG) > timestamp: if VERBOSE == True: print "Configfile is newer than timestamp. So going to the clean function." clean() # Creating Database queries insertquery = "%s file," % BEGININSERTQUERY # Getting the names of the database fields for option in orderlist: insertquery += "%s," % option # Setting the insertquery insertquery = "%s) VALUES (" % insertquery[:-1] # Processing the xml files for xmlfile in DATASET: if os.path.getmtime(xmlfile) > timestamp: cursor.execute("DELETE FROM quatview where file = '%s' LIMIT 1" % xmlfile) getinfo(xmlfile,configuration,cursor,insertquery,orderlist) else: if VERBOSE == True: print "%s is already processed." % xmlfile updatetimestamp(cursor) sys.exit(0) # The main function, where everything begins def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hv", ["help","verbose","cfg=","auto","clean"]) except getopt.GetoptError, err: # print help information and exit: print str(err) # will print something like "option -a not recognized" usage() sys.exit(2) # Set the given dataset global DATASET if args != []: DATASET = args # Check the different arguments given for o, a in opts: if o in ("-v","--verbose"): global VERBOSE VERBOSE = True print "Verbose activated." elif o in ("-h", "--help"): usage() sys.exit() elif o in ("--cfg"): global CONFIG CONFIG = a if VERBOSE == True: print "Using configfile: %s" % CONFIG elif o in ("--auto"): init() auto() elif o in ("--clean"): init() clean() else: assert False, "unhandled option" sys.exit(2) init() auto() if __name__ == "__main__": main()