forked from cockpit-project/bots
-
Notifications
You must be signed in to change notification settings - Fork 0
/
learn-tests
executable file
·131 lines (104 loc) · 4.44 KB
/
learn-tests
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
#!/usr/bin/env python3
# This file is part of Cockpit.
#
# Copyright (C) 2017 Slavek Kabrda
#
# Cockpit 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.
#
# Cockpit 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 Cockpit; If not, see <http://www.gnu.org/licenses/>.
# The name and version of the training data
TRAINING_DATA = "tests-train-1.jsonl.gz"
# The number of days in history to learn from. This is different from
# the amount of data we gather in tests-data, and can be adjusted
# independently.
SINCE = 21
import os
import socket
import ssl
import subprocess
import sys
import time
import urllib
sys.dont_write_bytecode = True
import task
from machine import testvm
from machine.machine_core.directories import BOTS_DIR
def run(url_or_file, verbose=False, dry=False, **kwargs):
# Default set of training data, retrieve it and use from data directory
if not url_or_file:
url_or_file = TRAINING_DATA
# A URL was provided directly, just use it
if url_or_file.startswith("http"):
filename = os.path.basename(url_or_file)
url = url_or_file
else:
host = os.environ.get("COCKPIT_LEARN_SERVICE_HOST", "learn-cockpit.apps.ci.centos.org")
port = os.environ.get("COCKPIT_LEARN_SERVICE_PORT", "443")
url = "{0}://{1}:{2}/train/{3}".format("https" if port == "443" else "http",
host, port, os.path.basename(url_or_file))
filename = url_or_file
if "/" not in filename and not os.path.exists(filename):
if not dry:
subprocess.check_call([os.path.join(BOTS_DIR, "image-download"), "--state", filename])
filename = os.path.join(testvm.get_images_data_dir(), filename)
train(filename, url, verbose)
# Does 'tail -F' on an HTTP URL
def tail(url, until, verbose=False):
stop = False
at = 0
while True:
time.sleep(10)
try:
req = urllib.request.Request(url, headers={"Range": "bytes={0}-".format(at)})
cafile = os.path.join(BOTS_DIR, "images", "files", "ca.pem")
context = ssl.create_default_context(cafile=cafile)
with urllib.request.urlopen(req, context=context) as f:
while True:
data = f.read(2048)
if not data:
break
at += len(data)
if verbose:
sys.stderr.buffer.write(data)
except urllib.error.HTTPError as ex:
if ex.code != 404 and ex.code != 416:
sys.stderr.write("{0}: {1}\n".format(url, ex))
except (ConnectionResetError, urllib.error.URLError, socket.gaierror) as ex:
sys.stderr.write("{0}: {1}\n".format(url, ex))
if stop:
break
# Note that we do one more loop after we stop, to make sure to get all of url
stop = until()
def train(filename, url, verbose=False):
if verbose:
sys.stderr.write(" ^ {0}\n".format(url))
cmd = [os.path.join(BOTS_DIR, "image-upload"), "--state", filename, "--store", url]
# Passing through a non terminal stdout is necessary to make progress work
subprocess.check_call(cmd)
# We run until the file disappears, which means training has taken place
def until():
try:
req = urllib.request.Request(url, method="HEAD")
with urllib.request.urlopen(req, cafile=os.path.join(BOTS_DIR, "images", "files", "ca.pem")) as f:
f.read()
except urllib.error.HTTPError as ex:
if ex.code == 404:
return True
sys.stderr.write("{0}: {1}\n".format(url, ex))
except (ConnectionResetError, urllib.error.URLError, socket.gaierror) as ex:
sys.stderr.write("{0}: {1}\n".format(url, ex))
return False
# Now tail the logs until above happens
log = urllib.parse.urljoin(url, "../log")
tail(log, until, verbose)
if __name__ == '__main__':
task.main(function=run, title="Learn from testing data", verbose=True)