cluster_manager.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import json
  2. import threading
  3. import urllib.request
  4. import ssl
  5. import config
  6. from core.file_manager import load_panel_settings, load_adblock_lists, load_custom_rules
  7. def _get_ssl_context():
  8. ctx = ssl.create_default_context()
  9. ctx.check_hostname = False
  10. ctx.verify_mode = ssl.CERT_NONE
  11. return ctx
  12. def broadcast_to_cluster(action, domain):
  13. def task():
  14. from core import dns_manager as dns
  15. settings = load_panel_settings()
  16. nodes = settings.get('cluster_nodes', [])
  17. masters = dns.get_zone_masters_list(domain)
  18. if not masters:
  19. master_ip = settings.get('server_public_ip', '').strip()
  20. if master_ip: masters = [master_ip]
  21. ctx = _get_ssl_context()
  22. for node in nodes:
  23. try:
  24. url = f"{node['url'].rstrip('/')}/api/v1/cluster/zone"
  25. headers = {"X-API-Key": node['api_key'], "Content-Type": "application/json"}
  26. payload = {"domain": domain, "masters": masters}
  27. if action == 'add_slave':
  28. req = urllib.request.Request(url, data=json.dumps(payload).encode('utf-8'), headers=headers, method='POST')
  29. elif action == 'delete_zone':
  30. req = urllib.request.Request(f"{url}/{domain}", headers=headers, method='DELETE')
  31. urllib.request.urlopen(req, timeout=10, context=ctx)
  32. print(f"Cluster Sync OK: {node['name']} ({action} {domain})")
  33. except Exception as e:
  34. print(f"Cluster Sync FAIL: {node['name']} -> {e}")
  35. threading.Thread(target=task, daemon=True).start()
  36. def broadcast_adblock_to_cluster(action):
  37. def task():
  38. s = load_panel_settings()
  39. lists = load_adblock_lists()
  40. rules = load_custom_rules()
  41. count = s.get('adblock_domains_count', 0)
  42. update_time = s.get('adblock_last_update', 'Never')
  43. ctx = _get_ssl_context()
  44. for node in s.get('cluster_nodes', []):
  45. try:
  46. url = f"{node['url'].rstrip('/')}/api/v1/cluster/adblock"
  47. headers = {"X-API-Key": node['api_key'], "Content-Type": "application/json"}
  48. payload = {
  49. "action": action,
  50. "lists": lists,
  51. "rules": rules,
  52. "count": count,
  53. "time": update_time
  54. }
  55. req = urllib.request.Request(url, data=json.dumps(payload).encode(), headers=headers, method='POST')
  56. urllib.request.urlopen(req, timeout=10, context=ctx)
  57. print(f"Cluster AdBlock Sync OK: {node['name']} ({action})")
  58. except Exception as e:
  59. print(f"Cluster AdBlock Sync FAIL: {node['name']} -> {e}")
  60. threading.Thread(target=task, daemon=True).start()
  61. def broadcast_user_to_cluster(action, username, user_data=None, old_username=None):
  62. def task():
  63. settings = load_panel_settings()
  64. nodes = settings.get('cluster_nodes', [])
  65. ctx = _get_ssl_context()
  66. for node in nodes:
  67. try:
  68. url = f"{node['url'].rstrip('/')}/api/v1/cluster/user"
  69. headers = {"X-API-Key": node['api_key'], "Content-Type": "application/json"}
  70. if action == 'save':
  71. payload = {"username": username, "user_data": user_data, "old_username": old_username}
  72. req = urllib.request.Request(url, data=json.dumps(payload).encode(), headers=headers, method='POST')
  73. elif action == 'delete':
  74. req = urllib.request.Request(f"{url}/{username}", headers=headers, method='DELETE')
  75. urllib.request.urlopen(req, timeout=5, context=ctx)
  76. print(f"Cluster Sync OK: {node['name']} (User {action} -> {username})")
  77. except Exception as e:
  78. print(f"Cluster Sync FAIL: {node['name']} -> User {username} ({e})")
  79. threading.Thread(target=task, daemon=True).start()
  80. def broadcast_templates_to_cluster(templates_dict):
  81. def task():
  82. settings = load_panel_settings()
  83. nodes = settings.get('cluster_nodes', [])
  84. ctx = _get_ssl_context()
  85. for node in nodes:
  86. try:
  87. url = f"{node['url'].rstrip('/')}/api/v1/cluster/templates"
  88. headers = {"X-API-Key": node['api_key'], "Content-Type": "application/json"}
  89. req = urllib.request.Request(url, data=json.dumps(templates_dict).encode(), headers=headers, method='POST')
  90. urllib.request.urlopen(req, timeout=5, context=ctx)
  91. print(f"Cluster Sync OK: {node['name']} (Templates updated)")
  92. except Exception as e:
  93. print(f"Cluster Sync FAIL: {node['name']} -> Templates ({e})")
  94. threading.Thread(target=task, daemon=True).start()