gonets/SRV/services/ip_service.py
2025-06-09 14:43:25 +05:00

112 lines
No EOL
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from sdbus_async.networkmanager import NetworkManager, NetworkManagerSettings, NetworkConnectionSettings, NetworkDeviceGeneric, ActiveConnection
import asyncio
from sdbus_async.networkmanager.settings import ConnectionProfile
from typing import Dict, Any
import sdbus
from services.arp_service import NetworkScanner
class IPService:
"""
Сервис проверки доступности IP-адреса и применения настроек сети
"""
def __init__(self):
self.arp_scanner = NetworkScanner()
self.bus = sdbus.sd_bus_open_system()
sdbus.set_default_bus(self.bus)
def _reset_bus(self):
""" Перезапускает соединение с системной шиной D-Bus """
new_bus = sdbus.sd_bus_open_system()
sdbus.set_default_bus(new_bus)
if hasattr(self, 'bus') and self.bus is not None:
self.bus = None
self.bus = new_bus
async def check_ip_config(self, args: Dict[str, Any]) -> Dict[str, Any]:
""" Проверяет доступность IP-адреса перед его применением """
self._reset_bus()
clients = self.arp_scanner.scan_network()
new_ip = args["ipv4_updates"]["ipv4.address-data"][0]["address"]
if any(client['ip'] == new_ip for client in clients):
return {"available": False, "message": f"IP address {new_ip} уже занят."}
return {"available": True, "message": "Network profile settings are available for use."}
async def apply_ip_config(self, args: Dict[str, Any]) -> None:
""" Применяет проверенные настройки IP """
self._reset_bus()
nm = NetworkManager(self.bus)
settings = NetworkManagerSettings(self.bus)
connection_paths = await settings.get_connections_by_id(args["connection_id"])
if not connection_paths:
raise ValueError(f"Подключение {args['connection_id']} не найдено")
connection = NetworkConnectionSettings(connection_paths[0], self.bus)
profile = await connection.get_profile()
settings_dict = profile.to_settings_dict()
# Обновляем настройки IPv4
for key_path, value in args["ipv4_updates"].items():
section, *props = key_path.split('.')
current = settings_dict[section]
for prop in props[:-1]:
current = current.setdefault(prop, {})
current[props[-1]] = value
new_profile = ConnectionProfile.from_settings_dict(settings_dict)
await connection.update(new_profile.to_dbus())
print(f"Обновлены настройки для {args['connection_id']}:")
# Проверяем interface-name
interface_name = settings_dict['connection'].get('interface-name')
if not interface_name:
# Ищем устройство, связанное с connection_id через активное соединение
devices = await nm.get_devices()
for device_path in devices:
device = NetworkDeviceGeneric(device_path, self.bus)
active_connection = await device.active_connection
if active_connection != '/':
active_conn = ActiveConnection(active_connection, self.bus)
conn_path = await active_conn.connection # Путь к настройкам соединения
if conn_path != '/':
conn_settings = NetworkConnectionSettings(conn_path, self.bus)
active_profile = await conn_settings.get_profile()
if active_profile.to_settings_dict()['connection']['id'] == args["connection_id"]:
interface_name = await device.interface
settings_dict['connection']['interface-name'] = interface_name
new_profile = ConnectionProfile.from_settings_dict(settings_dict)
await connection.update(new_profile.to_dbus())
print(f"Добавлен interface-name: {interface_name} для {args['connection_id']}")
break
if not interface_name:
# Если не нашли активное соединение, пробуем получить интерфейс из настроек устройства
devices = await nm.get_devices()
for device_path in devices:
device = NetworkDeviceGeneric(device_path, self.bus)
applied_connection = await device.get_applied_connection()
connection_settings = applied_connection[0]
conn_id = connection_settings.get('connection', {}).get('id', ('s', ''))[1]
if conn_id == args["connection_id"]:
interface_name = await device.interface
settings_dict['connection']['interface-name'] = interface_name
new_profile = ConnectionProfile.from_settings_dict(settings_dict)
await connection.update(new_profile.to_dbus())
print(f"Добавлен interface-name: {interface_name} для {args['connection_id']}")
break
if not interface_name:
raise ValueError(f"Не удалось определить interface-name для {args['connection_id']}")
# Переподключаем устройство
devices = await nm.get_devices()
for device_path in devices:
device = NetworkDeviceGeneric(device_path, self.bus)
if await device.interface == interface_name:
await device.disconnect()
print(f"Отключён от {interface_name}")
await nm.activate_connection(connection=connection_paths[0], device=device_path)
print(f"Переподключён к {args['connection_id']}")
return
raise RuntimeError(f"Устройство для интерфейса {interface_name} не найдено")