source: trunk/src/PBSQuery.py @ 192

Last change on this file since 192 was 192, checked in by bas, 15 years ago

src/PBSQuery.py:

  • fixed an error in the new data structure
  • Property svn:keywords set to Id
File size: 9.9 KB
Line 
1#
2# Authors: Roy Dragseth (roy.dragseth@cc.uit.no)
3#          Bas van der Vlies (basv@sara.nl)
4#
5# SVN INFO:
6#       $Id: PBSQuery.py 192 2009-05-14 14:22:27Z bas $
7#
8"""
9Usage: from PBSQuery import PBSQuery
10
11This class gets the info from the pbs_server via the pbs.py module
12for the several batch objects. All get..() functions return an dictionary
13with id as key and batch object as value
14
15There are four batch objects:
16 - server
17 - queue
18 - job
19 - node
20
21Each object can be handled as an dictionary and has several member
22functions. The second parameter is an python list and can be used if you
23are only interested in certain resources, see example
24
25There are the following functions for PBSQuery:
26  job -
27        getjob(job_id, attributes=<default is all>)
28        getjobs(attributes=<default is all>)
29 
30  node -
31        getnode(node_id, attributes=<default is all>)
32        getnodes(attributes=<default is all>)
33
34  queue -
35        getqueue(queue_id, attributes=<default is all>)
36        getqueues(attributes=<default is all>)
37
38  server -
39        get_serverinfo(attributes=<default is all>)
40
41Here is an example how to use the module:
42        from PBSQuery import PBSQuery
43        p = PBSQuery()
44        nodes = p.getnodes()
45        for name,node in nodes.items():
46            print name
47            if node.is_free():
48               print node, node['state']
49
50        l = [ 'state', 'np' ]
51        nodes = p.getnodes(l)
52        for name,node in nodes.items():
53               print node, node['state']
54
55The parameter 'attributes' is an python list of resources that
56you are interested in, eg: only show state of nodes
57        l = list()
58        l.append('state')
59        nodes = p.getnodes(l)
60"""
61import pbs
62import UserDict
63import string
64import sys
65import re
66
67class PBSError(Exception):
68        def __init__(self, msg=''):
69                self.msg = msg
70                Exception.__init__(self, msg)
71               
72        def __repr__(self):
73                return self.msg
74
75        __str__ = __repr__
76
77
78class PBSQuery:
79
80        # a[key] = value, key and value are data type string
81        #
82        OLD_DATA_STRUCTURE = True
83
84        def __init__(self, server=None):
85                if not server:
86                        self.server = pbs.pbs_default()
87                else:
88                        self.server = server
89
90        def _connect(self):
91                """Connect to the PBS/Torque server"""
92                self.con = pbs.pbs_connect(self.server)
93                if self.con < 0:
94                        str = "Could not make a connection with %s\n" %(self.server)
95                        raise PBSError(str)
96
97        def _disconnect(self):
98                """Close the PBS/Torque connection"""
99                pbs.pbs_disconnect(self.con)
100                self.attribs = 'NULL'
101
102        def _list_2_attrib(self, list):
103                """Convert a python list to an attrib list suitable for pbs"""
104                self.attribs = pbs.new_attrl( len(list) )
105                i = 0 
106                for attrib in list:
107                        # So we can user Resource
108                        attrib = attrib.split('.')
109                        self.attribs[i].name = attrib[0]
110                        i = i + 1
111
112        def _pbsstr_2_list(self, str, delimiter):
113                """Convert a string to a python list and use delimiter as spit char"""
114                l = sting.splitfields(str, delimiter)
115                if len(l) > 1:
116                        return l
117
118        def _list_2_dict(self, l, class_func):
119                """
120                Convert a pbsstat function list to a class dictionary, The
121                data structure depends on the function new_data_structure().
122               
123                Default data structure is:
124                        class[key] = value, Where key and value are of type string
125
126                Future release, can be set by new_data_structure():
127                        - class[key] = value where value can be:
128                          1. a list of values of type string
129                          2. a dictionary with as list of values of type string. If
130                             values contain a '=' character
131
132                          eg:
133                            print node['np']
134                                >> [ '2' ]
135
136                                print node['status']['arch']
137                                >> [ 'x86_64' ]
138                """
139                self.d = {}
140                for item in l:
141                        new = class_func()
142
143                        self.d[item.name] = new
144                       
145                        new.name = item.name
146
147                        for a in item.attribs:
148
149                                if a.resource:
150                                        key = '%s.%s' %(a.name, a.resource)
151                                else:
152                                        key = a.name
153
154                                if self.OLD_DATA_STRUCTURE:
155                                        new[key] = a.value
156                                else:
157                                        values = string.split(a.value, ',') 
158                                       
159                                        if len(values) == 1:
160                                                # simple form
161                                                # print 'simple %s =  %s' %(key, values[0])
162                                                #
163                                                new[key] = values
164
165                                        else:
166                                                # list check
167                                                list_or_dict = string.split(a.value, '=')
168
169
170                                                if len(list_or_dict) == 1:
171                                                        # This is a list
172                                                        # print 'list %s = %s' %(key, values)
173                                                        #
174                                                        new[key] = values
175
176                                                else:
177                                                        # This is dictionary
178                                                        # print 'dict %s = %s' %(key, values)
179                                                        #
180                                                        new[key] = dict()
181                                                        for v in values:
182                                                                # First argument is the key and the rest is the value
183                                                                # - value can contain a '='
184                                                                #
185                                                                tmp = v.split('=')
186                                                                new[key][ tmp[0] ] =  tmp[1:] 
187                                               
188                self._free(l)
189               
190        def _free(self, memory):
191                """
192                freeing up used memmory
193
194                """
195                pbs.pbs_statfree(memory)
196
197        def _statserver(self, attrib_list=None):
198                """Get the server config from the pbs server"""
199                if attrib_list:
200                        self._list_2_attrib(attrib_list)
201                else:
202                        self.attribs = 'NULL' 
203                       
204                self._connect()
205                serverinfo = pbs.pbs_statserver(self.con, self.attribs, 'NULL')
206                self._disconnect() 
207               
208                self._list_2_dict(serverinfo, server)
209
210        def get_serverinfo(self, attrib_list=None):
211                self._statserver(attrib_list)
212                return self.d
213
214        def _statqueue(self, queue_name='', attrib_list=None):
215                """Get the queue config from the pbs server"""
216                if attrib_list:
217                        self._list_2_attrib(attrib_list)
218                else:
219                        self.attribs = 'NULL' 
220                       
221                self._connect()
222                queues = pbs.pbs_statque(self.con, queue_name, self.attribs, 'NULL')
223                self._disconnect() 
224               
225                self._list_2_dict(queues, queue)
226
227        def getqueue(self, name, attrib_list=None):
228                self._statqueue(name, attrib_list)
229                try:
230                        return self.d[name]
231                except KeyError, detail:
232                        return self.d
233       
234        def getqueues(self, attrib_list=None):
235                self._statqueue('', attrib_list)
236                return self.d
237
238        def _statnode(self, select='', attrib_list=None, property=None):
239                """Get the node config from the pbs server"""
240                if attrib_list:
241                        self._list_2_attrib(attrib_list)
242                else:
243                        self.attribs = 'NULL' 
244                       
245                if property:
246                        select = ':%s' %(property)
247
248                self._connect()
249                nodes = pbs.pbs_statnode(self.con, select, self.attribs, 'NULL')
250                self._disconnect() 
251               
252                self._list_2_dict(nodes, node)
253
254        def getnode(self, name, attrib_list=None):
255                self._statnode(name, attrib_list)
256                try:
257                        return self.d[name]
258                except KeyError, detail:
259                        return self.d
260       
261        def getnodes(self, attrib_list=None):
262                self._statnode('', attrib_list)
263                return self.d
264
265        def getnodes_with_property(self, property, attrib_list=None):
266                self._statnode('', attrib_list, property)
267                return self.d
268
269        def _statjob(self, job_name='', attrib_list=None):
270                """Get the job config from the pbs server"""
271                if attrib_list:
272                        self._list_2_attrib(attrib_list)
273                else:
274                        self.attribs = 'NULL' 
275                       
276                self._connect()
277                jobs = pbs.pbs_statjob(self.con, job_name, self.attribs, 'NULL')
278                self._disconnect() 
279               
280                self._list_2_dict(jobs, job)
281
282        def getjob(self, name, attrib_list=None):
283                # To make sure we use the full name of a job; Changes a name
284                # like 1234567 into 1234567.server.name
285                name = name.split('.')[0] + "." + self.get_server_name()
286
287                self._statjob(name, attrib_list)
288                try:
289                        return self.d[name]
290                except KeyError, detail:
291                        return self.d
292       
293        def getjobs(self, attrib_list=None):
294                self._statjob('', attrib_list)
295                return self.d
296
297        def get_server_name(self):
298                return self.server
299
300        def new_data_structure(self): 
301                """
302                Use new data structure, will be standard in future release
303                """
304                self.OLD_DATA_STRUCTURE = False
305
306class _PBSobject(UserDict.UserDict):
307        TRUE  = 1
308        FALSE = 0
309
310        def __init__(self):
311                UserDict.UserDict.__init__(self)
312                self.name = None
313
314        def get_value(self, key):
315                if self.has_key(key):
316                        return self[key]
317                else:
318                        return None
319
320        def __repr__(self):
321                return repr(self.data)
322
323        def __str__(self):
324                return str(self.data)
325
326        def __getattr__(self, name):
327                try:
328                        return self.data[name]
329                except KeyError:
330                        error = 'invalid attribute %s' %(name)
331                        raise PBSError(error)
332
333        def __iter__(self):
334                return iter(self.data.keys())
335
336        def uniq(self, list):
337                """Filter out unique items of a list"""
338                uniq_items = {}
339                for item in list:
340                        uniq_items[item] = 1
341                return uniq_items.keys()
342
343class job(_PBSobject):
344        """PBS job class""" 
345        def is_running(self):
346                if self.get_value('job_state') == 'Q':
347                        return self.FALSE
348                else:
349                        return self.TRUE
350
351        def get_nodes(self, unique=None):
352                """Returns a list of the nodes which run this job"""
353                nodes = self.get_value('exec_host')
354                if nodes:
355                        nodelist = string.split(nodes,'+')
356                        if not unique:
357                                return nodelist
358                        else:
359                                return self.uniq(nodelist)
360                return list()
361
362
363class node(_PBSobject):
364        """PBS node class"""
365       
366        def is_free(self):
367                """Check if node is free"""
368                if self.get_value('state') == 'free':
369                        return self.TRUE
370                else: 
371                        return self.FALSE
372
373        def has_job(self):
374                """Does the node run a job"""
375                if self.get_value('jobs'):
376                        return self.TRUE
377                else:
378                        return self.FALSE
379       
380        def get_jobs(self, unique=None):
381                """Returns a list of the currently running job-id('s) on the node"""
382                jobstring = self.get_value('jobs')
383                if jobstring:
384                        joblist = re.compile('[^\\ /]\\d+[^/.]').findall( jobstring )
385                        if not unique:
386                                return joblist
387                        else:
388                                return self.uniq(joblist)
389                return list()
390
391
392class queue(_PBSobject):
393        """PBS queue class"""
394        def is_enabled(self):
395                if self.get_value('enabled') == 'True':
396                        return self.TRUE
397                else:
398                        return self.FALSE
399
400        def is_execution(self):
401                if self.get_value('queue_type') == 'Execution':
402                        return self.TRUE
403                else:
404                        return self.FALSE
405
406class server(_PBSobject):
407        """PBS server class"""
408
409        def get_version(self):
410                return self.get_value('pbs_version')
411
412def main():
413        p = PBSQuery() 
414        serverinfo = p.get_serverinfo()
415        for server in serverinfo.keys():
416                print server, ' version: ', serverinfo[server].get_version()
417        for resource in serverinfo[server].keys():
418                print '\t ', resource, ' = ', serverinfo[server][resource]
419
420        queues = p.getqueues()
421        for queue in queues.keys():
422                print queue
423                if queues[queue].is_execution():
424                        print '\t ', queues[queue]
425                if queues[queue].has_key('acl_groups'):
426                        print '\t acl_groups: yes'
427                else:
428                        print '\t acl_groups: no'
429
430        jobs = p.getjobs()
431        for name,job in jobs.items():
432                if job.is_running():
433                        print job
434
435        l = ['state']
436        nodes = p.getnodes(l)
437        for name,node in nodes.items():
438                if node.is_free(): 
439                        print node
440
441if __name__ == "__main__":
442        main()
Note: See TracBrowser for help on using the repository browser.