diff --git a/__main__.py b/__main__.py index 7492176..bb3d5c3 100644 --- a/__main__.py +++ b/__main__.py @@ -8,6 +8,7 @@ async def main(): asyncio.create_task(metrics.update_loop()) + asyncio.create_task(bot.update_base_message_loop()) await bot.start() await jobs.start() try: diff --git a/src/core/metrics.py b/src/core/metrics.py index d5cd7b2..6ae040a 100644 --- a/src/core/metrics.py +++ b/src/core/metrics.py @@ -1,27 +1,33 @@ +from docker import DockerClient import asyncio import shutil class Metrics: - update_loop: bool = False + docker_client: DockerClient + update_loop_active: bool = False storage_total: int storage_left: int storage_used: int + running_container_count: int - def __init__(self): + def __init__(self, docker_client: DockerClient): + self.docker_client = docker_client self.collect_metrics() def collect_metrics(self): disk_usage = shutil.disk_usage("/") self.storage_total, self.storage_used, self.storage_left = [ x // (2**30) for x in disk_usage] + self.running_container_count = len( + self.docker_client.containers.list()) async def update_loop(self): - if self.update_loop: + if self.update_loop_active: return - self.update_loop = True - while self.update_loop: + self.update_loop_active = True + while self.update_loop_active: self.collect_metrics() - asyncio.sleep(60) + await asyncio.sleep(60) diff --git a/src/core/telegrambot.py b/src/core/telegrambot.py index da7d642..cfde969 100644 --- a/src/core/telegrambot.py +++ b/src/core/telegrambot.py @@ -45,8 +45,13 @@ async def update_base_message(self): if content != self.base_message.text: await self.base_message.edit_text(content) + async def update_base_message_loop(self): + while True: + await asyncio.sleep(30) + await self.update_base_message() + def get_info_board(self) -> str: - msg = f"{Emoji.ROCKET} keepalive is currently keeping alive\n" + \ + msg = f"{Emoji.ROCKET.value} keepalive is currently keeping alive\n" + \ f"Last ping: {datetime.now().strftime('%d.%m.%Y %H:%M')}\n" msg += "\n".join(f() for f in self.informants) return msg diff --git a/src/core/utility.py b/src/core/utility.py index 7dbfc36..37749a5 100644 --- a/src/core/utility.py +++ b/src/core/utility.py @@ -1,20 +1,27 @@ -import os +import logging +from enum import Enum, auto +from subprocess import call +log = logging.getLogger() -class Emoji: + +class Emoji(Enum): ROCKET = "\U0001F680" CHECK_MARK = "\U00002705" CROSS_MARK = "\U0000274C" +class ImportanceLevel(Enum): + VERY_LOW = auto() + LOW = auto() + MEDIUM = auto() + IMPORTANT = auto() + URGENT = auto() + + def time_in_seconds(seconds: float = 0, minutes=0, hours=0, days=0) -> float: return seconds + minutes * 60 + hours * 60 * 60 + days * 60 * 60 * 24 def exec_sh(command: str) -> int: - return os.system(command) - - -def free_storage(): - for item in ["image", "container"]: - exec_sh(f"docker {item} prune -f") + return call(command, shell=True) diff --git a/src/register_jobs.py b/src/register_jobs.py index 6509f59..f574264 100644 --- a/src/register_jobs.py +++ b/src/register_jobs.py @@ -2,7 +2,7 @@ import os import docker from dotenv import load_dotenv -from src.core.utility import free_storage, time_in_seconds +from src.core.utility import exec_sh, time_in_seconds from src.core.jobs import Jobs from src.core.metrics import Metrics @@ -17,11 +17,14 @@ docker_client = docker.from_env() jobs = Jobs() -metrics = Metrics() +metrics = Metrics(docker_client) bot = TelegramBot(BOT_TOKEN, ADMIN_ID) bot.informants.append( lambda: f"Storage: {metrics.storage_left} GB of {metrics.storage_total} GB left") +bot.informants.append( + lambda: f"Running Containers: {metrics.running_container_count}" +) @jobs.register(time_in_seconds(hours=1)) @@ -29,4 +32,27 @@ async def check_storage(): if metrics.storage_left/metrics.storage_total < .1 or metrics.storage_left < 2: question = f"Storage is low: only {metrics.storage_left} GB left. Clear dangling docker images/containers?" if await bot.decide(question, ["yes", "no"]) == 0: - free_storage() + log.info(f"Pruned: {docker_client.images.prune()}") + log.info(f"Pruned: {docker_client.containers.prune()}") + + +@jobs.register(time_in_seconds(minutes=1)) +async def verify_cloud(): + nx_containers = [] + for container in docker_client.containers.list(True): + if container.name in ["nextcloud", "nextcloud-db"]: + nx_containers.append(container) + + for container in nx_containers: + if container.status != "running": + if await bot.decide(f"Nexcloud container \"{container.name}\" is not running. Start it again?", ["yes", "no"]) == 0: + container.restart() + + +@jobs.register(time_in_seconds(days=3), False) +async def update_packages(): + # TODO: process return code + code = exec_sh("apt-get update") + if await bot.decide(f"`apt-get update` returned status code {code}. Run `apt-get upgrade`?", ["yes", "no"]) == 0: + # TODO: process return code + code = exec_sh("apt-get upgrade")