-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild_functions.py
187 lines (159 loc) · 8.19 KB
/
build_functions.py
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import os
import traceback
import docker
import urllib.request
from datetime import datetime, timedelta
from pathlib import Path
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import Qt, QObject, QUrl
from PySide6.QtGui import QPixmap
from PySide6.QtWidgets import *
from ui_utils import resource_path, get_text
from ui.ui_build import Ui_BuildBiaPy
class buildBiapy_Ui(QDialog):
def __init__(self, parent_worker):
super(buildBiapy_Ui, self).__init__()
self.run_window = Ui_BuildBiaPy()
self.parent_worker = parent_worker
self.run_window.setupUi(self)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.run_window.bn_min.clicked.connect(self.showMinimized)
self.run_window.bn_close.clicked.connect(self.close_all)
self.run_window.bn_close.setIcon(QPixmap(resource_path(os.path.join("images","bn_images","close_icon.png"))))
self.run_window.bn_min.setIcon(QPixmap(resource_path(os.path.join("images","bn_images","hide_icon.png"))))
self.run_window.icon_label.setPixmap(QPixmap(resource_path(os.path.join("images","bn_images","info.png"))))
self.run_window.build_progress_bar.setValue(0)
self.setStyleSheet("#centralwidget{ border: 1px solid black;} QWidget{ font-size:16px;}")
self.progress_first_time = True
self.dragPos = self.pos()
def movedialogWindow(event):
if event.buttons() == Qt.LeftButton:
self.move(self.pos() + event.globalPos() - self.dragPos)
self.dragPos = event.globalPos()
event.accept()
self.run_window.frame_top.mouseMoveEvent = movedialogWindow
def closeEvent(self, event):
self.close_all()
def close_all(self):
self.parent_worker.finished_signal.emit(self.parent_worker.finished_good)
self.parent_worker.close_signal.emit()
self.close()
def init_log(self, container_info):
self.run_window.biapy_container_info_label.setText(container_info)
self.run_window.build_biapy_log.setText(' ')
def update_gui(self, signal):
# Initialize the GUI
if signal == 0:
self.parent_worker.init_gui()
elif signal == 1:
self.update_log()
else:
print("Nothing")
def update_log(self):
with open(self.parent_worker.container_stdout_file, 'r') as f:
last_lines = f.readlines()[-11:]
last_lines = ' '.join(last_lines)
self.run_window.build_biapy_log.setText(last_lines)
if "Successfully built " in last_lines:
self.parent_worker.finished_good = 0
def update_building_progress(self, value):
if self.progress_first_time:
self.run_window.build_progress_bar.setMaximum(self.parent_worker.total_steps)
self.run_window.build_progress_bar.setValue(value)
def mousePressEvent(self, event):
self.dragPos = event.globalPos()
class build_worker(QObject):
# Signal to indicate the main thread that the worker has finished
finished_signal = QtCore.Signal(int)
# Signal to indicate the main thread that the worker has finished
close_signal = QtCore.Signal()
# Signal to indicate the main thread to update the log frame (1) or init the GUI (0, this last is done just one time)
update_log_signal = QtCore.Signal(int)
# Signal to indicate the main thread to update the GUI with the new progress of the building
update_build_progress_signal = QtCore.Signal(int)
def __init__(self, main_gui, biapy_container_dockerfile, container_name, output_folder):
super(build_worker, self).__init__()
self.main_gui = main_gui
self.biapy_container_dockerfile = biapy_container_dockerfile
self.container_name = container_name
self.output_folder = output_folder
self.gui = buildBiapy_Ui(self)
self.gui.open()
self.docker_client = docker.from_env()
self.container_info = 'NONE'
self.finished_good = 1
self.container_stdout_file = "None"
def init_gui(self):
self.gui.init_log(self.container_info)
def run(self):
f = None
try:
now = datetime.now()
dt_string = now.strftime("%Y%m%d_%H%M%S")
jobname = get_text(self.main_gui.ui.job_name_input)
# dockerfile = os.path.join(self.log_dir, "Dockerfile")
dockerfile = os.path.join(str(Path.home()), "Dockerfile")
container_out_dir = os.path.join(self.output_folder, jobname)
if jobname == '': jobname = "BiaPy"
self.container_stdout_file = os.path.join(container_out_dir, jobname+"_container_build_"+dt_string)
# Log the output in a file
f = open(self.container_stdout_file, "w")
f.write("#########################################################\n")
f.write("Building BiaPy container\nStart date: {}\nDockerfile: {}\n".format(now.strftime("%Y/%m/%d %H:%M:%S"), dockerfile))
f.write("#########################################################\n")
if os.path.exists(dockerfile):
self.main_gui.yes_no_exec("{} file exists. Do you want to overwrite it?".format(dockerfile))
if self.main_gui.yes_no.answer:
print("Fetching file {}".format(self.biapy_container_dockerfile))
f.write("Fetching file {}".format(self.biapy_container_dockerfile))
urllib.request.urlretrieve(self.biapy_container_dockerfile, dockerfile)
# Set the window header
self.container_info = \
"<b>Building BiaPy container</b><br>\
<table>\
<tr><td>Start date</td><td>{}</td>\
</tr><tr><td>Dockerfile</td><td><a href={}>{}</a></td></tr>\
</tr><tr><td>Build log</td><td><a href={}>{}</a></td></tr>\
</table>"\
.format(now.strftime("%Y/%m/%d %H:%M:%S"),
bytearray(QUrl.fromLocalFile(dockerfile).toEncoded()).decode(), dockerfile,
bytearray(QUrl.fromLocalFile(self.container_stdout_file).toEncoded()).decode(), self.container_stdout_file)
self.update_log_signal.emit(0)
# Build container
result = self.docker_client.images.build(path="/data/dfranco/ficheros_BiaPy_GUI", rm=True, forcerm=True)
# Collect the output of the container and update the GUI
last_write = datetime.now()
self.steps = 0
first_time = True
for item in result[1]:
for key, value in item.items():
if key == 'stream':
text = value.strip()
if text:
print(text)
f.write(text+'\n')
if 'Step' in text:
if first_time:
self.total_steps = int(text.split(' ')[1].split('/')[1])
first_time = False
self.steps += 1
self.update_build_progress_signal.emit(self.steps)
# Update GUI after a few seconds
if datetime.now() - last_write > timedelta(seconds=3):
self.update_log_signal.emit(1)
last_write = datetime.now()
self.update_log_signal.emit(1)
self.finished_signal.emit(self.finished_good)
f.close()
except:
# Print first the traceback (only visible through terminal)
print(traceback.format_exc())
# Try to log the error in the error file
ferr = open(container_stderr_file, "w")
ferr.write("#########################################################\n")
ferr.write(self.container_info+"\n")
ferr.write("#########################################################\n")
ferr.write(traceback.format_exc())
ferr.close()
if f is not None: f.close()
self.finished_signal.emit(2)