Skip to content

Commit

Permalink
Add support for retrieval of a jobid for a given test (#14)
Browse files Browse the repository at this point in the history
For some tests, we want to retrieve a specific job ID for a test.
For example, if we want to retrieve a prepared qcow2 image from openQA
to use with libvirt on a local machine.

To support this, add a new API endpoint:
/v1/latest_job/<arch>/<distri>/<flavor>/<version>/<test>

for example:
/v1/latest_job/x86_64/sle/Online/15-SP2/create_hdd_minimal_base+sdk

If successful, the openQA job ID is returned. If no job can be found, an
error 404 is returned.

Signed-off-by: Michael Moese <[email protected]>
  • Loading branch information
frankenmichl authored Jun 3, 2020
1 parent 68b8f6c commit 814360d
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 9 deletions.
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
[![Build Status](https://travis-ci.com/frankenmichl/baremetal_support.svg?branch=master)](https://travis-ci.com/frankenmichl/baremetal_support)
[![codecov](https://codecov.io/gh/frankenmichl/baremetal_support/branch/master/graph/badge.svg)](https://codecov.io/gh/frankenmichl/baremetal_support)

While this is designed to work with openQA, this service has not dependencies
to openQA. However, it may be of limited use without being used with an openQA
instance.

## Running

Prior to doing anyting. some preparation is needed:
Expand All @@ -18,8 +14,22 @@ Prior to doing anyting. some preparation is needed:
make init
```

To start the server, just run ```pythin server.py```.
Hit C-c to exit.
To get some usage instructions, just run:
```
# ./baremetal_support.py --help
usage: baremetal_support.py [-h] [-l LISTEN] [-p PORT] [-i INSTANCE]
optional arguments:
-h, --help show this help message and exit
-l LISTEN, --listen LISTEN
hostname to listen on - defaults to all
-p PORT, --port PORT specify listening port - defaults to 8080
-i INSTANCE, --instance INSTANCE
specify openQA instance - defaults to http://openqa.suse.de
```

You can also use the included systemd service file baremetal_support.service
or retrieve a package from https://build.opensuse.org/project/show/home:MMoese:baremetal_support

## Running the tests

Expand Down Expand Up @@ -61,3 +71,13 @@ All parameters in this documentation are surrounded by <>.
- GET
retrieve the lock status of <addr>. Returned in the body as _locked_ or
_unlocked_

### Job-ID related API
#### v1/latest_job/<arch>/<distri>/<flavor>/<version>/<test>
- GET
retrieve the latest jobid from the connected openQA-instance in the request
body. All variables are mandatory here.
Example:
v1/latest_job/x86_64/sle/Online/15-SP2/create_hdd_minimal_base+sdk
On error, HTTP status 404 is returned.

8 changes: 7 additions & 1 deletion baremetal_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
if __name__ == "__main__":
host = "0.0.0.0"
port = 8080
instance = "http://openqa.suse.de"

parser = argparse.ArgumentParser()

Expand All @@ -14,6 +15,8 @@
parser.add_argument("-p", "--port",
type=int,
help="specify listening port - defaults to 8080")
parser.add_argument("-i", "--instance",
help="specify openQA instance - defaults to http://openqa.suse.de")

args = parser.parse_args()

Expand All @@ -23,5 +26,8 @@
if args.listen:
host = args.listen

server = Baremetal_Support(host=host, port=port)
if args.instance:
instance = args.instance

server = Baremetal_Support(host=host, port=port, instance=instance)
server.start()
5 changes: 4 additions & 1 deletion baremetal_support/baremetal_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@

from .bootscript import Bootscript
from .lock import Host_Lock
from . jobid import LatestJob

if __name__ == "__main__":
import argparse


class Baremetal_Support:
def __init__(self, host, port):
def __init__(self, host, port, instance):
self._host = host
self._port = port
self._instance = instance
self._app = Bottle()

self._bootscript = Bootscript(self._app)
self._locks = Host_Lock(self._app)
self._latest_job = LatestJob(self._app, self._instance)

self._route()

Expand Down
50 changes: 50 additions & 0 deletions baremetal_support/jobid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (C) 2020 SUSE LLC
# SPDX-License-Identifier: GPL-3.0

import os
import bottle
import socket
from openqa_client.client import OpenQA_Client

class LatestJobNotFound(Exception):
"""Raised when no job is found"""
pass


class LatestJob:
def __init__(self, app, instance='http://openqa.suse.de'):
self.bootscript = {}
self._instance = instance
self._app = app
self._app.route('/v1/latest_job/<arch>/<distri>/<flavor>/<version>/<test>',
method="GET",
callback=self.http_get_latest_job)

def get_latest_job(self, filter):
try:
client = OpenQA_Client(server=self._instance)
result = client.openqa_request('GET', 'jobs', filter)
jobs = sorted(result['jobs'], key=lambda x: str(x['t_finished']))
if jobs:
return ([[job] for job in jobs if job['result'] in ['passed', 'softfailed']][-1][0])
else:
raise LatestJobNotFound("no such job found");
except Exception:
raise LatestJobNotFound("no such job found");

def http_get_latest_job(self, arch, distri, flavor, version, test):
filter = {}
filter['arch'] = arch
filter['distri'] = distri
filter['flavor'] = flavor
filter['version'] = version
filter['test'] = test

try:
job = self.get_latest_job(filter)
bottle.response.content_type = 'text/text; charset=utf-8'
result = job['id']
return str(result)
except LatestJobNotFound:
bottle.response.body = 'not found'
bootle.respons.status = '404 Not Found'
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pytest-cov>=2.6.1
requests>=2.21.0
pycodestyle>=2.5.0
codecov
openqa_client
14 changes: 13 additions & 1 deletion tests/test_baremetal_Support.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def server_task(arg):
def test_baremetal_support():
hostname = 'localhost'
port = '23456'
instance = "http://openqa.opensuse.org"

url = 'http://' + hostname + ':' + port + '/v1/'
use_ip = '10.0.0.1'
Expand All @@ -43,9 +44,12 @@ def test_baremetal_support():
url_lock_timeout = url + 'host_lock/lock/' + use_ip + '/10'
url_unlock = url + 'host_lock/lock/' + use_ip

url_jobid_good = url + 'latest_job/x86_64/opensuse/DVD/Tumbleweed/create_hdd_textmode'
url_jobid_bad = url + 'latest_job/MIPS/Gentoo/hardened/1.0/install_foobar'

text = "data foo bar"

server = Baremetal_Support(hostname, port)
server = Baremetal_Support(hostname, port, instance)
signal.signal(signal.SIGTERM, cleanup)
assert isinstance(server, Baremetal_Support)
p = Process(target=server_task, args=(server,))
Expand Down Expand Up @@ -141,6 +145,14 @@ def test_baremetal_support():
r22 = requests.put(url_unlock3)
assert r22.status_code == 412

# tests for jobid.py
r23 = requests.get(url_jobid_good)
assert r23.status_code == 200
assert r23.text != ""

r24 = requests.get(url_jobid_bad)
assert r24.status_code != 200

p.terminate()
p.join()

35 changes: 35 additions & 0 deletions tests/test_jobid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright (C) 2019 SUSE LLC
# SPDX-License-Identifier: GPL-3.0

from bottle import Bottle
from pytest import raises

from baremetal_support.jobid import LatestJob, LatestJobNotFound


def test_exception():
app = Bottle()
# retrieve value after setting it
lj = LatestJob(app)

filter = {}
filter['arch'] = 'MIPS'
filter['distri'] = 'gentoo'
filter['flavor'] = 'hardened'
filter['version'] = '1.0'
filter['test'] = 'install_gentoo_mips'
with raises(LatestJobNotFound):
res = lj.get_latest_job(filter)

def test_get():
app = Bottle()
lj = LatestJob(app, 'http://openqa.opensuse.org')
filter = {}
filter['arch'] = 'x86_64'
filter['distri'] = 'opensuse'
filter['flavor'] = 'DVD'
filter['version'] = 'Tumbleweed'
filter['test'] = 'create_hdd_textmode'

res = lj.get_latest_job(filter)
assert res

0 comments on commit 814360d

Please sign in to comment.