#!/usr/bin/env python # # $Id$ # $HeadURL$ # # This file contains utilities for extracting # information about a COOL configuration using # Python. It is not intended to be run directly. # To use these in a python script, add the following # to the top of the script. # # import coolutils # # make sure your PYTHONPATH environment variable is # set to the directory containing this file. # # Default values for COOL_HOME, EXPID, SESSION and # CODA_CONFIG are taken from environment # variables. Of these, only COOL_HOME and EXPID need # to be set since SESSION will default to be the same # as EXPID and the configuration will be extracted # from the COOL DB using those. # # Component values and other configuration parameters # can be accessed directly via the globals in this # module. For example, the array of ROCs for the current # configuration can be accessed from: # # coolutils.rocs # # The configuration specific data like the lists of # ROCs, Event Builders, Event Recorders, etc. is only # valid if the global coolutils.configDataValid is True. # # The environment variables may be overidden # programmatically using the following: # # coolutils.SetCOOL_HOME(cool_home) # coolutils.SetEXPID(expid) # coolutils.SetSESSION(session) # coolutils.SetCONFIG(config) # # Calling any of these may set the configDataValid flag # to False depending on whether the new value differs # from the old value. To read in the configuration # based on the current settings do this: # # coolutils.ReadConfiguration() # # One can also specify the configuration as an argument: # # coolutils.ReadConfiguration('PROD') # # # If COOL_HOME is set, then coolutils.expids will contain # a list of available EXPID values # # If COOL_HOME and EXPID are set, then coolutils.configs # will contain the available CODA configurations # import sys,os import subprocess import traceback import string import time import math import re from xml.dom.minidom import parseString from xml.dom.minidom import parse COOL_HOME = os.getenv("COOL_HOME") EXPID = os.getenv("EXPID") SESSION = os.getenv("SESSION", EXPID) CONFIG = os.getenv("CODA_CONFIG") DAQ_HOME = os.getenv("DAQ_HOME") RUN_NUMBER = 0 OUTPUT_FILE= '' OUTPUT_DIR = '' configDataValid = False rocs = [] # will be filled by GetComponents ts = [] # will be filled by GetComponents dcs = [] # will be filled by GetComponents pebs = [] # will be filled by GetComponents sebs = [] # will be filled by GetComponents ers = [] # will be filled by GetComponents fcss = [] # will be filled by GetComponents files = [] # will be filled by GetComponents hosts = {} # will be filled by GetHosts expids = {} # will be filled by GetEXPIDs configs = {} # will be filled by GetConfigurations #------------------ # SetCOOL_HOME #------------------ def SetCOOL_HOME(cool_home): global COOL_HOME, configDataValid if cool_home != COOL_HOME : configDataValid = False COOL_HOME = cool_home #------------------ # SetEXPID #------------------ def SetEXPID(expid): global EXPID, configDataValid if expid != EXPID : configDataValid = False EXPID = expid #------------------ # SetSESSION #------------------ def SetSESSION(session): global SESSION, configDataValid if session != SESSION : configDataValid = False SESSION = session #------------------ # SetCONFIG #------------------ def SetCONFIG(config): global CONFIG, configDataValid if config != CONFIG : configDataValid = False CONFIG = config #------------------ # GetCODAconfig # # Get the current or otherwise most recent CODA configuration # used for this EXPID #------------------ def GetCODAconfig(): global COOL_HOME, EXPID, SESSION, CONFIG, RUN_NUMBER, OUTPUT_FILE, OUTPUT_DIR # Try current_run.log first, and previous_run.log only if needed run_log = '%s/%s/ddb/run-log/%s/current_run.log' % (COOL_HOME, EXPID, SESSION) if not os.path.exists(run_log) : run_log = '%s/%s/ddb/run-log/%s/previous_run.log' % (COOL_HOME, EXPID, SESSION) if not os.path.exists(run_log) : return None # Parse run_log file and get configuration # CODA >=3.04 includes an "&" in some udl values. The minidom # parser chokes on this so we must read the whole file in as # string and replace it with '--AMPERSAND--' xml = '' with open(run_log) as f: xml = f.read() if xml=='' : raise Exception('Problem reading file') xml = re.sub('&','--AMPERSAND--', xml) dom = parseString(xml) coda = dom.getElementsByTagName('coda').item(0) # Verify node has a runtype attribute then set CONFIG to it if not coda.hasAttribute('runtype') : return None CONFIG = coda.attributes['runtype'].value # Grab run number if we can run_number = dom.getElementsByTagName('run-number').item(0) if run_number != None: RUN_NUMBER = int(run_number.firstChild.nodeValue) # Ditto for output file and directory out_file = dom.getElementsByTagName('out-file').item(0) if out_file != None: if out_file.firstChild != None: OUTPUT_FILE = os.path.realpath(out_file.firstChild.nodeValue) OUTPUT_DIR = os.path.dirname(OUTPUT_FILE) if not os.path.exists(OUTPUT_FILE) : OUTPUT_FILE = '' if not os.path.exists(OUTPUT_DIR ) : OUTPUT_DIR = '' return CONFIG #------------------ # GetEXPIDs #------------------ def GetEXPIDs(): global expids, COOL_HOME cooldir = "%s" % (COOL_HOME) if os.path.exists(cooldir): expids = os.listdir(cooldir) expids = [x for x in expids if x != '.svn'] #------------------ # GetConfigurations #------------------ def GetConfigurations(): global configs, COOL_HOME, EXPID confdir = "%s/%s/config/Control" % (COOL_HOME, EXPID) if os.path.exists(confdir): configs = os.listdir(confdir) configs = [x for x in configs if x != '.svn'] else: mess = "Directory doesn't exist: %s" % confdir mess += "Check your COOL_HOME and EXPID environment variables!" raise IOError(mess) #------------------ # GetComponents #------------------ def GetComponents(): global rocs, ts, pebs, sebs,ers, fcss, files configdir = "%s/%s/config/Control/%s" % (COOL_HOME, EXPID, CONFIG) fname = "%s/%s.rdf" % (configdir, CONFIG) with open(fname) as f: lines = f.readlines() for line in lines: idx_end = string.rfind(line, '.rdf"/>') if idx_end < 2: continue idx_start = string.rfind(line[0:idx_end], '/') if idx_start < 2: continue cname = line[idx_start+1:idx_end] # Read in specific component file and get type # n.b. some of these are in the "Processes" directory instead # of "Components". We don't care about those, but we'll get # an exception when trying to open them. Catch the exception # ignore it. try: if 'hasType>ROC<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): rocs.append(cname) if 'hasType>TS<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): ts.append(cname) if 'hasType>DC<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): dcs.append(cname) if 'hasType>PEB<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): pebs.append(cname) if 'hasType>SEB<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): sebs.append(cname) if 'hasType>ER<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): ers.append(cname) if 'hasType>FCS<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): fcss.append(cname) if 'hasType>FILE<' in open('%s/Components/%s.rdf' % (configdir, cname)).read(): files.append(cname) if string.find(cname, "localhost" ) == 0: rocs.append(cname) # for running sandbox test except: pass #------------------ # GetHosts #------------------ def GetHosts(): global hosts, rocs, ts # Add all rocs and TS's for roc in rocs : hosts[roc] = roc for roc in ts : hosts[roc] = roc if DAQ_HOME==None: print 'DAQ_HOME not set. All non-ROC hosts will be run locally' return # Configuration names with a "." indicate they are just peturbations # on configurations whose name is the same up to the dot. config = CONFIG dotpos = string.find(CONFIG, '.') if dotpos > 0 : config = CONFIG[0:dotpos] hostsfile = '%s/config/%s/hosts' % (DAQ_HOME, config) if not os.path.exists(hostsfile): print 'File %s does not exist. All non-ROC hosts will be assumed localhost' % hostsfile return # Open hosts file and parse it with open(hostsfile) as f: lines = f.readlines() for line in lines: if string.find(line.strip(), '#') == 0 : continue strs = line.strip().split() if len(strs)<2 : continue hosts[strs[0]] = strs[1] #------------------ # GetETInfo # # Get info about the ET system created by this component. # It will return a dictionary with all attributes defined # in the XML file corresponding to the specific component. # In addition, the host will be specified as either "localhost" # or whatever was specified in the "hosts" file. The most # useful entries in the dictionary are: # # ETInfo['host'] # ETInfo['port'] # ETInfo['etName'] # #------------------ def GetETInfo(component): global COOL_HOME, EXPID, CONFIG, configDataValid, hosts if not configDataValid : raise StandardError('Configuration data not valid!') # Get the name of the options file optionsfile = '%s/%s/config/Control/%s/Options/%s_option.rdf' % (COOL_HOME, EXPID, CONFIG, component) optionsdom = parse(optionsfile) # Open and parse options file for server info xmlfile = optionsdom.getElementsByTagName('cool:hasConfigFile')[0].childNodes[0].data xmldom = parse('%s/%s/config/Control/%s/Options/%s' % (COOL_HOME, EXPID, CONFIG, xmlfile)) servertags = xmldom.getElementsByTagName('server') for servertag in servertags: # Only looking for ET systems being created by this component if servertag.attributes['class'].value != 'Et' : continue if not servertag.hasAttribute('create') : continue if servertag.attributes['create'].value != 'true' : continue # Copy host into dictionary. # Use "localhost" if not in hosts file. ETInfo = {} ETInfo['component'] = component ETInfo['host'] = 'localhost' if component in hosts : ETInfo['host'] = hosts[component] # Copy all attributes into output dictionary for i in range(0, servertag.attributes.length): attr = servertag.attributes.item(i) name = attr.localName.encode('ascii','ignore') value = attr.nodeValue.encode('ascii','ignore') ETInfo[name] = value return ETInfo #------------------ # ReadConfiguration #------------------ def ReadConfiguration(config=''): global CONFIG, configDataValid if config != '' : SetCONFIG(config) GetComponents() GetHosts() configDataValid = True #----------------------------------------- # Try reading in configuration based on values from # environment. Quietly return if this fails for any reason # since the calling script may intend to set these values # explicitly. # Check that COOL_HOME,EXPID, and CONFIG are set if COOL_HOME!=None : try: GetEXPIDs() if EXPID!=None: GetConfigurations() # fill "configs" global if CONFIG == None : GetCODAconfig() if CONFIG != None : ReadConfiguration() except Exception as e: print(traceback.format_exc())