def loginUser(self, username, password): for session_id in System.getActiveSessionIds(protocol="console"): System.lockSession(session_id) for _unused in range(20): if self._controlPipe.credentialProviderConnected( login_capable=True): break time.sleep(0.5) if not self._controlPipe.credentialProviderConnected( login_capable=True): raise RuntimeError( "No login capable opsi credential provider connected") logger.info( "Login capable opsi credential provider connected, calling loginUser" ) for response in self._controlPipe.executeRpc("loginUser", username, password): if not response.get("error") and response.get("result"): return True raise RuntimeError( f"opsi credential provider failed to login user '{username}': {response.get('error')}" )
def showPopup(self, message, mode='prepend', addTimestamp=True, displaySeconds=0): # pylint: disable=too-many-branches,too-many-statements, too-many-locals if mode not in ('prepend', 'append', 'replace'): mode = 'prepend' port = config.get('notification_server', 'popup_port') if not port: raise Exception('notification_server.popup_port not defined') notifierCommand = config.get('opsiclientd_notifier', 'command') if not notifierCommand: raise Exception('opsiclientd_notifier.command not defined') notifierCommand = f'{notifierCommand} -s {os.path.join("notifier", "popup.ini")}' if addTimestamp: message = "=== " + time.strftime( "%Y-%m-%d %H:%M:%S") + " ===\n" + message with self._popupNotificationLock: # pylint: disable=too-many-nested-blocks if (mode in ('prepend', 'append') and self._popupNotificationServer and self._popupNotificationServer.isListening()): # Already runnning try: for subject in self._popupNotificationServer.getSubjects(): if subject.getId() == 'message': if mode == 'prepend': message = message + "\n\n" + subject.getMessage( ) else: message = subject.getMessage( ) + "\n\n" + message break except Exception as err: # pylint: disable=broad-except logger.warning(err, exc_info=True) self.hidePopup() popupSubject = MessageSubject(id='message') choiceSubject = ChoiceSubject(id='choice') popupSubject.setMessage(message) logger.notice( "Starting popup message notification server on port %d", port) try: self._popupNotificationServer = NotificationServer( address="127.0.0.1", start_port=port, subjects=[popupSubject, choiceSubject]) self._popupNotificationServer.daemon = True with log_context({'instance': 'popup notification server'}): if not self._popupNotificationServer.start_and_wait( timeout=30): raise Exception( "Timed out while waiting for notification server") except Exception as err: # pylint: disable=broad-except logger.error("Failed to start notification server: %s", err) raise notifierCommand = notifierCommand.replace( '%port%', str(self._popupNotificationServer.port)).replace( '%id%', "popup") choiceSubject.setChoices([_('Close')]) choiceSubject.setCallbacks([self.popupCloseCallback]) sessionIds = System.getActiveSessionIds() if not sessionIds: sessionIds = [System.getActiveConsoleSessionId()] for sessionId in sessionIds: desktops = [None] if RUNNING_ON_WINDOWS: desktops = ["default", "winlogon"] for desktop in desktops: try: System.runCommandInSession(command=notifierCommand, sessionId=sessionId, desktop=desktop, waitForProcessEnding=False) except Exception as err: # pylint: disable=broad-except logger.error( "Failed to start popup message notifier app in session %s on desktop %s: %s", sessionId, desktop, err) class PopupClosingThread(threading.Thread): def __init__(self, opsiclientd, seconds): super().__init__() self.opsiclientd = opsiclientd self.seconds = seconds self.stopped = False def stop(self): self.stopped = True def run(self): while not self.stopped: time.sleep(1) if time.time() > self.seconds: break if not self.stopped: logger.debug("hiding popup window") self.opsiclientd.hidePopup() # last popup decides end time (even if unlimited) if self._popupClosingThread and self._popupClosingThread.is_alive( ): self._popupClosingThread.stop() if displaySeconds > 0: logger.debug("displaying popup for %s seconds", displaySeconds) self._popupClosingThread = PopupClosingThread( self, time.time() + displaySeconds) self._popupClosingThread.start()