summaryrefslogtreecommitdiffstats
path: root/israwhidebroken/client.py
blob: 41f8dd16b3184e35487b8f1151850392cdfeb929 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/python
# uses the fedora.client library to talk to israwhidebroken

from fedora.client import BaseClient, AppError, ServerError
import os, sys

# A couple of useful helper methods
def todays_compose_id(serial=1):
    import datetime
    '''Return the default compose_id for today'''
    return int(datetime.datetime.today().strftime('%Y%m%d') + '%02u' % serial)

def treedata_from_url(url):
    import urllib2, ConfigParser
    import xml.etree.cElementTree as ElementTree
    '''Given the URL of a rawhide tree, return a dict of tree data'''
    treedata = dict()
    # this one's a gimme
    treedata['compose_id'] = todays_compose_id()
    try:
        # fetch treeinfo
        treeinfo = ConfigParser.SafeConfigParser()
        treeinfo.readfp(urllib2.urlopen(url+'/.treeinfo'))
        treedata['arch'] = treeinfo.get('general','arch')
        treedata['tree_time'] = int(float(treeinfo.get('general','timestamp')))
    except:
        pass
    try:
        # fetch repomd.xml
        repomd = urllib2.urlopen(url+'/repodata/repomd.xml')
        repomdtree = ElementTree.parse(repomd)
        ns = '{http://linux.duke.edu/metadata/repo}'
        revision = repomdtree.getroot().find(ns+'revision')
        treedata['repodata_time'] = int(revision.text)
    except:
        pass
    return treedata

# XXX TODO: if 'exc' in r: raise appropriate error?
class IRBClient(BaseClient):
    def get_tests(self):
        '''Returns a list of known tests'''
        r = self.send_request('/get_tests')
        return r.get('tests')

    def get_trees(self, *args, **kw):
        '''Get a list of trees that match all the given parameters:
        id, compose_id, arch, tree_time, repodata_time'''
        r = self.send_request('/get_trees', req_params=kw)
        return r.get('trees')

    def add_tree(self, *args, **kw):
        '''Add a new tree to israwhidebroken.
        Required arguments: arch, compose_id
        Optional: tree_time, repodata_time
        Returns the new tree.'''
        for field in ('arch', 'compose_id', 'tree_time', 'repodata_time'):
            if field not in kw:
                raise ValueError, "Missing required arg %s" % field
        if type(kw['arch']) is not str:
            raise ValueError, 'arch must be str'
        r = self.send_request('/add_tree', auth=True, req_params=kw)
        return r.get('tree')

    def update_tree(self, *args, **kw):
        '''Add a new tree, or update an existing tree.
        Required arguments: id, or arch and compose_id
        Optional: tree_time, repodata_time
        Returns the tree data.'''
        if 'id' in kw:
            treelist = self.get_trees(id=id)
        else:
            treelist = self.get_trees(arch=kw['arch'],
                                      compose_id=kw['compose_id'])
        if len(treelist) == 0:
            return self.add_tree(*args, **kw)

        kw['treeid'] = treelist[0]['id']
        r = self.send_request('/update_tree', auth=True, req_params=kw)
        return r.get('tree')

    def add_result(self, treeid, testid, result, detail_url=None):
        '''Add a test result to the database. Returns result id on success.'''
        params = {'treeid':treeid, 'testid':testid, 'result': result}
        if detail_url:
            params['detail_url'] = detail_url
        r = self.send_request('/add_result', auth=True, req_params=params)
        return r.get('id')

    def report_result(self, testid, tree_data, result, add_tree=False):
        '''Convenience method that will look up the tree using tree_data and
        then add the given result for the given testid. 

        tree_data should be a dict containing enough data to look up exactly
        one tree. Typically that means either specifying the exact treeid if
        it's already known (e.g. {'id':treeid}) or a dict with 'arch' and one or
        more of (compose_id, tree_time, repodata_time)

        If add_tree is True and tree_data does not match any known tree, a new
        tree will be added.

        Returns result id on success.'''
        treelist = self.get_trees(**tree_data)
        if not treelist:
            if not add_tree:
                print 'Could not find a matching tree'
                return None
            tree = self.add_tree(**tree_data)
            # FIXME else check for error
        elif len(treelist) > 1:
            print 'Ambiguous tree data - too many matching trees'
            return False
        else:
            tree = treelist.pop()
        return self.add_result(treeid=tree['id'], testid=testid, result=result)