Split Vm class from SysTray, and make it launch hyperkit

This commit is contained in:
Micah Lee 2021-06-30 10:45:38 -07:00
parent e8f7d96f90
commit d7cd8584f2
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
5 changed files with 137 additions and 42 deletions

View file

@ -8,6 +8,7 @@ from PySide2 import QtCore, QtWidgets
from .common import GuiCommon
from .main_window import MainWindow
from .vm import Vm
from .systray import SysTray
from .docker_installer import (
is_docker_installed,
@ -101,6 +102,17 @@ def gui_main(custom_container, filename):
docker_installer.start()
return
# The dangerzone VM, for non-Linux platforms
if platform.system() == "Darwin":
vm = Vm(global_common)
else:
vm = None
# Create the system tray
systray = SysTray(global_common, gui_common, app, vm)
if vm:
vm.start()
closed_windows = {}
windows = {}
@ -156,7 +168,4 @@ def gui_main(custom_container, filename):
# If the application is activated and all windows are closed, open a new one
app_wrapper.application_activated.connect(application_activated)
# Create a system tray, which also handles the VM subprocess
systray = SysTray(global_common, gui_common, app)
sys.exit(app.exec_())

View file

@ -1,59 +1,51 @@
import os
import platform
from PySide2 import QtWidgets
class SysTray(QtWidgets.QSystemTrayIcon):
def __init__(self, global_common, gui_common, app):
def __init__(self, global_common, gui_common, app, vm):
super(SysTray, self).__init__()
self.global_common = global_common
self.gui_common = gui_common
self.app = app
self.vm = vm
self.setIcon(self.gui_common.get_window_icon())
menu = QtWidgets.QMenu()
self.status_action = menu.addAction("...")
self.status_action.setEnabled(False)
menu.addSeparator()
self.restart_action = menu.addAction("Restart")
self.restart_action.triggered.connect(self.restart_clicked)
if platform.system() == "Darwin":
self.status_action = menu.addAction("...")
self.status_action.setEnabled(False)
menu.addSeparator()
self.restart_action = menu.addAction("Restart")
self.restart_action.triggered.connect(self.restart_clicked)
self.quit_action = menu.addAction("Quit")
self.quit_action.triggered.connect(self.quit_clicked)
self.setContextMenu(menu)
self.show()
# Dangerzone VM
self.vpnkit_p = None
self.hyperkit_p = None
self.hyperkit_path = self.global_common.get_resource_path("bin/hyperkit")
self.vpnkit_path = self.global_common.get_resource_path("bin/vpnkit")
self.vm_iso_path = self.global_common.get_resource_path(
"vm/alpine-dangerzone-v3.14-x86_64.iso"
)
self.vm_kernel_path = self.global_common.get_resource_path("vm/vmlinuz-virt")
self.vm_initramfs_path = self.global_common.get_resource_path(
"vm/initramfs-virt"
)
self.vm_state_dir = os.path.join(self.global_common.appdata_path, "vm-state")
os.makedirs(self.vm_state_dir, exist_ok=True)
self.vm_start()
if self.vm:
self.vm.vm_state_change.connect(self.vm_state_change)
def vm_start(self):
self.status_action.setText("Starting Dangerzone ...")
# Kill existing processes
if self.vpnkit_p is not None:
self.vpnkit_p.terminate()
if self.hyperkit_p is not None:
self.hyperkit_p.terminate()
# Run VPNKit
# Run Hyperkit
def vm_state_change(self, state):
if state == self.vm.STATE_OFF:
self.status_action.setText("Dangerzone VM is off")
self.restart_action.setEnabled(True)
elif state == self.vm.STATE_STARTING:
self.status_action.setText("Dangerzone VM is starting...")
self.restart_action.setEnabled(False)
elif state == self.vm.STATE_ON:
self.status_action.setText("Dangerzone VM is running")
self.restart_action.setEnabled(True)
elif state == self.vm.STATE_STOPPING:
self.status_action.setText("Dangerzone VM is stopping...")
self.restart_action.setEnabled(False)
def restart_clicked(self):
self.status_action.setText("Restarting Dangerzone ...")
self.vm.restart()
def quit_clicked(self):
self.app.quit()

91
dangerzone/gui/vm.py Normal file
View file

@ -0,0 +1,91 @@
import os
import sys
import subprocess
import uuid
import pipes
from PySide2 import QtCore
class Vm(QtCore.QObject):
STATE_OFF = 0
STATE_STARTING = 1
STATE_ON = 2
STATE_STOPPING = 3
vm_state_change = QtCore.Signal(int)
def __init__(self, global_common):
super(Vm, self).__init__()
self.global_common = global_common
# VM starts off
self.state = self.STATE_OFF
# Hyperkit subprocess
self.hyperkit_p = None
# Relevant paths
self.hyperkit_path = self.global_common.get_resource_path("bin/hyperkit")
self.vm_iso_path = self.global_common.get_resource_path("vm/dangerzone.iso")
self.vm_kernel_path = self.global_common.get_resource_path("vm/kernel")
self.vm_initramfs_path = self.global_common.get_resource_path(
"vm/initramfs.img"
)
# Folder to hold files related to the VM
self.vm_state_dir = os.path.join(self.global_common.appdata_path, "vm-state")
os.makedirs(self.vm_state_dir, exist_ok=True)
# UDID for VM
self.vm_uuid = str(uuid.uuid4())
self.vm_cmdline = "modules=virtio_net console=ttyS0"
def start(self):
self.state = self.STATE_STARTING
self.vm_state_change.emit(self.state)
# Kill existing process
if self.hyperkit_p is not None:
self.hyperkit_p.terminate()
self.hyperkit_p = None
# Run Hyperkit
args = [
self.hyperkit_path,
"-F",
os.path.join(self.vm_state_dir, "hyperkit.pid"),
"-A",
"-u",
"-m",
"4G",
"-c",
"2",
"-s",
"0:0,hostbridge",
"-s",
"31,lpc",
"-l",
"com1,stdio",
"-s",
f"1:0,ahci-cd,{self.vm_iso_path}",
"-s",
"2:0,virtio-net",
"-U",
self.vm_uuid,
"-f",
f'kexec,{self.vm_kernel_path},{self.vm_initramfs_path},"{self.vm_cmdline}"',
]
args_str = " ".join(pipes.quote(s) for s in args)
print("> " + args_str)
self.hyperkit_p = subprocess.Popen(
args,
stdout=sys.stdout,
stderr=sys.stderr,
)
def restart(self):
pass
def stop(self):
pass

View file

@ -38,6 +38,7 @@ sudo -u user sh mkimage.sh --tag v3.14 \
--repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main \
--repository http://dl-cdn.alpinelinux.org/alpine/v3.14/community \
--profile dangerzone
mv alpine-dangerzone-v3.14-x86_64.iso dangerzone.iso
# Fix permissions
chmod 755 /vagrant/vm
@ -45,7 +46,9 @@ chmod 644 /vagrant/vm/*
# Extract vmlinuz and initramfs
cd /vagrant/vm
7z x alpine-dangerzone-v3.14-x86_64.iso boot/vmlinuz-virt
7z x alpine-dangerzone-v3.14-x86_64.iso boot/initramfs-virt
7z x dangerzone.iso boot/vmlinuz-virt
7z x dangerzone.iso boot/initramfs-virt
mv boot/* .
rm -r boot
mv vmlinuz-virt kernel
mv initramfs-virt initramfs.img

View file

@ -22,10 +22,10 @@ $HYPERKIT \
-c 2 \
-s 0:0,hostbridge -s 31,lpc \
-l com1,stdio \
-s 1:0,ahci-cd,$ROOT/alpine-dangerzone-v3.14-x86_64.iso \
-s 1:0,ahci-cd,$ROOT/dangerzone.iso \
-s 2:0,virtio-net \
-U 9efa82d7-ebd5-4287-b1cc-ac4160a39fa7 \
-f kexec,$ROOT/vmlinuz-virt,$ROOT/initramfs-virt,"earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod,usb-storage vpnkit.connect=connect://2/1999"
-f kexec,$ROOT/kernel,$ROOT/initramfs.img,"earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod,usb-storage vpnkit.connect=connect://2/1999"
# hyperkit
# -c 1 -m 1024M