aboutsummaryrefslogtreecommitdiff
path: root/lava-v2-jobs-from-api.py
blob: fd92b5c029eee2dfa25057785fc22fe9c06eed9f (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/usr/bin/python
import urllib2
import urlparse
import httplib
import re
import os
import shutil
import argparse
import ConfigParser
import json
import sys
from lib.utils import setup_job_dir
from lib import configuration
from lib.device_map import device_map
from lib.utils import write_file
import requests
import urlparse
from jinja2 import Environment, FileSystemLoader


LEGACY_X86_PLATFORMS = ['x86', 'x86-kvm']
LEGACY_ARM64_PLATFORMS = ['qemu-aarch64-legacy']
INITRD_URLS = {'arm64': 'http://storage.kernelci.org/images/rootfs/buildroot/arm64/rootfs.cpio.gz',
               'arm64be': 'http://storage.kernelci.org/images/rootfs/buildroot/arm64be/rootfs.cpio.gz',
               'armeb': 'http://storage.kernelci.org/images/rootfs/buildroot/armeb/rootfs.cpio.gz',
               'armel': 'http://storage.kernelci.org/images/rootfs/buildroot/armel/rootfs.cpio.gz',
               'x86': 'http://storage.kernelci.org/images/rootfs/buildroot/x86/rootfs.cpio.gz'}


def main(args):
    config = configuration.get_config(args)
    plans = config.get("plans")
    targets = config.get("targets")
    if config.get("jobs"):
        job_dir = setup_job_dir(config.get("jobs"))
    else:
        job_dir = setup_job_dir(os.getcwd() + '/jobs')

    arch = args.get('arch')
    plans = args.get('plans')
    branch = args.get('branch')
    tree = args.get('tree')
    kernel = tree
    api = args.get('api')
    headers = {
        "Authorization": config.get('token')
    }

    print "Working on kernel %s/%s" % (tree, branch)
    url = urlparse.urljoin(api, ("/build?job=%s&kernel=%s&status=PASS&arch=%s" % (tree, branch, arch)))
    print "Calling KernelCI API: %s" % url
    response = requests.get(url, headers=headers)
    if response.status_code != 200:
        print "Error calling KernelCI API"
        print response
        sys.exit(1)
    data = json.loads(response.content)
    builds = data['result']
    print len(builds)
    jobs = []
    cwd = os.getcwd()
    for build in builds:
        defconfig = build['defconfig_full']
        arch_defconfig = ("%s-%s" % (arch, defconfig))
        print "Working on build %s" % arch_defconfig
        test_suite = None
        test_set = None
        test_desc = None
        test_type = None
        plan_defconfigs = []
        modules = build['modules']
        for plan in plans:
            if plan != 'boot':
                    config = ConfigParser.ConfigParser()
                    try:
                        config.read(cwd + '/templates/' + plan + '/' + plan + '.ini')
                        test_suite = config.get(plan, 'suite')
                        test_set = config.get(plan, 'set')
                        test_desc = config.get(plan, 'description')
                        test_type = config.get(plan, 'type')
                        plan_defconfigs = config.get(plan, 'defconfigs').split(',')
                    except:
                        print "Unable to load test configuration"
                        exit(1)
            if build['kernel_image']:
                # handle devices without a DTB, hacky :/
                if build['kernel_image'] == 'bzImage' and arch == 'x86':
                    build['dtb_dir_data'].extend(LEGACY_X86_PLATFORMS)
                if arch == 'arm64' and 'arm64-defconfig' in arch_defconfig:
                    build['dtb_dir_data'].extend(LEGACY_ARM64_PLATFORMS)
                for dtb in build['dtb_dir_data']:
                    # hack for arm64 dtbs in subfolders
                    dtb_full = dtb
                    if arch == 'arm64':
                        dtb = str(dtb).split('/')[-1]
                    if dtb in device_map:
                        # print "device %s was in the device_map" % dtb
                        for device in device_map[dtb]:
                            # print "working on device %s" % dtb
                            lpae = device['lpae']
                            device_type = device['device_type']
                            fastboot = str(device['fastboot']).lower()
                            blacklist = False
                            nfs_blacklist = False
                            if arch_defconfig in device['defconfig_blacklist']:
                                print "defconfig %s is blacklisted for device %s" % (defconfig, device['device_type'])
                                continue
                            elif "BIG_ENDIAN" in defconfig and plan != 'boot-be':
                                print "BIG_ENDIAN is not supported on %s" % device_type
                                continue
                            elif "LPAE" in defconfig and not lpae:
                                print "LPAE is not support on %s" % device_type
                                continue
                            elif any([x for x in device['kernel_blacklist'] if x in kernel]):
                                print "kernel %s is blacklisted for device %s" % (kernel, device_type)
                                continue
                            elif any([x for x in device['nfs_blacklist'] if x in kernel]) \
                                    and plan in ['boot-nfs', 'boot-nfs-mp']:
                                print "kernel %s is blacklisted for NFS on device %s" % (kernel, device_type)
                                continue
                            elif 'be_blacklist' in device \
                                    and any([x for x in device['be_blacklist'] if x in kernel]) \
                                    and plan in ['boot-be']:
                                print "kernel %s is blacklisted for BE on device %s" % (kernel, device_type)
                                continue
                            elif (arch_defconfig not in plan_defconfigs) and (plan != "boot"):
                                print "defconfig %s not in test plan %s" % (arch_defconfig, plan)
                                continue
                            elif targets is not None and device_type not in targets:
                                print "device_type %s is not in targets %s" % (device_type, targets)
                            else:
                                for template in device['templates']:
                                    short_template_file = plan + '/' + str(template)
                                    template_file = cwd + '/templates/' + short_template_file
                                    if os.path.exists(template_file) and template_file.endswith('.jinja2'):
                                        job_name = tree + '-' + branch + '-' + arch + "-" + defconfig[:100] + '-' + dtb + '-' + device_type + '-' + plan
                                        base_url = "https://storage.kernelci.org/%s/%s/%s/" % (build['job'], build['kernel'], arch_defconfig)
                                        dtb_url = base_url + "dtbs/" + dtb_full
                                        kernel_url = urlparse.urljoin(base_url, build['kernel_image'])
                                        defconfig_base = ''.join(defconfig.split('+')[:1])
                                        endian = 'little'
                                        if 'BIG_ENDIAN' in defconfig and plan == 'boot-be':
                                            endian = 'big'
                                        initrd_arch = arch
                                        if arch not in INITRD_URLS.keys():
                                            if arch == 'arm64' and endian == 'big':
                                                initrd_arch = 'arm64be'
                                            if arch == 'arm':
                                                if endian == 'big':
                                                    initrd_arch = 'armeb'
                                                else:
                                                    initrd_arch = 'armel'
                                        initrd_url = INITRD_URLS[initrd_arch]
                                        if build['modules']:
                                            modules_url = urlparse.urljoin(base_url, build['modules'])
                                        else:
                                            modules_url = None
                                        if device['device_type'].startswith('qemu') or device['device_type'] == 'kvm':
                                            device['device_type'] = 'qemu'
                                        job = {'name': job_name, 'dtb_url': dtb_url, 'platform': dtb_full, 'kernel_url': kernel_url, 'image_type': 'kernel-ci', 'image_url': base_url,
                                               'modules_url': modules_url, 'plan': plan, 'kernel': branch, 'tree': tree, 'defconfig': defconfig, 'fastboot': fastboot,
                                               'priority': args.get('priority'), 'device': device, 'template_file': template_file, 'base_url': base_url, 'endian': endian,
                                               'test_suite': test_suite, 'test_set': test_set, 'test_desc': test_desc, 'test_type': test_type, 'short_template_file': short_template_file,
                                               'arch': arch, 'arch_defconfig': arch_defconfig, 'git_branch': build['git_branch'], 'git_commit': build['git_commit'], 'git_describe': build['git_describe'],
                                               'defconfig_base': defconfig_base, 'initrd_url': initrd_url, 'kernel_image': build['kernel_image'], 'dtb_short': dtb}
                                        jobs.append(job)
            else:
                print "no kernel_image for %s" % build['defconfig_full']

    for job in jobs:
        job_file = job_dir + '/' + job['name'] + '.yaml'
        with open(job_file, 'w') as f:
            f.write(jinja_render(job))
        print "Job written: %s" % job_file


def jinja_render(job):
    env = Environment(loader=FileSystemLoader('templates'))
    template = env.get_template(job['short_template_file'])
    return template.render(job)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("--token", help="KernelCI API Token")
    parser.add_argument("--api", help="KernelCI API URL", default="https://api.kernelci.org")
    parser.add_argument("--jobs", help="absolute path to top jobs folder")
    parser.add_argument("--tree", help="KernelCI build kernel tree")
    parser.add_argument("--branch", help="KernelCI build kernel branch")
    parser.add_argument("--config", help="configuration for the LAVA server")
    parser.add_argument("--section", default="default", help="section in the LAVA config file")
    parser.add_argument("--plans", nargs='+', required=True, help="test plan to create jobs for")
    parser.add_argument("--arch", help="specific architecture to create jobs for")
    parser.add_argument("--targets", nargs='+', help="specific targets to create jobs for")
    parser.add_argument("--priority", choices=['high', 'medium', 'low', 'HIGH', 'MEDIUM', 'LOW'],
                        help="priority for LAVA jobs", default='high')
    args = vars(parser.parse_args())
    main(args)