Changeset 248
- Timestamp:
- 08/16/10 16:53:49 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/examples/new_rack_pbsmon.py
r239 r248 1 1 #! /usr/bin/env python 2 2 # 3 # pbsmon WJ104 3 # This version of pbsmon is base on the new_rack_pbsmon.py 4 # 5 # Authors: 6 # Bas van der Vlies 7 # Dennis Stam 4 8 # 5 # * added START_RACK BvdV 6 # * added Total, pbs_serial_free and pbs_parallel free, BvdV 9 # SVN Info: 10 # $Id$ 11 # $URL$ 7 12 # 8 # Hint: set ts=4 9 # 10 # SVN Info: 11 # $Id$ 12 # 13 import os 13 14 """ 15 Usage: pbsmon [hosts].... 16 17 Specifying hostnames: 18 To specify a range use the [] to indicate a range, a couple of examples: 19 20 The first five nodes of rack 16 21 - gb-r16n[1-5] 22 23 The first five nodes and node 12 and 18 of rack 16 to 20 24 - gb-r[16-20]n[1-5,12,18] 25 26 The first five nodes de in rack 16 with padding enabled 27 - gb-r[16]n[01-5] 28 29 The ranges ([]) are not only limited to numbers, letters can also be used. 30 """ 31 14 32 import sys 15 import string16 import getopt17 33 import re 34 import re 35 import types 36 from optparse import OptionParser 18 37 19 38 import pbs 20 39 from PBSQuery import PBSQuery 21 40 from PBSQuery import PBSError 41 42 # Remark: When both are True, extended view is being printed 43 PRINT_TABLE = True 44 PRINT_EXTENDED = False 45 46 # Which nodes must be skipped 47 EXCLUDE_NODES = [ 'login' ] 48 49 # Some global OPTS 50 OPT_SKIP_EMPTY_RACKS = True 51 OPT_SERVERNAME = None 52 53 ## Begin: TABLE view opts 22 54 23 55 # A node has the following syntax gb-r10n10 … … 27 59 # number of nodes and racks 28 60 # 29 NODE_EXPR = re.compile(r""" 30 (?P<racknr>r[0-9]+) 31 (?P<nodenr>n[0-9]+) 32 """, re.VERBOSE) 33 34 SKIP_CHARS_RACK = 1 35 SKIP_CHARS_NODE = 1 36 37 START_RACK = 1 38 39 pbs_ND_single = 'job (single)' 40 pbs_ND_total = 'total' 41 pbs_ND_free_serial = 'free serial' 42 pbs_ND_free_parallel = 'free parallel' 61 NODE_EXPR = "gb-r(?P<racknr>[0-9]+)n(?P<nodenr>[0-9]+)" 62 63 START_RACK = 1 64 65 ## End: TABLE view opts 66 67 ## Begin: EXTENDED view opts 68 69 LENGTH_NODE = 0 70 LENGTH_STATE = 0 71 72 EXTENDED_PATTERNS = { 73 'header' : ' %-*s | %-*s | %s', 74 'row': ' %-*s | %-*s | %s', 75 'line': ' %s', 76 'line_char': '-', 77 } 78 79 ## End: EXTENDED view opts 80 81 pbs_ND_single = 'job (single)' 82 pbs_ND_total = 'total' 83 pbs_ND_free_serial = 'free serial' 84 pbs_ND_free_parallel = 'free parallel' 43 85 44 86 PBS_STATES = { 45 pbs.ND_free: '_',46 pbs.ND_down: 'X',47 pbs.ND_offline: '.',48 pbs.ND_reserve: 'R',49 pbs.ND_job_exclusive: 'J',50 pbs.ND_job_sharing: 'S',51 pbs.ND_busy: '*',52 pbs.ND_state_unknown: '?',53 pbs.ND_timeshared: 'T',54 pbs.ND_cluster: 'C',55 pbs_ND_single: 'j',56 pbs_ND_free_serial: '_',57 pbs_ND_free_parallel: '_',58 pbs_ND_total: ' '87 pbs.ND_free : '_', 88 pbs.ND_down : 'X', 89 pbs.ND_offline : '.', 90 pbs.ND_reserve : 'R', 91 pbs.ND_job_exclusive : 'J', 92 pbs.ND_job_sharing : 'S', 93 pbs.ND_busy : '*', 94 pbs.ND_state_unknown : '?', 95 pbs.ND_timeshared : 'T', 96 pbs.ND_cluster : 'C', 97 pbs_ND_single : 'j', 98 pbs_ND_free_serial : '_', 99 pbs_ND_free_parallel : '_', 100 pbs_ND_total : ' ' 59 101 } 60 102 61 # command line options 62 OPT_NODESTATUS = 1 63 OPT_SUMMARY = 0 64 OPT_SERVERNAME = None 65 OPT_SKIP_EMPTY_RACKS = 1 66 67 68 def parse_hostname(id): 69 """ 70 Determiine the the limits of the cluster: 71 - How many racks are in the cluster 72 - What is the max amount of nodes per rack 73 """ 74 result = NODE_EXPR.search(id) 75 if result: 76 r = int(result.group('racknr')[SKIP_CHARS_RACK:]) 77 n = int(result.group('nodenr')[SKIP_CHARS_NODE:]) 78 79 return (r,n) 80 81 82 def pbsmon(server = None): 83 global PBS_STATES 84 85 try: 86 if not server: 87 p = PBSQuery() 88 else: 89 p = PBSQuery(server) 90 except PBSError, reason: 91 print 'error: %s' % reason 92 sys.exit(-1) 93 94 p.new_data_structure() 95 96 # get the state of the nodes 97 attr = [ 'state', 'jobs', 'properties' ] 98 99 try: 100 nodes = p.getnodes(attr) 101 except PBSError, reason: 102 print 'error: %s' % reason 103 sys.exit(-1) 104 105 node_dict = {} 106 107 number_of_racks = nodes_per_rack = 0 108 #determine_limits(nodes) 109 110 for id in nodes: 111 112 # Skip login nodes in status display 113 # 114 if not nodes[id].name.find('login'): 115 continue 116 117 if pbs.ND_down in nodes[id].state: 118 state = pbs.ND_down 119 else: 120 state = nodes[id].state[0] 121 122 state_char = PBS_STATES[state] 123 124 #print 'TD: ', nodes[id].name, nodes[id].is_free() ,nodes[id].has_job() 125 126 if nodes[id].is_free() and nodes[id].has_job(): # single job 127 #print 'TD: %s' % id, nodes[id] 128 state_char = PBS_STATES[pbs_ND_single] 129 130 #print 'TD: %s %s' % (id, state_char) 131 132 racknr, nodenr = parse_hostname(id) 133 134 if racknr > number_of_racks: 135 number_of_racks = racknr 136 137 if nodenr > nodes_per_rack: 138 nodes_per_rack = nodenr 139 140 try: 141 node_dict[racknr][nodenr] = state_char 142 except KeyError: 143 node_dict[racknr] = dict() 144 node_dict[racknr][nodenr] = state_char 145 146 147 # print header lines 148 save_column = None 149 print ' ', 150 for rack in xrange(START_RACK, number_of_racks + 1): 151 152 if not (rack % 10): 153 char = '%d' %(rack/10) 154 save_column = char 155 else: 156 char = ' ' 157 158 if OPT_SKIP_EMPTY_RACKS: 159 if node_dict.has_key(rack): 160 if save_column: 161 char = save_column 162 save_column = None 163 164 print char, 165 else: 166 print char, 167 print 168 169 print ' ', 170 for rack in xrange(START_RACK, number_of_racks + 1): 171 172 char = rack % 10 173 if OPT_SKIP_EMPTY_RACKS: 174 if node_dict.has_key(rack): 175 print char, 176 else: 177 print char, 178 print 179 180 181 for node_nr in xrange(1, nodes_per_rack + 1): 182 print '%2d' % node_nr, 183 184 for rack in xrange(START_RACK, number_of_racks + 1): 185 186 if OPT_SKIP_EMPTY_RACKS: 187 if not node_dict.has_key(rack): 188 continue 189 try: 190 print node_dict[rack][node_nr], 191 except KeyError: 192 print ' ', 193 print 194 103 ###### Some Useful Class ################## 195 104 # 196 # summary() counts the number of nodes in a particular state 105 # Author: Dennis Stam 106 # Date : 09-04-2009 107 # Desc. : This class allows you use ranges within the given arguments. Very 108 # useful for specifying mutliple hosts. This class extends the 109 # OptionParser class. 197 110 # 198 def pbsmon_summary(server = None): 199 global PBS_STATES 200 201 try: 202 if not server: 203 p = PBSQuery() 204 else: 205 p = PBSQuery(server) 206 except PBSQuery.PBSError, reason: 207 print 'error: %s' % reason 208 sys.exit(-1) 209 210 # get the state of the nodes 211 attr = [ 'state', 'jobs', 'properties' ] 212 try: 213 nodes = p.getnodes(attr) 214 except PBSError, reason: 215 print 'error: %s' % reason 216 sys.exit(-1) 217 218 node_dict = {} 219 220 count_states = {} 221 for key in PBS_STATES.keys(): 222 count_states[key] = 0 223 224 for nodename, node in nodes.items(): 225 226 # Skip login nodes in status display 227 # 228 if not nodename.find('login'): 229 continue 230 231 # A node can have multiple states 232 state = node['state'][0] 233 234 state_char = PBS_STATES[state] 235 count_states[state] += 1 236 count_states[pbs_ND_total] += 1 237 238 if node.is_free(): # can happen for single CPU jobs 239 if node.has_job(): 240 # print 'TD: %s' % nodename, node 241 state_char = PBS_STATES[pbs_ND_single] 242 count_states[pbs.ND_free] -= 1 243 count_states[pbs_ND_single] += 1 244 else: 245 if 'infiniband' in node['properties']: 246 count_states[pbs_ND_free_parallel] += 1 247 elif 'gigabit' in node['properties']: 248 count_states[pbs_ND_free_serial] += 1 249 #else: 250 # count_states[pbs_ND_free_serial] += 1 251 252 # print 'TD: %s %s' % (nodename, state_char) 253 dummy = string.split(nodename, '-') 254 node_dict[dummy[1]] = state_char 255 256 legend = PBS_STATES.keys() 257 legend.sort() 258 259 n = 0 260 for state in legend: 261 print ' %s %-13s : %-5d' % (PBS_STATES[state], state, count_states[state]), 262 263 n = n + 1 264 if not (n & 1): 265 print 266 267 268 def pbsmon_legend(): 269 global PBS_STATES 270 271 legend = PBS_STATES.keys() 272 legend.sort() 273 274 n = 0 275 for state in legend: 276 if state == 'total': 277 continue 278 279 print ' %s %-20s' % (PBS_STATES[state], state), 280 281 n = n + 1 282 if not (n & 1): 283 print 284 285 286 def usage(): 287 global PROGNAME 288 289 print 'usage: %s [options]' % PROGNAME 290 print '%s displays the status of the nodes in the batch system' % PROGNAME 291 print 292 print 'Options:' 293 print ' -h, --help Show this information' 294 print ' -s, --summary Display only a short summary' 295 print ' -a, --all Display both status and summary' 296 print ' -w, --wide Wide display for node status' 297 print ' -S, --server=<server> Use a different PBS/Torque server' 298 print 299 print 'Legend:' 300 301 pbsmon_legend() 302 303 304 def getopts(): 305 global PROGNAME, OPT_NODESTATUS, OPT_SUMMARY, OPT_SKIP_EMPTY_RACKS, OPT_SERVERNAME 306 307 if len(sys.argv) <= 1: 308 return 309 310 try: 311 opts, args = getopt.getopt(sys.argv[1:], 'hsawS:', ['help','summary', 'all', 'wide', 'server=']) 312 except getopt.error, reason: 313 print '%s: %s' % (PROGNAME, reason) 314 usage() 315 sys.exit(1) 316 317 except getopt.GetoptError, reason: 318 print '%s: %s' % (PROGNAME, reason) 319 usage() 320 sys.exit(1) 321 322 except: 323 usage() 324 sys.exit(1) 325 326 server = None 327 errors = 0 328 329 for opt, arg in opts: 330 if opt in ('-h', '--help', '-?'): 331 usage() 332 sys.exit(1) 333 334 if opt in ('-s', '--summary'): 335 OPT_SUMMARY = 1 336 OPT_NODESTATUS = 0 337 continue 338 339 if opt in ('-a', '--all'): 340 OPT_SUMMARY = 1 341 OPT_NODESTATUS = 1 342 continue 343 344 if opt in ('-w', '--wide'): 345 OPT_SKIP_EMPTY_RACKS = 0 346 continue 347 348 if opt in ('-S', '--server'): 349 OPT_SERVERNAME = arg 350 continue 351 352 print "%s: unknown command line option '%s'" % (PROGNAME, opt) 353 errors = errors + 1 354 355 if errors: 356 usage() 357 sys.exit(1) 358 111 # SVN Info: 112 # $Id$ 113 # 114 115 class AdvancedParser(OptionParser): 116 """ 117 This class extends from OptionParser, where the method check_values has been 118 overrided. 119 120 In this function a extra parsing is done on the the rest of the arguments. This 121 extra parsing is the creating of multiple hostnames from a pattern/range. 122 123 When a user specifies this argument dr-r[15,17-20]n[1-5,10] then this class 124 returns 24 hosts. Besides using numbers you can also specify lower cased 125 letters from a-z. 126 127 Doctest: 128 >>> parser = AdvancedParser() 129 >>> parser.return_range('12-15,20') 130 [12, 13, 14, 15, '20'] 131 132 >>> option, args = parser.parse_args(['dr-r7n[1-5]']) 133 >>> print args 134 ['dr-r7n1', 'dr-r7n2', 'dr-r7n3', 'dr-r7n4', 'dr-r7n5'] 135 """ 136 137 def return_range(self, string): 138 """ 139 This method uses the given numbers and converts them to ranges. When 140 ower cased letters are specified they will be converted to integer 141 ordinal of a one-character string. 142 (ie. a = 97, z = 122) 143 144 The ranges will be return as lists 145 """ 146 parts = string.split( ',' ) 147 numbers_chars = list() 148 equal_width_length = 0 149 150 for part in parts: 151 part_range = part.split( '-' ) 152 if len( part_range ) == 2: 153 try: 154 if part_range[0][0] == '0' or part_range[1][0] == '0': 155 if len( part_range[0] ) > len( part_range[1] ): 156 equal_width_length = len( part_range[0] ) 157 else: 158 equal_width_length = len( part_range[1] ) 159 160 numbers_chars += range( int( part_range[0] ), int( part_range[1] ) + 1 ) 161 except ValueError: 162 begin = ord( part_range[0] ) 163 end = ord( part_range[1] ) 164 tmplist = list() 165 166 if begin > 96 and end < 123: 167 tmplist = range( begin, end + 1) 168 169 for letter in tmplist: 170 numbers_chars.append( chr( letter ) ) 171 else: 172 if equal_width_length != 0 and len( part ) > equal_width_length: 173 equal_width_length = len( part ) 174 175 numbers_chars.append( part ) 176 177 if equal_width_length > 0: 178 tmplist = list() 179 180 for number_char in numbers_chars: 181 try: 182 nnum = int( number_char ) 183 tmplist.append( '%0*d' % (equal_width_length, nnum) ) 184 except ValueError: 185 tmplist.append( number_char ) 186 187 numbers_chars = tmplist 188 189 return numbers_chars 190 191 def combine( self, pre, post): 192 ''' 193 This method is used to combine a possibility of a combination 194 ''' 195 if pre == '': 196 return post 197 else: 198 return '%s %s' % (pre, post) 199 200 def combinations( self, listin, prefix=''): 201 ''' 202 This method creates from the given ranges all possible combinations 203 ''' 204 outlist = list() 205 206 if len( listin ) > 1: 207 for item in listin[0]: 208 outlist += self.combinations( listin[1:], self.combine( prefix, str( item ) ) ) 209 else: 210 for item in listin[0]: 211 outlist.append( tuple( self.combine( prefix, str( item ) ).split( ' ') ) ) 212 213 return outlist 214 215 def args_parser(self, args): 216 ''' 217 This method checks all given extra arguments for the given ranges between the 218 [ and ] 219 ''' 220 findregex = re.compile( r'\[([0-9a-z\-,]+)\]', re.VERBOSE ) 221 nodenames = list() 222 223 for arg in args: 224 found = findregex.findall( arg ) 225 ranges = list() 226 227 if found: 228 pattern = findregex.sub( '%s', arg ) 229 230 for part in found: 231 ranges.append( self.return_range( part ) ) 232 233 combs = self.combinations( ranges ) 234 235 for comb in combs: 236 # Here the %s in the pattern are 237 # replaced by the correct value 238 nodenames.append( pattern % comb ) 239 else: 240 nodenames.append( arg ) 241 242 return nodenames 243 244 def check_values(self, values, args): 245 ''' 246 Here we override the default method in OptionParser to 247 enable our extra parsing on the given Arguments 248 ''' 249 return values, self.args_parser( args ) 250 251 #### End Useful Class ##### 252 253 def sanitize_jobs( jobs ): 254 255 ljobs = list() 256 257 for job in jobs: 258 ljobs.extend( re.findall( r'[0-9]+\/([0-9]+)\.*.', job ) ) 259 260 return list( set( ljobs ) ) 261 262 def parse_nodename( nodename ): 263 global NODE_EXPR 264 265 parts = re.search( r'%s' % NODE_EXPR, nodename, re.VERBOSE ) 266 267 try: 268 racknr = parts.group( 'racknr' ) 269 except Exception: 270 racknr = 0 271 272 try: 273 nodenr = parts.group( 'nodenr' ) 274 except Exception: 275 nodenr = 0 276 277 return int( racknr ), int( nodenr ) 278 279 def get_nodes( racknode=False, hosts=None ): 280 global LENGTH_NODE 281 global LENGTH_STATE 282 global OPT_SERVERNAME 283 284 nodes_dict = dict() 285 286 try: 287 if not OPT_SERVERNAME: 288 p = PBSQuery() 289 else: 290 p = PBSQuery( OPT_SERVERNAME ) 291 except PBSError, reason: 292 print 'Error: %s' % reason 293 sys.exit( -1 ) 294 295 p.new_data_structure() 296 297 attr = [ 'state', 'jobs', 'properties' ] 298 299 try: 300 nodes = p.getnodes( attr ) 301 except PBSError, reason: 302 print 'Error: %s' % reason 303 sys.exit( -1 ) 304 305 number_of_racks = 0 306 nodes_per_rack = 0 307 hosts_list = list() 308 309 for node, attr in nodes.items(): 310 if node in EXCLUDE_NODES: 311 continue 312 313 if hosts and node not in hosts: 314 continue 315 316 if pbs.ND_down in attr.state: 317 state = pbs.ND_down 318 else: 319 state = attr.state[ 0 ] 320 321 state_char = PBS_STATES[ state ] 322 323 if attr.is_free() and attr.has_job(): 324 state = pbs.ND_busy 325 state_char = PBS_STATES[ pbs_ND_single ] 326 327 if not nodes_dict.has_key( node ): 328 nodes_dict[ node ] = dict() 329 330 # Setting the longest lenght 331 if len( node ) > LENGTH_NODE: 332 LENGTH_NODE = len( node ) 333 334 if len( state ) > LENGTH_STATE: 335 LENGTH_STATE = len( state ) 336 337 if racknode: 338 racknr, nodenr = parse_nodename( node ) 339 340 if racknr > number_of_racks: 341 number_of_racks = racknr 342 343 if nodenr > nodes_per_rack: 344 nodes_per_rack = nodenr 345 346 if not nodes_dict.has_key( racknr ): 347 nodes_dict[ racknr ] = dict() 348 349 if not nodes_dict[ racknr ].has_key( nodenr ): 350 nodes_dict[ racknr ][ nodenr ] = dict() 351 352 nodes_dict[ racknr ][ nodenr ][ 'state_char' ] = state_char 353 nodes_dict[ racknr ][ nodenr ][ 'state' ] = state 354 355 if attr.has_key( 'jobs' ): 356 nodes_dict[ racknr ][ nodenr ][ 'jobs' ] = sanitize_jobs( attr.jobs ) 357 else: 358 nodes_dict[ racknr ][ nodenr ][ 'jobs' ] = [] 359 else: 360 hosts_list.append( node ) 361 nodes_dict[ node ][ 'state_char' ] = state_char 362 nodes_dict[ node ][ 'state' ] = state 363 364 if attr.has_key( 'jobs' ): 365 nodes_dict[ node ][ 'jobs' ] = sanitize_jobs( attr.jobs ) 366 else: 367 nodes_dict[ node ][ 'jobs' ] = [] 368 369 if not racknode: 370 return nodes_dict, hosts_list 371 372 return nodes_dict, number_of_racks, nodes_per_rack 373 374 def _generate_index( str ): 375 index = [] 376 377 def _append( fragment, alist=index ): 378 if fragment.isdigit(): 379 fragment = int( fragment ) 380 alist.append( fragment ) 381 382 prev_isdigit = str[0].isdigit() 383 current_fragment = '' 384 385 for char in str: 386 curr_isdigit = char.isdigit() 387 388 if curr_isdigit == prev_isdigit: 389 current_fragment += char 390 else: 391 _append( current_fragment ) 392 current_fragment = char 393 prev_isdigit = curr_isdigit 394 395 _append( current_fragment ) 396 397 return tuple( index ) 398 399 def real_sort( inlist ): 400 indices = map(_generate_index, inlist ) 401 decorated = zip( indices, inlist ) 402 decorated.sort() 403 404 return [ item for index, item in decorated ] 405 406 def print_table(): 407 global START_RACK 408 global OPT_SKIP_EMPTY_RACKS 409 410 nodes, racknr, nodenr = get_nodes( True ) 411 412 ## Code herebelow has been taken from the new_rack_pbsmon.py 413 save_column = None 414 415 print 416 print ' ', 417 for rack in xrange( START_RACK, racknr + 1 ): 418 419 if not ( rack % 10 ): 420 char = '%d' % ( rack / 10 ) 421 save_column = char 422 else: 423 char = ' ' 424 425 if OPT_SKIP_EMPTY_RACKS: 426 if nodes.has_key( rack ): 427 if save_column: 428 char = save_column 429 save_column = None 430 print char, 431 else: 432 print char, 433 print 434 435 print ' ', 436 for rack in xrange( START_RACK, racknr + 1 ): 437 438 char = rack % 10 439 if OPT_SKIP_EMPTY_RACKS: 440 if nodes.has_key( rack ): 441 print char, 442 else: 443 print char, 444 print 445 446 for node in xrange( 1, nodenr + 1 ): 447 print '%2d' % node, 448 449 for rack in xrange( START_RACK, racknr + 1 ): 450 if OPT_SKIP_EMPTY_RACKS: 451 if not nodes.has_key( rack ): 452 continue 453 try: 454 print nodes[ rack ][ node ][ 'state_char' ], 455 except KeyError: 456 print ' ', 457 print 458 print 459 460 def print_table_summary(): 461 global PBS_STATES 462 global OPT_SERVERNAME 463 464 try: 465 if not OPT_SERVERNAME: 466 p = PBSQuery() 467 else: 468 p = PBSQuery( OPT_SERVERNAME ) 469 except PBSError, reason: 470 print 'error: %s' % reason 471 sys.exit(-1) 472 473 # get the state of the nodes 474 attr = [ 'state', 'jobs', 'properties' ] 475 try: 476 nodes = p.getnodes(attr) 477 except PBSError, reason: 478 print 'error: %s' % reason 479 sys.exit(-1) 480 481 node_dict = {} 482 483 count_states = {} 484 for key in PBS_STATES.keys(): 485 count_states[key] = 0 486 487 for nodename, node in nodes.items(): 488 489 # Skip login nodes in status display 490 # 491 if not nodename.find('login'): 492 continue 493 494 state = node['state'][ 0 ] 495 496 state_char = PBS_STATES[state] 497 count_states[state] += 1 498 count_states[pbs_ND_total] += 1 499 500 if node.is_free(): # can happen for single CPU jobs 501 if node.has_job(): 502 # print 'TD: %s' % nodename, node 503 state_char = PBS_STATES[pbs_ND_single] 504 count_states[pbs.ND_free] -= 1 505 count_states[pbs_ND_single] += 1 506 else: 507 if 'infiniband' in node['properties']: 508 count_states[pbs_ND_free_parallel] += 1 509 elif 'ifiniband' in node['properties']: 510 count_states[pbs_ND_free_serial] += 1 511 #else: 512 # count_states[pbs_ND_free_serial] += 1 513 514 # print 'TD: %s %s' % (nodename, state_char) 515 dummy = nodename.split('-') 516 if len( dummy ) > 1: 517 node_dict[dummy[1]] = state_char 518 else: 519 node_dict[dummy[0]] = state_char 520 521 legend = PBS_STATES.keys() 522 legend.sort() 523 524 n = 0 525 for state in legend: 526 print ' %s %-13s : %-5d' % (PBS_STATES[state], state, count_states[state]), 527 528 n = n + 1 529 if not (n & 1): 530 print 531 532 def print_extended( hosts=None ): 533 global LENGTH_NODE 534 global LENGTH_STATE 535 global EXTENDED_PATTERNS 536 537 nodes, ihosts = get_nodes( hosts=hosts ) 538 row_header = EXTENDED_PATTERNS[ 'header' ] % ( ( LENGTH_NODE + 2 ), 'Node', ( LENGTH_STATE + 2 ), 'State', 'Jobs' ) 539 LENGTH_ROW = len( row_header ) 540 541 rows_str = list() 542 ihosts = real_sort( ihosts ) 543 544 for node in ihosts: 545 attr = nodes[ node ] 546 row_str = EXTENDED_PATTERNS[ 'row' ] % ( ( LENGTH_NODE + 2 ), node, ( LENGTH_STATE + 2 ), attr[ 'state' ], ','.join( attr[ 'jobs' ] ) ) 547 548 if len( row_str ) > LENGTH_ROW: 549 LENGTH_ROW = len( row_str ) 550 551 rows_str.append( row_str ) 552 553 print 554 print row_header 555 print EXTENDED_PATTERNS[ 'line' ] % ( EXTENDED_PATTERNS[ 'line_char' ] * LENGTH_ROW ) 556 print '\n'.join( rows_str ) 557 print 359 558 360 559 if __name__ == '__main__': 361 PROGNAME = os.path.basename(sys.argv[0]) 362 getopts() 363 364 if OPT_NODESTATUS: 365 pbsmon(OPT_SERVERNAME) 366 367 if OPT_SUMMARY: 368 print 'Summary:' 369 pbsmon_summary(OPT_SERVERNAME) 370 371 sys.exit(0) 372 373 # EOB 374 560 561 parser = AdvancedParser(usage=__doc__) 562 563 parser.add_option( "-t", "--table", dest="table", action="store_true", help="Show an table" ) 564 parser.add_option( "-l", "--list", dest="extended", action="store_true", help="Show node rows with state and jobinfo" ) 565 parser.add_option( "-s", "--summary", dest="summary", action="store_true", help="Display a short summary" ) 566 parser.add_option( "-w", "--wide", dest="wide", action="store_true", help="Wide display for node status ( only when -t is used )" ) 567 parser.add_option( "-S", "--servername", dest="servername", help="Change the default servername" ) 568 569 parser.set_defaults( table=PRINT_TABLE ) 570 parser.set_defaults( summary=False ) 571 parser.set_defaults( extended=PRINT_EXTENDED ) 572 parser.set_defaults( servername=None ) 573 574 ( options, args ) = parser.parse_args() 575 576 if options.servername: 577 OPT_SERVERNAME = options.servername 578 579 if options.wide: 580 OPT_SKIP_EMPTY_RACKS = False 581 582 if args: 583 options.extended = True 584 585 if options.extended and PRINT_TABLE: 586 options.table = False 587 588 if options.table and PRINT_EXTENDED: 589 options.extended = False 590 591 if options.extended: 592 print_extended( args ) 593 elif options.table: 594 print_table() 595 else: 596 print 'Something is wrong, bye!' 597 sys.exit( -1 ) 598 599 if options.summary: 600 print_table_summary()
Note: See TracChangeset
for help on using the changeset viewer.