From 6248c6e0713e47fa488ecf282d5b429db025786f Mon Sep 17 00:00:00 2001 From: Andrew Schoen Date: Thu, 7 May 2015 16:18:25 -0500 Subject: [PATCH] Adds packaging.get_koji_task_result, to query kojihub for a tasks result. We need this because we want to be able to use scratch builds, which do not generate a build ID. We can download the rpms we need by retrieving the results of a task then looking at the list of rpms it created. Signed-off-by: Andrew Schoen --- teuthology/packaging.py | 58 ++++++++++++++++++++++++++++--- teuthology/test/test_packaging.py | 32 +++++++++++++++++ 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/teuthology/packaging.py b/teuthology/packaging.py index df6786ed15..5aa29031ba 100644 --- a/teuthology/packaging.py +++ b/teuthology/packaging.py @@ -102,6 +102,45 @@ def remove_package(package, remote): return remote.run(args=pkgcmd) +def get_koji_task_result(task_id, remote, ctx): + """ + Queries kojihub and retrieves information about + the given task_id. The package, koji, must be installed + on the remote for this command to work. + + We need a remote here because koji can only be installed + on rpm based machines and teuthology runs on Ubuntu. + + The results of the given task are returned. For example: + + { + 'brootid': 3303567, + 'srpms': [], + 'rpms': [ + 'tasks/6745/9666745/kernel-4.1.0-0.rc2.git2.1.fc23.x86_64.rpm', + 'tasks/6745/9666745/kernel-modules-4.1.0-0.rc2.git2.1.fc23.x86_64.rpm', + ], + 'logs': [] + } + + :param task_id: The koji task_id we want to retrieve results for. + :param remote: The remote to run the koji command on. + :param ctx: The ctx from the current run, used to provide a + failure_reason and status if the koji command fails. + :returns: A python dict containing info about the task results. + """ + py_cmd = ('import koji; ' + 'hub = koji.ClientSession("{kojihub_url}"); ' + 'print hub.getTaskResult({task_id})') + py_cmd = py_cmd.format( + task_id=task_id, + kojihub_url=config.kojihub_url + ) + log.info("Querying kojihub for the result of task {0}".format(task_id)) + task_result = _run_python_command(py_cmd, remote, ctx) + return task_result + + def get_koji_build_info(build_id, remote, ctx): """ Queries kojihub and retrieves information about @@ -122,7 +161,7 @@ def get_koji_build_info(build_id, remote, ctx): 'package_id': 34590, 'id': 412677, 'volume_id': 0, 'owner_id': 2826 } - :param build_id: The brew build_id we want to retrieve info on. + :param build_id: The koji build_id we want to retrieve info on. :param remote: The remote to run the koji command on. :param ctx: The ctx from the current run, used to provide a failure_reason and status if the koji command fails. @@ -135,6 +174,17 @@ def get_koji_build_info(build_id, remote, ctx): build_id=build_id, kojihub_url=config.kojihub_url ) + log.info('Querying kojihub for info on build {0}'.format(build_id)) + build_info = _run_python_command(py_cmd, remote, ctx) + return build_info + + +def _run_python_command(py_cmd, remote, ctx): + """ + Runs the given python code on the remote + and returns the stdout from the code as + a python object. + """ proc = remote.run( args=[ 'python', '-c', py_cmd @@ -145,9 +195,9 @@ def get_koji_build_info(build_id, remote, ctx): # returns the __repr__ of a python dict stdout = proc.stdout.getvalue().strip() # take the __repr__ and makes it a python dict again - build_info = ast.literal_eval(stdout) + result = ast.literal_eval(stdout) else: - msg = "Failed to query koji for build {0}".format(build_id) + msg = "Error running the following on {0}: {1}".format(remote, py_cmd) log.error(msg) log.error("stdout: {0}".format(proc.stdout.getvalue().strip())) log.error("stderr: {0}".format(proc.stderr.getvalue().strip())) @@ -155,7 +205,7 @@ def get_koji_build_info(build_id, remote, ctx): ctx.summary["status"] = "dead" raise RuntimeError(msg) - return build_info + return result def get_kojiroot_base_url(build_info, arch="x86_64"): diff --git a/teuthology/test/test_packaging.py b/teuthology/test/test_packaging.py index 3f74bf6019..b20b33c395 100644 --- a/teuthology/test/test_packaging.py +++ b/teuthology/test/test_packaging.py @@ -146,6 +146,38 @@ class TestPackaging(object): with pytest.raises(RuntimeError): packaging.get_koji_build_info(1, m_remote, m_ctx) + @patch("teuthology.packaging.config") + def test_get_koji_task_result_success(self, m_config): + m_config.kojihub_url = "http://kojihub.com" + m_proc = Mock() + expected = dict(foo="bar") + m_proc.exitstatus = 0 + m_proc.stdout.getvalue.return_value = str(expected) + m_remote = Mock() + m_remote.run.return_value = m_proc + result = packaging.get_koji_task_result(1, m_remote, dict()) + assert result == expected + args, kwargs = m_remote.run.call_args + expected_args = [ + 'python', '-c', + 'import koji; ' + 'hub = koji.ClientSession("http://kojihub.com"); ' + 'print hub.getTaskResult(1)', + ] + assert expected_args == kwargs['args'] + + @patch("teuthology.packaging.config") + def test_get_koji_task_result_fail(self, m_config): + m_config.kojihub_url = "http://kojihub.com" + m_proc = Mock() + m_proc.exitstatus = 1 + m_remote = Mock() + m_remote.run.return_value = m_proc + m_ctx = Mock() + m_ctx.summary = dict() + with pytest.raises(RuntimeError): + packaging.get_koji_task_result(1, m_remote, m_ctx) + def test_get_package_version_deb_found(self): remote = Mock() remote.os.package_type = "deb" -- 2.39.5