From 4d516d7c033150460e3cdf05e963636d9d38da8d Mon Sep 17 00:00:00 2001 From: gsd Date: Thu, 7 Dec 2023 18:07:41 +0300 Subject: [PATCH] docker features --- ext/python-docker-client/Dockerfile | 6 + ext/python-docker-client/dockerclient.py | 121 ++++++++++++++++++ ext/python-docker-client/git/Dockerfile | 7 + .../controllers/other/DockerController.java | 11 ++ 4 files changed, 145 insertions(+) create mode 100644 ext/python-docker-client/Dockerfile create mode 100644 ext/python-docker-client/dockerclient.py create mode 100644 ext/python-docker-client/git/Dockerfile diff --git a/ext/python-docker-client/Dockerfile b/ext/python-docker-client/Dockerfile new file mode 100644 index 0000000..8ad7a21 --- /dev/null +++ b/ext/python-docker-client/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.10 +RUN python -m pip install aiodocker aiohttp && mkdir /app +WORKDIR /app +COPY ./ ./ +ENV PYTHONUNBUFFERED 1 +ENTRYPOINT ["python", "dockerclient.py"] \ No newline at end of file diff --git a/ext/python-docker-client/dockerclient.py b/ext/python-docker-client/dockerclient.py new file mode 100644 index 0000000..f9ab74c --- /dev/null +++ b/ext/python-docker-client/dockerclient.py @@ -0,0 +1,121 @@ +import aiodocker +import asyncio +import aiohttp +from time import time +import os, sys, traceback + +class Client: + def __init__(self): + self.endpoint = os.getenv("ENDPOINT","") + self.gateway = os.getenv("GATEWAY", "api/docker") + self.secretkey = os.getenv("SECRET_KEY","") + self.docker_url = os.getenv("DOCKER_URL", "") + ################################################# + self.url = self.endpoint + "/" + self.gateway + self.docker = aiodocker.Docker(self.docker_url) + self.servers = [] + + async def loop(self, timeout = 5): + while 1: + try: + t = [] + for server in self.servers: + t.append(self.update_stats(server)) + await asyncio.gather(*t) + except Exception as e: + print(e) + traceback.print_exc() + except KeyboardInterrupt: + print("Exit") + sys.exit(0) + finally: + await asyncio.sleep(timeout) + + async def request_srvs(self): + try: + async with aiohttp.ClientSession(cookies={"secretkey":self.secretkey}) as session: + async with session.get(self.url, ssl = False) as response: + self.servers = await response.json() + return self.servers + except: + traceback.print_exc() + return [] + + async def update_stats(self, sc): + srv = sc['srv'] + dc = sc['container'] + + try: + stats = await self.request_stats(dc) + except: + stats = None + print(f"Cannot get container stats on: {srv}") + + try: + if stats != None: + await self.send_stats(srv, stats) + else: + await self.down_stats(srv) + except: + print(f"Cannot update information on: {srv}") + traceback.print_exc() + + async def request_stats(self, container_name): + c = await self.docker.containers.get(container_name) + s = await c.stats(stream=False) + s = s[0] + + print(s) + + cpu_delta = s['cpu_stats']['cpu_usage']['total_usage'] - s['precpu_stats']['cpu_usage']['total_usage'] + system_cpu_delta = s['cpu_stats']['system_cpu_usage'] - s['precpu_stats']['system_cpu_usage'] + + used_memory = s['memory_stats']['usage']# - s['memory_stats']['stats']['cache'] + available_memory = s['memory_stats']['limit'] + + b = { + "cpu":{ + "percent": round((cpu_delta / system_cpu_delta) * s['cpu_stats']['online_cpus'] * 100.0, 2) + }, + "mem":{ + "percent":round((used_memory / available_memory) * 100.0, 2), + "usage":round(used_memory, 2), + "limit":round(available_memory, 2) + }, + "net":{ + "input":round(s["networks"]['eth0']['rx_bytes'], 2), + "output":round(s["networks"]['eth0']['tx_bytes'], 2) + }, + "io":{ + "input":round(s["blkio_stats"]['io_service_bytes_recursive'][0]['value'], 2), + "output":round(s["blkio_stats"]['io_service_bytes_recursive'][1]['value'], 2) + }, + "utime":time() + } + + return b + + async def send_stats(self, srv, stats): + async with aiohttp.ClientSession(cookies={"secretkey":self.secretkey}) as session: + async with session.post(self.url + "/" + srv, ssl=False, json=stats) as response: + return await response.text() + + async def down_stats(self, srv): + async with aiohttp.ClientSession(cookies={"secretkey":self.secretkey}) as session: + async with session.delete(self.url + "/" + srv, ssl=False) as response: + return await response.text() + +if __name__ == "__main__": + c = Client() + loop = asyncio.get_event_loop() + + print("Pre setup stage, get servers list...") + loop.run_until_complete(c.request_srvs()) + if c.servers.__len__() == 0: + print("Backent not respond, or server list not setup! Exit after 5 seconds...") + loop.run_until_complete(asyncio.sleep(5)) + sys.exit(1) + else: + print(f"Found {c.servers.__len__()} servers!") + + loop.run_until_complete(c.loop(int(os.getenv("TIMEOUT", "5")))) \ No newline at end of file diff --git a/ext/python-docker-client/git/Dockerfile b/ext/python-docker-client/git/Dockerfile new file mode 100644 index 0000000..52267fc --- /dev/null +++ b/ext/python-docker-client/git/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.10 +RUN python -m pip install aiodocker aiohttp && mkdir /app +RUN cd /tmp && git clone https://git.pblr-nyk.pro/gsd/Facti13.Web.Backend.Java.V2 && cd ./Facti13.Web.Backend.Java.V2/ext/python-docker-client && cp *.* /app && rm -r /tmp/Facti13.Web.Backend.Java.V2 +WORKDIR /app +COPY ./ ./ +ENV PYTHONUNBUFFERED 1 +ENTRYPOINT ["python", "dockerclient.py"] \ No newline at end of file diff --git a/src/main/java/app/controllers/other/DockerController.java b/src/main/java/app/controllers/other/DockerController.java index 6de48d3..5245ce1 100644 --- a/src/main/java/app/controllers/other/DockerController.java +++ b/src/main/java/app/controllers/other/DockerController.java @@ -12,6 +12,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.time.Instant; import java.util.List; import java.util.stream.Collectors; @@ -39,6 +40,16 @@ public class DockerController { return ResponseEntity.ok().build(); } + @DeleteMapping("/{srv}") + @CheckWebAccess(auth_method = AuthMethod.SECRET_KEY) + public ResponseEntity setStats(HttpServletRequest httpServletRequest, @PathVariable String srv) { + if (!stats.getServers().containsKey(srv)) return new ResponseEntity<>(HttpStatus.NOT_FOUND); + DockerStats clear = new DockerStats(); + clear.setUtime(Instant.now().getEpochSecond()); + stats.getServers().get(srv).setDockerStats(clear); + return ResponseEntity.ok().build(); + } + @Data @AllArgsConstructor public class SrvDc {