-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathservice_manager.py
More file actions
188 lines (150 loc) · 7.25 KB
/
Copy pathservice_manager.py
File metadata and controls
188 lines (150 loc) · 7.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
Simplified Service Manager for OpenChamp Admin Tool
Orchestrates container management, build operations, and process execution
"""
import subprocess
import os
import sys
import queue
import psutil
from pathlib import Path
from typing import Dict, Optional, Tuple
from config import ConfigManager
from container_manager import ContainerManager
from build_manager import BuildManager
from setup_manager import SetupManager
class ServiceManager:
"""Simplified service manager that delegates to specialized managers"""
def __init__(self, ConfigMagager):
self.config = ConfigManager()
# Initialize specialized managers
self.container_manager = ContainerManager(self.db_settings)
self.build_manager = BuildManager(self.install_dir, self.container_manager)
self.setup_manager = SetupManager(self.install_dir, self.build_manager)
# Process management
self.processes: Dict[str, subprocess.Popen] = {}
self.process_output_queues: Dict[str, queue.Queue] = {}
def update_install_dir(self, new_path: str):
"""Update installation directory across all managers"""
self.config.update_install_dir(new_path)
self.install_dir = Path(new_path)
self.build_manager.update_install_dir(self.install_dir)
self.setup_manager.update_install_dir(self.install_dir)
def update_db_settings(self, settings: Dict[str, str]):
"""Update database settings across managers"""
self.config.update_db_settings(settings)
self.db_settings = self.config.db_settings
self.container_manager.update_db_settings(self.db_settings)
# ======================== Setup & Installation ========================
def first_time_setup(self, progress_queue=None) -> Tuple[bool, str]:
"""Delegate to SetupManager"""
success, message = self.setup_manager.first_time_setup(progress_queue)
if success:
self.config.save()
return success, message
def download_and_extract_godot(self, progress_queue=None) -> Tuple[bool, str]:
"""Delegate to BuildManager"""
return self.build_manager.download_and_extract_godot(progress_queue)
# ======================== Container Management ========================
def get_podman_containers(self):
"""Delegate to ContainerManager"""
return self.container_manager.get_containers()
def get_container_stats(self, container_id: str):
"""Delegate to ContainerManager"""
return self.container_manager.get_container_stats(container_id)
def start_database_container(self) -> Tuple[bool, str]:
"""Delegate to ContainerManager"""
return self.container_manager.start_database_container()
def stop_database_container(self) -> Tuple[bool, str]:
"""Delegate to ContainerManager"""
return self.container_manager.stop_database_container()
# ======================== Matchmaking Server ========================
def start_matchmaking_server(self) -> Tuple[bool, str]:
"""Start the matchmaking server binary"""
try:
server_binary = self.install_dir / "openchampps" / "server"
if sys.platform == "win32":
server_binary = server_binary.with_suffix('.exe')
if not server_binary.exists():
return False, f"Matchmaking server binary not found. Run 'Pull Latest' first."
self.process_output_queues['matchmaking'] = queue.Queue()
self.processes['matchmaking'] = subprocess.Popen(
[str(server_binary)],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
cwd=str(self.install_dir / "openchampps"),
env={
**os.environ,
"DB_HOST": self.db_settings['database_host'],
"DB_PORT": self.db_settings['database_port'],
"DB_USER": self.db_settings['database_user'],
"DB_PASSWORD": self.db_settings['database_password'],
"DB_NAME": self.db_settings['database_name'],
}
)
return True, "Matchmaking server started"
except Exception as e:
return False, str(e)
def read_matchmaking_output(self):
"""Read output from matchmaking process"""
if 'matchmaking' not in self.processes:
return
proc = self.processes['matchmaking']
output_queue = self.process_output_queues.get('matchmaking')
if not output_queue or not proc.stdout:
return
try:
while proc.poll() is None:
line = proc.stdout.readline()
if line:
output_queue.put(('output', line.rstrip()))
remaining = proc.stdout.read()
if remaining:
for line in remaining.split('\n'):
if line.strip():
output_queue.put(('output', line.rstrip()))
output_queue.put(('end', None))
except Exception as e:
output_queue.put(('error', str(e)))
output_queue.put(('end', None))
def stop_matchmaking_server(self) -> Tuple[bool, str]:
"""Stop the matchmaking server"""
try:
if 'matchmaking' in self.processes:
proc = self.processes['matchmaking']
proc.terminate()
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
proc.kill()
del self.processes['matchmaking']
if 'matchmaking' in self.process_output_queues:
del self.process_output_queues['matchmaking']
return True, "Matchmaking server stopped"
return False, "Matchmaking server not running"
except Exception as e:
return False, str(e)
def get_matchmaking_process_info(self) -> Optional[Dict]:
"""Get info about matchmaking process"""
try:
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
try:
if 'matchmaking' in ' '.join(proc.info['cmdline'] or []).lower():
with proc.oneshot():
return {
'pid': proc.pid,
'name': proc.name(),
'cpu_percent': proc.cpu_percent(interval=0.1),
'memory_mb': proc.memory_info().rss / 1024 / 1024,
'status': proc.status()
}
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
return None
except Exception:
return None
# ======================== Build Operations ========================
def pull_latest_versions(self, progress_queue=None) -> Tuple[bool, str]:
"""Delegate to BuildManager"""
return self.build_manager.pull_latest_versions(progress_queue)