The script supports to list avaialable builders and his options, also can force a build if the builder is IDLE or not.
Also supports specify options via cmdline using python dictionaries as string. Signed-off-by: Aníbal Limón <anibal.li...@linux.intel.com> --- bin/forcebuild.py | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100755 bin/forcebuild.py diff --git a/bin/forcebuild.py b/bin/forcebuild.py new file mode 100755 index 0000000..5fe61a0 --- /dev/null +++ b/bin/forcebuild.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python + +# YoctoAutobuilder force build script +# +# Copyright (C) 2017 Intel Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import urllib2 +import urllib +import cookielib +import uuid +import sys +import argparse +import json +from bs4 import BeautifulSoup + +class YoctoAutobuilderAPI(object): + def __init__(self, server): + self.server = server + self.opener = urllib2.build_opener( + urllib2.HTTPCookieProcessor(cookielib.CookieJar())) + + def login(self, user, passwd): + data = urllib.urlencode(dict(username=user, + passwd=passwd)) + url = self.server + "/login" + request = urllib2.Request(url, data) + result = self.opener.open(request).read() + if result.find("The username or password you entered were not correct") > 0: + print("Invalid username or password") + return 1 + return 0 + + def _get_builders(self): + url = "%s/json/builders/?as_text=1" % (self.server) + request = urllib2.Request(url) + json_raw_data = self.opener.open(request) + + return json.load(json_raw_data) + + def list_builders(self): + builders = self._get_builders() + + if builders: + print('Available builders:\n') + for builder in builders: + print(builder) + return 0 + else: + print('No available builders in this server.') + return 1 + + def _get_options_by_builder(self, builder): + options = {} + + url = "%s/builders/%s" % (self.server, builder) + request = urllib2.Request(url) + html = self.opener.open(request).read() + + inputs = BeautifulSoup(html, 'lxml').find_all('input') + for input in inputs: + type = input.attrs['type'] + if type == 'submit': + continue + + options[input.attrs['name']] = input.attrs['value'] + + selects = BeautifulSoup(html, 'lxml').find_all('select') + for select in selects: + value = select.find_all('option', selected=True)[0].getText() + options[select.attrs['name']] = value + + return options + + def list_options(self, builder): + builders = self._get_builders() + if not builder in builders: + print('Builder %s specified isn\'t available' % builder) + return 1 + + opts = self._get_options_by_builder(builder) + print('Available options in builder %s:\n' % (builder)) + for name in opts: + value = opts[name] + print('Name: %s, Default value: %s' % (name, value)) + + def force_build(self, builder, opts, idle_check=False): + builders = self._get_builders() + if not builder in builders: + print('Builder specified isn\'t available') + return 1 + + state = builders[builder]['state'] + if idle_check and not state == 'idle': + print('Builder %s specified isn\'t IDLE, current state %s' \ + % (builder, state)) + return 1 + + opts = eval(opts) # FIXME: transform string argument into dictionary, security? + current_opts = self._get_options_by_builder(builder) + for opt in opts: + if not opt in current_opts: + print('Option %s isn\'t supported by builder %s' % \ + (opt, builder)) + return 1 + else: + current_opts[opt] = opts[opt] + + url_params = urllib.urlencode(current_opts) + url = "%s/builders/%s/force" % (self.server, builder) + request = urllib2.Request(url, url_params) + result = self.opener.open(request) + if 'Forced build' in result.read(): + return 0 + else: + print("Failed to force build") + return 1 + +def main(): + parser = argparse.ArgumentParser(description="Yocto Autobuilder force build script", + add_help=False) + parser.add_argument('-s', '--server', help='Server URL', + action='store', required=True) + + parser.add_argument('-u', '--username', action='store', required=True) + parser.add_argument('-p', '--password', action='store', required=True) + + group = parser.add_mutually_exclusive_group() + group.add_argument('--list-builders', help='List available builders', + action='store_true') + group.add_argument('--list-options', help='List options by builder', + action='store', metavar='BUILDER') + group.add_argument('--force-build', help='Force build by builder', + action='store', metavar='BUILDER') + group.add_argument('--force-build-idle', help='Force build by builder if is idle', + action='store', metavar='BUILDER') + + parser.add_argument('-o', '--options', help='Custom options by operation', + action='store') + + parser.add_argument('-d', '--debug', help='Enable debug output', + action='store_true') + parser.add_argument('-q', '--quiet', help='Print only errors', + action='store_true') + + parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, + help='show this help message and exit') + + args = parser.parse_args() + + api = YoctoAutobuilderAPI(args.server) + if api.login(args.username, args.password): + return 1 + + if args.list_builders: + return api.list_builders() + elif args.list_options: + return api.list_options(args.list_options) + elif args.force_build: + return api.force_build(args.force_build, args.options) + elif args.force_build_idle: + return api.force_build(args.force_build_idle, args.options, idle_check=True) + +if __name__ == '__main__': + try: + ret = main() + except Exception: + ret = 1 + import traceback + traceback.print_exc() + sys.exit(ret) -- 2.1.4 -- _______________________________________________ yocto mailing list yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/yocto