def wait_for_domain_shutdown(vm, timeout): ''' Helper function to wait for domain shutdown. This function wait for domain shutdown, but do not initiate the shutdown itself. Note: you need to close event loop after calling this function. :param vm: QubesVM object to wait for shutdown on :param timeout: Timeout in seconds, use 0 for no timeout ''' events = qubesadmin.events.EventsDispatcher(vm.app) loop = asyncio.get_event_loop() events.add_handler('domain-shutdown', functools.partial(interrupt_on_vm_shutdown, vm)) events.add_handler('connection-established', functools.partial(interrupt_on_vm_shutdown, vm)) events_task = asyncio.ensure_future(events.listen_for_events(), loop=loop) if timeout: # pylint: disable=no-member loop.call_later(timeout, events_task.cancel) try: loop.run_until_complete(events_task) except asyncio.CancelledError: raise qubesadmin.exc.QubesVMShutdownTimeout( 'VM %s shutdown timeout expired', vm.name) except Interrupt: pass
def main(args=None): ''' 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') if args.watch and args.notify_monitor_layout: parser.error('--watch cannot be used with --notify-monitor-layout') launcher = GUILauncher(args.app) if args.watch: if not have_events: parser.error('--watch option require Python >= 3.5') with daemon.pidfile.TimeoutPIDLockFile(args.pidfile): loop = asyncio.get_event_loop() # pylint: disable=no-member events = qubesadmin.events.EventsDispatcher(args.app) # pylint: enable=no-member launcher.register_events(events) events_listener = asyncio.ensure_future(events.listen_for_events()) for signame in ('SIGINT', 'SIGTERM'): loop.add_signal_handler(getattr(signal, signame), events_listener.cancel) # pylint: disable=no-member loop.add_signal_handler(signal.SIGHUP, launcher.send_monitor_layout_all) conn = xcffib.connect() x_fd = conn.get_file_descriptor() loop.add_reader(x_fd, x_reader, conn, events_listener.cancel) try: loop.run_until_complete(events_listener) except asyncio.CancelledError: pass loop.remove_reader(x_fd) loop.stop() loop.run_forever() loop.close() elif args.notify_monitor_layout: try: with open(pidfile_path, 'r') as pidfile: pid = int(pidfile.read().strip()) os.kill(pid, signal.SIGHUP) except (FileNotFoundError, ValueError) as e: parser.error('Cannot open pidfile {}: {}'.format(pidfile_path, str(e))) else: loop = asyncio.get_event_loop() tasks = [] for vm in args.domains: if vm.is_running(): tasks.append(asyncio.ensure_future(launcher.start_gui( vm, force_stubdom=args.force_stubdomain))) if tasks: loop.run_until_complete(asyncio.wait(tasks)) loop.stop() loop.run_forever() loop.close()
def wait_for_domain_shutdown(vms): ''' Helper function to wait for domain shutdown. This function wait for domain shutdown, but do not initiate the shutdown itself. :param vms: QubesVM object collection to wait for shutdown on ''' if not vms: return app = list(vms)[0].app vms = set(vms) events = qubesadmin.events.EventsDispatcher(app, enable_cache=False) events.add_handler('domain-shutdown', functools.partial(interrupt_on_vm_shutdown, vms)) events.add_handler('connection-established', functools.partial(interrupt_on_vm_shutdown, vms)) try: yield from events.listen_for_events() except Interrupt: pass
def main(args=None): """ Main function of qvm-start-daemon tool""" only_if_service_enabled = ['guivm-gui-agent', 'audiovm-audio-agent'] enabled_services = [ service for service in only_if_service_enabled if os.path.exists('/var/run/qubes-service/%s' % service) ] if not enabled_services and '--force' not in sys.argv and \ not os.path.exists('/etc/qubes-release'): 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') if args.watch and 'guivm-gui-agent' in enabled_services: args.set_keyboard_layout = True if args.set_keyboard_layout or os.path.exists('/etc/qubes-release'): guivm = args.app.domains[args.app.local_name] set_keyboard_layout(guivm) launcher = DAEMONLauncher(args.app) if args.watch: if not have_events: parser.error('--watch option require Python >= 3.5') with daemon.pidfile.TimeoutPIDLockFile(args.pidfile): loop = asyncio.get_event_loop() # pylint: disable=no-member events = qubesadmin.events.EventsDispatcher(args.app) # pylint: enable=no-member launcher.register_events(events) events_listener = asyncio.ensure_future(events.listen_for_events()) for signame in ('SIGINT', 'SIGTERM'): loop.add_signal_handler(getattr(signal, signame), events_listener.cancel) # pylint: disable=no-member loop.add_signal_handler(signal.SIGHUP, launcher.send_monitor_layout_all) conn = xcffib.connect() x_fd = conn.get_file_descriptor() loop.add_reader(x_fd, x_reader, conn, events_listener.cancel) try: loop.run_until_complete(events_listener) except asyncio.CancelledError: pass loop.remove_reader(x_fd) loop.stop() loop.run_forever() loop.close() elif args.notify_monitor_layout: try: with open(pidfile_path, 'r') as pidfile: pid = int(pidfile.read().strip()) os.kill(pid, signal.SIGHUP) except (FileNotFoundError, ValueError) as e: parser.error('Cannot open pidfile {}: {}'.format( pidfile_path, str(e))) else: loop = asyncio.get_event_loop() tasks = [] for vm in args.domains: if vm.is_running(): tasks.append( asyncio.ensure_future( launcher.start_gui( vm, force_stubdom=args.force_stubdomain))) tasks.append(asyncio.ensure_future(launcher.start_audio(vm))) if tasks: loop.run_until_complete(asyncio.wait(tasks)) loop.stop() loop.run_forever() loop.close()
def main(args=None): """ Main function of qvm-start-daemon tool""" only_if_service_enabled = ['guivm', 'audiovm'] enabled_services = [ service for service in only_if_service_enabled if os.path.exists('/var/run/qubes-service/%s' % service) ] if not enabled_services and '--force' not in sys.argv and \ not os.path.exists('/etc/qubes-release'): print(parser.format_help()) return args = parser.parse_args(args) if args.watch and args.notify_monitor_layout: parser.error('--watch cannot be used with --notify-monitor-layout') 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: fd = os.open(args.pidfile, os.O_RDWR | os.O_CREAT | os.O_CLOEXEC, 0o600) with os.fdopen(fd, 'r+') as lock_f: try: fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) except BlockingIOError: try: pid = int(lock_f.read().strip()) except ValueError: pid = 'unknown' print('Another GUI daemon process (with PID {}) is already ' 'running'.format(pid), file=sys.stderr) sys.exit(1) print(os.getpid(), file=lock_f) lock_f.flush() lock_f.truncate() loop = asyncio.get_event_loop() # pylint: disable=no-member events = qubesadmin.events.EventsDispatcher(args.app) # pylint: enable=no-member launcher.register_events(events) events_listener = asyncio.ensure_future(events.listen_for_events()) for signame in ('SIGINT', 'SIGTERM'): loop.add_signal_handler(getattr(signal, signame), events_listener.cancel) # pylint: disable=no-member loop.add_signal_handler(signal.SIGHUP, launcher.send_monitor_layout_all) conn = xcffib.connect() x_watcher = XWatcher(conn, args.app) x_fd = conn.get_file_descriptor() loop.add_reader(x_fd, x_watcher.event_reader, events_listener.cancel) x_watcher.update_keyboard_layout() try: loop.run_until_complete(events_listener) except asyncio.CancelledError: pass loop.remove_reader(x_fd) loop.stop() loop.run_forever() loop.close() elif args.notify_monitor_layout: try: with open(pidfile_path, 'r', encoding='ascii') as pidfile: pid = int(pidfile.read().strip()) os.kill(pid, signal.SIGHUP) except (FileNotFoundError, ValueError) as e: parser.error('Cannot open pidfile {}: {}'.format( pidfile_path, str(e))) else: loop = asyncio.get_event_loop() tasks = [] for vm in args.domains: if vm.is_running(): tasks.append( asyncio.ensure_future( launcher.start_gui( vm, force_stubdom=args.force_stubdomain))) tasks.append(asyncio.ensure_future(launcher.start_audio(vm))) if tasks: loop.run_until_complete(asyncio.wait(tasks)) loop.stop() loop.run_forever() loop.close()