def start_gui_for_vm(self, vm, monitor_layout=None): """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)]) if vm.virt_mode == 'hvm': guid_cmd.extend(['-n']) stubdom_guid_pidfile = self.guid_pidfile(vm.stubdom_xid) if not vm.debug and os.path.exists(stubdom_guid_pidfile): # Terminate stubdom guid once "real" gui agent connects with open(stubdom_guid_pidfile, 'r') as pidfile: stubdom_guid_pid = pidfile.read().strip() guid_cmd += ['-K', stubdom_guid_pid] vm.log.info('Starting GUI') yield from asyncio.create_subprocess_exec(*guid_cmd) yield from self.send_monitor_layout(vm, layout=monitor_layout, startup=True)
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 send_monitor_layout(self, vm, layout=None, startup=False): """Send monitor layout to a given VM This function is a coroutine. :param vm: VM to which send monitor layout :param layout: monitor layout to send; if None, fetch it from 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(): return if layout is None: layout = get_monitor_layout() if not layout: return vm.log.info('Sending monitor layout') if not startup: with open(self.guid_pidfile(vm.xid)) as pidfile: pid = int(pidfile.read()) os.kill(pid, signal.SIGHUP) try: with open(self.guid_pidfile(vm.stubdom_xid)) as pidfile: pid = int(pidfile.read()) os.kill(pid, signal.SIGHUP) except FileNotFoundError: 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)) except subprocess.CalledProcessError as e: vm.log.warning('Failed to send monitor layout: %s', e.stderr)
def stop(self): """ Stop the agent process """ with open(self.pidfile, 'r') as pidfile: pid = int(pidfile.read().strip()) proc = psutil.Process(pid) proc.terminate()
def stop(self): """ Stop the agent process """ with open(self.pidfile, 'r') as pidfile: pid = int(pidfile.read().strip()) proc = psutil.Process(pid) proc.terminate()
def _stop(app, name, config): try: with open(_pid_file(app,name), 'r') as pidfile: pid = int(pidfile.read()) log.info('Killing process {}'.format(pid)) try: os.kill(pid, signal.SIGINT) except: pass while True: try: os.kill(pid, 0) time.sleep(1) except Exception as e: break service = config['services'][name] replicas = int(service.get('deploy', {}).get('replicas', 1)) log.info("Stopped instance {}.{} (x{})".format(app, name, replicas)) except FileNotFoundError: pass
def start_gui_for_vm(self, vm): '''Start GUI daemon (qubes-guid) connected directly to a VM This function is a coroutine. ''' guid_cmd = self.common_guid_args(vm) guid_cmd.extend(['-d', str(vm.xid)]) if vm.hvm: guid_cmd.extend(['-n']) if vm.features.check_with_template('rpc-clipboard', False): guid_cmd.extend(['-Q']) stubdom_guid_pidfile = self.guid_pidfile(vm.stubdom_xid) if not vm.debug and os.path.exists(stubdom_guid_pidfile): # Terminate stubdom guid once "real" gui agent connects with open(stubdom_guid_pidfile, 'r') as pidfile: stubdom_guid_pid = pidfile.read().strip() guid_cmd += ['-K', stubdom_guid_pid] return asyncio.create_subprocess_exec(*guid_cmd)
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()