blob: 9c94f393b768f2fdecc09d8c1b6db288acd0c7e9 [file] [log] [blame]
"""
Utility for submitting files to a web server over HTTP.
"""
import sys
import urllib.request
import urllib.parse
import urllib.error
import contextlib
import json
import ssl
import certifi
import lnt.server.instance
# FIXME: I used to maintain this file in such a way that it could be used
# separate from LNT to do submission. This could be useful for adapting an
# older system to report to LNT, for example. It might be nice to factor the
# simplified submit code into a separate utility.
def _show_json_error(reply):
try:
error = json.loads(reply)
except ValueError:
print("error: {}".format(reply))
return
sys.stderr.write("error: lnt server: {}\n".format(error.get('error')))
message = error.get('message', '')
if message:
sys.stderr.write(message + '\n')
def submitFileToServer(url, file, select_machine=None, merge_run=None,
ignore_regressions=False):
with open(file, 'rb') as f:
values = {
'input_data': f.read(),
'commit': "1", # compatibility with old servers.
}
if select_machine is not None:
values['select_machine'] = select_machine
if merge_run is not None:
values['merge'] = merge_run
if ignore_regressions:
values['ignore_regressions'] = True
headers = {'Accept': 'application/json'}
data = urllib.parse.urlencode(values).encode(encoding='ascii')
try:
context = ssl.create_default_context(cafile=certifi.where())
response = urllib.request.urlopen(urllib.request.Request(url, data, headers=headers), context=context)
except urllib.error.HTTPError as e:
_show_json_error(e.read())
return
except urllib.error.URLError as e:
sys.stderr.write("error: could not resolve '%s': %s\n" %
(url, e))
return
result_data = response.read()
# The result is expected to be a JSON object.
try:
return json.loads(result_data)
except Exception:
import traceback
print("Unable to load result, not a valid JSON object.")
print()
print("Traceback:")
traceback.print_exc()
print()
print("Result:")
print("error:", result_data)
return
def submitFileToInstance(path, file, select_machine=None, merge_run=None,
testsuite=None, ignore_regressions=False):
# Otherwise, assume it is a local url and submit to the default database
# in the instance.
instance = lnt.server.instance.Instance.frompath(path)
config = instance.config
db_name = 'default'
with contextlib.closing(config.get_database(db_name)) as db:
if db is None:
raise ValueError("no default database in instance: %r" % (path,))
session = db.make_session()
return lnt.util.ImportData.import_and_report(
config, db_name, db, session, file, format='<auto>',
ts_name=testsuite or 'nts', select_machine=select_machine,
merge_run=merge_run, ignore_regressions=ignore_regressions)
def submitFile(url, file, verbose, select_machine=None, merge_run=None,
testsuite=None, ignore_regressions=False):
# If this is a real url, submit it using urllib.
if '://' in url:
result = submitFileToServer(url, file, select_machine, merge_run,
ignore_regressions)
else:
result = submitFileToInstance(url, file, select_machine, merge_run,
testsuite, ignore_regressions)
return result
def submitFiles(url, files, verbose, select_machine=None, merge_run=None,
testsuite=None, ignore_regressions=False):
results = []
for file in files:
result = submitFile(url, file, verbose, select_machine=select_machine,
merge_run=merge_run, testsuite=testsuite,
ignore_regressions=ignore_regressions)
if result:
results.append(result)
return results