daemon: updated core.services to avoid using deprecated type hinting, also updated string formatting to f strings
This commit is contained in:
parent
7f58224f43
commit
921bfdf527
11 changed files with 435 additions and 500 deletions
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
bird.py: defines routing services provided by the BIRD Internet Routing Daemon.
|
bird.py: defines routing services provided by the BIRD Internet Routing Daemon.
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
@ -14,12 +14,12 @@ class Bird(CoreService):
|
||||||
|
|
||||||
name: str = "bird"
|
name: str = "bird"
|
||||||
group: str = "BIRD"
|
group: str = "BIRD"
|
||||||
executables: Tuple[str, ...] = ("bird",)
|
executables: tuple[str, ...] = ("bird",)
|
||||||
dirs: Tuple[str, ...] = ("/etc/bird",)
|
dirs: tuple[str, ...] = ("/etc/bird",)
|
||||||
configs: Tuple[str, ...] = ("/etc/bird/bird.conf",)
|
configs: tuple[str, ...] = ("/etc/bird/bird.conf",)
|
||||||
startup: Tuple[str, ...] = ("bird -c %s" % (configs[0]),)
|
startup: tuple[str, ...] = (f"bird -c {configs[0]}",)
|
||||||
shutdown: Tuple[str, ...] = ("killall bird",)
|
shutdown: tuple[str, ...] = ("killall bird",)
|
||||||
validate: Tuple[str, ...] = ("pidof bird",)
|
validate: tuple[str, ...] = ("pidof bird",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -48,33 +48,30 @@ class Bird(CoreService):
|
||||||
Returns configuration file text. Other services that depend on bird
|
Returns configuration file text. Other services that depend on bird
|
||||||
will have hooks that are invoked here.
|
will have hooks that are invoked here.
|
||||||
"""
|
"""
|
||||||
cfg = """\
|
cfg = f"""\
|
||||||
/* Main configuration file for BIRD. This is ony a template,
|
/* Main configuration file for BIRD. This is ony a template,
|
||||||
* you will *need* to customize it according to your needs
|
* you will *need* to customize it according to your needs
|
||||||
* Beware that only double quotes \'"\' are valid. No singles. */
|
* Beware that only double quotes \'"\' are valid. No singles. */
|
||||||
|
|
||||||
|
|
||||||
log "/var/log/%s.log" all;
|
log "/var/log/{cls.name}.log" all;
|
||||||
#debug protocols all;
|
#debug protocols all;
|
||||||
#debug commands 2;
|
#debug commands 2;
|
||||||
|
|
||||||
router id %s; # Mandatory for IPv6, may be automatic for IPv4
|
router id {cls.router_id(node)}; # Mandatory for IPv6, may be automatic for IPv4
|
||||||
|
|
||||||
protocol kernel {
|
protocol kernel {{
|
||||||
persist; # Don\'t remove routes on BIRD shutdown
|
persist; # Don\'t remove routes on BIRD shutdown
|
||||||
scan time 200; # Scan kernel routing table every 200 seconds
|
scan time 200; # Scan kernel routing table every 200 seconds
|
||||||
export all;
|
export all;
|
||||||
import all;
|
import all;
|
||||||
}
|
}}
|
||||||
|
|
||||||
protocol device {
|
protocol device {{
|
||||||
scan time 10; # Scan interfaces every 10 seconds
|
scan time 10; # Scan interfaces every 10 seconds
|
||||||
}
|
}}
|
||||||
|
|
||||||
""" % (
|
"""
|
||||||
cls.name,
|
|
||||||
cls.router_id(node),
|
|
||||||
)
|
|
||||||
|
|
||||||
# generate protocol specific configurations
|
# generate protocol specific configurations
|
||||||
for s in node.services:
|
for s in node.services:
|
||||||
|
@ -94,8 +91,8 @@ class BirdService(CoreService):
|
||||||
|
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
group: str = "BIRD"
|
group: str = "BIRD"
|
||||||
executables: Tuple[str, ...] = ("bird",)
|
executables: tuple[str, ...] = ("bird",)
|
||||||
dependencies: Tuple[str, ...] = ("bird",)
|
dependencies: tuple[str, ...] = ("bird",)
|
||||||
meta: str = "The config file for this service can be found in the bird service."
|
meta: str = "The config file for this service can be found in the bird service."
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -111,7 +108,7 @@ class BirdService(CoreService):
|
||||||
"""
|
"""
|
||||||
cfg = ""
|
cfg = ""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += ' interface "%s";\n' % iface.name
|
cfg += f' interface "{iface.name}";\n'
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,18 +11,9 @@ import enum
|
||||||
import logging
|
import logging
|
||||||
import pkgutil
|
import pkgutil
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Iterable
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import (
|
from typing import TYPE_CHECKING, Optional, Union
|
||||||
TYPE_CHECKING,
|
|
||||||
Dict,
|
|
||||||
Iterable,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Set,
|
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
|
|
||||||
from core import services as core_services
|
from core import services as core_services
|
||||||
from core import utils
|
from core import utils
|
||||||
|
@ -41,7 +32,7 @@ logger = logging.getLogger(__name__)
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
|
|
||||||
CoreServiceType = Union["CoreService", Type["CoreService"]]
|
CoreServiceType = Union["CoreService", type["CoreService"]]
|
||||||
|
|
||||||
|
|
||||||
class ServiceMode(enum.Enum):
|
class ServiceMode(enum.Enum):
|
||||||
|
@ -57,25 +48,25 @@ class ServiceDependencies:
|
||||||
provided.
|
provided.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, services: List["CoreServiceType"]) -> None:
|
def __init__(self, services: list["CoreServiceType"]) -> None:
|
||||||
self.visited: Set[str] = set()
|
self.visited: set[str] = set()
|
||||||
self.services: Dict[str, "CoreServiceType"] = {}
|
self.services: dict[str, "CoreServiceType"] = {}
|
||||||
self.paths: Dict[str, List["CoreServiceType"]] = {}
|
self.paths: dict[str, list["CoreServiceType"]] = {}
|
||||||
self.boot_paths: List[List["CoreServiceType"]] = []
|
self.boot_paths: list[list["CoreServiceType"]] = []
|
||||||
roots = set([x.name for x in services])
|
roots = {x.name for x in services}
|
||||||
for service in services:
|
for service in services:
|
||||||
self.services[service.name] = service
|
self.services[service.name] = service
|
||||||
roots -= set(service.dependencies)
|
roots -= set(service.dependencies)
|
||||||
self.roots: List["CoreServiceType"] = [x for x in services if x.name in roots]
|
self.roots: list["CoreServiceType"] = [x for x in services if x.name in roots]
|
||||||
if services and not self.roots:
|
if services and not self.roots:
|
||||||
raise ValueError("circular dependency is present")
|
raise ValueError("circular dependency is present")
|
||||||
|
|
||||||
def _search(
|
def _search(
|
||||||
self,
|
self,
|
||||||
service: "CoreServiceType",
|
service: "CoreServiceType",
|
||||||
visiting: Set[str] = None,
|
visiting: set[str] = None,
|
||||||
path: List[str] = None,
|
path: list[str] = None,
|
||||||
) -> List["CoreServiceType"]:
|
) -> list["CoreServiceType"]:
|
||||||
if service.name in self.visited:
|
if service.name in self.visited:
|
||||||
return self.paths[service.name]
|
return self.paths[service.name]
|
||||||
self.visited.add(service.name)
|
self.visited.add(service.name)
|
||||||
|
@ -103,7 +94,7 @@ class ServiceDependencies:
|
||||||
self.paths[service.name] = path
|
self.paths[service.name] = path
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def boot_order(self) -> List[List["CoreServiceType"]]:
|
def boot_order(self) -> list[list["CoreServiceType"]]:
|
||||||
for service in self.roots:
|
for service in self.roots:
|
||||||
self._search(service)
|
self._search(service)
|
||||||
return self.boot_paths
|
return self.boot_paths
|
||||||
|
@ -114,10 +105,10 @@ class ServiceManager:
|
||||||
Manages services available for CORE nodes to use.
|
Manages services available for CORE nodes to use.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
services: Dict[str, Type["CoreService"]] = {}
|
services: dict[str, type["CoreService"]] = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add(cls, service: Type["CoreService"]) -> None:
|
def add(cls, service: type["CoreService"]) -> None:
|
||||||
"""
|
"""
|
||||||
Add a service to manager.
|
Add a service to manager.
|
||||||
|
|
||||||
|
@ -150,7 +141,7 @@ class ServiceManager:
|
||||||
cls.services[name] = service
|
cls.services[name] = service
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, name: str) -> Type["CoreService"]:
|
def get(cls, name: str) -> type["CoreService"]:
|
||||||
"""
|
"""
|
||||||
Retrieve a service from the manager.
|
Retrieve a service from the manager.
|
||||||
|
|
||||||
|
@ -163,7 +154,7 @@ class ServiceManager:
|
||||||
return service
|
return service
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_services(cls, path: Path) -> List[str]:
|
def add_services(cls, path: Path) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Method for retrieving all CoreServices from a given path.
|
Method for retrieving all CoreServices from a given path.
|
||||||
|
|
||||||
|
@ -183,7 +174,7 @@ class ServiceManager:
|
||||||
return service_errors
|
return service_errors
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_locals(cls) -> List[str]:
|
def load_locals(cls) -> list[str]:
|
||||||
errors = []
|
errors = []
|
||||||
for module_info in pkgutil.walk_packages(
|
for module_info in pkgutil.walk_packages(
|
||||||
core_services.__path__, f"{core_services.__name__}."
|
core_services.__path__, f"{core_services.__name__}."
|
||||||
|
@ -218,7 +209,7 @@ class CoreServices:
|
||||||
"""
|
"""
|
||||||
self.session: "Session" = session
|
self.session: "Session" = session
|
||||||
# dict of default services tuples, key is node type
|
# dict of default services tuples, key is node type
|
||||||
self.default_services: Dict[str, List[str]] = {
|
self.default_services: dict[str, list[str]] = {
|
||||||
"mdr": ["zebra", "OSPFv3MDR", "IPForward"],
|
"mdr": ["zebra", "OSPFv3MDR", "IPForward"],
|
||||||
"PC": ["DefaultRoute"],
|
"PC": ["DefaultRoute"],
|
||||||
"prouter": [],
|
"prouter": [],
|
||||||
|
@ -226,7 +217,7 @@ class CoreServices:
|
||||||
"host": ["DefaultRoute", "SSH"],
|
"host": ["DefaultRoute", "SSH"],
|
||||||
}
|
}
|
||||||
# dict of node ids to dict of custom services by name
|
# dict of node ids to dict of custom services by name
|
||||||
self.custom_services: Dict[int, Dict[str, "CoreService"]] = {}
|
self.custom_services: dict[int, dict[str, "CoreService"]] = {}
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -273,7 +264,7 @@ class CoreServices:
|
||||||
node_services[service.name] = service
|
node_services[service.name] = service
|
||||||
|
|
||||||
def add_services(
|
def add_services(
|
||||||
self, node: CoreNode, model: str, services: List[str] = None
|
self, node: CoreNode, model: str, services: list[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Add services to a node.
|
Add services to a node.
|
||||||
|
@ -298,7 +289,7 @@ class CoreServices:
|
||||||
continue
|
continue
|
||||||
node.services.append(service)
|
node.services.append(service)
|
||||||
|
|
||||||
def all_configs(self) -> List[Tuple[int, "CoreService"]]:
|
def all_configs(self) -> list[tuple[int, "CoreService"]]:
|
||||||
"""
|
"""
|
||||||
Return (node_id, service) tuples for all stored configs. Used when reconnecting
|
Return (node_id, service) tuples for all stored configs. Used when reconnecting
|
||||||
to a session or opening XML.
|
to a session or opening XML.
|
||||||
|
@ -313,7 +304,7 @@ class CoreServices:
|
||||||
configs.append((node_id, service))
|
configs.append((node_id, service))
|
||||||
return configs
|
return configs
|
||||||
|
|
||||||
def all_files(self, service: "CoreService") -> List[Tuple[str, str]]:
|
def all_files(self, service: "CoreService") -> list[tuple[str, str]]:
|
||||||
"""
|
"""
|
||||||
Return all customized files stored with a service.
|
Return all customized files stored with a service.
|
||||||
Used when reconnecting to a session or opening XML.
|
Used when reconnecting to a session or opening XML.
|
||||||
|
@ -349,7 +340,7 @@ class CoreServices:
|
||||||
if exceptions:
|
if exceptions:
|
||||||
raise CoreServiceBootError(*exceptions)
|
raise CoreServiceBootError(*exceptions)
|
||||||
|
|
||||||
def _boot_service_path(self, node: CoreNode, boot_path: List["CoreServiceType"]):
|
def _boot_service_path(self, node: CoreNode, boot_path: list["CoreServiceType"]):
|
||||||
logger.info(
|
logger.info(
|
||||||
"booting node(%s) services: %s",
|
"booting node(%s) services: %s",
|
||||||
node.name,
|
node.name,
|
||||||
|
@ -400,7 +391,7 @@ class CoreServices:
|
||||||
status = self.startup_service(node, service, wait)
|
status = self.startup_service(node, service, wait)
|
||||||
if status:
|
if status:
|
||||||
raise CoreServiceBootError(
|
raise CoreServiceBootError(
|
||||||
"node(%s) service(%s) error during startup" % (node.name, service.name)
|
f"node({node.name}) service({service.name}) error during startup"
|
||||||
)
|
)
|
||||||
|
|
||||||
# blocking mode is finished
|
# blocking mode is finished
|
||||||
|
@ -425,7 +416,7 @@ class CoreServices:
|
||||||
|
|
||||||
if status:
|
if status:
|
||||||
raise CoreServiceBootError(
|
raise CoreServiceBootError(
|
||||||
"node(%s) service(%s) failed validation" % (node.name, service.name)
|
f"node({node.name}) service({service.name}) failed validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
def copy_service_file(self, node: CoreNode, file_path: Path, cfg: str) -> bool:
|
def copy_service_file(self, node: CoreNode, file_path: Path, cfg: str) -> bool:
|
||||||
|
@ -540,11 +531,11 @@ class CoreServices:
|
||||||
# get the file data
|
# get the file data
|
||||||
data = service.config_data.get(filename)
|
data = service.config_data.get(filename)
|
||||||
if data is None:
|
if data is None:
|
||||||
data = "%s" % service.generate_config(node, filename)
|
data = service.generate_config(node, filename)
|
||||||
else:
|
else:
|
||||||
data = "%s" % data
|
data = data
|
||||||
|
|
||||||
filetypestr = "service:%s" % service.name
|
filetypestr = f"service:{service.name}"
|
||||||
return FileData(
|
return FileData(
|
||||||
message_type=MessageFlags.ADD,
|
message_type=MessageFlags.ADD,
|
||||||
node=node.id,
|
node=node.id,
|
||||||
|
@ -636,7 +627,7 @@ class CoreServices:
|
||||||
try:
|
try:
|
||||||
if self.copy_service_file(node, file_path, cfg):
|
if self.copy_service_file(node, file_path, cfg):
|
||||||
continue
|
continue
|
||||||
except IOError:
|
except OSError:
|
||||||
logger.exception("error copying service file: %s", file_name)
|
logger.exception("error copying service file: %s", file_name)
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
|
@ -674,31 +665,31 @@ class CoreService:
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
|
|
||||||
# executables that must exist for service to run
|
# executables that must exist for service to run
|
||||||
executables: Tuple[str, ...] = ()
|
executables: tuple[str, ...] = ()
|
||||||
|
|
||||||
# sets service requirements that must be started prior to this service starting
|
# sets service requirements that must be started prior to this service starting
|
||||||
dependencies: Tuple[str, ...] = ()
|
dependencies: tuple[str, ...] = ()
|
||||||
|
|
||||||
# group string allows grouping services together
|
# group string allows grouping services together
|
||||||
group: Optional[str] = None
|
group: Optional[str] = None
|
||||||
|
|
||||||
# private, per-node directories required by this service
|
# private, per-node directories required by this service
|
||||||
dirs: Tuple[str, ...] = ()
|
dirs: tuple[str, ...] = ()
|
||||||
|
|
||||||
# config files written by this service
|
# config files written by this service
|
||||||
configs: Tuple[str, ...] = ()
|
configs: tuple[str, ...] = ()
|
||||||
|
|
||||||
# config file data
|
# config file data
|
||||||
config_data: Dict[str, str] = {}
|
config_data: dict[str, str] = {}
|
||||||
|
|
||||||
# list of startup commands
|
# list of startup commands
|
||||||
startup: Tuple[str, ...] = ()
|
startup: tuple[str, ...] = ()
|
||||||
|
|
||||||
# list of shutdown commands
|
# list of shutdown commands
|
||||||
shutdown: Tuple[str, ...] = ()
|
shutdown: tuple[str, ...] = ()
|
||||||
|
|
||||||
# list of validate commands
|
# list of validate commands
|
||||||
validate: Tuple[str, ...] = ()
|
validate: tuple[str, ...] = ()
|
||||||
|
|
||||||
# validation mode, used to determine startup success
|
# validation mode, used to determine startup success
|
||||||
validation_mode: ServiceMode = ServiceMode.NON_BLOCKING
|
validation_mode: ServiceMode = ServiceMode.NON_BLOCKING
|
||||||
|
@ -723,7 +714,7 @@ class CoreService:
|
||||||
configuration is used to override their default parameters.
|
configuration is used to override their default parameters.
|
||||||
"""
|
"""
|
||||||
self.custom: bool = True
|
self.custom: bool = True
|
||||||
self.config_data: Dict[str, str] = self.__class__.config_data.copy()
|
self.config_data: dict[str, str] = self.__class__.config_data.copy()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def on_load(cls) -> None:
|
def on_load(cls) -> None:
|
||||||
|
@ -742,7 +733,7 @@ class CoreService:
|
||||||
return cls.configs
|
return cls.configs
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> None:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
"""
|
"""
|
||||||
Generate configuration file given a node object. The filename is
|
Generate configuration file given a node object. The filename is
|
||||||
provided to allow for multiple config files.
|
provided to allow for multiple config files.
|
||||||
|
@ -751,7 +742,7 @@ class CoreService:
|
||||||
|
|
||||||
:param node: node to generate config for
|
:param node: node to generate config for
|
||||||
:param filename: file name to generate config for
|
:param filename: file name to generate config for
|
||||||
:return: nothing
|
:return: generated config
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from core.emane.nodes import EmaneNet
|
from core.emane.nodes import EmaneNet
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
@ -9,14 +7,14 @@ from core.xml import emanexml
|
||||||
class EmaneTransportService(CoreService):
|
class EmaneTransportService(CoreService):
|
||||||
name: str = "transportd"
|
name: str = "transportd"
|
||||||
group: str = "EMANE"
|
group: str = "EMANE"
|
||||||
executables: Tuple[str, ...] = ("emanetransportd", "emanegentransportxml")
|
executables: tuple[str, ...] = ("emanetransportd", "emanegentransportxml")
|
||||||
dependencies: Tuple[str, ...] = ()
|
dependencies: tuple[str, ...] = ()
|
||||||
dirs: Tuple[str, ...] = ()
|
dirs: tuple[str, ...] = ()
|
||||||
configs: Tuple[str, ...] = ("emanetransport.sh",)
|
configs: tuple[str, ...] = ("emanetransport.sh",)
|
||||||
startup: Tuple[str, ...] = (f"bash {configs[0]}",)
|
startup: tuple[str, ...] = (f"bash {configs[0]}",)
|
||||||
validate: Tuple[str, ...] = (f"pidof {executables[0]}",)
|
validate: tuple[str, ...] = (f"pidof {executables[0]}",)
|
||||||
validation_timer: float = 0.5
|
validation_timer: float = 0.5
|
||||||
shutdown: Tuple[str, ...] = (f"killall {executables[0]}",)
|
shutdown: tuple[str, ...] = (f"killall {executables[0]}",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
frr.py: defines routing services provided by FRRouting.
|
frr.py: defines routing services provided by FRRouting.
|
||||||
Assumes installation of FRR via https://deb.frrouting.org/
|
Assumes installation of FRR via https://deb.frrouting.org/
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
|
@ -30,16 +30,16 @@ def is_wireless(node: NodeBase) -> bool:
|
||||||
class FRRZebra(CoreService):
|
class FRRZebra(CoreService):
|
||||||
name: str = "FRRzebra"
|
name: str = "FRRzebra"
|
||||||
group: str = "FRR"
|
group: str = "FRR"
|
||||||
dirs: Tuple[str, ...] = ("/usr/local/etc/frr", "/var/run/frr", "/var/log/frr")
|
dirs: tuple[str, ...] = ("/usr/local/etc/frr", "/var/run/frr", "/var/log/frr")
|
||||||
configs: Tuple[str, ...] = (
|
configs: tuple[str, ...] = (
|
||||||
"/usr/local/etc/frr/frr.conf",
|
"/usr/local/etc/frr/frr.conf",
|
||||||
"frrboot.sh",
|
"frrboot.sh",
|
||||||
"/usr/local/etc/frr/vtysh.conf",
|
"/usr/local/etc/frr/vtysh.conf",
|
||||||
"/usr/local/etc/frr/daemons",
|
"/usr/local/etc/frr/daemons",
|
||||||
)
|
)
|
||||||
startup: Tuple[str, ...] = ("bash frrboot.sh zebra",)
|
startup: tuple[str, ...] = ("bash frrboot.sh zebra",)
|
||||||
shutdown: Tuple[str, ...] = ("killall zebra",)
|
shutdown: tuple[str, ...] = ("killall zebra",)
|
||||||
validate: Tuple[str, ...] = ("pidof zebra",)
|
validate: tuple[str, ...] = ("pidof zebra",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -75,7 +75,7 @@ class FRRZebra(CoreService):
|
||||||
# we could verify here that filename == frr.conf
|
# we could verify here that filename == frr.conf
|
||||||
cfg = ""
|
cfg = ""
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
cfg += "interface %s\n" % iface.name
|
cfg += f"interface {iface.name}\n"
|
||||||
# include control interfaces in addressing but not routing daemons
|
# include control interfaces in addressing but not routing daemons
|
||||||
if iface.control:
|
if iface.control:
|
||||||
cfg += " "
|
cfg += " "
|
||||||
|
@ -127,11 +127,11 @@ class FRRZebra(CoreService):
|
||||||
"""
|
"""
|
||||||
address = str(ip.ip)
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv4(address):
|
if netaddr.valid_ipv4(address):
|
||||||
return "ip address %s" % ip
|
return f"ip address {ip}"
|
||||||
elif netaddr.valid_ipv6(address):
|
elif netaddr.valid_ipv6(address):
|
||||||
return "ipv6 address %s" % ip
|
return f"ipv6 address {ip}"
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid address: %s", ip)
|
raise ValueError(f"invalid address: {ip}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_frr_boot(cls, node: CoreNode) -> str:
|
def generate_frr_boot(cls, node: CoreNode) -> str:
|
||||||
|
@ -144,16 +144,16 @@ class FRRZebra(CoreService):
|
||||||
frr_sbin_search = node.session.options.get(
|
frr_sbin_search = node.session.options.get(
|
||||||
"frr_sbin_search", '"/usr/local/sbin /usr/sbin /usr/lib/frr"'
|
"frr_sbin_search", '"/usr/local/sbin /usr/sbin /usr/lib/frr"'
|
||||||
)
|
)
|
||||||
cfg = """\
|
cfg = f"""\
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# auto-generated by zebra service (frr.py)
|
# auto-generated by zebra service (frr.py)
|
||||||
FRR_CONF=%s
|
FRR_CONF={cls.configs[0]}
|
||||||
FRR_SBIN_SEARCH=%s
|
FRR_SBIN_SEARCH={frr_sbin_search}
|
||||||
FRR_BIN_SEARCH=%s
|
FRR_BIN_SEARCH={frr_bin_search}
|
||||||
FRR_STATE_DIR=%s
|
FRR_STATE_DIR={FRR_STATE_DIR}
|
||||||
|
|
||||||
searchforprog()
|
searchforprog()
|
||||||
{
|
{{
|
||||||
prog=$1
|
prog=$1
|
||||||
searchpath=$@
|
searchpath=$@
|
||||||
ret=
|
ret=
|
||||||
|
@ -164,10 +164,10 @@ searchforprog()
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo $ret
|
echo $ret
|
||||||
}
|
}}
|
||||||
|
|
||||||
confcheck()
|
confcheck()
|
||||||
{
|
{{
|
||||||
CONF_DIR=`dirname $FRR_CONF`
|
CONF_DIR=`dirname $FRR_CONF`
|
||||||
# if /etc/frr exists, point /etc/frr/frr.conf -> CONF_DIR
|
# if /etc/frr exists, point /etc/frr/frr.conf -> CONF_DIR
|
||||||
if [ "$CONF_DIR" != "/etc/frr" ] && [ -d /etc/frr ] && [ ! -e /etc/frr/frr.conf ]; then
|
if [ "$CONF_DIR" != "/etc/frr" ] && [ -d /etc/frr ] && [ ! -e /etc/frr/frr.conf ]; then
|
||||||
|
@ -177,10 +177,10 @@ confcheck()
|
||||||
if [ "$CONF_DIR" != "/etc/frr" ] && [ -d /etc/frr ] && [ ! -e /etc/frr/vtysh.conf ]; then
|
if [ "$CONF_DIR" != "/etc/frr" ] && [ -d /etc/frr ] && [ ! -e /etc/frr/vtysh.conf ]; then
|
||||||
ln -s $CONF_DIR/vtysh.conf /etc/frr/vtysh.conf
|
ln -s $CONF_DIR/vtysh.conf /etc/frr/vtysh.conf
|
||||||
fi
|
fi
|
||||||
}
|
}}
|
||||||
|
|
||||||
bootdaemon()
|
bootdaemon()
|
||||||
{
|
{{
|
||||||
FRR_SBIN_DIR=$(searchforprog $1 $FRR_SBIN_SEARCH)
|
FRR_SBIN_DIR=$(searchforprog $1 $FRR_SBIN_SEARCH)
|
||||||
if [ "z$FRR_SBIN_DIR" = "z" ]; then
|
if [ "z$FRR_SBIN_DIR" = "z" ]; then
|
||||||
echo "ERROR: FRR's '$1' daemon not found in search path:"
|
echo "ERROR: FRR's '$1' daemon not found in search path:"
|
||||||
|
@ -207,10 +207,10 @@ bootdaemon()
|
||||||
echo "ERROR: FRR's '$1' daemon failed to start!:"
|
echo "ERROR: FRR's '$1' daemon failed to start!:"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}}
|
||||||
|
|
||||||
bootfrr()
|
bootfrr()
|
||||||
{
|
{{
|
||||||
FRR_BIN_DIR=$(searchforprog 'vtysh' $FRR_BIN_SEARCH)
|
FRR_BIN_DIR=$(searchforprog 'vtysh' $FRR_BIN_SEARCH)
|
||||||
if [ "z$FRR_BIN_DIR" = "z" ]; then
|
if [ "z$FRR_BIN_DIR" = "z" ]; then
|
||||||
echo "ERROR: FRR's 'vtysh' program not found in search path:"
|
echo "ERROR: FRR's 'vtysh' program not found in search path:"
|
||||||
|
@ -229,8 +229,8 @@ bootfrr()
|
||||||
bootdaemon "staticd"
|
bootdaemon "staticd"
|
||||||
fi
|
fi
|
||||||
for r in rip ripng ospf6 ospf bgp babel isis; do
|
for r in rip ripng ospf6 ospf bgp babel isis; do
|
||||||
if grep -q "^router \\<${r}\\>" $FRR_CONF; then
|
if grep -q "^router \\<${{r}}\\>" $FRR_CONF; then
|
||||||
bootdaemon "${r}d"
|
bootdaemon "${{r}}d"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ bootfrr()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$FRR_BIN_DIR/vtysh -b
|
$FRR_BIN_DIR/vtysh -b
|
||||||
}
|
}}
|
||||||
|
|
||||||
if [ "$1" != "zebra" ]; then
|
if [ "$1" != "zebra" ]; then
|
||||||
echo "WARNING: '$1': all FRR daemons are launched by the 'zebra' service!"
|
echo "WARNING: '$1': all FRR daemons are launched by the 'zebra' service!"
|
||||||
|
@ -248,12 +248,7 @@ fi
|
||||||
|
|
||||||
confcheck
|
confcheck
|
||||||
bootfrr
|
bootfrr
|
||||||
""" % (
|
"""
|
||||||
cls.configs[0],
|
|
||||||
frr_sbin_search,
|
|
||||||
frr_bin_search,
|
|
||||||
FRR_STATE_DIR,
|
|
||||||
)
|
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
cfg += f"ip link set dev {iface.name} down\n"
|
cfg += f"ip link set dev {iface.name} down\n"
|
||||||
cfg += "sleep 1\n"
|
cfg += "sleep 1\n"
|
||||||
|
@ -337,7 +332,7 @@ class FrrService(CoreService):
|
||||||
|
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
group: str = "FRR"
|
group: str = "FRR"
|
||||||
dependencies: Tuple[str, ...] = ("FRRzebra",)
|
dependencies: tuple[str, ...] = ("FRRzebra",)
|
||||||
meta: str = "The config file for this service can be found in the Zebra service."
|
meta: str = "The config file for this service can be found in the Zebra service."
|
||||||
ipv4_routing: bool = False
|
ipv4_routing: bool = False
|
||||||
ipv6_routing: bool = False
|
ipv6_routing: bool = False
|
||||||
|
@ -388,8 +383,8 @@ class FRROspfv2(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRROSPFv2"
|
name: str = "FRROSPFv2"
|
||||||
shutdown: Tuple[str, ...] = ("killall ospfd",)
|
shutdown: tuple[str, ...] = ("killall ospfd",)
|
||||||
validate: Tuple[str, ...] = ("pidof ospfd",)
|
validate: tuple[str, ...] = ("pidof ospfd",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -424,7 +419,7 @@ class FRROspfv2(FrrService):
|
||||||
def generate_frr_config(cls, node: CoreNode) -> str:
|
def generate_frr_config(cls, node: CoreNode) -> str:
|
||||||
cfg = "router ospf\n"
|
cfg = "router ospf\n"
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += " router-id %s\n" % rtrid
|
cfg += f" router-id {rtrid}\n"
|
||||||
# network 10.0.0.0/24 area 0
|
# network 10.0.0.0/24 area 0
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for ip4 in iface.ip4s:
|
for ip4 in iface.ip4s:
|
||||||
|
@ -458,8 +453,8 @@ class FRROspfv3(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRROSPFv3"
|
name: str = "FRROSPFv3"
|
||||||
shutdown: Tuple[str, ...] = ("killall ospf6d",)
|
shutdown: tuple[str, ...] = ("killall ospf6d",)
|
||||||
validate: Tuple[str, ...] = ("pidof ospf6d",)
|
validate: tuple[str, ...] = ("pidof ospf6d",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
|
||||||
|
@ -486,7 +481,7 @@ class FRROspfv3(FrrService):
|
||||||
"""
|
"""
|
||||||
minmtu = cls.min_mtu(iface)
|
minmtu = cls.min_mtu(iface)
|
||||||
if minmtu < iface.mtu:
|
if minmtu < iface.mtu:
|
||||||
return " ipv6 ospf6 ifmtu %d\n" % minmtu
|
return f" ipv6 ospf6 ifmtu {minmtu:d}\n"
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@ -504,9 +499,9 @@ class FRROspfv3(FrrService):
|
||||||
def generate_frr_config(cls, node: CoreNode) -> str:
|
def generate_frr_config(cls, node: CoreNode) -> str:
|
||||||
cfg = "router ospf6\n"
|
cfg = "router ospf6\n"
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += " router-id %s\n" % rtrid
|
cfg += f" router-id {rtrid}\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += " interface %s area 0.0.0.0\n" % iface.name
|
cfg += f" interface {iface.name} area 0.0.0.0\n"
|
||||||
cfg += "!\n"
|
cfg += "!\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -523,8 +518,8 @@ class FRRBgp(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRRBGP"
|
name: str = "FRRBGP"
|
||||||
shutdown: Tuple[str, ...] = ("killall bgpd",)
|
shutdown: tuple[str, ...] = ("killall bgpd",)
|
||||||
validate: Tuple[str, ...] = ("pidof bgpd",)
|
validate: tuple[str, ...] = ("pidof bgpd",)
|
||||||
custom_needed: bool = True
|
custom_needed: bool = True
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
@ -534,9 +529,9 @@ class FRRBgp(FrrService):
|
||||||
cfg = "!\n! BGP configuration\n!\n"
|
cfg = "!\n! BGP configuration\n!\n"
|
||||||
cfg += "! You should configure the AS number below,\n"
|
cfg += "! You should configure the AS number below,\n"
|
||||||
cfg += "! along with this router's peers.\n!\n"
|
cfg += "! along with this router's peers.\n!\n"
|
||||||
cfg += "router bgp %s\n" % node.id
|
cfg += f"router bgp {node.id}\n"
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += " bgp router-id %s\n" % rtrid
|
cfg += f" bgp router-id {rtrid}\n"
|
||||||
cfg += " redistribute connected\n"
|
cfg += " redistribute connected\n"
|
||||||
cfg += "! neighbor 1.2.3.4 remote-as 555\n!\n"
|
cfg += "! neighbor 1.2.3.4 remote-as 555\n!\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
@ -548,8 +543,8 @@ class FRRRip(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRRRIP"
|
name: str = "FRRRIP"
|
||||||
shutdown: Tuple[str, ...] = ("killall ripd",)
|
shutdown: tuple[str, ...] = ("killall ripd",)
|
||||||
validate: Tuple[str, ...] = ("pidof ripd",)
|
validate: tuple[str, ...] = ("pidof ripd",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -571,8 +566,8 @@ class FRRRipng(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRRRIPNG"
|
name: str = "FRRRIPNG"
|
||||||
shutdown: Tuple[str, ...] = ("killall ripngd",)
|
shutdown: tuple[str, ...] = ("killall ripngd",)
|
||||||
validate: Tuple[str, ...] = ("pidof ripngd",)
|
validate: tuple[str, ...] = ("pidof ripngd",)
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -595,15 +590,15 @@ class FRRBabel(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRRBabel"
|
name: str = "FRRBabel"
|
||||||
shutdown: Tuple[str, ...] = ("killall babeld",)
|
shutdown: tuple[str, ...] = ("killall babeld",)
|
||||||
validate: Tuple[str, ...] = ("pidof babeld",)
|
validate: tuple[str, ...] = ("pidof babeld",)
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_frr_config(cls, node: CoreNode) -> str:
|
def generate_frr_config(cls, node: CoreNode) -> str:
|
||||||
cfg = "router babel\n"
|
cfg = "router babel\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += " network %s\n" % iface.name
|
cfg += f" network {iface.name}\n"
|
||||||
cfg += " redistribute static\n redistribute ipv4 connected\n"
|
cfg += " redistribute static\n redistribute ipv4 connected\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -621,8 +616,8 @@ class FRRpimd(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRRpimd"
|
name: str = "FRRpimd"
|
||||||
shutdown: Tuple[str, ...] = ("killall pimd",)
|
shutdown: tuple[str, ...] = ("killall pimd",)
|
||||||
validate: Tuple[str, ...] = ("pidof pimd",)
|
validate: tuple[str, ...] = ("pidof pimd",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -636,8 +631,8 @@ class FRRpimd(FrrService):
|
||||||
cfg += "router igmp\n!\n"
|
cfg += "router igmp\n!\n"
|
||||||
cfg += "router pim\n"
|
cfg += "router pim\n"
|
||||||
cfg += " !ip pim rp-address 10.0.0.1\n"
|
cfg += " !ip pim rp-address 10.0.0.1\n"
|
||||||
cfg += " ip pim bsr-candidate %s\n" % ifname
|
cfg += f" ip pim bsr-candidate {ifname}\n"
|
||||||
cfg += " ip pim rp-candidate %s\n" % ifname
|
cfg += f" ip pim rp-candidate {ifname}\n"
|
||||||
cfg += " !ip pim spt-threshold interval 10 bytes 80000\n"
|
cfg += " !ip pim spt-threshold interval 10 bytes 80000\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -654,8 +649,8 @@ class FRRIsis(FrrService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FRRISIS"
|
name: str = "FRRISIS"
|
||||||
shutdown: Tuple[str, ...] = ("killall isisd",)
|
shutdown: tuple[str, ...] = ("killall isisd",)
|
||||||
validate: Tuple[str, ...] = ("pidof isisd",)
|
validate: tuple[str, ...] = ("pidof isisd",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
|
||||||
|
@ -672,7 +667,7 @@ class FRRIsis(FrrService):
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_frr_config(cls, node: CoreNode) -> str:
|
def generate_frr_config(cls, node: CoreNode) -> str:
|
||||||
cfg = "router isis DEFAULT\n"
|
cfg = "router isis DEFAULT\n"
|
||||||
cfg += " net 47.0001.0000.1900.%04x.00\n" % node.id
|
cfg += f" net 47.0001.0000.1900.{node.id:04x}.00\n"
|
||||||
cfg += " metric-style wide\n"
|
cfg += " metric-style wide\n"
|
||||||
cfg += " is-type level-2-only\n"
|
cfg += " is-type level-2-only\n"
|
||||||
cfg += "!\n"
|
cfg += "!\n"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
nrl.py: defines services provided by NRL protolib tools hosted here:
|
nrl.py: defines services provided by NRL protolib tools hosted here:
|
||||||
http://www.nrl.navy.mil/itd/ncs/products
|
http://www.nrl.navy.mil/itd/ncs/products
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
|
@ -33,29 +33,29 @@ class NrlService(CoreService):
|
||||||
ip4 = iface.get_ip4()
|
ip4 = iface.get_ip4()
|
||||||
if ip4:
|
if ip4:
|
||||||
return f"{ip4.ip}/{prefixlen}"
|
return f"{ip4.ip}/{prefixlen}"
|
||||||
return "0.0.0.0/%s" % prefixlen
|
return f"0.0.0.0/{prefixlen}"
|
||||||
|
|
||||||
|
|
||||||
class MgenSinkService(NrlService):
|
class MgenSinkService(NrlService):
|
||||||
name: str = "MGEN_Sink"
|
name: str = "MGEN_Sink"
|
||||||
executables: Tuple[str, ...] = ("mgen",)
|
executables: tuple[str, ...] = ("mgen",)
|
||||||
configs: Tuple[str, ...] = ("sink.mgen",)
|
configs: tuple[str, ...] = ("sink.mgen",)
|
||||||
startup: Tuple[str, ...] = ("mgen input sink.mgen",)
|
startup: tuple[str, ...] = ("mgen input sink.mgen",)
|
||||||
validate: Tuple[str, ...] = ("pidof mgen",)
|
validate: tuple[str, ...] = ("pidof mgen",)
|
||||||
shutdown: Tuple[str, ...] = ("killall mgen",)
|
shutdown: tuple[str, ...] = ("killall mgen",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
cfg = "0.0 LISTEN UDP 5000\n"
|
cfg = "0.0 LISTEN UDP 5000\n"
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
name = utils.sysctl_devname(iface.name)
|
name = utils.sysctl_devname(iface.name)
|
||||||
cfg += "0.0 Join 224.225.1.2 INTERFACE %s\n" % name
|
cfg += f"0.0 Join 224.225.1.2 INTERFACE {name}\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]:
|
def get_startup(cls, node: CoreNode) -> tuple[str, ...]:
|
||||||
cmd = cls.startup[0]
|
cmd = cls.startup[0]
|
||||||
cmd += " output /tmp/mgen_%s.log" % node.name
|
cmd += f" output /tmp/mgen_{node.name}.log"
|
||||||
return (cmd,)
|
return (cmd,)
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,23 +65,23 @@ class NrlNhdp(NrlService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "NHDP"
|
name: str = "NHDP"
|
||||||
executables: Tuple[str, ...] = ("nrlnhdp",)
|
executables: tuple[str, ...] = ("nrlnhdp",)
|
||||||
startup: Tuple[str, ...] = ("nrlnhdp",)
|
startup: tuple[str, ...] = ("nrlnhdp",)
|
||||||
shutdown: Tuple[str, ...] = ("killall nrlnhdp",)
|
shutdown: tuple[str, ...] = ("killall nrlnhdp",)
|
||||||
validate: Tuple[str, ...] = ("pidof nrlnhdp",)
|
validate: tuple[str, ...] = ("pidof nrlnhdp",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]:
|
def get_startup(cls, node: CoreNode) -> tuple[str, ...]:
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
cmd = cls.startup[0]
|
cmd = cls.startup[0]
|
||||||
cmd += " -l /var/log/nrlnhdp.log"
|
cmd += " -l /var/log/nrlnhdp.log"
|
||||||
cmd += " -rpipe %s_nhdp" % node.name
|
cmd += f" -rpipe {node.name}_nhdp"
|
||||||
servicenames = map(lambda x: x.name, node.services)
|
servicenames = map(lambda x: x.name, node.services)
|
||||||
if "SMF" in servicenames:
|
if "SMF" in servicenames:
|
||||||
cmd += " -flooding ecds"
|
cmd += " -flooding ecds"
|
||||||
cmd += " -smfClient %s_smf" % node.name
|
cmd += f" -smfClient {node.name}_smf"
|
||||||
ifaces = node.get_ifaces(control=False)
|
ifaces = node.get_ifaces(control=False)
|
||||||
if len(ifaces) > 0:
|
if len(ifaces) > 0:
|
||||||
iface_names = map(lambda x: x.name, ifaces)
|
iface_names = map(lambda x: x.name, ifaces)
|
||||||
|
@ -96,11 +96,11 @@ class NrlSmf(NrlService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "SMF"
|
name: str = "SMF"
|
||||||
executables: Tuple[str, ...] = ("nrlsmf",)
|
executables: tuple[str, ...] = ("nrlsmf",)
|
||||||
startup: Tuple[str, ...] = ("bash startsmf.sh",)
|
startup: tuple[str, ...] = ("bash startsmf.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall nrlsmf",)
|
shutdown: tuple[str, ...] = ("killall nrlsmf",)
|
||||||
validate: Tuple[str, ...] = ("pidof nrlsmf",)
|
validate: tuple[str, ...] = ("pidof nrlsmf",)
|
||||||
configs: Tuple[str, ...] = ("startsmf.sh",)
|
configs: tuple[str, ...] = ("startsmf.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -112,7 +112,7 @@ class NrlSmf(NrlService):
|
||||||
cfg = "#!/bin/sh\n"
|
cfg = "#!/bin/sh\n"
|
||||||
cfg += "# auto-generated by nrl.py:NrlSmf.generateconfig()\n"
|
cfg += "# auto-generated by nrl.py:NrlSmf.generateconfig()\n"
|
||||||
comments = ""
|
comments = ""
|
||||||
cmd = "nrlsmf instance %s_smf" % node.name
|
cmd = f"nrlsmf instance {node.name}_smf"
|
||||||
|
|
||||||
servicenames = map(lambda x: x.name, node.services)
|
servicenames = map(lambda x: x.name, node.services)
|
||||||
ifaces = node.get_ifaces(control=False)
|
ifaces = node.get_ifaces(control=False)
|
||||||
|
@ -142,13 +142,13 @@ class NrlOlsr(NrlService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "OLSR"
|
name: str = "OLSR"
|
||||||
executables: Tuple[str, ...] = ("nrlolsrd",)
|
executables: tuple[str, ...] = ("nrlolsrd",)
|
||||||
startup: Tuple[str, ...] = ("nrlolsrd",)
|
startup: tuple[str, ...] = ("nrlolsrd",)
|
||||||
shutdown: Tuple[str, ...] = ("killall nrlolsrd",)
|
shutdown: tuple[str, ...] = ("killall nrlolsrd",)
|
||||||
validate: Tuple[str, ...] = ("pidof nrlolsrd",)
|
validate: tuple[str, ...] = ("pidof nrlolsrd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]:
|
def get_startup(cls, node: CoreNode) -> tuple[str, ...]:
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
|
@ -157,13 +157,13 @@ class NrlOlsr(NrlService):
|
||||||
ifaces = node.get_ifaces()
|
ifaces = node.get_ifaces()
|
||||||
if len(ifaces) > 0:
|
if len(ifaces) > 0:
|
||||||
iface = ifaces[0]
|
iface = ifaces[0]
|
||||||
cmd += " -i %s" % iface.name
|
cmd += f" -i {iface.name}"
|
||||||
cmd += " -l /var/log/nrlolsrd.log"
|
cmd += " -l /var/log/nrlolsrd.log"
|
||||||
cmd += " -rpipe %s_olsr" % node.name
|
cmd += f" -rpipe {node.name}_olsr"
|
||||||
servicenames = map(lambda x: x.name, node.services)
|
servicenames = map(lambda x: x.name, node.services)
|
||||||
if "SMF" in servicenames and "NHDP" not in servicenames:
|
if "SMF" in servicenames and "NHDP" not in servicenames:
|
||||||
cmd += " -flooding s-mpr"
|
cmd += " -flooding s-mpr"
|
||||||
cmd += " -smfClient %s_smf" % node.name
|
cmd += f" -smfClient {node.name}_smf"
|
||||||
if "zebra" in servicenames:
|
if "zebra" in servicenames:
|
||||||
cmd += " -z"
|
cmd += " -z"
|
||||||
return (cmd,)
|
return (cmd,)
|
||||||
|
@ -175,23 +175,23 @@ class NrlOlsrv2(NrlService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "OLSRv2"
|
name: str = "OLSRv2"
|
||||||
executables: Tuple[str, ...] = ("nrlolsrv2",)
|
executables: tuple[str, ...] = ("nrlolsrv2",)
|
||||||
startup: Tuple[str, ...] = ("nrlolsrv2",)
|
startup: tuple[str, ...] = ("nrlolsrv2",)
|
||||||
shutdown: Tuple[str, ...] = ("killall nrlolsrv2",)
|
shutdown: tuple[str, ...] = ("killall nrlolsrv2",)
|
||||||
validate: Tuple[str, ...] = ("pidof nrlolsrv2",)
|
validate: tuple[str, ...] = ("pidof nrlolsrv2",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]:
|
def get_startup(cls, node: CoreNode) -> tuple[str, ...]:
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
cmd = cls.startup[0]
|
cmd = cls.startup[0]
|
||||||
cmd += " -l /var/log/nrlolsrv2.log"
|
cmd += " -l /var/log/nrlolsrv2.log"
|
||||||
cmd += " -rpipe %s_olsrv2" % node.name
|
cmd += f" -rpipe {node.name}_olsrv2"
|
||||||
servicenames = map(lambda x: x.name, node.services)
|
servicenames = map(lambda x: x.name, node.services)
|
||||||
if "SMF" in servicenames:
|
if "SMF" in servicenames:
|
||||||
cmd += " -flooding ecds"
|
cmd += " -flooding ecds"
|
||||||
cmd += " -smfClient %s_smf" % node.name
|
cmd += f" -smfClient {node.name}_smf"
|
||||||
cmd += " -p olsr"
|
cmd += " -p olsr"
|
||||||
ifaces = node.get_ifaces(control=False)
|
ifaces = node.get_ifaces(control=False)
|
||||||
if len(ifaces) > 0:
|
if len(ifaces) > 0:
|
||||||
|
@ -207,15 +207,15 @@ class OlsrOrg(NrlService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "OLSRORG"
|
name: str = "OLSRORG"
|
||||||
executables: Tuple[str, ...] = ("olsrd",)
|
executables: tuple[str, ...] = ("olsrd",)
|
||||||
configs: Tuple[str, ...] = ("/etc/olsrd/olsrd.conf",)
|
configs: tuple[str, ...] = ("/etc/olsrd/olsrd.conf",)
|
||||||
dirs: Tuple[str, ...] = ("/etc/olsrd",)
|
dirs: tuple[str, ...] = ("/etc/olsrd",)
|
||||||
startup: Tuple[str, ...] = ("olsrd",)
|
startup: tuple[str, ...] = ("olsrd",)
|
||||||
shutdown: Tuple[str, ...] = ("killall olsrd",)
|
shutdown: tuple[str, ...] = ("killall olsrd",)
|
||||||
validate: Tuple[str, ...] = ("pidof olsrd",)
|
validate: tuple[str, ...] = ("pidof olsrd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]:
|
def get_startup(cls, node: CoreNode) -> tuple[str, ...]:
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
|
@ -558,11 +558,11 @@ class MgenActor(NrlService):
|
||||||
# a unique name is required, without spaces
|
# a unique name is required, without spaces
|
||||||
name: str = "MgenActor"
|
name: str = "MgenActor"
|
||||||
group: str = "ProtoSvc"
|
group: str = "ProtoSvc"
|
||||||
executables: Tuple[str, ...] = ("mgen",)
|
executables: tuple[str, ...] = ("mgen",)
|
||||||
configs: Tuple[str, ...] = ("start_mgen_actor.sh",)
|
configs: tuple[str, ...] = ("start_mgen_actor.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash start_mgen_actor.sh",)
|
startup: tuple[str, ...] = ("bash start_mgen_actor.sh",)
|
||||||
validate: Tuple[str, ...] = ("pidof mgen",)
|
validate: tuple[str, ...] = ("pidof mgen",)
|
||||||
shutdown: Tuple[str, ...] = ("killall mgen",)
|
shutdown: tuple[str, ...] = ("killall mgen",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -574,7 +574,7 @@ class MgenActor(NrlService):
|
||||||
cfg = "#!/bin/sh\n"
|
cfg = "#!/bin/sh\n"
|
||||||
cfg += "# auto-generated by nrl.py:MgenActor.generateconfig()\n"
|
cfg += "# auto-generated by nrl.py:MgenActor.generateconfig()\n"
|
||||||
comments = ""
|
comments = ""
|
||||||
cmd = "mgenBasicActor.py -n %s -a 0.0.0.0" % node.name
|
cmd = f"mgenBasicActor.py -n {node.name} -a 0.0.0.0"
|
||||||
ifaces = node.get_ifaces(control=False)
|
ifaces = node.get_ifaces(control=False)
|
||||||
if len(ifaces) == 0:
|
if len(ifaces) == 0:
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
quagga.py: defines routing services provided by Quagga.
|
quagga.py: defines routing services provided by Quagga.
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
|
@ -29,15 +29,15 @@ def is_wireless(node: NodeBase) -> bool:
|
||||||
class Zebra(CoreService):
|
class Zebra(CoreService):
|
||||||
name: str = "zebra"
|
name: str = "zebra"
|
||||||
group: str = "Quagga"
|
group: str = "Quagga"
|
||||||
dirs: Tuple[str, ...] = ("/usr/local/etc/quagga", "/var/run/quagga")
|
dirs: tuple[str, ...] = ("/usr/local/etc/quagga", "/var/run/quagga")
|
||||||
configs: Tuple[str, ...] = (
|
configs: tuple[str, ...] = (
|
||||||
"/usr/local/etc/quagga/Quagga.conf",
|
"/usr/local/etc/quagga/Quagga.conf",
|
||||||
"quaggaboot.sh",
|
"quaggaboot.sh",
|
||||||
"/usr/local/etc/quagga/vtysh.conf",
|
"/usr/local/etc/quagga/vtysh.conf",
|
||||||
)
|
)
|
||||||
startup: Tuple[str, ...] = ("bash quaggaboot.sh zebra",)
|
startup: tuple[str, ...] = ("bash quaggaboot.sh zebra",)
|
||||||
shutdown: Tuple[str, ...] = ("killall zebra",)
|
shutdown: tuple[str, ...] = ("killall zebra",)
|
||||||
validate: Tuple[str, ...] = ("pidof zebra",)
|
validate: tuple[str, ...] = ("pidof zebra",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -71,7 +71,7 @@ class Zebra(CoreService):
|
||||||
# we could verify here that filename == Quagga.conf
|
# we could verify here that filename == Quagga.conf
|
||||||
cfg = ""
|
cfg = ""
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
cfg += "interface %s\n" % iface.name
|
cfg += f"interface {iface.name}\n"
|
||||||
# include control interfaces in addressing but not routing daemons
|
# include control interfaces in addressing but not routing daemons
|
||||||
if iface.control:
|
if iface.control:
|
||||||
cfg += " "
|
cfg += " "
|
||||||
|
@ -123,11 +123,11 @@ class Zebra(CoreService):
|
||||||
"""
|
"""
|
||||||
address = str(ip.ip)
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv4(address):
|
if netaddr.valid_ipv4(address):
|
||||||
return "ip address %s" % ip
|
return f"ip address {ip}"
|
||||||
elif netaddr.valid_ipv6(address):
|
elif netaddr.valid_ipv6(address):
|
||||||
return "ipv6 address %s" % ip
|
return f"ipv6 address {ip}"
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid address: %s", ip)
|
raise ValueError(f"invalid address: {ip}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_quagga_boot(cls, node: CoreNode) -> str:
|
def generate_quagga_boot(cls, node: CoreNode) -> str:
|
||||||
|
@ -140,16 +140,16 @@ class Zebra(CoreService):
|
||||||
quagga_sbin_search = node.session.options.get(
|
quagga_sbin_search = node.session.options.get(
|
||||||
"quagga_sbin_search", '"/usr/local/sbin /usr/sbin /usr/lib/quagga"'
|
"quagga_sbin_search", '"/usr/local/sbin /usr/sbin /usr/lib/quagga"'
|
||||||
)
|
)
|
||||||
return """\
|
return f"""\
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# auto-generated by zebra service (quagga.py)
|
# auto-generated by zebra service (quagga.py)
|
||||||
QUAGGA_CONF=%s
|
QUAGGA_CONF={cls.configs[0]}
|
||||||
QUAGGA_SBIN_SEARCH=%s
|
QUAGGA_SBIN_SEARCH={quagga_sbin_search}
|
||||||
QUAGGA_BIN_SEARCH=%s
|
QUAGGA_BIN_SEARCH={quagga_bin_search}
|
||||||
QUAGGA_STATE_DIR=%s
|
QUAGGA_STATE_DIR={QUAGGA_STATE_DIR}
|
||||||
|
|
||||||
searchforprog()
|
searchforprog()
|
||||||
{
|
{{
|
||||||
prog=$1
|
prog=$1
|
||||||
searchpath=$@
|
searchpath=$@
|
||||||
ret=
|
ret=
|
||||||
|
@ -160,10 +160,10 @@ searchforprog()
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo $ret
|
echo $ret
|
||||||
}
|
}}
|
||||||
|
|
||||||
confcheck()
|
confcheck()
|
||||||
{
|
{{
|
||||||
CONF_DIR=`dirname $QUAGGA_CONF`
|
CONF_DIR=`dirname $QUAGGA_CONF`
|
||||||
# if /etc/quagga exists, point /etc/quagga/Quagga.conf -> CONF_DIR
|
# if /etc/quagga exists, point /etc/quagga/Quagga.conf -> CONF_DIR
|
||||||
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -e /etc/quagga/Quagga.conf ]; then
|
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -e /etc/quagga/Quagga.conf ]; then
|
||||||
|
@ -173,10 +173,10 @@ confcheck()
|
||||||
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -e /etc/quagga/vtysh.conf ]; then
|
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -e /etc/quagga/vtysh.conf ]; then
|
||||||
ln -s $CONF_DIR/vtysh.conf /etc/quagga/vtysh.conf
|
ln -s $CONF_DIR/vtysh.conf /etc/quagga/vtysh.conf
|
||||||
fi
|
fi
|
||||||
}
|
}}
|
||||||
|
|
||||||
bootdaemon()
|
bootdaemon()
|
||||||
{
|
{{
|
||||||
QUAGGA_SBIN_DIR=$(searchforprog $1 $QUAGGA_SBIN_SEARCH)
|
QUAGGA_SBIN_DIR=$(searchforprog $1 $QUAGGA_SBIN_SEARCH)
|
||||||
if [ "z$QUAGGA_SBIN_DIR" = "z" ]; then
|
if [ "z$QUAGGA_SBIN_DIR" = "z" ]; then
|
||||||
echo "ERROR: Quagga's '$1' daemon not found in search path:"
|
echo "ERROR: Quagga's '$1' daemon not found in search path:"
|
||||||
|
@ -196,10 +196,10 @@ bootdaemon()
|
||||||
echo "ERROR: Quagga's '$1' daemon failed to start!:"
|
echo "ERROR: Quagga's '$1' daemon failed to start!:"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}}
|
||||||
|
|
||||||
bootquagga()
|
bootquagga()
|
||||||
{
|
{{
|
||||||
QUAGGA_BIN_DIR=$(searchforprog 'vtysh' $QUAGGA_BIN_SEARCH)
|
QUAGGA_BIN_DIR=$(searchforprog 'vtysh' $QUAGGA_BIN_SEARCH)
|
||||||
if [ "z$QUAGGA_BIN_DIR" = "z" ]; then
|
if [ "z$QUAGGA_BIN_DIR" = "z" ]; then
|
||||||
echo "ERROR: Quagga's 'vtysh' program not found in search path:"
|
echo "ERROR: Quagga's 'vtysh' program not found in search path:"
|
||||||
|
@ -215,8 +215,8 @@ bootquagga()
|
||||||
|
|
||||||
bootdaemon "zebra"
|
bootdaemon "zebra"
|
||||||
for r in rip ripng ospf6 ospf bgp babel; do
|
for r in rip ripng ospf6 ospf bgp babel; do
|
||||||
if grep -q "^router \\<${r}\\>" $QUAGGA_CONF; then
|
if grep -q "^router \\<${{r}}\\>" $QUAGGA_CONF; then
|
||||||
bootdaemon "${r}d"
|
bootdaemon "${{r}}d"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ bootquagga()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$QUAGGA_BIN_DIR/vtysh -b
|
$QUAGGA_BIN_DIR/vtysh -b
|
||||||
}
|
}}
|
||||||
|
|
||||||
if [ "$1" != "zebra" ]; then
|
if [ "$1" != "zebra" ]; then
|
||||||
echo "WARNING: '$1': all Quagga daemons are launched by the 'zebra' service!"
|
echo "WARNING: '$1': all Quagga daemons are launched by the 'zebra' service!"
|
||||||
|
@ -233,12 +233,7 @@ if [ "$1" != "zebra" ]; then
|
||||||
fi
|
fi
|
||||||
confcheck
|
confcheck
|
||||||
bootquagga
|
bootquagga
|
||||||
""" % (
|
"""
|
||||||
cls.configs[0],
|
|
||||||
quagga_sbin_search,
|
|
||||||
quagga_bin_search,
|
|
||||||
QUAGGA_STATE_DIR,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class QuaggaService(CoreService):
|
class QuaggaService(CoreService):
|
||||||
|
@ -249,7 +244,7 @@ class QuaggaService(CoreService):
|
||||||
|
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
group: str = "Quagga"
|
group: str = "Quagga"
|
||||||
dependencies: Tuple[str, ...] = (Zebra.name,)
|
dependencies: tuple[str, ...] = (Zebra.name,)
|
||||||
meta: str = "The config file for this service can be found in the Zebra service."
|
meta: str = "The config file for this service can be found in the Zebra service."
|
||||||
ipv4_routing: bool = False
|
ipv4_routing: bool = False
|
||||||
ipv6_routing: bool = False
|
ipv6_routing: bool = False
|
||||||
|
@ -300,8 +295,8 @@ class Ospfv2(QuaggaService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "OSPFv2"
|
name: str = "OSPFv2"
|
||||||
shutdown: Tuple[str, ...] = ("killall ospfd",)
|
shutdown: tuple[str, ...] = ("killall ospfd",)
|
||||||
validate: Tuple[str, ...] = ("pidof ospfd",)
|
validate: tuple[str, ...] = ("pidof ospfd",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -336,7 +331,7 @@ class Ospfv2(QuaggaService):
|
||||||
def generate_quagga_config(cls, node: CoreNode) -> str:
|
def generate_quagga_config(cls, node: CoreNode) -> str:
|
||||||
cfg = "router ospf\n"
|
cfg = "router ospf\n"
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += " router-id %s\n" % rtrid
|
cfg += f" router-id {rtrid}\n"
|
||||||
# network 10.0.0.0/24 area 0
|
# network 10.0.0.0/24 area 0
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for ip4 in iface.ip4s:
|
for ip4 in iface.ip4s:
|
||||||
|
@ -369,8 +364,8 @@ class Ospfv3(QuaggaService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "OSPFv3"
|
name: str = "OSPFv3"
|
||||||
shutdown: Tuple[str, ...] = ("killall ospf6d",)
|
shutdown: tuple[str, ...] = ("killall ospf6d",)
|
||||||
validate: Tuple[str, ...] = ("pidof ospf6d",)
|
validate: tuple[str, ...] = ("pidof ospf6d",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
|
||||||
|
@ -397,7 +392,7 @@ class Ospfv3(QuaggaService):
|
||||||
"""
|
"""
|
||||||
minmtu = cls.min_mtu(iface)
|
minmtu = cls.min_mtu(iface)
|
||||||
if minmtu < iface.mtu:
|
if minmtu < iface.mtu:
|
||||||
return " ipv6 ospf6 ifmtu %d\n" % minmtu
|
return f" ipv6 ospf6 ifmtu {minmtu:d}\n"
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@ -416,9 +411,9 @@ class Ospfv3(QuaggaService):
|
||||||
cfg = "router ospf6\n"
|
cfg = "router ospf6\n"
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += " instance-id 65\n"
|
cfg += " instance-id 65\n"
|
||||||
cfg += " router-id %s\n" % rtrid
|
cfg += f" router-id {rtrid}\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += " interface %s area 0.0.0.0\n" % iface.name
|
cfg += f" interface {iface.name} area 0.0.0.0\n"
|
||||||
cfg += "!\n"
|
cfg += "!\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -466,8 +461,8 @@ class Bgp(QuaggaService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "BGP"
|
name: str = "BGP"
|
||||||
shutdown: Tuple[str, ...] = ("killall bgpd",)
|
shutdown: tuple[str, ...] = ("killall bgpd",)
|
||||||
validate: Tuple[str, ...] = ("pidof bgpd",)
|
validate: tuple[str, ...] = ("pidof bgpd",)
|
||||||
custom_needed: bool = True
|
custom_needed: bool = True
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
@ -477,9 +472,9 @@ class Bgp(QuaggaService):
|
||||||
cfg = "!\n! BGP configuration\n!\n"
|
cfg = "!\n! BGP configuration\n!\n"
|
||||||
cfg += "! You should configure the AS number below,\n"
|
cfg += "! You should configure the AS number below,\n"
|
||||||
cfg += "! along with this router's peers.\n!\n"
|
cfg += "! along with this router's peers.\n!\n"
|
||||||
cfg += "router bgp %s\n" % node.id
|
cfg += f"router bgp {node.id}\n"
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += " bgp router-id %s\n" % rtrid
|
cfg += f" bgp router-id {rtrid}\n"
|
||||||
cfg += " redistribute connected\n"
|
cfg += " redistribute connected\n"
|
||||||
cfg += "! neighbor 1.2.3.4 remote-as 555\n!\n"
|
cfg += "! neighbor 1.2.3.4 remote-as 555\n!\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
@ -491,8 +486,8 @@ class Rip(QuaggaService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "RIP"
|
name: str = "RIP"
|
||||||
shutdown: Tuple[str, ...] = ("killall ripd",)
|
shutdown: tuple[str, ...] = ("killall ripd",)
|
||||||
validate: Tuple[str, ...] = ("pidof ripd",)
|
validate: tuple[str, ...] = ("pidof ripd",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -514,8 +509,8 @@ class Ripng(QuaggaService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "RIPNG"
|
name: str = "RIPNG"
|
||||||
shutdown: Tuple[str, ...] = ("killall ripngd",)
|
shutdown: tuple[str, ...] = ("killall ripngd",)
|
||||||
validate: Tuple[str, ...] = ("pidof ripngd",)
|
validate: tuple[str, ...] = ("pidof ripngd",)
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -538,15 +533,15 @@ class Babel(QuaggaService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "Babel"
|
name: str = "Babel"
|
||||||
shutdown: Tuple[str, ...] = ("killall babeld",)
|
shutdown: tuple[str, ...] = ("killall babeld",)
|
||||||
validate: Tuple[str, ...] = ("pidof babeld",)
|
validate: tuple[str, ...] = ("pidof babeld",)
|
||||||
ipv6_routing: bool = True
|
ipv6_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_quagga_config(cls, node: CoreNode) -> str:
|
def generate_quagga_config(cls, node: CoreNode) -> str:
|
||||||
cfg = "router babel\n"
|
cfg = "router babel\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += " network %s\n" % iface.name
|
cfg += f" network {iface.name}\n"
|
||||||
cfg += " redistribute static\n redistribute connected\n"
|
cfg += " redistribute static\n redistribute connected\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -564,8 +559,8 @@ class Xpimd(QuaggaService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "Xpimd"
|
name: str = "Xpimd"
|
||||||
shutdown: Tuple[str, ...] = ("killall xpimd",)
|
shutdown: tuple[str, ...] = ("killall xpimd",)
|
||||||
validate: Tuple[str, ...] = ("pidof xpimd",)
|
validate: tuple[str, ...] = ("pidof xpimd",)
|
||||||
ipv4_routing: bool = True
|
ipv4_routing: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -579,8 +574,8 @@ class Xpimd(QuaggaService):
|
||||||
cfg += "router igmp\n!\n"
|
cfg += "router igmp\n!\n"
|
||||||
cfg += "router pim\n"
|
cfg += "router pim\n"
|
||||||
cfg += " !ip pim rp-address 10.0.0.1\n"
|
cfg += " !ip pim rp-address 10.0.0.1\n"
|
||||||
cfg += " ip pim bsr-candidate %s\n" % ifname
|
cfg += f" ip pim bsr-candidate {ifname}\n"
|
||||||
cfg += " ip pim rp-candidate %s\n" % ifname
|
cfg += f" ip pim rp-candidate {ifname}\n"
|
||||||
cfg += " !ip pim spt-threshold interval 10 bytes 80000\n"
|
cfg += " !ip pim spt-threshold interval 10 bytes 80000\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ sdn.py defines services to start Open vSwitch and the Ryu SDN Controller.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
@ -24,15 +23,15 @@ class SdnService(CoreService):
|
||||||
class OvsService(SdnService):
|
class OvsService(SdnService):
|
||||||
name: str = "OvsService"
|
name: str = "OvsService"
|
||||||
group: str = "SDN"
|
group: str = "SDN"
|
||||||
executables: Tuple[str, ...] = ("ovs-ofctl", "ovs-vsctl")
|
executables: tuple[str, ...] = ("ovs-ofctl", "ovs-vsctl")
|
||||||
dirs: Tuple[str, ...] = (
|
dirs: tuple[str, ...] = (
|
||||||
"/etc/openvswitch",
|
"/etc/openvswitch",
|
||||||
"/var/run/openvswitch",
|
"/var/run/openvswitch",
|
||||||
"/var/log/openvswitch",
|
"/var/log/openvswitch",
|
||||||
)
|
)
|
||||||
configs: Tuple[str, ...] = ("OvsService.sh",)
|
configs: tuple[str, ...] = ("OvsService.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash OvsService.sh",)
|
startup: tuple[str, ...] = ("bash OvsService.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall ovs-vswitchd", "killall ovsdb-server")
|
shutdown: tuple[str, ...] = ("killall ovs-vswitchd", "killall ovsdb-server")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -59,39 +58,41 @@ class OvsService(SdnService):
|
||||||
|
|
||||||
# create virtual interfaces
|
# create virtual interfaces
|
||||||
cfg += "## Create a veth pair to send the data to\n"
|
cfg += "## Create a veth pair to send the data to\n"
|
||||||
cfg += "ip link add rtr%s type veth peer name sw%s\n" % (ifnum, ifnum)
|
cfg += f"ip link add rtr{ifnum} type veth peer name sw{ifnum}\n"
|
||||||
|
|
||||||
# remove ip address of eths because quagga/zebra will assign same IPs to rtr interfaces
|
# remove ip address of eths because quagga/zebra will assign same IPs to rtr interfaces
|
||||||
# or assign them manually to rtr interfaces if zebra is not running
|
# or assign them manually to rtr interfaces if zebra is not running
|
||||||
for ip4 in iface.ip4s:
|
for ip4 in iface.ip4s:
|
||||||
cfg += "ip addr del %s dev %s\n" % (ip4.ip, iface.name)
|
cfg += f"ip addr del {ip4.ip} dev {iface.name}\n"
|
||||||
if has_zebra == 0:
|
if has_zebra == 0:
|
||||||
cfg += "ip addr add %s dev rtr%s\n" % (ip4.ip, ifnum)
|
cfg += f"ip addr add {ip4.ip} dev rtr{ifnum}\n"
|
||||||
for ip6 in iface.ip6s:
|
for ip6 in iface.ip6s:
|
||||||
cfg += "ip -6 addr del %s dev %s\n" % (ip6.ip, iface.name)
|
cfg += f"ip -6 addr del {ip6.ip} dev {iface.name}\n"
|
||||||
if has_zebra == 0:
|
if has_zebra == 0:
|
||||||
cfg += "ip -6 addr add %s dev rtr%s\n" % (ip6.ip, ifnum)
|
cfg += f"ip -6 addr add {ip6.ip} dev rtr{ifnum}\n"
|
||||||
|
|
||||||
# add interfaces to bridge
|
# add interfaces to bridge
|
||||||
# Make port numbers explicit so they're easier to follow in reading the script
|
# Make port numbers explicit so they're easier to follow in
|
||||||
|
# reading the script
|
||||||
cfg += "## Add the CORE interface to the switch\n"
|
cfg += "## Add the CORE interface to the switch\n"
|
||||||
cfg += (
|
cfg += (
|
||||||
"ovs-vsctl add-port ovsbr0 eth%s -- set Interface eth%s ofport_request=%d\n"
|
f"ovs-vsctl add-port ovsbr0 eth{ifnum} -- "
|
||||||
% (ifnum, ifnum, portnum)
|
f"set Interface eth{ifnum} ofport_request={portnum:d}\n"
|
||||||
)
|
)
|
||||||
cfg += "## And then add its sibling veth interface\n"
|
cfg += "## And then add its sibling veth interface\n"
|
||||||
cfg += (
|
cfg += (
|
||||||
"ovs-vsctl add-port ovsbr0 sw%s -- set Interface sw%s ofport_request=%d\n"
|
f"ovs-vsctl add-port ovsbr0 sw{ifnum} -- "
|
||||||
% (ifnum, ifnum, portnum + 1)
|
f"set Interface sw{ifnum} ofport_request={portnum + 1:d}\n"
|
||||||
)
|
)
|
||||||
cfg += "## start them up so we can send/receive data\n"
|
cfg += "## start them up so we can send/receive data\n"
|
||||||
cfg += "ovs-ofctl mod-port ovsbr0 eth%s up\n" % ifnum
|
cfg += f"ovs-ofctl mod-port ovsbr0 eth{ifnum} up\n"
|
||||||
cfg += "ovs-ofctl mod-port ovsbr0 sw%s up\n" % ifnum
|
cfg += f"ovs-ofctl mod-port ovsbr0 sw{ifnum} up\n"
|
||||||
cfg += "## Bring up the lower part of the veth pair\n"
|
cfg += "## Bring up the lower part of the veth pair\n"
|
||||||
cfg += "ip link set dev rtr%s up\n" % ifnum
|
cfg += f"ip link set dev rtr{ifnum} up\n"
|
||||||
portnum += 2
|
portnum += 2
|
||||||
|
|
||||||
# Add rule for default controller if there is one local (even if the controller is not local, it finds it)
|
# Add rule for default controller if there is one local
|
||||||
|
# (even if the controller is not local, it finds it)
|
||||||
cfg += "\n## We assume there will be an SDN controller on the other end of this, \n"
|
cfg += "\n## We assume there will be an SDN controller on the other end of this, \n"
|
||||||
cfg += "## but it will still function if there's not\n"
|
cfg += "## but it will still function if there's not\n"
|
||||||
cfg += "ovs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\n"
|
cfg += "ovs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\n"
|
||||||
|
@ -102,14 +103,8 @@ class OvsService(SdnService):
|
||||||
portnum = 1
|
portnum = 1
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "## Take the data from the CORE interface and put it on the veth and vice versa\n"
|
cfg += "## Take the data from the CORE interface and put it on the veth and vice versa\n"
|
||||||
cfg += (
|
cfg += f"ovs-ofctl add-flow ovsbr0 priority=1000,in_port={portnum:d},action=output:{portnum + 1:d}\n"
|
||||||
"ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\n"
|
cfg += f"ovs-ofctl add-flow ovsbr0 priority=1000,in_port={portnum + 1:d},action=output:{portnum:d}\n"
|
||||||
% (portnum, portnum + 1)
|
|
||||||
)
|
|
||||||
cfg += (
|
|
||||||
"ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\n"
|
|
||||||
% (portnum + 1, portnum)
|
|
||||||
)
|
|
||||||
portnum += 2
|
portnum += 2
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -117,10 +112,10 @@ class OvsService(SdnService):
|
||||||
class RyuService(SdnService):
|
class RyuService(SdnService):
|
||||||
name: str = "ryuService"
|
name: str = "ryuService"
|
||||||
group: str = "SDN"
|
group: str = "SDN"
|
||||||
executables: Tuple[str, ...] = ("ryu-manager",)
|
executables: tuple[str, ...] = ("ryu-manager",)
|
||||||
configs: Tuple[str, ...] = ("ryuService.sh",)
|
configs: tuple[str, ...] = ("ryuService.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash ryuService.sh",)
|
startup: tuple[str, ...] = ("bash ryuService.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall ryu-manager",)
|
shutdown: tuple[str, ...] = ("killall ryu-manager",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
|
|
@ -4,7 +4,6 @@ firewall)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from core import constants
|
from core import constants
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
|
@ -17,10 +16,10 @@ logger = logging.getLogger(__name__)
|
||||||
class VPNClient(CoreService):
|
class VPNClient(CoreService):
|
||||||
name: str = "VPNClient"
|
name: str = "VPNClient"
|
||||||
group: str = "Security"
|
group: str = "Security"
|
||||||
configs: Tuple[str, ...] = ("vpnclient.sh",)
|
configs: tuple[str, ...] = ("vpnclient.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash vpnclient.sh",)
|
startup: tuple[str, ...] = ("bash vpnclient.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall openvpn",)
|
shutdown: tuple[str, ...] = ("killall openvpn",)
|
||||||
validate: Tuple[str, ...] = ("pidof openvpn",)
|
validate: tuple[str, ...] = ("pidof openvpn",)
|
||||||
custom_needed: bool = True
|
custom_needed: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -32,9 +31,9 @@ class VPNClient(CoreService):
|
||||||
cfg += "# custom VPN Client configuration for service (security.py)\n"
|
cfg += "# custom VPN Client configuration for service (security.py)\n"
|
||||||
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleVPNClient"
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleVPNClient"
|
||||||
try:
|
try:
|
||||||
with open(fname, "r") as f:
|
with open(fname) as f:
|
||||||
cfg += f.read()
|
cfg += f.read()
|
||||||
except IOError:
|
except OSError:
|
||||||
logger.exception(
|
logger.exception(
|
||||||
"error opening VPN client configuration template (%s)", fname
|
"error opening VPN client configuration template (%s)", fname
|
||||||
)
|
)
|
||||||
|
@ -44,10 +43,10 @@ class VPNClient(CoreService):
|
||||||
class VPNServer(CoreService):
|
class VPNServer(CoreService):
|
||||||
name: str = "VPNServer"
|
name: str = "VPNServer"
|
||||||
group: str = "Security"
|
group: str = "Security"
|
||||||
configs: Tuple[str, ...] = ("vpnserver.sh",)
|
configs: tuple[str, ...] = ("vpnserver.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash vpnserver.sh",)
|
startup: tuple[str, ...] = ("bash vpnserver.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall openvpn",)
|
shutdown: tuple[str, ...] = ("killall openvpn",)
|
||||||
validate: Tuple[str, ...] = ("pidof openvpn",)
|
validate: tuple[str, ...] = ("pidof openvpn",)
|
||||||
custom_needed: bool = True
|
custom_needed: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -60,9 +59,9 @@ class VPNServer(CoreService):
|
||||||
cfg += "# custom VPN Server Configuration for service (security.py)\n"
|
cfg += "# custom VPN Server Configuration for service (security.py)\n"
|
||||||
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleVPNServer"
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleVPNServer"
|
||||||
try:
|
try:
|
||||||
with open(fname, "r") as f:
|
with open(fname) as f:
|
||||||
cfg += f.read()
|
cfg += f.read()
|
||||||
except IOError:
|
except OSError:
|
||||||
logger.exception(
|
logger.exception(
|
||||||
"Error opening VPN server configuration template (%s)", fname
|
"Error opening VPN server configuration template (%s)", fname
|
||||||
)
|
)
|
||||||
|
@ -72,9 +71,9 @@ class VPNServer(CoreService):
|
||||||
class IPsec(CoreService):
|
class IPsec(CoreService):
|
||||||
name: str = "IPsec"
|
name: str = "IPsec"
|
||||||
group: str = "Security"
|
group: str = "Security"
|
||||||
configs: Tuple[str, ...] = ("ipsec.sh",)
|
configs: tuple[str, ...] = ("ipsec.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash ipsec.sh",)
|
startup: tuple[str, ...] = ("bash ipsec.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall racoon",)
|
shutdown: tuple[str, ...] = ("killall racoon",)
|
||||||
custom_needed: bool = True
|
custom_needed: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -88,9 +87,9 @@ class IPsec(CoreService):
|
||||||
cfg += "(security.py)\n"
|
cfg += "(security.py)\n"
|
||||||
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleIPsec"
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleIPsec"
|
||||||
try:
|
try:
|
||||||
with open(fname, "r") as f:
|
with open(fname) as f:
|
||||||
cfg += f.read()
|
cfg += f.read()
|
||||||
except IOError:
|
except OSError:
|
||||||
logger.exception("Error opening IPsec configuration template (%s)", fname)
|
logger.exception("Error opening IPsec configuration template (%s)", fname)
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -98,8 +97,8 @@ class IPsec(CoreService):
|
||||||
class Firewall(CoreService):
|
class Firewall(CoreService):
|
||||||
name: str = "Firewall"
|
name: str = "Firewall"
|
||||||
group: str = "Security"
|
group: str = "Security"
|
||||||
configs: Tuple[str, ...] = ("firewall.sh",)
|
configs: tuple[str, ...] = ("firewall.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash firewall.sh",)
|
startup: tuple[str, ...] = ("bash firewall.sh",)
|
||||||
custom_needed: bool = True
|
custom_needed: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -111,9 +110,9 @@ class Firewall(CoreService):
|
||||||
cfg += "# custom node firewall rules for service (security.py)\n"
|
cfg += "# custom node firewall rules for service (security.py)\n"
|
||||||
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleFirewall"
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleFirewall"
|
||||||
try:
|
try:
|
||||||
with open(fname, "r") as f:
|
with open(fname) as f:
|
||||||
cfg += f.read()
|
cfg += f.read()
|
||||||
except IOError:
|
except OSError:
|
||||||
logger.exception(
|
logger.exception(
|
||||||
"Error opening Firewall configuration template (%s)", fname
|
"Error opening Firewall configuration template (%s)", fname
|
||||||
)
|
)
|
||||||
|
@ -127,9 +126,9 @@ class Nat(CoreService):
|
||||||
|
|
||||||
name: str = "NAT"
|
name: str = "NAT"
|
||||||
group: str = "Security"
|
group: str = "Security"
|
||||||
executables: Tuple[str, ...] = ("iptables",)
|
executables: tuple[str, ...] = ("iptables",)
|
||||||
configs: Tuple[str, ...] = ("nat.sh",)
|
configs: tuple[str, ...] = ("nat.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash nat.sh",)
|
startup: tuple[str, ...] = ("bash nat.sh",)
|
||||||
custom_needed: bool = False
|
custom_needed: bool = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
"""
|
"""
|
||||||
ucarp.py: defines high-availability IP address controlled by ucarp
|
ucarp.py: defines high-availability IP address controlled by ucarp
|
||||||
"""
|
"""
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
@ -12,16 +11,16 @@ UCARP_ETC = "/usr/local/etc/ucarp"
|
||||||
class Ucarp(CoreService):
|
class Ucarp(CoreService):
|
||||||
name: str = "ucarp"
|
name: str = "ucarp"
|
||||||
group: str = "Utility"
|
group: str = "Utility"
|
||||||
dirs: Tuple[str, ...] = (UCARP_ETC,)
|
dirs: tuple[str, ...] = (UCARP_ETC,)
|
||||||
configs: Tuple[str, ...] = (
|
configs: tuple[str, ...] = (
|
||||||
UCARP_ETC + "/default.sh",
|
UCARP_ETC + "/default.sh",
|
||||||
UCARP_ETC + "/default-up.sh",
|
UCARP_ETC + "/default-up.sh",
|
||||||
UCARP_ETC + "/default-down.sh",
|
UCARP_ETC + "/default-down.sh",
|
||||||
"ucarpboot.sh",
|
"ucarpboot.sh",
|
||||||
)
|
)
|
||||||
startup: Tuple[str, ...] = ("bash ucarpboot.sh",)
|
startup: tuple[str, ...] = ("bash ucarpboot.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall ucarp",)
|
shutdown: tuple[str, ...] = ("killall ucarp",)
|
||||||
validate: Tuple[str, ...] = ("pidof ucarp",)
|
validate: tuple[str, ...] = ("pidof ucarp",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -45,13 +44,13 @@ class Ucarp(CoreService):
|
||||||
Returns configuration file text.
|
Returns configuration file text.
|
||||||
"""
|
"""
|
||||||
ucarp_bin = node.session.options.get("ucarp_bin", "/usr/sbin/ucarp")
|
ucarp_bin = node.session.options.get("ucarp_bin", "/usr/sbin/ucarp")
|
||||||
return """\
|
return f"""\
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Location of UCARP executable
|
# Location of UCARP executable
|
||||||
UCARP_EXEC=%s
|
UCARP_EXEC={ucarp_bin}
|
||||||
|
|
||||||
# Location of the UCARP config directory
|
# Location of the UCARP config directory
|
||||||
UCARP_CFGDIR=%s
|
UCARP_CFGDIR={UCARP_ETC}
|
||||||
|
|
||||||
# Logging Facility
|
# Logging Facility
|
||||||
FACILITY=daemon
|
FACILITY=daemon
|
||||||
|
@ -92,40 +91,34 @@ OPTIONS="-z -n -M"
|
||||||
|
|
||||||
# Send extra parameter to down and up scripts
|
# Send extra parameter to down and up scripts
|
||||||
#XPARAM="-x <enter param here>"
|
#XPARAM="-x <enter param here>"
|
||||||
XPARAM="-x ${VIRTUAL_NET}"
|
XPARAM="-x ${{VIRTUAL_NET}}"
|
||||||
|
|
||||||
# The start and stop scripts
|
# The start and stop scripts
|
||||||
START_SCRIPT=${UCARP_CFGDIR}/default-up.sh
|
START_SCRIPT=${{UCARP_CFGDIR}}/default-up.sh
|
||||||
STOP_SCRIPT=${UCARP_CFGDIR}/default-down.sh
|
STOP_SCRIPT=${{UCARP_CFGDIR}}/default-down.sh
|
||||||
|
|
||||||
# These line should not need to be touched
|
# These line should not need to be touched
|
||||||
UCARP_OPTS="$OPTIONS -b $UCARP_BASE -k $SKEW -i $INTERFACE -v $INSTANCE_ID -p $PASSWORD -u $START_SCRIPT -d $STOP_SCRIPT -a $VIRTUAL_ADDRESS -s $SOURCE_ADDRESS -f $FACILITY $XPARAM"
|
UCARP_OPTS="$OPTIONS -b $UCARP_BASE -k $SKEW -i $INTERFACE -v $INSTANCE_ID -p $PASSWORD -u $START_SCRIPT -d $STOP_SCRIPT -a $VIRTUAL_ADDRESS -s $SOURCE_ADDRESS -f $FACILITY $XPARAM"
|
||||||
|
|
||||||
${UCARP_EXEC} -B ${UCARP_OPTS}
|
${{UCARP_EXEC}} -B ${{UCARP_OPTS}}
|
||||||
""" % (
|
"""
|
||||||
ucarp_bin,
|
|
||||||
UCARP_ETC,
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_ucarp_boot(cls, node: CoreNode) -> str:
|
def generate_ucarp_boot(cls, node: CoreNode) -> str:
|
||||||
"""
|
"""
|
||||||
Generate a shell script used to boot the Ucarp daemons.
|
Generate a shell script used to boot the Ucarp daemons.
|
||||||
"""
|
"""
|
||||||
return (
|
return f"""\
|
||||||
"""\
|
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Location of the UCARP config directory
|
# Location of the UCARP config directory
|
||||||
UCARP_CFGDIR=%s
|
UCARP_CFGDIR={UCARP_ETC}
|
||||||
|
|
||||||
chmod a+x ${UCARP_CFGDIR}/*.sh
|
chmod a+x ${{UCARP_CFGDIR}}/*.sh
|
||||||
|
|
||||||
# Start the default ucarp daemon configuration
|
# Start the default ucarp daemon configuration
|
||||||
${UCARP_CFGDIR}/default.sh
|
${{UCARP_CFGDIR}}/default.sh
|
||||||
|
|
||||||
"""
|
"""
|
||||||
% UCARP_ETC
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_vip_up(cls, node: CoreNode) -> str:
|
def generate_vip_up(cls, node: CoreNode) -> str:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
utility.py: defines miscellaneous utility services.
|
utility.py: defines miscellaneous utility services.
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ class UtilService(CoreService):
|
||||||
|
|
||||||
class IPForwardService(UtilService):
|
class IPForwardService(UtilService):
|
||||||
name: str = "IPForward"
|
name: str = "IPForward"
|
||||||
configs: Tuple[str, ...] = ("ipforward.sh",)
|
configs: tuple[str, ...] = ("ipforward.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash ipforward.sh",)
|
startup: tuple[str, ...] = ("bash ipforward.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -36,32 +36,30 @@ class IPForwardService(UtilService):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfiglinux(cls, node: CoreNode, filename: str) -> str:
|
def generateconfiglinux(cls, node: CoreNode, filename: str) -> str:
|
||||||
cfg = """\
|
cfg = f"""\
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# auto-generated by IPForward service (utility.py)
|
# auto-generated by IPForward service (utility.py)
|
||||||
%(sysctl)s -w net.ipv4.conf.all.forwarding=1
|
{SYSCTL} -w net.ipv4.conf.all.forwarding=1
|
||||||
%(sysctl)s -w net.ipv4.conf.default.forwarding=1
|
{SYSCTL} -w net.ipv4.conf.default.forwarding=1
|
||||||
%(sysctl)s -w net.ipv6.conf.all.forwarding=1
|
{SYSCTL} -w net.ipv6.conf.all.forwarding=1
|
||||||
%(sysctl)s -w net.ipv6.conf.default.forwarding=1
|
{SYSCTL} -w net.ipv6.conf.default.forwarding=1
|
||||||
%(sysctl)s -w net.ipv4.conf.all.send_redirects=0
|
{SYSCTL} -w net.ipv4.conf.all.send_redirects=0
|
||||||
%(sysctl)s -w net.ipv4.conf.default.send_redirects=0
|
{SYSCTL} -w net.ipv4.conf.default.send_redirects=0
|
||||||
%(sysctl)s -w net.ipv4.conf.all.rp_filter=0
|
{SYSCTL} -w net.ipv4.conf.all.rp_filter=0
|
||||||
%(sysctl)s -w net.ipv4.conf.default.rp_filter=0
|
{SYSCTL} -w net.ipv4.conf.default.rp_filter=0
|
||||||
""" % {
|
"""
|
||||||
"sysctl": SYSCTL
|
|
||||||
}
|
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
name = utils.sysctl_devname(iface.name)
|
name = utils.sysctl_devname(iface.name)
|
||||||
cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (SYSCTL, name)
|
cfg += f"{SYSCTL} -w net.ipv4.conf.{name}.forwarding=1\n"
|
||||||
cfg += "%s -w net.ipv4.conf.%s.send_redirects=0\n" % (SYSCTL, name)
|
cfg += f"{SYSCTL} -w net.ipv4.conf.{name}.send_redirects=0\n"
|
||||||
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (SYSCTL, name)
|
cfg += f"{SYSCTL} -w net.ipv4.conf.{name}.rp_filter=0\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
class DefaultRouteService(UtilService):
|
class DefaultRouteService(UtilService):
|
||||||
name: str = "DefaultRoute"
|
name: str = "DefaultRoute"
|
||||||
configs: Tuple[str, ...] = ("defaultroute.sh",)
|
configs: tuple[str, ...] = ("defaultroute.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash defaultroute.sh",)
|
startup: tuple[str, ...] = ("bash defaultroute.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -83,8 +81,8 @@ class DefaultRouteService(UtilService):
|
||||||
|
|
||||||
class DefaultMulticastRouteService(UtilService):
|
class DefaultMulticastRouteService(UtilService):
|
||||||
name: str = "DefaultMulticastRoute"
|
name: str = "DefaultMulticastRoute"
|
||||||
configs: Tuple[str, ...] = ("defaultmroute.sh",)
|
configs: tuple[str, ...] = ("defaultmroute.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash defaultmroute.sh",)
|
startup: tuple[str, ...] = ("bash defaultmroute.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -94,7 +92,7 @@ class DefaultMulticastRouteService(UtilService):
|
||||||
cfg += "as needed\n"
|
cfg += "as needed\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
rtcmd = "ip route add 224.0.0.0/4 dev"
|
rtcmd = "ip route add 224.0.0.0/4 dev"
|
||||||
cfg += "%s %s\n" % (rtcmd, iface.name)
|
cfg += f"{rtcmd} {iface.name}\n"
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
break
|
break
|
||||||
return cfg
|
return cfg
|
||||||
|
@ -102,8 +100,8 @@ class DefaultMulticastRouteService(UtilService):
|
||||||
|
|
||||||
class StaticRouteService(UtilService):
|
class StaticRouteService(UtilService):
|
||||||
name: str = "StaticRoute"
|
name: str = "StaticRoute"
|
||||||
configs: Tuple[str, ...] = ("staticroute.sh",)
|
configs: tuple[str, ...] = ("staticroute.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash staticroute.sh",)
|
startup: tuple[str, ...] = ("bash staticroute.sh",)
|
||||||
custom_needed: bool = True
|
custom_needed: bool = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -127,16 +125,16 @@ class StaticRouteService(UtilService):
|
||||||
if ip[-2] == ip[1]:
|
if ip[-2] == ip[1]:
|
||||||
return ""
|
return ""
|
||||||
else:
|
else:
|
||||||
rtcmd = "#/sbin/ip route add %s via" % dst
|
rtcmd = f"#/sbin/ip route add {dst} via"
|
||||||
return "%s %s" % (rtcmd, ip[1])
|
return f"{rtcmd} {ip[1]}"
|
||||||
|
|
||||||
|
|
||||||
class SshService(UtilService):
|
class SshService(UtilService):
|
||||||
name: str = "SSH"
|
name: str = "SSH"
|
||||||
configs: Tuple[str, ...] = ("startsshd.sh", "/etc/ssh/sshd_config")
|
configs: tuple[str, ...] = ("startsshd.sh", "/etc/ssh/sshd_config")
|
||||||
dirs: Tuple[str, ...] = ("/etc/ssh", "/var/run/sshd")
|
dirs: tuple[str, ...] = ("/etc/ssh", "/var/run/sshd")
|
||||||
startup: Tuple[str, ...] = ("bash startsshd.sh",)
|
startup: tuple[str, ...] = ("bash startsshd.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall sshd",)
|
shutdown: tuple[str, ...] = ("killall sshd",)
|
||||||
validation_mode: ServiceMode = ServiceMode.BLOCKING
|
validation_mode: ServiceMode = ServiceMode.BLOCKING
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -149,26 +147,22 @@ class SshService(UtilService):
|
||||||
sshstatedir = cls.dirs[1]
|
sshstatedir = cls.dirs[1]
|
||||||
sshlibdir = "/usr/lib/openssh"
|
sshlibdir = "/usr/lib/openssh"
|
||||||
if filename == "startsshd.sh":
|
if filename == "startsshd.sh":
|
||||||
return """\
|
return f"""\
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# auto-generated by SSH service (utility.py)
|
# auto-generated by SSH service (utility.py)
|
||||||
ssh-keygen -q -t rsa -N "" -f %s/ssh_host_rsa_key
|
ssh-keygen -q -t rsa -N "" -f {sshcfgdir}/ssh_host_rsa_key
|
||||||
chmod 655 %s
|
chmod 655 {sshstatedir}
|
||||||
# wait until RSA host key has been generated to launch sshd
|
# wait until RSA host key has been generated to launch sshd
|
||||||
/usr/sbin/sshd -f %s/sshd_config
|
/usr/sbin/sshd -f {sshcfgdir}/sshd_config
|
||||||
""" % (
|
"""
|
||||||
sshcfgdir,
|
|
||||||
sshstatedir,
|
|
||||||
sshcfgdir,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return """\
|
return f"""\
|
||||||
# auto-generated by SSH service (utility.py)
|
# auto-generated by SSH service (utility.py)
|
||||||
Port 22
|
Port 22
|
||||||
Protocol 2
|
Protocol 2
|
||||||
HostKey %s/ssh_host_rsa_key
|
HostKey {sshcfgdir}/ssh_host_rsa_key
|
||||||
UsePrivilegeSeparation yes
|
UsePrivilegeSeparation yes
|
||||||
PidFile %s/sshd.pid
|
PidFile {sshstatedir}/sshd.pid
|
||||||
|
|
||||||
KeyRegenerationInterval 3600
|
KeyRegenerationInterval 3600
|
||||||
ServerKeyBits 768
|
ServerKeyBits 768
|
||||||
|
@ -197,23 +191,19 @@ PrintLastLog yes
|
||||||
TCPKeepAlive yes
|
TCPKeepAlive yes
|
||||||
|
|
||||||
AcceptEnv LANG LC_*
|
AcceptEnv LANG LC_*
|
||||||
Subsystem sftp %s/sftp-server
|
Subsystem sftp {sshlibdir}/sftp-server
|
||||||
UsePAM yes
|
UsePAM yes
|
||||||
UseDNS no
|
UseDNS no
|
||||||
""" % (
|
"""
|
||||||
sshcfgdir,
|
|
||||||
sshstatedir,
|
|
||||||
sshlibdir,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DhcpService(UtilService):
|
class DhcpService(UtilService):
|
||||||
name: str = "DHCP"
|
name: str = "DHCP"
|
||||||
configs: Tuple[str, ...] = ("/etc/dhcp/dhcpd.conf",)
|
configs: tuple[str, ...] = ("/etc/dhcp/dhcpd.conf",)
|
||||||
dirs: Tuple[str, ...] = ("/etc/dhcp", "/var/lib/dhcp")
|
dirs: tuple[str, ...] = ("/etc/dhcp", "/var/lib/dhcp")
|
||||||
startup: Tuple[str, ...] = ("touch /var/lib/dhcp/dhcpd.leases", "dhcpd")
|
startup: tuple[str, ...] = ("touch /var/lib/dhcp/dhcpd.leases", "dhcpd")
|
||||||
shutdown: Tuple[str, ...] = ("killall dhcpd",)
|
shutdown: tuple[str, ...] = ("killall dhcpd",)
|
||||||
validate: Tuple[str, ...] = ("pidof dhcpd",)
|
validate: tuple[str, ...] = ("pidof dhcpd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -252,21 +242,15 @@ ddns-update-style none;
|
||||||
index = (ip.size - 2) / 2
|
index = (ip.size - 2) / 2
|
||||||
rangelow = ip[index]
|
rangelow = ip[index]
|
||||||
rangehigh = ip[-2]
|
rangehigh = ip[-2]
|
||||||
return """
|
return f"""
|
||||||
subnet %s netmask %s {
|
subnet {ip.cidr.ip} netmask {ip.netmask} {{
|
||||||
pool {
|
pool {{
|
||||||
range %s %s;
|
range {rangelow} {rangehigh};
|
||||||
default-lease-time 600;
|
default-lease-time 600;
|
||||||
option routers %s;
|
option routers {ip.ip};
|
||||||
}
|
}}
|
||||||
}
|
}}
|
||||||
""" % (
|
"""
|
||||||
ip.cidr.ip,
|
|
||||||
ip.netmask,
|
|
||||||
rangelow,
|
|
||||||
rangehigh,
|
|
||||||
ip.ip,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DhcpClientService(UtilService):
|
class DhcpClientService(UtilService):
|
||||||
|
@ -275,10 +259,10 @@ class DhcpClientService(UtilService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "DHCPClient"
|
name: str = "DHCPClient"
|
||||||
configs: Tuple[str, ...] = ("startdhcpclient.sh",)
|
configs: tuple[str, ...] = ("startdhcpclient.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash startdhcpclient.sh",)
|
startup: tuple[str, ...] = ("bash startdhcpclient.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("killall dhclient",)
|
shutdown: tuple[str, ...] = ("killall dhclient",)
|
||||||
validate: Tuple[str, ...] = ("pidof dhclient",)
|
validate: tuple[str, ...] = ("pidof dhclient",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -291,10 +275,10 @@ class DhcpClientService(UtilService):
|
||||||
cfg += "side DNS\n# resolution based on the DHCP server response.\n"
|
cfg += "side DNS\n# resolution based on the DHCP server response.\n"
|
||||||
cfg += "#mkdir -p /var/run/resolvconf/interface\n"
|
cfg += "#mkdir -p /var/run/resolvconf/interface\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "#ln -s /var/run/resolvconf/interface/%s.dhclient" % iface.name
|
cfg += f"#ln -s /var/run/resolvconf/interface/{iface.name}.dhclient"
|
||||||
cfg += " /var/run/resolvconf/resolv.conf\n"
|
cfg += " /var/run/resolvconf/resolv.conf\n"
|
||||||
cfg += "/sbin/dhclient -nw -pf /var/run/dhclient-%s.pid" % iface.name
|
cfg += f"/sbin/dhclient -nw -pf /var/run/dhclient-{iface.name}.pid"
|
||||||
cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (iface.name, iface.name)
|
cfg += f" -lf /var/run/dhclient-{iface.name}.lease {iface.name}\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
|
@ -304,11 +288,11 @@ class FtpService(UtilService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "FTP"
|
name: str = "FTP"
|
||||||
configs: Tuple[str, ...] = ("vsftpd.conf",)
|
configs: tuple[str, ...] = ("vsftpd.conf",)
|
||||||
dirs: Tuple[str, ...] = ("/var/run/vsftpd/empty", "/var/ftp")
|
dirs: tuple[str, ...] = ("/var/run/vsftpd/empty", "/var/ftp")
|
||||||
startup: Tuple[str, ...] = ("vsftpd ./vsftpd.conf",)
|
startup: tuple[str, ...] = ("vsftpd ./vsftpd.conf",)
|
||||||
shutdown: Tuple[str, ...] = ("killall vsftpd",)
|
shutdown: tuple[str, ...] = ("killall vsftpd",)
|
||||||
validate: Tuple[str, ...] = ("pidof vsftpd",)
|
validate: tuple[str, ...] = ("pidof vsftpd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -337,12 +321,12 @@ class HttpService(UtilService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "HTTP"
|
name: str = "HTTP"
|
||||||
configs: Tuple[str, ...] = (
|
configs: tuple[str, ...] = (
|
||||||
"/etc/apache2/apache2.conf",
|
"/etc/apache2/apache2.conf",
|
||||||
"/etc/apache2/envvars",
|
"/etc/apache2/envvars",
|
||||||
"/var/www/index.html",
|
"/var/www/index.html",
|
||||||
)
|
)
|
||||||
dirs: Tuple[str, ...] = (
|
dirs: tuple[str, ...] = (
|
||||||
"/etc/apache2",
|
"/etc/apache2",
|
||||||
"/var/run/apache2",
|
"/var/run/apache2",
|
||||||
"/var/log/apache2",
|
"/var/log/apache2",
|
||||||
|
@ -350,9 +334,9 @@ class HttpService(UtilService):
|
||||||
"/var/lock/apache2",
|
"/var/lock/apache2",
|
||||||
"/var/www",
|
"/var/www",
|
||||||
)
|
)
|
||||||
startup: Tuple[str, ...] = ("chown www-data /var/lock/apache2", "apache2ctl start")
|
startup: tuple[str, ...] = ("chown www-data /var/lock/apache2", "apache2ctl start")
|
||||||
shutdown: Tuple[str, ...] = ("apache2ctl stop",)
|
shutdown: tuple[str, ...] = ("apache2ctl stop",)
|
||||||
validate: Tuple[str, ...] = ("pidof apache2",)
|
validate: tuple[str, ...] = ("pidof apache2",)
|
||||||
APACHEVER22: int = 22
|
APACHEVER22: int = 22
|
||||||
APACHEVER24: int = 24
|
APACHEVER24: int = 24
|
||||||
|
|
||||||
|
@ -538,18 +522,15 @@ export LANG
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generatehtml(cls, node: CoreNode, filename: str) -> str:
|
def generatehtml(cls, node: CoreNode, filename: str) -> str:
|
||||||
body = (
|
body = f"""\
|
||||||
"""\
|
|
||||||
<!-- generated by utility.py:HttpService -->
|
<!-- generated by utility.py:HttpService -->
|
||||||
<h1>%s web server</h1>
|
<h1>{node.name} web server</h1>
|
||||||
<p>This is the default web page for this server.</p>
|
<p>This is the default web page for this server.</p>
|
||||||
<p>The web server software is running but no content has been added, yet.</p>
|
<p>The web server software is running but no content has been added, yet.</p>
|
||||||
"""
|
"""
|
||||||
% node.name
|
|
||||||
)
|
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
body += "<li>%s - %s</li>\n" % (iface.name, [str(x) for x in iface.ips()])
|
body += f"<li>{iface.name} - {[str(x) for x in iface.ips()]}</li>\n"
|
||||||
return "<html><body>%s</body></html>" % body
|
return f"<html><body>{body}</body></html>"
|
||||||
|
|
||||||
|
|
||||||
class PcapService(UtilService):
|
class PcapService(UtilService):
|
||||||
|
@ -558,10 +539,10 @@ class PcapService(UtilService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "pcap"
|
name: str = "pcap"
|
||||||
configs: Tuple[str, ...] = ("pcap.sh",)
|
configs: tuple[str, ...] = ("pcap.sh",)
|
||||||
startup: Tuple[str, ...] = ("bash pcap.sh start",)
|
startup: tuple[str, ...] = ("bash pcap.sh start",)
|
||||||
shutdown: Tuple[str, ...] = ("bash pcap.sh stop",)
|
shutdown: tuple[str, ...] = ("bash pcap.sh stop",)
|
||||||
validate: Tuple[str, ...] = ("pidof tcpdump",)
|
validate: tuple[str, ...] = ("pidof tcpdump",)
|
||||||
meta: str = "logs network traffic to pcap packet capture files"
|
meta: str = "logs network traffic to pcap packet capture files"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -582,11 +563,9 @@ if [ "x$1" = "xstart" ]; then
|
||||||
if iface.control:
|
if iface.control:
|
||||||
cfg += "# "
|
cfg += "# "
|
||||||
redir = "< /dev/null"
|
redir = "< /dev/null"
|
||||||
cfg += "tcpdump ${DUMPOPTS} -w %s.%s.pcap -i %s %s &\n" % (
|
cfg += (
|
||||||
node.name,
|
f"tcpdump ${{DUMPOPTS}} -w {node.name}.{iface.name}.pcap "
|
||||||
iface.name,
|
f"-i {iface.name} {redir} &\n"
|
||||||
iface.name,
|
|
||||||
redir,
|
|
||||||
)
|
)
|
||||||
cfg += """
|
cfg += """
|
||||||
|
|
||||||
|
@ -600,13 +579,13 @@ fi;
|
||||||
|
|
||||||
class RadvdService(UtilService):
|
class RadvdService(UtilService):
|
||||||
name: str = "radvd"
|
name: str = "radvd"
|
||||||
configs: Tuple[str, ...] = ("/etc/radvd/radvd.conf",)
|
configs: tuple[str, ...] = ("/etc/radvd/radvd.conf",)
|
||||||
dirs: Tuple[str, ...] = ("/etc/radvd", "/var/run/radvd")
|
dirs: tuple[str, ...] = ("/etc/radvd", "/var/run/radvd")
|
||||||
startup: Tuple[str, ...] = (
|
startup: tuple[str, ...] = (
|
||||||
"radvd -C /etc/radvd/radvd.conf -m logfile -l /var/log/radvd.log",
|
"radvd -C /etc/radvd/radvd.conf -m logfile -l /var/log/radvd.log",
|
||||||
)
|
)
|
||||||
shutdown: Tuple[str, ...] = ("pkill radvd",)
|
shutdown: tuple[str, ...] = ("pkill radvd",)
|
||||||
validate: Tuple[str, ...] = ("pidof radvd",)
|
validate: tuple[str, ...] = ("pidof radvd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -619,32 +598,26 @@ class RadvdService(UtilService):
|
||||||
prefixes = list(map(cls.subnetentry, iface.ips()))
|
prefixes = list(map(cls.subnetentry, iface.ips()))
|
||||||
if len(prefixes) < 1:
|
if len(prefixes) < 1:
|
||||||
continue
|
continue
|
||||||
cfg += (
|
cfg += f"""\
|
||||||
"""\
|
interface {iface.name}
|
||||||
interface %s
|
{{
|
||||||
{
|
|
||||||
AdvSendAdvert on;
|
AdvSendAdvert on;
|
||||||
MinRtrAdvInterval 3;
|
MinRtrAdvInterval 3;
|
||||||
MaxRtrAdvInterval 10;
|
MaxRtrAdvInterval 10;
|
||||||
AdvDefaultPreference low;
|
AdvDefaultPreference low;
|
||||||
AdvHomeAgentFlag off;
|
AdvHomeAgentFlag off;
|
||||||
"""
|
"""
|
||||||
% iface.name
|
|
||||||
)
|
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
if prefix == "":
|
if prefix == "":
|
||||||
continue
|
continue
|
||||||
cfg += (
|
cfg += f"""\
|
||||||
"""\
|
prefix {prefix}
|
||||||
prefix %s
|
{{
|
||||||
{
|
|
||||||
AdvOnLink on;
|
AdvOnLink on;
|
||||||
AdvAutonomous on;
|
AdvAutonomous on;
|
||||||
AdvRouterAddr on;
|
AdvRouterAddr on;
|
||||||
};
|
}};
|
||||||
"""
|
"""
|
||||||
% prefix
|
|
||||||
)
|
|
||||||
cfg += "};\n"
|
cfg += "};\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -667,10 +640,10 @@ class AtdService(UtilService):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = "atd"
|
name: str = "atd"
|
||||||
configs: Tuple[str, ...] = ("startatd.sh",)
|
configs: tuple[str, ...] = ("startatd.sh",)
|
||||||
dirs: Tuple[str, ...] = ("/var/spool/cron/atjobs", "/var/spool/cron/atspool")
|
dirs: tuple[str, ...] = ("/var/spool/cron/atjobs", "/var/spool/cron/atspool")
|
||||||
startup: Tuple[str, ...] = ("bash startatd.sh",)
|
startup: tuple[str, ...] = ("bash startatd.sh",)
|
||||||
shutdown: Tuple[str, ...] = ("pkill atd",)
|
shutdown: tuple[str, ...] = ("pkill atd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
xorp.py: defines routing services provided by the XORP routing suite.
|
xorp.py: defines routing services provided by the XORP routing suite.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
|
@ -19,15 +19,14 @@ class XorpRtrmgr(CoreService):
|
||||||
|
|
||||||
name: str = "xorp_rtrmgr"
|
name: str = "xorp_rtrmgr"
|
||||||
group: str = "XORP"
|
group: str = "XORP"
|
||||||
executables: Tuple[str, ...] = ("xorp_rtrmgr",)
|
executables: tuple[str, ...] = ("xorp_rtrmgr",)
|
||||||
dirs: Tuple[str, ...] = ("/etc/xorp",)
|
dirs: tuple[str, ...] = ("/etc/xorp",)
|
||||||
configs: Tuple[str, ...] = ("/etc/xorp/config.boot",)
|
configs: tuple[str, ...] = ("/etc/xorp/config.boot",)
|
||||||
startup: Tuple[str, ...] = (
|
startup: tuple[
|
||||||
"xorp_rtrmgr -d -b %s -l /var/log/%s.log -P /var/run/%s.pid"
|
str, ...
|
||||||
% (configs[0], name, name),
|
] = f"xorp_rtrmgr -d -b {configs[0]} -l /var/log/{name}.log -P /var/run/{name}.pid"
|
||||||
)
|
shutdown: tuple[str, ...] = ("killall xorp_rtrmgr",)
|
||||||
shutdown: Tuple[str, ...] = ("killall xorp_rtrmgr",)
|
validate: tuple[str, ...] = ("pidof xorp_rtrmgr",)
|
||||||
validate: Tuple[str, ...] = ("pidof xorp_rtrmgr",)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
||||||
|
@ -38,8 +37,8 @@ class XorpRtrmgr(CoreService):
|
||||||
"""
|
"""
|
||||||
cfg = "interfaces {\n"
|
cfg = "interfaces {\n"
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
cfg += " interface %s {\n" % iface.name
|
cfg += f" interface {iface.name} {{\n"
|
||||||
cfg += "\tvif %s {\n" % iface.name
|
cfg += f"\tvif {iface.name} {{\n"
|
||||||
cfg += "".join(map(cls.addrstr, iface.ips()))
|
cfg += "".join(map(cls.addrstr, iface.ips()))
|
||||||
cfg += cls.lladdrstr(iface)
|
cfg += cls.lladdrstr(iface)
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
@ -59,8 +58,8 @@ class XorpRtrmgr(CoreService):
|
||||||
"""
|
"""
|
||||||
helper for mapping IP addresses to XORP config statements
|
helper for mapping IP addresses to XORP config statements
|
||||||
"""
|
"""
|
||||||
cfg = "\t address %s {\n" % ip.ip
|
cfg = f"\t address {ip.ip} {{\n"
|
||||||
cfg += "\t\tprefix-length: %s\n" % ip.prefixlen
|
cfg += f"\t\tprefix-length: {ip.prefixlen}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -69,7 +68,7 @@ class XorpRtrmgr(CoreService):
|
||||||
"""
|
"""
|
||||||
helper for adding link-local address entries (required by OSPFv3)
|
helper for adding link-local address entries (required by OSPFv3)
|
||||||
"""
|
"""
|
||||||
cfg = "\t address %s {\n" % iface.mac.eui64()
|
cfg = f"\t address {iface.mac.eui64()} {{\n"
|
||||||
cfg += "\t\tprefix-length: 64\n"
|
cfg += "\t\tprefix-length: 64\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
@ -83,8 +82,8 @@ class XorpService(CoreService):
|
||||||
|
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
group: str = "XORP"
|
group: str = "XORP"
|
||||||
executables: Tuple[str, ...] = ("xorp_rtrmgr",)
|
executables: tuple[str, ...] = ("xorp_rtrmgr",)
|
||||||
dependencies: Tuple[str, ...] = ("xorp_rtrmgr",)
|
dependencies: tuple[str, ...] = ("xorp_rtrmgr",)
|
||||||
meta: str = (
|
meta: str = (
|
||||||
"The config file for this service can be found in the xorp_rtrmgr service."
|
"The config file for this service can be found in the xorp_rtrmgr service."
|
||||||
)
|
)
|
||||||
|
@ -95,7 +94,7 @@ class XorpService(CoreService):
|
||||||
Helper to add a forwarding engine entry to the config file.
|
Helper to add a forwarding engine entry to the config file.
|
||||||
"""
|
"""
|
||||||
cfg = "fea {\n"
|
cfg = "fea {\n"
|
||||||
cfg += " %s {\n" % forwarding
|
cfg += f" {forwarding} {{\n"
|
||||||
cfg += "\tdisable:false\n"
|
cfg += "\tdisable:false\n"
|
||||||
cfg += " }\n"
|
cfg += " }\n"
|
||||||
cfg += "}\n"
|
cfg += "}\n"
|
||||||
|
@ -111,10 +110,10 @@ class XorpService(CoreService):
|
||||||
names.append(iface.name)
|
names.append(iface.name)
|
||||||
names.append("register_vif")
|
names.append("register_vif")
|
||||||
cfg = "plumbing {\n"
|
cfg = "plumbing {\n"
|
||||||
cfg += " %s {\n" % forwarding
|
cfg += f" {forwarding} {{\n"
|
||||||
for name in names:
|
for name in names:
|
||||||
cfg += "\tinterface %s {\n" % name
|
cfg += f"\tinterface {name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % name
|
cfg += f"\t vif {name} {{\n"
|
||||||
cfg += "\t\tdisable: false\n"
|
cfg += "\t\tdisable: false\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
@ -173,13 +172,13 @@ class XorpOspfv2(XorpService):
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += "\nprotocols {\n"
|
cfg += "\nprotocols {\n"
|
||||||
cfg += " ospf4 {\n"
|
cfg += " ospf4 {\n"
|
||||||
cfg += "\trouter-id: %s\n" % rtrid
|
cfg += f"\trouter-id: {rtrid}\n"
|
||||||
cfg += "\tarea 0.0.0.0 {\n"
|
cfg += "\tarea 0.0.0.0 {\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\t interface %s {\n" % iface.name
|
cfg += f"\t interface {iface.name} {{\n"
|
||||||
cfg += "\t\tvif %s {\n" % iface.name
|
cfg += f"\t\tvif {iface.name} {{\n"
|
||||||
for ip4 in iface.ip4s:
|
for ip4 in iface.ip4s:
|
||||||
cfg += "\t\t address %s {\n" % ip4.ip
|
cfg += f"\t\t address {ip4.ip} {{\n"
|
||||||
cfg += "\t\t }\n"
|
cfg += "\t\t }\n"
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
|
@ -204,11 +203,11 @@ class XorpOspfv3(XorpService):
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += "\nprotocols {\n"
|
cfg += "\nprotocols {\n"
|
||||||
cfg += " ospf6 0 { /* Instance ID 0 */\n"
|
cfg += " ospf6 0 { /* Instance ID 0 */\n"
|
||||||
cfg += "\trouter-id: %s\n" % rtrid
|
cfg += f"\trouter-id: {rtrid}\n"
|
||||||
cfg += "\tarea 0.0.0.0 {\n"
|
cfg += "\tarea 0.0.0.0 {\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\t interface %s {\n" % iface.name
|
cfg += f"\t interface {iface.name} {{\n"
|
||||||
cfg += "\t\tvif %s {\n" % iface.name
|
cfg += f"\t\tvif {iface.name} {{\n"
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
@ -234,7 +233,7 @@ class XorpBgp(XorpService):
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += "\nprotocols {\n"
|
cfg += "\nprotocols {\n"
|
||||||
cfg += " bgp {\n"
|
cfg += " bgp {\n"
|
||||||
cfg += "\tbgp-id: %s\n" % rtrid
|
cfg += f"\tbgp-id: {rtrid}\n"
|
||||||
cfg += "\tlocal-as: 65001 /* change this */\n"
|
cfg += "\tlocal-as: 65001 /* change this */\n"
|
||||||
cfg += '\texport: "export-connected"\n'
|
cfg += '\texport: "export-connected"\n'
|
||||||
cfg += "\tpeer 10.0.1.1 { /* change this */\n"
|
cfg += "\tpeer 10.0.1.1 { /* change this */\n"
|
||||||
|
@ -262,10 +261,10 @@ class XorpRip(XorpService):
|
||||||
cfg += " rip {\n"
|
cfg += " rip {\n"
|
||||||
cfg += '\texport: "export-connected"\n'
|
cfg += '\texport: "export-connected"\n'
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\tinterface %s {\n" % iface.name
|
cfg += f"\tinterface {iface.name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % iface.name
|
cfg += f"\t vif {iface.name} {{\n"
|
||||||
for ip4 in iface.ip4s:
|
for ip4 in iface.ip4s:
|
||||||
cfg += "\t\taddress %s {\n" % ip4.ip
|
cfg += f"\t\taddress {ip4.ip} {{\n"
|
||||||
cfg += "\t\t disable: false\n"
|
cfg += "\t\t disable: false\n"
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
|
@ -290,9 +289,9 @@ class XorpRipng(XorpService):
|
||||||
cfg += " ripng {\n"
|
cfg += " ripng {\n"
|
||||||
cfg += '\texport: "export-connected"\n'
|
cfg += '\texport: "export-connected"\n'
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\tinterface %s {\n" % iface.name
|
cfg += f"\tinterface {iface.name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % iface.name
|
cfg += f"\t vif {iface.name} {{\n"
|
||||||
cfg += "\t\taddress %s {\n" % iface.mac.eui64()
|
cfg += f"\t\taddress {iface.mac.eui64()} {{\n"
|
||||||
cfg += "\t\t disable: false\n"
|
cfg += "\t\t disable: false\n"
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
|
@ -317,8 +316,8 @@ class XorpPimSm4(XorpService):
|
||||||
names = []
|
names = []
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
names.append(iface.name)
|
names.append(iface.name)
|
||||||
cfg += "\tinterface %s {\n" % iface.name
|
cfg += f"\tinterface {iface.name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % iface.name
|
cfg += f"\t vif {iface.name} {{\n"
|
||||||
cfg += "\t\tdisable: false\n"
|
cfg += "\t\tdisable: false\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
@ -329,20 +328,20 @@ class XorpPimSm4(XorpService):
|
||||||
|
|
||||||
names.append("register_vif")
|
names.append("register_vif")
|
||||||
for name in names:
|
for name in names:
|
||||||
cfg += "\tinterface %s {\n" % name
|
cfg += f"\tinterface {name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % name
|
cfg += f"\t vif {name} {{\n"
|
||||||
cfg += "\t\tdr-priority: 1\n"
|
cfg += "\t\tdr-priority: 1\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
cfg += "\tbootstrap {\n"
|
cfg += "\tbootstrap {\n"
|
||||||
cfg += "\t cand-bsr {\n"
|
cfg += "\t cand-bsr {\n"
|
||||||
cfg += "\t\tscope-zone 224.0.0.0/4 {\n"
|
cfg += "\t\tscope-zone 224.0.0.0/4 {\n"
|
||||||
cfg += '\t\t cand-bsr-by-vif-name: "%s"\n' % names[0]
|
cfg += f'\t\t cand-bsr-by-vif-name: "{names[0]}"\n'
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t cand-rp {\n"
|
cfg += "\t cand-rp {\n"
|
||||||
cfg += "\t\tgroup-prefix 224.0.0.0/4 {\n"
|
cfg += "\t\tgroup-prefix 224.0.0.0/4 {\n"
|
||||||
cfg += '\t\t cand-rp-by-vif-name: "%s"\n' % names[0]
|
cfg += f'\t\t cand-rp-by-vif-name: "{names[0]}"\n'
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
@ -371,8 +370,8 @@ class XorpPimSm6(XorpService):
|
||||||
names = []
|
names = []
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
names.append(iface.name)
|
names.append(iface.name)
|
||||||
cfg += "\tinterface %s {\n" % iface.name
|
cfg += f"\tinterface {iface.name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % iface.name
|
cfg += f"\t vif {iface.name} {{\n"
|
||||||
cfg += "\t\tdisable: false\n"
|
cfg += "\t\tdisable: false\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
@ -383,20 +382,20 @@ class XorpPimSm6(XorpService):
|
||||||
|
|
||||||
names.append("register_vif")
|
names.append("register_vif")
|
||||||
for name in names:
|
for name in names:
|
||||||
cfg += "\tinterface %s {\n" % name
|
cfg += f"\tinterface {name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % name
|
cfg += f"\t vif {name} {{\n"
|
||||||
cfg += "\t\tdr-priority: 1\n"
|
cfg += "\t\tdr-priority: 1\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
cfg += "\tbootstrap {\n"
|
cfg += "\tbootstrap {\n"
|
||||||
cfg += "\t cand-bsr {\n"
|
cfg += "\t cand-bsr {\n"
|
||||||
cfg += "\t\tscope-zone ff00::/8 {\n"
|
cfg += "\t\tscope-zone ff00::/8 {\n"
|
||||||
cfg += '\t\t cand-bsr-by-vif-name: "%s"\n' % names[0]
|
cfg += f'\t\t cand-bsr-by-vif-name: "{names[0]}"\n'
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t cand-rp {\n"
|
cfg += "\t cand-rp {\n"
|
||||||
cfg += "\t\tgroup-prefix ff00::/8 {\n"
|
cfg += "\t\tgroup-prefix ff00::/8 {\n"
|
||||||
cfg += '\t\t cand-rp-by-vif-name: "%s"\n' % names[0]
|
cfg += f'\t\t cand-rp-by-vif-name: "{names[0]}"\n'
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
@ -423,12 +422,12 @@ class XorpOlsr(XorpService):
|
||||||
rtrid = cls.router_id(node)
|
rtrid = cls.router_id(node)
|
||||||
cfg += "\nprotocols {\n"
|
cfg += "\nprotocols {\n"
|
||||||
cfg += " olsr4 {\n"
|
cfg += " olsr4 {\n"
|
||||||
cfg += "\tmain-address: %s\n" % rtrid
|
cfg += f"\tmain-address: {rtrid}\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\tinterface %s {\n" % iface.name
|
cfg += f"\tinterface {iface.name} {{\n"
|
||||||
cfg += "\t vif %s {\n" % iface.name
|
cfg += f"\t vif {iface.name} {{\n"
|
||||||
for ip4 in iface.ip4s:
|
for ip4 in iface.ip4s:
|
||||||
cfg += "\t\taddress %s {\n" % ip4.ip
|
cfg += f"\t\taddress {ip4.ip} {{\n"
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
|
Loading…
Add table
Reference in a new issue