init
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Cell Manager for Personal Internet Cell
|
||||
Handles overall cell configuration and service orchestration
|
||||
"""
|
||||
|
||||
from network_manager import NetworkManager
|
||||
from wireguard_manager import WireGuardManager
|
||||
from peer_registry import PeerRegistry
|
||||
from email_manager import EmailManager
|
||||
from calendar_manager import CalendarManager
|
||||
from file_manager import FileManager
|
||||
from routing_manager import RoutingManager
|
||||
from vault_manager import VaultManager
|
||||
from container_manager import ContainerManager
|
||||
from datetime import datetime
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any
|
||||
from base_service_manager import BaseServiceManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class CellManager(BaseServiceManager):
|
||||
"""Manages overall cell configuration and service orchestration"""
|
||||
|
||||
def __init__(self, config_path=None, data_dir: str = '/app/data', config_dir: str = '/app/config'):
|
||||
super().__init__('cell', data_dir, config_dir)
|
||||
import os
|
||||
self.config_path = Path(config_path or os.environ.get('CELL_CONFIG_PATH', 'cell_config.json'))
|
||||
|
||||
# Initialize all service managers
|
||||
self.network_manager = NetworkManager(data_dir, config_dir)
|
||||
self.wireguard_manager = WireGuardManager(data_dir, config_dir)
|
||||
self.peer_registry = PeerRegistry()
|
||||
self.email_manager = EmailManager(data_dir, config_dir)
|
||||
self.calendar_manager = CalendarManager(data_dir, config_dir)
|
||||
self.file_manager = FileManager(data_dir, config_dir)
|
||||
self.routing_manager = RoutingManager(data_dir, config_dir)
|
||||
self.vault_manager = VaultManager(config_dir, data_dir)
|
||||
self.container_manager = ContainerManager(data_dir, config_dir)
|
||||
|
||||
self._peers = []
|
||||
self._uptime = 3600
|
||||
|
||||
# Load config from file if exists
|
||||
if self.config_path.exists():
|
||||
with open(self.config_path, 'r') as f:
|
||||
self.config = json.load(f)
|
||||
else:
|
||||
self.cell_name = os.environ.get("CELL_NAME", "personal-internet-cell")
|
||||
self.domain = os.environ.get("DOMAIN", f"{self.cell_name}.cell")
|
||||
self.ip_range = os.environ.get("IP_RANGE", "10.0.0.0/24")
|
||||
self.wireguard_port = int(os.environ.get("WIREGUARD_PORT", 51820))
|
||||
self.dns_port = int(os.environ.get("DNS_PORT", 53))
|
||||
self.dhcp_range = os.environ.get("DHCP_RANGE", "10.0.0.100-10.0.200")
|
||||
self.config = {
|
||||
"cell_name": self.cell_name,
|
||||
"domain": self.domain,
|
||||
"ip_range": self.ip_range,
|
||||
"wireguard_port": self.wireguard_port,
|
||||
"dns_port": self.dns_port,
|
||||
"dhcp_range": self.dhcp_range,
|
||||
"created_at": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
# Always update attributes from config
|
||||
for k, v in self.config.items():
|
||||
setattr(self, k, v)
|
||||
|
||||
def get_status(self) -> Dict[str, Any]:
|
||||
"""Get cell service status"""
|
||||
try:
|
||||
services_status = self.get_services_status()
|
||||
|
||||
# Count healthy services
|
||||
healthy_services = 0
|
||||
total_services = len(services_status)
|
||||
|
||||
for service_name, status in services_status.items():
|
||||
if status.get('running', False):
|
||||
healthy_services += 1
|
||||
|
||||
status = {
|
||||
'running': healthy_services > 0,
|
||||
'status': 'online' if healthy_services > 0 else 'offline',
|
||||
'cell_name': self.config["cell_name"],
|
||||
'domain': self.config["domain"],
|
||||
'ip_range': self.config["ip_range"],
|
||||
'wireguard_port': self.config["wireguard_port"],
|
||||
'dns_port': self.config["dns_port"],
|
||||
'dhcp_range': self.config["dhcp_range"],
|
||||
'uptime': self._uptime,
|
||||
'peers_count': len(self._peers),
|
||||
'healthy_services': healthy_services,
|
||||
'total_services': total_services,
|
||||
'services': services_status,
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
return status
|
||||
except Exception as e:
|
||||
return self.handle_error(e, "get_status")
|
||||
|
||||
def test_connectivity(self) -> Dict[str, Any]:
|
||||
"""Test cell service connectivity"""
|
||||
try:
|
||||
# Test all service managers connectivity
|
||||
network_test = self.network_manager.test_connectivity()
|
||||
wireguard_test = self.wireguard_manager.test_connectivity()
|
||||
email_test = self.email_manager.test_connectivity()
|
||||
calendar_test = self.calendar_manager.test_connectivity()
|
||||
files_test = self.file_manager.test_connectivity()
|
||||
routing_test = self.routing_manager.test_connectivity()
|
||||
vault_test = self.vault_manager.test_connectivity()
|
||||
container_test = self.container_manager.test_connectivity()
|
||||
|
||||
# Calculate overall success
|
||||
all_tests = [
|
||||
network_test, wireguard_test, email_test, calendar_test,
|
||||
files_test, routing_test, vault_test, container_test
|
||||
]
|
||||
|
||||
successful_tests = sum(1 for test in all_tests if test.get('success', False))
|
||||
total_tests = len(all_tests)
|
||||
|
||||
results = {
|
||||
'network': network_test,
|
||||
'wireguard': wireguard_test,
|
||||
'email': email_test,
|
||||
'calendar': calendar_test,
|
||||
'files': files_test,
|
||||
'routing': routing_test,
|
||||
'vault': vault_test,
|
||||
'container': container_test,
|
||||
'success': successful_tests > 0,
|
||||
'successful_tests': successful_tests,
|
||||
'total_tests': total_tests,
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
return results
|
||||
except Exception as e:
|
||||
return self.handle_error(e, "test_connectivity")
|
||||
|
||||
def save_config(self):
|
||||
"""Save cell configuration"""
|
||||
try:
|
||||
with open(self.config_path, 'w') as f:
|
||||
json.dump(self.config, f, indent=2)
|
||||
self.logger.info("Cell configuration saved")
|
||||
return True
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error saving cell configuration: {e}")
|
||||
return False
|
||||
|
||||
def get_config(self) -> Dict[str, Any]:
|
||||
"""Get cell configuration"""
|
||||
return {
|
||||
"cell_name": self.cell_name,
|
||||
"domain": self.domain,
|
||||
"ip_range": self.ip_range,
|
||||
"wireguard_port": self.wireguard_port,
|
||||
"dns_port": self.dns_port,
|
||||
"dhcp_range": self.dhcp_range
|
||||
}
|
||||
|
||||
def update_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Update cell configuration"""
|
||||
try:
|
||||
# Update config attributes from dict
|
||||
for k, v in config.items():
|
||||
if hasattr(self, k):
|
||||
setattr(self, k, v)
|
||||
self.config[k] = v
|
||||
|
||||
# Save updated config
|
||||
self.save_config()
|
||||
|
||||
return {"status": "updated", "message": "Configuration updated successfully"}
|
||||
except Exception as e:
|
||||
return {"status": "error", "message": f"Failed to update configuration: {str(e)}"}
|
||||
|
||||
def get_peers(self) -> List[Dict[str, Any]]:
|
||||
"""Get all peers"""
|
||||
return self._peers
|
||||
|
||||
def add_peer(self, peer: Dict[str, Any]) -> tuple[bool, str]:
|
||||
"""Add a new peer"""
|
||||
try:
|
||||
# Simulate validation: must have name, ip, public_key
|
||||
if not all(k in peer for k in ("name", "ip", "public_key")):
|
||||
return False, "Missing required fields"
|
||||
|
||||
# Prevent duplicate peer names
|
||||
if any(p['name'] == peer['name'] for p in self._peers):
|
||||
return False, "Peer already exists"
|
||||
|
||||
self._peers.append(peer)
|
||||
self.logger.info(f"Added peer: {peer['name']}")
|
||||
return True, "Peer added successfully"
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error adding peer: {e}")
|
||||
return False, f"Error adding peer: {str(e)}"
|
||||
|
||||
def remove_peer(self, name: str) -> tuple[bool, str]:
|
||||
"""Remove a peer"""
|
||||
try:
|
||||
for i, p in enumerate(self._peers):
|
||||
if p['name'] == name:
|
||||
del self._peers[i]
|
||||
self.logger.info(f"Removed peer: {name}")
|
||||
return True, "Peer removed successfully"
|
||||
return False, "Peer not found"
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error removing peer {name}: {e}")
|
||||
return False, f"Error removing peer: {str(e)}"
|
||||
|
||||
def get_services_status(self) -> Dict[str, Any]:
|
||||
"""Get status of all services"""
|
||||
try:
|
||||
return {
|
||||
"network": self.network_manager.get_status(),
|
||||
"wireguard": self.wireguard_manager.get_status(),
|
||||
"email": self.email_manager.get_status(),
|
||||
"calendar": self.calendar_manager.get_status(),
|
||||
"files": self.file_manager.get_status(),
|
||||
"routing": self.routing_manager.get_status(),
|
||||
"vault": self.vault_manager.get_status(),
|
||||
"container": self.container_manager.get_status()
|
||||
}
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error getting services status: {e}")
|
||||
return {}
|
||||
|
||||
def get_uptime(self) -> int:
|
||||
"""Get cell uptime"""
|
||||
return self._uptime
|
||||
|
||||
def restart_all_services(self) -> Dict[str, Any]:
|
||||
"""Restart all services"""
|
||||
try:
|
||||
results = {}
|
||||
|
||||
# Restart each service manager
|
||||
services = {
|
||||
'network': self.network_manager,
|
||||
'wireguard': self.wireguard_manager,
|
||||
'email': self.email_manager,
|
||||
'calendar': self.calendar_manager,
|
||||
'files': self.file_manager,
|
||||
'routing': self.routing_manager,
|
||||
'vault': self.vault_manager,
|
||||
'container': self.container_manager
|
||||
}
|
||||
|
||||
for service_name, service_manager in services.items():
|
||||
try:
|
||||
success = service_manager.restart_service()
|
||||
results[service_name] = {
|
||||
'success': success,
|
||||
'message': f"Service {'restarted' if success else 'failed to restart'}"
|
||||
}
|
||||
except Exception as e:
|
||||
results[service_name] = {
|
||||
'success': False,
|
||||
'message': f"Error restarting service: {str(e)}"
|
||||
}
|
||||
|
||||
return {
|
||||
'success': any(r.get('success', False) for r in results.values()),
|
||||
'results': results,
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
}
|
||||
except Exception as e:
|
||||
return self.handle_error(e, "restart_all_services")
|
||||
|
||||
def get_health_summary(self) -> Dict[str, Any]:
|
||||
"""Get comprehensive health summary"""
|
||||
try:
|
||||
services_status = self.get_services_status()
|
||||
connectivity = self.test_connectivity()
|
||||
|
||||
# Calculate health metrics
|
||||
healthy_services = sum(1 for status in services_status.values() if status.get('running', False))
|
||||
total_services = len(services_status)
|
||||
health_percentage = (healthy_services / total_services * 100) if total_services > 0 else 0
|
||||
|
||||
return {
|
||||
'overall_health': 'healthy' if health_percentage >= 80 else 'degraded' if health_percentage >= 50 else 'unhealthy',
|
||||
'health_percentage': round(health_percentage, 2),
|
||||
'healthy_services': healthy_services,
|
||||
'total_services': total_services,
|
||||
'services_status': services_status,
|
||||
'connectivity': connectivity,
|
||||
'uptime': self._uptime,
|
||||
'peers_count': len(self._peers),
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
}
|
||||
except Exception as e:
|
||||
return self.handle_error(e, "get_health_summary")
|
||||
Reference in New Issue
Block a user