All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
batchstatus.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 ######################################################################
3 #
4 # Name: batchstatus.py
5 #
6 # Purpose: Python class BatchStatus (used by project.py script).
7 # This class contains information about batch system status
8 # corresponding to the specified project.
9 #
10 # Created: 12-Dec-2014 Herbert Greenlee
11 #
12 ######################################################################
13 
14 from __future__ import absolute_import
15 from __future__ import print_function
16 import sys
17 import project_utilities
18 import subprocess
19 from project_modules.jobsuberror import JobsubError
20 from larbatch_utilities import convert_str
21 
22 # Cache jobs list independent of project.
23 
24 jobs = None
25 
26 # Cache jobsub server.
27 
28 server = None
29 
30 # Batch status class.
31 
33 
34  # Constructor.
35 
36  def __init__(self, projects):
37 
38  # Initialize attributes.
39 
40  self.projects = projects
41 
42  # The status for each stage is a 4-tuple of integers consisting
43  # of the following values.
44  # 1. Number of idle batch jobs (state 'I')
45  # 2. Number of running batch jobs (state 'R')
46  # 3. Number of held batch jobs (state 'H')
47  # 4. Number of batch jobs in any other stage.
48 
49  self.stage_stats = {}
50  self.update(projects)
51 
52 
53  # Update data for the specified project.
54 
55  def update(self, projects):
56 
57  global jobs, server
58 
59  for project in projects:
60  if project.server != '-' and project.server != '':
61  server = project.server
62  for stage in project.stages:
63  self.stage_stats[stage.name] = [0, 0, 0, 0]
64 
65  # Get information from the batch system.
66 
67  if jobs == None:
68  BatchStatus.update_jobs()
69  for job in jobs:
70  words = job.split()
71  if len(words) > 4:
72  state = words[-4]
73  script = words[-1]
74 
75  # Loop over stages.
76 
77  for project in projects:
78  for stage in project.stages:
79  workscript = '%s-%s-%s.sh' % (stage.name, project.name, project.release_tag)
80  if script.find(workscript) == 0:
81  if state == 'I':
82  self.stage_stats[stage.name][0] = \
83  self.stage_stats[stage.name][0] + 1
84  elif state == 'R':
85  self.stage_stats[stage.name][1] = \
86  self.stage_stats[stage.name][1] + 1
87  elif state == 'H':
88  self.stage_stats[stage.name][2] = \
89  self.stage_stats[stage.name][2] + 1
90  else:
91  self.stage_stats[stage.name][3] = \
92  self.stage_stats[stage.name][3] + 1
93 
94  # Update jobs list.
95 
96  @staticmethod
97  def update_jobs():
98 
99  global jobs, server
100 
101  command = ['jobsub_q']
102  if server != None:
103  command.append('--jobsub-server=%s' % server)
104  command.append('--group=%s' % project_utilities.get_experiment())
105  command.append('--user=%s' % project_utilities.get_user())
106  command.append('--role=%s' % project_utilities.get_role())
107  jobinfo = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
108  jobout, joberr = jobinfo.communicate()
109  jobout = convert_str(jobout)
110  joberr = convert_str(joberr)
111  rc = jobinfo.poll()
112  if rc != 0:
113  #raise JobsubError(command, rc, jobout, joberr)
114  # Simply return in case jobsub_q fails.
115  return
116  jobs = jobout.split('\n')
117 
118  # Return jobs list.
119 
120  @staticmethod
121  def get_jobs():
122 
123  global jobs
124  return jobs
125 
126  # Get stage status for specified stage.
127  # Returns 4-tuple (# idle, # running, # held, # other).
128 
129  def get_stage_status(self, stagename):
130  return self.stage_stats[stagename]