mirror of
https://github.com/blw1138/cross-py-builder.git
synced 2025-12-17 08:38:11 +00:00
Fixed issue with updates after builds and restarting process
This commit is contained in:
@@ -15,6 +15,8 @@ import requests
|
|||||||
from build_agent import build_agent_version
|
from build_agent import build_agent_version
|
||||||
from zeroconf_server import ZeroconfServer
|
from zeroconf_server import ZeroconfServer
|
||||||
|
|
||||||
|
TIMEOUT = 10
|
||||||
|
|
||||||
def find_server_ips():
|
def find_server_ips():
|
||||||
ZeroconfServer.configure("_crosspybuilder._tcp.local.", socket.gethostname(), 9001)
|
ZeroconfServer.configure("_crosspybuilder._tcp.local.", socket.gethostname(), 9001)
|
||||||
hostnames = []
|
hostnames = []
|
||||||
@@ -47,12 +49,13 @@ def get_all_servers_status():
|
|||||||
def get_worker_status(hostname):
|
def get_worker_status(hostname):
|
||||||
"""Fetch worker status from the given hostname."""
|
"""Fetch worker status from the given hostname."""
|
||||||
try:
|
try:
|
||||||
response = requests.get(f"http://{hostname}:9001/status", timeout=5)
|
response = requests.get(f"http://{hostname}:9001/status", timeout=TIMEOUT)
|
||||||
status = response.json()
|
status = response.json()
|
||||||
if status['hostname'] != hostname and status['ip'] != hostname:
|
if status['hostname'] != hostname and status['ip'] != hostname:
|
||||||
status['ip'] = socket.gethostbyname(hostname)
|
status['ip'] = socket.gethostbyname(hostname)
|
||||||
return status
|
return status
|
||||||
except requests.exceptions.RequestException:
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"EXCEPTION: {e}")
|
||||||
return {"hostname": hostname, "status": "offline"}
|
return {"hostname": hostname, "status": "offline"}
|
||||||
|
|
||||||
|
|
||||||
@@ -71,8 +74,7 @@ def zip_project(source_dir, output_zip):
|
|||||||
def send_build_request(zip_file, server_ip, download_after=False):
|
def send_build_request(zip_file, server_ip, download_after=False):
|
||||||
"""Uploads the zip file to the given server."""
|
"""Uploads the zip file to the given server."""
|
||||||
upload_url = f"http://{server_ip}:9001/upload"
|
upload_url = f"http://{server_ip}:9001/upload"
|
||||||
print(f"Submitting build request to URL: {upload_url}")
|
print(f"Submitting build request to URL: {upload_url} - Please wait. This may take a few minutes...")
|
||||||
print("Please wait. This may take a few minutes...")
|
|
||||||
with open(zip_file, 'rb') as f:
|
with open(zip_file, 'rb') as f:
|
||||||
response = requests.post(upload_url, files={"file": f})
|
response = requests.post(upload_url, files={"file": f})
|
||||||
|
|
||||||
@@ -189,7 +191,7 @@ def update_worker(server):
|
|||||||
response_json = response.json()
|
response_json = response.json()
|
||||||
if response_json.get('updated_files') and not response_json.get('error_files'):
|
if response_json.get('updated_files') and not response_json.get('error_files'):
|
||||||
try:
|
try:
|
||||||
requests.get(f"http://{server['ip']}:9001/restart", timeout=2)
|
requests.get(f"http://{server['ip']}:9001/restart", timeout=TIMEOUT)
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
pass
|
pass
|
||||||
return server
|
return server
|
||||||
@@ -223,7 +225,7 @@ def update_build_workers(server_data):
|
|||||||
while unverified_servers and datetime.now() < end_time:
|
while unverified_servers and datetime.now() < end_time:
|
||||||
for server_ip in list(unverified_servers.keys()): # Iterate over a copy to avoid modification issues
|
for server_ip in list(unverified_servers.keys()): # Iterate over a copy to avoid modification issues
|
||||||
try:
|
try:
|
||||||
response = requests.get(f"http://{server_ip}:9001/status", timeout=2)
|
response = requests.get(f"http://{server_ip}:9001/status")
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
server_info = unverified_servers[server_ip] # Get full server details
|
server_info = unverified_servers[server_ip] # Get full server details
|
||||||
agent_version = response.json().get('agent_version')
|
agent_version = response.json().get('agent_version')
|
||||||
@@ -254,7 +256,7 @@ def main():
|
|||||||
parser.add_argument("-restart", type=str, help="Hostname to restart")
|
parser.add_argument("-restart", type=str, help="Hostname to restart")
|
||||||
parser.add_argument("-restart-all", action="store_true", help="Restart all agents")
|
parser.add_argument("-restart-all", action="store_true", help="Restart all agents")
|
||||||
parser.add_argument("-shutdown", type=str, help="Hostname to shutdown")
|
parser.add_argument("-shutdown", type=str, help="Hostname to shutdown")
|
||||||
# parser.add_argument("-worker", type=str, help="Update Agents")
|
parser.add_argument("-shutdown-all", action="store_true", help="Restart all agents")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.status:
|
if args.status:
|
||||||
@@ -267,11 +269,11 @@ def main():
|
|||||||
for server_ip in find_server_ips():
|
for server_ip in find_server_ips():
|
||||||
restart_agent(server_ip)
|
restart_agent(server_ip)
|
||||||
elif args.shutdown:
|
elif args.shutdown:
|
||||||
print(f"Shutting down hostname: {args.shutdown}")
|
shutdown_agent(args.shutdown)
|
||||||
try:
|
elif args.shutdown_all:
|
||||||
requests.get(f"http://{args.shutdown}:9001/shutdown")
|
print("Shutting down all agents...")
|
||||||
except requests.exceptions.ConnectionError:
|
for server_ip in find_server_ips():
|
||||||
pass
|
shutdown_agent(server_ip)
|
||||||
elif args.delete_cache:
|
elif args.delete_cache:
|
||||||
delete_cache(get_all_servers_status())
|
delete_cache(get_all_servers_status())
|
||||||
elif args.path:
|
elif args.path:
|
||||||
@@ -281,12 +283,18 @@ def main():
|
|||||||
else:
|
else:
|
||||||
print("No path given!")
|
print("No path given!")
|
||||||
|
|
||||||
|
def shutdown_agent(hostname):
|
||||||
|
print(f"Shutting down hostname: {hostname}")
|
||||||
|
try:
|
||||||
|
requests.get(f"http://{hostname}:9001/shutdown", timeout=TIMEOUT)
|
||||||
|
except (requests.exceptions.ConnectionError, TimeoutError):
|
||||||
|
pass
|
||||||
|
|
||||||
def restart_agent(hostname):
|
def restart_agent(hostname):
|
||||||
print(f"Restarting agent: {hostname}")
|
print(f"Restarting agent: {hostname}")
|
||||||
try:
|
try:
|
||||||
requests.get(f"http://{hostname}:9001/restart")
|
requests.get(f"http://{hostname}:9001/restart", timeout=TIMEOUT)
|
||||||
except requests.exceptions.ConnectionError:
|
except (requests.exceptions.ConnectionError, TimeoutError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,11 @@ import platform
|
|||||||
from zeroconf_server import ZeroconfServer
|
from zeroconf_server import ZeroconfServer
|
||||||
from version import APP_VERSION, APP_NAME
|
from version import APP_VERSION, APP_NAME
|
||||||
|
|
||||||
build_agent_version = "0.1.23"
|
build_agent_version = "0.1.32"
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
launch_time = datetime.datetime.now()
|
||||||
|
LAUNCH_DIR = os.curdir
|
||||||
SCRIPT_PATH = os.path.basename(__file__)
|
SCRIPT_PATH = os.path.basename(__file__)
|
||||||
LOCAL_DIR = os.path.dirname(__file__)
|
LOCAL_DIR = os.path.dirname(__file__)
|
||||||
BUILD_DIR = "pybuild-data"
|
BUILD_DIR = "pybuild-data"
|
||||||
@@ -69,7 +71,6 @@ def update_files():
|
|||||||
check=True)
|
check=True)
|
||||||
|
|
||||||
print("Update complete")
|
print("Update complete")
|
||||||
|
|
||||||
return jsonify({'updated_files': updated_files, 'error_files': error_files}), 200 if not error_files else 500
|
return jsonify({'updated_files': updated_files, 'error_files': error_files}), 200 if not error_files else 500
|
||||||
|
|
||||||
@app.get("/restart")
|
@app.get("/restart")
|
||||||
@@ -100,6 +101,7 @@ def restart():
|
|||||||
try:
|
try:
|
||||||
return jsonify({"message": "=== Restarting ==="}), 200
|
return jsonify({"message": "=== Restarting ==="}), 200
|
||||||
finally:
|
finally:
|
||||||
|
time.sleep(0.1)
|
||||||
os.kill(os.getpid(), signal.SIGTERM)
|
os.kill(os.getpid(), signal.SIGTERM)
|
||||||
|
|
||||||
@app.get("/shutdown")
|
@app.get("/shutdown")
|
||||||
@@ -109,7 +111,7 @@ def shutdown():
|
|||||||
system_status['status'] = "shutting_down"
|
system_status['status'] = "shutting_down"
|
||||||
return jsonify({"message": "Shutting down"}), 200
|
return jsonify({"message": "Shutting down"}), 200
|
||||||
finally:
|
finally:
|
||||||
time.sleep(1)
|
time.sleep(0.1)
|
||||||
os.kill(os.getpid(), signal.SIGTERM)
|
os.kill(os.getpid(), signal.SIGTERM)
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
@@ -117,7 +119,7 @@ def status_page():
|
|||||||
version = platform.mac_ver()[0] if platform.mac_ver() else platform.version()
|
version = platform.mac_ver()[0] if platform.mac_ver() else platform.version()
|
||||||
hostname = socket.gethostname()
|
hostname = socket.gethostname()
|
||||||
return (f"{APP_NAME} - Build Agent {build_agent_version} - \n"
|
return (f"{APP_NAME} - Build Agent {build_agent_version} - \n"
|
||||||
f"{platform.system()} | {cpu_arch()} | {version} | {hostname} | {ZeroconfServer.get_local_ip()}")
|
f"{system_os()} | {cpu_arch()} | {version} | {hostname} | {ZeroconfServer.get_local_ip()}")
|
||||||
|
|
||||||
@app.get("/status")
|
@app.get("/status")
|
||||||
def status():
|
def status():
|
||||||
@@ -137,9 +139,17 @@ def status():
|
|||||||
size_in_bytes /= 1024
|
size_in_bytes /= 1024
|
||||||
|
|
||||||
hostname = socket.gethostname()
|
hostname = socket.gethostname()
|
||||||
return jsonify({"status": system_status['status'], "agent_version": build_agent_version, "os": platform.system(), "cpu": cpu_arch(),
|
return jsonify({"status": system_status['status'],
|
||||||
"python_version": platform.python_version(), "hostname": hostname, "ip": ZeroconfServer.get_local_ip(),
|
"agent_version": build_agent_version,
|
||||||
"running_job": system_status['running_job'], "job_cache": len(job_cache()), "job_cache_size": format_size(get_directory_size(TMP_DIR))})
|
"os": system_os(),
|
||||||
|
"cpu": cpu_arch(),
|
||||||
|
"python": platform.python_version(),
|
||||||
|
"hostname": hostname,
|
||||||
|
"ip": ZeroconfServer.get_local_ip(),
|
||||||
|
"job_id": system_status['running_job'],
|
||||||
|
"cache_size": format_size(get_directory_size(TMP_DIR)),
|
||||||
|
"uptime": str(datetime.datetime.now() - launch_time)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/upload', methods=['POST'])
|
@app.route('/upload', methods=['POST'])
|
||||||
@@ -220,7 +230,6 @@ def install_and_build(project_path, job_id, start_time):
|
|||||||
# Compile with PyInstaller
|
# Compile with PyInstaller
|
||||||
print(f"\n========== Compiling spec file {index+1} of {len(spec_files)} - {spec_file} ==========")
|
print(f"\n========== Compiling spec file {index+1} of {len(spec_files)} - {spec_file} ==========")
|
||||||
simple_name = os.path.splitext(os.path.basename(spec_file))[0]
|
simple_name = os.path.splitext(os.path.basename(spec_file))[0]
|
||||||
os.chdir(project_path)
|
|
||||||
dist_path = os.path.join(project_path, "dist")
|
dist_path = os.path.join(project_path, "dist")
|
||||||
work_path = os.path.join(project_path, "build")
|
work_path = os.path.join(project_path, "build")
|
||||||
log_file_path = os.path.join(project_path, f"build-{simple_name}.log")
|
log_file_path = os.path.join(project_path, f"build-{simple_name}.log")
|
||||||
@@ -231,12 +240,10 @@ def install_and_build(project_path, job_id, start_time):
|
|||||||
[py_exec, "-m", "PyInstaller", spec_file, "--distpath", dist_path, "--workpath", work_path],
|
[py_exec, "-m", "PyInstaller", spec_file, "--distpath", dist_path, "--workpath", work_path],
|
||||||
text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
for line in process.stdout:
|
for line in process.stdout:
|
||||||
print(line, end="") # Print to console
|
print(line, end="") # Print to console
|
||||||
log_file.write(line) # Save to log file
|
log_file.write(line) # Save to log file
|
||||||
log_file.flush() # Ensure real-time writing
|
log_file.flush() # Ensure real-time writing
|
||||||
|
|
||||||
process.wait() # Wait for the process to complete
|
process.wait() # Wait for the process to complete
|
||||||
print(f"\n========== Compilation of spec file {spec_file} complete ==========\n")
|
print(f"\n========== Compilation of spec file {spec_file} complete ==========\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -256,7 +263,7 @@ def install_and_build(project_path, job_id, start_time):
|
|||||||
"output_folder": dist_path,
|
"output_folder": dist_path,
|
||||||
"duration": str(datetime.datetime.now() - start_time),
|
"duration": str(datetime.datetime.now() - start_time),
|
||||||
"cpu": cpu_arch(),
|
"cpu": cpu_arch(),
|
||||||
"os": platform.system(),
|
"os": system_os(),
|
||||||
"hostname": socket.gethostname()
|
"hostname": socket.gethostname()
|
||||||
}), 200
|
}), 200
|
||||||
|
|
||||||
@@ -273,6 +280,9 @@ def cpu_arch():
|
|||||||
arch = arch.replace(x, y)
|
arch = arch.replace(x, y)
|
||||||
return arch
|
return arch
|
||||||
|
|
||||||
|
def system_os():
|
||||||
|
return platform.system().replace("Darwin", "macOS")
|
||||||
|
|
||||||
@app.route('/download/<job_id>', methods=['GET'])
|
@app.route('/download/<job_id>', methods=['GET'])
|
||||||
def download_binaries(job_id):
|
def download_binaries(job_id):
|
||||||
"""Handles downloading the compiled PyInstaller binaries for a given job."""
|
"""Handles downloading the compiled PyInstaller binaries for a given job."""
|
||||||
@@ -369,13 +379,11 @@ if __name__ == "__main__":
|
|||||||
print("Another instance is running. Waiting until it exits.")
|
print("Another instance is running. Waiting until it exits.")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
os.system('cls' if os.name == 'nt' else 'clear')
|
|
||||||
print(f"===== {APP_NAME} {APP_VERSION} Build Agent (v{build_agent_version}) =====")
|
print(f"===== {APP_NAME} {APP_VERSION} Build Agent (v{build_agent_version}) =====")
|
||||||
ZeroconfServer.configure("_crosspybuilder._tcp.local.", socket.gethostname(), 9001)
|
ZeroconfServer.configure("_crosspybuilder._tcp.local.", socket.gethostname(), 9001)
|
||||||
try:
|
try:
|
||||||
ZeroconfServer.start()
|
ZeroconfServer.start()
|
||||||
app.run(host="0.0.0.0", port=9001, threaded=True)
|
app.run(host="0.0.0.0", port=9001, threaded=True)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
Reference in New Issue
Block a user