Ejemplo n.º 1
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
Ejemplo n.º 2
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})")
Ejemplo n.º 3
0
    def createActionProcessorUser(self, recreate=True):
        if not config.get('action_processor', 'create_user'):
            return

        run_as_user = config.get('action_processor', 'run_as_user')
        if run_as_user.lower() == 'system':
            self._actionProcessorUserName = ''
            self._actionProcessorUserPassword = ''
            return

        if '\\' in run_as_user:
            logger.warning(
                "Ignoring domain part of user to run action processor '%s'",
                run_as_user)
            run_as_user = run_as_user.split('\\', -1)

        if not recreate and self._actionProcessorUserName and self._actionProcessorUserPassword and System.existsUser(
                username=run_as_user):
            return

        self._actionProcessorUserName = run_as_user
        logger.notice(f"Creating local user '{run_as_user}'")

        self._actionProcessorUserPassword = '******' + str(
            randomString(16)) + '!/%'
        secret_filter.add_secrets(self._actionProcessorUserPassword)

        if System.existsUser(username=run_as_user):
            System.deleteUser(username=run_as_user)
        System.createUser(username=run_as_user,
                          password=self._actionProcessorUserPassword,
                          groups=[System.getAdminGroupName()])
Ejemplo n.º 4
0
    def SvcStop(self):  # pylint: disable=invalid-name
        """
		Gets called from windows to stop service
		"""
        logger.notice("Handling stop request")
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self._stopEvent)
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def restart(self, waitSeconds=0):
        def _restart(waitSeconds=0):
            time.sleep(waitSeconds)
            timeline.addEvent(title="opsiclientd restart", category="system")
            try:
                if not os.path.exists(config.restart_marker):
                    logger.notice("Writing restart marker %s",
                                  config.restart_marker)
                    with open(config.restart_marker, "w",
                              encoding="utf-8") as file:
                        file.write("#")
            except Exception as err:  # pylint: disable=broad-except
                logger.error(err)

            if RUNNING_ON_WINDOWS:
                subprocess.Popen(  # pylint: disable=consider-using-with
                    "net stop opsiclientd & net start opsiclientd",
                    shell=True,
                    creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
                    | subprocess.DETACHED_PROCESS)
            else:
                logger.notice("Executing: %s", self._argv)
                os.chdir(os.path.dirname(self._argv[0]))
                os.execvp(self._argv[0], self._argv)

        logger.notice("Will restart in %d seconds", waitSeconds)
        threading.Thread(target=_restart, args=(waitSeconds, )).start()
Ejemplo n.º 7
0
def install_service_windows():
    logger.notice("Installing windows service")
    from opsiclientd.windows.service import handle_commandline  # pylint: disable=import-outside-toplevel
    handle_commandline(
        argv=["opsiclientd.exe", "--startup", "auto", "install"])

    # pyright: reportMissingImports=false
    import winreg  # pylint: disable=import-outside-toplevel,import-error
    import win32process  # pylint: disable=import-outside-toplevel,import-error
    key_handle = winreg.CreateKey(
        winreg.HKEY_LOCAL_MACHINE,
        r"SYSTEM\CurrentControlSet\Services\opsiclientd")
    if win32process.IsWow64Process():
        winreg.DisableReflectionKey(key_handle)
    winreg.SetValueEx(key_handle, 'DependOnService', 0, winreg.REG_MULTI_SZ,
                      ["Dhcp"])
    #winreg.SetValueEx(key_handle, 'DependOnService', 0, winreg.REG_MULTI_SZ, ["Dhcp", "Dnscache"])
    winreg.CloseKey(key_handle)

    key_handle = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE,
                                  r"SYSTEM\CurrentControlSet\Control")
    if win32process.IsWow64Process():
        winreg.DisableReflectionKey(key_handle)
    winreg.SetValueEx(key_handle, 'ServicesPipeTimeout', 0, winreg.REG_DWORD,
                      120000)
    winreg.CloseKey(key_handle)
Ejemplo n.º 8
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)
Ejemplo n.º 9
0
def setup(full=False, options=None) -> None:
    logger.notice("Running opsiclientd setup")
    errors = []

    if full:
        opsi_service_setup(options)
        try:
            install_service()
        except Exception as err:  # pylint: disable=broad-except
            logger.error("Failed to install service: %s", err, exc_info=True)
            errors.append(str(err))

    try:
        setup_ssl(full)
    except Exception as err:  # pylint: disable=broad-except
        logger.error("Failed to setup ssl: %s", err, exc_info=True)
        errors.append(str(err))

    try:
        setup_firewall()
    except Exception as err:  # pylint: disable=broad-except
        logger.error("Failed to setup firewall: %s", err, exc_info=True)
        errors.append(str(err))

    try:
        setup_on_shutdown()
    except Exception as err:  # pylint: disable=broad-except
        logger.error("Failed to setup on_shutdown: %s", err, exc_info=True)
        errors.append(str(err))

    logger.notice("Setup completed with %d errors", len(errors))
    if errors and full:
        raise RuntimeError(", ".join(errors))
Ejemplo n.º 10
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()))
Ejemplo n.º 11
0
 def systemShutdownInitiated(self):
     if not self.isRebootTriggered() and not self.isShutdownTriggered():
         # This shutdown was triggered by someone else
         # Reset shutdown/reboot requests to avoid reboot/shutdown on next boot
         logger.notice(
             "Someone triggered a reboot or a shutdown => clearing reboot request"
         )
         self.clearRebootRequest()
Ejemplo n.º 12
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
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
    def SvcShutdown(self):  # pylint: disable=invalid-name
        """
		Gets called from windows on system shutdown
		"""
        logger.notice("Handling shutdown request")
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        if self.opsiclientd:
            self.opsiclientd.systemShutdownInitiated()
        win32event.SetEvent(self._stopEvent)
Ejemplo n.º 15
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)
Ejemplo n.º 16
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)
Ejemplo n.º 17
0
 def start(self):
     db_file = config.get('global', 'timeline_db')
     logger.notice("Starting timeline (database location: %s)", db_file)
     try:
         self._createDatabase()
     except sqlite3.DatabaseError as err:
         logger.error(
             "Failed to connect to database %s: %s, recreating database",
             db_file, err)
         self._createDatabase(delete_existing=True)
     self._cleanupDatabase()
Ejemplo n.º 18
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)
Ejemplo n.º 19
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)
Ejemplo n.º 20
0
    def initialize(self):
        EventGenerator.initialize(self)

        logger.notice("Registring ISensLogon")

        from opsiclientd.windows import importWmiAndPythoncom, SensLogon  # pylint: disable=import-outside-toplevel

        (_wmi, pythoncom) = importWmiAndPythoncom(importWmi=False,
                                                  importPythoncom=True)
        pythoncom.CoInitialize()

        sl = SensLogon(self.callback)
        sl.subscribe()
Ejemplo n.º 21
0
 def suspendBitlocker(self):  # pylint: disable=no-self-use
     logger.notice("Suspending bitlocker for one reboot if active")
     try:
         System.execute(
             "powershell.exe -ExecutionPolicy Bypass -Command \""
             "foreach($v in Get-BitLockerVolume)"
             "{if ($v.EncryptionPercentage -gt 0)"
             "{$v | Suspend-BitLocker -RebootCount 1}}\"",
             captureStderr=True,
             waitForEnding=True,
             timeout=20)
     except Exception as err:  # pylint: disable=broad-except
         logger.error("Failed to suspend bitlocker: %s", err, exc_info=True)
Ejemplo n.º 22
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)
Ejemplo n.º 23
0
    def deleteActionProcessorUser(self):
        if not config.get('action_processor', 'delete_user'):
            return

        if not self._actionProcessorUserName:
            return

        if not System.existsUser(username=self._actionProcessorUserName):
            return

        logger.notice("Deleting local user '%s'",
                      self._actionProcessorUserName)
        System.deleteUser(username=self._actionProcessorUserName)
        self._actionProcessorUserName = ''
        self._actionProcessorUserPassword = ''
Ejemplo n.º 24
0
 def self_update_from_url(self, url):
     logger.notice("Self-update from url: %s", url)
     filename = url.split('/')[-1]
     with tempfile.TemporaryDirectory() as tmpdir:
         filename = os.path.join(tmpdir, filename)
         if url.startswith("file://"):
             src = url[7:]
             if RUNNING_ON_WINDOWS:
                 src = src.lstrip('/').replace('/', '\\')
             shutil.copy(src, filename)
         else:
             with urllib.request.urlopen(url) as response:
                 with open(filename, 'wb') as file:
                     file.write(response.read())
         self.self_update_from_file(filename)
Ejemplo n.º 25
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)
Ejemplo n.º 26
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)
Ejemplo n.º 27
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()
Ejemplo n.º 28
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)
Ejemplo n.º 29
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)
Ejemplo n.º 30
0
def start_pty(shell="powershell.exe", lines=30, columns=120):
    logger.notice("Starting %s (%d/%d)", shell, lines, columns)
    try:
        # Import of winpty may sometimes fail because of problems with the needed dll.
        # Therefore we do not import at toplevel
        from winpty import PtyProcess  # pylint: disable=import-error,import-outside-toplevel
    except ImportError as err:
        logger.error("Failed to start pty: %s", err, exc_info=True)
        raise
    process = PtyProcess.spawn(shell, dimensions=(lines, columns))

    def read(length: int):
        return process.read(length).encode("utf-8")

    def write(data: bytes):
        return process.write(data.decode("utf-8"))

    def stop():
        process.close()

    return (read, write, stop)