Helfer für Interface-Infos, MAC-Normalisierung und Option-Spezifikationen
This commit is contained in:
18
src/option_specs.py
Normal file
18
src/option_specs.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
"""
|
||||||
|
Definitions for supported extended DHCP options in the GUI.
|
||||||
|
Extend this list to add more options; codes must be numeric strings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXTENDED_OPTION_SPECS = [
|
||||||
|
# Managed internally (anzeige, aber nicht editierbar)
|
||||||
|
{"code": "1", "label": "Subnet Mask", "desc": "Automatisch aus IP-Settings", "type": "text", "disabled": True},
|
||||||
|
{"code": "3", "label": "Router/Gateway", "desc": "Automatisch auf Server-IP", "type": "text", "disabled": True},
|
||||||
|
{"code": "6", "label": "DNS-Server", "desc": "Aus IP-Settings (GUI)", "type": "text", "disabled": True},
|
||||||
|
|
||||||
|
# Freie Optionen (aufsteigend)
|
||||||
|
{"code": "15", "label": "DNS-Suffix", "desc": "DNS-Domäne", "type": "text"},
|
||||||
|
{"code": "42", "label": "NTP-Server", "desc": "NTP-Server IPs (kommagetrennt)", "type": "text"},
|
||||||
|
{"code": "51", "label": "Lease Time", "desc": "Lease in Sekunden (mandatory)", "type": "text", "mandatory": True, "default": "3600"},
|
||||||
|
{"code": "66", "label": "TFTP-Server", "desc": "TFTP-Servername oder IP", "type": "text"},
|
||||||
|
{"code": "67", "label": "Bootfile", "desc": "Bootfile-Name (PXE)", "type": "text"},
|
||||||
|
]
|
||||||
28
src/utils.py
28
src/utils.py
@@ -1,8 +1,11 @@
|
|||||||
import socket
|
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import psutil
|
import socket
|
||||||
|
import string
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
|
||||||
def get_network_interfaces():
|
def get_network_interfaces():
|
||||||
"""Return only interfaces that have an IPv4 address to keep choices sane."""
|
"""Return only interfaces that have an IPv4 address to keep choices sane."""
|
||||||
interfaces = []
|
interfaces = []
|
||||||
@@ -21,6 +24,19 @@ def get_iface_ipv4_config(iface: str) -> Tuple[Optional[str], Optional[str]]:
|
|||||||
return a.address, a.netmask
|
return a.address, a.netmask
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
|
def get_iface_hwinfo(iface: str) -> Tuple[Optional[str], Optional[int]]:
|
||||||
|
"""Return (MAC, speed_mbps) where available."""
|
||||||
|
mac = None
|
||||||
|
addrs = psutil.net_if_addrs().get(iface, [])
|
||||||
|
for a in addrs:
|
||||||
|
if getattr(a, "family", None) == getattr(psutil, "AF_LINK", None):
|
||||||
|
mac = a.address
|
||||||
|
break
|
||||||
|
stats = psutil.net_if_stats().get(iface)
|
||||||
|
speed = stats.speed if stats else None
|
||||||
|
return mac, speed
|
||||||
|
|
||||||
def format_ip_address(ip: str) -> str:
|
def format_ip_address(ip: str) -> str:
|
||||||
"""Normalize dotted quad; raises on invalid input."""
|
"""Normalize dotted quad; raises on invalid input."""
|
||||||
ip_obj = ipaddress.ip_address(ip)
|
ip_obj = ipaddress.ip_address(ip)
|
||||||
@@ -31,3 +47,11 @@ def format_ip_address(ip: str) -> str:
|
|||||||
def validate_subnet_mask(mask: str) -> None:
|
def validate_subnet_mask(mask: str) -> None:
|
||||||
"""Accept masks like 255.255.255.0; raise ValueError if invalid."""
|
"""Accept masks like 255.255.255.0; raise ValueError if invalid."""
|
||||||
ipaddress.IPv4Network(f"0.0.0.0/{mask}")
|
ipaddress.IPv4Network(f"0.0.0.0/{mask}")
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_mac(mac: str) -> str:
|
||||||
|
"""Return MAC as AA:BB:CC:DD:EE:FF; raises on invalid input."""
|
||||||
|
cleaned = mac.strip().replace("-", "").replace(":", "").replace(".", "").lower()
|
||||||
|
if len(cleaned) != 12 or any(c not in string.hexdigits for c in cleaned):
|
||||||
|
raise ValueError("Ungültige MAC-Adresse.")
|
||||||
|
return ":".join(cleaned[i:i+2] for i in range(0, 12, 2)).upper()
|
||||||
|
|||||||
Reference in New Issue
Block a user