source: trunk/src/PBSQuery.py @ 195

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

src/PBSQuery.py:

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