bunkerweb 1.4.0
This commit is contained in:
@@ -1,156 +1,214 @@
|
||||
import docker, os, requests, subprocess
|
||||
import os
|
||||
from typing import Any
|
||||
from subprocess import run
|
||||
|
||||
class Instances :
|
||||
from api.API import API
|
||||
from utils.ApiCaller import ApiCaller
|
||||
|
||||
def __init__(self, docker_host, api_uri) :
|
||||
try :
|
||||
self.__docker = docker.DockerClient(base_url=docker_host)
|
||||
except :
|
||||
self.__docker = None
|
||||
self.__api_uri = api_uri
|
||||
|
||||
def __instance(self, id, name, type, status, data=None) :
|
||||
instance = {}
|
||||
instance["id"] = id
|
||||
instance["name"] = name
|
||||
instance["type"] = type
|
||||
instance["status"] = status
|
||||
instance["data"] = data
|
||||
return instance
|
||||
class Instance:
|
||||
_id: str
|
||||
name: str
|
||||
hostname: str
|
||||
_type: str
|
||||
health: bool
|
||||
env: Any
|
||||
apiCaller: ApiCaller
|
||||
|
||||
def __api_request(self, instance, order) :
|
||||
result = True
|
||||
hosts = []
|
||||
if instance["type"] == "container" :
|
||||
hosts.append(instance["name"])
|
||||
elif instances["type"] == "service" :
|
||||
for task in instance["data"].tasks() :
|
||||
host = instance["name"] + "." + task["NodeID"] + "." + task["ID"]
|
||||
hosts.append(host)
|
||||
for host in hosts :
|
||||
try :
|
||||
req = requests.post("http://" + host + ":8080" + self.__api_uri + order)
|
||||
if not req or req.status_code != 200 or req.text != "ok" :
|
||||
result = False
|
||||
except :
|
||||
result = False
|
||||
return result
|
||||
def __init__(
|
||||
self,
|
||||
_id: str,
|
||||
name: str,
|
||||
hostname: str,
|
||||
_type: str,
|
||||
status: str,
|
||||
data: Any = None,
|
||||
apiCaller: ApiCaller = ApiCaller(),
|
||||
) -> None:
|
||||
self._id = _id
|
||||
self.name = name
|
||||
self.hostname = hostname
|
||||
self._type = _type
|
||||
self.health = status == "up" and (
|
||||
(
|
||||
data.attrs["State"]["Health"]["Status"] == "healthy"
|
||||
if "Health" in data.attrs["State"]
|
||||
else False
|
||||
)
|
||||
if data
|
||||
else True
|
||||
)
|
||||
self.env = data
|
||||
self.apiCaller = apiCaller
|
||||
|
||||
def __instance_from_id(self, id) :
|
||||
instances = self.get_instances()
|
||||
for instance in instances :
|
||||
if instance["id"] == id :
|
||||
return instance
|
||||
raise Exception("Can't find instance with id " + id)
|
||||
def get_id(self) -> str:
|
||||
return self._id
|
||||
|
||||
def get_instances(self) :
|
||||
instances = []
|
||||
def run_jobs(self) -> bool:
|
||||
return self.apiCaller._send_to_apis("POST", "/jobs")
|
||||
|
||||
# Docker instances (containers or services)
|
||||
if self.__docker != None :
|
||||
for instance in self.__docker.containers.list(all=True, filters={"label" : "bunkerized-nginx.UI"}) :
|
||||
id = instance.id
|
||||
name = instance.name
|
||||
type = "container"
|
||||
status = "down"
|
||||
if instance.status == "running" :
|
||||
status = "up"
|
||||
instances.append(self.__instance(id, name, type, status, instance))
|
||||
is_swarm = True
|
||||
try :
|
||||
version = self.__docker.swarm.version
|
||||
except :
|
||||
is_swarm = False
|
||||
if is_swarm :
|
||||
for instance in self.__docker.services.list(filters={"label" : "bunkerized-nginx.UI"}) :
|
||||
id = instance.id
|
||||
name = instance.name
|
||||
type = "service"
|
||||
status = "down"
|
||||
desired_tasks = instance.attrs["ServiceStatus"]["DesiredTasks"]
|
||||
running_tasks = instance.attrs["ServiceStatus"]["RunningTasks"]
|
||||
if desired_tasks > 0 and (desired_tasks == running_tasks) :
|
||||
status = "up"
|
||||
instances.append(self.__instance(id, name, type, status, instance))
|
||||
def reload(self) -> bool:
|
||||
return self.apiCaller._send_to_apis("POST", "/reload")
|
||||
|
||||
# Local instance
|
||||
if os.path.exists("/usr/sbin/nginx") :
|
||||
id = "local"
|
||||
name = "local"
|
||||
type = "local"
|
||||
status = "down"
|
||||
if os.path.exists("/tmp/nginx.pid") :
|
||||
status = "up"
|
||||
instances.append(self.__instance(id, name, type, status))
|
||||
def start(self) -> bool:
|
||||
return self.apiCaller._send_to_apis("POST", "/start")
|
||||
|
||||
return instances
|
||||
def stop(self) -> bool:
|
||||
return self.apiCaller._send_to_apis("POST", "/stop")
|
||||
|
||||
def reload_instances(self) :
|
||||
all_reload = True
|
||||
for instance in self.get_instances() :
|
||||
if instance["status"] == "down" :
|
||||
all_reload = False
|
||||
continue
|
||||
if instance["type"] == "local" :
|
||||
proc = subprocess.run(["/opt/bunkerized-nginx/entrypoint/jobs.sh"], capture_output=True)
|
||||
if proc.returncode != 0 :
|
||||
all_reload = False
|
||||
else :
|
||||
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "reload"], capture_output=True)
|
||||
if proc.returncode != 0 :
|
||||
all_reload = False
|
||||
elif instance["type"] == "container" or instance["type"] == "service" :
|
||||
all_reload = self.__api_request(instance, "/reload")
|
||||
return all_reload
|
||||
def restart(self) -> bool:
|
||||
return self.apiCaller._send_to_apis("POST", "/restart")
|
||||
|
||||
def reload_instance(self, id) :
|
||||
instance = self.__instance_from_id(id)
|
||||
result = True
|
||||
if instance["type"] == "local" :
|
||||
proc = subprocess.run(["/opt/bunkerized-nginx/entrypoint/jobs.sh"], capture_output=True)
|
||||
if proc.returncode != 0 :
|
||||
result = False
|
||||
else :
|
||||
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "reload"], capture_output=True)
|
||||
result = proc.returncode == 0
|
||||
elif instance["type"] == "container" or instance["type"] == "service" :
|
||||
result = self.__api_request(instance, "/reload")
|
||||
if result :
|
||||
return "Instance " + instance["name"] + " has been reloaded."
|
||||
return "Can't reload " + instance["name"]
|
||||
|
||||
def start_instance(self, id) :
|
||||
instance = self.__instance_from_id(id)
|
||||
result = True
|
||||
if instance["type"] == "local" :
|
||||
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "start"], capture_output=True)
|
||||
result = proc.returncode == 0
|
||||
elif instance["type"] == "container" or instance["type"] == "service" :
|
||||
result = False #self.__api_request(instance, "/start")
|
||||
if result :
|
||||
return "Instance " + instance["name"] + " has been started."
|
||||
return "Can't start " + instance["name"]
|
||||
class Instances:
|
||||
def __init__(self, docker_client):
|
||||
self.__docker = docker_client
|
||||
|
||||
def stop_instance(self, id) :
|
||||
instance = self.__instance_from_id(id)
|
||||
result = True
|
||||
if instance["type"] == "local" :
|
||||
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "stop"], capture_output=True)
|
||||
result = proc.returncode == 0
|
||||
elif instance["type"] == "container" or instance["type"] == "service" :
|
||||
result = self.__api_request(instance, "/stop")
|
||||
if result :
|
||||
return "Instance " + instance["name"] + " has been stopped."
|
||||
return "Can't stop " + instance["name"]
|
||||
def __instance_from_id(self, _id) -> Instance:
|
||||
instances: list[Instance] = self.get_instances()
|
||||
for instance in instances:
|
||||
if instance._id == _id:
|
||||
return instance
|
||||
|
||||
def restart_instance(self, id) :
|
||||
instance = self.__instance_from_id(id)
|
||||
result = True
|
||||
if instance["type"] == "local" :
|
||||
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "restart"], capture_output=True)
|
||||
result = proc.returncode == 0
|
||||
elif instance["type"] == "container" or instance["type"] == "service" :
|
||||
result = False #self.__api_request(instance, "/restart")
|
||||
if result :
|
||||
return "Instance " + instance["name"] + " has been restarted."
|
||||
return "Can't restart " + instance["name"]
|
||||
raise Exception(f"Can't find instance with id {_id}")
|
||||
|
||||
def get_instances(self) -> list[Instance]:
|
||||
instances = []
|
||||
# Docker instances (containers or services)
|
||||
if self.__docker is not None:
|
||||
for instance in self.__docker.containers.list(
|
||||
all=True, filters={"label": "bunkerweb.UI"}
|
||||
):
|
||||
env_variables = {
|
||||
x[0]: x[1]
|
||||
for x in [env.split("=") for env in instance.attrs["Config"]["Env"]]
|
||||
}
|
||||
|
||||
apiCaller = ApiCaller()
|
||||
apiCaller._set_apis(
|
||||
[
|
||||
API(
|
||||
f"http://{instance.name}:{env_variables.get('API_HTTP_PORT', '5000')}",
|
||||
env_variables.get("API_SERVER_NAME", "bwapi"),
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
instances.append(
|
||||
Instance(
|
||||
instance.id,
|
||||
instance.name,
|
||||
instance.name,
|
||||
"container",
|
||||
"up" if instance.status == "running" else "down",
|
||||
instance,
|
||||
apiCaller,
|
||||
)
|
||||
)
|
||||
|
||||
instances = sorted(
|
||||
instances,
|
||||
key=lambda x: x.name,
|
||||
)
|
||||
|
||||
# Local instance
|
||||
if os.path.exists("/usr/sbin/nginx"):
|
||||
instances.insert(
|
||||
0,
|
||||
Instance(
|
||||
"local",
|
||||
"local",
|
||||
"127.0.0.1",
|
||||
"local",
|
||||
"up" if os.path.exists("/opt/bunkerweb/tmp/nginx.pid") else "down",
|
||||
),
|
||||
)
|
||||
|
||||
return instances
|
||||
|
||||
def reload_instances(self) -> list[str]:
|
||||
not_reloaded: list[str] = []
|
||||
for instance in self.get_instances():
|
||||
if instance.health is False:
|
||||
not_reloaded.append(instance.name)
|
||||
continue
|
||||
|
||||
if self.reload_instance(None, instance).startswith("Can't reload"):
|
||||
not_reloaded.append(instance.name)
|
||||
|
||||
return not_reloaded
|
||||
|
||||
def reload_instance(self, id: int = None, instance: Instance = None) -> str:
|
||||
if instance is None:
|
||||
instance = self.__instance_from_id(id)
|
||||
|
||||
result = True
|
||||
if instance._type == "local":
|
||||
result = (
|
||||
run(
|
||||
["sudo", "systemctl", "restart", "bunkerweb"], capture_output=True
|
||||
).returncode
|
||||
!= 0
|
||||
)
|
||||
elif instance._type == "container":
|
||||
result = instance.run_jobs()
|
||||
result = result & instance.reload()
|
||||
|
||||
if result:
|
||||
return f"Instance {instance.name} has been reloaded."
|
||||
|
||||
return f"Can't reload {instance.name}"
|
||||
|
||||
def start_instance(self, id) -> str:
|
||||
instance = self.__instance_from_id(id)
|
||||
result = True
|
||||
|
||||
if instance._type == "local":
|
||||
proc = run(
|
||||
["sudo", "/opt/bunkerweb/ui/linux.sh", "start"],
|
||||
capture_output=True,
|
||||
)
|
||||
result = proc.returncode == 0
|
||||
elif instance._type == "container":
|
||||
result = instance.start()
|
||||
|
||||
if result:
|
||||
return f"Instance {instance.name} has been started."
|
||||
|
||||
return f"Can't start {instance.name}"
|
||||
|
||||
def stop_instance(self, id) -> str:
|
||||
instance = self.__instance_from_id(id)
|
||||
result = True
|
||||
|
||||
if instance._type == "local":
|
||||
proc = run(
|
||||
["sudo", "/opt/bunkerweb/ui/linux.sh", "stop"],
|
||||
capture_output=True,
|
||||
)
|
||||
result = proc.returncode == 0
|
||||
elif instance._type == "container":
|
||||
result = instance.stop()
|
||||
|
||||
if result:
|
||||
return f"Instance {instance.name} has been stopped."
|
||||
|
||||
return f"Can't stop {instance.name}"
|
||||
|
||||
def restart_instance(self, id) -> str:
|
||||
instance = self.__instance_from_id(id)
|
||||
result = True
|
||||
|
||||
if instance._type == "local":
|
||||
proc = run(
|
||||
["sudo", "/opt/bunkerweb/ui/linux.sh", "restart"],
|
||||
capture_output=True,
|
||||
)
|
||||
result = proc.returncode == 0
|
||||
elif instance._type == "container":
|
||||
result = instance.restart()
|
||||
|
||||
if result:
|
||||
return f"Instance {instance.name} has been restarted."
|
||||
|
||||
return f"Can't restart {instance.name}"
|
||||
|
||||
Reference in New Issue
Block a user