Fred808 commited on
Commit
38420d7
·
verified ·
1 Parent(s): 968dfdc

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -127
app.py CHANGED
@@ -1,127 +1,65 @@
1
- from fastapi import FastAPI, HTTPException
2
- import subprocess
3
- import os
4
- import logging
5
-
6
- # Set up logging
7
- logging.basicConfig(level=logging.INFO)
8
- logger = logging.getLogger(__name__)
9
-
10
- app = FastAPI()
11
-
12
- def run_docker_compose(command):
13
- """Run a docker-compose command and return the result"""
14
- try:
15
- result = subprocess.run(
16
- f"docker-compose {command}",
17
- shell=True,
18
- capture_output=True,
19
- text=True
20
- )
21
- if result.returncode != 0:
22
- logger.error(f"Docker compose {command} failed: {result.stderr}")
23
- raise Exception(result.stderr)
24
- return result.stdout
25
- except Exception as e:
26
- logger.error(f"Error running docker-compose {command}: {e}")
27
- raise
28
-
29
- @app.on_event("startup")
30
- async def startup_event():
31
- try:
32
- logger.info("Starting Docker Compose stack...")
33
- # Build and start the containers
34
- run_docker_compose("up --build -d")
35
- logger.info("Docker Compose stack is up")
36
-
37
- # Execute run.sh inside the container
38
- logger.info("Executing run.sh inside the container...")
39
- result = subprocess.run(
40
- "docker-compose exec -T vpn /opt/src/run.sh",
41
- shell=True,
42
- capture_output=True,
43
- text=True
44
- )
45
- if result.returncode == 0:
46
- logger.info("run.sh executed successfully")
47
- else:
48
- logger.error(f"run.sh execution failed: {result.stderr}")
49
-
50
- except Exception as e:
51
- logger.error(f"Startup error: {e}")
52
- raise
53
-
54
- @app.on_event("shutdown")
55
- async def shutdown_event():
56
- try:
57
- logger.info("Stopping Docker Compose stack...")
58
- run_docker_compose("down")
59
- logger.info("Docker Compose stack is down")
60
- except Exception as e:
61
- logger.error(f"Shutdown error: {e}")
62
-
63
- @app.get("/")
64
- async def root():
65
- return {"message": "VPN Server is running"}
66
-
67
- @app.get("/status")
68
- async def status():
69
- try:
70
- result = subprocess.run(
71
- "docker-compose ps --format json",
72
- shell=True,
73
- capture_output=True,
74
- text=True
75
- )
76
- if result.returncode == 0:
77
- return {"status": "running", "details": result.stdout}
78
- return {"status": "not_running", "details": result.stderr}
79
- except Exception as e:
80
- logger.error(f"Status check error: {e}")
81
- raise HTTPException(status_code=500, detail=str(e))
82
-
83
- @app.get("/logs")
84
- async def logs():
85
- try:
86
- return {"logs": run_docker_compose("logs")}
87
- except Exception as e:
88
- raise HTTPException(status_code=500, detail=str(e))
89
-
90
- @app.post("/restart")
91
- async def restart():
92
- try:
93
- run_docker_compose("restart")
94
- return {"message": "Services restarted successfully"}
95
- except Exception as e:
96
- raise HTTPException(status_code=500, detail=str(e))
97
-
98
- @app.get("/vpn-details")
99
- async def vpn_details():
100
- try:
101
- # Get VPN connection details from the container
102
- result = subprocess.run(
103
- "docker-compose exec -T vpn cat /etc/ipsec.d/vpn-gen.env",
104
- shell=True,
105
- capture_output=True,
106
- text=True
107
- )
108
- if result.returncode == 0:
109
- return {"vpn_details": result.stdout}
110
-
111
- # If vpn-gen.env doesn't exist, try getting details from container logs
112
- logs_result = subprocess.run(
113
- "docker-compose logs vpn | grep -A 4 'Connect to your new VPN with these details:'",
114
- shell=True,
115
- capture_output=True,
116
- text=True
117
- )
118
- if logs_result.returncode == 0:
119
- return {"vpn_details": logs_result.stdout}
120
-
121
- return {"error": "Could not retrieve VPN details"}
122
- except Exception as e:
123
- raise HTTPException(status_code=500, detail=str(e))
124
-
125
- if __name__ == "__main__":
126
- import uvicorn
127
- uvicorn.run(app, host="0.0.0.0", port=8000)
 
1
+ from fastapi import FastAPI, HTTPException
2
+ import subprocess
3
+ import os
4
+ import logging
5
+ import threading
6
+
7
+ # Set up logging
8
+ logging.basicConfig(level=logging.INFO)
9
+ logger = logging.getLogger(__name__)
10
+
11
+ app = FastAPI()
12
+
13
+ def run_setup_script():
14
+ """
15
+ Executes the run.sh script with root privileges.
16
+ The script is expected to be at /opt/src/run.sh inside the container.
17
+ """
18
+ script_path = "/opt/src/run.sh"
19
+ logger.info(f"Attempting to execute setup script: {script_path}")
20
+
21
+ # The container is running as root by default, so we don't need 'sudo'.
22
+ # We execute the script directly.
23
+ try:
24
+ # Use subprocess.run to execute the script and wait for it to finish
25
+ # We capture output for logging/debugging.
26
+ result = subprocess.run(
27
+ ["/bin/bash", script_path],
28
+ check=True, # Raise an exception for non-zero exit codes
29
+ stdout=subprocess.PIPE,
30
+ stderr=subprocess.STDOUT,
31
+ text=True
32
+ )
33
+ logger.info("Setup script executed successfully.")
34
+ logger.info(f"Script output:\n{result.stdout}")
35
+ except subprocess.CalledProcessError as e:
36
+ logger.error(f"Setup script failed with exit code {e.returncode}.")
37
+ logger.error(f"Script output:\n{e.stdout}")
38
+ # Depending on the application's requirement, we might want to exit here
39
+ # or just log the error and continue with the web server.
40
+ # For a critical setup script like this VPN one, failure is critical.
41
+ # We will log and let the main thread decide if it should exit.
42
+ # For now, we just log the error.
43
+ except FileNotFoundError:
44
+ logger.error(f"Setup script not found at {script_path}")
45
+ except Exception as e:
46
+ logger.error(f"An unexpected error occurred during script execution: {e}")
47
+
48
+ # Run the setup script in a separate thread or before the uvicorn server starts.
49
+ # Since the setup script is likely long-running and critical, we'll run it
50
+ # synchronously before starting the web server. If the web server is meant to
51
+ # serve status while the script runs, we'd use a thread. Given the context
52
+ # of a VPN setup, the setup must complete first.
53
+
54
+ # We will use a simple function call before uvicorn.run.
55
+ # For a production-ready FastAPI app, this logic should be in a startup event handler,
56
+ # but for a simple script, running it before uvicorn.run is sufficient.
57
+
58
+ if __name__ == "__main__":
59
+ # 1. Run the setup script
60
+ run_setup_script()
61
+
62
+ # 2. Start the web server
63
+ import uvicorn
64
+ logger.info("Starting Uvicorn server...")
65
+ uvicorn.run(app, host="0.0.0.0", port=8000)