mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2025-01-19 01:35:28 +01:00
Add the server creation endpoint
This commit is contained in:
parent
53459d83dc
commit
721c9cfe12
@ -35,6 +35,7 @@ class ServersController:
|
||||
server_stop: str,
|
||||
server_type: str,
|
||||
server_port: int = 25565,
|
||||
server_host: str = "127.0.0.1",
|
||||
) -> int:
|
||||
"""Create a server in the database
|
||||
|
||||
@ -48,7 +49,8 @@ class ServersController:
|
||||
server_log_file: The path to the server log file
|
||||
server_stop: This is the command to stop the server
|
||||
server_type: This is the type of server you're creating.
|
||||
server_port: The port the server will run on, defaults to 25565 (optional)
|
||||
server_port: The port the server will be monitored on, defaults to 25565
|
||||
server_host: The host the server will be monitored on, defaults to 127.0.0.1
|
||||
|
||||
Returns:
|
||||
int: The new server's id
|
||||
@ -67,6 +69,7 @@ class ServersController:
|
||||
server_stop,
|
||||
server_type,
|
||||
server_port,
|
||||
server_host,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
@ -95,6 +95,7 @@ class HelperServers:
|
||||
server_stop: str,
|
||||
server_type: str,
|
||||
server_port: int = 25565,
|
||||
server_host: str = "127.0.0.1",
|
||||
) -> int:
|
||||
"""Create a server in the database
|
||||
|
||||
@ -108,7 +109,8 @@ class HelperServers:
|
||||
server_log_file: The path to the server log file
|
||||
server_stop: This is the command to stop the server
|
||||
server_type: This is the type of server you're creating.
|
||||
server_port: The port the server will run on, defaults to 25565 (optional)
|
||||
server_port: The port the server will be monitored on, defaults to 25565
|
||||
server_host: The host the server will be monitored on, defaults to 127.0.0.1
|
||||
|
||||
Returns:
|
||||
int: The new server's id
|
||||
@ -128,6 +130,7 @@ class HelperServers:
|
||||
Servers.crash_detection: False,
|
||||
Servers.log_path: server_log_file,
|
||||
Servers.server_port: server_port,
|
||||
Servers.server_ip: server_host,
|
||||
Servers.stop_command: server_stop,
|
||||
Servers.backup_path: backup_path,
|
||||
Servers.type: server_type,
|
||||
|
@ -72,7 +72,7 @@ class Helpers:
|
||||
installer.do_install()
|
||||
|
||||
@staticmethod
|
||||
def float_to_string(gbs: int):
|
||||
def float_to_string(gbs: float):
|
||||
s = str(float(gbs) * 1000).rstrip("0").rstrip(".")
|
||||
return s
|
||||
|
||||
@ -232,7 +232,7 @@ class Helpers:
|
||||
return default_return
|
||||
|
||||
with open(self.settings_file, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=1)
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
except Exception as e:
|
||||
logger.critical(
|
||||
|
@ -337,6 +337,177 @@ class Controller:
|
||||
svr_obj = self.get_server_obj(server_id)
|
||||
svr_obj.stop_threaded_server()
|
||||
|
||||
def create_api_server(self, data: dict):
|
||||
server_fs_uuid = Helpers.create_uuid()
|
||||
new_server_path = os.path.join(self.helper.servers_dir, server_fs_uuid)
|
||||
backup_path = os.path.join(self.helper.backup_path, server_fs_uuid)
|
||||
|
||||
if Helpers.is_os_windows():
|
||||
new_server_path = Helpers.wtol_path(new_server_path)
|
||||
backup_path = Helpers.wtol_path(backup_path)
|
||||
new_server_path.replace(" ", "^ ")
|
||||
backup_path.replace(" ", "^ ")
|
||||
|
||||
Helpers.ensure_dir_exists(new_server_path)
|
||||
Helpers.ensure_dir_exists(backup_path)
|
||||
|
||||
def _copy_import_dir_files(existing_server_path):
|
||||
existing_server_path = Helpers.get_os_understandable_path(
|
||||
existing_server_path
|
||||
)
|
||||
try:
|
||||
FileHelpers.copy_dir(existing_server_path, new_server_path, True)
|
||||
except shutil.Error as ex:
|
||||
logger.error(f"Server import failed with error: {ex}")
|
||||
|
||||
def _create_server_properties_if_needed(port, empty=False):
|
||||
properties_file = os.path.join(new_server_path, "server.properties")
|
||||
has_properties = os.path.exists(properties_file)
|
||||
|
||||
if not has_properties:
|
||||
logger.info(
|
||||
f"No server.properties found on import."
|
||||
f"Creating one with port selection of {port}"
|
||||
)
|
||||
with open(
|
||||
properties_file,
|
||||
"w",
|
||||
encoding="utf-8",
|
||||
) as file:
|
||||
file.write(
|
||||
"# generated by Crafty Controller"
|
||||
+ ("" if empty else f"\nserver-port={port}")
|
||||
)
|
||||
|
||||
root_create_data = data[data["create_type"] + "_create_data"]
|
||||
create_data = root_create_data[root_create_data["create_type"] + "_create_data"]
|
||||
if data["create_type"] == "minecraft_java":
|
||||
if root_create_data["create_type"] == "download_jar":
|
||||
server_file = f"{create_data['type']}-{create_data['version']}.jar"
|
||||
full_jar_path = os.path.join(new_server_path, server_file)
|
||||
|
||||
# Create an EULA file
|
||||
with open(
|
||||
os.path.join(new_server_path, "eula.txt"), "w", encoding="utf-8"
|
||||
) as file:
|
||||
file.write(
|
||||
"eula=" + ("true" if create_data["agree_to_eula"] else "false")
|
||||
)
|
||||
elif root_create_data["create_type"] == "import_server":
|
||||
_copy_import_dir_files(create_data["existing_server_path"])
|
||||
full_jar_path = os.path.join(new_server_path, create_data["jarfile"])
|
||||
elif root_create_data["create_type"] == "import_zip":
|
||||
# TODO: Copy files from the zip file to the new server directory
|
||||
full_jar_path = os.path.join(new_server_path, create_data["jarfile"])
|
||||
raise Exception("Not yet implemented")
|
||||
_create_server_properties_if_needed(create_data["server_properties_port"])
|
||||
|
||||
min_mem = create_data["mem_min"]
|
||||
max_mem = create_data["mem_max"]
|
||||
|
||||
def _gibs_to_mibs(gibs: float) -> str:
|
||||
return str(int(gibs * 1024))
|
||||
|
||||
def _wrap_jar_if_windows():
|
||||
return (
|
||||
f'"{full_jar_path}"' if Helpers.is_os_windows() else full_jar_path
|
||||
)
|
||||
|
||||
server_command = (
|
||||
f"java -Xms{_gibs_to_mibs(min_mem)}M "
|
||||
f"-Xmx{_gibs_to_mibs(max_mem)}M "
|
||||
f"-jar {_wrap_jar_if_windows()} nogui"
|
||||
)
|
||||
elif data["create_type"] == "minecraft_bedrock":
|
||||
if root_create_data["create_type"] == "import_server":
|
||||
existing_server_path = Helpers.get_os_understandable_path(
|
||||
create_data["existing_server_path"]
|
||||
)
|
||||
try:
|
||||
FileHelpers.copy_dir(existing_server_path, new_server_path, True)
|
||||
except shutil.Error as ex:
|
||||
logger.error(f"Server import failed with error: {ex}")
|
||||
elif root_create_data["create_type"] == "import_zip":
|
||||
# TODO: Copy files from the zip file to the new server directory
|
||||
raise Exception("Not yet implemented")
|
||||
|
||||
_create_server_properties_if_needed(0, True)
|
||||
|
||||
server_command = create_data["command"]
|
||||
server_file = ""
|
||||
elif data["create_type"] == "custom":
|
||||
# TODO: working_directory, executable_update
|
||||
if root_create_data["create_type"] == "raw_exec":
|
||||
pass
|
||||
elif root_create_data["create_type"] == "import_server":
|
||||
existing_server_path = Helpers.get_os_understandable_path(
|
||||
create_data["existing_server_path"]
|
||||
)
|
||||
try:
|
||||
FileHelpers.copy_dir(existing_server_path, new_server_path, True)
|
||||
except shutil.Error as ex:
|
||||
logger.error(f"Server import failed with error: {ex}")
|
||||
elif root_create_data["create_type"] == "import_zip":
|
||||
# TODO: Copy files from the zip file to the new server directory
|
||||
raise Exception("Not yet implemented")
|
||||
|
||||
_create_server_properties_if_needed(0, True)
|
||||
|
||||
server_command = create_data["command"]
|
||||
server_file = root_create_data["executable_update"].get("file", "")
|
||||
|
||||
stop_command = data.get("stop_command", "")
|
||||
if stop_command == "":
|
||||
# TODO: different default stop commands for server creation types
|
||||
stop_command = "stop"
|
||||
|
||||
log_location = data.get("log_location", "")
|
||||
if log_location == "":
|
||||
# TODO: different default log locations for server creation types
|
||||
log_location = "/logs/latest.log"
|
||||
|
||||
if data["monitoring_type"] == "minecraft_java":
|
||||
monitoring_port = data["minecraft_java_monitoring_data"]["port"]
|
||||
monitoring_host = data["minecraft_java_monitoring_data"]["host"]
|
||||
monitoring_type = "minecraft-java"
|
||||
elif data["monitoring_type"] == "minecraft_bedrock":
|
||||
monitoring_port = data["minecraft_bedrock_monitoring_data"]["port"]
|
||||
monitoring_host = data["minecraft_bedrock_monitoring_data"]["host"]
|
||||
monitoring_type = "minecraft-bedrock"
|
||||
elif data["monitoring_type"] == "none":
|
||||
# TODO: this needs to be NUKED..
|
||||
# There shouldn't be anything set if there are nothing to monitor
|
||||
monitoring_port = 25565
|
||||
monitoring_host = "127.0.0.1"
|
||||
monitoring_type = "minecraft-java"
|
||||
|
||||
new_server_id = self.register_server(
|
||||
name=data["name"],
|
||||
server_uuid=server_fs_uuid,
|
||||
server_dir=new_server_path,
|
||||
backup_path=backup_path,
|
||||
server_command=server_command,
|
||||
server_file=server_file,
|
||||
server_log_file=log_location,
|
||||
server_stop=stop_command,
|
||||
server_port=monitoring_port,
|
||||
server_host=monitoring_host,
|
||||
server_type=monitoring_type,
|
||||
)
|
||||
|
||||
if (
|
||||
data["create_type"] == "minecraft_java"
|
||||
and root_create_data["create_type"] == "download_jar"
|
||||
):
|
||||
self.server_jars.download_jar(
|
||||
create_data["type"],
|
||||
create_data["version"],
|
||||
full_jar_path,
|
||||
new_server_id,
|
||||
)
|
||||
|
||||
return new_server_id, server_fs_uuid
|
||||
|
||||
def create_jar_server(
|
||||
self,
|
||||
server: str,
|
||||
@ -759,6 +930,7 @@ class Controller:
|
||||
server_stop: str,
|
||||
server_port: int,
|
||||
server_type: str,
|
||||
server_host: str = "127.0.0.1",
|
||||
):
|
||||
# put data in the db
|
||||
new_id = self.servers.create_server(
|
||||
@ -772,6 +944,7 @@ class Controller:
|
||||
server_stop,
|
||||
server_type,
|
||||
server_port,
|
||||
server_host,
|
||||
)
|
||||
|
||||
if not Helpers.check_file_exists(
|
||||
@ -788,7 +961,6 @@ class Controller:
|
||||
"The server is managed by Crafty Controller.\n "
|
||||
"Leave this directory/files alone please"
|
||||
)
|
||||
file.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Unable to create required server files due to :{e}")
|
||||
|
@ -30,6 +30,7 @@ new_server_schema = {
|
||||
"version": "1.18.2",
|
||||
"mem_min": 1,
|
||||
"mem_max": 2,
|
||||
"server_properties_port": 25565,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -90,7 +91,6 @@ new_server_schema = {
|
||||
"type": "string",
|
||||
"default": "127.0.0.1",
|
||||
"examples": ["127.0.0.1"],
|
||||
"pattern": "^.*$",
|
||||
},
|
||||
"port": {
|
||||
"title": "Port",
|
||||
@ -142,7 +142,14 @@ new_server_schema = {
|
||||
"download_jar_create_data": {
|
||||
"title": "JAR download data",
|
||||
"type": "object",
|
||||
"required": ["type", "version", "mem_min", "mem_max"],
|
||||
"required": [
|
||||
"type",
|
||||
"version",
|
||||
"mem_min",
|
||||
"mem_max",
|
||||
"server_properties_port",
|
||||
"agree_to_eula",
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"title": "Server JAR Type",
|
||||
@ -155,19 +162,31 @@ new_server_schema = {
|
||||
"examples": ["1.18.2"],
|
||||
},
|
||||
"mem_min": {
|
||||
"title": "Minimum JVM memory",
|
||||
"title": "Minimum JVM memory (in GiBs)",
|
||||
"type": "number",
|
||||
"examples": [1],
|
||||
"default": 1,
|
||||
"exclusiveMinimum": 0,
|
||||
},
|
||||
"mem_max": {
|
||||
"title": "Maximum JVM memory",
|
||||
"title": "Maximum JVM memory (in GiBs)",
|
||||
"type": "number",
|
||||
"examples": [2],
|
||||
"default": 2,
|
||||
"exclusiveMinimum": 0,
|
||||
},
|
||||
"server_properties_port": {
|
||||
"title": "Port",
|
||||
"type": "integer",
|
||||
"examples": [25565],
|
||||
"default": 25565,
|
||||
"minimum": 0,
|
||||
},
|
||||
"agree_to_eula": {
|
||||
"title": "Agree to the EULA",
|
||||
"type": "boolean",
|
||||
"default": False,
|
||||
},
|
||||
},
|
||||
},
|
||||
"import_server_create_data": {
|
||||
@ -178,6 +197,8 @@ new_server_schema = {
|
||||
"jarfile",
|
||||
"mem_min",
|
||||
"mem_max",
|
||||
"server_properties_port",
|
||||
"agree_to_eula",
|
||||
],
|
||||
"properties": {
|
||||
"existing_server_path": {
|
||||
@ -190,22 +211,34 @@ new_server_schema = {
|
||||
"title": "JAR file",
|
||||
"description": "The JAR file relative to the previous path",
|
||||
"type": "string",
|
||||
"examples": ["paper.jar"],
|
||||
"examples": ["paper.jar", "jars/vanilla-1.12.jar"],
|
||||
},
|
||||
"mem_min": {
|
||||
"title": "Minimum JVM memory",
|
||||
"title": "Minimum JVM memory (in GiBs)",
|
||||
"type": "number",
|
||||
"examples": [1],
|
||||
"default": 1,
|
||||
"exclusiveMinimum": 0,
|
||||
},
|
||||
"mem_max": {
|
||||
"title": "Maximum JVM memory",
|
||||
"title": "Maximum JVM memory (in GiBs)",
|
||||
"type": "number",
|
||||
"examples": [2],
|
||||
"default": 2,
|
||||
"exclusiveMinimum": 0,
|
||||
},
|
||||
"server_properties_port": {
|
||||
"title": "Port",
|
||||
"type": "integer",
|
||||
"examples": [25565],
|
||||
"default": 25565,
|
||||
"minimum": 0,
|
||||
},
|
||||
"agree_to_eula": {
|
||||
"title": "Agree to the EULA",
|
||||
"type": "boolean",
|
||||
"default": False,
|
||||
},
|
||||
},
|
||||
},
|
||||
"import_zip_create_data": {
|
||||
@ -217,6 +250,8 @@ new_server_schema = {
|
||||
"jarfile",
|
||||
"mem_min",
|
||||
"mem_max",
|
||||
"server_properties_port",
|
||||
"agree_to_eula",
|
||||
],
|
||||
"properties": {
|
||||
"zip_path": {
|
||||
@ -229,7 +264,7 @@ new_server_schema = {
|
||||
"title": "Server root directory",
|
||||
"description": "The server root in the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/", "/paper-server/"],
|
||||
"examples": ["/", "/paper-server/", "server-1"],
|
||||
},
|
||||
"jarfile": {
|
||||
"title": "JAR file",
|
||||
@ -238,19 +273,31 @@ new_server_schema = {
|
||||
"examples": ["paper.jar", "jars/vanilla-1.12.jar"],
|
||||
},
|
||||
"mem_min": {
|
||||
"title": "Minimum JVM memory",
|
||||
"title": "Minimum JVM memory (in GiBs)",
|
||||
"type": "number",
|
||||
"examples": [1],
|
||||
"default": 1,
|
||||
"exclusiveMinimum": 0,
|
||||
},
|
||||
"mem_max": {
|
||||
"title": "Maximum JVM memory",
|
||||
"title": "Maximum JVM memory (in GiBs)",
|
||||
"type": "number",
|
||||
"examples": [2],
|
||||
"default": 2,
|
||||
"exclusiveMinimum": 0,
|
||||
},
|
||||
"server_properties_port": {
|
||||
"title": "Port",
|
||||
"type": "integer",
|
||||
"examples": [25565],
|
||||
"default": 25565,
|
||||
"minimum": 0,
|
||||
},
|
||||
"agree_to_eula": {
|
||||
"title": "Agree to the EULA",
|
||||
"type": "boolean",
|
||||
"default": False,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -333,7 +380,7 @@ new_server_schema = {
|
||||
"title": "Server root directory",
|
||||
"description": "The server root in the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/", "/paper-server/"],
|
||||
"examples": ["/", "/paper-server/", "server-1"],
|
||||
},
|
||||
"command": {
|
||||
"title": "Command",
|
||||
@ -382,6 +429,7 @@ new_server_schema = {
|
||||
"properties": {
|
||||
"working_directory": {
|
||||
"title": "Working directory",
|
||||
"description": '"" means the default',
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"examples": ["/mnt/mydrive/server-configs/", "./subdirectory", ""],
|
||||
@ -390,6 +438,7 @@ new_server_schema = {
|
||||
"title": "Executable Updation",
|
||||
"description": "Also configurable later on and for other servers",
|
||||
"type": "object",
|
||||
"required": ["enabled", "file", "url"],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"title": "Enabled",
|
||||
@ -413,7 +462,7 @@ new_server_schema = {
|
||||
"title": "Creation type",
|
||||
"type": "string",
|
||||
"default": "raw_exec",
|
||||
"enum": ["raw_exec", "import_exec", "import_zip"],
|
||||
"enum": ["raw_exec", "import_server", "import_zip"],
|
||||
},
|
||||
"raw_exec_create_data": {
|
||||
"title": "Raw execution command create data",
|
||||
@ -462,7 +511,7 @@ new_server_schema = {
|
||||
"title": "Server root directory",
|
||||
"description": "The server root in the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/", "/paper-server/"],
|
||||
"examples": ["/", "/paper-server/", "server-1"],
|
||||
},
|
||||
"command": {
|
||||
"title": "Command",
|
||||
@ -485,7 +534,9 @@ new_server_schema = {
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {"create_type": {"const": "import_exec"}}
|
||||
"properties": {
|
||||
"create_type": {"const": "import_server"}
|
||||
}
|
||||
},
|
||||
"then": {"required": ["import_server_create_data"]},
|
||||
},
|
||||
@ -611,12 +662,21 @@ class ApiServersIndexHandler(BaseApiHandler):
|
||||
},
|
||||
)
|
||||
|
||||
# TODO: implement everything
|
||||
new_server_id, new_server_uuid = self.controller.create_api_server(data)
|
||||
|
||||
# Increase the server creation counter
|
||||
self.controller.crafty_perms.add_server_creation(user["user_id"])
|
||||
|
||||
self.controller.stats.record_stats()
|
||||
|
||||
self.controller.management.add_to_audit_log(
|
||||
user["user_id"],
|
||||
f"Created server {'1234'} (ID:{123})",
|
||||
server_id=0,
|
||||
(
|
||||
f"created server {data['name']}"
|
||||
f" (ID: {new_server_id})"
|
||||
f" (UUID: {new_server_uuid})"
|
||||
),
|
||||
server_id=new_server_id,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
|
||||
@ -624,5 +684,11 @@ class ApiServersIndexHandler(BaseApiHandler):
|
||||
|
||||
self.finish_json(
|
||||
201,
|
||||
{"status": "ok", "data": {"server_id": ""}},
|
||||
{
|
||||
"status": "ok",
|
||||
"data": {
|
||||
"new_server_id": str(new_server_id),
|
||||
"new_server_uuid": new_server_uuid,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user