Merge pull request #29 from firstlookmedia/26_docker_installer_improvements

Docker installer improvements
This commit is contained in:
Micah Lee 2020-02-26 14:06:21 -08:00 committed by GitHub
commit 47064bd5b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 168 deletions

View file

@ -55,50 +55,14 @@ def main(filename):
return return
# See if we need to install Docker... # See if we need to install Docker...
if platform.system() == "Darwin" and ( if (platform.system() == "Darwin" or platform.system() == "Windows") and (
not is_docker_installed(common) or not is_docker_ready(common) not is_docker_installed(common) or not is_docker_ready(common)
): ):
print("Docker is either not installed or not running") print("Docker is either not installed or not running")
docker_installer = DockerInstaller(common) docker_installer = DockerInstaller(common)
if docker_installer.start(): docker_installer.start()
# When installer finished, wait up to 20 minutes for the user to launch it
for i in range(120):
if is_docker_installed(common) and is_docker_ready(common):
main(filename)
return
print("Waiting for docker to be available ...")
time.sleep(1)
# Give up
print("Docker not available, giving up")
return return
if platform.system() == "Windows":
if not is_docker_installed(common):
print("Docker is not installed")
docker_installer = DockerInstaller(common)
docker_installer.start()
# Quit after the installer runs, because it requires rebooting
return
if not is_docker_ready(common):
print("Docker is not running")
launch_docker_windows(common)
# Wait up to 20 minutes for docker to be ready
for i in range(120):
if is_docker_ready(common):
main(filename)
return
print("Waiting for docker to be available ...")
time.sleep(1)
# Give up
print("Docker not available, giving up")
# Main window # Main window
main_window = MainWindow(common) main_window = MainWindow(common)

View file

@ -52,6 +52,7 @@ class DockerInstaller(QtWidgets.QDialog):
self.setWindowTitle("dangerzone") self.setWindowTitle("dangerzone")
self.setWindowIcon(self.common.get_window_icon()) self.setWindowIcon(self.common.get_window_icon())
self.setMinimumHeight(170)
label = QtWidgets.QLabel() label = QtWidgets.QLabel()
if platform.system() == "Darwin": if platform.system() == "Darwin":
@ -63,29 +64,26 @@ class DockerInstaller(QtWidgets.QDialog):
self.task_label = QtWidgets.QLabel() self.task_label = QtWidgets.QLabel()
self.task_label.setAlignment(QtCore.Qt.AlignCenter) self.task_label.setAlignment(QtCore.Qt.AlignCenter)
self.task_label.setWordWrap(True)
self.progress = QtWidgets.QProgressBar() self.progress = QtWidgets.QProgressBar()
self.progress.setMinimum(0) self.progress.setMinimum(0)
self.install_button = QtWidgets.QPushButton("Install Docker") self.open_finder_button = QtWidgets.QPushButton()
self.install_button.setStyleSheet("QPushButton { font-weight: bold; }")
self.install_button.clicked.connect(self.install_clicked)
self.install_button.hide()
if platform.system() == "Darwin": if platform.system() == "Darwin":
self.launch_button = QtWidgets.QPushButton("Launch Docker") self.open_finder_button.setText("Show in Finder")
self.launch_button.setStyleSheet("QPushButton { font-weight: bold; }") else:
self.launch_button.clicked.connect(self.launch_clicked) self.open_finder_button.setText("Show in Explorer")
self.launch_button.hide() self.open_finder_button.setStyleSheet("QPushButton { font-weight: bold; }")
self.open_finder_button.clicked.connect(self.open_finder_clicked)
self.open_finder_button.hide()
self.cancel_button = QtWidgets.QPushButton("Cancel") self.cancel_button = QtWidgets.QPushButton("Cancel")
self.cancel_button.clicked.connect(self.cancel_clicked) self.cancel_button.clicked.connect(self.cancel_clicked)
buttons_layout = QtWidgets.QHBoxLayout() buttons_layout = QtWidgets.QHBoxLayout()
buttons_layout.addStretch() buttons_layout.addStretch()
buttons_layout.addWidget(self.install_button) buttons_layout.addWidget(self.open_finder_button)
if platform.system() == "Darwin":
buttons_layout.addWidget(self.launch_button)
buttons_layout.addWidget(self.cancel_button) buttons_layout.addWidget(self.cancel_button)
buttons_layout.addStretch() buttons_layout.addStretch()
@ -97,18 +95,17 @@ class DockerInstaller(QtWidgets.QDialog):
layout.addStretch() layout.addStretch()
self.setLayout(layout) self.setLayout(layout)
if platform.system == "Darwin": if platform.system() == "Darwin":
self.tmp_dir = tempfile.TemporaryDirectory(prefix="/tmp/dangerzone-docker-")
self.installer_filename = os.path.join(self.tmp_dir.name, "Docker.dmg")
else:
self.tmp_dir = tempfile.TemporaryDirectory(prefix="dangerzone-docker-")
self.installer_filename = os.path.join( self.installer_filename = os.path.join(
self.tmp_dir.name, "Docker for Windows Installer.exe" os.path.expanduser("~/Downloads"), "Docker.dmg"
)
else:
self.installer_filename = os.path.join(
os.path.expanduser("~\\Downloads"), "Docker for Windows Installer.exe"
) )
# Threads # Threads
self.download_t = None self.download_t = None
self.install_t = None
def update_progress(self, value, maximum): def update_progress(self, value, maximum):
self.progress.setMaximum(maximum) self.progress.setMaximum(maximum)
@ -118,10 +115,15 @@ class DockerInstaller(QtWidgets.QDialog):
self.task_label.setText(s) self.task_label.setText(s)
def download_finished(self): def download_finished(self):
self.task_label.setText("Finished downloading Docker") self.task_label.setText(
"Finished downloading Docker. Install it, make sure it's running, and then open Dangerzone again."
)
self.download_t = None self.download_t = None
self.progress.hide() self.progress.hide()
self.install_button.show() self.cancel_button.hide()
self.open_finder_path = self.installer_filename
self.open_finder_button.show()
def download_failed(self, status_code): def download_failed(self, status_code):
print(f"Download failed: status code {status_code}") print(f"Download failed: status code {status_code}")
@ -142,66 +144,43 @@ class DockerInstaller(QtWidgets.QDialog):
self.download_t.update_progress.connect(self.update_progress) self.download_t.update_progress.connect(self.update_progress)
self.download_t.start() self.download_t.start()
def install_finished(self):
if platform.system() == "Darwin":
self.task_label.setText("Finished installing Docker")
self.launch_button.show()
self.cancel_button.setEnabled(True)
elif platform.system == "Windows":
self.task_label.setText("Reboot to finish installing Docker")
self.install_t = None
self.progress.hide()
self.install_button.hide()
def install_failed(self, exception):
print(f"Install failed: {exception}")
self.task_label.setText(f"Install failed: {exception}")
self.install_t = None
self.progress.hide()
self.cancel_button.setEnabled(True)
def install_clicked(self):
self.task_label.setText("Installing Docker")
self.progress.show()
self.install_button.hide()
self.cancel_button.setEnabled(False)
self.progress.setMinimum(0)
self.progress.setMaximum(0)
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.start_installer)
self.timer.setSingleShot(True)
self.timer.start(10)
def start_installer(self):
self.install_t = Installer(self.common, self.installer_filename)
self.install_t.install_finished.connect(self.install_finished)
self.install_t.install_failed.connect(self.install_failed)
self.install_t.update_task_label.connect(self.update_task_label)
self.install_t.start()
def launch_clicked(self):
if system.platform() == "Darwin":
print("Launching Docker")
self.accept()
subprocess.Popen(["open", "-a", "Docker.app"])
def cancel_clicked(self): def cancel_clicked(self):
self.reject() self.reject()
if self.download_t: if self.download_t:
self.download_t.quit() self.download_t.quit()
if self.install_t: try:
self.install_t.quit() os.remove(self.installer_filename)
except:
pass
def open_finder_clicked(self):
if platform.system() == "Darwin":
subprocess.call(["open", "-R", self.open_finder_path])
else:
subprocess.Popen(
f'explorer.exe /select,"{self.open_finder_path}"', shell=True
)
self.accept()
def start(self): def start(self):
if not os.path.isdir("/Applications/Docker.app"): if platform.system() == "Darwin":
docker_app_path = "/Applications/Docker.app"
else:
docker_app_path = "C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe"
if not os.path.exists(docker_app_path):
self.download() self.download()
else: else:
self.task_label.setText("Docker is installed, but you must launch it first") self.task_label.setText(
"Docker is installed, but you must launch it first. Open Docker, make sure it's running, and then open Dangerzone again."
)
self.progress.hide() self.progress.hide()
self.launch_button.show() self.cancel_button.hide()
self.open_finder_path = docker_app_path
self.open_finder_button.show()
return self.exec_() == QtWidgets.QDialog.Accepted return self.exec_() == QtWidgets.QDialog.Accepted
@ -236,62 +215,3 @@ class Downloader(QtCore.QThread):
self.update_progress.emit(downloaded_bytes, total_bytes) self.update_progress.emit(downloaded_bytes, total_bytes)
self.download_finished.emit() self.download_finished.emit()
class Installer(QtCore.QThread):
install_finished = QtCore.pyqtSignal()
install_failed = QtCore.pyqtSignal(str)
update_task_label = QtCore.pyqtSignal(str)
def __init__(self, common, installer_filename):
super(Installer, self).__init__()
self.common = common
self.installer_filename = installer_filename
def run(self):
print(f"Installing Docker")
if platform.system() == "Darwin":
try:
# Mount the dmg
self.update_task_label.emit(f"Mounting Docker.dmg")
subprocess.run(
["hdiutil", "attach", "-nobrowse", self.installer_filename]
)
# Copy Docker.app to Applications
self.update_task_label.emit("Copying Docker into Applications")
shutil.copytree(
"/Volumes/Docker/Docker.app", "/Applications/Docker.app"
)
# Sync
self.update_task_label.emit("Syncing filesystem")
subprocess.run(["sync"])
# Wait, to prevent early crash
time.sleep(1)
# Unmount the dmg
self.update_task_label.emit(f"Unmounting /Volumes/Docker")
subprocess.run(["hdiutil", "detach", "/Volumes/Docker"])
self.install_finished.emit()
except Exception as e:
self.install_failed.emit(str(e))
return
elif platform.system() == "Windows":
try:
# Run the installer
subprocess.run(
[self.installer_filename],
startupinfo=self.common.get_subprocess_startupinfo(),
)
self.install_finished.emit()
except Exception as e:
self.install_failed.emit(str(e))
return