From a5102d752f33ba9267b75afd40e34cb51dcff104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 13:24:56 +0200 Subject: [PATCH 1/9] Make PEP8 happier --- qubesadmin/app.py | 10 +-- qubesadmin/qubesadmin | 1 - qubesadmin/tools/qvm_start_gui.py | 134 ++++++++++++++++-------------- 3 files changed, 77 insertions(+), 68 deletions(-) delete mode 120000 qubesadmin/qubesadmin diff --git a/qubesadmin/app.py b/qubesadmin/app.py index 3f580e3..0e60424 100644 --- a/qubesadmin/app.py +++ b/qubesadmin/app.py @@ -167,13 +167,13 @@ class QubesBase(qubesadmin.base.PropertyHolder): def list_vmclass(self): """Call Qubesd in order to obtain the vm classes list""" - vmclass = self.qubesd_call('dom0', 'admin.vmclass.List')\ + vmclass = self.qubesd_call('dom0', 'admin.vmclass.List') \ .decode().splitlines() return sorted(vmclass) def list_deviceclass(self): """Call Qubesd in order to obtain the device classes list""" - deviceclasses = self.qubesd_call('dom0', 'admin.deviceclass.List')\ + deviceclasses = self.qubesd_call('dom0', 'admin.deviceclass.List') \ .decode().splitlines() return sorted(deviceclasses) @@ -715,8 +715,8 @@ class QubesRemote(QubesBase): kwargs.setdefault('stderr', subprocess.PIPE) proc = subprocess.Popen( [qubesadmin.config.QREXEC_CLIENT_VM] + - qrexec_opts + - [dest or '', service] + - (shlex.split(localcmd) if localcmd else []), + qrexec_opts + + [dest or '', service] + + (shlex.split(localcmd) if localcmd else []), **kwargs) return proc diff --git a/qubesadmin/qubesadmin b/qubesadmin/qubesadmin deleted file mode 120000 index d8da336..0000000 --- a/qubesadmin/qubesadmin +++ /dev/null @@ -1 +0,0 @@ -/home/user/qubes-builder/qubes-src/core-admin-client/qubesadmin \ No newline at end of file diff --git a/qubesadmin/tools/qvm_start_gui.py b/qubesadmin/tools/qvm_start_gui.py index 31ebf40..4db27f6 100644 --- a/qubesadmin/tools/qvm_start_gui.py +++ b/qubesadmin/tools/qvm_start_gui.py @@ -18,7 +18,7 @@ # You should have received a copy of the GNU Lesser General Public License along # with this program; if not, see . -''' GUI daemon launcher tool''' +""" GUI daemon launcher tool""" import os import signal @@ -35,10 +35,12 @@ import qubesadmin import qubesadmin.exc import qubesadmin.tools import qubesadmin.vm + have_events = False try: # pylint: disable=wrong-import-position import qubesadmin.events + have_events = True except ImportError: pass @@ -47,7 +49,7 @@ GUI_DAEMON_PATH = '/usr/bin/qubes-guid' QUBES_ICON_DIR = '/usr/share/icons/hicolor/128x128/devices' # "LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm" -REGEX_OUTPUT = re.compile(r''' +REGEX_OUTPUT = re.compile(r""" (?x) # ignore whitespace ^ # start of string (?P[A-Za-z0-9\-]*)[ ] # LVDS VGA etc @@ -67,11 +69,11 @@ REGEX_OUTPUT = re.compile(r''' )? .* # ignore rest of line )? # everything after (dis)connect is optional - ''') + """) def get_monitor_layout(): - '''Get list of monitors and their size/position''' + """Get list of monitors and their size/position""" outputs = [] for line in subprocess.Popen( @@ -85,7 +87,7 @@ def get_monitor_layout(): # don't provide real values for privacy reasons - see # #1951 for details dpi = (int(output_params['width']) * 254 // - int(output_params['width_mm']) // 10) + int(output_params['width_mm']) // 10) if dpi > 300: dpi = 300 elif dpi > 200: @@ -102,28 +104,29 @@ def get_monitor_layout(): int(output_params['height']) * 254 // dpi // 10, ) outputs.append("%s %s %s %s%s\n" % ( - output_params['width'], - output_params['height'], - output_params['x'], - output_params['y'], - phys_size, + output_params['width'], + output_params['height'], + output_params['x'], + output_params['y'], + phys_size, )) return outputs class GUILauncher(object): - '''Launch GUI daemon for VMs''' + """Launch GUI daemon for VMs""" + def __init__(self, app: qubesadmin.app.QubesBase): - ''' Initialize GUILauncher. + """ Initialize GUILauncher. :param app: :py:class:`qubesadmin.Qubes` instance - ''' + """ self.app = app self.started_processes = {} @staticmethod def kde_guid_args(vm): - '''Return KDE-specific arguments for gui-daemon, if applicable''' + """Return KDE-specific arguments for gui-daemon, if applicable""" guid_cmd = [] # Avoid using environment variables for checking the current session, @@ -149,19 +152,20 @@ class GUILauncher(object): data_dir = os.path.expanduser('~/.local/share') guid_cmd += ['-p', - '_KDE_NET_WM_COLOR_SCHEME=s:{}'.format( - os.path.join(data_dir, - 'qubes-kde', vm.label.name + '.colors'))] + '_KDE_NET_WM_COLOR_SCHEME=s:{}'.format( + os.path.join(data_dir, + 'qubes-kde', + vm.label.name + '.colors'))] return guid_cmd def common_guid_args(self, vm): - '''Common qubes-guid arguments for PV(H), HVM and Stubdomain''' + """Common qubes-guid arguments for PV(H), HVM and Stubdomain""" guid_cmd = [GUI_DAEMON_PATH, - '-N', vm.name, - '-c', vm.label.color, - '-i', os.path.join(QUBES_ICON_DIR, vm.label.icon) + '.png', - '-l', str(vm.label.index)] + '-N', vm.name, + '-c', vm.label.color, + '-i', os.path.join(QUBES_ICON_DIR, vm.label.icon) + '.png', + '-l', str(vm.label.index)] if vm.debug: guid_cmd += ['-v', '-v'] @@ -177,19 +181,19 @@ class GUILauncher(object): @staticmethod def guid_pidfile(xid): - '''Helper function to construct a pidfile path''' + """Helper function to construct a pidfile path""" return '/var/run/qubes/guid-running.{}'.format(xid) @asyncio.coroutine def start_gui_for_vm(self, vm, monitor_layout=None): - '''Start GUI daemon (qubes-guid) connected directly to a VM + """Start GUI daemon (qubes-guid) connected directly to a VM This function is a coroutine. :param vm: VM for which start GUI daemon :param monitor_layout: monitor layout to send; if None, fetch it from local X server. - ''' + """ guid_cmd = self.common_guid_args(vm) guid_cmd.extend(['-d', str(vm.xid)]) @@ -208,14 +212,14 @@ class GUILauncher(object): yield from asyncio.create_subprocess_exec(*guid_cmd) yield from self.send_monitor_layout(vm, layout=monitor_layout, - startup=True) + startup=True) @asyncio.coroutine def start_gui_for_stubdomain(self, vm, force=False): - '''Start GUI daemon (qubes-guid) connected to a stubdomain + """Start GUI daemon (qubes-guid) connected to a stubdomain This function is a coroutine. - ''' + """ want_stubdom = force if not want_stubdom and \ vm.features.check_with_template('gui-emulated', False): @@ -239,17 +243,17 @@ class GUILauncher(object): @asyncio.coroutine def start_gui(self, vm, force_stubdom=False, monitor_layout=None): - '''Start GUI daemon regardless of start event. + """Start GUI daemon regardless of start event. This function is a coroutine. :param vm: VM for which GUI daemon should be started :param force_stubdom: Force GUI daemon for stubdomain, even if the one for target AppVM is running. - ''' + :param monitor_layout: monitor layout configuration + """ if vm.virt_mode == 'hvm': - yield from self.start_gui_for_stubdomain(vm, - force=force_stubdom) + yield from self.start_gui_for_stubdomain(vm, force=force_stubdom) if not vm.features.check_with_template('gui', True): return @@ -259,7 +263,7 @@ class GUILauncher(object): @asyncio.coroutine def send_monitor_layout(self, vm, layout=None, startup=False): - '''Send monitor layout to a given VM + """Send monitor layout to a given VM This function is a coroutine. @@ -268,7 +272,7 @@ class GUILauncher(object): local X server. :param startup: :return: None - ''' + """ # pylint: disable=no-self-use if vm.features.check_with_template('no-monitor-layout', False) \ or not vm.is_running(): @@ -293,16 +297,18 @@ class GUILauncher(object): pass try: - yield from asyncio.get_event_loop().run_in_executor(None, - functools.partial(vm.run_service_for_stdio, - 'qubes.SetMonitorLayout', - input=''.join(layout).encode(), - autostart=False)) + yield from asyncio.get_event_loop(). \ + run_in_executor(None, + functools.partial( + vm.run_service_for_stdio, + 'qubes.SetMonitorLayout', + input=''.join(layout).encode(), + autostart=False)) except subprocess.CalledProcessError as e: vm.log.warning('Failed to send monitor layout: %s', e.stderr) def send_monitor_layout_all(self): - '''Send monitor layout to all (running) VMs''' + """Send monitor layout to all (running) VMs""" monitor_layout = get_monitor_layout() for vm in self.app.domains: if vm.klass == 'AdminVM': @@ -311,10 +317,10 @@ class GUILauncher(object): if not vm.features.check_with_template('gui', True): continue asyncio.ensure_future(self.send_monitor_layout(vm, - monitor_layout)) + monitor_layout)) def on_domain_spawn(self, vm, _event, **kwargs): - '''Handler of 'domain-spawn' event, starts GUI daemon for stubdomain''' + """Handler of 'domain-spawn' event, starts GUI daemon for stubdomain""" try: if not vm.features.check_with_template('gui', True): return @@ -325,7 +331,7 @@ class GUILauncher(object): vm.log.warning('Failed to start GUI for %s: %s', vm.name, str(e)) def on_domain_start(self, vm, _event, **kwargs): - '''Handler of 'domain-start' event, starts GUI daemon for actual VM''' + """Handler of 'domain-start' event, starts GUI daemon for actual VM""" try: if not vm.features.check_with_template('gui', True): return @@ -335,8 +341,8 @@ class GUILauncher(object): vm.log.warning('Failed to start GUI for %s: %s', vm.name, str(e)) def on_connection_established(self, _subject, _event, **_kwargs): - '''Handler of 'connection-established' event, used to launch GUI - daemon for domains started before this tool. ''' + """Handler of 'connection-established' event, used to launch GUI + daemon for domains started before this tool. """ monitor_layout = get_monitor_layout() self.app.domains.clear_cache() @@ -347,8 +353,8 @@ class GUILauncher(object): continue power_state = vm.get_power_state() if power_state == 'Running': - asyncio.ensure_future(self.start_gui(vm, - monitor_layout=monitor_layout)) + asyncio.ensure_future( + self.start_gui(vm, monitor_layout=monitor_layout)) elif power_state == 'Transient': # it is still starting, we'll get 'domain-start' event when # fully started @@ -356,43 +362,47 @@ class GUILauncher(object): asyncio.ensure_future(self.start_gui_for_stubdomain(vm)) def register_events(self, events): - '''Register domain startup events in app.events dispatcher''' + """Register domain startup events in app.events dispatcher""" events.add_handler('domain-spawn', self.on_domain_spawn) events.add_handler('domain-start', self.on_domain_start) events.add_handler('connection-established', - self.on_connection_established) + self.on_connection_established) + def x_reader(conn, callback): - '''Try reading something from X connection to check if it's still alive. + """Try reading something from X connection to check if it's still alive. In case it isn't, call *callback*. - ''' + """ try: conn.poll_for_event() except xcffib.ConnectionException: callback() + if 'XDG_RUNTIME_DIR' in os.environ: pidfile_path = os.path.join(os.environ['XDG_RUNTIME_DIR'], - 'qvm-start-gui.pid') + 'qvm-start-gui.pid') else: pidfile_path = os.path.join(os.environ.get('HOME', '/'), - '.qvm-start-gui.pid') + '.qvm-start-gui.pid') parser = qubesadmin.tools.QubesArgumentParser( description='start GUI for qube(s)', vmname_nargs='*') parser.add_argument('--watch', action='store_true', - help='Keep watching for further domains startups, must be used with --all') + help='Keep watching for further domains' + ' startups, must be used with --all') parser.add_argument('--force-stubdomain', action='store_true', - help='Start GUI to stubdomain-emulated VGA, even if gui-agent is running ' - 'in the VM') + help='Start GUI to stubdomain-emulated VGA,' + ' even if gui-agent is running in the VM') parser.add_argument('--pidfile', action='store', default=pidfile_path, - help='Pidfile path to create in --watch mode') + help='Pidfile path to create in --watch mode') parser.add_argument('--notify-monitor-layout', action='store_true', - help='Notify running instance in --watch mode about changed monitor layout') + help='Notify running instance in --watch mode' + ' about changed monitor layout') def main(args=None): - ''' Main function of qvm-start-gui tool''' + """ Main function of qvm-start-gui tool""" args = parser.parse_args(args) if args.watch and not args.all_domains: parser.error('--watch option must be used with --all') @@ -413,10 +423,10 @@ def main(args=None): for signame in ('SIGINT', 'SIGTERM'): loop.add_signal_handler(getattr(signal, signame), - events_listener.cancel) # pylint: disable=no-member + events_listener.cancel) # pylint: disable=no-member loop.add_signal_handler(signal.SIGHUP, - launcher.send_monitor_layout_all) + launcher.send_monitor_layout_all) conn = xcffib.connect() x_fd = conn.get_file_descriptor() @@ -437,7 +447,7 @@ def main(args=None): os.kill(pid, signal.SIGHUP) except (FileNotFoundError, ValueError) as e: parser.error('Cannot open pidfile {}: {}'.format(pidfile_path, - str(e))) + str(e))) else: loop = asyncio.get_event_loop() tasks = [] From 6b4a99f83f327e060cb8a361c41728e3f2a12dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 13:31:57 +0200 Subject: [PATCH 2/9] qvm-start-gui: handle GuiVM --- qubesadmin/app.py | 4 ++++ qubesadmin/tools/qvm_start_gui.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/qubesadmin/app.py b/qubesadmin/app.py index 0e60424..2fd47db 100644 --- a/qubesadmin/app.py +++ b/qubesadmin/app.py @@ -226,6 +226,10 @@ class QubesBase(qubesadmin.base.PropertyHolder): """ Remove a storage pool """ self.qubesd_call('dom0', 'admin.pool.Remove', name, None) + @staticmethod + def get_local_name(): + return os.uname()[1] + def get_label(self, label): """Get label as identified by index or name diff --git a/qubesadmin/tools/qvm_start_gui.py b/qubesadmin/tools/qvm_start_gui.py index 4db27f6..bfbb567 100644 --- a/qubesadmin/tools/qvm_start_gui.py +++ b/qubesadmin/tools/qvm_start_gui.py @@ -252,6 +252,11 @@ class GUILauncher(object): one for target AppVM is running. :param monitor_layout: monitor layout configuration """ + if vm.guivm != vm.app.get_local_name(): + vm.log.info( + '{} has GuiVM {}. Skipping.'.format(vm.name, vm.guivm)) + return + if vm.virt_mode == 'hvm': yield from self.start_gui_for_stubdomain(vm, force=force_stubdom) @@ -311,6 +316,8 @@ class GUILauncher(object): """Send monitor layout to all (running) VMs""" monitor_layout = get_monitor_layout() for vm in self.app.domains: + if vm.guivm != vm.app.get_local_name(): + continue if vm.klass == 'AdminVM': continue if vm.is_running(): @@ -322,6 +329,8 @@ class GUILauncher(object): def on_domain_spawn(self, vm, _event, **kwargs): """Handler of 'domain-spawn' event, starts GUI daemon for stubdomain""" try: + if vm.guivm != vm.app.get_local_name(): + return if not vm.features.check_with_template('gui', True): return if vm.virt_mode == 'hvm' and \ @@ -333,6 +342,8 @@ class GUILauncher(object): def on_domain_start(self, vm, _event, **kwargs): """Handler of 'domain-start' event, starts GUI daemon for actual VM""" try: + if vm.guivm != vm.app.get_local_name(): + return if not vm.features.check_with_template('gui', True): return if kwargs.get('start_guid', 'True') == 'True': @@ -349,6 +360,11 @@ class GUILauncher(object): for vm in self.app.domains: if vm.klass == 'AdminVM': continue + try: + if vm.guivm != vm.app.get_local_name(): + continue + except qubesadmin.exc.QubesPropertyAccessError: + continue if not vm.features.check_with_template('gui', True): continue power_state = vm.get_power_state() From e63510b4cf30ec9c9071b42544023feea625da7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 15:11:24 +0200 Subject: [PATCH 3/9] guivm: use getattr instead of try/except and direct property access --- qubesadmin/tools/qvm_start_gui.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/qubesadmin/tools/qvm_start_gui.py b/qubesadmin/tools/qvm_start_gui.py index bfbb567..45357d7 100644 --- a/qubesadmin/tools/qvm_start_gui.py +++ b/qubesadmin/tools/qvm_start_gui.py @@ -252,9 +252,10 @@ class GUILauncher(object): one for target AppVM is running. :param monitor_layout: monitor layout configuration """ - if vm.guivm != vm.app.get_local_name(): + guivm_name = getattr(vm, 'guivm', None) + if guivm_name != vm.app.get_local_name(): vm.log.info( - '{} has GuiVM {}. Skipping.'.format(vm.name, vm.guivm)) + '{} has GuiVM {}. Skipping.'.format(vm.name, guivm_name)) return if vm.virt_mode == 'hvm': @@ -316,7 +317,7 @@ class GUILauncher(object): """Send monitor layout to all (running) VMs""" monitor_layout = get_monitor_layout() for vm in self.app.domains: - if vm.guivm != vm.app.get_local_name(): + if getattr(vm, 'guivm', None) != vm.app.get_local_name(): continue if vm.klass == 'AdminVM': continue @@ -329,7 +330,7 @@ class GUILauncher(object): def on_domain_spawn(self, vm, _event, **kwargs): """Handler of 'domain-spawn' event, starts GUI daemon for stubdomain""" try: - if vm.guivm != vm.app.get_local_name(): + if getattr(vm, 'guivm', None) != vm.app.get_local_name(): return if not vm.features.check_with_template('gui', True): return @@ -342,7 +343,7 @@ class GUILauncher(object): def on_domain_start(self, vm, _event, **kwargs): """Handler of 'domain-start' event, starts GUI daemon for actual VM""" try: - if vm.guivm != vm.app.get_local_name(): + if getattr(vm, 'guivm', None) != vm.app.get_local_name(): return if not vm.features.check_with_template('gui', True): return @@ -360,10 +361,7 @@ class GUILauncher(object): for vm in self.app.domains: if vm.klass == 'AdminVM': continue - try: - if vm.guivm != vm.app.get_local_name(): - continue - except qubesadmin.exc.QubesPropertyAccessError: + if getattr(vm, 'guivm', None) != vm.app.get_local_name(): continue if not vm.features.check_with_template('gui', True): continue From 411e2884ccc9be8b566d62143df71422e392e1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 15:53:32 +0200 Subject: [PATCH 4/9] qvm-start-gui: simplify log info for start_gui function --- qubesadmin/tools/qvm_start_gui.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/qubesadmin/tools/qvm_start_gui.py b/qubesadmin/tools/qvm_start_gui.py index 45357d7..7de5479 100644 --- a/qubesadmin/tools/qvm_start_gui.py +++ b/qubesadmin/tools/qvm_start_gui.py @@ -252,10 +252,9 @@ class GUILauncher(object): one for target AppVM is running. :param monitor_layout: monitor layout configuration """ - guivm_name = getattr(vm, 'guivm', None) - if guivm_name != vm.app.get_local_name(): - vm.log.info( - '{} has GuiVM {}. Skipping.'.format(vm.name, guivm_name)) + guivm = getattr(vm, 'guivm', None) + if guivm != vm.app.get_local_name(): + vm.log.info('GUI connected to {}. Skipping.'.format(guivm)) return if vm.virt_mode == 'hvm': From 40d9696b90ed15b1cfd2506f63f5f956071913b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 17:41:41 +0200 Subject: [PATCH 5/9] app: fix missing docstring for get_local_name --- qubesadmin/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qubesadmin/app.py b/qubesadmin/app.py index 2fd47db..f512c38 100644 --- a/qubesadmin/app.py +++ b/qubesadmin/app.py @@ -228,6 +228,7 @@ class QubesBase(qubesadmin.base.PropertyHolder): @staticmethod def get_local_name(): + """ Get localhost name """ return os.uname()[1] def get_label(self, label): From 8a27c1919f6fc0051f0d5c95c470a5e282b1db70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 19:20:40 +0200 Subject: [PATCH 6/9] app: get_local_name set/from self attribute --- qubesadmin/app.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/qubesadmin/app.py b/qubesadmin/app.py index f512c38..9bfc5b3 100644 --- a/qubesadmin/app.py +++ b/qubesadmin/app.py @@ -153,6 +153,8 @@ class QubesBase(qubesadmin.base.PropertyHolder): log = None #: do not check for object (VM, label etc) existence before really needed blind_mode = False + #: local name + local_name = None def __init__(self): super(QubesBase, self).__init__(self, 'admin.property.', 'dom0') @@ -226,10 +228,12 @@ class QubesBase(qubesadmin.base.PropertyHolder): """ Remove a storage pool """ self.qubesd_call('dom0', 'admin.pool.Remove', name, None) - @staticmethod - def get_local_name(): + def get_local_name(self): """ Get localhost name """ - return os.uname()[1] + if not self.local_name: + self.local_name = os.uname()[1] + + return self.local_name def get_label(self, label): """Get label as identified by index or name From 63e63f0bcf049cb1db0a336774927e7c8b824644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 19:20:58 +0200 Subject: [PATCH 7/9] tests: fix with respect to gui properties --- qubesadmin/tests/tools/qvm_start_gui.py | 29 ++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/qubesadmin/tests/tools/qvm_start_gui.py b/qubesadmin/tests/tools/qvm_start_gui.py index 6d1a5dd..f6d5b87 100644 --- a/qubesadmin/tests/tools/qvm_start_gui.py +++ b/qubesadmin/tests/tools/qvm_start_gui.py @@ -369,7 +369,8 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): self.app.expected_calls[ ('dom0', 'admin.vm.List', None, None)] = \ - b'0\x00test-vm class=AppVM state=Running\n' + b'0\x00test-vm class=AppVM state=Running\n' \ + b'gui-vm class=AppVM state=Running' self.app.expected_calls[ ('test-vm', 'admin.vm.List', None, None)] = \ b'0\x00test-vm class=AppVM state=Running\n' @@ -389,7 +390,11 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'stubdom_xid', None)] = \ b'0\x00default=False type=int 3001' + self.app.expected_calls[ + ('test-vm', 'admin.vm.property.Get', 'guivm', None)] = \ + b'0\x00default=False type=vm gui-vm' + self.app.local_name = 'gui-vm' vm = self.app.domains['test-vm'] mock_start_vm = unittest.mock.Mock() mock_start_stubdomain = unittest.mock.Mock() @@ -625,8 +630,9 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x ('dom0', 'admin.vm.List', None, None)] = \ b'0\x00test-vm class=AppVM state=Running\n' \ b'test-vm2 class=AppVM state=Running\n' \ - b'test-vm3 class=AppVM state=Runnig\n' \ - b'test-vm4 class=AppVM state=Halted\n' + b'test-vm3 class=AppVM state=Running\n' \ + b'test-vm4 class=AppVM state=Halted\n' \ + b'gui-vm class=AppVM state=Running' self.app.expected_calls[ ('test-vm', 'admin.vm.List', None, None)] = \ b'0\x00test-vm class=AppVM state=Running\n' @@ -651,6 +657,23 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x ('test-vm3', 'admin.vm.feature.CheckWithTemplate', 'gui', None)] = \ b'0\x00' + self.app.expected_calls[ + ('gui-vm', 'admin.vm.property.Get', 'guivm', None)] = \ + b'0\x00default=True type=vm ' + self.app.expected_calls[ + ('test-vm', 'admin.vm.property.Get', 'guivm', None)] = \ + b'0\x00default=False type=vm gui-vm' + self.app.expected_calls[ + ('test-vm2', 'admin.vm.property.Get', 'guivm', None)] = \ + b'0\x00default=False type=vm gui-vm' + self.app.expected_calls[ + ('test-vm3', 'admin.vm.property.Get', 'guivm', None)] = \ + b'0\x00default=False type=vm gui-vm' + self.app.expected_calls[ + ('test-vm4', 'admin.vm.property.Get', 'guivm', None)] = \ + b'0\x00default=False type=vm gui-vm' + + self.app.local_name = 'gui-vm' vm = self.app.domains['test-vm'] vm2 = self.app.domains['test-vm2'] From f7740546c909dffdfce60481411be76770392915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 19:25:21 +0200 Subject: [PATCH 8/9] tests: qvm_start_gui: make PEP8 happier --- qubesadmin/tests/tools/qvm_start_gui.py | 140 +++++++++++++----------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/qubesadmin/tests/tools/qvm_start_gui.py b/qubesadmin/tests/tools/qvm_start_gui.py index f6d5b87..9ec4337 100644 --- a/qubesadmin/tests/tools/qvm_start_gui.py +++ b/qubesadmin/tests/tools/qvm_start_gui.py @@ -42,7 +42,7 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'label', None)] = \ - b'0\x00default=False type=label red' + b'0\x00default=False type=label red' proc_mock.side_effect = [ b'KWIN_RUNNING = 0x1\n', @@ -53,8 +53,9 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): args = self.launcher.kde_guid_args(self.app.domains['test-vm']) self.assertEqual(args, ['-T', '-p', - '_KDE_NET_WM_COLOR_SCHEME=s:' + - os.path.expanduser('~/.local/share/qubes-kde/red.colors')]) + '_KDE_NET_WM_COLOR_SCHEME=s:' + + os.path.expanduser( + '~/.local/share/qubes-kde/red.colors')]) self.assertAllCalled() @@ -77,10 +78,10 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'label', None)] = \ - b'0\x00default=False type=label red' + b'0\x00default=False type=label red' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'debug', None)] = \ - b'0\x00default=False type=bool False' + b'0\x00default=False type=bool False' self.app.expected_calls[ ('dom0', 'admin.label.Get', 'red', None)] = \ b'0\x000xff0000' @@ -89,7 +90,7 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x001' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'rpc-clipboard', None)] = \ + 'rpc-clipboard', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' with unittest.mock.patch.object(self.launcher, 'kde_guid_args') as \ @@ -111,10 +112,10 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'label', None)] = \ - b'0\x00default=False type=label red' + b'0\x00default=False type=label red' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'debug', None)] = \ - b'0\x00default=False type=bool True' + b'0\x00default=False type=bool True' self.app.expected_calls[ ('dom0', 'admin.label.Get', 'red', None)] = \ b'0\x000xff0000' @@ -123,7 +124,7 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x001' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'rpc-clipboard', None)] = \ + 'rpc-clipboard', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' with unittest.mock.patch.object(self.launcher, 'kde_guid_args') as \ @@ -145,10 +146,10 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'label', None)] = \ - b'0\x00default=False type=label red' + b'0\x00default=False type=label red' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'debug', None)] = \ - b'0\x00default=False type=bool False' + b'0\x00default=False type=bool False' self.app.expected_calls[ ('dom0', 'admin.label.Get', 'red', None)] = \ b'0\x000xff0000' @@ -157,7 +158,7 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x001' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'rpc-clipboard', None)] = \ + 'rpc-clipboard', None)] = \ b'0\x001' with unittest.mock.patch.object(self.launcher, 'kde_guid_args') as \ @@ -187,16 +188,16 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'xid', None)] = \ - b'0\x00default=False type=int 3000' + b'0\x00default=False type=int 3000' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'virt_mode', None)] = \ - b'0\x00default=False type=str pv' + b'0\x00default=False type=str pv' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' with unittest.mock.patch.object(self.launcher, - 'common_guid_args', lambda vm: []): + 'common_guid_args', lambda vm: []): loop.run_until_complete(self.launcher.start_gui_for_vm( self.app.domains['test-vm'])) # common arguments dropped for simplicity @@ -218,22 +219,22 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'xid', None)] = \ - b'0\x00default=False type=int 3000' + b'0\x00default=False type=int 3000' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'stubdom_xid', None)] = \ - b'0\x00default=False type=int 3001' + b'0\x00default=False type=int 3001' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'virt_mode', None)] = \ - b'0\x00default=False type=str hvm' + b'0\x00default=False type=str hvm' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'debug', None)] = \ - b'0\x00default=False type=bool False' + b'0\x00default=False type=bool False' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' with unittest.mock.patch.object(self.launcher, - 'common_guid_args', lambda vm: []): + 'common_guid_args', lambda vm: []): loop.run_until_complete(self.launcher.start_gui_for_vm( self.app.domains['test-vm'])) # common arguments dropped for simplicity @@ -254,19 +255,19 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'xid', None)] = \ - b'0\x00default=False type=int 3000' + b'0\x00default=False type=int 3000' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'stubdom_xid', None)] = \ - b'0\x00default=False type=int 3001' + b'0\x00default=False type=int 3001' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'virt_mode', None)] = \ - b'0\x00default=False type=str hvm' + b'0\x00default=False type=str hvm' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'debug', None)] = \ - b'0\x00default=False type=bool False' + b'0\x00default=False type=bool False' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' pidfile = tempfile.NamedTemporaryFile() pidfile.write(b'1234\n') @@ -275,9 +276,11 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): patch_proc = unittest.mock.patch('asyncio.create_subprocess_exec') patch_args = unittest.mock.patch.object(self.launcher, - 'common_guid_args', lambda vm: []) + 'common_guid_args', + lambda vm: []) patch_pidfile = unittest.mock.patch.object(self.launcher, - 'guid_pidfile', lambda vm: pidfile.name) + 'guid_pidfile', + lambda vm: pidfile.name) try: mock_proc = patch_proc.start() patch_args.start() @@ -302,22 +305,23 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'xid', None)] = \ - b'0\x00default=False type=int 3000' + b'0\x00default=False type=int 3000' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'stubdom_xid', None)] = \ - b'0\x00default=False type=int 3001' + b'0\x00default=False type=int 3001' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui-emulated', - None)] = \ + None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' proc_mock = unittest.mock.Mock() with unittest.mock.patch('asyncio.create_subprocess_exec', - lambda *args: self.mock_coroutine(proc_mock, *args)): + lambda *args: self.mock_coroutine(proc_mock, + *args)): with unittest.mock.patch.object(self.launcher, - 'common_guid_args', lambda vm: []): + 'common_guid_args', lambda vm: []): loop.run_until_complete(self.launcher.start_gui_for_stubdomain( self.app.domains['test-vm'])) # common arguments dropped for simplicity @@ -335,22 +339,23 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'xid', None)] = \ - b'0\x00default=False type=int 3000' + b'0\x00default=False type=int 3000' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'stubdom_xid', None)] = \ - b'0\x00default=False type=int 3001' + b'0\x00default=False type=int 3001' # self.app.expected_calls[ - # ('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui', None)] = \ - # b'0\x00' + # ('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui', None)] = \ + # b'0\x00' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui-emulated', - None)] = \ + None)] = \ b'0\x001' proc_mock = unittest.mock.Mock() with unittest.mock.patch('asyncio.create_subprocess_exec', - lambda *args: self.mock_coroutine(proc_mock, *args)): + lambda *args: self.mock_coroutine(proc_mock, + *args)): with unittest.mock.patch.object(self.launcher, - 'common_guid_args', lambda vm: []): + 'common_guid_args', lambda vm: []): loop.run_until_complete(self.launcher.start_gui_for_stubdomain( self.app.domains['test-vm'])) # common arguments dropped for simplicity @@ -379,17 +384,17 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): b'0\x00True' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'virt_mode', None)] = \ - b'0\x00default=False type=str hvm' + b'0\x00default=False type=str hvm' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'xid', None)] = \ - b'0\x00default=False type=int 3000' + b'0\x00default=False type=int 3000' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'stubdom_xid', None)] = \ - b'0\x00default=False type=int 3001' + b'0\x00default=False type=int 3001' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'guivm', None)] = \ b'0\x00default=False type=vm gui-vm' @@ -445,7 +450,7 @@ VGA1 disconnected (normal left inverted right x axis y axis) VIRTUAL1 disconnected (normal left inverted right x axis y axis) '''.splitlines() self.assertEqual(qubesadmin.tools.qvm_start_gui.get_monitor_layout(), - ['1920 1200 0 0\n']) + ['1920 1200 0 0\n']) @unittest.mock.patch('subprocess.Popen') def test_051_get_monitor_layout_multiple(self, proc_mock): @@ -454,7 +459,7 @@ LVDS1 connected 1600x900+0+0 (normal left inverted right x axis y axis) VGA1 connected 1280x1024+1600+0 (normal left inverted right x axis y axis) '''.splitlines() self.assertEqual(qubesadmin.tools.qvm_start_gui.get_monitor_layout(), - ['1600 900 0 0\n', '1280 1024 1600 0\n']) + ['1600 900 0 0\n', '1280 1024 1600 0\n']) @unittest.mock.patch('subprocess.Popen') def test_052_get_monitor_layout_hidpi1(self, proc_mock): @@ -464,8 +469,9 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 372mm x '''.splitlines() dpi = 150 self.assertEqual(qubesadmin.tools.qvm_start_gui.get_monitor_layout(), - ['2560 1920 0 0 {} {}\n'.format( - int(2560/dpi*254/10), int(1920/dpi*254/10))]) + ['2560 1920 0 0 {} {}\n'.format( + int(2560 / dpi * 254 / 10), + int(1920 / dpi * 254 / 10))]) @unittest.mock.patch('subprocess.Popen') def test_052_get_monitor_layout_hidpi2(self, proc_mock): @@ -475,8 +481,9 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 310mm x '''.splitlines() dpi = 200 self.assertEqual(qubesadmin.tools.qvm_start_gui.get_monitor_layout(), - ['2560 1920 0 0 {} {}\n'.format( - int(2560/dpi*254/10), int(1920/dpi*254/10))]) + ['2560 1920 0 0 {} {}\n'.format( + int(2560 / dpi * 254 / 10), + int(1920 / dpi * 254 / 10))]) @unittest.mock.patch('subprocess.Popen') def test_052_get_monitor_layout_hidpi3(self, proc_mock): @@ -486,8 +493,9 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x '''.splitlines() dpi = 300 self.assertEqual(qubesadmin.tools.qvm_start_gui.get_monitor_layout(), - ['2560 1920 0 0 {} {}\n'.format( - int(2560/dpi*254/10), int(1920/dpi*254/10))]) + ['2560 1920 0 0 {} {}\n'.format( + int(2560 / dpi * 254 / 10), + int(1920 / dpi * 254 / 10))]) def test_060_send_monitor_layout(self): loop = asyncio.new_event_loop() @@ -502,7 +510,7 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' vm = self.app.domains['test-vm'] @@ -529,7 +537,7 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x b'0\x00test-vm class=AppVM state=Running\n' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'0\x00True' vm = self.app.domains['test-vm'] @@ -558,7 +566,7 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x b'0\x00test-vm class=AppVM state=Halted\n' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' vm = self.app.domains['test-vm'] @@ -593,7 +601,7 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x b'0\x00default=False type=int 124' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'no-monitor-layout', None)] = \ + 'no-monitor-layout', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' vm = self.app.domains['test-vm'] @@ -614,11 +622,11 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x loop.run_until_complete(self.launcher.send_monitor_layout( vm, layout=monitor_layout, startup=False)) self.assertEqual(mock_guid_pidfile.mock_calls, - [unittest.mock.call(123), - unittest.mock.call(124)]) + [unittest.mock.call(123), + unittest.mock.call(124)]) self.assertEqual(mock_kill.mock_calls, - [unittest.mock.call(1234, signal.SIGHUP), - unittest.mock.call(1234, signal.SIGHUP)]) + [unittest.mock.call(1234, signal.SIGHUP), + unittest.mock.call(1234, signal.SIGHUP)]) self.assertAllCalled() def test_070_send_monitor_layout_all(self): @@ -647,15 +655,15 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x b'0\x00test-vm4 class=AppVM state=Halted\n' self.app.expected_calls[ ('test-vm', 'admin.vm.feature.CheckWithTemplate', - 'gui', None)] = \ + 'gui', None)] = \ b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00' self.app.expected_calls[ ('test-vm2', 'admin.vm.feature.CheckWithTemplate', - 'gui', None)] = \ + 'gui', None)] = \ b'0\x00True' self.app.expected_calls[ ('test-vm3', 'admin.vm.feature.CheckWithTemplate', - 'gui', None)] = \ + 'gui', None)] = \ b'0\x00' self.app.expected_calls[ ('gui-vm', 'admin.vm.property.Get', 'guivm', None)] = \ @@ -697,7 +705,7 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x # test-vm3 not called b/c feature 'gui' set to false # test-vm4 not called b/c not running self.assertCountEqual(mock_send_monitor_layout.mock_calls, - [unittest.mock.call(vm, monitor_layout), - unittest.mock.call(vm2, monitor_layout)]) + [unittest.mock.call(vm, monitor_layout), + unittest.mock.call(vm2, monitor_layout)]) mock_get_monior_layout.assert_called_once_with() self.assertAllCalled() From 03bc15dd3872303871d2226d813ef45755e3323b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Sun, 20 Oct 2019 21:12:31 +0200 Subject: [PATCH 9/9] app: switch get_local_name method to property --- qubesadmin/app.py | 12 ++++++------ qubesadmin/tests/tools/qvm_start_gui.py | 4 ++-- qubesadmin/tools/qvm_start_gui.py | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/qubesadmin/app.py b/qubesadmin/app.py index 9bfc5b3..4be23cd 100644 --- a/qubesadmin/app.py +++ b/qubesadmin/app.py @@ -153,8 +153,6 @@ class QubesBase(qubesadmin.base.PropertyHolder): log = None #: do not check for object (VM, label etc) existence before really needed blind_mode = False - #: local name - local_name = None def __init__(self): super(QubesBase, self).__init__(self, 'admin.property.', 'dom0') @@ -166,6 +164,7 @@ class QubesBase(qubesadmin.base.PropertyHolder): #: cache for available storage pool drivers and options to create them self._pool_drivers = None self.log = logging.getLogger('app') + self._local_name = None def list_vmclass(self): """Call Qubesd in order to obtain the vm classes list""" @@ -228,12 +227,13 @@ class QubesBase(qubesadmin.base.PropertyHolder): """ Remove a storage pool """ self.qubesd_call('dom0', 'admin.pool.Remove', name, None) - def get_local_name(self): + @property + def local_name(self): """ Get localhost name """ - if not self.local_name: - self.local_name = os.uname()[1] + if not self._local_name: + self._local_name = os.uname()[1] - return self.local_name + return self._local_name def get_label(self, label): """Get label as identified by index or name diff --git a/qubesadmin/tests/tools/qvm_start_gui.py b/qubesadmin/tests/tools/qvm_start_gui.py index 9ec4337..f3af184 100644 --- a/qubesadmin/tests/tools/qvm_start_gui.py +++ b/qubesadmin/tests/tools/qvm_start_gui.py @@ -399,7 +399,7 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase): ('test-vm', 'admin.vm.property.Get', 'guivm', None)] = \ b'0\x00default=False type=vm gui-vm' - self.app.local_name = 'gui-vm' + self.app._local_name = 'gui-vm' vm = self.app.domains['test-vm'] mock_start_vm = unittest.mock.Mock() mock_start_stubdomain = unittest.mock.Mock() @@ -681,7 +681,7 @@ HDMI1 connected 2560x1920+0+0 (normal left inverted right x axis y axis) 206mm x ('test-vm4', 'admin.vm.property.Get', 'guivm', None)] = \ b'0\x00default=False type=vm gui-vm' - self.app.local_name = 'gui-vm' + self.app._local_name = 'gui-vm' vm = self.app.domains['test-vm'] vm2 = self.app.domains['test-vm2'] diff --git a/qubesadmin/tools/qvm_start_gui.py b/qubesadmin/tools/qvm_start_gui.py index 7de5479..1cac518 100644 --- a/qubesadmin/tools/qvm_start_gui.py +++ b/qubesadmin/tools/qvm_start_gui.py @@ -253,7 +253,7 @@ class GUILauncher(object): :param monitor_layout: monitor layout configuration """ guivm = getattr(vm, 'guivm', None) - if guivm != vm.app.get_local_name(): + if guivm != vm.app.local_name: vm.log.info('GUI connected to {}. Skipping.'.format(guivm)) return @@ -316,7 +316,7 @@ class GUILauncher(object): """Send monitor layout to all (running) VMs""" monitor_layout = get_monitor_layout() for vm in self.app.domains: - if getattr(vm, 'guivm', None) != vm.app.get_local_name(): + if getattr(vm, 'guivm', None) != vm.app.local_name: continue if vm.klass == 'AdminVM': continue @@ -329,7 +329,7 @@ class GUILauncher(object): def on_domain_spawn(self, vm, _event, **kwargs): """Handler of 'domain-spawn' event, starts GUI daemon for stubdomain""" try: - if getattr(vm, 'guivm', None) != vm.app.get_local_name(): + if getattr(vm, 'guivm', None) != vm.app.local_name: return if not vm.features.check_with_template('gui', True): return @@ -342,7 +342,7 @@ class GUILauncher(object): def on_domain_start(self, vm, _event, **kwargs): """Handler of 'domain-start' event, starts GUI daemon for actual VM""" try: - if getattr(vm, 'guivm', None) != vm.app.get_local_name(): + if getattr(vm, 'guivm', None) != vm.app.local_name: return if not vm.features.check_with_template('gui', True): return @@ -360,7 +360,7 @@ class GUILauncher(object): for vm in self.app.domains: if vm.klass == 'AdminVM': continue - if getattr(vm, 'guivm', None) != vm.app.get_local_name(): + if getattr(vm, 'guivm', None) != vm.app.local_name: continue if not vm.features.check_with_template('gui', True): continue