예제 #1
0
    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")
예제 #2
0
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)
예제 #3
0
    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})")
예제 #4
0
 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)
예제 #6
0
    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)
예제 #7
0
 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)
예제 #8
0
 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)
예제 #9
0
    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)
예제 #10
0
 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)
예제 #11
0
    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)
예제 #12
0
 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)
예제 #13
0
    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
예제 #14
0
    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)
예제 #15
0
 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)
예제 #16
0
    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])
예제 #17
0
 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)
예제 #18
0
        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)
예제 #19
0
 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)
예제 #20
0
    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)
예제 #21
0
    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)
예제 #22
0
    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])
예제 #23
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)
예제 #24
0
    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()
예제 #25
0
    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)
예제 #26
0
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)
예제 #27
0
    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()))
예제 #28
0
    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))
예제 #29
0
    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
예제 #30
0
        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)