Skip to content

Commit

Permalink
qvm-start-daemon: allow --watch without --all
Browse files Browse the repository at this point in the history
Allow specifying VM names to look for.
  • Loading branch information
pwmarcz committed Jul 29, 2020
1 parent cb7f191 commit c6be7ca
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 10 deletions.
2 changes: 1 addition & 1 deletion doc/manpages/qvm-start-daemon.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Options

.. option:: --watch

Keep watching for further domains startups, must be used with --all
Keep watching for further domain startups

.. option:: --force-stubdomain

Expand Down
50 changes: 41 additions & 9 deletions qubesadmin/tools/qvm_start_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,14 +314,17 @@ def get_monitor_layout():
class DAEMONLauncher:
"""Launch GUI/AUDIO daemon for VMs"""

def __init__(self, app: qubesadmin.app.QubesBase):
def __init__(self, app: qubesadmin.app.QubesBase, vm_names=None, kde=False):
""" Initialize DAEMONLauncher.
:param app: :py:class:`qubesadmin.Qubes` instance
:param vm_names: VM names to watch for, or None if watching for all
:param kde: add KDE-specific arguments for guid
"""
self.app = app
self.started_processes = {}
self.kde = False
self.vm_names = vm_names
self.kde = kde

async def send_monitor_layout(self, vm, layout=None, startup=False):
"""Send monitor layout to a given VM
Expand Down Expand Up @@ -582,6 +585,10 @@ async def start_audio(self, vm):

def on_domain_spawn(self, vm, _event, **kwargs):
"""Handler of 'domain-spawn' event, starts GUI daemon for stubdomain"""

if not self.is_watched(vm):
return

try:
if getattr(vm, 'guivm', None) != vm.app.local_name:
return
Expand All @@ -596,6 +603,10 @@ def on_domain_spawn(self, vm, _event, **kwargs):
def on_domain_start(self, vm, _event, **kwargs):
"""Handler of 'domain-start' event, starts GUI/AUDIO daemon for
actual VM """

if not self.is_watched(vm):
return

try:
if getattr(vm, 'guivm', None) == vm.app.local_name and \
vm.features.check_with_template('gui', True) and \
Expand All @@ -622,6 +633,9 @@ def on_connection_established(self, _subject, _event, **_kwargs):
if vm.klass == 'AdminVM':
continue

if not self.is_watched(vm):
return

power_state = vm.get_power_state()
if power_state == 'Running':
asyncio.ensure_future(
Expand All @@ -636,6 +650,10 @@ def on_connection_established(self, _subject, _event, **_kwargs):

def on_domain_stopped(self, vm, _event, **_kwargs):
"""Handler of 'domain-stopped' event, cleans up"""

if not self.is_watched(vm):
return

self.cleanup_guid(vm.xid)
if vm.virt_mode == 'hvm':
self.cleanup_guid(vm.stubdom_xid)
Expand All @@ -658,6 +676,16 @@ def register_events(self, events):
self.on_connection_established)
events.add_handler('domain-stopped', self.on_domain_stopped)

def is_watched(self, vm):
"""
Should we watch this VM for changes
"""

if self.vm_names is None:
return True
return vm.name in self.vm_names


if 'XDG_RUNTIME_DIR' in os.environ:
pidfile_path = os.path.join(os.environ['XDG_RUNTIME_DIR'],
'qvm-start-daemon.pid')
Expand All @@ -668,8 +696,7 @@ def register_events(self, events):
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 domain startups')
parser.add_argument('--force-stubdomain', action='store_true',
help='Start GUI to stubdomain-emulated VGA,'
' even if gui-agent is running in the VM')
Expand All @@ -696,13 +723,18 @@ def main(args=None):
print(parser.format_help())
return
args = parser.parse_args(args)
if args.watch and not args.all_domains:
parser.error('--watch option must be used with --all')
if args.watch and args.notify_monitor_layout:
parser.error('--watch cannot be used with --notify-monitor-layout')
launcher = DAEMONLauncher(args.app)
if args.kde:
launcher.kde = True

if args.all_domains:
vm_names = None
else:
vm_names = [vm.name for vm in args.domains]
launcher = DAEMONLauncher(
args.app,
vm_names=vm_names,
kde=args.kde)

if args.watch:
with daemon.pidfile.TimeoutPIDLockFile(args.pidfile):
loop = asyncio.get_event_loop()
Expand Down

0 comments on commit c6be7ca

Please sign in to comment.