This commit is contained in:
2025-09-07 23:33:55 +02:00
parent d918f1e497
commit fbacfde9f2
33 changed files with 2626 additions and 1236 deletions

View File

@@ -2,7 +2,7 @@ import yaml
from pathlib import Path
from typing import List, Dict, Any
from models import (
Customer, CustomerService, Location, Host, Service,
Customer, CustomerService, Location, Host, Service, NetworkSegment, HostIP, PortForwarding,
ServiceType, HostType, VPNType
)
@@ -73,11 +73,42 @@ def parse_host(host_data: Dict[str, Any]) -> Host:
)
services.append(service)
# Parse IP addresses - handle both new HostIP format and legacy formats
ip_addresses = []
if 'ip_addresses' in host_data:
for ip_data in host_data['ip_addresses']:
if isinstance(ip_data, dict):
# New HostIP format: {ip_address: "192.168.1.10", network_segment: "LAN", is_primary: true}
host_ip = HostIP(
ip_address=ip_data['ip_address'],
network_segment=ip_data.get(
'network_segment', 'LAN'), # Default segment
is_primary=ip_data.get('is_primary', False)
)
ip_addresses.append(host_ip)
else:
# Legacy format: simple string list
host_ip = HostIP(
ip_address=ip_data,
network_segment='LAN', # Default segment for legacy format
is_primary=len(ip_addresses) == 0 # First IP is primary
)
ip_addresses.append(host_ip)
elif 'ip_address' in host_data:
# Very old format: single IP string
host_ip = HostIP(
ip_address=host_data['ip_address'],
network_segment='LAN',
is_primary=True
)
ip_addresses.append(host_ip)
# Create host
host = Host(
name=host_data['name'],
ip_address=host_data['ip_address'],
ip_addresses=ip_addresses,
host_type=parse_host_type(host_data['host_type']),
icon=host_data.get('icon'), # Custom icon name
description=host_data.get('description', ''),
services=services
)
@@ -93,6 +124,34 @@ def parse_host(host_data: Dict[str, Any]) -> Host:
def parse_location(location_data: Dict[str, Any]) -> Location:
"""Parse a location from YAML data."""
# Parse network segments
network_segments = []
if 'network_segments' in location_data:
for segment_data in location_data['network_segments']:
segment = NetworkSegment(
name=segment_data['name'],
cidr=segment_data['cidr'],
vlan_id=segment_data.get('vlan_id'),
zone=segment_data.get('zone', 'general'),
gateway=segment_data.get('gateway'),
description=segment_data.get('description', '')
)
network_segments.append(segment)
# Parse port forwardings
port_forwardings = []
if 'port_forwardings' in location_data:
for pf_data in location_data['port_forwardings']:
port_forward = PortForwarding(
external_port=pf_data['external_port'],
internal_ip=pf_data['internal_ip'],
internal_port=pf_data['internal_port'],
protocol=pf_data.get('protocol', 'tcp'),
description=pf_data.get('description', ''),
enabled=pf_data.get('enabled', True)
)
port_forwardings.append(port_forward)
# Parse hosts
hosts = []
if 'hosts' in location_data:
@@ -108,6 +167,10 @@ def parse_location(location_data: Dict[str, Any]) -> Location:
active=False, # Runtime state - always starts inactive
vpn_config=location_data.get('vpn_config', ''),
hosts=hosts,
network_segments=network_segments,
networks=location_data.get('networks', []), # Legacy support
external_addresses=location_data.get('external_addresses', []),
port_forwardings=port_forwardings,
vpn_credentials=location_data.get('vpn_credentials'),
nmcli_connection_name=location_data.get('nmcli_connection_name'),
auto_import=location_data.get('auto_import', True)
@@ -204,20 +267,64 @@ def save_customer(customer: Customer, filename: str = None) -> None:
# Convert locations
for location in customer.locations:
# Convert network segments
network_segments = []
for segment in location.network_segments:
segment_data = {
'name': segment.name,
'cidr': segment.cidr,
'zone': segment.zone,
'description': segment.description
}
if segment.vlan_id is not None:
segment_data['vlan_id'] = segment.vlan_id
if segment.gateway is not None:
segment_data['gateway'] = segment.gateway
network_segments.append(segment_data)
# Convert port forwardings
port_forwardings = []
for pf in location.port_forwardings:
pf_data = {
'external_port': pf.external_port,
'internal_ip': pf.internal_ip,
'internal_port': pf.internal_port,
'protocol': pf.protocol,
'enabled': pf.enabled
}
if pf.description:
pf_data['description'] = pf.description
port_forwardings.append(pf_data)
location_data = {
'name': location.name,
'vpn_type': location.vpn_type.value,
'vpn_config': location.vpn_config,
'active': location.active,
'connected': location.connected,
'network_segments': network_segments,
'external_addresses': location.external_addresses,
'port_forwardings': port_forwardings,
'hosts': []
}
# Add legacy networks if they exist
if location.networks:
location_data['networks'] = location.networks
# Convert hosts
def convert_host(host):
# Convert HostIP objects back to dictionaries
ip_addresses = []
for host_ip in host.ip_addresses:
ip_dict = {
'ip_address': host_ip.ip_address,
'network_segment': host_ip.network_segment,
'is_primary': host_ip.is_primary
}
ip_addresses.append(ip_dict)
host_data = {
'name': host.name,
'ip_address': host.ip_address,
'ip_addresses': ip_addresses,
'host_type': host.host_type.value,
'description': host.description,
'services': [
@@ -230,6 +337,10 @@ def save_customer(customer: Customer, filename: str = None) -> None:
]
}
# Add icon if specified
if host.icon:
host_data['icon'] = host.icon
if host.sub_hosts:
host_data['sub_hosts'] = [convert_host(
subhost) for subhost in host.sub_hosts]
@@ -267,12 +378,22 @@ def get_demo_customers() -> List[Customer]:
vpn_type=VPNType.OPENVPN,
connected=False,
active=True,
vpn_config="/etc/openvpn/demo.ovpn"
vpn_config="demo.ovpn" # File in ~/.vpntray/vpn/
)
# Create a demo network segment
demo_segment = NetworkSegment(
name="LAN",
cidr="10.0.0.0/24",
gateway="10.0.0.1",
zone="production",
description="Demo network"
)
demo_host = Host(
name="DEMO-01",
ip_address="10.0.0.1",
ip_addresses=[HostIP(ip_address="10.0.0.1",
network_segment="LAN", is_primary=True)],
host_type=HostType.LINUX,
description="Demo server",
services=[
@@ -282,6 +403,7 @@ def get_demo_customers() -> List[Customer]:
)
demo_location.hosts = [demo_host]
demo_location.network_segments = [demo_segment]
demo_customer.locations = [demo_location]
return [demo_customer]
@@ -317,13 +439,24 @@ services:
locations:
- name: Main Office
vpn_type: WireGuard
vpn_config: /etc/wireguard/simple.conf
active: false
connected: false
vpn_config: simple.conf # File in ~/.vpntray/vpn/
network_segments:
- name: LAN
cidr: 192.168.1.0/24
gateway: 192.168.1.1
zone: production
description: Main office network
external_addresses:
- simple.vpn.example.com
hosts:
- name: SERVER-01
ip_address: 192.168.1.10
ip_addresses:
- ip_address: 192.168.1.10
network_segment: LAN
is_primary: true
host_type: Linux
description: Main server
services: