Pep8
This commit is contained in:
parent
06a5a758a3
commit
58fa7d1ee6
19 changed files with 567 additions and 377 deletions
|
|
@ -20,12 +20,13 @@ from scapy.layers.l2 import ARP, Ether
|
|||
from scapy.sendrecv import srp, sr1
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NetworkScanner:
|
||||
|
||||
def __init__(self, interface: str):
|
||||
self.interface = interface
|
||||
conf.iface = interface
|
||||
|
|
@ -35,14 +36,19 @@ class NetworkScanner:
|
|||
arp = ARP(pdst=subnet)
|
||||
ether = Ether(dst="ff:ff:ff:ff:ff:ff")
|
||||
packet = ether / arp
|
||||
result = srp(packet, timeout=2, verbose=False, iface=self.interface)[0]
|
||||
return [(received.psrc, received.hwsrc) for sent, received in result]
|
||||
result = srp(packet,
|
||||
timeout=2,
|
||||
verbose=False,
|
||||
iface=self.interface)[0]
|
||||
return [(received.psrc, received.hwsrc)
|
||||
for sent, received in result]
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка ARP-сканирования подсети {subnet}: {str(e)}")
|
||||
return []
|
||||
|
||||
|
||||
class PortScanner:
|
||||
|
||||
def __init__(self, interface: str):
|
||||
self.interface = interface
|
||||
|
||||
|
|
@ -61,7 +67,8 @@ class PortScanner:
|
|||
return port_config.get_port_name(port)
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.debug(f"Ошибка проверки порта {port} для IP {ip}: {str(e)}")
|
||||
logger.debug(
|
||||
f"Ошибка проверки порта {port} для IP {ip}: {str(e)}")
|
||||
return None
|
||||
|
||||
try:
|
||||
|
|
@ -72,11 +79,13 @@ class PortScanner:
|
|||
logger.debug(f"Открытые порты для IP {ip}: {open_ports}")
|
||||
return open_ports
|
||||
except Exception as e:
|
||||
logger.warning(f"Ошибка при сканировании портов для IP {ip}: {str(e)}")
|
||||
logger.warning(
|
||||
f"Ошибка при сканировании портов для IP {ip}: {str(e)}")
|
||||
return []
|
||||
|
||||
|
||||
class DeviceInfoCollector:
|
||||
|
||||
def __init__(self):
|
||||
self.mac_lookup = MacLookup()
|
||||
|
||||
|
|
@ -86,8 +95,7 @@ class DeviceInfoCollector:
|
|||
return self.mac_lookup.lookup(mac)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Не удалось определить производителя для MAC {mac}: {str(e)}"
|
||||
)
|
||||
f"Не удалось определить производителя для MAC {mac}: {str(e)}")
|
||||
return "Unknown"
|
||||
|
||||
def get_hostname(self, ip: str) -> Optional[str]:
|
||||
|
|
@ -98,6 +106,7 @@ class DeviceInfoCollector:
|
|||
|
||||
|
||||
class DeviceStorage:
|
||||
|
||||
def __init__(self, storage_path: str = "storage/devices/devices.json"):
|
||||
self.storage_file = Path(storage_path)
|
||||
self.storage_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
|
@ -119,7 +128,8 @@ class DeviceStorage:
|
|||
logger.error(f"Ошибка при загрузке устройств: {str(e)}")
|
||||
return {}
|
||||
|
||||
def _clean_old_devices(self, devices: Dict[str, Device]) -> Dict[str, Device]:
|
||||
def _clean_old_devices(self, devices: Dict[str,
|
||||
Device]) -> Dict[str, Device]:
|
||||
now = datetime.now(ZoneInfo("UTC"))
|
||||
filtered = {}
|
||||
for mac, device in devices.items():
|
||||
|
|
@ -129,9 +139,11 @@ class DeviceStorage:
|
|||
if now - last_seen <= self.offline_timeout:
|
||||
filtered[mac] = device
|
||||
else:
|
||||
logger.info(f"Удалено устройство {mac} (offline > 7 дней)")
|
||||
logger.info(
|
||||
f"Удалено устройство {mac} (offline > 7 дней)")
|
||||
except ValueError:
|
||||
logger.warning(f"Неверный формат last_seen для устройства {mac}")
|
||||
logger.warning(
|
||||
f"Неверный формат last_seen для устройства {mac}")
|
||||
else:
|
||||
filtered[mac] = device
|
||||
return filtered
|
||||
|
|
@ -141,12 +153,14 @@ class DeviceStorage:
|
|||
data = SubnetScanResult(devices=devices).model_dump()
|
||||
with open(self.storage_file, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
logger.info(f"Сохранено {len(devices)} устройств в {self.storage_file}")
|
||||
logger.info(
|
||||
f"Сохранено {len(devices)} устройств в {self.storage_file}")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при сохранении устройств: {str(e)}")
|
||||
|
||||
|
||||
class SubnetService:
|
||||
|
||||
def __init__(self):
|
||||
self.interface = self._get_default_interface()
|
||||
self.network_scanner = NetworkScanner(self.interface)
|
||||
|
|
@ -157,7 +171,8 @@ class SubnetService:
|
|||
def _get_default_interface(self) -> str:
|
||||
try:
|
||||
gateways = netifaces.gateways()
|
||||
default_gateway = gateways.get("default", {}).get(netifaces.AF_INET)
|
||||
default_gateway = gateways.get("default",
|
||||
{}).get(netifaces.AF_INET)
|
||||
if default_gateway:
|
||||
return default_gateway[1]
|
||||
interfaces = netifaces.interfaces()
|
||||
|
|
@ -169,7 +184,9 @@ class SubnetService:
|
|||
logger.warning(f"Не удалось определить интерфейс: {str(e)}")
|
||||
return "eth0"
|
||||
|
||||
def scan_subnet(self, subnet: str, ports: List[int] = None) -> SubnetScanResult:
|
||||
def scan_subnet(self,
|
||||
subnet: str,
|
||||
ports: List[int] = None) -> SubnetScanResult:
|
||||
start_time = time.time()
|
||||
devices = []
|
||||
now = datetime.now(ZoneInfo("UTC")).isoformat()
|
||||
|
|
@ -220,7 +237,8 @@ class SubnetService:
|
|||
)
|
||||
|
||||
with ThreadPoolExecutor(max_workers=10) as executor:
|
||||
device_results = executor.map(process_device, discovered_devices)
|
||||
device_results = executor.map(process_device,
|
||||
discovered_devices)
|
||||
devices.extend([d for d in device_results if d is not None])
|
||||
|
||||
active_macs = {d.mac for d in devices if d.mac}
|
||||
|
|
@ -275,10 +293,12 @@ class SubnetService:
|
|||
last_seen=now,
|
||||
note=None,
|
||||
)
|
||||
logger.warning(f"Локальное устройство не найдено в подсети {subnet}")
|
||||
logger.warning(
|
||||
f"Локальное устройство не найдено в подсети {subnet}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.warning(f"Не удалось получить локальное устройство: {str(e)}")
|
||||
logger.warning(
|
||||
f"Не удалось получить локальное устройство: {str(e)}")
|
||||
return None
|
||||
|
||||
def add_note(self, mac: str, note: str) -> Tuple[bool, Optional[str]]:
|
||||
|
|
@ -302,14 +322,17 @@ class SubnetService:
|
|||
logger.warning(f"Устройство с MAC {mac} не найдено")
|
||||
return False, f"Устройство с MAC {mac} не найдено"
|
||||
if saved_devices[mac].note is not None:
|
||||
logger.error(f"Заметка для устройства с MAC {mac} уже существует")
|
||||
logger.error(
|
||||
f"Заметка для устройства с MAC {mac} уже существует")
|
||||
return False, f"Заметка для устройства с MAC {mac} уже существует"
|
||||
saved_devices[mac].note = note
|
||||
self.storage.save_devices(list(saved_devices.values()))
|
||||
logger.info(f"Добавлена заметка '{note}' для устройства с MAC {mac}")
|
||||
logger.info(
|
||||
f"Добавлена заметка '{note}' для устройства с MAC {mac}")
|
||||
return True, None
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при добавлении заметки для MAC {mac}: {str(e)}")
|
||||
logger.error(
|
||||
f"Ошибка при добавлении заметки для MAC {mac}: {str(e)}")
|
||||
return False, f"Внутренняя ошибка сервера: {str(e)}"
|
||||
|
||||
def update_note(self, mac: str, note: str) -> Tuple[bool, Optional[str]]:
|
||||
|
|
@ -333,14 +356,17 @@ class SubnetService:
|
|||
logger.warning(f"Устройство с MAC {mac} не найдено")
|
||||
return False, f"Устройство с MAC {mac} не найдено"
|
||||
if saved_devices[mac].note is None:
|
||||
logger.error(f"Заметка для устройства с MAC {mac} не существует")
|
||||
logger.error(
|
||||
f"Заметка для устройства с MAC {mac} не существует")
|
||||
return False, f"Заметка для устройства с MAC {mac} не существует"
|
||||
saved_devices[mac].note = note
|
||||
self.storage.save_devices(list(saved_devices.values()))
|
||||
logger.info(f"Обновлена заметка '{note}' для устройства с MAC {mac}")
|
||||
logger.info(
|
||||
f"Обновлена заметка '{note}' для устройства с MAC {mac}")
|
||||
return True, None
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обновлении заметки для MAC {mac}: {str(e)}")
|
||||
logger.error(
|
||||
f"Ошибка при обновлении заметки для MAC {mac}: {str(e)}")
|
||||
return False, f"Внутренняя ошибка сервера: {str(e)}"
|
||||
|
||||
def delete_note(self, mac: str) -> Tuple[bool, Optional[str]]:
|
||||
|
|
@ -363,12 +389,14 @@ class SubnetService:
|
|||
logger.warning(f"Устройство с MAC {mac} не найдено")
|
||||
return False, f"Устройство с MAC {mac} не найдено"
|
||||
if saved_devices[mac].note is None:
|
||||
logger.error(f"Заметка для устройства с MAC {mac} не существует")
|
||||
logger.error(
|
||||
f"Заметка для устройства с MAC {mac} не существует")
|
||||
return False, f"Заметка для устройства с MAC {mac} не существует"
|
||||
saved_devices[mac].note = None
|
||||
self.storage.save_devices(list(saved_devices.values()))
|
||||
logger.info(f"Удалена заметка для устройства с MAC {mac}")
|
||||
return True, None
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при удалении заметки для MAC {mac}: {str(e)}")
|
||||
logger.error(
|
||||
f"Ошибка при удалении заметки для MAC {mac}: {str(e)}")
|
||||
return False, f"Внутренняя ошибка сервера: {str(e)}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue