~vila/ubuntu-test-cases/retry-apt-get-update

« back to all changes in this revision

Viewing changes to jenkins/setup_jenkins.py

  • Committer: Leo Arias
  • Date: 2014-11-10 19:28:56 UTC
  • mfrom: (345 touch)
  • mto: This revision was merged to the branch mainline in revision 352.
  • Revision ID: leo.arias@canonical.com-20141110192856-rgpksx9n9j0b39yl
Merged with the touch branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
# Ubuntu Testing Automation Harness
 
4
# Copyright 2013 Canonical Ltd.
 
5
 
 
6
# This program is free software: you can redistribute it and/or modify it
 
7
# under the terms of the GNU General Public License version 3, as published
 
8
# by the Free Software Foundation.
 
9
 
 
10
# This program is distributed in the hope that it will be useful, but
 
11
# WITHOUT ANY WARRANTY; without even the implied warranties of
 
12
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
13
# PURPOSE.  See the GNU General Public License for more details.
 
14
 
 
15
# You should have received a copy of the GNU General Public License along
 
16
# with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 
 
18
import argparse
 
19
import imp
 
20
import jenkins
 
21
import jinja2
 
22
import logging
 
23
import os
 
24
 
 
25
import testconfig
 
26
 
 
27
from distro_info import UbuntuDistroInfo
 
28
DEV_SERIES = UbuntuDistroInfo().devel()
 
29
 
 
30
 
 
31
def _get_parser():
 
32
    """Create and return command line parser.
 
33
 
 
34
    :returns: command line parser
 
35
    :rtype: argparse.ArgumentParser
 
36
 
 
37
    """
 
38
    parser = argparse.ArgumentParser(
 
39
        description='Create/Update upgrade testing jenkins jobs.')
 
40
    parser.add_argument("-d", "--dryrun", action="store_true",
 
41
                        help="Dry run mode. Don't execute jenkins commands.")
 
42
    parser.add_argument("-u", "--username",
 
43
                        help="username to use when logging into Jenkins.")
 
44
    parser.add_argument("-p", "--password",
 
45
                        help="username to use when logging into Jenkins")
 
46
    parser.add_argument("--dashboard-key", default="",
 
47
                        help="The api-key for dashboard updates")
 
48
    parser.add_argument("--nfss-config", default="",
 
49
                        help="The path to the config file for nfss insertion")
 
50
    parser.add_argument("-b", "--branch", default="lp:ubuntu-test-cases/touch",
 
51
                        help="The branch this is located. default=%(default)s")
 
52
    parser.add_argument("-c", "--config", required=True,
 
53
                        type=argparse.FileType('r'),
 
54
                        help="The job config to use.")
 
55
    parser.add_argument("-P", "--publish", action="store_true",
 
56
                        help="Publish at the end of the job")
 
57
    parser.add_argument("--prefix",
 
58
                        help="Prefix to add to the beginning of the job name")
 
59
    parser.add_argument("-s", "--series", default=DEV_SERIES,
 
60
                        help=("series of Ubuntu to download "
 
61
                              "(default=%(default)s)"))
 
62
    parser.add_argument("-w", "--wait", type=int, default=300,
 
63
                        help=("How long to wait after jenkins triggers the"
 
64
                              "install-and-boot job (default=%(default)d)"))
 
65
    return parser
 
66
 
 
67
 
 
68
def _get_jenkins(url, username, password):
 
69
    logging.info('Attempting to login to jenkins at %s', url)
 
70
    if username is not None:
 
71
        logging.info('...with authentication as user: %s', username)
 
72
        instance = jenkins.Jenkins(url, username=username, password=password)
 
73
    else:
 
74
        logging.info('...without authentication')
 
75
        instance = jenkins.Jenkins(url)
 
76
 
 
77
    return instance
 
78
 
 
79
 
 
80
def _get_environment():
 
81
    base = os.path.join(os.path.dirname(__file__), 'templates')
 
82
    return jinja2.Environment(
 
83
        loader=jinja2.FileSystemLoader(base),
 
84
        undefined=jinja2.StrictUndefined,
 
85
        trim_blocks=True)
 
86
 
 
87
 
 
88
def _publish(instance, env, args, template, jobname, **params):
 
89
    tmpl = env.get_template(template)
 
90
    cfg = tmpl.render(**params)
 
91
    if args.dryrun:
 
92
        _dryrun_func(jobname, cfg)
 
93
        return
 
94
    if instance.job_exists(jobname):
 
95
        logging.info('reconfiguring job %s', jobname)
 
96
        instance.reconfig_job(jobname, cfg)
 
97
    else:
 
98
        logging.info('creating job %s', jobname)
 
99
        instance.create_job(jobname, cfg)
 
100
 
 
101
 
 
102
def _configure_smoke(instance, env, args, config_item, device):
 
103
    defserial = '$(${BZRDIR}/scripts/get-adb-id ${NODE_NAME})'
 
104
 
 
105
    params = {
 
106
        'name': device['slave-label'],
 
107
        'device_type': device['name'],
 
108
        'serial': device.get('serial', defserial),
 
109
        'publish': args.publish,
 
110
        'branch': args.branch,
 
111
        'imagetype': config_item['image-type'],
 
112
        'series': args.series,
 
113
        'image_opt': config_item.get('IMAGE_OPT', ''),
 
114
        'statsd_key': config_item.get('statsd-key', ''),
 
115
        'dashboard_host': config_item.get('dashboard-host', ''),
 
116
        'dashboard_port': config_item.get('dashboard-port', ''),
 
117
        'dashboard_prefix': config_item.get('dashboard-prefix', ''),
 
118
        'dashboard_user': config_item.get('dashboard-user', ''),
 
119
        'dashboard_key': args.dashboard_key,
 
120
        'nfss_config': args.nfss_config,
 
121
    }
 
122
 
 
123
    prefix = ""
 
124
    if(args.prefix):
 
125
        prefix = args.prefix + "-"
 
126
 
 
127
    job = '{}{}-{}-{}-smoke-daily'.format(
 
128
        prefix, args.series, config_item['image-type'], device['name'])
 
129
    _publish(instance, env, args, 'touch-smoke.xml.jinja2', job, **params)
 
130
    return job
 
131
 
 
132
 
 
133
def _configure_qa_job(instance, env, args, config_item, device, test):
 
134
    defserial = '$(${BZRDIR}/scripts/get-adb-id ${NODE_NAME})'
 
135
    # If the slave is specified for this test, set it
 
136
    slave = getattr(test, 'device', device['slave-label'])
 
137
    params = {
 
138
        'name': slave,
 
139
        'device_type': device['name'],
 
140
        'serial': device.get('serial', defserial),
 
141
        'publish': args.publish,
 
142
        'branch': args.branch,
 
143
        'imagetype': config_item['image-type'],
 
144
        'series': args.series,
 
145
        'image_opt': config_item.get('IMAGE_OPT', ''),
 
146
        'timeout': test.timeout,
 
147
        'test': test.name,
 
148
        'nfss_config': args.nfss_config,
 
149
    }
 
150
    prefix = ""
 
151
    if(args.prefix):
 
152
        prefix = args.prefix + "-"
 
153
    job = test.fmt.format(prefix=prefix,
 
154
                          series=args.series,
 
155
                          testname=test.name,
 
156
                          imagetype=config_item['image-type'],
 
157
                          type=device['name'])
 
158
    _publish(instance, env, args, 'touch-base.xml.jinja2', job, **params)
 
159
    return job
 
160
 
 
161
 
 
162
def _configure_qa_jobs(instance, env, args, config_item, device):
 
163
    tests = list(testconfig.TESTSUITES)
 
164
    tests = testconfig.filter_tests(tests, config_item['image-type'],
 
165
                                    device['name'])
 
166
    tests = [t for t in tests if not t.smoke]
 
167
    jobs = []
 
168
    for t in tests:
 
169
        j = _configure_qa_job(instance, env, args, config_item, device, t)
 
170
        jobs.append(j)
 
171
    return jobs
 
172
 
 
173
 
 
174
def _configure_master(instance, env, args, config_item, device, smoke, jobs):
 
175
    params = {
 
176
        'branch': args.branch,
 
177
        'trigger_url': device.get('trigger_url', ''),
 
178
        'wait': args.wait,
 
179
        'projects': jobs,
 
180
        'smoke_job': smoke,
 
181
        'num_workers': device.get('num-workers', 1),
 
182
    }
 
183
    prefix = ""
 
184
    if(args.prefix):
 
185
        prefix = args.prefix + "-"
 
186
    job = testconfig.DEF_FMT.format(prefix=prefix,
 
187
                                    series=args.series,
 
188
                                    testname='master',
 
189
                                    imagetype=config_item['image-type'],
 
190
                                    type=device['name'])
 
191
    _publish(instance, env, args, 'touch-master.xml.jinja2', job, **params)
 
192
    return job
 
193
 
 
194
 
 
195
def _dryrun_func(jobname, config):
 
196
    logging.debug(jobname)
 
197
    logging.debug(config)
 
198
 
 
199
 
 
200
def main():
 
201
    logging.basicConfig(level=logging.DEBUG)
 
202
    args = _get_parser().parse_args()
 
203
 
 
204
    config = imp.load_source('', 'config.py', args.config)
 
205
    if args.series not in config.MATRIX:
 
206
        print('"%s" series is not supported by this config.' % args.series)
 
207
        exit(1)
 
208
 
 
209
    jenkins_inst = _get_jenkins(config.JENKINS, args.username, args.password)
 
210
    if args.dryrun:
 
211
        jenkins_inst.create_job = _dryrun_func
 
212
        jenkins_inst.reconfig_job = _dryrun_func
 
213
 
 
214
    env = _get_environment()
 
215
 
 
216
    for item in config.MATRIX[args.series]:
 
217
        for device in item['devices']:
 
218
            job = _configure_smoke(jenkins_inst, env, args, item, device)
 
219
            jobs = []
 
220
            if item.get('include-qa'):
 
221
                jobs = _configure_qa_jobs(
 
222
                    jenkins_inst, env, args, item, device)
 
223
            _configure_master(jenkins_inst, env, args, item, device, job, jobs)
 
224
 
 
225
if __name__ == '__main__':
 
226
    main()