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/>.
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 (
24
22
from tstrun import testbed
26
logging.basicConfig(level=logging.INFO)
27
log = logging.getLogger(__name__)
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)
39
conf = tstrun.get_auth_config()
42
amqp_utils.progress_update(progress_queue, {'message': msg})
44
# The tests will succeed unless they fail ;)
45
notify = amqp_utils.progress_completed
25
class TestRunnerWorker(amqp_worker.AMQPWorker):
27
super(TestRunnerWorker, self).__init__('test_runner')
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
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({
43
log.exception('unable to upload subunit result for %s', package)
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']
52
amqp_utils.progress_update(progress_queue, {'message': msg})
54
# The tests will succeed unless they fail ;)
55
notify = amqp_utils.progress_completed
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)
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,
71
'name': artifact_name,
72
'reference': subunit_url,
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
86
# All tests have been run, report success or failure
87
notify(progress_queue, results)
88
# Request completed, remove from queue
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)
58
flavors = tstrun.get_auth_config()['tr_flavors']
60
test_bed = testbed.TestBed('testbed-{}'.format(progress_queue),
61
flavors, image_id, status_cb)
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
75
log, params, package, subunit_stream, results)
76
return notify, results
98
82
if __name__ == '__main__':
99
dump_stack.install_stack_dump_signal()
100
config = amqp_utils.get_config()
102
exit(1) # the get_config code prints an error
103
amqp_utils.process_queue(config, tstrun.internal_rabbit_queue, on_message)
83
TestRunnerWorker().main(tstrun.internal_rabbit_queue)