예제 #1
0
 def _command():
     if self.app.nice() != self.valid_priorities[
             DCSConfig.DCS_CPU_PRIORITY()]:
         LOGGER.debug('setting DCS process priority to: %s',
                      DCSConfig.DCS_CPU_PRIORITY())
         self.app.nice(
             self.valid_priorities[DCSConfig.DCS_CPU_PRIORITY()])
예제 #2
0
def get_latest_mission_from_github():
    """
    Downloads the latest mission from a Github repository

    The repository needs to have releases (tagged)
    The function will download the first MIZ file found in the latest release
    """
    if core.CTX.dcs_auto_mission:
        LOGGER.debug('getting latest mission from Github')
        commands.DCS.block_start('loading mission')
        if DCSConfig.DCS_AUTO_MISSION_GH_OWNER(
        ) and DCSConfig.DCS_AUTO_MISSION_GH_REPO():
            LOGGER.debug('looking for newer mission file')
            latest_version, asset_name, download_url = utils.get_latest_release(
                DCSConfig.DCS_AUTO_MISSION_GH_OWNER(),
                DCSConfig.DCS_AUTO_MISSION_GH_REPO())
            LOGGER.debug('latest release: %s', latest_version)
            local_file = MissionPath(Path(_get_mission_folder(), asset_name))
            if not local_file:
                LOGGER.info('downloading new mission: %s', asset_name)
                req = requests.get(download_url)
                if req.ok:
                    local_file.path.write_bytes(req.content)
                    local_file.set_as_active()
                else:
                    LOGGER.error('failed to download latest mission')
        else:
            LOGGER.warning('no config values given for [auto mission]')
        commands.DCS.unblock_start('loading mission')
    else:
        LOGGER.debug('skipping mission update')
예제 #3
0
    def set_priority(self):
        """
        Sets the DCS process CPU priority to the CFG value
        """
        def _command():
            if self.app.nice() != self.valid_priorities[
                    DCSConfig.DCS_CPU_PRIORITY()]:
                LOGGER.debug('setting DCS process priority to: %s',
                             DCSConfig.DCS_CPU_PRIORITY())
                self.app.nice(
                    self.valid_priorities[DCSConfig.DCS_CPU_PRIORITY()])

        time.sleep(15)
        while True:
            if DCSConfig.DCS_CPU_PRIORITY():
                if core.CTX.exit:
                    return
                if DCSConfig.DCS_CPU_PRIORITY(
                ) not in self.valid_priorities.keys():
                    LOGGER.error(
                        f'invalid priority: %s\n'
                        f'Choose one of: %s',
                        DCSConfig.DCS_CPU_PRIORITY(),
                        self.valid_priorities.keys(),
                    )
                    return
                self._work_with_dcs_process(_command)
            else:
                LOGGER.warning(
                    'no CPU priority given in config file for dcs.exe')
                return
            time.sleep(30)
예제 #4
0
 async def _monitor_server(self):
     await asyncio.sleep(0.1)
     if self.monitoring:
         if time.time() - self.last_ping > DCSConfig.DCS_PING_INTERVAL():
             LOGGER.error(
                 'It has been %s seconds since I heard from DCS. '
                 'It is likely that the server has crashed.',
                 DCSConfig.DCS_PING_INTERVAL())
             CTX.dcs_do_restart = True
             self.monitoring = False
예제 #5
0
 async def _monitor_server_startup(self):
     await asyncio.sleep(0.1)
     if CTX.listener_monitor_server_startup:
         if self.startup_age is None:
             self.startup_age = time.time()
         if time.time(
         ) - self.startup_age > DCSConfig.DCS_START_GRACE_PERIOD():
             LOGGER.error(
                 f'DCS is taking more than %s seconds to start a '
                 'multiplayer server.\n'
                 'Something is wrong ...',
                 DCSConfig.DCS_START_GRACE_PERIOD())
             CTX.listener_monitor_server_startup = False
예제 #6
0
        async def _ask_politely():
            if not self.app or not self.app.is_running():
                return True
            LOGGER.debug('sending socket command to DCS for graceful exit')
            commands.LISTENER.exit_dcs()
            await asyncio.sleep(1)
            LOGGER.debug(
                'waiting on DCS to close itself (grace period: %s seconds)',
                DCSConfig.DCS_CLOSE_GRACE_PERIOD())
            now_ = utils.now()
            while self.app.is_running():
                await asyncio.sleep(1)
                if utils.now() - now_ > DCSConfig.DCS_CLOSE_GRACE_PERIOD():
                    LOGGER.debug('grace period time out!')
                    return False

            LOGGER.info('DCS closed itself, nice')
            return True
예제 #7
0
    def monitor_cpu_usage(self):
        """
        Gets the CPU usage of "DCS.exe" over 5 seconds, and sends an alert if the given threshold is exceeded

        Threshold is set via the config value "DCS_HIGH_CPU_USAGE", and it defaults to 80%
        """
        while not core.CTX.exit:
            try:
                if self.app and self.app.is_running():
                    cpu_usage = int(
                        self.app.cpu_percent(
                            DCSConfig.DCS_HIGH_CPU_USAGE_INTERVAL()))
                    mem_usage = int(self.app.memory_percent())
                    core.Status.dcs_cpu_usage = f'{cpu_usage}%'
                    if core.CTX.dcs_show_cpu_usage or core.CTX.dcs_show_cpu_usage_once:
                        commands.DISCORD.say(f'DCS cpu usage: {cpu_usage}%')
                        core.CTX.dcs_show_cpu_usage_once = False
                    if DCSConfig.DCS_HIGH_CPU_USAGE():
                        if cpu_usage > DCSConfig.DCS_HIGH_CPU_USAGE(
                        ) and not core.Status.paused:
                            LOGGER.warning(
                                'DCS cpu usage has been higher than %s%% for %s seconds',
                                DCSConfig.DCS_HIGH_CPU_USAGE(),
                                DCSConfig.DCS_HIGH_CPU_USAGE_INTERVAL(),
                            )

                    now_ = utils.now()
                    core.CTX.dcs_mem_history.append((now_, mem_usage))
                    core.CTX.dcs_cpu_history.append((now_, cpu_usage))

            except psutil.NoSuchProcess:
                pass

            # I didn't think it could, happen, but of course it did ...
            # See https://github.com/132nd-vWing/ESST/issues/59
            except AttributeError:
                pass
예제 #8
0
    def set_affinity(self):
        """
        Sets the DCS process CPU affinity to the CFG value
        """
        def _command():
            if list(self._app.cpu_affinity()) != list(
                    DCSConfig.DCS_CPU_AFFINITY()):
                LOGGER.debug('setting DCS process affinity to: %s',
                             DCSConfig.DCS_CPU_AFFINITY())
                self._app.cpu_affinity(list(DCSConfig.DCS_CPU_AFFINITY()))

        while True:
            if DCSConfig.DCS_CPU_AFFINITY():
                if core.CTX.exit:
                    return
                self._work_with_dcs_process(_command)
            else:
                LOGGER.warning('no CPU affinity given in config file')
                return
            time.sleep(30)
예제 #9
0
 def _command():
     if list(self._app.cpu_affinity()) != list(
             DCSConfig.DCS_CPU_AFFINITY()):
         LOGGER.debug('setting DCS process affinity to: %s',
                      DCSConfig.DCS_CPU_AFFINITY())
         self._app.cpu_affinity(list(DCSConfig.DCS_CPU_AFFINITY()))
예제 #10
0
 def _init_dcs_path():
     from esst import DCSConfig
     FS.dcs_path = check_dir(DCSConfig.DCS_PATH())
     LOGGER.debug('DCS path:  %s', FS.dcs_path)
예제 #11
0
def _get_me_auth_path() -> Path:
    me_auth_path = Path(DCSConfig.DCS_PATH(),
                        'MissionEditor/modules/me_authorization.lua')
    if not me_auth_path.exists():
        raise FileNotFoundError(str(me_auth_path))
    return me_auth_path
예제 #12
0
def main(debug: bool):  # pylint: disable=too-many-locals
    """
    Main entry point

    Args:
        debug: show more verbose console output
    """
    from esst import __version__, LOGGER, LOGGING_CONSOLE_HANDLER, config
    config.init()

    from esst.core import CTX
    from esst import ESSTConfig, DiscordBotConfig, DCSConfig, ListenerConfig, ServerConfig

    from esst.sentry.sentry import SENTRY
    SENTRY.register_context('App context', CTX)
    CTX.sentry = SENTRY

    _setup_logging_debug(__version__, LOGGER, LOGGING_CONSOLE_HANDLER, debug, ESSTConfig.DEBUG())

    LOGGER.debug('instantiating main event loop')
    loop = asyncio.get_event_loop()
    CTX.loop = loop

    _check_wan_and_start_wan_monitor(loop, LOGGER, CTX)

    CTX.start_discord_loop = DiscordBotConfig.DISCORD_START_BOT()
    CTX.start_server_loop = ServerConfig.SERVER_START_LOOP()
    CTX.start_dcs_loop = DCSConfig.DCS_START_LOOP()
    CTX.start_listener_loop = ListenerConfig.LISTENER_START_LOOP()

    if not DCSConfig.DCS_CAN_START():
        CTX.dcs_blocker.append('config')

    CTX.dcs_setup_dedi_config = DCSConfig.DCS_INSTALL_DEDICATED_CONFIG()
    CTX.dcs_install_hooks = DCSConfig.DCS_INSTALL_HOOKS()
    CTX.dcs_auto_mission = DCSConfig.DCS_AUTO_MISSION_ENABLE()

    loop = asyncio.get_event_loop()
    # loop.set_debug(True)
    CTX.discord_msg_queue = queue.Queue()

    _set_console_title(__version__)

    from esst import FS
    FS.init()

    from esst.utils import clean_all_folder, assign_ports
    clean_all_folder()
    assign_ports()

    _init_atis_module()

    import esst.discord_bot.discord_bot
    discord_loop = esst.discord_bot.discord_bot.App()

    from esst.dcs import dcs
    dcs_loop = dcs.App()

    from esst.server import server
    server_loop = server.App()

    from esst.listener.listener import DCSListener
    listener_loop = DCSListener()

    futures = asyncio.gather(
        loop.create_task(discord_loop.run()),
        loop.create_task(dcs_loop.run()),
        loop.create_task(listener_loop.run()),
        loop.create_task(server_loop.run()),
        loop.create_task(watch_for_exceptions()),
    )

    import signal
    signal.signal(signal.SIGINT, sigint_handler)
    loop.run_until_complete(futures)
    LOGGER.debug('main loop is done, killing DCS')

    futures = asyncio.gather(  # type: ignore
        loop.create_task(dcs_loop.kill_running_app()),
        loop.create_task(listener_loop.run_until_dcs_is_closed()),
    )

    loop.run_until_complete(futures)

    LOGGER.debug('all done !')