From 36ce1749627268cb8446c2ad0f892a67a1db86fc Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Mon, 8 Apr 2019 03:19:07 -0400 Subject: [PATCH] Add UI for managing Qubes update repositories Depends on QubesOS/qubes-core-admin-linux#48 Fixes QubesOS/qubes-issues#4550 --- qubesmanager/global_settings.py | 77 ++++++++++++++++++++++++++++++++- ui/globalsettingsdlg.ui | 59 ++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/qubesmanager/global_settings.py b/qubesmanager/global_settings.py index f13e6ed2..2679f4b0 100644 --- a/qubesmanager/global_settings.py +++ b/qubesmanager/global_settings.py @@ -24,6 +24,7 @@ import os import os.path import traceback +import subprocess from PyQt4 import QtCore, QtGui # pylint: disable=import-error from qubesadmin import Qubes @@ -233,8 +234,15 @@ def __apply_mem_defaults__(self): qmemman_config_file.writelines(config_lines) qmemman_config_file.close() - def __init_updates__(self): + def __run_qrexec_repo(self, service, arg=''): + # Fake up a "qrexec call" to dom0 because dom0 can't qrexec to itself yet + cmd = '/etc/qubes-rpc/' + service + p = subprocess.run(['sudo', cmd, arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + assert not p.stderr + assert p.returncode == 0 + return p.stdout.decode('utf-8') + def __init_updates__(self): # TODO: remove workaround when it is no longer needed self.dom0_updates_file_path = '/var/lib/qubes/updates/disable-updates' @@ -251,6 +259,73 @@ def __init_updates__(self): self.enable_updates_all.clicked.connect(self.__enable_updates_all) self.disable_updates_all.clicked.connect(self.__disable_updates_all) + repos = dict() + for i in self.__run_qrexec_repo('qubes.repos.List').split('\n'): + l = i.split('\0') + # Keyed by repo name + d = repos[l[0]] = dict() + d['prettyname'] = l[1] + d['enabled'] = True if l[2] == 'enabled' else False + + if repos['qubes-dom0-unstable']['enabled']: + self.dom0_updates_repo.setCurrentIndex(3) + elif repos['qubes-dom0-current-testing']['enabled']: + self.dom0_updates_repo.setCurrentIndex(2) + elif repos['qubes-dom0-security-testing']['enabled']: + self.dom0_updates_repo.setCurrentIndex(1) + elif repos['qubes-dom0-current']['enabled']: + self.dom0_updates_repo.setCurrentIndex(0) + else: + raise Exception('Cannot detect enabled dom0 update repositories') + + if repos['qubes-templates-itl-testing']['enabled']: + self.itl_tmpl_updates_repo.setCurrentIndex(1) + elif repos['qubes-templates-itl']['enabled']: + self.itl_tmpl_updates_repo.setCurrentIndex(0) + else: + raise Exception('Cannot detect enabled ITL template update repositories') + + if repos['qubes-templates-community-testing']['enabled']: + self.comm_tmpl_updates_repo.setCurrentIndex(2) + elif repos['qubes-templates-community']['enabled']: + self.comm_tmpl_updates_repo.setCurrentIndex(1) + else: + self.comm_tmpl_updates_repo.setCurrentIndex(0) + + self.dom0_updates_repo.currentIndexChanged.connect(self.__handle_dom0_updates_combobox) + self.itl_tmpl_updates_repo.currentIndexChanged.connect(self.__handle_itl_tmpl_updates_combobox) + self.comm_tmpl_updates_repo.currentIndexChanged.connect(self.__handle_comm_tmpl_updates_combobox) + + def __manage_repos(self, l, action): + for i in l: + assert self.__run_qrexec_repo('qubes.repos.' + action, i) == 'ok\n' + + def __handle_dom0_updates_combobox(self, idx): + idx += 1 + l = ['qubes-dom0-current', 'qubes-dom0-security-testing', + 'qubes-dom0-current-testing', 'qubes-dom0-unstable'] + enable = l[:idx] + disable = l[idx:] + self.__manage_repos(enable, 'Enable') + self.__manage_repos(disable, 'Disable') + + def __handle_itl_tmpl_updates_combobox(self, idx): + idx += 1 + l = ['qubes-templates-itl', 'qubes-templates-itl-testing'] + enable = l[:idx] + disable = l[idx:] + self.__manage_repos(enable, 'Enable') + self.__manage_repos(disable, 'Disable') + + def __handle_comm_tmpl_updates_combobox(self, idx): + # We don't increment idx by 1 because this is the only combobox that + # has an explicit "disable this repository entirely" option + l = ['qubes-templates-community', 'qubes-templates-community-testing'] + enable = l[:idx] + disable = l[idx:] + self.__manage_repos(enable, 'Enable') + self.__manage_repos(disable, 'Disable') + def __enable_updates_all(self): reply = QtGui.QMessageBox.question( self, self.tr("Change state of all qubes"), diff --git a/ui/globalsettingsdlg.ui b/ui/globalsettingsdlg.ui index 0f72cdac..40de4118 100644 --- a/ui/globalsettingsdlg.ui +++ b/ui/globalsettingsdlg.ui @@ -98,7 +98,7 @@ - + Qt::Horizontal @@ -209,6 +209,30 @@ Updates + + + + + Stable updates + + + + + Testing updates (security only) + + + + + Testing updates + + + + + Unstable updates + + + + @@ -243,6 +267,39 @@ + + + + + ITL template updates + + + + + ITL template updates (testing) + + + + + + + + + (Community templates disabled) + + + + + Community template updates + + + + + Community template updates (testing) + + + +