diff --git a/src/actions/__init__.py b/src/actions/__init__.py index f689a298030bdb793cabc394d600864289f1ba2e..23a65a80c4baa198215f907419bd3838e80d10ad 100644 --- a/src/actions/__init__.py +++ b/src/actions/__init__.py @@ -4,6 +4,7 @@ from .interactive_session import * from .permissions import * from .server_management import * from .stats import * +from .systemctl import * from ..models.crud.server_crud import fn_get_all_chat_ids diff --git a/src/actions/basic_actions.py b/src/actions/basic_actions.py index 5c35909c6f12b7373d32e0bfe0bc744a5b012d6c..9b48d46518407851ad96c16c6fa2772e51aa68a6 100644 --- a/src/actions/basic_actions.py +++ b/src/actions/basic_actions.py @@ -21,6 +21,7 @@ async def overall_help(message: Message, state=None): # '* meme admin commands - Manage stored commands\n\n' '* meme admin exec {alias} {command} - Execute single command\n\n' '* meme admin docker - Manage docker on remote server\n\n' + '* meme admin sys - Manage systemctl on remote server\n\n' '* meme admin stats - See server statistics\n\n' '```', parse_mode=ParseMode.MARKDOWN diff --git a/src/actions/systemctl.py b/src/actions/systemctl.py new file mode 100644 index 0000000000000000000000000000000000000000..8a922405136dfe1dedc2b84aa89c7bb16c4c9518 --- /dev/null +++ b/src/actions/systemctl.py @@ -0,0 +1,112 @@ +import logging +import re + +from aiogram.types import Message, ParseMode + +from src.models.server import ServerPermissions +from src.utils.debug_mode import debug_message +from src.utils.decorators import ( + bot_action +) +from src.utils.server_utils import get_server_by_alias +from src.utils.ssh import run_ssh_command + +logger = logging.getLogger(__name__) + + +@bot_action(r'meme admin sys( help)?$') +async def overall_help(message: Message, state=None): + await message.reply( + '```\n' + '* sys stats {alias} {service} - Check status of the service\n\n' + '* sys start {alias} {service} - Start the service\n\n' + '* sys stop {alias} {service} - Stop the service\n\n' + '* sys restart {alias} {service} - Restart the service\n\n' + '* sys cat {alias} {service} - Show one or more service unit files\n\n' + '```', + parse_mode=ParseMode.MARKDOWN + ) + + +@bot_action(r'meme admin sys stats', + params=[ + ('alias', r'[\w\d]+'), + ('service', r'[\w\d]+\.service') + ]) +async def status(message: Message, alias, service, state): + server = await get_server_by_alias(message, + server_alias=alias, + minimal_permission=ServerPermissions.SERVICES) + service_info = await run_ssh_command(server, f'systemctl status {service}') + description = re.search(r'(.*) - (?P<description>.*)', service_info.splitlines()[0]) + startup_file = re.search(r'(.*)Loaded: loaded \((?P<file>.*\.service)', service_info) + service_state = re.search(r'(.*)Active: (?P<state>.*) since (.*); (?P<uptime>.*)', service_info) + pid = re.search(r'(.*)Main PID: (?P<pid>.*)', service_info) + tasks = re.search(r'(.*)Tasks: (?P<tasks>.*)', service_info) + memory = re.search(r'(.*)Memory: (?P<memory>.*)', service_info) + res_message = "```\n" + await debug_message(message, service_info) + for regex in [description, startup_file, service_state, pid, tasks, memory]: + if regex is None: + continue + for key, val in regex.groupdict().items(): + res_message += f'{key}: {val}\n\n' + res_message += '```' + await message.reply(res_message, parse_mode=ParseMode.MARKDOWN) + + +@bot_action(r'meme admin sys start', + params=[ + ('alias', r'[\w\d]+'), + ('service', r'[\w\d]+\.service') + ]) +async def start(message: Message, alias, service, state): + server = await get_server_by_alias(message, + server_alias=alias, + minimal_permission=ServerPermissions.SERVICES) + await run_ssh_command(server, f'systemctl start {service}') + await message.reply("Service started") + + +@bot_action(r'meme admin sys stop', + params=[ + ('alias', r'[\w\d]+'), + ('service', r'[\w\d]+\.service') + ]) +async def stop(message: Message, alias, service, state): + server = await get_server_by_alias(message, + server_alias=alias, + minimal_permission=ServerPermissions.SERVICES) + await run_ssh_command(server, f'systemctl stop {service}') + await message.reply("Service stopped") + + +@bot_action(r'meme admin sys restart', + params=[ + ('alias', r'[\w\d]+'), + ('service', r'[\w\d]+\.service') + ]) +async def restart(message: Message, alias, service, state): + server = await get_server_by_alias(message, + server_alias=alias, + minimal_permission=ServerPermissions.SERVICES) + await run_ssh_command(server, f'systemctl restart {service}') + await message.reply("Service restarted") + + +@bot_action(r'meme admin sys cat', + params=[ + ('alias', r'[\w\d]+'), + ('service', r'[\w\d]+\.service') + ]) +async def cat(message: Message, alias, service, state): + server = await get_server_by_alias(message, + server_alias=alias, + minimal_permission=ServerPermissions.SERVICES) + out = await run_ssh_command(server, f'systemctl cat {service}') + await message.reply( + '```\n' + f'{out}' + '```', + parse_mode=ParseMode.MARKDOWN + )