server steering implementation
This commit is contained in:
+79
-227
@@ -16,21 +16,6 @@ def _get_users_collection():
|
||||
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
|
||||
@@ -59,7 +44,7 @@ def clear_special(var_:str) -> str:
|
||||
except:
|
||||
return False
|
||||
|
||||
def execute_script(wd_: str, file_: str, com_: str, com2_: str="None", com3_: str="None"):
|
||||
def execute_script(wd_: str, file_: str, com_: str, com2_: str="None", com3_: str="None", com4_: str="None") -> str:
|
||||
"""
|
||||
executes a script with the option of to extra inputs
|
||||
|
||||
@@ -69,7 +54,7 @@ def execute_script(wd_: str, file_: str, com_: str, com2_: str="None", com3_: st
|
||||
- com_ = first option -> String
|
||||
- com2_ = second option (Optional if needet)-> String
|
||||
- com3_ = third option (Optional if needet)-> String
|
||||
|
||||
- com4_ = fourth option (Optional if needet)-> String
|
||||
Output:
|
||||
- ether False if failed -> bool
|
||||
- or result.stdout output of the executed process -> str
|
||||
@@ -82,6 +67,8 @@ def execute_script(wd_: str, file_: str, com_: str, com2_: str="None", com3_: st
|
||||
cmd = f'bash "{update_path}" {com_} {com2_}'
|
||||
elif com3_ != "None":
|
||||
cmd = f'bash "{update_path}" {com_} {com2_} {com3_}'
|
||||
elif com4_ != "None":
|
||||
cmd = f'bash "{update_path}" {com_} {com2_} {com3_} {com4_}'
|
||||
else:
|
||||
cmd = f'bash "{update_path}" {com_}'
|
||||
try:
|
||||
@@ -210,225 +197,90 @@ class versions:
|
||||
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
|
||||
|
||||
class Instance:
|
||||
@staticmethod
|
||||
def list() -> list:
|
||||
"""
|
||||
List off all tenants.
|
||||
|
||||
Output:
|
||||
- list with all tenants ("tenant1", "tenant2")
|
||||
"""
|
||||
Lists all existing tenants along with their mapped ports.
|
||||
Returns: list of dicts -> [{'name': 'school1', 'port': 10002}, ...]
|
||||
"""
|
||||
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:]]
|
||||
|
||||
tenants = []
|
||||
pattern = re.compile(r"^-\s+([^\s]+)\s+\(port\s+(\d+)\)")
|
||||
for line in result.splitlines():
|
||||
match = pattern.match(line.strip())
|
||||
if match:
|
||||
tenants.append({
|
||||
"name": match.group(1),
|
||||
"port": int(match.group(2))
|
||||
})
|
||||
return tenants
|
||||
|
||||
def backup(name: str) -> bool:
|
||||
"""
|
||||
Creates a backup of an instance with the subdomain [name].invario.eu
|
||||
@classmethod
|
||||
def get_next_available_port(cls, start_port=10002) -> int:
|
||||
tenants = cls.list()
|
||||
if not tenants:
|
||||
return start_port
|
||||
used_ports = [t["port"] for t in tenants]
|
||||
return max(used_ports) + 1
|
||||
|
||||
Input:
|
||||
- name -> String
|
||||
@classmethod
|
||||
def new(cls, name: str, port: int = None, password: str = "admin123") -> bool:
|
||||
safe_name = clear_special(name)
|
||||
if port is None:
|
||||
port = cls.get_next_available_port()
|
||||
|
||||
return execute_script(_var, _cmd, "add", safe_name, str(port), password)
|
||||
|
||||
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:
|
||||
@staticmethod
|
||||
def edit(name: str, module_preset: str) -> bool:
|
||||
safe_name = clear_special(name)
|
||||
presets = {
|
||||
"inventarsystem": "library=off inventory=on student_cards=off terminplan=off",
|
||||
"buecherei": "library=on inventory=off student_cards=off terminplan=off",
|
||||
"terminverwaltung": "library=off inventory=off student_cards=off terminplan=on",
|
||||
"emailversand": "library=off inventory=on student_cards=off terminplan=off",
|
||||
"starter": "library=on inventory=on student_cards=on terminplan=off",
|
||||
"advanced": "library=on inventory=on student_cards=on terminplan=on",
|
||||
}
|
||||
|
||||
config = presets.get(module_preset)
|
||||
if not config:
|
||||
return False
|
||||
|
||||
return execute_script(_var, _cmd, "module", safe_name, config)
|
||||
|
||||
@staticmethod
|
||||
def remove(name: str) -> bool:
|
||||
safe_name = clear_special(name)
|
||||
if not execute_script(_var, _cmd, "remove", safe_name):
|
||||
return False
|
||||
|
||||
try:
|
||||
client, packages = _get_users_collection()
|
||||
packages.delete_one({"client_name": safe_name})
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
if 'client' in locals() and client:
|
||||
client.close()
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def status(name: str) -> bool:
|
||||
safe_name = clear_special(name)
|
||||
try:
|
||||
res = requests.get(f"https://{safe_name}.invario-software.de/health", timeout=5)
|
||||
return res.status_code == 200
|
||||
except requests.RequestException:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def restart(name: str) -> bool:
|
||||
return execute_script(_var, _cmd, "restart-tenant", clear_special(name))
|
||||
|
||||
class ussage:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user