import os import requests from pymongo import MongoClient from bson.objectid import ObjectId import datetime _var = "/opt/legendary-octo-garbanzo" _cmd = "manage-tenants.sh" MONGO_URI = os.environ.get("MONGO_URI", "mongodb://localhost:27017") MONGO_DB_NAME = os.environ.get("MONGO_DB_NAME", "Invario_Website") def _get_users_collection(): client = MongoClient(MONGO_URI, serverSelectionTimeoutMS=1500) db = client[MONGO_DB_NAME] return client, db["packages"] def add_dns(name: str, port: int) -> bool: """ Adds the subdomain to the DNS Routes Input: - name (Name of the subdomain) -> String - port (Port number for the subdomain) -> int Output: - bool (True if adding of the Subdomain is active) """ # This is a placeholder function, as the actual implementation would depend on the DNS provider and how the DNS records are managed. return False def clear_special(var_:str) -> str: """ Clears the variable of any special carakters Input: - var -> String Output: - str cleared of the speacial carakters """ # Refactor the name varible to match the subdomain requirements try: var_ = var_.lower() special_caracters1 = '^°!"§$%&/()=?\ß{[]}´`*~#,;.:<>|@€µ' special_caracters2 = 'äüö' for char in special_caracters1: var_ = var_.replace(char, "") for i in special_caracters2: match i: case "ü": var_ = var_.replace(i, "ue") case "ä": var_ = var_.replace(i, "ae") case "ö": var_ = var_.replace(i, "oe") except: return False def execute_script(wd_: str, file_: str, com_: str, com2_: str="None", com3_: str="None"): """ executes a script with the option of to extra inputs Input: - wd_ = working directory of the Inventorysystem -> String - file_ = working file that youre targeting -> String - com_ = first option -> String - com2_ = second option (Optional if needet)-> String - com3_ = third option (Optional if needet)-> String Output: - ether False if failed -> bool - or result.stdout output of the executed process -> str """ import subprocess update_path = os.path.join(wd_, file_) if not update_path: return False if com2_ != "None": cmd = f'bash "{update_path}" {com_} {com2_}' elif com3_ != "None": cmd = f'bash "{update_path}" {com_} {com2_} {com3_}' else: cmd = f'bash "{update_path}" {com_}' try: result = subprocess.run( ["bash", "-lc", cmd], capture_output=True, text=True, cwd=wd_, ) except: return False return result.stdout class versions: """ This will give access to anything like: - Version of the Inventorysystem - Version of the Server modules: - inventorysystem() - server() """ def inventorysystem(name: str) -> str: """ Version of the Inventorysystem Output: - version -> String """ return instace.edit(name, "inventarsystem") def bibliothek(name: str) -> str: """ Version of the Inventorysystem Output: - version -> String """ return instace.edit(name, "buecherei") def terminplanen(name: str) -> str: """ Version of the Inventorysystem Output: - version -> String """ return instace.edit(name, "terminverwaltung") def emailversand(name: str) -> str: """ Version of the Inventorysystem Output: - version -> String """ return instace.edit(name, "emailversand") def starter(name: str) -> str: """ Version of the Inventorysystem Output: - version -> String """ return instace.edit(name, "starter") def advanced(name: str) -> str: """ Version of the Inventorysystem Output: - version -> String """ return instace.edit(name, "advanced") def testversion(name: str) -> str: """ Version of the Inventorysystem Output: - version -> String """ client = None try: client, packages = _get_users_collection() packages.insert_one( { 'client_name': name, 'inventarsystem': False, 'buecherei': False, 'terminverwaltung': False, 'emailversand': False, 'starter': False, 'advanced': False, 'registered_on': datetime.datetime.utcnow() } ) return True finally: if client: client.close() return instace.edit(name, "starter") def _get_auth(name: str) -> int: """ Check if the if it is older than 5 days Test Version Output: - days since registration -> int """ client = None try: client, packages = _get_users_collection() package = packages.find_one({'client_name': name}) or {} for key in package: if key == "registered_on": if package[key]: instance_age = (datetime.datetime.utcnow() - package[key]).days else: instance_age = None finally: if client: client.close() return int(instance_age) if int(instance_age) is not None and instance_age <= 5 else False class instace: """ This will give access to anything like: - Instances for Clients - starting - stopping - restarting - list all Clients modules: - new(name:str) - remove(name:str) - status(name:str) - restart(name:str) - list() """ def __init__(): return list() def new_trial(name: str) -> bool: """ Generates a new trial instance with the subdomain [name].invario.eu Input: - name -> String Output: - bool if the creation of the instance works (True: creation worked; False: didnt work) manage-tenant.sh trial [port] [days] """ port_starter = 10002 port = port_starter for i in instace.list(): port =+ 1 if execute_script(_var, _cmd, "trial", clear_special(name), port): add_dns(name, port) return int(port) else: return False def new(name: str) -> int: """ Generates a new instance with the subdomain [name].invario.eu Input: - name -> String Output: - int (Port number for the subdomain) or False if the creation of the instance didnt work """ port_starter = 10002 port = port_starter for i in instace.list(): port =+ 1 if execute_script(_var, _cmd, "add", clear_special(name), port): add_dns(name, port) return int(port) else: return False def edit(name: str, module:str) -> bool: """ Edits the name of an instance with the subdomain [name].invario.eu to [new_name].invario.eu Input: - name -> String - module -> String (Options: "inventarsystem", "buecherei", "terminverwaltung", "emailversand", "starter", "advanced") Output: - bool if the edit works (True: edit worked; False: didnt work) """ if module == "inventarsystem": if execute_script(_var, _cmd, "module", clear_special(name), 'library=off inventory=on'): return True else: return False elif module == "buecherei": if execute_script(_var, _cmd, "module", clear_special(name), 'library=on inventory=off'): return True else: return False elif module == "terminverwaltung": if execute_script(_var, _cmd, "module", clear_special(name), 'library=off inventory=off'): # -> has to be changed when the module is ready return True else: return False elif module == "emailversand": if execute_script(_var, _cmd, "module", clear_special(name), 'library=off inventory=on'):# -> has to be changed when the module is ready return True else: return False elif module == "starter": if execute_script(_var, _cmd, "module", clear_special(name), 'library=on inventory=on'): return True else: return False elif module == "advanced": if execute_script(_var, _cmd, "module", clear_special(name), 'library=on inventory=on'):# -> has to be changed when the module is ready return True else: return False else: return False def remove(name: str) -> bool: """ Removes a instance with the subdomain [name].invario.eu Input: - name -> String Output: - bool if the removal works (True: removal worked; False: didnt work) """ safe_name = clear_special(name) # try to remove via management script script_ok = execute_script(_var, _cmd, "remove", safe_name) if not script_ok: return False # best-effort: remove the associated package entry from the database client = None try: client, packages = _get_users_collection() packages.delete_one({"client_name": name}) except Exception: # don't fail the overall removal if DB cleanup fails pass finally: if client: client.close() return True def status(name: str) -> bool: """ Returns if a instance with the subdomain [name].invario.eu is up. Input: - name -> String Output: - bool if the page is online (True: Is working; False: Isnt online) """ name = clear_special(name) request = str(requests.get(f"{name}.invario.eu/test_connection")) if request == '{"message":"Connection successful","status":"success","status_code":200}': return True else: return False def restart(name: str) -> bool: """ Restart an instance with the subdomain [name].invario.eu Input: - name -> String Output: - bool if the restart works (True: restart worked; False: didnt work) """ if execute_script(_var, _cmd, "restart-tenant", clear_special(name)): return True else: return False def list() -> list: """ List off all tenants. Output: - list with all tenants ("tenant1", "tenant2") """ result = execute_script(_var, _cmd, "list") if not isinstance(result, str): return [] result = result.splitlines() if not result: return [] return [line.replace("- ", "") for line in result[1:]] def backup(name: str) -> bool: """ Creates a backup of an instance with the subdomain [name].invario.eu Input: - name -> String Output: - bool if the backup works (True: backup worked; False: didnt work) """ import subprocess try: subprocess.run( [ "docker", "compose", "-f", "docker-compose-multitenant.yml", "exec", "-T", "mongodb", "mongodump", f"--archive=/data/backups/inventar_{name}-$(date +%Y%m%d%H%M%S).gz", "--gzip", "--db", f"inventar_{name}" ], check=True ) return True except subprocess.CalledProcessError: return False class ussage: """ This will give informations about anything like: - RAM Ussage of the server - CPU Ussage of the server - Strorage that is in use modules: - ram() - cpu() - storage() """ def ram() -> int: """ RAM ussage of the complete system Output: - ram ussage -> interger in GB """ #print("RAM usage (%):", ram.percent) import psutil ram = psutil.virtual_memory() return int(round(ram.used / 1e9, 2)) def cpu() -> int: """ System cpu ussage Output: - cpu ussage -> integer in Percent """ import psutil return int(psutil.cpu_percent(interval=1)) def storage() -> int: """ System storage ussage Output: - storager ussage -> integer in Percent """ pass