removed node map file and utilities, added formal class methods to session objects and added checks for specific classes where needed

This commit is contained in:
bharnden 2019-09-26 13:00:12 -07:00
parent 8c348b5ab1
commit b14012e5e9
24 changed files with 161 additions and 264 deletions

View file

@ -4,8 +4,9 @@ url = "https://pypi.org/simple"
verify_ssl = true verify_ssl = true
[scripts] [scripts]
coredev = "python scripts/core-daemon -f data/core.conf -l data/logging.conf" core = "python scripts/core-daemon -f data/core.conf -l data/logging.conf"
coretest = "python -m pytest -v tests" test = "pytest -v tests"
test_emane = "pytest -v tests/emane"
[dev-packages] [dev-packages]
grpcio-tools = "*" grpcio-tools = "*"

View file

@ -12,6 +12,7 @@ import grpc
from core import CoreError from core import CoreError
from core.api.grpc import core_pb2, core_pb2_grpc from core.api.grpc import core_pb2, core_pb2_grpc
from core.emane.nodes import EmaneNode
from core.emulator.data import ( from core.emulator.data import (
ConfigData, ConfigData,
EventData, EventData,
@ -23,7 +24,6 @@ from core.emulator.data import (
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, LinkTypes, NodeTypes from core.emulator.enumerations import EventTypes, LinkTypes, NodeTypes
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
from core.nodes import nodeutils
from core.nodes.base import CoreNetworkBase from core.nodes.base import CoreNetworkBase
from core.nodes.docker import DockerNode from core.nodes.docker import DockerNode
from core.nodes.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
@ -444,7 +444,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
if not isinstance(node.id, int): if not isinstance(node.id, int):
continue continue
node_type = nodeutils.get_node_type(node.__class__).value node_type = session.get_node_type(node.__class__)
model = getattr(node, "type", None) model = getattr(node, "type", None)
position = core_pb2.Position( position = core_pb2.Position(
x=node.position.x, y=node.position.y, z=node.position.z x=node.position.x, y=node.position.y, z=node.position.z
@ -456,7 +456,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
services = [x.name for x in services] services = [x.name for x in services]
emane_model = None emane_model = None
if nodeutils.is_node(node, NodeTypes.EMANE): if isinstance(node, EmaneNode):
emane_model = node.model.name emane_model = node.model.name
node_proto = core_pb2.Node( node_proto = core_pb2.Node(
@ -464,7 +464,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
name=node.name, name=node.name,
emane=emane_model, emane=emane_model,
model=model, model=model,
type=node_type, type=node_type.value,
position=position, position=position,
services=services, services=services,
) )
@ -809,18 +809,18 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
interfaces.append(interface_proto) interfaces.append(interface_proto)
emane_model = None emane_model = None
if nodeutils.is_node(node, NodeTypes.EMANE): if isinstance(node, EmaneNode):
emane_model = node.model.name emane_model = node.model.name
services = [x.name for x in getattr(node, "services", [])] services = [x.name for x in getattr(node, "services", [])]
position = core_pb2.Position( position = core_pb2.Position(
x=node.position.x, y=node.position.y, z=node.position.z x=node.position.x, y=node.position.y, z=node.position.z
) )
node_type = nodeutils.get_node_type(node.__class__).value node_type = session.get_node_type(node.__class__)
node_proto = core_pb2.Node( node_proto = core_pb2.Node(
id=node.id, id=node.id,
name=node.name, name=node.name,
type=node_type, type=node_type.value,
emane=emane_model, emane=emane_model,
model=node.type, model=node.type,
position=position, position=position,

View file

@ -12,6 +12,7 @@ import threading
from core import utils from core import utils
from core.api.tlv import coreapi from core.api.tlv import coreapi
from core.emane.nodes import EmaneNet
from core.emulator.enumerations import ( from core.emulator.enumerations import (
ConfigDataTypes, ConfigDataTypes,
ConfigFlags, ConfigFlags,
@ -27,11 +28,10 @@ from core.emulator.enumerations import (
NodeTypes, NodeTypes,
RegisterTlvs, RegisterTlvs,
) )
from core.nodes import nodeutils
from core.nodes.base import CoreNetworkBase, CoreNodeBase from core.nodes.base import CoreNetworkBase, CoreNodeBase
from core.nodes.interface import GreTap from core.nodes.interface import GreTap
from core.nodes.ipaddress import IpAddress from core.nodes.ipaddress import IpAddress
from core.nodes.network import GreTapBridge from core.nodes.network import CtrlNet, GreTapBridge
from core.nodes.physical import PhysicalNode from core.nodes.physical import PhysicalNode
@ -495,15 +495,12 @@ class CoreBroker(object):
logging.info("adding net tunnel for: id(%s) %s", node_id, net) logging.info("adding net tunnel for: id(%s) %s", node_id, net)
# add other nets here that do not require tunnels # add other nets here that do not require tunnels
if nodeutils.is_node(net, NodeTypes.EMANE_NET): if isinstance(net, EmaneNet):
logging.warning("emane network does not require a tunnel") logging.warning("emane network does not require a tunnel")
return None return None
server_interface = getattr(net, "serverintf", None) server_interface = getattr(net, "serverintf", None)
if ( if isinstance(net, CtrlNet) and server_interface is not None:
nodeutils.is_node(net, NodeTypes.CONTROL_NET)
and server_interface is not None
):
logging.warning( logging.warning(
"control networks with server interfaces do not need a tunnel" "control networks with server interfaces do not need a tunnel"
) )
@ -824,7 +821,8 @@ class CoreBroker(object):
nodetype = message.get_tlv(NodeTlvs.TYPE.value) nodetype = message.get_tlv(NodeTlvs.TYPE.value)
if nodetype is not None: if nodetype is not None:
try: try:
nodecls = nodeutils.get_node_class(NodeTypes(nodetype)) nodetype = NodeTypes(nodetype)
nodecls = self.session.get_node_class(nodetype)
except KeyError: except KeyError:
logging.warning("broker invalid node type %s", nodetype) logging.warning("broker invalid node type %s", nodetype)
return handle_locally, servers return handle_locally, servers

View file

@ -38,7 +38,7 @@ from core.emulator.enumerations import (
SessionTlvs, SessionTlvs,
) )
from core.location.mobility import BasicRangeModel from core.location.mobility import BasicRangeModel
from core.nodes import nodeutils from core.nodes.network import WlanNode
from core.services.coreservices import ServiceManager, ServiceShim from core.services.coreservices import ServiceManager, ServiceShim
@ -1603,8 +1603,8 @@ class CoreHandler(socketserver.BaseRequestHandler):
node = self.session.get_node(node_id) node = self.session.get_node(node_id)
# configure mobility models for WLAN added during runtime # configure mobility models for WLAN added during runtime
if event_type == EventTypes.INSTANTIATION_STATE and nodeutils.is_node( if event_type == EventTypes.INSTANTIATION_STATE and isinstance(
node, NodeTypes.WIRELESS_LAN node, WlanNode
): ):
self.session.start_mobility(node_ids=(node.id,)) self.session.start_mobility(node_ids=(node.id,))
return () return ()

View file

@ -15,6 +15,7 @@ from core.emane.bypass import EmaneBypassModel
from core.emane.commeffect import EmaneCommEffectModel from core.emane.commeffect import EmaneCommEffectModel
from core.emane.emanemodel import EmaneModel from core.emane.emanemodel import EmaneModel
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNode
from core.emane.rfpipe import EmaneRfPipeModel from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel from core.emane.tdma import EmaneTdmaModel
from core.emulator.enumerations import ( from core.emulator.enumerations import (
@ -23,10 +24,8 @@ from core.emulator.enumerations import (
ConfigTlvs, ConfigTlvs,
MessageFlags, MessageFlags,
MessageTypes, MessageTypes,
NodeTypes,
RegisterTlvs, RegisterTlvs,
) )
from core.nodes import nodeutils
from core.xml import emanexml from core.xml import emanexml
try: try:
@ -266,7 +265,7 @@ class EmaneManager(ModelManager):
with self.session._nodes_lock: with self.session._nodes_lock:
for node_id in self.session.nodes: for node_id in self.session.nodes:
node = self.session.nodes[node_id] node = self.session.nodes[node_id]
if nodeutils.is_node(node, NodeTypes.EMANE): if isinstance(node, EmaneNode):
logging.debug( logging.debug(
"adding emane node: id(%s) name(%s)", node.id, node.name "adding emane node: id(%s) name(%s)", node.id, node.name
) )

View file

@ -25,7 +25,6 @@ class EmaneNet(CoreNetworkBase):
apitype = NodeTypes.EMANE.value apitype = NodeTypes.EMANE.value
linktype = LinkTypes.WIRELESS.value linktype = LinkTypes.WIRELESS.value
# icon used
type = "wlan" type = "wlan"
@ -36,6 +35,8 @@ class EmaneNode(EmaneNet):
Emane controller object that exists in a session. Emane controller object that exists in a session.
""" """
is_emane = True
def __init__(self, session, _id=None, name=None, start=True): def __init__(self, session, _id=None, name=None, start=True):
super(EmaneNode, self).__init__(session, _id, name, start) super(EmaneNode, self).__init__(session, _id, name, start)
self.conf = "" self.conf = ""

View file

@ -7,7 +7,6 @@ import sys
import core.services import core.services
from core.emulator.emudata import IdGen from core.emulator.emudata import IdGen
from core.emulator.session import Session from core.emulator.session import Session
from core.nodes import nodemaps, nodeutils
from core.services.coreservices import ServiceManager from core.services.coreservices import ServiceManager
@ -53,10 +52,6 @@ class CoreEmu(object):
self.session_id_gen = IdGen(_id=0) self.session_id_gen = IdGen(_id=0)
self.sessions = {} self.sessions = {}
# set default nodes
node_map = nodemaps.NODES
nodeutils.set_node_map(node_map)
# load services # load services
self.service_errors = [] self.service_errors = []
self.load_services() self.load_services()
@ -77,15 +72,6 @@ class CoreEmu(object):
custom_service_errors = ServiceManager.add_services(service_path) custom_service_errors = ServiceManager.add_services(service_path)
self.service_errors.extend(custom_service_errors) self.service_errors.extend(custom_service_errors)
def update_nodes(self, node_map):
"""
Updates node map used by core.
:param dict node_map: node map to update existing node map with
:return: nothing
"""
nodeutils.update_node_map(node_map)
def shutdown(self): def shutdown(self):
""" """
Shutdown all CORE session. Shutdown all CORE session.

View file

@ -1,7 +1,8 @@
from core.emulator.enumerations import LinkTypes, NodeTypes from core.emane.nodes import EmaneNode
from core.nodes import nodeutils from core.emulator.enumerations import LinkTypes
from core.nodes.base import CoreNetworkBase from core.nodes.base import CoreNetworkBase
from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress
from core.nodes.physical import PhysicalNode
class IdGen(object): class IdGen(object):
@ -65,7 +66,7 @@ def link_config(network, interface, link_options, devname=None, interface_two=No
} }
# hacky check here, because physical and emane nodes do not conform to the same linkconfig interface # hacky check here, because physical and emane nodes do not conform to the same linkconfig interface
if not nodeutils.is_node(network, [NodeTypes.EMANE, NodeTypes.PHYSICAL]): if not isinstance(network, (EmaneNode, PhysicalNode)):
config["devname"] = devname config["devname"] = devname
network.linkconfig(**config) network.linkconfig(**config)

View file

@ -14,11 +14,11 @@ import threading
import time import time
from multiprocessing.pool import ThreadPool from multiprocessing.pool import ThreadPool
import core.nodes.base
from core import CoreError, constants, utils from core import CoreError, constants, utils
from core.api.tlv import coreapi from core.api.tlv import coreapi
from core.api.tlv.broker import CoreBroker from core.api.tlv.broker import CoreBroker
from core.emane.emanemanager import EmaneManager from core.emane.emanemanager import EmaneManager
from core.emane.nodes import EmaneNet, EmaneNode
from core.emulator.data import EventData, ExceptionData, NodeData from core.emulator.data import EventData, ExceptionData, NodeData
from core.emulator.emudata import ( from core.emulator.emudata import (
IdGen, IdGen,
@ -33,14 +33,46 @@ from core.emulator.sessionconfig import SessionConfig, SessionMetaData
from core.location.corelocation import CoreLocation from core.location.corelocation import CoreLocation
from core.location.event import EventLoop from core.location.event import EventLoop
from core.location.mobility import MobilityManager from core.location.mobility import MobilityManager
from core.nodes import nodeutils from core.nodes.base import CoreNode, CoreNodeBase
from core.nodes.base import CoreNodeBase from core.nodes.docker import DockerNode
from core.nodes.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
from core.nodes.lxd import LxcNode
from core.nodes.network import (
CtrlNet,
GreTapBridge,
HubNode,
PtpNet,
SwitchNode,
TunnelNode,
WlanNode,
)
from core.nodes.physical import PhysicalNode, Rj45Node
from core.plugins.sdt import Sdt from core.plugins.sdt import Sdt
from core.services.coreservices import CoreServices from core.services.coreservices import CoreServices
from core.xml import corexml, corexmldeployment from core.xml import corexml, corexmldeployment
from core.xml.corexml import CoreXmlReader, CoreXmlWriter from core.xml.corexml import CoreXmlReader, CoreXmlWriter
# maps for converting from API call node type values to classes and vice versa
NODES = {
NodeTypes.DEFAULT: CoreNode,
NodeTypes.PHYSICAL: PhysicalNode,
NodeTypes.TBD: None,
NodeTypes.SWITCH: SwitchNode,
NodeTypes.HUB: HubNode,
NodeTypes.WIRELESS_LAN: WlanNode,
NodeTypes.RJ45: Rj45Node,
NodeTypes.TUNNEL: TunnelNode,
NodeTypes.KTUNNEL: None,
NodeTypes.EMANE: EmaneNode,
NodeTypes.EMANE_NET: EmaneNet,
NodeTypes.TAP_BRIDGE: GreTapBridge,
NodeTypes.PEER_TO_PEER: PtpNet,
NodeTypes.CONTROL_NET: CtrlNet,
NodeTypes.DOCKER: DockerNode,
NodeTypes.LXC: LxcNode,
}
NODES_TYPE = {NODES[x]: x for x in NODES}
class Session(object): class Session(object):
""" """
@ -121,6 +153,33 @@ class Session(object):
"host": ("DefaultRoute", "SSH"), "host": ("DefaultRoute", "SSH"),
} }
@classmethod
def get_node_class(cls, _type):
"""
Retrieve the class for a given node type.
:param core.emulator.enumerations.NodeTypes _type: node type to get class for
:return: node class
"""
node_class = NODES.get(_type)
if node_class is None:
raise CoreError("invalid node type: %s" % _type)
return node_class
@classmethod
def get_node_type(cls, _class):
"""
Retrieve node type for a given node class.
:param _class: node class to get a node type for
:return: node type
:rtype: core.emulator.enumerations.NodeTypes
"""
node_type = NODES_TYPE.get(_class)
if node_type is None:
raise CoreError("invalid node class: %s" % _class)
return node_type
def _link_nodes(self, node_one_id, node_two_id): def _link_nodes(self, node_one_id, node_two_id):
""" """
Convenience method for retrieving nodes within link data. Convenience method for retrieving nodes within link data.
@ -145,7 +204,7 @@ class Session(object):
# both node ids are provided # both node ids are provided
tunnel = self.broker.gettunnel(node_one_id, node_two_id) tunnel = self.broker.gettunnel(node_one_id, node_two_id)
logging.debug("tunnel between nodes: %s", tunnel) logging.debug("tunnel between nodes: %s", tunnel)
if nodeutils.is_node(tunnel, NodeTypes.TAP_BRIDGE): if isinstance(tunnel, GreTapBridge):
net_one = tunnel net_one = tunnel
if tunnel.remotenum == node_one_id: if tunnel.remotenum == node_one_id:
node_one = None node_one = None
@ -203,9 +262,7 @@ class Session(object):
raise CoreError("no common network found for wireless link/unlink") raise CoreError("no common network found for wireless link/unlink")
for common_network, interface_one, interface_two in common_networks: for common_network, interface_one, interface_two in common_networks:
if not nodeutils.is_node( if not isinstance(common_network, (WlanNode, EmaneNode)):
common_network, [NodeTypes.WIRELESS_LAN, NodeTypes.EMANE]
):
logging.info( logging.info(
"skipping common network that is not wireless/emane: %s", "skipping common network that is not wireless/emane: %s",
common_network, common_network,
@ -268,9 +325,8 @@ class Session(object):
node_one.name, node_one.name,
node_two.name, node_two.name,
) )
ptp_class = nodeutils.get_node_class(NodeTypes.PEER_TO_PEER)
start = self.state > EventTypes.DEFINITION_STATE.value start = self.state > EventTypes.DEFINITION_STATE.value
net_one = self.create_node(cls=ptp_class, start=start) net_one = self.create_node(cls=PtpNet, start=start)
# node to network # node to network
if node_one and net_one: if node_one and net_one:
@ -300,7 +356,7 @@ class Session(object):
net_one.name, net_one.name,
net_two.name, net_two.name,
) )
if nodeutils.is_node(net_two, NodeTypes.RJ45): if isinstance(net_two, Rj45Node):
interface = net_two.linknet(net_one) interface = net_two.linknet(net_one)
else: else:
interface = net_one.linknet(net_two) interface = net_one.linknet(net_two)
@ -324,12 +380,12 @@ class Session(object):
# tunnel node logic # tunnel node logic
key = link_options.key key = link_options.key
if key and nodeutils.is_node(net_one, NodeTypes.TUNNEL): if key and isinstance(net_one, TunnelNode):
logging.info("setting tunnel key for: %s", net_one.name) logging.info("setting tunnel key for: %s", net_one.name)
net_one.setkey(key) net_one.setkey(key)
if addresses: if addresses:
net_one.addrconfig(addresses) net_one.addrconfig(addresses)
if key and nodeutils.is_node(net_two, NodeTypes.TUNNEL): if key and isinstance(net_two, TunnelNode):
logging.info("setting tunnel key for: %s", net_two.name) logging.info("setting tunnel key for: %s", net_two.name)
net_two.setkey(key) net_two.setkey(key)
if addresses: if addresses:
@ -337,14 +393,14 @@ class Session(object):
# physical node connected with tunnel # physical node connected with tunnel
if not net_one and not net_two and (node_one or node_two): if not net_one and not net_two and (node_one or node_two):
if node_one and nodeutils.is_node(node_one, NodeTypes.PHYSICAL): if node_one and isinstance(node_one, PhysicalNode):
logging.info("adding link for physical node: %s", node_one.name) logging.info("adding link for physical node: %s", node_one.name)
addresses = interface_one.get_addresses() addresses = interface_one.get_addresses()
node_one.adoptnetif( node_one.adoptnetif(
tunnel, interface_one.id, interface_one.mac, addresses tunnel, interface_one.id, interface_one.mac, addresses
) )
link_config(node_one, tunnel, link_options) link_config(node_one, tunnel, link_options)
elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL): elif node_two and isinstance(node_two, PhysicalNode):
logging.info("adding link for physical node: %s", node_two.name) logging.info("adding link for physical node: %s", node_two.name)
addresses = interface_two.get_addresses() addresses = interface_two.get_addresses()
node_two.adoptnetif( node_two.adoptnetif(
@ -584,14 +640,11 @@ class Session(object):
:param int _id: id for node, defaults to None for generated id :param int _id: id for node, defaults to None for generated id
:param core.emulator.emudata.NodeOptions node_options: data to create node with :param core.emulator.emudata.NodeOptions node_options: data to create node with
:return: created node :return: created node
:raises core.CoreError: when an invalid node type is given
""" """
# retrieve node class for given node type # validate node type, get class, or throw error
try: node_class = self.get_node_class(_type)
node_class = nodeutils.get_node_class(_type)
except KeyError:
logging.error("invalid node type to create: %s", _type)
return None
# set node start based on current session state, override and check when rj45 # set node start based on current session state, override and check when rj45
start = self.state > EventTypes.DEFINITION_STATE.value start = self.state > EventTypes.DEFINITION_STATE.value
@ -651,10 +704,8 @@ class Session(object):
logging.debug("set node type: %s", node.type) logging.debug("set node type: %s", node.type)
self.services.add_services(node, node.type, node_options.services) self.services.add_services(node, node.type, node_options.services)
# boot nodes if created after runtime, LcxNodes, Physical, and RJ45 are all PyCoreNodes # boot nodes if created after runtime, CoreNodes, Physical, and RJ45 are all nodes
is_boot_node = isinstance(node, CoreNodeBase) and not nodeutils.is_node( is_boot_node = isinstance(node, CoreNodeBase) and not isinstance(node, Rj45Node)
node, NodeTypes.RJ45
)
if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node: if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node:
self.write_nodes() self.write_nodes()
self.add_remove_control_interface(node=node, remove=False) self.add_remove_control_interface(node=node, remove=False)
@ -1441,12 +1492,10 @@ class Session(object):
count = 0 count = 0
for node_id in self.nodes: for node_id in self.nodes:
node = self.nodes[node_id] node = self.nodes[node_id]
is_p2p_ctrlnet = nodeutils.is_node( is_p2p_ctrlnet = isinstance(node, (PtpNet, CtrlNet))
node, (NodeTypes.PEER_TO_PEER, NodeTypes.CONTROL_NET) is_tap = isinstance(node, GreTapBridge) and not isinstance(
node, TunnelNode
) )
is_tap = nodeutils.is_node(
node, NodeTypes.TAP_BRIDGE
) and not nodeutils.is_node(node, NodeTypes.TUNNEL)
if is_p2p_ctrlnet or is_tap: if is_p2p_ctrlnet or is_tap:
continue continue
@ -1493,7 +1542,7 @@ class Session(object):
for node_id in self.nodes: for node_id in self.nodes:
node = self.nodes[node_id] node = self.nodes[node_id]
# TODO: determine if checking for CoreNode alone is ok # TODO: determine if checking for CoreNode alone is ok
if isinstance(node, core.nodes.base.CoreNodeBase): if isinstance(node, CoreNodeBase):
self.services.stop_services(node) self.services.stop_services(node)
# shutdown emane # shutdown emane
@ -1546,10 +1595,7 @@ class Session(object):
start = time.time() start = time.time()
for _id in self.nodes: for _id in self.nodes:
node = self.nodes[_id] node = self.nodes[_id]
# TODO: PyCoreNode is not the type to check if isinstance(node, CoreNodeBase) and not isinstance(node, Rj45Node):
if isinstance(node, CoreNodeBase) and not nodeutils.is_node(
node, NodeTypes.RJ45
):
# add a control interface if configured # add a control interface if configured
logging.info( logging.info(
"booting node(%s): %s", "booting node(%s): %s",
@ -1648,8 +1694,7 @@ class Session(object):
# no controlnet needed # no controlnet needed
return None return None
else: else:
control_net_class = nodeutils.get_node_class(NodeTypes.CONTROL_NET) prefix_spec = CtrlNet.DEFAULT_PREFIX_LIST[net_index]
prefix_spec = control_net_class.DEFAULT_PREFIX_LIST[net_index]
logging.debug("prefix spec: %s", prefix_spec) logging.debug("prefix spec: %s", prefix_spec)
server_interface = self.get_control_net_server_interfaces()[net_index] server_interface = self.get_control_net_server_interfaces()[net_index]
@ -1725,9 +1770,8 @@ class Session(object):
prefix = prefixes[0] prefix = prefixes[0]
logging.info("controlnet prefix: %s - %s", type(prefix), prefix) logging.info("controlnet prefix: %s - %s", type(prefix), prefix)
control_net_class = nodeutils.get_node_class(NodeTypes.CONTROL_NET)
control_net = self.create_node( control_net = self.create_node(
cls=control_net_class, cls=CtrlNet,
_id=_id, _id=_id,
prefix=prefix, prefix=prefix,
assign_address=assign_address, assign_address=assign_address,

View file

@ -17,7 +17,7 @@ from socket import AF_INET, AF_INET6
from core import CoreCommandError, constants, utils from core import CoreCommandError, constants, utils
from core.emulator.data import LinkData, NodeData from core.emulator.data import LinkData, NodeData
from core.emulator.enumerations import LinkTypes, NodeTypes from core.emulator.enumerations import LinkTypes, NodeTypes
from core.nodes import client, ipaddress, nodeutils from core.nodes import client, ipaddress
from core.nodes.interface import CoreInterface, TunTap, Veth from core.nodes.interface import CoreInterface, TunTap, Veth
_DEFAULT_MTU = 1500 _DEFAULT_MTU = 1500
@ -886,8 +886,8 @@ class CoreNode(CoreNodeBase):
addrlist = [] addrlist = []
with self.lock: with self.lock:
# TODO: see if you can move this to emane specific code # TODO: emane specific code
if nodeutils.is_node(net, NodeTypes.EMANE): if net.is_emane is True:
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net) ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
# TUN/TAP is not ready for addressing yet; the device may # TUN/TAP is not ready for addressing yet; the device may
# take some time to appear, and installing it into a # take some time to appear, and installing it into a
@ -1050,6 +1050,7 @@ class CoreNetworkBase(NodeBase):
""" """
linktype = LinkTypes.WIRED.value linktype = LinkTypes.WIRED.value
is_emane = False
def __init__(self, session, _id, name, start=True): def __init__(self, session, _id, name, start=True):
""" """

View file

@ -7,8 +7,6 @@ import time
from builtins import int, range from builtins import int, range
from core import CoreCommandError, constants, utils from core import CoreCommandError, constants, utils
from core.emulator.enumerations import NodeTypes
from core.nodes import nodeutils
utils.check_executables([constants.IP_BIN]) utils.check_executables([constants.IP_BIN])
@ -387,13 +385,12 @@ class TunTap(CoreInterface):
if result: if result:
break break
# TODO: emane specific code
# check if this is an EMANE interface; if so, continue # check if this is an EMANE interface; if so, continue
# waiting if EMANE is still running # waiting if EMANE is still running
# TODO: remove emane code
should_retry = count < 5 should_retry = count < 5
is_emane_node = nodeutils.is_node(self.net, NodeTypes.EMANE)
is_emane_running = self.node.session.emane.emanerunning(self.node) is_emane_running = self.node.session.emane.emanerunning(self.node)
if all([should_retry, is_emane_node, is_emane_running]): if all([should_retry, self.net.is_emane, is_emane_running]):
count += 1 count += 1
else: else:
raise RuntimeError("node device failed to exist") raise RuntimeError("node device failed to exist")

View file

@ -1,32 +0,0 @@
"""
Provides default node maps that can be used to run core with.
"""
import core.nodes.base
import core.nodes.docker
import core.nodes.lxd
import core.nodes.network
import core.nodes.physical
from core.emane.nodes import EmaneNet, EmaneNode
from core.emulator.enumerations import NodeTypes
from core.nodes import physical
from core.nodes.network import GreTapBridge
# legacy core nodes, that leverage linux bridges
NODES = {
NodeTypes.DEFAULT: core.nodes.base.CoreNode,
NodeTypes.PHYSICAL: physical.PhysicalNode,
NodeTypes.TBD: None,
NodeTypes.SWITCH: core.nodes.network.SwitchNode,
NodeTypes.HUB: core.nodes.network.HubNode,
NodeTypes.WIRELESS_LAN: core.nodes.network.WlanNode,
NodeTypes.RJ45: core.nodes.physical.Rj45Node,
NodeTypes.TUNNEL: core.nodes.network.TunnelNode,
NodeTypes.KTUNNEL: None,
NodeTypes.EMANE: EmaneNode,
NodeTypes.EMANE_NET: EmaneNet,
NodeTypes.TAP_BRIDGE: GreTapBridge,
NodeTypes.PEER_TO_PEER: core.nodes.network.PtpNet,
NodeTypes.CONTROL_NET: core.nodes.network.CtrlNet,
NodeTypes.DOCKER: core.nodes.docker.DockerNode,
NodeTypes.LXC: core.nodes.lxd.LxcNode,
}

View file

@ -1,97 +0,0 @@
"""
Serves as a global point for storing and retrieving node types needed during simulation.
"""
import logging
_NODE_MAP = None
def _log_map():
global _NODE_MAP
for key in _NODE_MAP:
value = _NODE_MAP[key]
name = None
if value:
name = value.__name__
logging.debug("node type (%s) - class (%s)", key.name, name)
def _convert_map(x, y):
"""
Convenience method to create a human readable version of the node map to log.
:param dict x: dictionary to reduce node items into
:param tuple y: current node item
:return: human readable name mapping of the node map
"""
x[y[0].name] = y[1]
return x
def update_node_map(node_map):
"""
Update the current node map with the provided node map values.
:param dict node_map: node map to update with
"""
global _NODE_MAP
_NODE_MAP.update(node_map)
_log_map()
def set_node_map(node_map):
"""
Set the global node map that proides a consistent way to retrieve differently configured nodes.
:param dict node_map: node map to set to
:return: nothing
"""
global _NODE_MAP
_NODE_MAP = node_map
_log_map()
def get_node_class(node_type):
"""
Retrieve the node class for a given node type.
:param int node_type: node type to retrieve class for
:return: node class
"""
global _NODE_MAP
return _NODE_MAP[node_type]
def get_node_type(node_class):
"""
Retrieve the node type given a node class.
:param class node_class: node class to get type for
:return: node type
:rtype: core.emulator.enumerations.NodeTypes
"""
global _NODE_MAP
node_type_map = {_NODE_MAP[x]: x for x in _NODE_MAP}
return node_type_map.get(node_class)
def is_node(obj, node_types):
"""
Validates if an object is one of the provided node types.
:param obj: object to check type for
:param int|tuple|list node_types: node type(s) to check against
:return: True if the object is one of the node types, False otherwise
:rtype: bool
"""
type_classes = []
if isinstance(node_types, (tuple, list)):
for node_type in node_types:
type_class = get_node_class(node_type)
type_classes.append(type_class)
else:
type_class = get_node_class(node_types)
type_classes.append(type_class)
return isinstance(obj, tuple(type_classes))

View file

@ -8,6 +8,7 @@ import socket
from future.moves.urllib.parse import urlparse from future.moves.urllib.parse import urlparse
from core import CoreError, constants from core import CoreError, constants
from core.emane.nodes import EmaneNode
from core.emulator.enumerations import ( from core.emulator.enumerations import (
EventTypes, EventTypes,
LinkTlvs, LinkTlvs,
@ -17,8 +18,8 @@ from core.emulator.enumerations import (
NodeTlvs, NodeTlvs,
NodeTypes, NodeTypes,
) )
from core.nodes import nodeutils
from core.nodes.base import CoreNetworkBase, NodeBase from core.nodes.base import CoreNetworkBase, NodeBase
from core.nodes.network import WlanNode
# TODO: A named tuple may be more appropriate, than abusing a class dict like this # TODO: A named tuple may be more appropriate, than abusing a class dict like this
@ -27,14 +28,13 @@ class Bunch(object):
Helper class for recording a collection of attributes. Helper class for recording a collection of attributes.
""" """
def __init__(self, **kwds): def __init__(self, **kwargs):
""" """
Create a Bunch instance. Create a Bunch instance.
:param dict kwds: keyword arguments :param dict kwargs: keyword arguments
:return:
""" """
self.__dict__.update(kwds) self.__dict__.update(kwargs)
class Sdt(object): class Sdt(object):
@ -365,9 +365,7 @@ class Sdt(object):
for net in nets: for net in nets:
all_links = net.all_link_data(flags=MessageFlags.ADD.value) all_links = net.all_link_data(flags=MessageFlags.ADD.value)
for link_data in all_links: for link_data in all_links:
is_wireless = nodeutils.is_node( is_wireless = isinstance(net, (WlanNode, EmaneNode))
net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)
)
wireless_link = link_data.message_type == LinkTypes.WIRELESS.value wireless_link = link_data.message_type == LinkTypes.WIRELESS.value
if is_wireless and link_data.node1_id == net.id: if is_wireless and link_data.node1_id == net.id:
continue continue
@ -401,7 +399,7 @@ class Sdt(object):
def handlenodemsg(self, msg): def handlenodemsg(self, msg):
""" """
Process a Node Message to add/delete or move a node on Process a Node Message to add/delete or move a node on
the SDT display. Node properties are found in session._objs or the SDT display. Node properties are found in a session or
self.remotes for remote nodes (or those not yet instantiated). self.remotes for remote nodes (or those not yet instantiated).
:param msg: node message to handle :param msg: node message to handle
@ -430,7 +428,8 @@ class Sdt(object):
model = "router" model = "router"
nodetype = model nodetype = model
elif nodetype is not None: elif nodetype is not None:
nodetype = nodeutils.get_node_class(NodeTypes(nodetype)).type nodetype = NodeTypes(nodetype)
nodetype = self.session.get_node_class(nodetype).type
net = True net = True
else: else:
nodetype = None nodetype = None
@ -509,6 +508,6 @@ class Sdt(object):
n = self.session.get_node(nodenum) n = self.session.get_node(nodenum)
except CoreError: except CoreError:
return False return False
if nodeutils.is_node(n, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)): if isinstance(n, (WlanNode, EmaneNode)):
return True return True
return False return False

View file

@ -1,5 +1,4 @@
from core.emulator.enumerations import NodeTypes from core.emane.nodes import EmaneNode
from core.nodes import nodeutils
from core.services.coreservices import CoreService from core.services.coreservices import CoreService
from core.xml import emanexml from core.xml import emanexml
@ -22,7 +21,7 @@ class EmaneTransportService(CoreService):
transport_commands = [] transport_commands = []
for interface in node.netifs(sort=True): for interface in node.netifs(sort=True):
network_node = node.session.get_node(interface.net.id) network_node = node.session.get_node(interface.net.id)
if nodeutils.is_node(network_node, NodeTypes.EMANE): if isinstance(network_node, EmaneNode):
config = node.session.emane.get_configs( config = node.session.emane.get_configs(
network_node.id, network_node.model.name network_node.id, network_node.model.name
) )

View file

@ -4,8 +4,10 @@ Assumes installation of FRR via https://deb.frrouting.org/
""" """
from core import constants from core import constants
from core.emulator.enumerations import LinkTypes, NodeTypes from core.emulator.enumerations import LinkTypes
from core.nodes import ipaddress, nodeutils from core.nodes import ipaddress
from core.nodes.network import PtpNet
from core.nodes.physical import Rj45Node
from core.services.coreservices import CoreService from core.services.coreservices import CoreService
@ -341,7 +343,7 @@ class FrrService(CoreService):
for peerifc in ifc.net.netifs(): for peerifc in ifc.net.netifs():
if peerifc == ifc: if peerifc == ifc:
continue continue
if nodeutils.is_node(peerifc, NodeTypes.RJ45): if isinstance(peerifc, Rj45Node):
return True return True
return False return False
@ -395,7 +397,7 @@ class FRROspfv2(FrrService):
Helper to detect whether interface is connected to a notional Helper to detect whether interface is connected to a notional
point-to-point link. point-to-point link.
""" """
if nodeutils.is_node(ifc.net, NodeTypes.PEER_TO_PEER): if isinstance(ifc.net, PtpNet):
return " ip ospf network point-to-point\n" return " ip ospf network point-to-point\n"
return "" return ""
@ -481,7 +483,7 @@ class FRROspfv3(FrrService):
Helper to detect whether interface is connected to a notional Helper to detect whether interface is connected to a notional
point-to-point link. point-to-point link.
""" """
if nodeutils.is_node(ifc.net, NodeTypes.PEER_TO_PEER): if isinstance(ifc.net, PtpNet):
return " ipv6 ospf6 network point-to-point\n" return " ipv6 ospf6 network point-to-point\n"
return "" return ""

View file

@ -3,8 +3,11 @@ quagga.py: defines routing services provided by Quagga.
""" """
from core import constants from core import constants
from core.emulator.enumerations import LinkTypes, NodeTypes from core.emane.nodes import EmaneNode
from core.nodes import ipaddress, nodeutils from core.emulator.enumerations import LinkTypes
from core.nodes import ipaddress
from core.nodes.network import PtpNet, WlanNode
from core.nodes.physical import Rj45Node
from core.services.coreservices import CoreService from core.services.coreservices import CoreService
@ -267,7 +270,7 @@ class QuaggaService(CoreService):
for peerifc in ifc.net.netifs(): for peerifc in ifc.net.netifs():
if peerifc == ifc: if peerifc == ifc:
continue continue
if nodeutils.is_node(peerifc, NodeTypes.RJ45): if isinstance(peerifc, Rj45Node):
return True return True
return False return False
@ -321,7 +324,7 @@ class Ospfv2(QuaggaService):
Helper to detect whether interface is connected to a notional Helper to detect whether interface is connected to a notional
point-to-point link. point-to-point link.
""" """
if nodeutils.is_node(ifc.net, NodeTypes.PEER_TO_PEER): if isinstance(ifc.net, PtpNet):
return " ip ospf network point-to-point\n" return " ip ospf network point-to-point\n"
return "" return ""
@ -407,7 +410,7 @@ class Ospfv3(QuaggaService):
Helper to detect whether interface is connected to a notional Helper to detect whether interface is connected to a notional
point-to-point link. point-to-point link.
""" """
if nodeutils.is_node(ifc.net, NodeTypes.PEER_TO_PEER): if isinstance(ifc.net, PtpNet):
return " ipv6 ospf6 network point-to-point\n" return " ipv6 ospf6 network point-to-point\n"
return "" return ""
@ -457,9 +460,7 @@ class Ospfv3mdr(Ospfv3):
cfg = cls.mtucheck(ifc) cfg = cls.mtucheck(ifc)
# Uncomment the following line to use Address Family Translation for IPv4 # Uncomment the following line to use Address Family Translation for IPv4
cfg += " ipv6 ospf6 instance-id 65\n" cfg += " ipv6 ospf6 instance-id 65\n"
if ifc.net is not None and nodeutils.is_node( if ifc.net is not None and isinstance(ifc.net, (WlanNode, EmaneNode)):
ifc.net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)
):
return ( return (
cfg cfg
+ """\ + """\

View file

@ -4,11 +4,12 @@ from lxml import etree
import core.nodes.base import core.nodes.base
import core.nodes.physical import core.nodes.physical
from core.emane.nodes import EmaneNode
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.nodes import nodeutils
from core.nodes.base import CoreNetworkBase from core.nodes.base import CoreNetworkBase
from core.nodes.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
from core.nodes.network import CtrlNet
def write_xml_file(xml_element, file_path, doctype=None): def write_xml_file(xml_element, file_path, doctype=None):
@ -408,7 +409,7 @@ class CoreXmlWriter(object):
is_network_or_rj45 = isinstance( is_network_or_rj45 = isinstance(
node, (core.nodes.base.CoreNetworkBase, core.nodes.physical.Rj45Node) node, (core.nodes.base.CoreNetworkBase, core.nodes.physical.Rj45Node)
) )
is_controlnet = nodeutils.is_node(node, NodeTypes.CONTROL_NET) is_controlnet = isinstance(node, CtrlNet)
if is_network_or_rj45 and not is_controlnet: if is_network_or_rj45 and not is_controlnet:
self.write_network(node) self.write_network(node)
# device node # device node
@ -457,7 +458,7 @@ class CoreXmlWriter(object):
interface_name = node_interface.name interface_name = node_interface.name
# check if emane interface # check if emane interface
if nodeutils.is_node(node_interface.net, NodeTypes.EMANE): if isinstance(node_interface.net, EmaneNode):
nem = node_interface.net.getnemid(node_interface) nem = node_interface.net.getnemid(node_interface)
add_attribute(interface, "nem", nem) add_attribute(interface, "nem", nem)

View file

@ -4,8 +4,8 @@ import socket
from lxml import etree from lxml import etree
from core import constants, utils from core import constants, utils
from core.emulator.enumerations import NodeTypes from core.emane.nodes import EmaneNode
from core.nodes import ipaddress, nodeutils from core.nodes import ipaddress
from core.nodes.base import CoreNodeBase from core.nodes.base import CoreNodeBase
@ -144,7 +144,7 @@ class CoreXmlDeployment(object):
for netif in node.netifs(): for netif in node.netifs():
emane_element = None emane_element = None
if nodeutils.is_node(netif.net, NodeTypes.EMANE): if isinstance(netif.net, EmaneNode):
emane_element = add_emane_interface(host_element, netif) emane_element = add_emane_interface(host_element, netif)
parent_element = host_element parent_element = host_element

View file

@ -60,9 +60,6 @@ def cored(cfg, use_ovs):
try: try:
address = (host, port) address = (host, port)
server = CoreServer(address, CoreHandler, cfg) server = CoreServer(address, CoreHandler, cfg)
if use_ovs:
from core.nodes.openvswitch import OVS_NODES
server.coreemu.update_nodes(OVS_NODES)
except: except:
logging.exception("error starting main server on: %s:%s", host, port) logging.exception("error starting main server on: %s:%s", host, port)
sys.exit(1) sys.exit(1)

View file

@ -10,17 +10,16 @@ import sys
import ns.core import ns.core
import ns.mobility import ns.mobility
from core.nodes import nodeutils, nodemaps, ipaddress
from corens3.obj import Ns3LteNet from corens3.obj import Ns3LteNet
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
from core.nodes import ipaddress
def ltesession(opt): def ltesession(opt):
""" """
Run a test LTE session. Run a test LTE session.
""" """
nodeutils.set_node_map(nodemaps.NODES)
session = Ns3Session(1, persistent=True, duration=opt.duration) session = Ns3Session(1, persistent=True, duration=opt.duration)
lte = session.create_node(cls=Ns3LteNet, name="wlan1") lte = session.create_node(cls=Ns3LteNet, name="wlan1")
lte.setsubchannels(range(25), range(50, 100)) lte.setsubchannels(range(25), range(50, 100))

View file

@ -27,11 +27,11 @@ import optparse
import sys import sys
import ns.core import ns.core
from core.nodes import nodeutils, nodemaps, ipaddress
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
from corens3.obj import Ns3WifiNet from corens3.obj import Ns3WifiNet
from core.nodes import ipaddress
def add_to_server(session): def add_to_server(session):
""" """
@ -50,7 +50,6 @@ def wifisession(opt):
""" """
Run a test wifi session. Run a test wifi session.
""" """
nodeutils.set_node_map(nodemaps.NODES)
session = Ns3Session(1, persistent=True, duration=opt.duration) session = Ns3Session(1, persistent=True, duration=opt.duration)
session.name = "ns3wifi" session.name = "ns3wifi"
session.filename = session.name + ".py" session.filename = session.name + ".py"

View file

@ -14,13 +14,14 @@ How to run this:
import logging import logging
import optparse import optparse
import sys import sys
from builtins import range
import ns.core import ns.core
import ns.network import ns.network
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
from corens3.obj import Ns3WifiNet from corens3.obj import Ns3WifiNet
from core.nodes import nodeutils, nodemaps, ipaddress from core.nodes import ipaddress
def add_to_server(session): def add_to_server(session):
@ -40,7 +41,6 @@ def wifisession(opt):
""" """
Run a random walk wifi session. Run a random walk wifi session.
""" """
nodeutils.set_node_map(nodemaps.NODES)
session = Ns3Session(1, persistent=True, duration=opt.duration) session = Ns3Session(1, persistent=True, duration=opt.duration)
session.name = "ns3wifirandomwalk" session.name = "ns3wifirandomwalk"
session.filename = session.name + ".py" session.filename = session.name + ".py"
@ -54,7 +54,7 @@ def wifisession(opt):
prefix = ipaddress.Ipv4Prefix("10.0.0.0/16") prefix = ipaddress.Ipv4Prefix("10.0.0.0/16")
services_str = "zebra|OSPFv3MDR|IPForward" services_str = "zebra|OSPFv3MDR|IPForward"
nodes = [] nodes = []
for i in xrange(1, opt.numnodes + 1): for i in range(1, opt.numnodes + 1):
node = session.addnode(name="n%d" % i) node = session.addnode(name="n%d" % i)
node.newnetif(wifi, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) node.newnetif(wifi, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
nodes.append(node) nodes.append(node)

View file

@ -12,17 +12,18 @@ Current issues:
import logging import logging
import optparse import optparse
import sys import sys
from builtins import range
from core.nodes import nodeutils, nodemaps, ipaddress
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
from corens3.obj import Ns3WimaxNet from corens3.obj import Ns3WimaxNet
from core.nodes import ipaddress
def wimaxsession(opt): def wimaxsession(opt):
""" """
Run a test wimax session. Run a test wimax session.
""" """
nodeutils.set_node_map(nodemaps.NODES)
session = Ns3Session(1, persistent=True, duration=opt.duration) session = Ns3Session(1, persistent=True, duration=opt.duration)
wimax = session.create_node(cls=Ns3WimaxNet, name="wlan1") wimax = session.create_node(cls=Ns3WimaxNet, name="wlan1")
# wimax.wimax.EnableLogComponents() # wimax.wimax.EnableLogComponents()
@ -33,7 +34,7 @@ def wimaxsession(opt):
# classifier = (0, 65000, 0, 65000, 1, 1) # classifier = (0, 65000, 0, 65000, 1, 1)
classifier = (0, 65000, 0, 65000, 17, 1) classifier = (0, 65000, 0, 65000, 17, 1)
nodes = [] nodes = []
for i in xrange(1, opt.numnodes + 1): for i in range(1, opt.numnodes + 1):
node = session.addnode(name="n%d" % i) node = session.addnode(name="n%d" % i)
if i == 1: if i == 1:
wimax.setbasestation(node) wimax.setbasestation(node)