cvat/tests/perf/perfkit/cluster.py

122 lines
3.4 KiB
Python
Raw Normal View History

2025-09-16 01:19:40 +00:00
# Copyright (C) CVAT.ai Corporation
#
# SPDX-License-Identifier: MIT
import os
import pathlib
import pty
import sys
import time
import requests
from perfkit.config import (
CVAT_SERVER_SERVICE,
DOCKER_COMPOSE_FILE,
DOCKER_COMPOSE_FILE_WITH_CPUSET,
URL_SERVER_ABOUT,
)
from perfkit.console_print import console, exit_with_error, print_error, print_info, print_success
from perfkit.k6_profile import K6Profile
from plumbum import FG, local
WAIT_FOR_CLUSTER = 10
docker = local["docker"]
docker_compose = docker["compose", "-f", DOCKER_COMPOSE_FILE, "-f", DOCKER_COMPOSE_FILE_WITH_CPUSET]
def is_service_running(service_name: str) -> bool:
result = docker_compose[
"ps", "--filter", f"name={service_name}", "--filter", "status=running"
]()
if service_name in result:
return True
return False
def wait_for_server(url: str = URL_SERVER_ABOUT, timeout: int = 180, interval: float = 5.0) -> bool:
print_info("⏳ waiting for server...")
start_time = time.time()
while time.time() - start_time < timeout:
try:
response = requests.get(url, timeout=2)
if response.status_code == 200:
return True
except requests.RequestException:
pass
time.sleep(interval)
return False
def start_cluster(
container_name: str = CVAT_SERVER_SERVICE, compose_file: pathlib.Path = DOCKER_COMPOSE_FILE
) -> None:
if is_service_running(CVAT_SERVER_SERVICE):
print_success("✅ cluster already running")
return
print_info("starting cluster")
docker_compose_up = docker_compose["up", "-d"]
docker_compose_up(cwd="../")
if not wait_for_server():
exit_with_error("Server did not start in time.")
print_info("creating default admin user...")
admin_code = (
"from django.contrib.auth.models import User; "
"User.objects.create_superuser('admin', 'admin@localhost.company', '12qwaszx')"
)
exec_cmd = docker[
"exec",
"-i",
container_name,
"bash",
"-c",
f'echo "{admin_code}" | python3 ~/manage.py shell',
]
exec_cmd()
time.sleep(WAIT_FOR_CLUSTER)
def stop_cluster(compose_file: pathlib.Path = DOCKER_COMPOSE_FILE) -> None:
print_info("stopping cluster")
return docker_compose["down", "-v"]()
def _run_in_pty(cmd: list[str]) -> int:
def read(fd) -> None:
while True:
try:
output = os.read(fd, 1024)
if not output:
break
os.write(sys.stdout.fileno(), output)
except OSError:
break
return pty.spawn(cmd, read)
def run_k6_docker(k6_conf: K6Profile, tty_output: bool = False, silent: bool = False) -> int:
docker_cmd: list[str] = k6_conf.build_run_cmd()
cmd = docker_compose["run", "--rm", "perf-k6"][docker_cmd]
if tty_output:
exit_status = _run_in_pty(cmd.formulate())
code = os.waitstatus_to_exitcode(exit_status)
else:
with cmd.popen() as proc:
if not silent:
for line in proc.stdout:
console.print(line.rstrip().decode())
for line in proc.stderr:
print_error(line.rstrip().decode())
# else:
proc.communicate()
code = proc.returncode
return code
def stop_k6_docker() -> None:
print_info("stopping K6 service")
return docker_compose["kill"]["perf-k6"] & FG