### Author: ### Condor queue plugin ### Display information about jobs in queue (using condor_q(1)) ### ### WARNING: with many jobs in the queue, the condor_q might take quite ### some time to execute and use quite a bit of resources. Consider ### using a longer delay. import os import re global condor_classad class condor_classad: """ Utility class to work with Condor ClassAds """ global ATTR_VAR_PATTERN ATTR_VAR_PATTERN = re.compile(r'\$\((\w+)\)') def __init__(self, file=None, config=None): if file != None: self.attributes = condor_classad._read_from_file(file) elif config != None: self.attributes = condor_classad._parse(config) if self.attributes == None: raise Exception('condor_config must be initialized either using a file or config text') local_config_file = self['LOCAL_CONFIG_FILE'] if local_config_file != None: for k,v in condor_classad._read_from_file(local_config_file).items(): self.attributes[k] = v def __getitem__(self, name): if name in self.attributes: self._expand(name) return self.attributes[name] def _expand(self, var): if not var in self.attributes: return while True: m = ATTR_VAR_PATTERN.match(self.attributes[var]) if m == None: break var_name = m.group(1) self.attributes[var] = ATTR_VAR_PATTERN.sub(self.attributes[var_name], self.attributes[var]) @staticmethod def _parse(text): attributes = {} for l in [l for l in text.split('\n') if not l.strip().startswith('#')]: l = l.split('=') if len(l) <= 1 or len(l[0]) == 0: continue attributes[l[0].strip()] = ''.join(l[1:]).strip() return attributes @staticmethod def _read_from_file(filename): if not os.access(filename, os.R_OK): raise Exception('Unable to read file %s' % filename) try: f = open(filename) return condor_classad._parse((f.read())) finally: f.close() class dool_plugin(dool): """ Plugin for Condor queue stats """ global CONDOR_Q_STAT_PATTER CONDOR_Q_STAT_PATTER = re.compile(r'(\d+) jobs; (\d+) idle, (\d+) running, (\d+) held') def __init__(self): self.name = 'condor queue' self.vars = ('jobs', 'idle', 'running', 'held') self.type = 'd' self.width = 5 self.scale = 1 self.condor_config = None def check(self): config_file = os.environ['CONDOR_CONFIG'] if config_file == None: raise Exception('Environment varibale CONDOR_CONFIG is missing') self.condor_config = condor_classad(config_file) bin_dir = self.condor_config['BIN'] if bin_dir == None: raise Exception('Unable to find BIN directory in condor config file %s' % config_file) self.condor_status_cmd = os.path.join(bin_dir, 'condor_q') if not os.access(self.condor_status_cmd, os.X_OK): raise Exception('Needs %s in the path' % self.condor_status_cmd) else: try: p = os.popen(self.condor_status_cmd+' 2>&1 /dev/null') ret = p.close() if ret: raise Exception('Cannot interface with Condor - condor_q returned != 0?') except IOError: raise Exception('Unable to execute %s' % self.condor_status_cmd) return True def extract(self): last_line = None try: for repeats in range(3): for last_line in cmd_readlines(self.condor_status_cmd): pass m = CONDOR_Q_STAT_PATTER.match(last_line) if m == None: raise Exception('Invalid output from %s. Got: %s' % (cmd, last_line)) stats = [int(s.strip()) for s in m.groups()] for i,j in enumerate(self.vars): self.val[j] = stats[i] except Exception: for name in self.vars: self.val[name] = -1 # vim:ts=4:sw=4:et