Merge pull request #476 from coreemu/cleanup/executables

Cleanup/executables
This commit is contained in:
bharnden 2020-06-23 09:46:48 -07:00 committed by GitHub
commit 29a69e8b40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 117 additions and 99 deletions

View file

@ -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: |

View file

@ -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

View file

@ -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)

View file

@ -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()

View 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]

View file

@ -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:
""" """

View file

@ -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:
""" """

View file

@ -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:

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()