File: dstat_condor_queue.py

package info (click to toggle)
dstat 0.7.4-6.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 1,608 kB
  • sloc: python: 5,964; makefile: 70; sh: 3
file content (134 lines) | stat: -rw-r--r-- 4,338 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
### Author: <krikava$gmail,com>

### 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 dstat_plugin(dstat):
    """
    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