__init__.py 14.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#!/usr/bin/env python
###################################################################################
# LAVA QA tool
# Copyright (C) 2015  Luis Araujo <luis.araujo@collabora.co.uk>

# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  US
###################################################################################

import sys
22
import xmlrpclib
23 24
from argparse import ArgumentParser

25
from lqa_api.waitqueue import WAIT_DEFAULT_TIMEOUT
26
from lqa_api.exit_codes import APPLICATION_ERROR
27
from lqa_tool.version import __version__
Luis Araujo's avatar
Luis Araujo committed
28
from lqa_tool.commands import Command
29
from lqa_tool.exceptions import ProfileNotFound
30
from lqa_tool.settings import lqa_logger
31 32 33 34 35

class Cli(object):
    """Command line interface using argparse"""

    def __init__(self):
36
        self.parser = ArgumentParser(description="lqa v{}".format(__version__))
37
        # Add options common to all sub-commands
38 39 40
        self.parser.add_argument('-c', '--config', metavar='CONFIG.yaml',
                                 help="set configuration file")
        self.parser.add_argument('--log-file', type=str, help="set the log file")
41

42
        # Sub-commands
43
        subparsers = self.parser.add_subparsers()
44 45 46

        # Submit
        submit_parser = subparsers.add_parser('submit', help="Submit job files")
47
        submit_parser.add_argument('submit_job', nargs='*', type=str,
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
                                   metavar='JOB_FILE.json',
                                   help="job file to submit")
        submit_parser.add_argument('-g', '--profile-file', metavar='PROFILE.yaml',
                                   help="set profile file")
        submit_parser.add_argument('-n', '--dry-run', action='store_true',
                                   help="Dry-run, do everyting apart from "
                                   "submitting")
        submit_parser.add_argument('-p', '--profile', action='append', type=str,
                                   help="specify the profiles to use "
                                   "(can be given multiple times)")
        submit_parser.add_argument('--all-profiles', action='store_true', 
                                   help="process all the available profiles")
        submit_parser.add_argument('-t', '--template-vars', action='append', 
                                   type=str, help="set 'field:value' "
                                   "template variables/values "
                                   "(can be given multiple times")
        submit_parser.add_argument('-v', '--verbose', action='store_true',
                                   help="Verbose mode (e.g. print the resulting "
                                   "json)")
67
        submit_parser.add_argument('--wait',  nargs='?', type=str,
68 69 70 71
                                   metavar='TIMEOUT', dest='wait_timeout',
                                   const=WAIT_DEFAULT_TIMEOUT,
                                   help="Wait for submitted jobs to complete using"
                                   " a TIMEOUT value (Default timeout of 3 hours)")
72 73
        submit_parser.add_argument('--debug-vars', action='store_true',
                                   help="Debug undefined template variables")
74 75 76
        submit_parser.add_argument('--priority',
                                   choices=['high', 'medium', 'low'],
                                   help="Set the job priority"),
77 78 79 80
        submit_parser.set_defaults(func=submit)

        # Cancel
        cancel_parser = subparsers.add_parser('cancel', help="Cancel job id")
81
        cancel_parser.add_argument('job_ids',  nargs='+', type=str,
82 83 84 85
                                   metavar='JOB_ID', help="job id to cancel")
        cancel_parser.set_defaults(func=cancel)

        # Resubmit
86
        resubmit_parser = subparsers.add_parser('resubmit', help="Resubmit job id")
87
        resubmit_parser.add_argument('job_ids',  nargs='+', type=str,
88 89 90
                                     metavar='JOB_ID', help="job id to resubmit")
        resubmit_parser.set_defaults(func=resubmit)

Luis Araujo's avatar
Luis Araujo committed
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
        # Make stream
        mkstream_parser = subparsers.add_parser('mkstream',
                                                help="Create bundle stream")
        mkstream_parser.add_argument('description', type=str, nargs="?",
                                     default="", metavar='DESCRIPTION',
                                     help="description of the stream")
        # Group mutually exclusive options
        # Access group: public or private
        mkstream_access_group = mkstream_parser.add_mutually_exclusive_group()
        mkstream_access_group.add_argument('--public', action='store_const',
                                           const="public", default="public",
                                           help="create public stream (default)")
        mkstream_access_group.add_argument('--private', action='store_const',
                                           const="private",
                                           help="create private stream")
        # User group: anonymous, personal or team
        mkstream_user_group = mkstream_parser.add_mutually_exclusive_group()
        mkstream_user_group.add_argument('--anonymous', type=str, metavar="NAME",
                                         help="create anonymous stream (this "
                                         "option overrides access options since "
                                         "an anonymous stream is always public)")
        mkstream_user_group.add_argument('--personal', type=str,
                                         nargs='?', metavar="LOGGED_USER/SLUG",
                                         # $USER is replaced by the logged in user
                                         # when creating the bundle.
                                         const="$USER",
                                         help="create personal stream and when "
                                         "not argument is passed it defaults to "
                                         "the logged in username")
        mkstream_user_group.add_argument('--team', type=str,
                                         metavar="TEAM_NAME[/SLUG]",
                                         help="create team stream")
        mkstream_parser.set_defaults(func=mkstream)

125 126
        # Wait
        wait_parser = subparsers.add_parser('wait', help="Wait for job id")
127
        wait_parser.add_argument('job_ids',  nargs='+', type=str,
128
                                 metavar='JOB_ID', help="wait for this job id")
129
        wait_parser.add_argument('--timeout', type=str,
130
                                 default=WAIT_DEFAULT_TIMEOUT,
131 132 133
                                 help="set wait timeout")
        wait_parser.set_defaults(func=wait)

Luis Araujo's avatar
Luis Araujo committed
134 135
        # Status
        status_parser = subparsers.add_parser('status', help="Show job id status")
136
        status_parser.add_argument('job_ids',  nargs='+', type=str,
Luis Araujo's avatar
Luis Araujo committed
137 138 139 140
                                   metavar='JOB_ID',
                                   help="show the status for job id")
        status_parser.set_defaults(func=status)

Luis Araujo's avatar
Luis Araujo committed
141 142 143
        # Job Output
        output_parser = subparsers.add_parser('output',
                                              help="Fetch job id output log")
144
        output_parser.add_argument('job_id', type=int, metavar='JOB_ID',
Luis Araujo's avatar
Luis Araujo committed
145
                                   help="job id")
146 147 148 149 150
        output_group = output_parser.add_mutually_exclusive_group()
        output_group.add_argument('--file', type=str, metavar='FILE',
                                  help="write output to file")
        output_group.add_argument('--live', action='store_true',
                                  help="follow output log live")
Luis Araujo's avatar
Luis Araujo committed
151 152
        output_parser.set_defaults(func=output)

153 154 155
        # Job information
        job_parser = subparsers.add_parser('job',
                                           help="Get information for job id")
156
        job_parser.add_argument('job_ids', nargs='+', type=str, metavar='JOB_ID',
157 158 159
                                help="job id from which to fetch information")
        job_parser.add_argument('--info', action='store_true',
                                help="show job metadata information")
160 161
        job_parser.add_argument('-t', '--tests', action='store_true',
                                help="show the tests list")
162 163
        job_parser.set_defaults(func=job)

Luis Araujo's avatar
Luis Araujo committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
        # Test information
        test_parser = subparsers.add_parser('test', help="Show test information")
        test_parser.add_argument('job_id', type=int, metavar='JOB_ID',
                                 help="job id")
        test_parser.add_argument('test_name', nargs='*', type=str,
                                 metavar='TEST_NAME',
                                 help="test name or test uuid to get results, if"
                                 " no test is specified it will list all tests")
        test_parser.add_argument('--info', action='store_true',
                                 help="show test metadata information")
        test_parser.add_argument('--show-packages', action='store_true',
                                 help="show the installed packages in the system"
                                 " for the test (it can be a long output)")
        test_parser.add_argument('-e', '--exclude', action='append', type=str,
                                 help="exclude test from the result "
                                 "(can be given multiple times)")
180 181
        test_parser.add_argument('-r', '--results', action='store_true',
                                 help="show test results")
182 183
        test_parser.add_argument('--attachments', type=str, metavar="DIR",
                                 help="save test attachments to DIR")
Luis Araujo's avatar
Luis Araujo committed
184 185
        test_parser.set_defaults(func=test)

186 187 188 189 190 191 192 193 194 195 196 197 198
        # Report
        report_parser = subparsers.add_parser('report', help="Generate report"
                                              " for job id's")
        report_parser.add_argument('job_ids', nargs='+', type=str,
                                   metavar='JOB_ID',
                                   help="job id to generate report")
        report_parser.add_argument('-a', '--all-results', action='store_true',
                                   help="expand and show all test results (not "
                                   "only failed results)")
        report_parser.add_argument('-n', '--no-limit', action='store_true',
                                   help="ignore the number limit (set to 500) to "
                                   "show test results")
        report_parser.set_defaults(func=report)
199 200 201

        # Results
        results_parser = subparsers.add_parser('results', help="Get (raw) results")
202
        results_parser.add_argument('job_ids',  nargs='+', type=str,
203 204 205
                                    metavar='JOB_ID', help="job id to get results")
        results_parser.set_defaults(func=results)

206 207 208
        # Jobdef (show job definition)
        jobdef_parser = subparsers.add_parser('jobdef', 
                                              help="Show job definition file")
209
        jobdef_parser.add_argument('job_ids',  nargs='+', type=str,
210 211 212 213
                                   metavar='JOB_ID',
                                   help="show the job definition file for job id")
        jobdef_parser.set_defaults(func=jobdef)

Luis Araujo's avatar
Luis Araujo committed
214 215 216 217 218
        # Show running and submitted jobs
        queue_parser = subparsers.add_parser('queue', help="Show the current queue"
                                             " of running and submitted jobs")
        queue_parser.set_defaults(func=queue)

Luis Araujo's avatar
Luis Araujo committed
219 220 221 222 223
        # Show devices
        devices_parser = subparsers.add_parser('devices', help="Show status of all"
                                               " available devices")
        devices_parser.set_defaults(func=devices)

Luis Araujo's avatar
Luis Araujo committed
224 225 226 227 228
        # List streams
        streams_parser = subparsers.add_parser('liststreams', help="Show streams "
                                               "the user has access to")
        streams_parser.set_defaults(func=liststreams)

Luis Araujo's avatar
Luis Araujo committed
229 230 231 232 233
        # Who am I?
        whoami_parser = subparsers.add_parser('whoami', help="Show authenticated "
                                              "user name")
        whoami_parser.set_defaults(func=whoami)

234 235 236 237 238 239 240
    def run(self):
        args = self._parse_args()
        # Catch any high level exception at this point
        try:
            args.func(args)
        except ProfileNotFound:
            self.parser.error('Please specify a profile file using the -g option')
241 242 243 244
        except xmlrpclib.ProtocolError as e:
            # Catch any XMLRPC protocol error at this point.
            lqa_logger.error("xmlrpc error: {}".format(e))
            exit(APPLICATION_ERROR)
245 246
        except KeyboardInterrupt:
            pass
Luis Araujo's avatar
Luis Araujo committed
247

248 249
    def _parse_args(self, args=sys.argv[1:]):
        return self.parser.parse_args(args)
250 251


252
def submit(args):
253 254
    from lqa_tool.commands.submit import SubmitCmd
    SubmitCmd(args).run()
255

256
def cancel(args):
257 258
    from lqa_tool.commands.cancel import CancelCmd
    CancelCmd(args).run()
259

260
def resubmit(args):
261 262
    from lqa_tool.commands.resubmit import ReSubmitCmd
    ReSubmitCmd(args).run()
263

Luis Araujo's avatar
Luis Araujo committed
264 265 266 267
def mkstream(args):
    from lqa_tool.commands.mkstream import MkStreamCmd
    MkStreamCmd(args).run()

268
def wait(args):
269 270
    from lqa_tool.commands.wait import WaitCmd
    WaitCmd(args).run()
271

Luis Araujo's avatar
Luis Araujo committed
272 273 274 275
def status(args):
    from lqa_tool.commands.status import StatusCmd
    StatusCmd(args).run()

Luis Araujo's avatar
Luis Araujo committed
276 277 278 279
def output(args):
    from lqa_tool.commands.output import OutputCmd
    OutputCmd(args).run()

280 281 282 283
def job(args):
    from lqa_tool.commands.job import JobCmd
    JobCmd(args).run()

Luis Araujo's avatar
Luis Araujo committed
284 285 286 287
def test(args):
    from lqa_tool.commands.test import TestCmd
    TestCmd(args).run()

288 289 290
def report(args):
    from lqa_tool.commands.report import ReportCmd
    ReportCmd(args).run()
291

292
def results(args):
293 294
    from lqa_tool.commands.results import ResultsCmd
    ResultsCmd(args).run()
295 296 297 298

def jobdef(args):
    from lqa_tool.commands.jobdef import JobDefCmd
    JobDefCmd(args).run()
Luis Araujo's avatar
Luis Araujo committed
299

Luis Araujo's avatar
Luis Araujo committed
300 301 302 303
def queue(args):
    from lqa_tool.commands.queue import QueueCmd
    QueueCmd(args).run()

Luis Araujo's avatar
Luis Araujo committed
304 305 306
def devices(args):
    from lqa_tool.commands.devices import DevicesCmd
    DevicesCmd(args).run()
Luis Araujo's avatar
Luis Araujo committed
307

Luis Araujo's avatar
Luis Araujo committed
308 309 310 311
def liststreams(args):
    from lqa_tool.commands.liststreams import ListStreamsCmd
    ListStreamsCmd(args).run()

Luis Araujo's avatar
Luis Araujo committed
312 313 314
def whoami(args):
    from lqa_tool.commands.whoami import WhoAmICmd
    WhoAmICmd(args).run()