~ursinha/ubuntu-ci-services-itself/enable-get-private-data

« back to all changes in this revision

Viewing changes to test_runner/tstrun/run_worker.py

  • Committer: Ursula Junque (Ursinha)
  • Date: 2014-03-12 20:13:05 UTC
  • mfrom: (363.2.6 ubuntu-ci-services-itself)
  • Revision ID: ursinha@canonical.com-20140312201305-fkkuo2600x4x272y
Merging trunk. No conflicts \o/

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# You should have received a copy of the GNU Affero General Public License
15
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
 
import json
18
 
import logging
19
 
 
20
 
from ci_utils import amqp_utils
21
 
from ci_utils import dump_stack
22
 
from ci_utils import data_store
 
17
from ci_utils import (
 
18
    amqp_utils,
 
19
    amqp_worker,
 
20
)
23
21
import tstrun
24
22
from tstrun import testbed
25
23
 
26
 
logging.basicConfig(level=logging.INFO)
27
 
log = logging.getLogger(__name__)
28
 
 
29
 
 
30
 
def on_message(msg):
31
 
    log.info('on_message: %s', msg.body)
32
 
    params = json.loads(msg.body)
33
 
    ticket = params['ticket_id']
34
 
    progress_queue = params['progress_trigger']
35
 
    image_id = params['image_id']
36
 
    package_list = params['package_list']
37
 
    amqp_utils.progress_update(progress_queue, params)
38
 
 
39
 
    conf = tstrun.get_auth_config()
40
 
 
41
 
    def status_cb(msg):
42
 
        amqp_utils.progress_update(progress_queue, {'message': msg})
43
 
 
44
 
    # The tests will succeed unless they fail ;)
45
 
    notify = amqp_utils.progress_completed
46
 
    results = {
47
 
        'artifacts': [],
48
 
    }
49
 
    try:
 
24
 
 
25
class TestRunnerWorker(amqp_worker.AMQPWorker):
 
26
    def __init__(self):
 
27
        super(TestRunnerWorker, self).__init__('test_runner')
 
28
 
 
29
    def save_subunit(self, log, params, package, stream, retval):
 
30
        # make this exception-safe since we can already report pass/fail
 
31
        # with or without this file
 
32
        try:
 
33
            log.info('saving subunit results for %s', package)
 
34
            store = self._create_data_store(params['ticket_id'])
 
35
            name = 'test-runner.{}-subunit-stream'.format(package)
 
36
            url = store.put_file(name, stream, 'text/plain')
 
37
            retval.setdefault('artifacts', []).append({
 
38
                'name': name,
 
39
                'reference': url,
 
40
                'type': 'RESULTS',
 
41
            })
 
42
        except:
 
43
            log.exception('unable to upload subunit result for %s', package)
 
44
 
 
45
    def handle_request(self, log, params):
 
46
        progress_queue = params['progress_trigger']
 
47
        image_id = params['image_id']
 
48
        package_list = params['package_list']
 
49
 
 
50
        def status_cb(msg):
 
51
            log.info(msg)
 
52
            amqp_utils.progress_update(progress_queue, {'message': msg})
 
53
 
 
54
        # The tests will succeed unless they fail ;)
 
55
        notify = amqp_utils.progress_completed
 
56
        results = {}
50
57
        test_bed = None
51
 
        store = data_store.create_for_ticket(ticket, conf)
52
 
        flavors = conf['tr_flavors']
53
 
        test_bed = testbed.TestBed('testbed-{}'.format(progress_queue),
54
 
                                   flavors, image_id, status_cb)
55
 
        test_bed.setup()
56
 
 
57
 
        # FIXME: There is a potentially confusing failure mode here: by reusing
58
 
        # the same testbed for all packages, we may miss bad dependencies for
59
 
        # one package because that missing dependency is provided by another
60
 
        # package. It's vague and unclear that we should care about this edge
61
 
        # case at this point -- vila 2014-02-01
62
 
        for package in package_list:
63
 
            status_cb('testing %s' % package)
64
 
            # uci-vms shell adt-run ...  --- adt-virt-null
65
 
            return_code, subunit_stream = test_bed.run_test(package)
66
 
            # uci-vms shell collect test results
67
 
            artifact_name = 'test_runner.{}-subunit-stream'.format(package)
68
 
            subunit_url = store.put_file(artifact_name,
69
 
                                         subunit_stream)
70
 
            artifact = {
71
 
                'name': artifact_name,
72
 
                'reference': subunit_url,
73
 
                'type': 'RESULTS',
74
 
            }
75
 
            results['artifacts'].append(artifact)
76
 
            # 0 is success, 8 is skipped and considered a success
77
 
            if return_code not in (0, 8):
78
 
                # At least one test failed
79
 
                notify = amqp_utils.progress_failed
80
 
    except (KeyboardInterrupt, Exception) as e:
81
 
        results['message'] = str(e)
82
 
        notify = amqp_utils.progress_failed
83
 
        if isinstance(e, KeyboardInterrupt):
84
 
            raise  # re-raise so amqp_utils.process_queue can exit
85
 
    finally:
86
 
        # All tests have been run, report success or failure
87
 
        notify(progress_queue, results)
88
 
        # Request completed, remove from queue
89
 
 
90
 
        # FIXME: There is still a hole somewhere, the ack below won't happen if
91
 
        # an exception occurs while calling 'notify' just above, tricky testing
92
 
        # ahead... -- vila 2014-02-06
93
 
        msg.channel.basic_ack(msg.delivery_tag)
94
 
        if test_bed:
95
 
            test_bed.teardown()
 
58
        flavors = tstrun.get_auth_config()['tr_flavors']
 
59
        try:
 
60
            test_bed = testbed.TestBed('testbed-{}'.format(progress_queue),
 
61
                                       flavors, image_id, status_cb)
 
62
            test_bed.setup()
 
63
            for package in package_list:
 
64
                if params.get('cancelled'):
 
65
                    log.error('request has been cancelled, exiting')
 
66
                    return amqp_utils.progress_failed, results
 
67
                status_cb('testing %s' % package)
 
68
                # uci-vms shell adt-run ...  --- adt-virt-null
 
69
                return_code, subunit_stream = test_bed.run_test(package)
 
70
                # 0 is success, 8 is skipped and considered a success
 
71
                if return_code not in (0, 8):
 
72
                    # At least one test failed
 
73
                    notify = amqp_utils.progress_failed
 
74
                self.save_subunit(
 
75
                    log, params, package, subunit_stream, results)
 
76
            return notify, results
 
77
        finally:
 
78
            if test_bed:
 
79
                test_bed.teardown()
96
80
 
97
81
 
98
82
if __name__ == '__main__':
99
 
    dump_stack.install_stack_dump_signal()
100
 
    config = amqp_utils.get_config()
101
 
    if not config:
102
 
        exit(1)  # the get_config code prints an error
103
 
    amqp_utils.process_queue(config, tstrun.internal_rabbit_queue, on_message)
104
 
    log.info('exiting')
 
83
    TestRunnerWorker().main(tstrun.internal_rabbit_queue)