File: waitqueue.py

package info (click to toggle)
lqa 20191129~git41a4806-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 328 kB
  • sloc: python: 2,197; makefile: 5
file content (104 lines) | stat: -rw-r--r-- 3,766 bytes parent folder | download | duplicates (2)
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
###################################################################################
# LAVA QA tool
# Copyright (C) 2015 Collabora Ltd.

# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  US
###################################################################################

import time
from lqa_api.exit_codes import SUCCESS

# Default to a 3 hours timeout
WAIT_DEFAULT_TIMEOUT="3h"

class WaitQueue(list):
    """Wait queue for jobs. It is a subclass of the list object."""

    def __init__(self):
        # Default queue exit code is SUCCESS which means no job in the queue failed
        self._queue_exit_code = SUCCESS

    def addjob(self, job, add_cb=None):
        """Add job to the wait queue."""
        self.append(job)
        add_cb and add_cb(self, job)

    def removejob(self, job, remove_cb=None):
        """Remove job from the wait queue."""
        self.remove(job)
        # Update queue exit code
        self._update_exit_code(job)
        remove_cb and remove_cb(self, job)

    def has_jobs(self):
        """Check if there are pending jobs in the wait queue."""
        return len(self) > 0

    def wait(self, readable_timeout=WAIT_DEFAULT_TIMEOUT,
             wait_cb=None, remove_cb=None, timeout_cb=None):
        """Wait for the jobs on Submitted and Running state."""

        timeout = _convert_readable_timeout_to_seconds(readable_timeout)
        endtime = None
        # Negative value unset the timeout.
        if timeout >= 0:
            endtime = time.time() + timeout

        while True:
            for job in self[:]:
                if job.status in ['Submitted', 'Running']:
                    # Call the wait function (if specified).
                    wait_cb and wait_cb(self, job)
                else:
                    self.removejob(job, remove_cb)
            # Break if no more jobs to wait for.
            if not self.has_jobs(): 
                break
            # Exit with timeout of endtime.
            if endtime and time.time() > endtime:
                # Call the timeout function (if specified).
                timeout_cb and timeout_cb(self, timeout)
                break
            # Sleep for 30 seconds before polling again.
            time.sleep(30)

        # Return the queue.
        return self

    def _update_exit_code(self, job):
        """This function collates the queue exit code to the worst error code"""
        ec = job.exit_code
        if ec < self._queue_exit_code:
            self._queue_exit_code = ec

    @property
    def exit_code(self):
        return self._queue_exit_code

def _convert_readable_timeout_to_seconds(timeout):
    """
    Supported notations:
       <timeout>h = hours
       <timeout>m = minutes
       <timeout>s = seconds (default if not specified)
    """
    # 1 minute = 60 secs
    minute = 60
    hour = minute * minute
    return \
        timeout.endswith('h') and float(timeout[:-1]) * hour   or \
        timeout.endswith('m') and float(timeout[:-1]) * minute or \
        timeout.endswith('s') and float(timeout[:-1])          or \
        float(timeout)