-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun.py
More file actions
executable file
·244 lines (204 loc) · 7.62 KB
/
run.py
File metadata and controls
executable file
·244 lines (204 loc) · 7.62 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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/usr/bin/env python3
"""
Space Entropy Generator - Startup Script
Starts both backend (Docker) and frontend (npm) services
"""
import subprocess
import sys
import time
import signal
import os
from pathlib import Path
# Color codes for terminal output
GREEN = '\033[92m'
BLUE = '\033[94m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
RESET = '\033[0m'
# Global process handlers
processes = []
def print_header():
"""Print startup banner"""
print(f"\n{BOLD}{BLUE}{'='*60}{RESET}")
print(f"{BOLD}{GREEN}🌌 Space Image Based Entropy Generator{RESET}")
print(f"{BOLD}{BLUE} True Randomness as a Service{RESET}")
print(f"{BOLD}{BLUE}{'='*60}{RESET}\n")
def print_status(message, status="info"):
"""Print colored status message"""
colors = {
"info": BLUE,
"success": GREEN,
"warning": YELLOW,
"error": RED
}
color = colors.get(status, BLUE)
symbols = {
"info": "ℹ",
"success": "✓",
"warning": "⚠",
"error": "✗"
}
symbol = symbols.get(status, "•")
print(f"{color}{symbol} {message}{RESET}")
def cleanup(signum=None, frame=None):
"""Cleanup function to stop all processes"""
print(f"\n{YELLOW}🛑 Shutting down services...{RESET}")
# Stop frontend
for proc in processes:
try:
proc.terminate()
proc.wait(timeout=5)
print_status("Frontend stopped", "success")
except:
try:
proc.kill()
except:
pass
# Stop Docker containers
print_status("Stopping Docker containers...", "info")
subprocess.run(["docker-compose", "down"], capture_output=True)
print_status("Docker containers stopped", "success")
print(f"\n{GREEN}✓ All services stopped successfully{RESET}\n")
sys.exit(0)
def check_docker():
"""Check if Docker is available"""
try:
subprocess.run(["docker", "--version"], capture_output=True, check=True)
return True
except:
return False
def check_npm():
"""Check if npm is available"""
try:
subprocess.run(["npm", "--version"], capture_output=True, check=True)
return True
except:
return False
def start_backend():
"""Start backend services with Docker Compose"""
print_status("Starting backend services (Redis + FastAPI)...", "info")
try:
# Build and start containers
subprocess.run(["docker-compose", "up", "-d", "--build"], check=True)
print_status("Backend containers started", "success")
# Wait for backend to be healthy
print_status("Waiting for backend to be healthy...", "info")
max_retries = 30
for i in range(max_retries):
try:
result = subprocess.run(
["curl", "-s", "http://localhost:8000/api/v1/health"],
capture_output=True,
timeout=2
)
if result.returncode == 0:
print_status("Backend is healthy", "success")
return True
except:
pass
time.sleep(2)
if (i + 1) % 5 == 0:
print_status(f"Still waiting... ({i + 1}/{max_retries})", "warning")
print_status("Backend health check timeout (but may still be starting)", "warning")
return True
except subprocess.CalledProcessError as e:
print_status(f"Failed to start backend: {e}", "error")
return False
def start_frontend():
"""Start frontend development server"""
print_status("Starting frontend (React + Vite)...", "info")
# Get frontend directory
frontend_dir = Path(__file__).parent / "website" / "solar-entropy-api-main" / "solar-entropy-api-main"
if not frontend_dir.exists():
print_status(f"Frontend directory not found: {frontend_dir}", "error")
return None
try:
# Check if node_modules exists, if not run npm install
node_modules = frontend_dir / "node_modules"
if not node_modules.exists():
print_status("Installing frontend dependencies (this may take a minute)...", "info")
subprocess.run(["npm", "install"], cwd=frontend_dir, check=True)
print_status("Dependencies installed", "success")
# Start dev server
print_status("Launching Vite dev server...", "info")
proc = subprocess.Popen(
["npm", "run", "dev"],
cwd=frontend_dir,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
bufsize=1
)
# Wait for Vite to start
time.sleep(3)
if proc.poll() is None:
print_status("Frontend server started", "success")
return proc
else:
print_status("Frontend failed to start", "error")
return None
except Exception as e:
print_status(f"Failed to start frontend: {e}", "error")
return None
def print_summary():
"""Print summary of running services"""
print(f"\n{BOLD}{GREEN}{'='*60}{RESET}")
print(f"{BOLD}{GREEN}🚀 All services are running!{RESET}")
print(f"{BOLD}{GREEN}{'='*60}{RESET}\n")
print(f"{BOLD}Service URLs:{RESET}")
print(f" {BLUE}Frontend (Web UI):{RESET} http://localhost:8080")
print(f" {BLUE}Backend API:{RESET} http://localhost:8000")
print(f" {BLUE}API Documentation:{RESET} http://localhost:8000/docs")
print(f" {BLUE}Health Check:{RESET} http://localhost:8000/api/v1/health")
print(f"\n{BOLD}Quick Commands:{RESET}")
print(f" {YELLOW}Get random bytes:{RESET} curl http://localhost:8000/api/v1/random/256")
print(f" {YELLOW}Check pool stats:{RESET} curl http://localhost:8000/api/v1/stats")
print(f" {YELLOW}View backend logs:{RESET} docker logs -f space_entropy_app")
print(f"\n{BOLD}{RED}Press CTRL+C to stop all services{RESET}\n")
def main():
"""Main function"""
# Setup signal handlers
signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)
# Print header
print_header()
# Check prerequisites
print_status("Checking prerequisites...", "info")
if not check_docker():
print_status("Docker not found. Please install Docker first.", "error")
sys.exit(1)
if not check_npm():
print_status("npm not found. Please install Node.js and npm first.", "error")
sys.exit(1)
print_status("All prerequisites satisfied", "success")
# Start backend
print(f"\n{BOLD}Step 1: Starting Backend{RESET}")
if not start_backend():
print_status("Failed to start backend. Exiting.", "error")
sys.exit(1)
# Start frontend
print(f"\n{BOLD}Step 2: Starting Frontend{RESET}")
frontend_proc = start_frontend()
if frontend_proc is None:
print_status("Failed to start frontend. Stopping backend...", "error")
subprocess.run(["docker-compose", "down"], capture_output=True)
sys.exit(1)
processes.append(frontend_proc)
# Print summary
time.sleep(2)
print_summary()
# Keep running and monitor processes
try:
while True:
# Check if frontend process is still running
if frontend_proc.poll() is not None:
print_status("Frontend process stopped unexpectedly", "error")
break
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
cleanup()
if __name__ == "__main__":
main()