Esempio n. 1
0
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
Esempio n. 2
0
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()
Esempio n. 3
0
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
Esempio n. 4
0
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()