From 210f8675e5b8d647eca8424725293b5eace69358 Mon Sep 17 00:00:00 2001 From: Ali Mirjamali Date: Sat, 16 Nov 2024 23:06:27 +0330 Subject: [PATCH] Retire old `qubes-vm-create` dialog Retire the the old PyQt based `qubes-vm-create` dialog and replace it with GTK based `qubes-new-qube` for Qube Manager. resolves: https://github.com/QubesOS/qubes-issues/issues/6561 --- .pylintrc | 1 - Makefile | 1 - debian/install | 5 - qubes-vm-create.desktop | 10 - qubesmanager.pro | 3 - qubesmanager/create_new_vm.py | 360 ----------------------- qubesmanager/i18n/qubesmanager_en.ts | 159 ---------- qubesmanager/i18n/qubesmanager_es.ts | 159 ---------- qubesmanager/qube_manager.py | 14 +- qubesmanager/tests/test_create_new_vm.py | 308 ------------------- qubesmanager/tests/test_qube_manager.py | 10 - rpm_spec/qmgr.spec.in | 5 - setup.py | 1 - ui/newappvmdlg.ui | 290 ------------------ 14 files changed, 8 insertions(+), 1318 deletions(-) delete mode 100644 qubes-vm-create.desktop delete mode 100644 qubesmanager/create_new_vm.py delete mode 100644 qubesmanager/tests/test_create_new_vm.py delete mode 100644 ui/newappvmdlg.ui diff --git a/.pylintrc b/.pylintrc index cc1f6a2c..23ee66f2 100644 --- a/.pylintrc +++ b/.pylintrc @@ -7,7 +7,6 @@ ignore=tests, ui_informationnotes.py, ui_logdlg.py, ui_multiselectwidget.py, - ui_newappvmdlg.py, ui_newfwruledlg.py, ui_restoredlg.py, ui_settingsdlg.py, diff --git a/Makefile b/Makefile index 01acb37a..266e36e4 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,6 @@ install: cp qubesmanager/qvm_about.sh $(DESTDIR)/usr/libexec/qubes-manager/ mkdir -p $(DESTDIR)/usr/share/applications - cp qubes-vm-create.desktop $(DESTDIR)/usr/share/applications/ cp qubes-backup.desktop $(DESTDIR)/usr/share/applications/ cp qubes-backup-restore.desktop $(DESTDIR)/usr/share/applications/ cp qubes-qube-manager.desktop $(DESTDIR)/usr/share/applications/ diff --git a/debian/install b/debian/install index 03adb67e..9a7d23f9 100644 --- a/debian/install +++ b/debian/install @@ -1,5 +1,4 @@ /usr/bin/qubes-vm-settings -/usr/bin/qubes-vm-create /usr/bin/qubes-vm-boot-from-device /usr/bin/qubes-backup /usr/bin/qubes-backup-restore @@ -24,7 +23,6 @@ /usr/lib/*/dist-packages/qubesmanager/log_dialog.py /usr/lib/*/dist-packages/qubesmanager/about.py /usr/lib/*/dist-packages/qubesmanager/informationnotes.py -/usr/lib/*/dist-packages/qubesmanager/create_new_vm.py /usr/lib/*/dist-packages/qubesmanager/common_threads.py /usr/lib/*/dist-packages/qubesmanager/qube_manager.py /usr/lib/*/dist-packages/qubesmanager/utils.py @@ -39,7 +37,6 @@ /usr/lib/*/dist-packages/qubesmanager/ui_backupdlg.py /usr/lib/*/dist-packages/qubesmanager/ui_bootfromdevice.py /usr/lib/*/dist-packages/qubesmanager/ui_multiselectwidget.py -/usr/lib/*/dist-packages/qubesmanager/ui_newappvmdlg.py /usr/lib/*/dist-packages/qubesmanager/ui_newfwruledlg.py /usr/lib/*/dist-packages/qubesmanager/ui_restoredlg.py /usr/lib/*/dist-packages/qubesmanager/ui_settingsdlg.py @@ -61,13 +58,11 @@ /usr/lib/*/dist-packages/qubesmanager/tests/test_backup.py /usr/lib/*/dist-packages/qubesmanager/tests/test_backup_utils.py /usr/lib/*/dist-packages/qubesmanager/tests/test_qube_manager.py -/usr/lib/*/dist-packages/qubesmanager/tests/test_create_new_vm.py /usr/lib/*/dist-packages/qubesmanager/tests/test_vm_settings.py /usr/lib/*/dist-packages/qubesmanager/tests/test_clone_vm.py /usr/lib/*/dist-packages/qubesmanager-*.egg-info/* -/usr/share/applications/qubes-vm-create.desktop /usr/share/applications/qubes-backup.desktop /usr/share/applications/qubes-backup-restore.desktop /usr/share/applications/qubes-qube-manager.desktop diff --git a/qubes-vm-create.desktop b/qubes-vm-create.desktop deleted file mode 100644 index b5d70281..00000000 --- a/qubes-vm-create.desktop +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -Type=Application -Exec=qubes-vm-create -Path=/usr/bin -Icon=qubes-manager -Terminal=false -Name=Create Qubes VM -GenericName=Create Qubes VM -StartupNotify=false -Categories=Settings;X-XFCE-SettingsDialog diff --git a/qubesmanager.pro b/qubesmanager.pro index cde88c38..799dee13 100644 --- a/qubesmanager.pro +++ b/qubesmanager.pro @@ -6,7 +6,6 @@ SOURCES = \ ui/informationnotes.ui \ ui/logdlg.ui \ ui/multiselectwidget.ui \ - ui/newappvmdlg.ui \ ui/newfwruledlg.ui \ ui/qubemanager.ui \ ui/restoredlg.ui \ @@ -19,7 +18,6 @@ SOURCES = \ qubesmanager/bootfromdevice.py \ qubesmanager/clipboard.py \ qubesmanager/common_threads.py \ - qubesmanager/create_new_vm.py \ qubesmanager/device_list.py \ qubesmanager/firewall.py \ qubesmanager/informationnotes.py \ @@ -37,7 +35,6 @@ SOURCES = \ qubesmanager/ui_informationnotes.py \ qubesmanager/ui_logdlg.py \ qubesmanager/ui_multiselectwidget.py \ - qubesmanager/ui_newappvmdlg.py \ qubesmanager/ui_newfwruledlg.py \ qubesmanager/ui_qubemanager.py \ qubesmanager/ui_restoredlg.py \ diff --git a/qubesmanager/create_new_vm.py b/qubesmanager/create_new_vm.py deleted file mode 100644 index f75f97e3..00000000 --- a/qubesmanager/create_new_vm.py +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/python3 -# -# The Qubes OS Project, http://www.qubes-os.org -# -# Copyright (C) 2012 Agnieszka Kostrzewa -# Copyright (C) 2012 Marek Marczykowski -# Copyright (C) 2017 Wojtek Porczyk -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, see . -# -# - -import os -import sys -import subprocess - -from PyQt6 import QtCore, QtWidgets, QtGui # pylint: disable=import-error - -import qubesadmin -import qubesadmin.tools -import qubesadmin.exc - -from . import utils -from . import bootfromdevice - -from .ui_newappvmdlg import Ui_NewVMDlg # pylint: disable=import-error - -# this is needed for icons to actually work -# pylint: disable=unused-import, no-name-in-module -from . import resources - - -# pylint: disable=too-few-public-methods -class CreateVMThread(QtCore.QThread): - def __init__(self, *, app, vmclass, name, label, template, properties, - pool): - QtCore.QThread.__init__(self) - self.app = app - self.vmclass = vmclass - self.name = name - self.label = label - self.template = template - self.properties = properties - self.pool = pool - self.msg = None - - def run(self): - try: - if self.vmclass == 'TemplateVM' and self.template is not None: - args = {} - if self.pool: - args['pool'] = self.pool - - vm = self.app.clone_vm(self.template, self.name, - self.vmclass, **args) - - vm.label = self.label - elif self.vmclass == 'StandaloneVM' and self.template is not None: - args = { - 'ignore_volumes': ['private'] - } - if self.pool: - args['pool'] = self.pool - - vm = self.app.clone_vm(self.template, self.name, - self.vmclass, **args) - - vm.label = self.label - else: - args = { - "name": self.name, - "label": self.label, - "template": self.template - } - if self.pool: - args['pool'] = self.pool - - vm = self.app.add_new_vm(self.vmclass, **args) - - for k, v in self.properties.items(): - setattr(vm, k, v) - - except qubesadmin.exc.QubesException as qex: - self.msg = str(qex) - except Exception as ex: # pylint: disable=broad-except - self.msg = repr(ex) - - -class NewVmDlg(QtWidgets.QDialog, Ui_NewVMDlg): - def __init__(self, qtapp, app, parent=None): - super().__init__(parent) - self.setupUi(self) - - self.qtapp = qtapp - self.app = app - - self.thread = None - self.progress = None - self.boot_dialog = None - - utils.initialize_widget_with_labels( - widget=self.label, - qubes_app=self.app) - - utils.initialize_widget_with_vms( - widget=self.template_vm, - qubes_app=self.app, - filter_function=(lambda vm: not utils.is_internal(vm) and - vm.klass == 'TemplateVM'), - allow_none=True) - - default_template = self.app.default_template - for i in range(self.template_vm.count()): - if self.template_vm.itemData(i) == default_template: - self.template_vm.setCurrentIndex(i) - self.template_vm.setItemText( - i, str(default_template) + " (default)") - - self.template_type = "template" - - utils.initialize_widget_with_default( - widget=self.netvm, - choices=[(vm.name, vm) for vm in self.app.domains - if not utils.is_internal(vm) and - getattr(vm, 'provides_network', False)], - add_none=True, - add_qubes_default=True, - default_value=getattr(self.app, 'default_netvm', None)) - - try: - utils.initialize_widget_with_default( - widget=self.storage_pool, - choices=[(str(pool), pool) for pool in self.app.pools.values()], - add_qubes_default=True, - mark_existing_as_default=True, - default_value=self.app.default_pool) - except qubesadmin.exc.QubesDaemonAccessError: - self.storage_pool.clear() - self.storage_pool.addItem("(default)", qubesadmin.DEFAULT) - - self.name.setValidator(QtGui.QRegularExpressionValidator( - QtCore.QRegularExpression( - "[a-zA-Z0-9_-]*", - QtCore.QRegularExpression.PatternOption.CaseInsensitiveOption), - None)) - self.name.selectAll() - self.name.setFocus() - - if self.template_vm.count() < 1: - QtWidgets.QMessageBox.warning( - self, - self.tr('No template available!'), - self.tr('Cannot create a qube when no template exists.')) - - type_list = [ - (self.tr("AppVM (persistent home, volatile root)"), 'AppVM'), - (self.tr("TemplateVM (template home, persistent root)"), - 'TemplateVM'), - (self.tr("StandaloneVM (fully persistent)"), 'StandaloneVM'), - (self.tr("DisposableVM (fully volatile)"), 'DispVM')] - - utils.initialize_widget(widget=self.vm_type, - choices=type_list, - selected_value='AppVM', - add_current_label=False) - - self.vm_type.currentIndexChanged.connect(self.type_change) - - self.template_vm.currentIndexChanged.connect(self.template_change) - - self.launch_settings.stateChanged.connect(self.settings_change) - self.install_system.stateChanged.connect(self.install_change) - - def accept(self): - vmclass = self.vm_type.currentData() - name = str(self.name.text()) - - if self.install_system.isChecked(): - self.boot_dialog = bootfromdevice.VMBootFromDeviceWindow( - vm=name, qapp=self.qtapp, qubesapp=self.app, parent=self, - new_vm=True) - if not self.boot_dialog.exec(): - return - - if name in self.app.domains: - QtWidgets.QMessageBox.warning( - self, - self.tr('Incorrect qube name!'), - self.tr('A qube with the name {} already exists in the ' - 'system!').format(name)) - return - - label = self.label.currentData() - - template = self.template_vm.currentData() - - if vmclass in ['AppVM', 'DispVM'] and template is None: - QtWidgets.QMessageBox.warning( - self, - self.tr('Unspecified template'), - self.tr('{}s must be based on a template!'.format(vmclass))) - return - - properties = {'provides_network': self.provides_network.isChecked()} - if self.netvm.currentIndex() != 0: - properties['netvm'] = self.netvm.currentData() - - # Standalone - not based on a template - if vmclass == 'StandaloneVM' and template is None: - properties['virt_mode'] = 'hvm' - properties['kernel'] = None - - if self.storage_pool.currentData() is not qubesadmin.DEFAULT: - pool = self.storage_pool.currentData() - else: - pool = None - - if self.init_ram.value() > 0: - properties['memory'] = self.init_ram.value() - - self.thread = CreateVMThread( - app=self.app, vmclass=vmclass, name=name, label=label, - template=template, properties=properties, pool=pool) - self.thread.finished.connect(self.create_finished) - self.thread.start() - - self.progress = QtWidgets.QProgressDialog( - self.tr("Creating new qube {0}...").format(name), "", 0, 0) - self.progress.setCancelButton(None) - self.progress.setModal(True) - self.progress.show() - - def create_finished(self): - if self.thread.msg: - QtWidgets.QMessageBox.warning( - self, - self.tr("Error creating the qube!"), - self.tr("ERROR: {0}").format(self.thread.msg)) - - else: - if self.launch_settings.isChecked(): - subprocess.check_call(['qubes-vm-settings', - str(self.name.text())]) - if self.install_system.isChecked(): - qubesadmin.tools.qvm_start.main( - ['--cdrom', self.boot_dialog.cdrom_location, - self.name.text()]) - - self.progress.hide() - self.done(0) - - def type_change(self): - klass = self.vm_type.currentData() - - if klass == 'TemplateVM': - self.template_vm.setCurrentText('(none)') - self.template_vm.setEnabled(False) - self.netvm.setCurrentText('(none)') - else: - self.template_vm.setCurrentText('{} (default)'.format( - str(self.app.default_template))) - self.template_vm.setEnabled(True) - self.netvm.setCurrentText('default ({})'.format( - str(getattr(self.app, 'default_netvm', None)))) - - template = self.template_vm.currentData() - - if klass in ['TemplateVM', 'StandaloneVM'] and template is None: - self.install_system.setEnabled(True) - self.install_system.setChecked(True) - else: - self.install_system.setEnabled(False) - self.install_system.setChecked(False) - - if klass == 'DispVM': - self.template_vm.clear() - - for vm in self.app.domains: - if utils.is_internal(vm): - continue - if vm.klass != 'AppVM': - continue - if getattr(vm, 'template_for_dispvms', True): - self.template_vm.addItem(vm.name, userData=vm) - - self.template_vm.insertItem(self.template_vm.count(), - utils.translate("(none)"), None) - - self.template_vm.setCurrentIndex(0) - self.template_type = "dispvm" - elif self.template_type == "dispvm": - self.template_vm.clear() - - for vm in self.app.domains: - if utils.is_internal(vm): - continue - if vm.klass == 'TemplateVM': - self.template_vm.addItem(vm.name, userData=vm) - - self.template_vm.insertItem(self.template_vm.count(), - utils.translate("(none)"), None) - - self.template_vm.setCurrentIndex(0) - self.template_type = "template" - - def template_change(self): - template = self.template_vm.currentData() - klass = self.vm_type.currentData() - - if klass in ['TemplateVM', 'StandaloneVM'] and template is None: - self.install_system.setEnabled(True) - self.install_system.setChecked(True) - else: - self.install_system.setEnabled(False) - self.install_system.setChecked(False) - - def install_change(self): - if self.install_system.isChecked(): - self.launch_settings.setChecked(False) - - def settings_change(self): - if self.launch_settings.isChecked() and self.install_system.isEnabled(): - self.install_system.setChecked(False) - - -parser = qubesadmin.tools.QubesArgumentParser() - - -def main(args=None): - args = parser.parse_args(args) - - qtapp = QtWidgets.QApplication(sys.argv) - - translator = QtCore.QTranslator(qtapp) - locale = QtCore.QLocale.system().name() - i18n_dir = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - 'i18n') - translator.load("qubesmanager_{!s}.qm".format(locale), i18n_dir) - qtapp.installTranslator(translator) - QtCore.QCoreApplication.installTranslator(translator) - - qtapp.setOrganizationName('Invisible Things Lab') - qtapp.setOrganizationDomain('https://www.qubes-os.org/') - qtapp.setApplicationName(QtCore.QCoreApplication.translate( - "appname", 'Create qube')) - - dialog = NewVmDlg(qtapp, args.app) - dialog.exec() diff --git a/qubesmanager/i18n/qubesmanager_en.ts b/qubesmanager/i18n/qubesmanager_en.ts index 61989c75..628a62da 100644 --- a/qubesmanager/i18n/qubesmanager_en.ts +++ b/qubesmanager/i18n/qubesmanager_en.ts @@ -794,157 +794,6 @@ p, li { white-space: pre-wrap; } - - NewVMDlg - - - Name and label: - - - - - Create new qube - - - - - Networking: - - - - - Template: - - - - - my-new-qube - - - - - Type: - - - - - launch settings after creation - - - - - Basic - - - - - install system from device (also available from settings) - - - - - provides network to other qubes - - - - - Initial RAM (also available from settings) - - - - - <html><head/><body><p><span style=" font-weight:600;">Caution</span>: changing these settings can compromise your system or make the qube unable to boot. Use only if you know what you are doing.</p></body></html> - - - - - Storage pool - - - - - Advanced - - - - - (default) - - - - - MiB - - - - - NewVmDlg - - - No template available! - - - - - Cannot create a qube when no template exists. - - - - - Incorrect qube name! - - - - - A qube with the name <b>{}</b> already exists in the system! - - - - - Error creating the qube! - - - - - Creating new qube <b>{0}</b>... - - - - - ERROR: {0} - - - - - AppVM (persistent home, volatile root) - - - - - TemplateVM (template home, persistent root) - - - - - StandaloneVM (fully persistent) - - - - - DisposableVM (fully volatile) - - - - - Unspecified template - - - - - {}s must be based on a template! - - - QubeManager @@ -2626,14 +2475,6 @@ Error: {} - - appname - - - Create qube - - - dialog diff --git a/qubesmanager/i18n/qubesmanager_es.ts b/qubesmanager/i18n/qubesmanager_es.ts index 8a421b98..db6dbf72 100644 --- a/qubesmanager/i18n/qubesmanager_es.ts +++ b/qubesmanager/i18n/qubesmanager_es.ts @@ -816,157 +816,6 @@ p, li { white-space: pre-wrap; } - - NewVMDlg - - - Name and label: - Nombre y etiqueta: - - - - Create new qube - - - - - Networking: - - - - - Template: - - - - - my-new-qube - - - - - Type: - Tipo: - - - - launch settings after creation - - - - - Basic - Básico - - - - install system from device (also available from settings) - - - - - provides network to other qubes - - - - - Initial RAM (also available from settings) - - - - - <html><head/><body><p><span style=" font-weight:600;">Caution</span>: changing these settings can compromise your system or make the qube unable to boot. Use only if you know what you are doing.</p></body></html> - - - - - Storage pool - - - - - Advanced - Avanzado - - - - (default) - - - - - MiB - - - - - NewVmDlg - - - No template available! - ¡No hay una plantillas disponibles! - - - - Cannot create a qube when no template exists. - - - - - Incorrect qube name! - - - - - A qube with the name <b>{}</b> already exists in the system! - - - - - Error creating the qube! - - - - - Creating new qube <b>{0}</b>... - - - - - ERROR: {0} - ERROR: {0} - - - - AppVM (persistent home, volatile root) - - - - - TemplateVM (template home, persistent root) - - - - - StandaloneVM (fully persistent) - - - - - DisposableVM (fully volatile) - - - - - Unspecified template - - - - - {}s must be based on a template! - - - QubeManager @@ -2733,14 +2582,6 @@ Error: {} - - appname - - - Create qube - - - dialog diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 030bc283..4a92d4e4 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -35,7 +35,7 @@ # pylint: disable=import-error from PyQt6.QtCore import (Qt, QAbstractTableModel, QObject, pyqtSlot, QEvent, QSettings, QRegularExpression, QSortFilterProxyModel, - QSize, QPoint, QTimer) + QSize, QProcess, QPoint, QTimer) # pylint: disable=import-error from PyQt6.QtWidgets import (QLineEdit, QStyledItemDelegate, QToolTip, @@ -52,7 +52,6 @@ from qubesmanager import settings from qubesmanager import restore from qubesmanager import backup -from qubesmanager import create_new_vm from qubesmanager import log_dialog from qubesmanager import utils as manager_utils from qubesmanager import common_threads @@ -903,6 +902,8 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None): self.size_on_disk_timer.setInterval(1000 * 60 * 5) # every 5 mins self.size_on_disk_timer.start() + self.new_qube = QProcess() + def eventFilter(self, _object, event): ''' refresh disk usage every 60s if focused & every 5m in background ''' if event.type() == QEvent.Type.WindowActivate: @@ -1398,10 +1399,9 @@ def update_network_menu(self): # noinspection PyArgumentList @pyqtSlot(name='on_action_createvm_triggered') def action_createvm_triggered(self): - with common_threads.busy_cursor(): - create_window = create_new_vm.NewVmDlg( - self.qt_app, self.qubes_app, self) - create_window.exec() + if self.new_qube.state() == QProcess.ProcessState.Running: + return + self.new_qube.start("/usr/bin/qubes-new-qube") # noinspection PyArgumentList @pyqtSlot(name='on_action_removevm_triggered') @@ -1671,6 +1671,8 @@ def open_settings(self, vm, tab='basic'): "\nError: {}".format(str(ex)))) def closeEvent(self, _): + if self.new_qube.state() == QProcess.ProcessState.Running: + self.new_qube.terminate() self.save_showing() # noinspection PyArgumentList diff --git a/qubesmanager/tests/test_create_new_vm.py b/qubesmanager/tests/test_create_new_vm.py deleted file mode 100644 index 5f5408d7..00000000 --- a/qubesmanager/tests/test_create_new_vm.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/python3 -# -# The Qubes OS Project, https://www.qubes-os.org/ -# -# Copyright (C) 2016 Marta Marczykowska-Górecka -# -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -import logging.handlers -import unittest -import unittest.mock - -from PyQt6 import QtTest, QtCore -from qubesadmin import Qubes -from qubesmanager.tests import init_qtapp -from qubesmanager import create_new_vm - - -class NewVmTest(unittest.TestCase): - def setUp(self): - super(NewVmTest, self).setUp() - self.qtapp, self.loop = init_qtapp() - - self.qapp = Qubes() - - # mock up the Create VM Thread to avoid changing system state - self.patcher_thread = unittest.mock.patch( - 'qubesmanager.create_new_vm.CreateVMThread') - self.mock_thread = self.patcher_thread.start() - self.addCleanup(self.patcher_thread.stop) - - # mock the progress dialog to speed testing up - self.patcher_progress = unittest.mock.patch( - 'PyQt6.QtWidgets.QProgressDialog') - self.mock_progress = self.patcher_progress.start() - self.addCleanup(self.patcher_progress.stop) - - self.dialog = create_new_vm.NewVmDlg(self.qtapp, self.qapp) - - def test_00_window_loads(self): - self.assertGreater(self.dialog.template_vm.count(), 0, - "No templates shown") - self.assertGreater(self.dialog.netvm.count(), 0, "No netvm listed") - - def test_01_cancel_works(self): - self.__click_cancel() - self.assertEqual(self.mock_thread.call_count, 0, - "Attempted to create VM on cancel") - - def test_02_create_simple_vm(self): - self.dialog.name.setText("test-vm") - self.__click_ok() - - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="AppVM", name="test-vm", - label=unittest.mock.ANY, template=self.qapp.default_template, - properties={'provides_network': False}, pool=unittest.mock.ANY) - self.mock_thread().start.assert_called_once_with() - - def test_03_label(self): - for i in range(self.dialog.label.count()): - if self.dialog.label.itemText(i) == 'blue': - self.dialog.label.setCurrentIndex(i) - break - - self.dialog.name.setText("test-vm") - self.__click_ok() - - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="AppVM", name="test-vm", - label=self.qapp.labels['blue'], - template=self.qapp.default_template, - properties=unittest.mock.ANY, pool=unittest.mock.ANY) - self.mock_thread().start.assert_called_once_with() - - def test_04_template(self): - template = None - for i in range(self.dialog.template_vm.count()): - if not self.dialog.template_vm.itemText(i).startswith('default'): - self.dialog.template_vm.setCurrentIndex(i) - template = self.dialog.template_vm.currentText() - break - - self.dialog.name.setText("test-vm") - self.__click_ok() - - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="AppVM", name="test-vm", - label=unittest.mock.ANY, - template=template, - properties=unittest.mock.ANY, pool=unittest.mock.ANY) - - def test_05_netvm(self): - netvm = None - for i in range(self.dialog.netvm.count()): - if not self.dialog.netvm.itemText(i).startswith('default'): - self.dialog.netvm.setCurrentIndex(i) - netvm = self.dialog.netvm.currentText() - break - - self.dialog.name.setText("test-vm") - self.__click_ok() - - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="AppVM", name="test-vm", - label=unittest.mock.ANY, - template=unittest.mock.ANY, - properties={'netvm': netvm, 'provides_network': False}, - pool=unittest.mock.ANY) - - def test_06_provides_network(self): - self.dialog.provides_network.setChecked(True) - - self.dialog.name.setText("test-vm") - self.__click_ok() - - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="AppVM", name="test-vm", - label=unittest.mock.ANY, - template=unittest.mock.ANY, - properties={'provides_network': True}, - pool=unittest.mock.ANY) - - @unittest.mock.patch('subprocess.check_call') - def test_07_launch_settings(self, mock_call): - self.dialog.launch_settings.setChecked(True) - - self.dialog.name.setText("test-vm") - - self.__click_ok() - - # make sure the thread is not reporting an error - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="AppVM", name="test-vm", - label=unittest.mock.ANY, - template=unittest.mock.ANY, - properties=unittest.mock.ANY, - pool=unittest.mock.ANY) - - self.mock_thread().msg = None - self.dialog.create_finished() - - mock_call.assert_called_once_with(['qubes-vm-settings', "test-vm"]) - - def test_08_progress_hides(self): - self.dialog.name.setText("test-vm") - - self.__click_ok() - - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="AppVM", name="test-vm", - label=unittest.mock.ANY, - template=unittest.mock.ANY, - properties=unittest.mock.ANY, - pool=unittest.mock.ANY) - - # make sure the thread is not reporting an error - self.mock_thread().start.assert_called_once_with() - self.mock_thread().msg = None - - self.mock_progress().show.assert_called_once_with() - - self.dialog.create_finished() - - self.mock_progress().hide.assert_called_once_with() - - def test_09_standalone_clone(self): - self.dialog.name.setText("test-vm") - for i in range(self.dialog.vm_type.count()): - opt_text = self.dialog.vm_type.itemText(i).lower() - if "standalone" in opt_text: - self.dialog.vm_type.setCurrentIndex(i) - break - - self.__click_ok() - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="StandaloneVM", name="test-vm", - label=unittest.mock.ANY, - template=unittest.mock.ANY, - properties=unittest.mock.ANY, - pool=unittest.mock.ANY) - - @unittest.mock.patch('qubesmanager.bootfromdevice.VMBootFromDeviceWindow') - @unittest.mock.patch('qubesadmin.tools.qvm_start') - def test_10_standalone_empty(self, mock_qvm_start, mock_bootwindow): - self.dialog.name.setText("test-vm") - for i in range(self.dialog.vm_type.count()): - opt_text = self.dialog.vm_type.itemText(i).lower() - if "standalone" in opt_text: - self.dialog.vm_type.setCurrentIndex(i) - break - # select "(none)" template - self.dialog.template_vm.setCurrentIndex(self.dialog.template_vm.count()-1) - - mock_bootwindow.return_value.cdrom_location = 'CDROM_LOCATION' - - self.__click_ok() - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="StandaloneVM", name="test-vm", - label=unittest.mock.ANY, - template=None, - properties=unittest.mock.ANY, - pool=unittest.mock.ANY) - - self.mock_thread().msg = None - self.dialog.create_finished() - - mock_bootwindow.return_value.exec.assert_called_once_with() - mock_qvm_start.main.assert_called_once_with( - ['--cdrom', 'CDROM_LOCATION', 'test-vm']) - - @unittest.mock.patch('subprocess.check_call') - def test_11_standalone_empty_not_install(self, mock_call): - self.dialog.name.setText("test-vm") - - for i in range(self.dialog.vm_type.count()): - opt_text = self.dialog.vm_type.itemText(i).lower() - if "standalone" in opt_text: - self.dialog.vm_type.setCurrentIndex(i) - break - # select "(none)" template - self.dialog.template_vm.setCurrentIndex(self.dialog.template_vm.count()-1) - - self.dialog.install_system.setChecked(False) - - self.__click_ok() - self.mock_thread.assert_called_once_with( - app=self.qapp, vmclass="StandaloneVM", name="test-vm", - label=unittest.mock.ANY, - template=None, - properties=unittest.mock.ANY, - pool=unittest.mock.ANY) - - self.mock_thread().msg = None - self.dialog.create_finished() - - self.assertEqual(mock_call.call_count, 0) - - def test_12_setting_change(self): - # cannot install system on a template-based appvm - for i in range(self.dialog.vm_type.count()): - opt_text = self.dialog.vm_type.itemText(i).lower() - if "appvm" in opt_text: - self.dialog.vm_type.setCurrentIndex(i) - break - self.assertFalse(self.dialog.install_system.isEnabled()) - self.assertTrue(self.dialog.launch_settings.isEnabled()) - self.assertTrue(self.dialog.template_vm.isEnabled()) - - # or on a standalone vm cloned from a template - for i in range(self.dialog.vm_type.count()): - opt_text = self.dialog.vm_type.itemText(i).lower() - if "standalone" in opt_text: - self.dialog.vm_type.setCurrentIndex(i) - break - # select default template - self.dialog.template_vm.setCurrentIndex(0) - self.assertFalse(self.dialog.install_system.isEnabled()) - self.assertTrue(self.dialog.launch_settings.isEnabled()) - self.assertTrue(self.dialog.template_vm.isEnabled()) - - # can install system on a truly empty AppVM - for i in range(self.dialog.vm_type.count()): - opt_text = self.dialog.vm_type.itemText(i).lower() - if "standalone" in opt_text: - self.dialog.vm_type.setCurrentIndex(i) - break - self.assertTrue(self.dialog.template_vm.isEnabled()) - # select "(none)" template - self.dialog.template_vm.setCurrentIndex(self.dialog.template_vm.count()-1) - self.assertTrue(self.dialog.install_system.isEnabled()) - self.assertTrue(self.dialog.launch_settings.isEnabled()) - - def __click_ok(self): - okwidget = self.dialog.buttonBox.button( - self.dialog.buttonBox.StandardButton.Ok) - - QtTest.QTest.mouseClick(okwidget, QtCore.Qt.MouseButton.LeftButton) - - def __click_cancel(self): - cancelwidget = self.dialog.buttonBox.button( - self.dialog.buttonBox.StandardButton.Cancel) - - QtTest.QTest.mouseClick(cancelwidget, QtCore.Qt.MouseButton.LeftButton) - - -# class CreatteVMThreadTest(unittest.TestCase): - - -if __name__ == "__main__": - ha_syslog = logging.handlers.SysLogHandler('/dev/log') - ha_syslog.setFormatter( - logging.Formatter('%(name)s[%(process)d]: %(message)s')) - logging.root.addHandler(ha_syslog) - unittest.main() diff --git a/qubesmanager/tests/test_qube_manager.py b/qubesmanager/tests/test_qube_manager.py index 821c83c0..9e102725 100644 --- a/qubesmanager/tests/test_qube_manager.py +++ b/qubesmanager/tests/test_qube_manager.py @@ -467,16 +467,6 @@ def test_215_shutdown_halted_vm(self): self.assertFalse(self.dialog.action_shutdownvm.isEnabled()) - @unittest.mock.patch('qubesmanager.create_new_vm.NewVmDlg') - def test_216_create_vm(self, mock_new_vm): - action = self.dialog.action_createvm - self.assertTrue(action.isEnabled()) - - action.trigger() - - self.assertEqual(mock_new_vm.call_count, 1, - "Create New VM window did not appear") - def test_217_remove_admin_vm(self): self._select_admin_vm() diff --git a/rpm_spec/qmgr.spec.in b/rpm_spec/qmgr.spec.in index 6dc5c425..fe1e4ec9 100644 --- a/rpm_spec/qmgr.spec.in +++ b/rpm_spec/qmgr.spec.in @@ -58,7 +58,6 @@ rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) /usr/bin/qubes-vm-settings -/usr/bin/qubes-vm-create /usr/bin/qubes-vm-clone /usr/bin/qubes-vm-boot-from-device /usr/bin/qubes-backup @@ -84,7 +83,6 @@ rm -rf $RPM_BUILD_ROOT %{python3_sitelib}/qubesmanager/log_dialog.py %{python3_sitelib}/qubesmanager/about.py %{python3_sitelib}/qubesmanager/informationnotes.py -%{python3_sitelib}/qubesmanager/create_new_vm.py %{python3_sitelib}/qubesmanager/clone_vm.py %{python3_sitelib}/qubesmanager/common_threads.py %{python3_sitelib}/qubesmanager/qube_manager.py @@ -99,7 +97,6 @@ rm -rf $RPM_BUILD_ROOT %{python3_sitelib}/qubesmanager/ui_backupdlg.py %{python3_sitelib}/qubesmanager/ui_bootfromdevice.py %{python3_sitelib}/qubesmanager/ui_multiselectwidget.py -%{python3_sitelib}/qubesmanager/ui_newappvmdlg.py %{python3_sitelib}/qubesmanager/ui_newfwruledlg.py %{python3_sitelib}/qubesmanager/ui_restoredlg.py %{python3_sitelib}/qubesmanager/ui_settingsdlg.py @@ -121,14 +118,12 @@ rm -rf $RPM_BUILD_ROOT %{python3_sitelib}/qubesmanager/tests/test_backup.py %{python3_sitelib}/qubesmanager/tests/test_backup_utils.py %{python3_sitelib}/qubesmanager/tests/test_qube_manager.py -%{python3_sitelib}/qubesmanager/tests/test_create_new_vm.py %{python3_sitelib}/qubesmanager/tests/test_vm_settings.py %{python3_sitelib}/qubesmanager/tests/test_clone_vm.py %dir %{python3_sitelib}/qubesmanager-*.egg-info %{python3_sitelib}/qubesmanager-*.egg-info/* -/usr/share/applications/qubes-vm-create.desktop /usr/share/applications/qubes-backup.desktop /usr/share/applications/qubes-backup-restore.desktop /usr/share/applications/qubes-qube-manager.desktop diff --git a/setup.py b/setup.py index bceb30d0..b9a52b4f 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,6 @@ entry_points={ 'console_scripts': [ 'qubes-vm-settings = qubesmanager.settings:main', - 'qubes-vm-create = qubesmanager.create_new_vm:main', 'qubes-vm-clone = qubesmanager.clone_vm:main', 'qubes-vm-boot-from-device = qubesmanager.bootfromdevice:main', 'qubes-backup = qubesmanager.backup:main', diff --git a/ui/newappvmdlg.ui b/ui/newappvmdlg.ui deleted file mode 100644 index 41f5793c..00000000 --- a/ui/newappvmdlg.ui +++ /dev/null @@ -1,290 +0,0 @@ - - - NewVMDlg - - - - 0 - 0 - 616 - 300 - - - - Create new qube - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - 0 - 0 - - - - 0 - - - - Basic - - - - 12 - - - 12 - - - 12 - - - 12 - - - 12 - - - 9 - - - - - Networking: - - - - - - - - - - - - - Template: - - - - - - - Name and label: - - - - - - - my-new-qube - - - - - - - true - - - - - - - Launch settings after creation - - - - - - - Type: - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Advanced - - - - 12 - - - 12 - - - 12 - - - 12 - - - 12 - - - 9 - - - - - (default) - - - MiB - - - 90000000 - - - - - - - - 0 - 0 - - - - <html><head/><body><p><span style=" font-weight:600;">Caution</span>: Changing these settings can compromise your system or make the qube unable to boot. Use only if you know what you are doing.</p></body></html> - - - true - - - - - - - - - - - - - - Storage pool - - - - - - - Initial RAM (also available from settings) - - - - - - - false - - - Install system from device (also available from settings) - - - - - - - Provides network access to other qubes - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - name - label - vm_type - template_vm - netvm - launch_settings - buttonBox - - - - - buttonBox - accepted() - NewVMDlg - accept() - - - 257 - 190 - - - 157 - 274 - - - - - buttonBox - rejected() - NewVMDlg - reject() - - - 325 - 190 - - - 286 - 274 - - - - -