def initialize(self): if self._opsiclientd.is_stopping(): return if not self._wql: return from opsiclientd.windows import importWmiAndPythoncom # pylint: disable=import-outside-toplevel (wmi, pythoncom) = importWmiAndPythoncom() pythoncom.CoInitialize() max_attempts = 10 for attempt in range(1, 100): try: logger.debug("Creating wmi object") con = wmi.WMI(privileges=["Security"]) logger.info("Watching for wql: %s", self._wql) self._watcher = con.watch_for(raw_wql=self._wql, wmi_class='') break except Exception as err: # pylint: disable=broad-except if self._stopped: return logger.warning("Failed to create wmi watcher (wql=%s): %s", self._wql, err, exc_info=True) if attempt >= max_attempts: raise for i in range(3): # pylint: disable=unused-variable if self._stopped: return time.sleep(1) logger.debug("Initialized")
def importWmiAndPythoncom(importWmi=True, importPythoncom=True): global wmi # pylint: disable=global-statement,invalid-name global pythoncom # pylint: disable=global-statement,invalid-name if importWmi and not pythoncom: importPythoncom = True if not ((wmi or not importWmi) and (pythoncom or not importPythoncom)): logger.info("Importing wmi / pythoncom") with importWmiAndPythoncomLock: while not ((wmi or not importWmi) and (pythoncom or not importPythoncom)): try: if not pythoncom and importPythoncom: logger.debug("Importing pythoncom") import pythoncom # pylint: disable=import-error,import-outside-toplevel,redefined-outer-name if not wmi and importWmi: logger.debug("Importing wmi") pythoncom.CoInitialize() try: import wmi # pylint: disable=import-error,import-outside-toplevel,redefined-outer-name finally: pythoncom.CoUninitialize() except Exception as import_error: # pylint: disable=broad-except logger.warning( "Failed to import: %s, retrying in 2 seconds", import_error) time.sleep(2) return (wmi, pythoncom)
def waitForClient(self): logger.trace("Creating pipe %s", self._pipeName) PIPE_ACCESS_DUPLEX = 0x3 PIPE_TYPE_MESSAGE = 0x4 PIPE_READMODE_MESSAGE = 0x2 PIPE_WAIT = 0 PIPE_UNLIMITED_INSTANCES = 255 NMPWAIT_USE_DEFAULT_WAIT = 0 INVALID_HANDLE_VALUE = -1 self._pipe = windll.kernel32.CreateNamedPipeA( self._pipeName.encode("ascii"), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, self.bufferSize, self.bufferSize, NMPWAIT_USE_DEFAULT_WAIT, None) if self._pipe == INVALID_HANDLE_VALUE: raise Exception( f"Failed to create named pipe: {windll.kernel32.GetLastError()}" ) logger.debug("Pipe %s created, waiting for client to connect", self._pipeName) # This call is blocking until a client connects fConnected = windll.kernel32.ConnectNamedPipe(self._pipe, None) if fConnected == 0 and windll.kernel32.GetLastError() == 535: # ERROR_PIPE_CONNECTED fConnected = 1 if fConnected == 1: logger.notice("Client connected to %s", self._pipeName) self._client_id += 1 return (self._pipe, f"#{self._client_id}") error = windll.kernel32.GetLastError() windll.kernel32.CloseHandle(self._pipe) raise RuntimeError(f"Failed to connect to pipe (error: {error})")
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()
def set_status_message(backend, session_id, message): if session_id == "-1": logger.debug("Not setting status message") return try: backend.setStatusMessage(session_id, message) # pylint: disable=no-member except Exception as err: # pylint: disable=broad-except logger.warning("Failed to set status message: %s", err)
def createEvent(self, eventInfo={}): # pylint: disable=dangerous-default-value logger.debug("Creating event config from info: %s", eventInfo) eventConfig = self.getEventConfig() logger.debug("Event config: %s", eventConfig) if not eventConfig: return None return Event(eventConfig=eventConfig, eventInfo=eventInfo)
def shutdownMachine(self, waitSeconds=3): self._isShutdownTriggered = True if self._controlPipe: try: self._controlPipe.executeRpc("shutdownTriggered", True) except Exception as err: # pylint: disable=broad-except logger.debug(err) self.clearShutdownRequest() System.shutdown(wait=waitSeconds)
def stop(self): logger.debug("Stopping thread") self.cancelled = True self.running = False for _unused in range(10): if not self.is_alive(): break self.terminate() time.sleep(0.5)
def setBlockLogin(self, blockLogin, handleNotifier=True): # pylint: disable=too-many-branches blockLogin = forceBool(blockLogin) changed = self._blockLogin != blockLogin self._blockLogin = blockLogin logger.notice("Block login now set to '%s'", self._blockLogin) if self._blockLogin: if not self._blockLoginEventId: self._blockLoginEventId = timeline.addEvent( title="Blocking login", description="User login blocked", category="block_login", durationEvent=True) if not self._blockLoginNotifierPid and config.get( 'global', 'block_login_notifier'): if handleNotifier and RUNNING_ON_WINDOWS: logger.info("Starting block login notifier app") # Start block login notifier on physical console sessionId = System.getActiveConsoleSessionId() while True: try: self._blockLoginNotifierPid = System.runCommandInSession( command=config.get('global', 'block_login_notifier'), sessionId=sessionId, desktop='winlogon', waitForProcessEnding=False)[2] break except Exception as err: # pylint: disable=broad-except logger.error( "Failed to start block login notifier app: %s", err) break else: if self._blockLoginEventId: timeline.setEventEnd(eventId=self._blockLoginEventId) self._blockLoginEventId = None if handleNotifier and self._blockLoginNotifierPid: try: logger.info( "Terminating block login notifier app (pid %s)", self._blockLoginNotifierPid) System.terminateProcess( processId=self._blockLoginNotifierPid) except Exception as err: # pylint: disable=broad-except logger.warning( "Failed to terminate block login notifier app: %s", err) self._blockLoginNotifierPid = None if changed and self._controlPipe: try: self._controlPipe.executeRpc("blockLogin", self._blockLogin) except Exception as rpc_error: # pylint: disable=broad-except logger.debug(rpc_error)
def rebootMachine(self, waitSeconds=3): self._isRebootTriggered = True if self._controlPipe: try: self._controlPipe.executeRpc("rebootTriggered", True) except Exception as err: # pylint: disable=broad-except logger.debug(err) self.clearRebootRequest() System.reboot(wait=waitSeconds)
def processEvent(self, event): logger.notice("Processing event %s", event) description = f"Event {event.eventConfig.getId()} occurred\n" description += "Config:\n" _config = event.eventConfig.getConfig() configKeys = list(_config.keys()) configKeys.sort() for configKey in configKeys: description += f"{configKey}: {_config[configKey]}\n" logger.trace("check lock (ocd), currently %s -> locking if not True", self.eventLock.locked()) # if triggered by Basic.py fire_event, lock is already acquired if not self.eventLock.locked(): self.eventLock.acquire() # pylint: disable=consider-using-with try: timeline.addEvent(title=f"Event {event.eventConfig.getName()}", description=description, category="event_occurrence") # if processEvent is called through Event.fireEvent(), this check is already done #self.canProcessEvent(event) # A user login event should not cancel running non-login Event if event.eventConfig.actionType != 'login': self.cancelOthersAndWaitUntilReady() except (ValueError, RuntimeError) as err: # skipping execution if event cannot be created logger.warning("Could not start event: %s", err, exc_info=True) logger.trace("release lock (ocd cannot process event)") self.eventLock.release() return try: logger.debug("Creating new ept (ocd)") eventProcessingThread = EventProcessingThread(self, event) self.createActionProcessorUser(recreate=False) with self._eptListLock: self._eventProcessingThreads.append(eventProcessingThread) finally: logger.trace("release lock (ocd)") self.eventLock.release() try: eventProcessingThread.start() eventProcessingThread.join() logger.notice("Done processing event %s", event) finally: with self._eptListLock: self._eventProcessingThreads.remove(eventProcessingThread) if not self._eventProcessingThreads: try: self.deleteActionProcessorUser() except Exception as err: # pylint: disable=broad-except logger.warning(err)
def waitForClient(self): logger.debug("Waiting for client to connect to %s", self._socketName) self._socket.settimeout(2.0) while True: try: connection, client_address = self._socket.accept() logger.notice("Client %s connected to %s", client_address, self._socketName) return (connection, client_address) except socket.timeout: if self._stopEvent.is_set(): return (None, None)
def __init__(self, args): """ Initialize service and create stop event """ self.opsiclientd = None try: logger.debug("OpsiclientdService initiating") win32serviceutil.ServiceFramework.__init__(self, args) self._stopEvent = win32event.CreateEvent(None, 0, 0, None) socket.setdefaulttimeout(60) logger.debug("OpsiclientdService initiated") except Exception as err: # pylint: disable=broad-except logger.error(err, exc_info=True) raise
def run(self): with opsicommon.logging.log_context( {'instance': f'event generator {self._generatorConfig.getId()}'}): try: logger.info("Initializing event generator '%s'", self) self.initialize() if self._generatorConfig.activationDelay > 0: logger.debug( "Waiting %d seconds before activation of event generator '%s'", self._generatorConfig.activationDelay, self) time.sleep(self._generatorConfig.activationDelay) logger.info("Activating event generator '%s'", self) while not self._stopped and ( (self._generatorConfig.maxRepetitions < 0) or (self._eventsOccured <= self._generatorConfig.maxRepetitions)): logger.info("Getting next event...") event = self.getNextEvent() # pylint: disable=assignment-from-none,assignment-from-no-return self._eventsOccured += 1 # Count as occured, even if event is None! if event: logger.info("Got new event: %s (%d/%d)", event, self._eventsOccured, self._generatorConfig.maxRepetitions + 1) self.fireEvent(event) for _unused in range(10): if self._stopped: break time.sleep(1) if not self._stopped: logger.notice( "Event generator '%s' now deactivated after %d event occurrences", self, self._eventsOccured) except Exception as err: # pylint: disable=broad-except if not self._stopped: logger.error("Failure in event generator '%s': %s", self, err, exc_info=True) try: self.cleanup() except Exception as err: # pylint: disable=broad-except if not self._stopped: logger.error("Failed to clean up: %s", err) logger.info("Event generator '%s' exiting ", self)
def run(self): with opsicommon.logging.log_context({ 'instance': 'event generator ' + self._event.eventConfig.getId() }): if self._event.eventConfig.notificationDelay > 0: logger.debug( "Waiting %d seconds before notifying listener '%s' of event '%s'", self._event.eventConfig.notificationDelay, self._eventListener, self._event) time.sleep(self._event.eventConfig.notificationDelay) try: logger.info("Calling processEvent on listener %s", self._eventListener) self._eventListener.processEvent(self._event) except Exception as err: # pylint: disable=broad-except logger.error(err, exc_info=True)
def _applySystemSpecificConfiguration(self): defaultToApply = self.WINDOWS_DEFAULT_PATHS.copy() if RUNNING_ON_LINUX: defaultToApply = self.LINUX_DEFAULT_PATHS.copy() elif RUNNING_ON_DARWIN: defaultToApply = self.MACOS_DEFAULT_PATHS.copy() baseDir = self._config["global"]["base_dir"] for key in list(self._config): if key in defaultToApply: self._config[key].update(defaultToApply[key]) self._config['cache_service']['extension_config_dir'] = os.path.join( baseDir, 'opsiclientd', 'extend.d') if RUNNING_ON_WINDOWS: systemDrive = System.getSystemDrive() logger.debug( "Running on windows: adapting paths to use system drive (%s)", systemDrive) systemDrive += "\\" self._config['cache_service']['storage_dir'] = os.path.join( systemDrive, 'opsi.org', 'cache') self._config['global']['config_file'] = os.path.join( baseDir, 'opsiclientd', 'opsiclientd.conf') self._config['global']['log_dir'] = os.path.join( systemDrive, 'opsi.org', 'log') self._config['global']['state_file'] = os.path.join( systemDrive, 'opsi.org', 'opsiclientd', 'state.json') self._config['global']['server_cert_dir'] = os.path.join( systemDrive, 'opsi.org', 'tls') self._config['global']['timeline_db'] = os.path.join( systemDrive, 'opsi.org', 'opsiclientd', 'timeline.sqlite') self._config['system'][ 'program_files_dir'] = System.getProgramFilesDir() if sys.getwindowsversion()[0] == 5: # pylint: disable=no-member self._config['action_processor']['run_as_user'] = '******' else: sslCertDir = os.path.join('/etc', 'opsi-client-agent') for certPath in ('ssl_server_key_file', 'ssl_server_cert_file'): if sslCertDir not in self._config['control_server'][certPath]: self._config['control_server'][certPath] = os.path.join( sslCertDir, self._config['control_server'][certPath])
def getNextEvent(self): gui_process_names_lower = [n.lower() for n in self.gui_process_names] while not self._stopped: for proc in psutil.process_iter(): try: if proc.name().lower() in [ n.lower() for n in gui_process_names_lower ]: logger.debug("Process '%s' is running", proc.name()) return self.createEvent() except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): pass for _i in range(3): if self._stopped: break time.sleep(1)
def getEventGeneratorContext(): logger.debug("Creating event generators") createEventGenerators(self) for eventGenerator in getEventGenerators(): eventGenerator.addEventListener(self) eventGenerator.start() logger.info("Event generator '%s' started", eventGenerator) try: yield finally: for eventGenerator in getEventGenerators(): logger.info("Stopping event generator %s", eventGenerator) eventGenerator.stop() eventGenerator.join(2) logger.info("Event generator %s stopped", eventGenerator)
def ReportServiceStatus(self, serviceStatus, waitHint=5000, win32ExitCode=0, svcExitCode=0): # pylint: disable=invalid-name # Wrapping because ReportServiceStatus sometimes lets windows # report a crash of opsiclientd (python 2.6.5) invalid handle try: logger.debug("Reporting service status: %s", serviceStatus) win32serviceutil.ServiceFramework.ReportServiceStatus( self, serviceStatus, waitHint=waitHint, win32ExitCode=win32ExitCode, svcExitCode=svcExitCode) except Exception as err: # pylint: disable=broad-except logger.error("Failed to report service status %s: %s", serviceStatus, err)
def getDepotserverCredentials(self, configService): url = urlparse(self.get('depot_server', 'url')) if url.scheme in ("webdav", "webdavs", "http", "https"): return (self.get('global', 'host_id'), self.get('global', 'opsi_host_key')) if not configService: raise Exception("Not connected to config service") depotServerUsername = self.get('depot_server', 'username') encryptedDepotServerPassword = configService.user_getCredentials( username='******', hostId=self.get('global', 'host_id'))['password'] depotServerPassword = blowfishDecrypt( self.get('global', 'opsi_host_key'), encryptedDepotServerPassword) secret_filter.add_secrets(depotServerPassword) logger.debug("Using username '%s' for depot connection", depotServerUsername) return (depotServerUsername, depotServerPassword)
def SvcRun(self): # pylint: disable=invalid-name """ Gets called from windows to start service """ try: logger.notice("Handling start request") startTime = time.time() self.ReportServiceStatus(win32service.SERVICE_RUNNING) logger.debug("Took %0.2f seconds to report service running status", (time.time() - startTime)) # Write to event log servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '')) from .opsiclientd import opsiclientd_factory # pylint: disable=import-outside-toplevel self.opsiclientd = opsiclientd_factory() self.opsiclientd.start() # Wait for stop event win32event.WaitForSingleObject(self._stopEvent, win32event.INFINITE) # Shutdown opsiclientd self.opsiclientd.stop() self.opsiclientd.join(15) logger.notice("opsiclientd stopped") try: self.ReportServiceStatus(win32service.SERVICE_STOPPED) servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STOPPED, (self._svc_name_, '')) except Exception as err: # pylint: disable=broad-except # Errors can occur if windows is shutting down logger.info(err, exc_info=True) for thread in threading.enumerate(): logger.notice("Running thread after stop: %s", thread) except Exception as err: # pylint: disable=broad-except logger.critical("opsiclientd crash %s", err, exc_info=True)
def __init__(self): logger.debug("Opsiclient initiating") EventListener.__init__(self) threading.Thread.__init__(self) self._startupTime = time.time() self._running = False self._eventProcessingThreads = [] self.eventLock = threading.Lock() self._eptListLock = threading.Lock() self._blockLogin = True self._currentActiveDesktopName = {} self._gui_waiter = None self._isRebootTriggered = False self._isShutdownTriggered = False self._actionProcessorUserName = '' self._actionProcessorUserPassword = '' self._statusApplicationProcess = None self._blockLoginNotifierPid = None self._popupNotificationServer = None self._popupNotificationLock = threading.Lock() self._popupClosingThread = None self._blockLoginEventId = None self._opsiclientdRunningEventId = None self._stopEvent = threading.Event() self._stopEvent.clear() self._cacheService = None self._controlPipe = None self._controlServer = None self._selfUpdating = False self._argv = list(sys.argv) self._argv[0] = os.path.abspath(self._argv[0])
def getControlPipe(): logger.notice("Starting control pipe") try: self._controlPipe = ControlPipeFactory(self) self._controlPipe.daemon = True self._controlPipe.start() logger.notice("Control pipe started") yield except Exception as err: # pylint: disable=broad-except logger.error("Failed to start control pipe: %s", err, exc_info=True) raise finally: logger.info("Stopping control pipe") try: self._controlPipe.stop() self._controlPipe.join(2) logger.info("Control pipe stopped") except (NameError, RuntimeError) as stopError: logger.debug("Stopping controlPipe failed: %s", stopError)
def callback(self, eventType, *args): logger.debug( "UserLoginEventGenerator event callback: eventType '%s', args: %s", eventType, args) if self._opsiclientd.is_stopping(): return if args[0].split("\\")[-1] == OPSI_SETUP_USER_NAME: logger.info( "Login of user %s detected, no UserLoginAction will be fired.", args[0]) return if eventType == 'Logon': logger.notice("User login detected: %s", args[0]) self._eventsOccured += 1 self.fireEvent(self.createEvent(eventInfo={'User': args[0]})) if (self._generatorConfig.maxRepetitions > 0) and (self._eventsOccured > self._generatorConfig.maxRepetitions): self.stop()
def cancelOthersAndWaitUntilReady(self): WAIT_SECONDS = 30 with self._eptListLock: eptListCopy = self._eventProcessingThreads.copy() for ept in self._eventProcessingThreads: if ept.event.eventConfig.actionType != 'login': #trying to cancel all non-login events - RuntimeError if impossible logger.notice("Canceling event processing thread %s (ocd)", ept) ept.cancel(no_lock=True) logger.trace("Waiting for cancellation to conclude") # Use copy to allow for epts to be removed from eptList for ept in eptListCopy: if ept.event.eventConfig.actionType != 'login': logger.trace("Waiting for ending of ept %s (ocd)", ept) for _ in range(WAIT_SECONDS): if not ept or not ept.running: break time.sleep(1) if ept and ept.running: raise ValueError( f"Event {ept.event.eventConfig.name} didn't stop after {WAIT_SECONDS} seconds - aborting" ) logger.debug("Successfully canceled event '%s' of type %s", ept.event.eventConfig.name, ept.event.eventConfig.actionType) try: cache_service = self.getCacheService() logger.debug( "Got config_service with state: %s - marking dirty", cache_service.getConfigCacheState()) # mark cache as dirty when bypassing cache mechanism for installation cache_service.setConfigCacheFaulty() except RuntimeError as err: logger.info( "Could not mark config service cache dirty: %s", err, exc_info=True)
def check_signature(bin_dir): logger.info("check_signature is called") if not RUNNING_ON_WINDOWS: return # Not yet implemented windowsVersion = sys.getwindowsversion() # pylint: disable=no-member if windowsVersion.major < 6 or (windowsVersion.major == 6 and windowsVersion.minor < 4): return # Get-AuthenticodeSignature is only defined for versions since 2016 binary_list = [ os.path.join(bin_dir, "opsiclientd.exe"), os.path.join(bin_dir, "opsiclientd_rpc.exe"), os.path.join(bin_dir, "action_processor_starter.exe") ] for binary in binary_list: cmd = f'powershell.exe -ExecutionPolicy Bypass -Command \"(Get-AuthenticodeSignature \'{binary}\').Status -eq \'Valid\'\"' result = execute(cmd, captureStderr=True, waitForEnding=True, timeout=20) logger.debug(result) if not "True" in result: raise ValueError(f"Invalid Signature of file {binary}") logger.notice("Successfully verified %s", binary_list)
def getFromService(self, configService): ''' Get settings from service ''' logger.notice("Getting config from service") if not configService: raise Exception("Config service is undefined") query = { "objectId": self.get('global', 'host_id'), "configId": [ 'clientconfig.configserver.url', 'clientconfig.depot.drive', 'clientconfig.depot.id', 'clientconfig.depot.user', 'clientconfig.suspend_bitlocker_on_reboot', 'opsiclientd.*' # everything starting with opsiclientd. ] } configService.backend_setOptions({"addConfigStateDefaults": True}) for configState in configService.configState_getObjects(**query): logger.info("Got config state from service: %r", configState) if not configState.values: logger.debug("No values - skipping %s", configState.configId) continue if configState.configId == 'clientconfig.configserver.url': self.set('config_service', 'url', configState.values) elif configState.configId == 'clientconfig.depot.drive': self.set('depot_server', 'drive', configState.values[0]) elif configState.configId == 'clientconfig.depot.id': self.set('depot_server', 'depot_id', configState.values[0]) elif configState.configId == 'clientconfig.depot.user': self.set('depot_server', 'username', configState.values[0]) elif configState.configId == 'clientconfig.suspend_bitlocker_on_reboot': self.set('global', 'suspend_bitlocker_on_reboot', configState.values[0]) elif configState.configId.startswith('opsiclientd.'): try: parts = configState.configId.lower().split('.') if len(parts) < 3: logger.debug( "Expected at least 3 parts in %s - skipping.", configState.configId) continue value = configState.values if len(value) == 1: value = value[0] self.set(section=parts[1], option=parts[2], value=value) except Exception as err: # pylint: disable=broad-except logger.error("Failed to process configState '%s': %s", configState.configId, err) logger.notice("Got config from service") logger.debug("Config is now:\n %s", objectToBeautifiedText(self.getDict()))
def readConfigFile(self): ''' Get settings from config file ''' logger.notice("Trying to read config from file: '%s'", self.get('global', 'config_file')) try: self._config_file_mtime = os.path.getmtime( self.get('global', 'config_file')) # Read Config-File config = IniFile(filename=self.get('global', 'config_file'), raw=True).parse() # Read log settings early if config.has_section('global') and config.has_option( 'global', 'log_level'): self.set('global', 'log_level', config.get('global', 'log_level')) for section in config.sections(): logger.debug("Processing section '%s' in config file: '%s'", section, self.get('global', 'config_file')) for (option, value) in config.items(section): option = option.lower() self.set(section.lower(), option, value) except Exception as err: # pylint: disable=broad-except # An error occured while trying to read the config file logger.error("Failed to read config file '%s': %s", self.get('global', 'config_file'), err) logger.error(err, exc_info=True) return if not self.get("depot_server", "master_depot_id"): self.set("depot_server", "master_depot_id", self.get("depot_server", "depot_id")) logger.notice("Config read") logger.debug("Config is now:\n %s", objectToBeautifiedText(self._config))
def getCurrentActiveDesktopName(self, sessionId=None): if not RUNNING_ON_WINDOWS: return None if not ('opsiclientd_rpc' in config.getDict() and 'command' in config.getDict()['opsiclientd_rpc']): raise Exception("opsiclientd_rpc command not defined") if sessionId is None: sessionId = System.getActiveSessionId() if sessionId is None: sessionId = System.getActiveConsoleSessionId() rpc = f"setCurrentActiveDesktopName(\"{sessionId}\", System.getActiveDesktopName())" cmd = config.get('opsiclientd_rpc', 'command') + ' "' + rpc.replace( '"', '\\"') + '"' try: System.runCommandInSession(command=cmd, sessionId=sessionId, desktop="winlogon", waitForProcessEnding=True, timeoutSeconds=60, noWindow=True) except Exception as err: # pylint: disable=broad-except logger.error(err) desktop = self._currentActiveDesktopName.get(sessionId) if not desktop: logger.warning( "Failed to get current active desktop name for session %s, using 'default'", sessionId) desktop = "default" self._currentActiveDesktopName[sessionId] = desktop logger.debug( "Returning current active dektop name '%s' for session %s", desktop, sessionId) return desktop
def getControlServer(): logger.notice("Starting control server") self._controlServer = None try: self._controlServer = ControlServer( opsiclientd=self, httpsPort=config.get('control_server', 'port'), sslServerKeyFile=config.get('control_server', 'ssl_server_key_file'), sslServerCertFile=config.get('control_server', 'ssl_server_cert_file'), staticDir=config.get('control_server', 'static_dir')) logger.debug("Current control server: %s", self._controlServer) self._controlServer.start() logger.notice("Control server started") self._stopEvent.wait(1) if self._stopEvent.is_set(): # Probably a failure during binding to port. raise RuntimeError("Received stop signal.") yield except Exception as err: # pylint: disable=broad-except logger.error("Failed to start control server: %s", err, exc_info=True) raise err finally: if self._controlServer: logger.info("Stopping control server") try: self._controlServer.stop() self._controlServer.join(2) logger.info("Control server stopped") except (NameError, RuntimeError) as stopError: logger.debug("Stopping controlServer failed: %s", stopError)