Merge pull request #476 from coreemu/cleanup/executables
Cleanup/executables
This commit is contained in:
commit
29a69e8b40
14 changed files with 117 additions and 99 deletions
2
.github/workflows/daemon-checks.yml
vendored
2
.github/workflows/daemon-checks.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
||||||
cd daemon
|
cd daemon
|
||||||
cp setup.py.in setup.py
|
cp setup.py.in setup.py
|
||||||
cp core/constants.py.in core/constants.py
|
cp core/constants.py.in core/constants.py
|
||||||
sed -i 's/True/False/g' core/constants.py
|
sed -i 's/required=True/required=False/g' core/emulator/coreemu.py
|
||||||
pipenv sync --dev
|
pipenv sync --dev
|
||||||
- name: isort
|
- name: isort
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -52,10 +52,8 @@ class ConfigServiceManager:
|
||||||
for executable in service.executables:
|
for executable in service.executables:
|
||||||
try:
|
try:
|
||||||
utils.which(executable, required=True)
|
utils.which(executable, required=True)
|
||||||
except ValueError:
|
except CoreError as e:
|
||||||
raise CoreError(
|
raise CoreError(f"config service({service.name}): {e}")
|
||||||
f"service({service.name}) missing executable {executable}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# make service available
|
# make service available
|
||||||
self.services[name] = service
|
self.services[name] = service
|
||||||
|
|
|
@ -1,17 +1,3 @@
|
||||||
from core.utils import which
|
|
||||||
|
|
||||||
COREDPY_VERSION = "@PACKAGE_VERSION@"
|
COREDPY_VERSION = "@PACKAGE_VERSION@"
|
||||||
CORE_CONF_DIR = "@CORE_CONF_DIR@"
|
CORE_CONF_DIR = "@CORE_CONF_DIR@"
|
||||||
CORE_DATA_DIR = "@CORE_DATA_DIR@"
|
CORE_DATA_DIR = "@CORE_DATA_DIR@"
|
||||||
|
|
||||||
VNODED_BIN = which("vnoded", required=True)
|
|
||||||
VCMD_BIN = which("vcmd", required=True)
|
|
||||||
SYSCTL_BIN = which("sysctl", required=True)
|
|
||||||
IP_BIN = which("ip", required=True)
|
|
||||||
ETHTOOL_BIN = which("ethtool", required=True)
|
|
||||||
TC_BIN = which("tc", required=True)
|
|
||||||
EBTABLES_BIN = which("ebtables", required=True)
|
|
||||||
MOUNT_BIN = which("mount", required=True)
|
|
||||||
UMOUNT_BIN = which("umount", required=True)
|
|
||||||
OVS_BIN = which("ovs-vsctl", required=False)
|
|
||||||
OVS_FLOW_BIN = which("ovs-ofctl", required=False)
|
|
||||||
|
|
|
@ -6,9 +6,10 @@ import sys
|
||||||
from typing import Dict, List, Type
|
from typing import Dict, List, Type
|
||||||
|
|
||||||
import core.services
|
import core.services
|
||||||
from core import configservices
|
from core import configservices, utils
|
||||||
from core.configservice.manager import ConfigServiceManager
|
from core.configservice.manager import ConfigServiceManager
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
|
from core.executables import COMMON_REQUIREMENTS, OVS_REQUIREMENTS, VCMD_REQUIREMENTS
|
||||||
from core.services.coreservices import ServiceManager
|
from core.services.coreservices import ServiceManager
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,10 +66,34 @@ class CoreEmu:
|
||||||
if custom_dir:
|
if custom_dir:
|
||||||
self.service_manager.load(custom_dir)
|
self.service_manager.load(custom_dir)
|
||||||
|
|
||||||
|
# check executables exist on path
|
||||||
|
self._validate_env()
|
||||||
|
|
||||||
# catch exit event
|
# catch exit event
|
||||||
atexit.register(self.shutdown)
|
atexit.register(self.shutdown)
|
||||||
|
|
||||||
|
def _validate_env(self) -> None:
|
||||||
|
"""
|
||||||
|
Validates executables CORE depends on exist on path.
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
:raises core.errors.CoreError: when an executable does not exist on path
|
||||||
|
"""
|
||||||
|
requirements = COMMON_REQUIREMENTS
|
||||||
|
use_ovs = self.config.get("ovs") == "True"
|
||||||
|
if use_ovs:
|
||||||
|
requirements += OVS_REQUIREMENTS
|
||||||
|
else:
|
||||||
|
requirements += VCMD_REQUIREMENTS
|
||||||
|
for requirement in requirements:
|
||||||
|
utils.which(requirement, required=True)
|
||||||
|
|
||||||
def load_services(self) -> None:
|
def load_services(self) -> None:
|
||||||
|
"""
|
||||||
|
Loads default and custom services for use within CORE.
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
# load default services
|
# load default services
|
||||||
self.service_errors = core.services.load()
|
self.service_errors = core.services.load()
|
||||||
|
|
||||||
|
|
16
daemon/core/executables.py
Normal file
16
daemon/core/executables.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
VNODED: str = "vnoded"
|
||||||
|
VCMD: str = "vcmd"
|
||||||
|
SYSCTL: str = "sysctl"
|
||||||
|
IP: str = "ip"
|
||||||
|
ETHTOOL: str = "ethtool"
|
||||||
|
TC: str = "tc"
|
||||||
|
EBTABLES: str = "ebtables"
|
||||||
|
MOUNT: str = "mount"
|
||||||
|
UMOUNT: str = "umount"
|
||||||
|
OVS_VSCTL: str = "ovs-vsctl"
|
||||||
|
|
||||||
|
COMMON_REQUIREMENTS: List[str] = [SYSCTL, IP, ETHTOOL, TC, EBTABLES, MOUNT, UMOUNT]
|
||||||
|
VCMD_REQUIREMENTS: List[str] = [VNODED, VCMD]
|
||||||
|
OVS_REQUIREMENTS: List[str] = [OVS_VSCTL]
|
|
@ -13,10 +13,10 @@ import netaddr
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.configservice.dependencies import ConfigServiceDependencies
|
from core.configservice.dependencies import ConfigServiceDependencies
|
||||||
from core.constants import MOUNT_BIN, VNODED_BIN
|
|
||||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
||||||
from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes
|
from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
|
from core.executables import MOUNT, VNODED
|
||||||
from core.nodes.client import VnodeClient
|
from core.nodes.client import VnodeClient
|
||||||
from core.nodes.interface import CoreInterface, TunTap, Veth
|
from core.nodes.interface import CoreInterface, TunTap, Veth
|
||||||
from core.nodes.netclient import LinuxNetClient, get_net_client
|
from core.nodes.netclient import LinuxNetClient, get_net_client
|
||||||
|
@ -511,7 +511,7 @@ class CoreNode(CoreNodeBase):
|
||||||
|
|
||||||
# create a new namespace for this node using vnoded
|
# create a new namespace for this node using vnoded
|
||||||
vnoded = (
|
vnoded = (
|
||||||
f"{VNODED_BIN} -v -c {self.ctrlchnlname} -l {self.ctrlchnlname}.log "
|
f"{VNODED} -v -c {self.ctrlchnlname} -l {self.ctrlchnlname}.log "
|
||||||
f"-p {self.ctrlchnlname}.pid"
|
f"-p {self.ctrlchnlname}.pid"
|
||||||
)
|
)
|
||||||
if self.nodedir:
|
if self.nodedir:
|
||||||
|
@ -640,7 +640,7 @@ class CoreNode(CoreNodeBase):
|
||||||
source = os.path.abspath(source)
|
source = os.path.abspath(source)
|
||||||
logging.debug("node(%s) mounting: %s at %s", self.name, source, target)
|
logging.debug("node(%s) mounting: %s at %s", self.name, source, target)
|
||||||
self.cmd(f"mkdir -p {target}")
|
self.cmd(f"mkdir -p {target}")
|
||||||
self.cmd(f"{MOUNT_BIN} -n --bind {source} {target}")
|
self.cmd(f"{MOUNT} -n --bind {source} {target}")
|
||||||
self._mounts.append((source, target))
|
self._mounts.append((source, target))
|
||||||
|
|
||||||
def next_iface_id(self) -> int:
|
def next_iface_id(self) -> int:
|
||||||
|
@ -753,7 +753,7 @@ class CoreNode(CoreNodeBase):
|
||||||
iface = self.get_iface(iface_id)
|
iface = self.get_iface(iface_id)
|
||||||
iface.set_mac(mac)
|
iface.set_mac(mac)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.node_net_client.device_mac(iface.name, mac)
|
self.node_net_client.device_mac(iface.name, str(iface.mac))
|
||||||
|
|
||||||
def add_ip(self, iface_id: int, ip: str) -> None:
|
def add_ip(self, iface_id: int, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,7 +5,7 @@ The control channel can be accessed via calls using the vcmd shell.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.constants import VCMD_BIN
|
from core.executables import VCMD
|
||||||
|
|
||||||
|
|
||||||
class VnodeClient:
|
class VnodeClient:
|
||||||
|
@ -50,7 +50,7 @@ class VnodeClient:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def create_cmd(self, args: str) -> str:
|
def create_cmd(self, args: str) -> str:
|
||||||
return f"{VCMD_BIN} -c {self.ctrlchnlname} -- {args}"
|
return f"{VCMD} -c {self.ctrlchnlname} -- {args}"
|
||||||
|
|
||||||
def check_cmd(self, args: str, wait: bool = True, shell: bool = False) -> str:
|
def check_cmd(self, args: str, wait: bool = True, shell: bool = False) -> str:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import Callable
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
from core.constants import ETHTOOL_BIN, IP_BIN, OVS_BIN, SYSCTL_BIN, TC_BIN
|
from core.executables import ETHTOOL, IP, OVS_VSCTL, SYSCTL, TC
|
||||||
|
|
||||||
|
|
||||||
class LinuxNetClient:
|
class LinuxNetClient:
|
||||||
|
@ -38,7 +38,7 @@ class LinuxNetClient:
|
||||||
:param device: device to add route to
|
:param device: device to add route to
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} route add {route} dev {device}")
|
self.run(f"{IP} route add {route} dev {device}")
|
||||||
|
|
||||||
def device_up(self, device: str) -> None:
|
def device_up(self, device: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -47,7 +47,7 @@ class LinuxNetClient:
|
||||||
:param device: device to bring up
|
:param device: device to bring up
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set {device} up")
|
self.run(f"{IP} link set {device} up")
|
||||||
|
|
||||||
def device_down(self, device: str) -> None:
|
def device_down(self, device: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -56,7 +56,7 @@ class LinuxNetClient:
|
||||||
:param device: device to bring down
|
:param device: device to bring down
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set {device} down")
|
self.run(f"{IP} link set {device} down")
|
||||||
|
|
||||||
def device_name(self, device: str, name: str) -> None:
|
def device_name(self, device: str, name: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -66,7 +66,7 @@ class LinuxNetClient:
|
||||||
:param name: name to set
|
:param name: name to set
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set {device} name {name}")
|
self.run(f"{IP} link set {device} name {name}")
|
||||||
|
|
||||||
def device_show(self, device: str) -> str:
|
def device_show(self, device: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -75,7 +75,7 @@ class LinuxNetClient:
|
||||||
:param device: device to get information for
|
:param device: device to get information for
|
||||||
:return: device information
|
:return: device information
|
||||||
"""
|
"""
|
||||||
return self.run(f"{IP_BIN} link show {device}")
|
return self.run(f"{IP} link show {device}")
|
||||||
|
|
||||||
def address_show(self, device: str) -> str:
|
def address_show(self, device: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -84,7 +84,7 @@ class LinuxNetClient:
|
||||||
:param device: device name
|
:param device: device name
|
||||||
:return: address information
|
:return: address information
|
||||||
"""
|
"""
|
||||||
return self.run(f"{IP_BIN} address show {device}")
|
return self.run(f"{IP} address show {device}")
|
||||||
|
|
||||||
def get_mac(self, device: str) -> str:
|
def get_mac(self, device: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -112,7 +112,7 @@ class LinuxNetClient:
|
||||||
:param namespace: namespace to set device to
|
:param namespace: namespace to set device to
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set {device} netns {namespace}")
|
self.run(f"{IP} link set {device} netns {namespace}")
|
||||||
|
|
||||||
def device_flush(self, device: str) -> None:
|
def device_flush(self, device: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -123,7 +123,7 @@ class LinuxNetClient:
|
||||||
"""
|
"""
|
||||||
self.run(
|
self.run(
|
||||||
f"[ -e /sys/class/net/{device} ] && "
|
f"[ -e /sys/class/net/{device} ] && "
|
||||||
f"{IP_BIN} address flush dev {device} || true",
|
f"{IP} address flush dev {device} || true",
|
||||||
shell=True,
|
shell=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ class LinuxNetClient:
|
||||||
:param mac: mac to set
|
:param mac: mac to set
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set dev {device} address {mac}")
|
self.run(f"{IP} link set dev {device} address {mac}")
|
||||||
|
|
||||||
def delete_device(self, device: str) -> None:
|
def delete_device(self, device: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -144,7 +144,7 @@ class LinuxNetClient:
|
||||||
:param device: device to delete
|
:param device: device to delete
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link delete {device}")
|
self.run(f"{IP} link delete {device}")
|
||||||
|
|
||||||
def delete_tc(self, device: str) -> None:
|
def delete_tc(self, device: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -153,7 +153,7 @@ class LinuxNetClient:
|
||||||
:param device: device to remove tc
|
:param device: device to remove tc
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{TC_BIN} qdisc delete dev {device} root")
|
self.run(f"{TC} qdisc delete dev {device} root")
|
||||||
|
|
||||||
def checksums_off(self, iface_name: str) -> None:
|
def checksums_off(self, iface_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -162,7 +162,7 @@ class LinuxNetClient:
|
||||||
:param iface_name: interface to update
|
:param iface_name: interface to update
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{ETHTOOL_BIN} -K {iface_name} rx off tx off")
|
self.run(f"{ETHTOOL} -K {iface_name} rx off tx off")
|
||||||
|
|
||||||
def create_address(self, device: str, address: str, broadcast: str = None) -> None:
|
def create_address(self, device: str, address: str, broadcast: str = None) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -174,15 +174,13 @@ class LinuxNetClient:
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
if broadcast is not None:
|
if broadcast is not None:
|
||||||
self.run(
|
self.run(f"{IP} address add {address} broadcast {broadcast} dev {device}")
|
||||||
f"{IP_BIN} address add {address} broadcast {broadcast} dev {device}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self.run(f"{IP_BIN} address add {address} dev {device}")
|
self.run(f"{IP} address add {address} dev {device}")
|
||||||
if netaddr.valid_ipv6(address.split("/")[0]):
|
if netaddr.valid_ipv6(address.split("/")[0]):
|
||||||
# IPv6 addresses are removed by default on interface down.
|
# IPv6 addresses are removed by default on interface down.
|
||||||
# Make sure that the IPv6 address we add is not removed
|
# Make sure that the IPv6 address we add is not removed
|
||||||
self.run(f"{SYSCTL_BIN} -w net.ipv6.conf.{device}.keep_addr_on_down=1")
|
self.run(f"{SYSCTL} -w net.ipv6.conf.{device}.keep_addr_on_down=1")
|
||||||
|
|
||||||
def delete_address(self, device: str, address: str) -> None:
|
def delete_address(self, device: str, address: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -192,7 +190,7 @@ class LinuxNetClient:
|
||||||
:param address: address to remove
|
:param address: address to remove
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} address delete {address} dev {device}")
|
self.run(f"{IP} address delete {address} dev {device}")
|
||||||
|
|
||||||
def create_veth(self, name: str, peer: str) -> None:
|
def create_veth(self, name: str, peer: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -202,7 +200,7 @@ class LinuxNetClient:
|
||||||
:param peer: peer name
|
:param peer: peer name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link add name {name} type veth peer name {peer}")
|
self.run(f"{IP} link add name {name} type veth peer name {peer}")
|
||||||
|
|
||||||
def create_gretap(
|
def create_gretap(
|
||||||
self, device: str, address: str, local: str, ttl: int, key: int
|
self, device: str, address: str, local: str, ttl: int, key: int
|
||||||
|
@ -217,7 +215,7 @@ class LinuxNetClient:
|
||||||
:param key: key for tap
|
:param key: key for tap
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
cmd = f"{IP_BIN} link add {device} type gretap remote {address}"
|
cmd = f"{IP} link add {device} type gretap remote {address}"
|
||||||
if local is not None:
|
if local is not None:
|
||||||
cmd += f" local {local}"
|
cmd += f" local {local}"
|
||||||
if ttl is not None:
|
if ttl is not None:
|
||||||
|
@ -233,11 +231,11 @@ class LinuxNetClient:
|
||||||
:param name: bridge name
|
:param name: bridge name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link add name {name} type bridge")
|
self.run(f"{IP} link add name {name} type bridge")
|
||||||
self.run(f"{IP_BIN} link set {name} type bridge stp_state 0")
|
self.run(f"{IP} link set {name} type bridge stp_state 0")
|
||||||
self.run(f"{IP_BIN} link set {name} type bridge forward_delay 0")
|
self.run(f"{IP} link set {name} type bridge forward_delay 0")
|
||||||
self.run(f"{IP_BIN} link set {name} type bridge mcast_snooping 0")
|
self.run(f"{IP} link set {name} type bridge mcast_snooping 0")
|
||||||
self.run(f"{IP_BIN} link set {name} type bridge group_fwd_mask 65528")
|
self.run(f"{IP} link set {name} type bridge group_fwd_mask 65528")
|
||||||
self.device_up(name)
|
self.device_up(name)
|
||||||
|
|
||||||
def delete_bridge(self, name: str) -> None:
|
def delete_bridge(self, name: str) -> None:
|
||||||
|
@ -248,7 +246,7 @@ class LinuxNetClient:
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.device_down(name)
|
self.device_down(name)
|
||||||
self.run(f"{IP_BIN} link delete {name} type bridge")
|
self.run(f"{IP} link delete {name} type bridge")
|
||||||
|
|
||||||
def set_iface_master(self, bridge_name: str, iface_name: str) -> None:
|
def set_iface_master(self, bridge_name: str, iface_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -258,7 +256,7 @@ class LinuxNetClient:
|
||||||
:param iface_name: interface name
|
:param iface_name: interface name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set dev {iface_name} master {bridge_name}")
|
self.run(f"{IP} link set dev {iface_name} master {bridge_name}")
|
||||||
self.device_up(iface_name)
|
self.device_up(iface_name)
|
||||||
|
|
||||||
def delete_iface(self, bridge_name: str, iface_name: str) -> None:
|
def delete_iface(self, bridge_name: str, iface_name: str) -> None:
|
||||||
|
@ -269,7 +267,7 @@ class LinuxNetClient:
|
||||||
:param iface_name: interface name
|
:param iface_name: interface name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set dev {iface_name} nomaster")
|
self.run(f"{IP} link set dev {iface_name} nomaster")
|
||||||
|
|
||||||
def existing_bridges(self, _id: int) -> bool:
|
def existing_bridges(self, _id: int) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -278,7 +276,7 @@ class LinuxNetClient:
|
||||||
:param _id: node id to check bridges for
|
:param _id: node id to check bridges for
|
||||||
:return: True if there are existing bridges, False otherwise
|
:return: True if there are existing bridges, False otherwise
|
||||||
"""
|
"""
|
||||||
output = self.run(f"{IP_BIN} -o link show type bridge")
|
output = self.run(f"{IP} -o link show type bridge")
|
||||||
lines = output.split("\n")
|
lines = output.split("\n")
|
||||||
for line in lines:
|
for line in lines:
|
||||||
values = line.split(":")
|
values = line.split(":")
|
||||||
|
@ -299,7 +297,7 @@ class LinuxNetClient:
|
||||||
:param name: bridge name
|
:param name: bridge name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{IP_BIN} link set {name} type bridge ageing_time 0")
|
self.run(f"{IP} link set {name} type bridge ageing_time 0")
|
||||||
|
|
||||||
|
|
||||||
class OvsNetClient(LinuxNetClient):
|
class OvsNetClient(LinuxNetClient):
|
||||||
|
@ -314,10 +312,10 @@ class OvsNetClient(LinuxNetClient):
|
||||||
:param name: bridge name
|
:param name: bridge name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{OVS_BIN} add-br {name}")
|
self.run(f"{OVS_VSCTL} add-br {name}")
|
||||||
self.run(f"{OVS_BIN} set bridge {name} stp_enable=false")
|
self.run(f"{OVS_VSCTL} set bridge {name} stp_enable=false")
|
||||||
self.run(f"{OVS_BIN} set bridge {name} other_config:stp-max-age=6")
|
self.run(f"{OVS_VSCTL} set bridge {name} other_config:stp-max-age=6")
|
||||||
self.run(f"{OVS_BIN} set bridge {name} other_config:stp-forward-delay=4")
|
self.run(f"{OVS_VSCTL} set bridge {name} other_config:stp-forward-delay=4")
|
||||||
self.device_up(name)
|
self.device_up(name)
|
||||||
|
|
||||||
def delete_bridge(self, name: str) -> None:
|
def delete_bridge(self, name: str) -> None:
|
||||||
|
@ -328,7 +326,7 @@ class OvsNetClient(LinuxNetClient):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.device_down(name)
|
self.device_down(name)
|
||||||
self.run(f"{OVS_BIN} del-br {name}")
|
self.run(f"{OVS_VSCTL} del-br {name}")
|
||||||
|
|
||||||
def set_iface_master(self, bridge_name: str, iface_name: str) -> None:
|
def set_iface_master(self, bridge_name: str, iface_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -338,7 +336,7 @@ class OvsNetClient(LinuxNetClient):
|
||||||
:param iface_name: interface name
|
:param iface_name: interface name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{OVS_BIN} add-port {bridge_name} {iface_name}")
|
self.run(f"{OVS_VSCTL} add-port {bridge_name} {iface_name}")
|
||||||
self.device_up(iface_name)
|
self.device_up(iface_name)
|
||||||
|
|
||||||
def delete_iface(self, bridge_name: str, iface_name: str) -> None:
|
def delete_iface(self, bridge_name: str, iface_name: str) -> None:
|
||||||
|
@ -349,7 +347,7 @@ class OvsNetClient(LinuxNetClient):
|
||||||
:param iface_name: interface name
|
:param iface_name: interface name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{OVS_BIN} del-port {bridge_name} {iface_name}")
|
self.run(f"{OVS_VSCTL} del-port {bridge_name} {iface_name}")
|
||||||
|
|
||||||
def existing_bridges(self, _id: int) -> bool:
|
def existing_bridges(self, _id: int) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -358,7 +356,7 @@ class OvsNetClient(LinuxNetClient):
|
||||||
:param _id: node id to check bridges for
|
:param _id: node id to check bridges for
|
||||||
:return: True if there are existing bridges, False otherwise
|
:return: True if there are existing bridges, False otherwise
|
||||||
"""
|
"""
|
||||||
output = self.run(f"{OVS_BIN} list-br")
|
output = self.run(f"{OVS_VSCTL} list-br")
|
||||||
if output:
|
if output:
|
||||||
for line in output.split("\n"):
|
for line in output.split("\n"):
|
||||||
fields = line.split(".")
|
fields = line.split(".")
|
||||||
|
@ -373,7 +371,7 @@ class OvsNetClient(LinuxNetClient):
|
||||||
:param name: bridge name
|
:param name: bridge name
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.run(f"{OVS_BIN} set bridge {name} other_config:mac-aging-time=0")
|
self.run(f"{OVS_VSCTL} set bridge {name} other_config:mac-aging-time=0")
|
||||||
|
|
||||||
|
|
||||||
def get_net_client(use_ovs: bool, run: Callable[..., str]) -> LinuxNetClient:
|
def get_net_client(use_ovs: bool, run: Callable[..., str]) -> LinuxNetClient:
|
||||||
|
|
|
@ -10,7 +10,6 @@ from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Type
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.constants import EBTABLES_BIN, TC_BIN
|
|
||||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
||||||
from core.emulator.enumerations import (
|
from core.emulator.enumerations import (
|
||||||
LinkTypes,
|
LinkTypes,
|
||||||
|
@ -20,6 +19,7 @@ from core.emulator.enumerations import (
|
||||||
RegisterTlvs,
|
RegisterTlvs,
|
||||||
)
|
)
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
|
from core.executables import EBTABLES, TC
|
||||||
from core.nodes.base import CoreNetworkBase
|
from core.nodes.base import CoreNetworkBase
|
||||||
from core.nodes.interface import CoreInterface, GreTap, Veth
|
from core.nodes.interface import CoreInterface, GreTap, Veth
|
||||||
from core.nodes.netclient import get_net_client
|
from core.nodes.netclient import get_net_client
|
||||||
|
@ -104,7 +104,7 @@ class EbtablesQueue:
|
||||||
:param cmd: ebtable command
|
:param cmd: ebtable command
|
||||||
:return: ebtable atomic command
|
:return: ebtable atomic command
|
||||||
"""
|
"""
|
||||||
return f"{EBTABLES_BIN} --atomic-file {self.atomic_file} {cmd}"
|
return f"{EBTABLES} --atomic-file {self.atomic_file} {cmd}"
|
||||||
|
|
||||||
def lastupdate(self, wlan: "CoreNetwork") -> float:
|
def lastupdate(self, wlan: "CoreNetwork") -> float:
|
||||||
"""
|
"""
|
||||||
|
@ -338,8 +338,8 @@ class CoreNetwork(CoreNetworkBase):
|
||||||
self.net_client.delete_bridge(self.brname)
|
self.net_client.delete_bridge(self.brname)
|
||||||
if self.has_ebtables_chain:
|
if self.has_ebtables_chain:
|
||||||
cmds = [
|
cmds = [
|
||||||
f"{EBTABLES_BIN} -D FORWARD --logical-in {self.brname} -j {self.brname}",
|
f"{EBTABLES} -D FORWARD --logical-in {self.brname} -j {self.brname}",
|
||||||
f"{EBTABLES_BIN} -X {self.brname}",
|
f"{EBTABLES} -X {self.brname}",
|
||||||
]
|
]
|
||||||
ebtablescmds(self.host_cmd, cmds)
|
ebtablescmds(self.host_cmd, cmds)
|
||||||
except CoreCommandError:
|
except CoreCommandError:
|
||||||
|
@ -448,7 +448,7 @@ class CoreNetwork(CoreNetworkBase):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
devname = iface.localname
|
devname = iface.localname
|
||||||
tc = f"{TC_BIN} qdisc replace dev {devname}"
|
tc = f"{TC} qdisc replace dev {devname}"
|
||||||
parent = "root"
|
parent = "root"
|
||||||
changed = False
|
changed = False
|
||||||
bw = options.bandwidth
|
bw = options.bandwidth
|
||||||
|
@ -466,7 +466,7 @@ class CoreNetwork(CoreNetworkBase):
|
||||||
changed = True
|
changed = True
|
||||||
elif iface.getparam("has_tbf") and bw <= 0:
|
elif iface.getparam("has_tbf") and bw <= 0:
|
||||||
if self.up:
|
if self.up:
|
||||||
cmd = f"{TC_BIN} qdisc delete dev {devname} {parent}"
|
cmd = f"{TC} qdisc delete dev {devname} {parent}"
|
||||||
iface.host_cmd(cmd)
|
iface.host_cmd(cmd)
|
||||||
iface.setparam("has_tbf", False)
|
iface.setparam("has_tbf", False)
|
||||||
# removing the parent removes the child
|
# removing the parent removes the child
|
||||||
|
@ -512,14 +512,12 @@ class CoreNetwork(CoreNetworkBase):
|
||||||
if not iface.getparam("has_netem"):
|
if not iface.getparam("has_netem"):
|
||||||
return
|
return
|
||||||
if self.up:
|
if self.up:
|
||||||
cmd = f"{TC_BIN} qdisc delete dev {devname} {parent} handle 10:"
|
cmd = f"{TC} qdisc delete dev {devname} {parent} handle 10:"
|
||||||
iface.host_cmd(cmd)
|
iface.host_cmd(cmd)
|
||||||
iface.setparam("has_netem", False)
|
iface.setparam("has_netem", False)
|
||||||
elif len(netem) > 1:
|
elif len(netem) > 1:
|
||||||
if self.up:
|
if self.up:
|
||||||
cmd = (
|
cmd = f"{TC} qdisc replace dev {devname} {parent} handle 10: {netem}"
|
||||||
f"{TC_BIN} qdisc replace dev {devname} {parent} handle 10: {netem}"
|
|
||||||
)
|
|
||||||
iface.host_cmd(cmd)
|
iface.host_cmd(cmd)
|
||||||
iface.setparam("has_netem", True)
|
iface.setparam("has_netem", True)
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@ import os
|
||||||
import threading
|
import threading
|
||||||
from typing import IO, TYPE_CHECKING, List, Optional, Tuple
|
from typing import IO, TYPE_CHECKING, List, Optional, Tuple
|
||||||
|
|
||||||
from core.constants import MOUNT_BIN, UMOUNT_BIN
|
|
||||||
from core.emulator.data import InterfaceData, LinkOptions
|
from core.emulator.data import InterfaceData, LinkOptions
|
||||||
from core.emulator.distributed import DistributedServer
|
from core.emulator.distributed import DistributedServer
|
||||||
from core.emulator.enumerations import NodeTypes, TransportType
|
from core.emulator.enumerations import NodeTypes, TransportType
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
|
from core.executables import MOUNT, UMOUNT
|
||||||
from core.nodes.base import CoreNetworkBase, CoreNodeBase
|
from core.nodes.base import CoreNetworkBase, CoreNodeBase
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
from core.nodes.network import CoreNetwork, GreTap
|
from core.nodes.network import CoreNetwork, GreTap
|
||||||
|
@ -76,7 +76,7 @@ class PhysicalNode(CoreNodeBase):
|
||||||
iface = self.get_iface(iface_id)
|
iface = self.get_iface(iface_id)
|
||||||
iface.set_mac(mac)
|
iface.set_mac(mac)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.net_client.device_mac(iface.name, mac)
|
self.net_client.device_mac(iface.name, str(iface.mac))
|
||||||
|
|
||||||
def add_ip(self, iface_id: int, ip: str) -> None:
|
def add_ip(self, iface_id: int, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -186,13 +186,13 @@ class PhysicalNode(CoreNodeBase):
|
||||||
source = os.path.abspath(source)
|
source = os.path.abspath(source)
|
||||||
logging.info("mounting %s at %s", source, target)
|
logging.info("mounting %s at %s", source, target)
|
||||||
os.makedirs(target)
|
os.makedirs(target)
|
||||||
self.host_cmd(f"{MOUNT_BIN} --bind {source} {target}", cwd=self.nodedir)
|
self.host_cmd(f"{MOUNT} --bind {source} {target}", cwd=self.nodedir)
|
||||||
self._mounts.append((source, target))
|
self._mounts.append((source, target))
|
||||||
|
|
||||||
def umount(self, target: str) -> None:
|
def umount(self, target: str) -> None:
|
||||||
logging.info("unmounting '%s'", target)
|
logging.info("unmounting '%s'", target)
|
||||||
try:
|
try:
|
||||||
self.host_cmd(f"{UMOUNT_BIN} -l {target}", cwd=self.nodedir)
|
self.host_cmd(f"{UMOUNT} -l {target}", cwd=self.nodedir)
|
||||||
except CoreCommandError:
|
except CoreCommandError:
|
||||||
logging.exception("unmounting failed for %s", target)
|
logging.exception("unmounting failed for %s", target)
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,9 @@ import time
|
||||||
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Tuple, Type
|
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Tuple, Type
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.constants import which
|
|
||||||
from core.emulator.data import FileData
|
from core.emulator.data import FileData
|
||||||
from core.emulator.enumerations import ExceptionLevels, MessageFlags, RegisterTlvs
|
from core.emulator.enumerations import ExceptionLevels, MessageFlags, RegisterTlvs
|
||||||
from core.errors import CoreCommandError
|
from core.errors import CoreCommandError, CoreError
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -262,7 +261,10 @@ class ServiceManager:
|
||||||
|
|
||||||
# validate dependent executables are present
|
# validate dependent executables are present
|
||||||
for executable in service.executables:
|
for executable in service.executables:
|
||||||
which(executable, required=True)
|
try:
|
||||||
|
utils.which(executable, required=True)
|
||||||
|
except CoreError as e:
|
||||||
|
raise CoreError(f"service({name}): {e}")
|
||||||
|
|
||||||
# validate service on load succeeds
|
# validate service on load succeeds
|
||||||
try:
|
try:
|
||||||
|
@ -300,7 +302,7 @@ class ServiceManager:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cls.add(service)
|
cls.add(service)
|
||||||
except ValueError as e:
|
except (CoreError, ValueError) as e:
|
||||||
service_errors.append(service.name)
|
service_errors.append(service.name)
|
||||||
logging.debug("not loading service(%s): %s", service.name, e)
|
logging.debug("not loading service(%s): %s", service.name, e)
|
||||||
return service_errors
|
return service_errors
|
||||||
|
|
|
@ -5,8 +5,9 @@ from typing import Optional, Tuple
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
from core import constants, utils
|
from core import utils
|
||||||
from core.errors import CoreCommandError
|
from core.errors import CoreCommandError
|
||||||
|
from core.executables import SYSCTL
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService, ServiceMode
|
from core.services.coreservices import CoreService, ServiceMode
|
||||||
|
|
||||||
|
@ -47,19 +48,13 @@ class IPForwardService(UtilService):
|
||||||
%(sysctl)s -w net.ipv4.conf.all.rp_filter=0
|
%(sysctl)s -w net.ipv4.conf.all.rp_filter=0
|
||||||
%(sysctl)s -w net.ipv4.conf.default.rp_filter=0
|
%(sysctl)s -w net.ipv4.conf.default.rp_filter=0
|
||||||
""" % {
|
""" % {
|
||||||
"sysctl": constants.SYSCTL_BIN
|
"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" % (
|
cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (SYSCTL, name)
|
||||||
constants.SYSCTL_BIN,
|
cfg += "%s -w net.ipv4.conf.%s.send_redirects=0\n" % (SYSCTL, name)
|
||||||
name,
|
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (SYSCTL, name)
|
||||||
)
|
|
||||||
cfg += "%s -w net.ipv4.conf.%s.send_redirects=0\n" % (
|
|
||||||
constants.SYSCTL_BIN,
|
|
||||||
name,
|
|
||||||
)
|
|
||||||
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (constants.SYSCTL_BIN, name)
|
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ from typing import (
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
from core.errors import CoreCommandError
|
from core.errors import CoreCommandError, CoreError
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
|
@ -154,7 +154,7 @@ def which(command: str, required: bool) -> str:
|
||||||
"""
|
"""
|
||||||
found_path = shutil.which(command)
|
found_path = shutil.which(command)
|
||||||
if found_path is None and required:
|
if found_path is None and required:
|
||||||
raise ValueError(f"failed to find required executable({command}) in path")
|
raise CoreError(f"failed to find required executable({command}) in path")
|
||||||
return found_path
|
return found_path
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ import netaddr
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.constants import IP_BIN
|
|
||||||
from core.emane.nodes import EmaneNet
|
from core.emane.nodes import EmaneNet
|
||||||
|
from core.executables import IP
|
||||||
from core.nodes.base import CoreNodeBase, NodeBase
|
from core.nodes.base import CoreNodeBase, NodeBase
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ def get_address_type(address: str) -> str:
|
||||||
def get_ipv4_addresses(hostname: str) -> List[Tuple[str, str]]:
|
def get_ipv4_addresses(hostname: str) -> List[Tuple[str, str]]:
|
||||||
if hostname == "localhost":
|
if hostname == "localhost":
|
||||||
addresses = []
|
addresses = []
|
||||||
args = f"{IP_BIN} -o -f inet address show"
|
args = f"{IP} -o -f inet address show"
|
||||||
output = utils.cmd(args)
|
output = utils.cmd(args)
|
||||||
for line in output.split(os.linesep):
|
for line in output.split(os.linesep):
|
||||||
split = line.split()
|
split = line.split()
|
||||||
|
|
Loading…
Reference in a new issue