feat(utils): add several util methods

Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
dw-0
2023-12-17 14:42:53 +01:00
parent 78cefddb2e
commit a80f0bb0e8
5 changed files with 310 additions and 3 deletions

View File

@@ -18,8 +18,15 @@ import time
import urllib.error
import urllib.request
from pathlib import Path
from typing import List
from typing import List, Literal
from zipfile import ZipFile
from kiauh.utils import (
NGINX_CONFD,
MODULE_PATH,
NGINX_SITES_AVAILABLE,
NGINX_SITES_ENABLED,
)
from kiauh.utils.input_utils import get_confirm
from kiauh.utils.logger import Logger
@@ -273,11 +280,22 @@ def get_ipv4_addr() -> str:
s.close()
def download_file(url: str, target_folder: str, target_name: str, show_progress=True):
def download_file(
url: str, target_folder: str, target_name: str, show_progress=True
) -> None:
"""
Helper method for downloading files from a provided URL |
:param url: the url to the file
:param target_folder: the target folder to download the file into
:param target_name: the name of the downloaded file
:param show_progress: show download progress or not
:return: None
"""
target_path = os.path.join(target_folder, target_name)
try:
if show_progress:
urllib.request.urlretrieve(url, target_path, download_progress)
sys.stdout.write("\n")
else:
urllib.request.urlretrieve(url, target_path)
except urllib.error.HTTPError as e:
@@ -291,7 +309,14 @@ def download_file(url: str, target_folder: str, target_name: str, show_progress=
raise
def download_progress(block_num, block_size, total_size):
def download_progress(block_num, block_size, total_size) -> None:
"""
Reporthook method for urllib.request.urlretrieve() method call in download_file() |
:param block_num:
:param block_size:
:param total_size: total filesize in bytes
:return: None
"""
downloaded = block_num * block_size
percent = 100 if downloaded >= total_size else downloaded / total_size * 100
mb = 1024 * 1024
@@ -300,3 +325,151 @@ def download_progress(block_num, block_size, total_size):
dl = f"\rDownloading: [{'#' * progress}{remaining}]{percent:.2f}% ({downloaded/mb:.2f}/{total_size/mb:.2f}MB)"
sys.stdout.write(dl)
sys.stdout.flush()
def unzip(file: str, target_dir: str) -> None:
"""
Helper function to unzip a zip-archive into a target directory |
:param file: the zip-file to unzip
:param target_dir: the target directory to extract the files into
:return: None
"""
with ZipFile(file, "r") as _zip:
_zip.extractall(target_dir)
def create_upstream_nginx_cfg() -> None:
"""
Creates an upstream.conf in /etc/nginx/conf.d
:return: None
"""
source = os.path.join(MODULE_PATH, "res", "upstreams.conf")
target = os.path.join(NGINX_CONFD, "upstreams.conf")
try:
command = ["sudo", "cp", source, target]
subprocess.run(command, stderr=subprocess.PIPE, check=True)
except subprocess.CalledProcessError as e:
log = f"Unable to create upstreams.conf: {e.stderr.decode()}"
Logger.print_error(log)
raise
def create_common_vars_nginx_cfg() -> None:
"""
Creates a common_vars.conf in /etc/nginx/conf.d
:return: None
"""
source = os.path.join(MODULE_PATH, "res", "common_vars.conf")
target = os.path.join(NGINX_CONFD, "common_vars.conf")
try:
command = ["sudo", "cp", source, target]
subprocess.run(command, stderr=subprocess.PIPE, check=True)
except subprocess.CalledProcessError as e:
log = f"Unable to create upstreams.conf: {e.stderr.decode()}"
Logger.print_error(log)
raise
def create_nginx_cfg(name: str, port: int, root_dir: str) -> None:
"""
Creates an NGINX config from a template file and replaces all placeholders
:param name: name of the config to create
:param port: listen port
:param root_dir: directory of the static files
:return: None
"""
tmp = f"{Path.home()}/{name}.tmp"
shutil.copy(os.path.join(MODULE_PATH, "res", "nginx_cfg"), tmp)
with open(tmp, "r+") as f:
content = f.read()
content = content.replace("%NAME%", name)
content = content.replace("%PORT%", str(port))
content = content.replace("%ROOT_DIR%", root_dir)
f.seek(0)
f.write(content)
f.truncate()
target = os.path.join(NGINX_SITES_AVAILABLE, name)
try:
command = ["sudo", "mv", tmp, target]
subprocess.run(command, stderr=subprocess.PIPE, check=True)
except subprocess.CalledProcessError as e:
log = f"Unable to create '{target}': {e.stderr.decode()}"
Logger.print_error(log)
raise
def delete_default_nginx_cfg() -> None:
"""
Deletes a default NGINX config
:return: None
"""
default_cfg = Path("/etc/nginx/sites-enabled/default")
if not check_file_exists(default_cfg):
return
try:
command = ["sudo", "rm", default_cfg]
subprocess.run(command, stderr=subprocess.PIPE, check=True)
except subprocess.CalledProcessError as e:
log = f"Unable to delete '{default_cfg}': {e.stderr.decode()}"
Logger.print_error(log)
raise
def enable_nginx_cfg(name: str) -> None:
"""
Helper method to enable an NGINX config |
:param name: name of the config to enable
:return: None
"""
source = os.path.join(NGINX_SITES_AVAILABLE, name)
target = os.path.join(NGINX_SITES_ENABLED, name)
if check_file_exists(Path(target)):
return
try:
command = ["sudo", "ln", "-s", source, target]
subprocess.run(command, stderr=subprocess.PIPE, check=True)
except subprocess.CalledProcessError as e:
log = f"Unable to create symlink: {e.stderr.decode()}"
Logger.print_error(log)
raise
def set_nginx_permissions() -> None:
"""
Check if permissions of the users home directory
grant execution rights to group and other and set them if not set.
Required permissions for NGINX to be able to serve Mainsail/Fluidd.
This seems to have become necessary with Ubuntu 21+. |
:return: None
"""
cmd1 = f"ls -ld {Path.home()} | cut -d' ' -f1"
homedir_perm = subprocess.run(cmd1, shell=True, stdout=subprocess.PIPE, text=True)
homedir_perm = homedir_perm.stdout
if homedir_perm.count("x") < 3:
Logger.print_status("Granting NGINX the required permissions ...")
subprocess.run(["chmod", "og+x", Path.home()])
Logger.print_ok("Permissions granted.")
def control_systemd_service(
name: str, action: Literal["start", "stop", "restart", "disable"]
) -> None:
"""
Helper method to execute several actions for a specific systemd service. |
:param name: the service name
:param action: Either "start", "stop", "restart" or "disable"
:return: None
"""
try:
Logger.print_status(f"{action.capitalize()} {name}.service ...")
command = ["sudo", "systemctl", action, f"{name}.service"]
subprocess.run(command, stderr=subprocess.PIPE, check=True)
Logger.print_ok(f"OK!")
except subprocess.CalledProcessError as e:
log = f"Failed to {action} {name}.service: {e.stderr.decode()}"
Logger.print_error(log)
raise