routerless 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- routerless/__init__.py +3 -0
- routerless/adapters/__init__.py +11 -0
- routerless/adapters/base.py +90 -0
- routerless/adapters/bbox_ultim.py +665 -0
- routerless/adapters/openwrt.py +567 -0
- routerless/adapters/qnap_qhora.py +88 -0
- routerless/cli.py +977 -0
- routerless/models/__init__.py +23 -0
- routerless/models/config.py +180 -0
- routerless/models/status.py +42 -0
- routerless/version.py +1 -0
- routerless/yaml_loader.py +159 -0
- routerless-0.1.0.dist-info/METADATA +499 -0
- routerless-0.1.0.dist-info/RECORD +17 -0
- routerless-0.1.0.dist-info/WHEEL +4 -0
- routerless-0.1.0.dist-info/entry_points.txt +2 -0
- routerless-0.1.0.dist-info/licenses/LICENSE +21 -0
routerless/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from routerless.adapters.base import BaseAdapter
|
|
2
|
+
from routerless.adapters.bbox_ultim import BboxUltimAdapter
|
|
3
|
+
from routerless.adapters.openwrt import OpenWrtAdapter
|
|
4
|
+
from routerless.adapters.qnap_qhora import QnapQhoraAdapter
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"BaseAdapter",
|
|
8
|
+
"BboxUltimAdapter",
|
|
9
|
+
"OpenWrtAdapter",
|
|
10
|
+
"QnapQhoraAdapter",
|
|
11
|
+
]
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Abstract base class for all router adapters."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from routerless.models.status import AdapterStatus, ConnectedDevice, WifiRadio
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from routerless.models.config import (
|
|
11
|
+
DHCPConfig,
|
|
12
|
+
FirewallConfig,
|
|
13
|
+
NATConfig,
|
|
14
|
+
NetworkConfig,
|
|
15
|
+
TargetConfig,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseAdapter(ABC):
|
|
20
|
+
"""Common interface every router adapter must implement."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, target: "TargetConfig") -> None:
|
|
23
|
+
self.target = target
|
|
24
|
+
|
|
25
|
+
# ------------------------------------------------------------------
|
|
26
|
+
# Apply methods — called individually by the CLI --section flag
|
|
27
|
+
# ------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def apply_dhcp(self, config: "DHCPConfig") -> None:
|
|
31
|
+
"""Apply DHCP server settings and static lease reservations."""
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def apply_nat(self, config: "NATConfig") -> None:
|
|
35
|
+
"""Apply NAT / port-forwarding rules."""
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def apply_firewall(self, config: "FirewallConfig") -> None:
|
|
39
|
+
"""Apply firewall rules."""
|
|
40
|
+
|
|
41
|
+
# ------------------------------------------------------------------
|
|
42
|
+
# Dump — read current running config from device
|
|
43
|
+
# ------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def dump(self) -> "NetworkConfig":
|
|
47
|
+
"""Read the current configuration from the device and return it
|
|
48
|
+
as a :class:`~routerless.models.config.NetworkConfig`.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
# ------------------------------------------------------------------
|
|
52
|
+
# Convenience: apply all sections at once
|
|
53
|
+
# ------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
def apply_all(self, config: "NetworkConfig") -> None:
|
|
56
|
+
"""Apply all present sections from *config*."""
|
|
57
|
+
if config.dhcp is not None:
|
|
58
|
+
self.apply_dhcp(config.dhcp)
|
|
59
|
+
if config.nat is not None:
|
|
60
|
+
self.apply_nat(config.nat)
|
|
61
|
+
if config.firewall is not None:
|
|
62
|
+
self.apply_firewall(config.firewall)
|
|
63
|
+
|
|
64
|
+
# ------------------------------------------------------------------
|
|
65
|
+
# Optional read-only commands (raise NotImplementedError if unsupported)
|
|
66
|
+
# ------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
def get_status(self) -> AdapterStatus:
|
|
69
|
+
raise NotImplementedError(
|
|
70
|
+
f"{type(self).__name__} does not implement get_status(). "
|
|
71
|
+
"Only Bbox Ultim and OpenWrt adapters support this command."
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def get_devices(self, only_active: bool = True) -> list[ConnectedDevice]:
|
|
75
|
+
raise NotImplementedError(
|
|
76
|
+
f"{type(self).__name__} does not implement get_devices(). "
|
|
77
|
+
"Only Bbox Ultim and OpenWrt adapters support this command."
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def get_wifi(self) -> list[WifiRadio]:
|
|
81
|
+
raise NotImplementedError(
|
|
82
|
+
f"{type(self).__name__} does not implement get_wifi(). "
|
|
83
|
+
"Only Bbox Ultim and OpenWrt adapters support this command."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def wifi_enable(self, enable: bool) -> None:
|
|
87
|
+
raise NotImplementedError(
|
|
88
|
+
f"{type(self).__name__} does not implement wifi_enable(). "
|
|
89
|
+
"Only Bbox Ultim and OpenWrt adapters support this command."
|
|
90
|
+
)
|