From 43d1a912b0e7ac0bfab7c6ad48810649e5a2cb11 Mon Sep 17 00:00:00 2001 From: Chris Josten Date: Fri, 13 Mar 2020 14:15:38 +0100 Subject: [PATCH] Voeg ober-broncode toe --- ober/README.md | 13 +++++ ober/aiuo-shutdown.service | 12 +++++ ober/ober/__init__.py | 0 ober/ober/autoshutdown.py | 103 +++++++++++++++++++++++++++++++++++++ ober/setup.py | 16 ++++++ 5 files changed, 144 insertions(+) create mode 100644 ober/README.md create mode 100644 ober/aiuo-shutdown.service create mode 100644 ober/ober/__init__.py create mode 100755 ober/ober/autoshutdown.py create mode 100644 ober/setup.py diff --git a/ober/README.md b/ober/README.md new file mode 100644 index 0000000..b7e4a12 --- /dev/null +++ b/ober/README.md @@ -0,0 +1,13 @@ +# Hoe te gebruiken +1. Voer `sudo pip3 install .` uit in deze map. + - Je zou een specifieke gebruiker aan kunnen maken voor dit script, maar zorg dan + wel dat deze gebruiker machtigingen heeft om het commando "shutdown" uit te voeren. +2. Pas aiuo-shutdown.service aan + - Vervang [wachttijd] door de tijd die gewacht moet worden (in secondes) + en [klant-ip] door het ip-adres van het rekentuig dat de klant draait. + - Als je het programmaatje niet als root wilt uitvoeren, verander dan ook + de gebruiker in dit script. +3. Plaats aiuo-shutdown.service in `/etc/systemd/system`. +4. Start de de systemd-service. Als je zeker weet dat het werkt, schakel het dan in. + - Ik heb mijn rekentuig een keer onopstartbaar gemaakt, omdat het zichzelf meteen + afsloot. Houd hier rekening mee! diff --git a/ober/aiuo-shutdown.service b/ober/aiuo-shutdown.service new file mode 100644 index 0000000..3102468 --- /dev/null +++ b/ober/aiuo-shutdown.service @@ -0,0 +1,12 @@ +[Unit] +Description=AIUO Shutdown Manager +Wants=network-online.target +After=network-online.target + +[Service] +Type=idle +ExecStart=aiuo-shutdown [timeout] [ip user] +User=root + +[Install] +WantedBy=multi-user.target diff --git a/ober/ober/__init__.py b/ober/ober/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ober/ober/autoshutdown.py b/ober/ober/autoshutdown.py new file mode 100755 index 0000000..175b7c8 --- /dev/null +++ b/ober/ober/autoshutdown.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +import aio_msgpack_rpc +import argparse +import asyncio +import logging +import os +import subprocess +import time + +CLIENT_IP="example.org" +LOGGER = logging.getLogger(__name__) +TIMEOUT: float = 30 * 60 +last_checked: float = time.time() +last_checked_value: bool = False +cur_timeout: float = TIMEOUT + + +def count_users() -> int: + """Checks if any users are logged in""" + cmd = "who | wc -l" + ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT) + output = ps.communicate()[0] + try: + user_count = int(output) + except Exception as e: + LOGGER.exception(f"{output} could not be parsed as an int") + return user_count + +def count_minecraft_players() -> int: + """Checks if there any minecraft players""" + cmd = "netstat | grep 25565 | grep -v TIME_WAIT | wc -l" + ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT) + output = ps.communicate()[0] + try: + minecraft_players = int(output) + except Exception as e: + LOGGER.exception(f"{output} could not be parsed as an int") + return minecraft_players + +def should_shutdown() -> bool: + user_count = count_users() + player_count = count_minecraft_players() + res = user_count == 0 and player_count == 0 + LOGGER.debug(f"Player count: {player_count}") + LOGGER.debug(f"User count: {user_count}") + LOGGER.info("Should shut down" if res else "Should not shut down") + return res + +def trusty_sleep(amount: float): + while time.time() - last_checked < amount: + LOGGER.debug("Woke up early") + time.sleep(amount - (time.time() - last_checked)) + +async def main() -> None: + global TIMEOUT + global CLIENT_IP + global last_checked + global last_checked_value + + logging.basicConfig(format='[%(asctime)s %(levelname)s] %(name)s: %(message)s', level=logging.DEBUG) + argparser = argparse.ArgumentParser(description="AIUO - Automatisch In- en Uitschakelen Ober (Oberkant)") + argparser.add_argument("wachttijd", type=float, help="Wachttijd voor het uitschakelen van ober, in secondes") + argparser.add_argument("ip_klant", type=str, help="IP-adres van klant") + args = argparser.parse_args() + CLIENT_IP = args.ip_klant + TIMEOUT = args.wachttijd + + LOGGER.debug("Trying to connect via RPC") + + success = False + while not success: + try: + client = aio_msgpack_rpc.Client(*await asyncio.open_connection(CLIENT_IP, 18002)) + success = True + except Exception as e: + LOGGER.debug(f"Connection failed: {e}. Retrying in 10s") + await asyncio.sleep(10) + + LOGGER.debug(await client.call("GetBootReason")) + + + final_verdict = False + while not final_verdict: + LOGGER.debug("Stayling alive") + trusty_sleep(TIMEOUT / 2) + last_checked = time.time() + + shutdown = should_shutdown() + if last_checked_value and shutdown: + break + elif shutdown: + last_checked_value = True + else: + last_checked_value = False + + os.system("shutdown +1 The system is going to shut down because no active sessions were found and no one is on the server") + + +def start_main(): + asyncio.run(main()) + +if __name__ == "__main__": + start_main() diff --git a/ober/setup.py b/ober/setup.py new file mode 100644 index 0000000..00b320b --- /dev/null +++ b/ober/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +from setuptools import setup + +setup(name="AIUO-ober", + version="0.1", + description="Automatisch In- en Uitschakelen Ober Ober", + author="Chris Josten", + author_email="chris@netsoj.nl", + packages=["ober"], + install_requires=["aio_msgpack_rpc"], + entry_points={ + "console_scripts": { + "aiuo-shutdown = ober.autoshutdown:start_main" + } + } + )