예제 #1
0
def reconfigureEventGenerators():
    eventConfigs = getEventConfigs()
    for eventGenerator in _EVENT_GENERATORS.values():
        eventGenerator.setEventConfigs([])

    for (eventConfigId, eventConfig) in eventConfigs.items():
        mainEventConfigId = eventConfigId.split('{')[0]

        try:
            eventGenerator = _EVENT_GENERATORS[mainEventConfigId]
        except KeyError:
            logger.info(
                "Cannot reconfigure event generator for event '%s': not found",
                eventConfigId)
            continue

        try:
            eventType = eventConfig['type']
            del eventConfig['type']
            ec = EventConfigFactory(eventType, eventConfigId, **eventConfig)
            eventGenerator.addEventConfig(ec)
            logger.notice("Event config '%s' added to event generator '%s'",
                          eventConfigId, mainEventConfigId)
        except Exception as err:  # pylint: disable=broad-except
            logger.error("Failed to reconfigure event generator '%s': %s",
                         mainEventConfigId, err)
예제 #2
0
    def getNextEvent(self):
        if self._opsiclientd.is_stopping():
            return None

        if not self._watcher:
            logger.info("Nothing to watch for")
            self._event = threading.Event()
            self._event.wait()
            return None

        wqlResult = None
        from opsiclientd.windows import importWmiAndPythoncom  # pylint: disable=import-outside-toplevel
        (wmi, _pythoncom) = importWmiAndPythoncom()
        while not self._stopped:
            try:
                wqlResult = self._watcher(timeout_ms=500)
                break
            except wmi.x_wmi_timed_out:
                continue

        if wqlResult:
            eventInfo = {}
            for prop in wqlResult.properties:
                value = getattr(wqlResult, prop)
                if isinstance(value, tuple):
                    eventInfo[prop] = []
                    for val in value:
                        eventInfo[prop].append(val)
                else:
                    eventInfo[prop] = value

            return self.createEvent(eventInfo)
예제 #3
0
            def mergeObjectsFunction(snapshotObj, updateObj, masterObj,
                                     snapshotBackend, workBackend,
                                     masterBackend):  # pylint: disable=unused-argument,too-many-arguments
                masterVersions = sorted([
                    f"{p.productVersion}-{p.packageVersion}"
                    for p in masterBackend.productOnDepot_getObjects(
                        ["productVersion", "packageVersion"],
                        productId=snapshotObj.productId,
                        depotId=self._depotId)
                ])
                snapshotVersions = sorted([
                    f"{p.productVersion}-{p.packageVersion}"
                    for p in snapshotBackend.productOnDepot_getObjects(
                        ["productVersion", "packageVersion"],
                        productId=snapshotObj.productId,
                        depotId=self._depotId)
                ])

                logger.info(
                    "Syncing ProductOnClient %s (product versions local=%s, server=%s)",
                    updateObj, snapshotVersions, masterVersions)
                if snapshotVersions != masterVersions:
                    logger.notice(
                        "Product %s changed on server since last sync, not updating actionRequest (local=%s, server=%s)",
                        snapshotObj.productId, snapshotVersions,
                        masterVersions)
                    updateObj.actionRequest = None
                    updateObj.targetConfiguration = None
                return updateObj
예제 #4
0
 def check_restart_marker(self):
     logger.info("Checking if restart marker '%s' exists",
                 self.restart_marker)
     if os.path.exists(self.restart_marker):
         if os.path.getsize(self.restart_marker) == 0:
             logger.notice(
                 "Old restart marker found, gui startup and daemon startup events disabled"
             )
             self.disabledEventTypes = ["gui startup", "daemon startup"]
         else:
             logger.notice("Reading restart marker")
             with open(self.restart_marker, "r", encoding="utf-8") as file:
                 for line in file.readlines():
                     line = line.strip()
                     if line.startswith("#") or not "=" in line:
                         continue
                     option, value = line.split("=", 1)
                     option = option.strip().lower()
                     if option == "disabled_event_types":
                         self.disabledEventTypes = [
                             v.strip().lower() for v in value.split(",")
                             if v.strip().lower()
                         ]
                         logger.notice(
                             "Event types %s disabled by restart marker",
                             self.disabledEventTypes)
         try:
             os.remove(self.restart_marker)
         except Exception as err:  # pylint: disable=broad-except
             logger.error(err)
예제 #5
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")
예제 #6
0
def setup_firewall_linux():
    logger.notice("Configure iptables")
    port = config.get('control_server', 'port')
    cmds = []
    if os.path.exists("/usr/bin/firewall-cmd"):
        # openSUSE Leap
        cmds.append([
            "/usr/bin/firewall-cmd", f"--add-port={port}/tcp", "--zone",
            "public"
        ])
    elif os.path.exists("/sbin/SuSEfirewall2"):
        # other SUSE
        cmds.append(["/sbin/SuSEfirewall2", "open", "EXT", "TCP" f"{port}"])
    elif os.path.exists("/usr/sbin/ucr"):
        # UCS
        cmds.append([
            "/usr/sbin/ucr", "set",
            f"security/packetfilter/package/opsiclientd/tcp/{port}/all=ACCEPT"
        ])
        cmds.append(["/usr/sbin/service", "univention-firewall", "restart"])
    elif os.path.exists("/sbin/iptables"):
        for iptables in ("iptables", "ip6tables"):
            cmds.append([
                iptables, "-A", "INPUT", "-p", "tcp", "--dport",
                str(port), "-j", "ACCEPT"
            ])
    else:
        logger.warning(
            "Could not configure firewall - no suitable executable found.")

    for cmd in cmds:
        logger.info("Running command: %s", str(cmd))
        subprocess.call(cmd)
예제 #7
0
    def run(self):
        with log_context({'instance': 'control pipe'}):
            try:
                while not self._stopEvent.is_set():
                    if self.clientInfo:
                        self.checkConnection()
                    else:
                        # Old protocol
                        with self.comLock:
                            request = self.read()
                            if request:
                                logger.info("Received request '%s' from %s",
                                            request, self)
                                response = self.processIncomingRpc(request)
                                logger.info("Sending response '%s' to %s",
                                            response, self)
                                self.write(response)

                                if self.clientInfo:
                                    # Switch to new protocol
                                    self.executeRpc('blockLogin', [
                                        self._controller._opsiclientd.
                                        _blockLogin
                                    ],
                                                    with_lock=False)  # pylint: disable=protected-access
                    time.sleep(0.5)
            except Exception as err:  # pylint: disable=broad-except
                logger.error(err, exc_info=True)
            finally:
                self.clientDisconnected()
예제 #8
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)
예제 #9
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()))
예제 #10
0
    def hidePopup(self):
        if self._popupNotificationServer:
            try:
                logger.info("Stopping popup message notification server")

                self._popupNotificationServer.stop(stopReactor=False)
            except Exception as err:  # pylint: disable=broad-except
                logger.error("Failed to stop popup notification server: %s",
                             err)
예제 #11
0
 def getNextEvent(self):
     from opsiclientd.windows import importWmiAndPythoncom  # pylint: disable=import-outside-toplevel
     (_wmi, pythoncom) = importWmiAndPythoncom(importWmi=False,
                                               importPythoncom=True)
     pythoncom.PumpMessages()
     logger.info(
         "Event generator '%s' now deactivated after %d event occurrences",
         self, self._eventsOccured)
     self.cleanup()
예제 #12
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)
예제 #13
0
 def licenseOnClient_getObjects(self, attributes=[], **filter):  # pylint: disable=dangerous-default-value,redefined-builtin
     licenseOnClients = self._workBackend.licenseOnClient_getObjects(
         attributes, **filter)
     logger.info(
         "licenseOnClient_getObjects called with filter %s, %s LicenseOnClients found",
         filter, len(licenseOnClients))
     for licenseOnClient in licenseOnClients:
         # Recreate for later sync to server
         self.licenseOnClient_insertObject(licenseOnClient)
     return licenseOnClients
예제 #14
0
 def run(self):
     while True:
         try:
             System.reboot(0)
             logger.notice("Reboot initiated")
             break
         except Exception as err:  # pylint: disable=broad-except
             # Device not ready?
             logger.info("Failed to initiate reboot: %s", err)
             time.sleep(1)
예제 #15
0
    def isShutdownRequested(self):
        try:
            shutdownRequested = System.getRegistryValue(
                System.HKEY_LOCAL_MACHINE, "SOFTWARE\\opsi.org\\winst",
                "ShutdownRequested")
        except Exception as err:  # pylint: disable=broad-except
            logger.info("Failed to get shutdownRequested from registry: %s",
                        err)
            shutdownRequested = 0

        logger.notice("Shutdown request in Registry: %s", shutdownRequested)
        return forceBool(shutdownRequested)
예제 #16
0
 def processEvent(self, event):
     logger.trace("check lock (ocd), currently %s -> locking if not True",
                  self._opsiclientd.eventLock.locked())
     # if triggered by Basic.py fire_event, lock is already acquired
     if not self._opsiclientd.eventLock.locked():
         self._opsiclientd.eventLock.acquire()
     try:
         logger.info("GUI started")
         self._guiStarted.set()
     finally:
         logger.trace("release lock (WaitForGUI)")
         self._opsiclientd.eventLock.release()
예제 #17
0
    def cleanup(self):
        if self._lastEventOccurence and (time.time() - self._lastEventOccurence
                                         < 10):
            # Waiting some seconds before exit to avoid Win32 releasing
            # exceptions
            waitTime = int(10 - (time.time() - self._lastEventOccurence))
            logger.info("Event generator '%s' cleaning up in %d seconds", self,
                        waitTime)
            time.sleep(waitTime)

        from opsiclientd.windows import importWmiAndPythoncom  # pylint: disable=import-outside-toplevel
        (_wmi, pythoncom) = importWmiAndPythoncom(importWmi=False,
                                                  importPythoncom=True)
        pythoncom.CoUninitialize()
예제 #18
0
def setup_firewall_windows():
    logger.notice("Configure Windows firewall")
    port = config.get('control_server', 'port')
    cmds = [[
        "netsh", "advfirewall", "firewall", "delete", "rule",
        'name="opsiclientd-control-port"'
    ],
            [
                "netsh", "advfirewall", "firewall", "add", "rule",
                'name="opsiclientd-control-port"', "dir=in", "action=allow",
                "protocol=TCP", f"localport={port}"
            ]]
    for cmd in cmds:
        logger.info("Running command: %s", str(cmd))
        subprocess.call(cmd)
예제 #19
0
def setup_firewall_macos():
    logger.notice("Configure MacOS firewall")
    cmds = []

    for path in ("/usr/local/bin/opsiclientd",
                 "/usr/local/lib/opsiclientd/opsiclientd"):
        cmds.append(
            ["/usr/libexec/ApplicationFirewall/socketfilterfw", "--add", path])
        cmds.append([
            "/usr/libexec/ApplicationFirewall/socketfilterfw", "--unblockapp",
            path
        ])

    for cmd in cmds:
        logger.info("Running command: %s", str(cmd))
        subprocess.call(cmd)
예제 #20
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)
예제 #21
0
    def self_update_from_file(self, filename):
        logger.notice("Self-update from file %s", filename)

        test_file = "base_library.zip"
        inst_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
        if not os.path.exists(os.path.join(inst_dir, test_file)):
            raise RuntimeError(
                f"File not found: {os.path.join(inst_dir, test_file)}")

        if self._selfUpdating:
            raise RuntimeError("Self-update already running")
        self._selfUpdating = True
        try:
            with tempfile.TemporaryDirectory() as tmpdir:
                destination = os.path.join(tmpdir, "content")
                shutil.unpack_archive(filename=filename,
                                      extract_dir=destination)

                bin_dir = destination
                if not os.path.exists(os.path.join(bin_dir, test_file)):
                    bin_dir = None
                    for fn in os.listdir(destination):
                        if os.path.exists(
                                os.path.join(destination, fn, test_file)):
                            bin_dir = os.path.join(destination, fn)
                            break
                if not bin_dir:
                    raise RuntimeError("Invalid archive")

                try:
                    check_signature(bin_dir)
                except Exception as err:  # pylint: disable=broad-except
                    logger.error("Could not verify signature!\n%s",
                                 err,
                                 exc_info=True)
                    logger.error("Not performing self_update.")
                    raise RuntimeError("Invalid signature") from err

                binary = os.path.join(bin_dir, os.path.basename(self._argv[0]))

                logger.info("Testing new binary: %s", binary)
                out = subprocess.check_output([binary, "--version"])
                logger.info(out)

                move_dir = inst_dir + "_old"
                logger.info("Moving current installation dir '%s' to '%s'",
                            inst_dir, move_dir)
                if os.path.exists(move_dir):
                    shutil.rmtree(move_dir)
                os.rename(inst_dir, move_dir)

                logger.info("Installing '%s' into '%s'", bin_dir, inst_dir)
                shutil.copytree(bin_dir, inst_dir)

                self.restart(3)
        finally:
            self._selfUpdating = False
예제 #22
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)
예제 #23
0
def opsi_service_setup(options=None):
    try:
        config.readConfigFile()
    except Exception as err:  # pylint: disable=broad-except
        logger.info(err)

    if os.path.exists(config.ca_cert_file):
        # Delete ca cert which could be invalid or expired
        os.remove(config.ca_cert_file)

    service_address = getattr(options, "service_address", None) or config.get(
        'config_service', 'url')[0]
    service_username = getattr(options, "service_username",
                               None) or config.get('global', 'host_id')
    service_password = getattr(options, "service_password",
                               None) or config.get('global', 'opsi_host_key')
    if getattr(options, "client_id", None):
        config.set('global', 'host_id', options.client_id)
    if not config.get('global', 'host_id'):
        fqdn = get_fqdn()
        fqdn = config.set('global', 'host_id', fqdn)

    secret_filter.add_secrets(service_password)

    logger.notice("Connecting to '%s' as '%s'", service_address,
                  service_username)
    jsonrpc_client = JSONRPCClient(address=service_address,
                                   username=service_username,
                                   password=service_password,
                                   verify_server_cert=False)

    try:
        update_ca_cert(jsonrpc_client, allow_remove=False)
    except Exception as err:  # pylint: disable=broad-except
        logger.error(err, exc_info=True)

    try:
        client = jsonrpc_client.host_getObjects(id=config.get(
            'global', 'host_id'))  # pylint: disable=no-member
        if client and client[0] and client[0].opsiHostKey:
            config.set('global', 'opsi_host_key', client[0].opsiHostKey)

        config.getFromService(jsonrpc_client)
        config.updateConfigFile(force=True)
    finally:
        jsonrpc_client.disconnect()
예제 #24
0
    def isRebootRequested(self):
        try:
            rebootRequested = System.getRegistryValue(
                System.HKEY_LOCAL_MACHINE, "SOFTWARE\\opsi.org\\winst",
                "RebootRequested")
        except Exception as error:  # pylint: disable=broad-except
            logger.warning("Failed to get RebootRequested from registry: %s",
                           error)
            rebootRequested = 0

        logger.notice("Reboot request in Registry: %s", rebootRequested)
        if rebootRequested == 2:
            # Logout
            logger.info("Logout requested")
            self.clearRebootRequest()
            return False

        return forceBool(rebootRequested)
예제 #25
0
    def cleanup(self):
        if self._opsiclientd.is_stopping():
            return

        if self._lastEventOccurence and (time.time() - self._lastEventOccurence
                                         < 10):
            # Waiting some seconds before exit to avoid Win32 releasing exceptions
            waitTime = int(10 - (time.time() - self._lastEventOccurence))
            logger.info("Event generator '%s' cleaning up in %d seconds", self,
                        waitTime)
            time.sleep(waitTime)

        try:
            from opsiclientd.windows import importWmiAndPythoncom  # pylint: disable=import-outside-toplevel
            (_wmi, pythoncom) = importWmiAndPythoncom()
            pythoncom.CoUninitialize()
        except ImportError:
            # Probably not running on Windows.
            pass
예제 #26
0
    def executeRpc(self, method, params=None, with_lock=True):
        params = params or []
        with log_context({'instance': 'control pipe'}):
            rpc_id = 1
            if not self.clientInfo:
                return {
                    "id": rpc_id,
                    "error":
                    f"Cannot execute rpc, not supported by client {self}",
                    "result": None
                }

            request = {"id": rpc_id, "method": method, "params": params}
            try:
                if with_lock:
                    self.comLock.acquire()  # pylint: disable=consider-using-with
                try:
                    request_json = toJson(request)
                    logger.info("Sending request '%s' to client %s",
                                request_json, self)
                    self.write(request_json)
                    response_json = self.read()
                    if not response_json:
                        logger.warning(
                            "No response for method '%s' received from client %s",
                            request["method"], self)
                        return {"id": rpc_id, "error": None, "result": None}
                    logger.info("Received response '%s' from client %s",
                                response_json, self)
                    response = fromJson(response_json)
                    if method == "loginUser" and response.get("result"):
                        # Credential provider can only handle one successful login.
                        # Ensure, that the credential provider is not used for a
                        # second login if it keeps the pipe connection open.
                        self.login_capable = False
                    return response
                finally:
                    if with_lock:
                        self.comLock.release()
            except Exception as client_err:  # pylint: disable=broad-except
                logger.error(client_err, exc_info=True)
                return {"id": rpc_id, "error": str(client_err), "result": None}
예제 #27
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)
예제 #28
0
        def getDaemonLoopingContext():
            with getEventGeneratorContext():
                for event_generator in getEventGenerators(
                        generatorClass=DaemonStartupEventGenerator):
                    try:
                        event_generator.createAndFireEvent()
                    except ValueError as err:
                        logger.error(
                            "Unable to fire DaemonStartupEvent from %s: %s",
                            event_generator,
                            err,
                            exc_info=True)

                if getEventGenerators(generatorClass=GUIStartupEventGenerator):
                    # Wait until gui starts up
                    logger.notice(
                        "Waiting for gui startup (timeout: %d seconds)",
                        config.get('global', 'wait_for_gui_timeout'))
                    self.waitForGUI(
                        timeout=config.get('global', 'wait_for_gui_timeout'))
                    if not self.is_stopping():
                        logger.notice("Done waiting for GUI")
                        # Wait some more seconds for events to fire
                        time.sleep(5)

                try:
                    yield
                finally:
                    for event_generator in getEventGenerators(
                            generatorClass=DaemonShutdownEventGenerator):
                        logger.info(
                            "Create and fire shutdown event generator %s",
                            event_generator)
                        try:
                            event_generator.createAndFireEvent()
                        except ValueError as err:
                            logger.error(
                                "Unable to fire DaemonStartupEvent from %s: %s",
                                event_generator,
                                err,
                                exc_info=True)
예제 #29
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)
예제 #30
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()