|
|
@@ -1023,32 +1023,53 @@ def cluster_node_service():
|
|
|
except Exception as e:
|
|
|
return jsonify({"status": "error", "message": f"Connection failed: {str(e)}"})
|
|
|
|
|
|
-# Στο app.py του MASTER
|
|
|
+# --- GLOBAL CLUSTER SYNC (MASTER ACTION) ---
|
|
|
@app.route('/api/cluster/sync_all', methods=['POST'])
|
|
|
@admin_required
|
|
|
def sync_all_cluster():
|
|
|
conf = fm.read_file(config.LOCAL_CONF)
|
|
|
- # Βρίσκουμε ΟΛΑ τα zone names που είναι μέσα σε εισαγωγικά
|
|
|
import re
|
|
|
zones = re.findall(r'zone\s+"([^"]+)"', conf)
|
|
|
|
|
|
- # Λίστα προς αγνόηση (τα default του BIND)
|
|
|
ignore = ["rpz.blacklist", ".", "localhost", "127.in-addr.arpa", "0.in-addr.arpa", "255.in-addr.arpa"]
|
|
|
valid_zones = [z for z in zones if z not in ignore]
|
|
|
|
|
|
if not valid_zones:
|
|
|
- return jsonify({"status": "error", "message": "No zones found in named.conf.local"})
|
|
|
-
|
|
|
+ return jsonify({"status": "error", "message": "No zones found to sync."})
|
|
|
+
|
|
|
def bulk_sync():
|
|
|
- import time
|
|
|
- for z in valid_zones:
|
|
|
- # Εδώ καλούμε τον cluster manager να στείλει τη ζώνη
|
|
|
- cm.broadcast_to_cluster('add_slave', z)
|
|
|
- time.sleep(0.5)
|
|
|
-
|
|
|
+ import urllib.request, json, ssl, time
|
|
|
+ settings = fm.load_panel_settings()
|
|
|
+ nodes = settings.get('cluster_nodes', [])
|
|
|
+
|
|
|
+ ctx = ssl.create_default_context()
|
|
|
+ ctx.check_hostname = False
|
|
|
+ ctx.verify_mode = ssl.CERT_NONE
|
|
|
+
|
|
|
+ for node in nodes:
|
|
|
+ for z in valid_zones:
|
|
|
+ masters = dns.get_zone_masters_list(z)
|
|
|
+ if not masters:
|
|
|
+ master_ip = settings.get('server_public_ip', '').strip()
|
|
|
+ if master_ip: masters = [master_ip]
|
|
|
+
|
|
|
+ try:
|
|
|
+ url = f"{node['url'].rstrip('/')}/api/v1/cluster/zone"
|
|
|
+ headers = {"X-API-Key": node['api_key'], "Content-Type": "application/json"}
|
|
|
+ payload = {"domain": z, "masters": masters}
|
|
|
+
|
|
|
+ req = urllib.request.Request(url, data=json.dumps(payload).encode('utf-8'), headers=headers, method='POST')
|
|
|
+ urllib.request.urlopen(req, timeout=5, context=ctx)
|
|
|
+ print(f"Cluster Sync OK: {node['name']} -> {z}")
|
|
|
+ except Exception as e:
|
|
|
+ print(f"Cluster Sync FAIL: {node['name']} -> {z} ({e})")
|
|
|
+
|
|
|
+ # ΠΟΛΥ ΣΗΜΑΝΤΙΚΟ: Περιμένουμε μισό δευτερόλεπτο για να προλάβει ο Slave να γράψει το αρχείο!
|
|
|
+ time.sleep(0.5)
|
|
|
+
|
|
|
import threading
|
|
|
threading.Thread(target=bulk_sync, daemon=True).start()
|
|
|
- return jsonify({"status": "success", "message": f"Pushing {len(valid_zones)} zones to nodes..."})
|
|
|
+ return jsonify({"status": "success", "message": f"Sync started! Sending {len(valid_zones)} zones in the background. Please wait ~10 seconds."})
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
# Είναι σημαντικό το threaded=True για να μην κάνει "block" το UI στο self-ping
|