Files

474 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 <tenant_id> [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