From 19a9007286c6655083a3eedaf65e9df8569b21f6 Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Wed, 30 Apr 2014 13:56:01 -0300 Subject: [PATCH] Introduce Avocado journal replay utility A command line utility that can read a test journal (when the test is run using '--journal' (and thus the journal plugin), and can send all the test activities recorded to a central Avocado Server. Signed-off-by: Cleber Rosa --- avocado.spec | 7 +- requirements.txt | 1 + scripts/avocado-journal-replay | 151 +++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 2 deletions(-) create mode 100755 scripts/avocado-journal-replay diff --git a/avocado.spec b/avocado.spec index 1f74e87f..3dbe095d 100644 --- a/avocado.spec +++ b/avocado.spec @@ -1,14 +1,14 @@ Summary: Avocado Test Framework Name: avocado Version: %{avocadoversion} -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv2 Group: Development/Tools URL: http://avocado-framework.readthedocs.org/ Source: avocado-%{version}.tar.gz BuildRequires: python2-devel BuildArch: noarch -Requires: python +Requires: python, python-requests %description Avocado is an experimental test framework that is built on the experience with @@ -35,5 +35,8 @@ shortcomings. %{_datadir}/avocado %changelog +* Wed Apr 30 2014 Cleber Rosa - 0.0.1-2 +- Added new requirements reflecting new upstream deps + * Wed Apr 2 2014 Ruda Moura - 0.0.1-1 - Created initial spec file diff --git a/requirements.txt b/requirements.txt index 80134107..839fbed7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ nosexcover==1.0.8 tox==1.5.0 virtualenv==1.9.1 mysql-python==1.2.3 +requests==1.2.3 diff --git a/scripts/avocado-journal-replay b/scripts/avocado-journal-replay new file mode 100755 index 00000000..3f581909 --- /dev/null +++ b/scripts/avocado-journal-replay @@ -0,0 +1,151 @@ +#!/usr/bin/env python + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; specifically version 2 of the License. +# +# This program 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 LICENSE for more details. +# +# Copyright: Red Hat Inc. 2014 +# Author: Cleber Rosa + +""" +Avocado Journal Replay Utility. Sends test journal data to an Avocado Server. +""" + +import sys +import sqlite3 +import argparse + +import requests + + +class ArgumentParser(argparse.ArgumentParser): + + def __init__(self): + super(ArgumentParser, self).__init__( + prog='avocado-journal-replay', + description=('Avocado Test Journal Replay. Sends test journal data' + 'to an Avocado Server')) + + self.add_argument('-s', '--server-uri', + help=('Avocado server http URI. Example: ' + 'http://avocado-server:8000')) + self.add_argument('-u', '--username', + help='Username to authenticate to Avocado Server') + self.add_argument('-p', '--password', + help='Password to authenticate to Avocado Server') + self.add_argument('-n', '--job-name', + help='Name to give to job on the Avocado Server') + self.add_argument('-j', '--journal-path', + help='Path to the journal file (.journal.sqlite)') + + +class App(object): + + def __init__(self): + self.app_parser = ArgumentParser() + self.args = None + + def replay_test_activity(self, job, tag, time, action, status): + action_uri = 'jobs/%s/test_activity' % job + full_uri = "%s/%s/" % (self.args.server_uri, action_uri) + + data = {'activity': action, + 'status': status, + 'job': job, + 'time': time, + 'test_tag': tag} + + r = requests.post(full_uri, + auth=(self.args.username, + self.args.password), + data=data) + + if r.status_code == 200: + return True + else: + print r.text + return False + + def create_job(self, unique_id): + action_uri = 'jobs' + full_uri = "%s/%s/" % (self.args.server_uri, action_uri) + + data = {'name': self.args.job_name, + 'uniqueident': str(unique_id)} + + r = requests.post(full_uri, + auth=(self.args.username, + self.args.password), + data=data) + + if r.status_code == 201: + return r.json()['id'] + else: + print("Failed to add job. reason(s): %s" % r.text) + return False + + def replay(self): + journal = sqlite3.connect(self.args.journal_path) + journal_cursor = journal.cursor() + job_unique_id_sql = 'SELECT unique_id FROM job_info' + job_unique_id = journal_cursor.execute(job_unique_id_sql).fetchone()[0] + + job_result = self.create_job(job_unique_id) + if not job_result: + return -1 + + while True: + journal = sqlite3.connect(self.args.journal_path) + journal_cursor = journal.cursor() + + backlog_count_sql = "SELECT COUNT(*) FROM test_journal WHERE flushed==0" + backlog_count = journal_cursor.execute(backlog_count_sql).fetchone()[0] + + journal_cursor.close() + journal.close() + + if backlog_count == 0: + break + + entry_sql = ("SELECT tag, time, action, status " + "FROM test_journal WHERE flushed==0 " + "ORDER BY time LIMIT 1") + + journal = sqlite3.connect(self.args.journal_path) + journal_cursor = journal.cursor() + entry = journal_cursor.execute(entry_sql).fetchone() + journal_cursor.close() + journal.close() + + tag, time, action, status = entry + activity_result = self.replay_test_activity(job_result, + tag, + time, + action, + status) + if activity_result: + flush_sql = ("UPDATE test_journal SET flushed=1 WHERE " + "tag=='%s' AND action=='%s' AND flushed==0") + flush_sql = flush_sql % (tag, action) + + journal = sqlite3.connect(self.args.journal_path) + journal_cursor = journal.cursor() + flush_result = journal_cursor.execute(flush_sql) + journal.commit() + journal_cursor.close() + journal.close() + + def run(self): + self.args = self.app_parser.parse_args() + return self.replay() + + +if __name__ == '__main__': + app = App() + sys.exit(app.run()) -- GitLab