daemon: adjustments to revamp how core nodes are created in session.add_node, nodes now provide a create_options function for node specific options that are type hinted
This commit is contained in:
parent
03e646031c
commit
2e3e085522
35 changed files with 646 additions and 478 deletions
|
@ -17,15 +17,22 @@ from core.api.grpc.services_pb2 import (
|
|||
ServiceDefaults,
|
||||
)
|
||||
from core.config import ConfigurableOptions
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
|
||||
from core.emane.nodes import EmaneNet, EmaneOptions
|
||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
||||
from core.emulator.enumerations import LinkTypes, NodeTypes
|
||||
from core.emulator.links import CoreLink
|
||||
from core.emulator.session import Session
|
||||
from core.errors import CoreError
|
||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.base import (
|
||||
CoreNode,
|
||||
CoreNodeBase,
|
||||
CoreNodeOptions,
|
||||
NodeBase,
|
||||
NodeOptions,
|
||||
Position,
|
||||
)
|
||||
from core.nodes.docker import DockerNode, DockerOptions
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.nodes.lxd import LxcNode
|
||||
from core.nodes.network import CoreNetwork, CtrlNet, PtpNet, WlanNode
|
||||
|
@ -55,34 +62,33 @@ class CpuUsage:
|
|||
return (total_diff - idle_diff) / total_diff
|
||||
|
||||
|
||||
def add_node_data(node_proto: core_pb2.Node) -> Tuple[NodeTypes, int, NodeOptions]:
|
||||
def add_node_data(
|
||||
_class: Type[NodeBase], node_proto: core_pb2.Node
|
||||
) -> Tuple[Position, NodeOptions]:
|
||||
"""
|
||||
Convert node protobuf message to data for creating a node.
|
||||
|
||||
:param _class: node class to create options from
|
||||
:param node_proto: node proto message
|
||||
:return: node type, id, and options
|
||||
"""
|
||||
_id = node_proto.id
|
||||
_type = NodeTypes(node_proto.type)
|
||||
options = NodeOptions(
|
||||
name=node_proto.name,
|
||||
model=node_proto.model,
|
||||
icon=node_proto.icon,
|
||||
image=node_proto.image,
|
||||
services=node_proto.services,
|
||||
config_services=node_proto.config_services,
|
||||
canvas=node_proto.canvas,
|
||||
)
|
||||
if node_proto.emane:
|
||||
options.emane = node_proto.emane
|
||||
if node_proto.server:
|
||||
options.server = node_proto.server
|
||||
position = node_proto.position
|
||||
options.set_position(position.x, position.y)
|
||||
options = _class.create_options()
|
||||
options.icon = node_proto.icon
|
||||
options.canvas = node_proto.canvas
|
||||
if isinstance(options, CoreNodeOptions):
|
||||
options.model = node_proto.model
|
||||
options.services = node_proto.services
|
||||
options.config_services = node_proto.config_services
|
||||
if isinstance(options, EmaneOptions):
|
||||
options.emane_model = node_proto.emane
|
||||
if isinstance(options, DockerOptions):
|
||||
options.image = node_proto.image
|
||||
position = Position()
|
||||
position.set(node_proto.position.x, node_proto.position.y)
|
||||
if node_proto.HasField("geo"):
|
||||
geo = node_proto.geo
|
||||
options.set_location(geo.lat, geo.lon, geo.alt)
|
||||
return _type, _id, options
|
||||
position.set_geo(geo.lon, geo.lat, geo.alt)
|
||||
return position, options
|
||||
|
||||
|
||||
def link_iface(iface_proto: core_pb2.Interface) -> InterfaceData:
|
||||
|
@ -150,9 +156,17 @@ def create_nodes(
|
|||
"""
|
||||
funcs = []
|
||||
for node_proto in node_protos:
|
||||
_type, _id, options = add_node_data(node_proto)
|
||||
_type = NodeTypes(node_proto.type)
|
||||
_class = session.get_node_class(_type)
|
||||
args = (_class, _id, options)
|
||||
position, options = add_node_data(_class, node_proto)
|
||||
args = (
|
||||
_class,
|
||||
node_proto.id or None,
|
||||
node_proto.name or None,
|
||||
node_proto.server or None,
|
||||
position,
|
||||
options,
|
||||
)
|
||||
funcs.append((session.add_node, args, {}))
|
||||
start = time.monotonic()
|
||||
results, exceptions = utils.threadpool(funcs)
|
||||
|
|
|
@ -88,7 +88,12 @@ from core.configservice.base import ConfigServiceBootError
|
|||
from core.emane.modelmanager import EmaneModelManager
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
||||
from core.emulator.enumerations import EventTypes, ExceptionLevels, MessageFlags
|
||||
from core.emulator.enumerations import (
|
||||
EventTypes,
|
||||
ExceptionLevels,
|
||||
MessageFlags,
|
||||
NodeTypes,
|
||||
)
|
||||
from core.emulator.session import NT, Session
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
|
@ -548,9 +553,17 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logger.debug("add node: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
_type, _id, options = grpcutils.add_node_data(request.node)
|
||||
_type = NodeTypes(request.node.type)
|
||||
_class = session.get_node_class(_type)
|
||||
node = session.add_node(_class, _id, options)
|
||||
position, options = grpcutils.add_node_data(_class, request.node)
|
||||
node = session.add_node(
|
||||
_class,
|
||||
request.node.id or None,
|
||||
request.node.name or None,
|
||||
request.node.server or None,
|
||||
position,
|
||||
options,
|
||||
)
|
||||
grpcutils.configure_node(session, request.node, node, context)
|
||||
source = request.source if request.source else None
|
||||
session.broadcast_node(node, MessageFlags.ADD, source)
|
||||
|
|
|
@ -603,7 +603,7 @@ class EmaneManager:
|
|||
node = iface.node
|
||||
loglevel = str(DEFAULT_LOG_LEVEL)
|
||||
cfgloglevel = self.session.options.get_int("emane_log_level", 2)
|
||||
realtime = self.session.options.get_bool("emane_realtime")
|
||||
realtime = self.session.options.get_bool("emane_realtime", True)
|
||||
if cfgloglevel:
|
||||
logger.info("setting user-defined emane log level: %d", cfgloglevel)
|
||||
loglevel = str(cfgloglevel)
|
||||
|
|
|
@ -5,13 +5,14 @@ share the same MAC+PHY model.
|
|||
|
||||
import logging
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Type, Union
|
||||
|
||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
||||
from core.emulator.distributed import DistributedServer
|
||||
from core.emulator.enumerations import EventTypes, MessageFlags, RegisterTlvs
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode, NodeOptions
|
||||
from core.nodes.interface import CoreInterface
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -139,6 +140,12 @@ class TunTap(CoreInterface):
|
|||
self.node.node_net_client.create_address(self.name, str(ip))
|
||||
|
||||
|
||||
@dataclass
|
||||
class EmaneOptions(NodeOptions):
|
||||
emane_model: str = None
|
||||
"""name of emane model to associate an emane network to"""
|
||||
|
||||
|
||||
class EmaneNet(CoreNetworkBase):
|
||||
"""
|
||||
EMANE node contains NEM configuration and causes connected nodes
|
||||
|
@ -152,11 +159,20 @@ class EmaneNet(CoreNetworkBase):
|
|||
_id: int = None,
|
||||
name: str = None,
|
||||
server: DistributedServer = None,
|
||||
options: EmaneOptions = None,
|
||||
) -> None:
|
||||
super().__init__(session, _id, name, server)
|
||||
options = options or EmaneOptions()
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.conf: str = ""
|
||||
self.wireless_model: Optional["EmaneModel"] = None
|
||||
self.mobility: Optional[WayPointMobility] = None
|
||||
model_class = self.session.emane.get_model(options.emane_model)
|
||||
self.wireless_model: Optional["EmaneModel"] = model_class(self.session, self.id)
|
||||
if self.session.state == EventTypes.RUNTIME_STATE:
|
||||
self.session.emane.add_node(self)
|
||||
|
||||
@classmethod
|
||||
def create_options(cls) -> EmaneOptions:
|
||||
return EmaneOptions()
|
||||
|
||||
def linkconfig(
|
||||
self, iface: CoreInterface, options: LinkOptions, iface2: CoreInterface = None
|
||||
|
|
|
@ -14,7 +14,7 @@ import tempfile
|
|||
import threading
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar, Union
|
||||
from typing import Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar, Union
|
||||
|
||||
from core import constants, utils
|
||||
from core.configservice.manager import ConfigServiceManager
|
||||
|
@ -29,7 +29,6 @@ from core.emulator.data import (
|
|||
LinkData,
|
||||
LinkOptions,
|
||||
NodeData,
|
||||
NodeOptions,
|
||||
)
|
||||
from core.emulator.distributed import DistributedController
|
||||
from core.emulator.enumerations import (
|
||||
|
@ -44,7 +43,7 @@ from core.errors import CoreError
|
|||
from core.location.event import EventLoop
|
||||
from core.location.geo import GeoLocation
|
||||
from core.location.mobility import BasicRangeModel, MobilityManager
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode, CoreNodeBase, NodeBase
|
||||
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase, NodeOptions, Position
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.interface import DEFAULT_MTU, CoreInterface
|
||||
from core.nodes.lxd import LxcNode
|
||||
|
@ -476,14 +475,23 @@ class Session:
|
|||
return _id
|
||||
|
||||
def add_node(
|
||||
self, _class: Type[NT], _id: int = None, options: NodeOptions = None
|
||||
self,
|
||||
_class: Type[NT],
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
server: str = None,
|
||||
position: Position = None,
|
||||
options: NodeOptions = None,
|
||||
) -> NT:
|
||||
"""
|
||||
Add a node to the session, based on the provided node data.
|
||||
|
||||
:param _class: node class to create
|
||||
:param _id: id for node, defaults to None for generated id
|
||||
:param options: data to create node with
|
||||
:param name: name to assign to node
|
||||
:param server: distributed server for node, if desired
|
||||
:param position: geo or x/y/z position to set
|
||||
:param options: options to create node with
|
||||
:return: created node
|
||||
:raises core.CoreError: when an invalid node type is given
|
||||
"""
|
||||
|
@ -492,89 +500,31 @@ class Session:
|
|||
enable_rj45 = self.options.get_int("enablerj45") == 1
|
||||
if _class == Rj45Node and not enable_rj45:
|
||||
start = False
|
||||
|
||||
# determine node id
|
||||
if not _id:
|
||||
_id = self.next_node_id()
|
||||
|
||||
# generate name if not provided
|
||||
if not options:
|
||||
options = NodeOptions()
|
||||
options.set_position(0, 0)
|
||||
name = options.name
|
||||
if not name:
|
||||
name = f"{_class.__name__}{_id}"
|
||||
|
||||
# generate options if not provided
|
||||
options = options if options else _class.create_options()
|
||||
# verify distributed server
|
||||
server = self.distributed.servers.get(options.server)
|
||||
if options.server is not None and server is None:
|
||||
raise CoreError(f"invalid distributed server: {options.server}")
|
||||
|
||||
dist_server = None
|
||||
if server is not None:
|
||||
dist_server = self.distributed.servers.get(server)
|
||||
if not dist_server:
|
||||
raise CoreError(f"invalid distributed server: {server}")
|
||||
# create node
|
||||
logger.info(
|
||||
"creating node(%s) id(%s) name(%s) start(%s)",
|
||||
_class.__name__,
|
||||
_id,
|
||||
name,
|
||||
start,
|
||||
)
|
||||
kwargs = dict(_id=_id, name=name, server=server)
|
||||
if _class in CONTAINER_NODES:
|
||||
kwargs["image"] = options.image
|
||||
kwargs["binds"] = options.binds
|
||||
kwargs["volumes"] = options.volumes
|
||||
node = self.create_node(_class, start, **kwargs)
|
||||
|
||||
# set node attributes
|
||||
node.icon = options.icon
|
||||
node.canvas = options.canvas
|
||||
|
||||
# set node position and broadcast it
|
||||
has_geo = all(i is not None for i in [options.lon, options.lat, options.alt])
|
||||
if has_geo:
|
||||
self.set_node_geo(node, options.lon, options.lat, options.alt)
|
||||
node = self.create_node(_class, start, _id, name, dist_server, options)
|
||||
# set node position
|
||||
position = position or Position()
|
||||
if position.has_geo():
|
||||
self.set_node_geo(node, position.lon, position.lat, position.alt)
|
||||
else:
|
||||
self.set_node_pos(node, options.x, options.y)
|
||||
|
||||
# add services to needed nodes
|
||||
if isinstance(node, (CoreNode, PhysicalNode)):
|
||||
node.model = options.model
|
||||
if options.legacy or options.services:
|
||||
logger.debug("set node type: %s", node.model)
|
||||
self.services.add_services(node, node.model, options.services)
|
||||
|
||||
# add config services
|
||||
config_services = options.config_services
|
||||
if not options.legacy and not config_services and not node.services:
|
||||
config_services = self.services.default_services.get(node.model, [])
|
||||
logger.info("setting node config services: %s", config_services)
|
||||
for name in config_services:
|
||||
service_class = self.service_manager.get_service(name)
|
||||
node.add_config_service(service_class)
|
||||
|
||||
# set network mtu, if configured
|
||||
mtu = self.options.get_int("mtu")
|
||||
if isinstance(node, CoreNetworkBase) and mtu > 0:
|
||||
node.mtu = mtu
|
||||
|
||||
# ensure default emane configuration
|
||||
if isinstance(node, EmaneNet) and options.emane:
|
||||
model_class = self.emane.get_model(options.emane)
|
||||
node.wireless_model = model_class(self, node.id)
|
||||
if self.state == EventTypes.RUNTIME_STATE:
|
||||
self.emane.add_node(node)
|
||||
|
||||
# set default wlan config if needed
|
||||
self.set_node_pos(node, position.x, position.y)
|
||||
# setup default wlan
|
||||
if isinstance(node, WlanNode):
|
||||
self.mobility.set_model_config(_id, BasicRangeModel.name)
|
||||
|
||||
# boot nodes after runtime CoreNodes and PhysicalNodes
|
||||
is_boot_node = isinstance(node, (CoreNode, PhysicalNode))
|
||||
if self.state == EventTypes.RUNTIME_STATE and is_boot_node:
|
||||
self.mobility.set_model_config(self.id, BasicRangeModel.name)
|
||||
# boot core nodes after runtime
|
||||
is_runtime = self.state == EventTypes.RUNTIME_STATE
|
||||
if is_runtime and isinstance(node, CoreNode):
|
||||
self.write_nodes()
|
||||
self.add_remove_control_iface(node, remove=False)
|
||||
self.boot_node(node)
|
||||
|
||||
self.sdt.add_node(node)
|
||||
return node
|
||||
|
||||
|
@ -980,24 +930,39 @@ class Session:
|
|||
logger.exception("failed to set permission on %s", self.directory)
|
||||
|
||||
def create_node(
|
||||
self, _class: Type[NT], start: bool, *args: Any, **kwargs: Any
|
||||
self,
|
||||
_class: Type[NT],
|
||||
start: bool,
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
server: str = None,
|
||||
options: NodeOptions = None,
|
||||
) -> NT:
|
||||
"""
|
||||
Create an emulation node.
|
||||
|
||||
:param _class: node class to create
|
||||
:param start: True to start node, False otherwise
|
||||
:param args: list of arguments for the class to create
|
||||
:param kwargs: dictionary of arguments for the class to create
|
||||
:param _id: id for node, defaults to None for generated id
|
||||
:param name: name to assign to node
|
||||
:param server: distributed server for node, if desired
|
||||
:param options: options to create node with
|
||||
:return: the created node instance
|
||||
:raises core.CoreError: when id of the node to create already exists
|
||||
"""
|
||||
with self.nodes_lock:
|
||||
node = _class(self, *args, **kwargs)
|
||||
node = _class(self, _id=_id, name=name, server=server, options=options)
|
||||
if node.id in self.nodes:
|
||||
node.shutdown()
|
||||
raise CoreError(f"duplicate node id {node.id} for {node.name}")
|
||||
self.nodes[node.id] = node
|
||||
logger.info(
|
||||
"created node(%s) id(%s) name(%s) start(%s)",
|
||||
_class.__name__,
|
||||
node.id,
|
||||
node.name,
|
||||
start,
|
||||
)
|
||||
if start:
|
||||
node.startup()
|
||||
return node
|
||||
|
@ -1219,7 +1184,7 @@ class Session:
|
|||
funcs = []
|
||||
start = time.monotonic()
|
||||
for node in self.nodes.values():
|
||||
if isinstance(node, (CoreNode, PhysicalNode)):
|
||||
if isinstance(node, CoreNode):
|
||||
self.add_remove_control_iface(node, remove=False)
|
||||
funcs.append((self.boot_node, (node,), {}))
|
||||
results, exceptions = utils.threadpool(funcs)
|
||||
|
@ -1354,21 +1319,18 @@ class Session:
|
|||
updown_script,
|
||||
server_iface,
|
||||
)
|
||||
control_net = self.create_node(
|
||||
CtrlNet,
|
||||
start=False,
|
||||
prefix=prefix,
|
||||
_id=_id,
|
||||
updown_script=updown_script,
|
||||
serverintf=server_iface,
|
||||
)
|
||||
options = CtrlNet.create_options()
|
||||
options.prefix = prefix
|
||||
options.updown_script = updown_script
|
||||
options.serverintf = server_iface
|
||||
control_net = self.create_node(CtrlNet, False, _id, options=options)
|
||||
control_net.brname = f"ctrl{net_index}.{self.short_session_id()}"
|
||||
control_net.startup()
|
||||
return control_net
|
||||
|
||||
def add_remove_control_iface(
|
||||
self,
|
||||
node: Union[CoreNode, PhysicalNode],
|
||||
node: CoreNode,
|
||||
net_index: int = 0,
|
||||
remove: bool = False,
|
||||
conf_required: bool = True,
|
||||
|
|
|
@ -5,6 +5,7 @@ import abc
|
|||
import logging
|
||||
import shutil
|
||||
import threading
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from threading import RLock
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type, Union
|
||||
|
@ -33,6 +34,94 @@ if TYPE_CHECKING:
|
|||
PRIVATE_DIRS: List[Path] = [Path("/var/run"), Path("/var/log")]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Position:
|
||||
"""
|
||||
Helper class for Cartesian coordinate position
|
||||
"""
|
||||
|
||||
x: float = 0.0
|
||||
y: float = 0.0
|
||||
z: float = 0.0
|
||||
lon: float = None
|
||||
lat: float = None
|
||||
alt: float = None
|
||||
|
||||
def set(self, x: float = None, y: float = None, z: float = None) -> bool:
|
||||
"""
|
||||
Returns True if the position has actually changed.
|
||||
|
||||
:param x: x position
|
||||
:param y: y position
|
||||
:param z: z position
|
||||
:return: True if position changed, False otherwise
|
||||
"""
|
||||
if self.x == x and self.y == y and self.z == z:
|
||||
return False
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
return True
|
||||
|
||||
def get(self) -> Tuple[float, float, float]:
|
||||
"""
|
||||
Retrieve x,y,z position.
|
||||
|
||||
:return: x,y,z position tuple
|
||||
"""
|
||||
return self.x, self.y, self.z
|
||||
|
||||
def has_geo(self) -> bool:
|
||||
return all(x is not None for x in [self.lon, self.lat, self.alt])
|
||||
|
||||
def set_geo(self, lon: float, lat: float, alt: float) -> None:
|
||||
"""
|
||||
Set geo position lon, lat, alt.
|
||||
|
||||
:param lon: longitude value
|
||||
:param lat: latitude value
|
||||
:param alt: altitude value
|
||||
:return: nothing
|
||||
"""
|
||||
self.lon = lon
|
||||
self.lat = lat
|
||||
self.alt = alt
|
||||
|
||||
def get_geo(self) -> Tuple[float, float, float]:
|
||||
"""
|
||||
Retrieve current geo position lon, lat, alt.
|
||||
|
||||
:return: lon, lat, alt position tuple
|
||||
"""
|
||||
return self.lon, self.lat, self.alt
|
||||
|
||||
|
||||
@dataclass
|
||||
class NodeOptions:
|
||||
"""
|
||||
Base options for configuring a node.
|
||||
"""
|
||||
|
||||
canvas: int = None
|
||||
"""id of canvas for display within gui"""
|
||||
icon: str = None
|
||||
"""custom icon for display, None for default"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class CoreNodeOptions(NodeOptions):
|
||||
model: str = "PC"
|
||||
"""model is used for providing a default set of services"""
|
||||
services: List[str] = field(default_factory=list)
|
||||
"""services to start within node"""
|
||||
config_services: List[str] = field(default_factory=list)
|
||||
"""config services to start within node"""
|
||||
directory: Path = None
|
||||
"""directory to define node, defaults to path under the session directory"""
|
||||
legacy: bool = False
|
||||
"""legacy nodes default to standard services"""
|
||||
|
||||
|
||||
class NodeBase(abc.ABC):
|
||||
"""
|
||||
Base class for CORE nodes (nodes and networks)
|
||||
|
@ -44,6 +133,7 @@ class NodeBase(abc.ABC):
|
|||
_id: int = None,
|
||||
name: str = None,
|
||||
server: "DistributedServer" = None,
|
||||
options: NodeOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Creates a NodeBase instance.
|
||||
|
@ -53,26 +143,29 @@ class NodeBase(abc.ABC):
|
|||
:param name: object name
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param options: options to create node with
|
||||
"""
|
||||
|
||||
self.session: "Session" = session
|
||||
if _id is None:
|
||||
_id = session.next_node_id()
|
||||
self.id: int = _id
|
||||
self.name: str = name or f"o{self.id}"
|
||||
self.id: int = _id if _id is not None else self.session.next_node_id()
|
||||
self.name: str = name or f"{self.__class__.__name__}{self.id}"
|
||||
self.server: "DistributedServer" = server
|
||||
self.model: Optional[str] = None
|
||||
self.services: CoreServices = []
|
||||
self.ifaces: Dict[int, CoreInterface] = {}
|
||||
self.iface_id: int = 0
|
||||
self.canvas: Optional[int] = None
|
||||
self.icon: Optional[str] = None
|
||||
self.position: Position = Position()
|
||||
self.up: bool = False
|
||||
self.lock: RLock = RLock()
|
||||
self.net_client: LinuxNetClient = get_net_client(
|
||||
self.session.use_ovs(), self.host_cmd
|
||||
)
|
||||
options = options if options else NodeOptions()
|
||||
self.canvas: Optional[int] = options.canvas
|
||||
self.icon: Optional[str] = options.icon
|
||||
|
||||
@classmethod
|
||||
def create_options(cls) -> NodeOptions:
|
||||
return NodeOptions()
|
||||
|
||||
@abc.abstractmethod
|
||||
def startup(self) -> None:
|
||||
|
@ -288,6 +381,7 @@ class CoreNodeBase(NodeBase):
|
|||
_id: int = None,
|
||||
name: str = None,
|
||||
server: "DistributedServer" = None,
|
||||
options: NodeOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Create a CoreNodeBase instance.
|
||||
|
@ -298,7 +392,7 @@ class CoreNodeBase(NodeBase):
|
|||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
"""
|
||||
super().__init__(session, _id, name, server)
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.config_services: Dict[str, "ConfigService"] = {}
|
||||
self.directory: Optional[Path] = None
|
||||
self.tmpnodedir: bool = False
|
||||
|
@ -460,8 +554,8 @@ class CoreNode(CoreNodeBase):
|
|||
session: "Session",
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
directory: Path = None,
|
||||
server: "DistributedServer" = None,
|
||||
options: CoreNodeOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Create a CoreNode instance.
|
||||
|
@ -469,18 +563,37 @@ class CoreNode(CoreNodeBase):
|
|||
:param session: core session instance
|
||||
:param _id: object id
|
||||
:param name: object name
|
||||
:param directory: node directory
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param options: options to create node with
|
||||
"""
|
||||
super().__init__(session, _id, name, server)
|
||||
self.directory: Optional[Path] = directory
|
||||
options = options or CoreNodeOptions()
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.directory: Optional[Path] = options.directory
|
||||
self.ctrlchnlname: Path = self.session.directory / self.name
|
||||
self.pid: Optional[int] = None
|
||||
self._mounts: List[Tuple[Path, Path]] = []
|
||||
self.node_net_client: LinuxNetClient = self.create_node_net_client(
|
||||
self.session.use_ovs()
|
||||
)
|
||||
options = options or CoreNodeOptions()
|
||||
self.model: Optional[str] = options.model
|
||||
# setup services
|
||||
if options.legacy or options.services:
|
||||
logger.debug("set node type: %s", self.model)
|
||||
self.session.services.add_services(self, self.model, options.services)
|
||||
# add config services
|
||||
config_services = options.config_services
|
||||
if not options.legacy and not config_services and not options.services:
|
||||
config_services = self.session.services.default_services.get(self.model, [])
|
||||
logger.info("setting node config services: %s", config_services)
|
||||
for name in config_services:
|
||||
service_class = self.session.service_manager.get_service(name)
|
||||
self.add_config_service(service_class)
|
||||
|
||||
@classmethod
|
||||
def create_options(cls) -> CoreNodeOptions:
|
||||
return CoreNodeOptions()
|
||||
|
||||
def create_node_net_client(self, use_ovs: bool) -> LinuxNetClient:
|
||||
"""
|
||||
|
@ -797,6 +910,7 @@ class CoreNetworkBase(NodeBase):
|
|||
_id: int,
|
||||
name: str,
|
||||
server: "DistributedServer" = None,
|
||||
options: NodeOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Create a CoreNetworkBase instance.
|
||||
|
@ -806,9 +920,11 @@ class CoreNetworkBase(NodeBase):
|
|||
:param name: object name
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param options: options to create node with
|
||||
"""
|
||||
super().__init__(session, _id, name, server)
|
||||
self.mtu: int = DEFAULT_MTU
|
||||
super().__init__(session, _id, name, server, options)
|
||||
mtu = self.session.options.get_int("mtu")
|
||||
self.mtu: int = mtu if mtu > 0 else DEFAULT_MTU
|
||||
self.brname: Optional[str] = None
|
||||
self.linked: Dict[CoreInterface, Dict[CoreInterface, bool]] = {}
|
||||
self.linked_lock: threading.Lock = threading.Lock()
|
||||
|
@ -839,69 +955,3 @@ class CoreNetworkBase(NodeBase):
|
|||
iface.net_id = None
|
||||
with self.linked_lock:
|
||||
del self.linked[iface]
|
||||
|
||||
|
||||
class Position:
|
||||
"""
|
||||
Helper class for Cartesian coordinate position
|
||||
"""
|
||||
|
||||
def __init__(self, x: float = None, y: float = None, z: float = None) -> None:
|
||||
"""
|
||||
Creates a Position instance.
|
||||
|
||||
:param x: x position
|
||||
:param y: y position
|
||||
:param z: z position
|
||||
"""
|
||||
self.x: float = x
|
||||
self.y: float = y
|
||||
self.z: float = z
|
||||
self.lon: Optional[float] = None
|
||||
self.lat: Optional[float] = None
|
||||
self.alt: Optional[float] = None
|
||||
|
||||
def set(self, x: float = None, y: float = None, z: float = None) -> bool:
|
||||
"""
|
||||
Returns True if the position has actually changed.
|
||||
|
||||
:param x: x position
|
||||
:param y: y position
|
||||
:param z: z position
|
||||
:return: True if position changed, False otherwise
|
||||
"""
|
||||
if self.x == x and self.y == y and self.z == z:
|
||||
return False
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
return True
|
||||
|
||||
def get(self) -> Tuple[float, float, float]:
|
||||
"""
|
||||
Retrieve x,y,z position.
|
||||
|
||||
:return: x,y,z position tuple
|
||||
"""
|
||||
return self.x, self.y, self.z
|
||||
|
||||
def set_geo(self, lon: float, lat: float, alt: float) -> None:
|
||||
"""
|
||||
Set geo position lon, lat, alt.
|
||||
|
||||
:param lon: longitude value
|
||||
:param lat: latitude value
|
||||
:param alt: altitude value
|
||||
:return: nothing
|
||||
"""
|
||||
self.lon = lon
|
||||
self.lat = lat
|
||||
self.alt = alt
|
||||
|
||||
def get_geo(self) -> Tuple[float, float, float]:
|
||||
"""
|
||||
Retrieve current geo position lon, lat, alt.
|
||||
|
||||
:return: lon, lat, alt position tuple
|
||||
"""
|
||||
return self.lon, self.lat, self.alt
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import json
|
||||
import logging
|
||||
import shlex
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import TYPE_CHECKING, Dict, List, Tuple
|
||||
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Dict, List, Tuple
|
|||
from core.emulator.distributed import DistributedServer
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.executables import BASH
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, CoreNodeOptions
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -19,6 +19,21 @@ if TYPE_CHECKING:
|
|||
DOCKER: str = "docker"
|
||||
|
||||
|
||||
@dataclass
|
||||
class DockerOptions(CoreNodeOptions):
|
||||
image: str = "ubuntu"
|
||||
"""image used when creating container"""
|
||||
binds: List[Tuple[str, str]] = field(default_factory=list)
|
||||
"""bind mount source and destinations to setup within container"""
|
||||
volumes: List[Tuple[str, str, bool, bool]] = field(default_factory=list)
|
||||
"""
|
||||
volume mount source, destination, unique, delete to setup within container
|
||||
|
||||
unique is True for node unique volume naming
|
||||
delete is True for deleting volume mount during shutdown
|
||||
"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class DockerVolume:
|
||||
src: str
|
||||
|
@ -38,11 +53,8 @@ class DockerNode(CoreNode):
|
|||
session: "Session",
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
directory: str = None,
|
||||
server: DistributedServer = None,
|
||||
image: str = None,
|
||||
binds: List[Tuple[str, str]] = None,
|
||||
volumes: List[Tuple[str, str, bool, bool]] = None,
|
||||
options: DockerOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Create a DockerNode instance.
|
||||
|
@ -50,22 +62,23 @@ class DockerNode(CoreNode):
|
|||
:param session: core session instance
|
||||
:param _id: object id
|
||||
:param name: object name
|
||||
:param directory: node directory
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param image: image to start container with
|
||||
:param binds: bind mounts to set for the created container
|
||||
:param volumes: volume mount settings to set for the created container
|
||||
:param options: options for creating node
|
||||
"""
|
||||
super().__init__(session, _id, name, directory, server)
|
||||
self.image: str = image if image is not None else "ubuntu"
|
||||
self.binds: List[Tuple[str, str]] = binds or []
|
||||
options = options or DockerOptions()
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.image: str = options.image
|
||||
self.binds: List[Tuple[str, str]] = options.binds
|
||||
self.volumes: Dict[str, DockerVolume] = {}
|
||||
volumes = volumes or []
|
||||
for src, dst, unique, delete in volumes:
|
||||
for src, dst, unique, delete in options.volumes:
|
||||
src_name = self._unique_name(src) if unique else src
|
||||
self.volumes[src] = DockerVolume(src_name, dst, unique, delete)
|
||||
|
||||
@classmethod
|
||||
def create_options(cls) -> DockerOptions:
|
||||
return DockerOptions()
|
||||
|
||||
def _create_cmd(self, args: str, shell: bool = False) -> str:
|
||||
"""
|
||||
Create command used to run commands within the context of a node.
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import json
|
||||
import logging
|
||||
import time
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import TYPE_CHECKING, Callable, Dict, Optional
|
||||
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
|
||||
|
||||
from core import utils
|
||||
from core.emulator.data import InterfaceData, LinkOptions
|
||||
from core.emulator.distributed import DistributedServer
|
||||
from core.errors import CoreCommandError
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, CoreNodeOptions
|
||||
from core.nodes.interface import CoreInterface
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -66,15 +67,29 @@ class LxdClient:
|
|||
self.run(args)
|
||||
|
||||
|
||||
@dataclass
|
||||
class LxcOptions(CoreNodeOptions):
|
||||
image: str = "ubuntu"
|
||||
"""image used when creating container"""
|
||||
binds: List[Tuple[str, str]] = field(default_factory=list)
|
||||
"""bind mount source and destinations to setup within container"""
|
||||
volumes: List[Tuple[str, str, bool, bool]] = field(default_factory=list)
|
||||
"""
|
||||
volume mount source, destination, unique, delete to setup within container
|
||||
|
||||
unique is True for node unique volume naming
|
||||
delete is True for deleting volume mount during shutdown
|
||||
"""
|
||||
|
||||
|
||||
class LxcNode(CoreNode):
|
||||
def __init__(
|
||||
self,
|
||||
session: "Session",
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
directory: str = None,
|
||||
server: DistributedServer = None,
|
||||
image: str = None,
|
||||
options: LxcOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Create a LxcNode instance.
|
||||
|
@ -82,15 +97,19 @@ class LxcNode(CoreNode):
|
|||
:param session: core session instance
|
||||
:param _id: object id
|
||||
:param name: object name
|
||||
:param directory: node directory
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param image: image to start container with
|
||||
:param options: option to create node with
|
||||
"""
|
||||
super().__init__(session, _id, name, directory, server)
|
||||
self.image: str = image if image is not None else "ubuntu"
|
||||
options = options or LxcOptions()
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.image: str = options.image
|
||||
self.client: Optional[LxdClient] = None
|
||||
|
||||
@classmethod
|
||||
def create_options(cls) -> LxcOptions:
|
||||
return LxcOptions()
|
||||
|
||||
def alive(self) -> bool:
|
||||
"""
|
||||
Check if the node is alive.
|
||||
|
|
|
@ -4,6 +4,7 @@ Defines network nodes used within core.
|
|||
|
||||
import logging
|
||||
import threading
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Type
|
||||
|
||||
|
@ -14,7 +15,7 @@ from core.emulator.data import InterfaceData, LinkData
|
|||
from core.emulator.enumerations import MessageFlags, NetworkPolicy, RegisterTlvs
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.executables import NFTABLES
|
||||
from core.nodes.base import CoreNetworkBase
|
||||
from core.nodes.base import CoreNetworkBase, NodeOptions
|
||||
from core.nodes.interface import CoreInterface, GreTap
|
||||
from core.nodes.netclient import get_net_client
|
||||
|
||||
|
@ -180,6 +181,12 @@ class NftablesQueue:
|
|||
nft_queue: NftablesQueue = NftablesQueue()
|
||||
|
||||
|
||||
@dataclass
|
||||
class NetworkOptions(NodeOptions):
|
||||
policy: NetworkPolicy = None
|
||||
"""allows overriding the network policy, otherwise uses class defined default"""
|
||||
|
||||
|
||||
class CoreNetwork(CoreNetworkBase):
|
||||
"""
|
||||
Provides linux bridge network functionality for core nodes.
|
||||
|
@ -193,7 +200,7 @@ class CoreNetwork(CoreNetworkBase):
|
|||
_id: int = None,
|
||||
name: str = None,
|
||||
server: "DistributedServer" = None,
|
||||
policy: NetworkPolicy = None,
|
||||
options: NetworkOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Creates a CoreNetwork instance.
|
||||
|
@ -203,18 +210,19 @@ class CoreNetwork(CoreNetworkBase):
|
|||
:param name: object name
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param policy: network policy
|
||||
:param options: options to create node with
|
||||
"""
|
||||
super().__init__(session, _id, name, server)
|
||||
if name is None:
|
||||
name = str(self.id)
|
||||
if policy is not None:
|
||||
self.policy: NetworkPolicy = policy
|
||||
self.name: Optional[str] = name
|
||||
options = options or NetworkOptions()
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.policy: NetworkPolicy = options.policy if options.policy else self.policy
|
||||
sessionid = self.session.short_session_id()
|
||||
self.brname: str = f"b.{self.id}.{sessionid}"
|
||||
self.has_nftables_chain: bool = False
|
||||
|
||||
@classmethod
|
||||
def create_options(cls) -> NetworkOptions:
|
||||
return NetworkOptions()
|
||||
|
||||
def host_cmd(
|
||||
self,
|
||||
args: str,
|
||||
|
@ -482,6 +490,20 @@ class GreTapBridge(CoreNetwork):
|
|||
self.add_ips(ips)
|
||||
|
||||
|
||||
@dataclass
|
||||
class CtrlNetOptions(NetworkOptions):
|
||||
prefix: str = None
|
||||
"""ip4 network prefix to use for generating an address"""
|
||||
updown_script: str = None
|
||||
"""script to execute during startup and shutdown"""
|
||||
serverintf: str = None
|
||||
"""used to associate an interface with the control network bridge"""
|
||||
assign_address: bool = True
|
||||
"""used to determine if a specific address should be assign using hostid"""
|
||||
hostid: int = None
|
||||
"""used with assign address to """
|
||||
|
||||
|
||||
class CtrlNet(CoreNetwork):
|
||||
"""
|
||||
Control network functionality.
|
||||
|
@ -500,36 +522,32 @@ class CtrlNet(CoreNetwork):
|
|||
def __init__(
|
||||
self,
|
||||
session: "Session",
|
||||
prefix: str,
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
hostid: int = None,
|
||||
server: "DistributedServer" = None,
|
||||
assign_address: bool = True,
|
||||
updown_script: str = None,
|
||||
serverintf: str = None,
|
||||
options: CtrlNetOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Creates a CtrlNet instance.
|
||||
|
||||
:param session: core session instance
|
||||
:param _id: node id
|
||||
:param name: node namee
|
||||
:param prefix: control network ipv4 prefix
|
||||
:param hostid: host id
|
||||
:param name: node name
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param assign_address: assigned address
|
||||
:param updown_script: updown script
|
||||
:param serverintf: server interface
|
||||
:return:
|
||||
:param options: node options for creation
|
||||
"""
|
||||
self.prefix: netaddr.IPNetwork = netaddr.IPNetwork(prefix).cidr
|
||||
self.hostid: Optional[int] = hostid
|
||||
self.assign_address: bool = assign_address
|
||||
self.updown_script: Optional[str] = updown_script
|
||||
self.serverintf: Optional[str] = serverintf
|
||||
super().__init__(session, _id, name, server)
|
||||
options = options or CtrlNetOptions()
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.prefix: netaddr.IPNetwork = netaddr.IPNetwork(options.prefix).cidr
|
||||
self.hostid: Optional[int] = options.hostid
|
||||
self.assign_address: bool = options.assign_address
|
||||
self.updown_script: Optional[str] = options.updown_script
|
||||
self.serverintf: Optional[str] = options.serverintf
|
||||
|
||||
@classmethod
|
||||
def create_options(cls) -> CtrlNetOptions:
|
||||
return CtrlNetOptions()
|
||||
|
||||
def add_addresses(self, index: int) -> None:
|
||||
"""
|
||||
|
@ -669,7 +687,7 @@ class WlanNode(CoreNetwork):
|
|||
_id: int = None,
|
||||
name: str = None,
|
||||
server: "DistributedServer" = None,
|
||||
policy: NetworkPolicy = None,
|
||||
options: NetworkOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Create a WlanNode instance.
|
||||
|
@ -679,9 +697,9 @@ class WlanNode(CoreNetwork):
|
|||
:param name: node name
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param policy: wlan policy
|
||||
:param options: options to create node with
|
||||
"""
|
||||
super().__init__(session, _id, name, server, policy)
|
||||
super().__init__(session, _id, name, server, options)
|
||||
# wireless and mobility models (BasicRangeModel, Ns2WaypointMobility)
|
||||
self.wireless_model: Optional[WirelessModel] = None
|
||||
self.mobility: Optional[WayPointMobility] = None
|
||||
|
|
|
@ -13,7 +13,7 @@ from core.emulator.distributed import DistributedServer
|
|||
from core.emulator.enumerations import TransportType
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.executables import BASH, TEST, UMOUNT
|
||||
from core.nodes.base import CoreNode, CoreNodeBase
|
||||
from core.nodes.base import CoreNode, CoreNodeBase, CoreNodeOptions, NodeOptions
|
||||
from core.nodes.interface import CoreInterface
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -34,6 +34,7 @@ class Rj45Node(CoreNodeBase):
|
|||
_id: int = None,
|
||||
name: str = None,
|
||||
server: DistributedServer = None,
|
||||
options: NodeOptions = None,
|
||||
) -> None:
|
||||
"""
|
||||
Create an RJ45Node instance.
|
||||
|
@ -43,8 +44,9 @@ class Rj45Node(CoreNodeBase):
|
|||
:param name: node name
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:param options: option to create node with
|
||||
"""
|
||||
super().__init__(session, _id, name, server)
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.iface: CoreInterface = CoreInterface(
|
||||
self.iface_id, name, name, session.use_ovs(), node=self, server=server
|
||||
)
|
||||
|
@ -224,12 +226,12 @@ class PhysicalNode(CoreNode):
|
|||
session: "Session",
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
directory: Path = None,
|
||||
server: DistributedServer = None,
|
||||
options: CoreNodeOptions = None,
|
||||
) -> None:
|
||||
if not self.server:
|
||||
raise CoreError("physical nodes must be assigned to a remote server")
|
||||
super().__init__(session, _id, name, directory, server)
|
||||
super().__init__(session, _id, name, server, options)
|
||||
|
||||
def startup(self) -> None:
|
||||
with self.lock:
|
||||
|
|
|
@ -14,7 +14,7 @@ from core.emulator.data import LinkData, LinkOptions
|
|||
from core.emulator.enumerations import LinkTypes, MessageFlags
|
||||
from core.errors import CoreError
|
||||
from core.executables import NFTABLES
|
||||
from core.nodes.base import CoreNetworkBase
|
||||
from core.nodes.base import CoreNetworkBase, NodeOptions
|
||||
from core.nodes.interface import CoreInterface
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -108,8 +108,9 @@ class WirelessNode(CoreNetworkBase):
|
|||
_id: int,
|
||||
name: str,
|
||||
server: "DistributedServer" = None,
|
||||
options: NodeOptions = None,
|
||||
):
|
||||
super().__init__(session, _id, name, server)
|
||||
super().__init__(session, _id, name, server, options)
|
||||
self.bridges: Dict[int, Tuple[CoreInterface, str]] = {}
|
||||
self.links: Dict[Tuple[int, int], WirelessLink] = {}
|
||||
self.position_enabled: bool = CONFIG_ENABLED
|
||||
|
|
|
@ -8,12 +8,12 @@ import core.nodes.base
|
|||
import core.nodes.physical
|
||||
from core import utils
|
||||
from core.config import Configuration
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.data import InterfaceData, LinkOptions, NodeOptions
|
||||
from core.emane.nodes import EmaneNet, EmaneOptions
|
||||
from core.emulator.data import InterfaceData, LinkOptions
|
||||
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||
from core.errors import CoreXmlError
|
||||
from core.nodes.base import CoreNodeBase, NodeBase
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.base import CoreNodeBase, CoreNodeOptions, NodeBase, Position
|
||||
from core.nodes.docker import DockerNode, DockerOptions
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.nodes.lxd import LxcNode
|
||||
from core.nodes.network import CtrlNet, GreTapBridge, PtpNet, WlanNode
|
||||
|
@ -802,68 +802,76 @@ class CoreXmlReader:
|
|||
clazz = device_element.get("class")
|
||||
image = device_element.get("image")
|
||||
server = device_element.get("server")
|
||||
options = NodeOptions(
|
||||
name=name, model=model, image=image, icon=icon, server=server
|
||||
)
|
||||
canvas = get_int(device_element, "canvas")
|
||||
node_type = NodeTypes.DEFAULT
|
||||
if clazz == "docker":
|
||||
node_type = NodeTypes.DOCKER
|
||||
elif clazz == "lxc":
|
||||
node_type = NodeTypes.LXC
|
||||
_class = self.session.get_node_class(node_type)
|
||||
|
||||
service_elements = device_element.find("services")
|
||||
if service_elements is not None:
|
||||
options.services = [x.get("name") for x in service_elements.iterchildren()]
|
||||
|
||||
config_service_elements = device_element.find("configservices")
|
||||
if config_service_elements is not None:
|
||||
options.config_services = [
|
||||
x.get("name") for x in config_service_elements.iterchildren()
|
||||
]
|
||||
|
||||
options = _class.create_options()
|
||||
options.icon = icon
|
||||
options.canvas = canvas
|
||||
# check for special options
|
||||
if isinstance(options, CoreNodeOptions):
|
||||
options.model = model
|
||||
service_elements = device_element.find("services")
|
||||
if service_elements is not None:
|
||||
options.services.extend(
|
||||
x.get("name") for x in service_elements.iterchildren()
|
||||
)
|
||||
config_service_elements = device_element.find("configservices")
|
||||
if config_service_elements is not None:
|
||||
options.config_services.extend(
|
||||
x.get("name") for x in config_service_elements.iterchildren()
|
||||
)
|
||||
if isinstance(options, DockerOptions):
|
||||
options.image = image
|
||||
# get position information
|
||||
position_element = device_element.find("position")
|
||||
position = None
|
||||
if position_element is not None:
|
||||
position = Position()
|
||||
x = get_float(position_element, "x")
|
||||
y = get_float(position_element, "y")
|
||||
if all([x, y]):
|
||||
options.set_position(x, y)
|
||||
|
||||
position.set(x, y)
|
||||
lat = get_float(position_element, "lat")
|
||||
lon = get_float(position_element, "lon")
|
||||
alt = get_float(position_element, "alt")
|
||||
if all([lat, lon, alt]):
|
||||
options.set_location(lat, lon, alt)
|
||||
|
||||
position.set_geo(lon, lat, alt)
|
||||
logger.info("reading node id(%s) model(%s) name(%s)", node_id, model, name)
|
||||
self.session.add_node(_class, node_id, options)
|
||||
self.session.add_node(_class, node_id, name, server, position, options)
|
||||
|
||||
def read_network(self, network_element: etree.Element) -> None:
|
||||
node_id = get_int(network_element, "id")
|
||||
name = network_element.get("name")
|
||||
server = network_element.get("server")
|
||||
node_type = NodeTypes[network_element.get("type")]
|
||||
_class = self.session.get_node_class(node_type)
|
||||
icon = network_element.get("icon")
|
||||
server = network_element.get("server")
|
||||
options = NodeOptions(name=name, icon=icon, server=server)
|
||||
if node_type == NodeTypes.EMANE:
|
||||
model = network_element.get("model")
|
||||
options.emane = model
|
||||
options = _class.create_options()
|
||||
options.canvas = get_int(network_element, "canvas")
|
||||
options.icon = network_element.get("icon")
|
||||
if isinstance(options, EmaneOptions):
|
||||
options.emane_model = network_element.get("model")
|
||||
position_element = network_element.find("position")
|
||||
position = None
|
||||
if position_element is not None:
|
||||
position = Position()
|
||||
x = get_float(position_element, "x")
|
||||
y = get_float(position_element, "y")
|
||||
if all([x, y]):
|
||||
options.set_position(x, y)
|
||||
position.set(x, y)
|
||||
lat = get_float(position_element, "lat")
|
||||
lon = get_float(position_element, "lon")
|
||||
alt = get_float(position_element, "alt")
|
||||
if all([lat, lon, alt]):
|
||||
options.set_location(lat, lon, alt)
|
||||
position.set_geo(lon, lat, alt)
|
||||
logger.info(
|
||||
"reading node id(%s) node_type(%s) name(%s)", node_id, node_type, name
|
||||
)
|
||||
node = self.session.add_node(_class, node_id, options)
|
||||
node = self.session.add_node(_class, node_id, name, server, position, options)
|
||||
if isinstance(node, WirelessNode):
|
||||
wireless_element = network_element.find("wireless")
|
||||
if wireless_element:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.network import SwitchNode
|
||||
|
@ -11,13 +11,13 @@ if __name__ == "__main__":
|
|||
|
||||
# setup basic network
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(model=None)
|
||||
coreemu = CoreEmu()
|
||||
session = coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
switch = session.add_node(SwitchNode)
|
||||
|
||||
# node one
|
||||
options = CoreNode.create_options()
|
||||
options.config_services = ["DefaultRoute", "IPForward"]
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
interface = prefixes.create_iface(node1)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.docker import DockerNode
|
||||
|
@ -14,9 +14,10 @@ if __name__ == "__main__":
|
|||
|
||||
try:
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(model=None, image="ubuntu")
|
||||
|
||||
# create node one
|
||||
options = DockerNode.create_options()
|
||||
options.image = "ubuntu"
|
||||
node1 = session.add_node(DockerNode, options=options)
|
||||
interface1_data = prefixes.create_iface(node1)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.docker import DockerNode
|
||||
|
||||
|
@ -15,9 +15,10 @@ if __name__ == "__main__":
|
|||
# create nodes and interfaces
|
||||
try:
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(model=None, image="ubuntu")
|
||||
|
||||
# create node one
|
||||
options = DockerNode.create_options()
|
||||
options.image = "ubuntu"
|
||||
node1 = session.add_node(DockerNode, options=options)
|
||||
interface1_data = prefixes.create_iface(node1)
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.network import SwitchNode
|
||||
|
||||
|
@ -16,12 +15,15 @@ if __name__ == "__main__":
|
|||
|
||||
try:
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(model=None, image="ubuntu")
|
||||
|
||||
# create switch
|
||||
switch = session.add_node(SwitchNode)
|
||||
|
||||
# node one
|
||||
options = DockerNode.create_options()
|
||||
options.image = "core"
|
||||
options.binds.append(("/tmp/testbind", "/tmp/bind"))
|
||||
options.volumes.append(("var.log", "/tmp/var.log", True, True))
|
||||
node1 = session.add_node(DockerNode, options=options)
|
||||
interface1_data = prefixes.create_iface(node1)
|
||||
|
||||
|
@ -30,16 +32,18 @@ if __name__ == "__main__":
|
|||
interface2_data = prefixes.create_iface(node2)
|
||||
|
||||
# node three
|
||||
node_three = session.add_node(CoreNode)
|
||||
interface_three = prefixes.create_iface(node_three)
|
||||
# node_three = session.add_node(CoreNode)
|
||||
# interface_three = prefixes.create_iface(node_three)
|
||||
|
||||
# add links
|
||||
session.add_link(node1.id, switch.id, interface1_data)
|
||||
session.add_link(node2.id, switch.id, interface2_data)
|
||||
session.add_link(node_three.id, switch.id, interface_three)
|
||||
# session.add_link(node_three.id, switch.id, interface_three)
|
||||
|
||||
# instantiate
|
||||
session.instantiate()
|
||||
|
||||
print(f"{node2.name}: {node2.volumes.values()}")
|
||||
finally:
|
||||
input("continue to shutdown")
|
||||
coreemu.shutdown()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.lxd import LxcNode
|
||||
|
@ -14,9 +14,10 @@ if __name__ == "__main__":
|
|||
|
||||
try:
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(image="ubuntu")
|
||||
|
||||
# create node one
|
||||
options = LxcNode.create_options()
|
||||
options.image = "ubuntu"
|
||||
node1 = session.add_node(LxcNode, options=options)
|
||||
interface1_data = prefixes.create_iface(node1)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.lxd import LxcNode
|
||||
|
||||
|
@ -15,9 +15,10 @@ if __name__ == "__main__":
|
|||
# create nodes and interfaces
|
||||
try:
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(image="ubuntu:18.04")
|
||||
|
||||
# create node one
|
||||
options = LxcNode.create_options()
|
||||
options.image = "ubuntu:18.04"
|
||||
node1 = session.add_node(LxcNode, options=options)
|
||||
interface1_data = prefixes.create_iface(node1)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.lxd import LxcNode
|
||||
|
@ -16,12 +16,13 @@ if __name__ == "__main__":
|
|||
|
||||
try:
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(image="ubuntu")
|
||||
|
||||
# create switch
|
||||
switch = session.add_node(SwitchNode)
|
||||
|
||||
# node one
|
||||
options = LxcNode.create_options()
|
||||
options.image = "ubuntu"
|
||||
node1 = session.add_node(LxcNode, options=options)
|
||||
interface1_data = prefixes.create_iface(node1)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import logging
|
|||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
|
||||
|
@ -50,11 +50,13 @@ def main(args):
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create local node, switch, and remote nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
emane_net = session.add_node(EmaneNet)
|
||||
session.emane.set_model(emane_net, EmaneIeee80211abgModel)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneIeee80211abgModel.name
|
||||
emane_net = session.add_node(EmaneNet, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.server = server_name
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import argparse
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.lxd import LxcNode
|
||||
|
||||
|
@ -42,7 +42,8 @@ def main(args):
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create local node, switch, and remote nodes
|
||||
options = NodeOptions(image="ubuntu:18.04")
|
||||
options = LxcNode.create_options()
|
||||
options.image = "ubuntu:18.04"
|
||||
node1 = session.add_node(LxcNode, options=options)
|
||||
options.server = server_name
|
||||
node2 = session.add_node(LxcNode, options=options)
|
||||
|
|
|
@ -7,7 +7,7 @@ import argparse
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
|
||||
|
@ -42,10 +42,8 @@ def main(args):
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create local node, switch, and remote nodes
|
||||
options = NodeOptions()
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
options.server = server_name
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
node1 = session.add_node(CoreNode)
|
||||
node2 = session.add_node(CoreNode, server=server_name)
|
||||
|
||||
# create node interfaces and link
|
||||
interface1_data = prefixes.create_iface(node1)
|
||||
|
|
|
@ -7,7 +7,7 @@ import argparse
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.network import SwitchNode
|
||||
|
@ -47,7 +47,7 @@ def main(args):
|
|||
# create local node, switch, and remote nodes
|
||||
node1 = session.add_node(CoreNode)
|
||||
switch = session.add_node(SwitchNode)
|
||||
options = NodeOptions()
|
||||
options = CoreNode.create_options()
|
||||
options.server = server_name
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
|
||||
# ip nerator for example
|
||||
ip_prefixes = IpPrefixes(ip4_prefix="10.0.0.0/24")
|
||||
|
@ -21,14 +21,20 @@ session.location.refscale = 150.0
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create emane
|
||||
options = NodeOptions(x=200, y=200, emane=EmaneIeee80211abgModel.name)
|
||||
emane = session.add_node(EmaneNet, options=options)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneIeee80211abgModel.name
|
||||
position = Position(x=200, y=200)
|
||||
emane = session.add_node(EmaneNet, position=position, options=options)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr", x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(model="mdr", x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
# configure general emane settings
|
||||
config = session.emane.get_configs()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# required imports
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
|
||||
# ip nerator for example
|
||||
ip_prefixes = IpPrefixes(ip4_prefix="10.0.0.0/24")
|
||||
|
@ -15,10 +15,10 @@ session = coreemu.create_session()
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position)
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position)
|
||||
|
||||
# link nodes together
|
||||
iface1 = ip_prefixes.create_iface(n1)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# required imports
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
from core.nodes.network import SwitchNode
|
||||
|
||||
# ip nerator for example
|
||||
|
@ -16,14 +16,14 @@ session = coreemu.create_session()
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create switch
|
||||
options = NodeOptions(x=200, y=200)
|
||||
switch = session.add_node(SwitchNode, options=options)
|
||||
position = Position(x=200, y=200)
|
||||
switch = session.add_node(SwitchNode, position=position)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position)
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position)
|
||||
|
||||
# link nodes to switch
|
||||
iface1 = ip_prefixes.create_iface(n1)
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
import logging
|
||||
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
from core.nodes.network import WlanNode
|
||||
|
||||
# enable info logging
|
||||
|
@ -21,14 +21,18 @@ session = coreemu.create_session()
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create wireless
|
||||
options = NodeOptions(x=200, y=200)
|
||||
wireless = session.add_node(WlanNode, options=options)
|
||||
position = Position(x=200, y=200)
|
||||
wireless = session.add_node(WlanNode, position=position)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr", x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(model="mdr", x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
# link nodes to wireless
|
||||
iface1 = ip_prefixes.create_iface(n1)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# required imports
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.location.mobility import BasicRangeModel
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
from core.nodes.network import WlanNode
|
||||
|
||||
# ip nerator for example
|
||||
|
@ -17,14 +17,18 @@ session = coreemu.create_session()
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create wlan
|
||||
options = NodeOptions(x=200, y=200)
|
||||
wlan = session.add_node(WlanNode, options=options)
|
||||
position = Position(x=200, y=200)
|
||||
wlan = session.add_node(WlanNode, position=position)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr", x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(model="mdr", x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
# configuring wlan
|
||||
session.mobility.set_model_config(
|
||||
|
|
|
@ -16,10 +16,10 @@ from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
|||
from core.emane.models.rfpipe import EmaneRfPipeModel
|
||||
from core.emane.models.tdma import EmaneTdmaModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.session import Session
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
|
||||
_EMANE_MODELS = [
|
||||
EmaneIeee80211abgModel,
|
||||
|
@ -53,19 +53,22 @@ class TestEmane:
|
|||
"""
|
||||
# create emane node for networking the core nodes
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions()
|
||||
options.set_position(80, 50)
|
||||
options.emane = EmaneIeee80211abgModel.name
|
||||
emane_net1 = session.add_node(EmaneNet, options=options)
|
||||
options.emane = EmaneRfPipeModel.name
|
||||
emane_net2 = session.add_node(EmaneNet, options=options)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneIeee80211abgModel.name
|
||||
position = Position(x=80, y=50)
|
||||
emane_net1 = session.add_node(EmaneNet, position=position, options=options)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneRfPipeModel.name
|
||||
position = Position(x=80, y=50)
|
||||
emane_net2 = session.add_node(EmaneNet, position=position, options=options)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(150, 150)
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
options.set_position(300, 150)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=150, y=150)
|
||||
node1 = session.add_node(CoreNode, position=position, options=options)
|
||||
position = Position(x=300, y=150)
|
||||
node2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
# create interfaces
|
||||
ip_prefix1 = IpPrefixes("10.0.0.0/24")
|
||||
|
@ -100,9 +103,10 @@ class TestEmane:
|
|||
|
||||
# create emane node for networking the core nodes
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions(emane=model.name)
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(EmaneNet, options=options)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = model.name
|
||||
position = Position(x=80, y=50)
|
||||
emane_network = session.add_node(EmaneNet, position=position, options=options)
|
||||
|
||||
# configure tdma
|
||||
if model == EmaneTdmaModel:
|
||||
|
@ -111,11 +115,12 @@ class TestEmane:
|
|||
)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(150, 150)
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
options.set_position(300, 150)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=150, y=150)
|
||||
node1 = session.add_node(CoreNode, position=position, options=options)
|
||||
position = Position(x=300, y=150)
|
||||
node2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
for i, node in enumerate([node1, node2]):
|
||||
node.setposition(x=150 * (i + 1), y=150)
|
||||
|
@ -141,9 +146,10 @@ class TestEmane:
|
|||
"""
|
||||
# create emane node for networking the core nodes
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions(emane=EmaneIeee80211abgModel.name)
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(EmaneNet, options=options)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneIeee80211abgModel.name
|
||||
position = Position(x=80, y=50)
|
||||
emane_network = session.add_node(EmaneNet, position=position, options=options)
|
||||
config_key = "txpower"
|
||||
config_value = "10"
|
||||
session.emane.set_config(
|
||||
|
@ -151,11 +157,12 @@ class TestEmane:
|
|||
)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(150, 150)
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
options.set_position(300, 150)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=150, y=150)
|
||||
node1 = session.add_node(CoreNode, position=position, options=options)
|
||||
position = Position(x=300, y=150)
|
||||
node2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
for i, node in enumerate([node1, node2]):
|
||||
node.setposition(x=150 * (i + 1), y=150)
|
||||
|
@ -205,14 +212,17 @@ class TestEmane:
|
|||
self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes
|
||||
):
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr", x=50, y=50)
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=50, y=50)
|
||||
node1 = session.add_node(CoreNode, position=position, options=options)
|
||||
iface1_data = ip_prefixes.create_iface(node1)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
node2 = session.add_node(CoreNode, position=position, options=options)
|
||||
iface2_data = ip_prefixes.create_iface(node2)
|
||||
|
||||
# create emane node
|
||||
options = NodeOptions(model=None, emane=EmaneRfPipeModel.name)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneRfPipeModel.name
|
||||
emane_node = session.add_node(EmaneNet, options=options)
|
||||
|
||||
# create links
|
||||
|
@ -255,11 +265,7 @@ class TestEmane:
|
|||
assert session.get_node(node1.id, CoreNode)
|
||||
assert session.get_node(node2.id, CoreNode)
|
||||
assert session.get_node(emane_node.id, EmaneNet)
|
||||
links = []
|
||||
for node_id in session.nodes:
|
||||
node = session.nodes[node_id]
|
||||
links += node.links()
|
||||
assert len(links) == 2
|
||||
assert len(session.link_manager.links()) == 2
|
||||
config = session.emane.get_config(node1.id, EmaneRfPipeModel.name)
|
||||
assert config["datarate"] == datarate
|
||||
|
||||
|
@ -267,14 +273,17 @@ class TestEmane:
|
|||
self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes
|
||||
):
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr", x=50, y=50)
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=50, y=50)
|
||||
node1 = session.add_node(CoreNode, position=position, options=options)
|
||||
iface1_data = ip_prefixes.create_iface(node1)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
node2 = session.add_node(CoreNode, position=position, options=options)
|
||||
iface2_data = ip_prefixes.create_iface(node2)
|
||||
|
||||
# create emane node
|
||||
options = NodeOptions(model=None, emane=EmaneRfPipeModel.name)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneRfPipeModel.name
|
||||
emane_node = session.add_node(EmaneNet, options=options)
|
||||
|
||||
# create links
|
||||
|
@ -318,10 +327,6 @@ class TestEmane:
|
|||
assert session.get_node(node1.id, CoreNode)
|
||||
assert session.get_node(node2.id, CoreNode)
|
||||
assert session.get_node(emane_node.id, EmaneNet)
|
||||
links = []
|
||||
for node_id in session.nodes:
|
||||
node = session.nodes[node_id]
|
||||
links += node.links()
|
||||
assert len(links) == 2
|
||||
assert len(session.link_manager.links()) == 2
|
||||
config = session.emane.get_config(config_id, EmaneRfPipeModel.name)
|
||||
assert config["datarate"] == datarate
|
||||
|
|
|
@ -8,7 +8,7 @@ from typing import List, Type
|
|||
|
||||
import pytest
|
||||
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.session import Session
|
||||
from core.errors import CoreCommandError
|
||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
|
@ -75,8 +75,8 @@ class TestCore:
|
|||
session.mobility.set_model(wlan_node, BasicRangeModel)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
|
||||
|
@ -105,8 +105,8 @@ class TestCore:
|
|||
session.mobility.set_model(wlan_node, BasicRangeModel)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from core.emulator.data import NodeOptions
|
||||
from core.emulator.session import Session
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.network import HubNode
|
||||
|
@ -12,8 +11,7 @@ class TestDistributed:
|
|||
|
||||
# when
|
||||
session.distributed.add_server(server_name, host)
|
||||
options = NodeOptions(server=server_name)
|
||||
node = session.add_node(CoreNode, options=options)
|
||||
node = session.add_node(CoreNode, server=server_name)
|
||||
session.instantiate()
|
||||
|
||||
# then
|
||||
|
@ -30,8 +28,7 @@ class TestDistributed:
|
|||
# when
|
||||
session.distributed.add_server(server_name, host)
|
||||
node1 = session.add_node(HubNode)
|
||||
options = NodeOptions(server=server_name)
|
||||
node2 = session.add_node(HubNode, options=options)
|
||||
node2 = session.add_node(HubNode, server=server_name)
|
||||
session.add_link(node1.id, node2.id)
|
||||
session.instantiate()
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ from core.api.grpc.wrappers import (
|
|||
)
|
||||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.data import EventData, IpPrefixes, NodeData, NodeOptions
|
||||
from core.emulator.data import EventData, IpPrefixes, NodeData
|
||||
from core.emulator.enumerations import EventTypes, ExceptionLevels, MessageFlags
|
||||
from core.errors import CoreError
|
||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
|
@ -350,8 +350,7 @@ class TestGrpc:
|
|||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
options = NodeOptions(model="Host")
|
||||
node = session.add_node(CoreNode, options=options)
|
||||
node = session.add_node(CoreNode)
|
||||
session.instantiate()
|
||||
expected_output = "hello world"
|
||||
expected_status = 0
|
||||
|
@ -369,8 +368,7 @@ class TestGrpc:
|
|||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
options = NodeOptions(model="Host")
|
||||
node = session.add_node(CoreNode, options=options)
|
||||
node = session.add_node(CoreNode)
|
||||
session.instantiate()
|
||||
|
||||
# then
|
||||
|
@ -444,10 +442,12 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
switch = session.add_node(SwitchNode)
|
||||
node = session.add_node(CoreNode)
|
||||
iface_data = ip_prefixes.create_iface(node)
|
||||
iface, _ = session.add_link(node.id, switch.id, iface_data)
|
||||
session.instantiate()
|
||||
options = LinkOptions(bandwidth=30000)
|
||||
assert iface.options.bandwidth != options.bandwidth
|
||||
link = Link(node.id, switch.id, iface1=Interface(id=iface.id), options=options)
|
||||
|
@ -535,7 +535,8 @@ class TestGrpc:
|
|||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions(emane=EmaneIeee80211abgModel.name)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneIeee80211abgModel.name
|
||||
emane_network = session.add_node(EmaneNet, options=options)
|
||||
session.emane.node_models[emane_network.id] = EmaneIeee80211abgModel.name
|
||||
config_key = "bandwidth"
|
||||
|
@ -565,7 +566,8 @@ class TestGrpc:
|
|||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions(emane=EmaneIeee80211abgModel.name)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneIeee80211abgModel.name
|
||||
emane_network = session.add_node(EmaneNet, options=options)
|
||||
session.emane.node_models[emane_network.id] = EmaneIeee80211abgModel.name
|
||||
|
||||
|
@ -685,7 +687,8 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
options = NodeOptions(legacy=True)
|
||||
options = CoreNode.create_options()
|
||||
options.legacy = True
|
||||
node = session.add_node(CoreNode, options=options)
|
||||
service_name = "DefaultRoute"
|
||||
|
||||
|
@ -932,6 +935,7 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
wlan = session.add_node(WlanNode)
|
||||
node1 = session.add_node(CoreNode)
|
||||
node2 = session.add_node(CoreNode)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from core.emulator.data import InterfaceData, NodeOptions
|
||||
from core.emulator.data import InterfaceData
|
||||
from core.emulator.session import Session
|
||||
from core.errors import CoreError
|
||||
from core.nodes.base import CoreNode
|
||||
|
@ -14,7 +14,8 @@ class TestNodes:
|
|||
@pytest.mark.parametrize("model", MODELS)
|
||||
def test_node_add(self, session: Session, model: str):
|
||||
# given
|
||||
options = NodeOptions(model=model)
|
||||
options = CoreNode.create_options()
|
||||
options.model = model
|
||||
|
||||
# when
|
||||
node = session.add_node(CoreNode, options=options)
|
||||
|
|
|
@ -4,7 +4,7 @@ from xml.etree import ElementTree
|
|||
|
||||
import pytest
|
||||
|
||||
from core.emulator.data import IpPrefixes, LinkOptions, NodeOptions
|
||||
from core.emulator.data import IpPrefixes, LinkOptions
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.emulator.session import Session
|
||||
from core.errors import CoreError
|
||||
|
@ -116,8 +116,7 @@ class TestXml:
|
|||
:param ip_prefixes: generates ip addresses for nodes
|
||||
"""
|
||||
# create nodes
|
||||
options = NodeOptions(model="host")
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
node1 = session.add_node(CoreNode)
|
||||
node2 = session.add_node(CoreNode)
|
||||
|
||||
# link nodes to ptp net
|
||||
|
@ -180,8 +179,8 @@ class TestXml:
|
|||
session.mobility.set_model(wlan, BasicRangeModel, {"test": "1"})
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
node1 = session.add_node(CoreNode, options=options)
|
||||
node2 = session.add_node(CoreNode, options=options)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Python API
|
||||
|
||||
* Table of Contents
|
||||
{:toc}
|
||||
{:toc}
|
||||
|
||||
## Overview
|
||||
|
||||
|
@ -21,13 +21,13 @@ When creating nodes of type `core.nodes.base.CoreNode` these are the default mod
|
|||
and the services they map to.
|
||||
|
||||
* mdr
|
||||
* zebra, OSPFv3MDR, IPForward
|
||||
* zebra, OSPFv3MDR, IPForward
|
||||
* PC
|
||||
* DefaultRoute
|
||||
* DefaultRoute
|
||||
* router
|
||||
* zebra, OSPFv2, OSPFv3, IPForward
|
||||
* zebra, OSPFv2, OSPFv3, IPForward
|
||||
* host
|
||||
* DefaultRoute, SSH
|
||||
* DefaultRoute, SSH
|
||||
|
||||
### Interface Helper
|
||||
|
||||
|
@ -36,8 +36,10 @@ when creating interface data for nodes. Alternatively one can manually create
|
|||
a `core.emulator.data.InterfaceData` class instead with appropriate information.
|
||||
|
||||
Manually creating interface data:
|
||||
|
||||
```python
|
||||
from core.emulator.data import InterfaceData
|
||||
|
||||
# id is optional and will set to the next available id
|
||||
# name is optional and will default to eth<id>
|
||||
# mac is optional and will result in a randomly generated mac
|
||||
|
@ -52,6 +54,7 @@ iface_data = InterfaceData(
|
|||
```
|
||||
|
||||
Leveraging the interface prefixes helper class:
|
||||
|
||||
```python
|
||||
from core.emulator.data import IpPrefixes
|
||||
|
||||
|
@ -69,6 +72,7 @@ iface_data = ip_prefixes.create_iface(
|
|||
Various events that can occur within a session can be listened to.
|
||||
|
||||
Event types:
|
||||
|
||||
* session - events for changes in session state and mobility start/stop/pause
|
||||
* node - events for node movements and icon changes
|
||||
* link - events for link configuration changes and wireless link add/delete
|
||||
|
@ -80,6 +84,7 @@ Event types:
|
|||
def event_listener(event):
|
||||
print(event)
|
||||
|
||||
|
||||
# add an event listener to event type you want to listen to
|
||||
# each handler will receive an object unique to that type
|
||||
session.event_handlers.append(event_listener)
|
||||
|
@ -95,6 +100,7 @@ session.config_handlers.append(event_listener)
|
|||
Links can be configured at the time of creation or during runtime.
|
||||
|
||||
Currently supported configuration options:
|
||||
|
||||
* bandwidth (bps)
|
||||
* delay (us)
|
||||
* dup (%)
|
||||
|
@ -119,12 +125,13 @@ session.update_link(n1_id, n2_id, iface1_id, iface2_id, options)
|
|||
```
|
||||
|
||||
### Peer to Peer Example
|
||||
|
||||
```python
|
||||
# required imports
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
|
||||
# ip nerator for example
|
||||
ip_prefixes = IpPrefixes(ip4_prefix="10.0.0.0/24")
|
||||
|
@ -137,10 +144,10 @@ session = coreemu.create_session()
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position)
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position)
|
||||
|
||||
# link nodes together
|
||||
iface1 = ip_prefixes.create_iface(n1)
|
||||
|
@ -158,12 +165,13 @@ session.shutdown()
|
|||
```
|
||||
|
||||
### Switch/Hub Example
|
||||
|
||||
```python
|
||||
# required imports
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
from core.nodes.network import SwitchNode
|
||||
|
||||
# ip nerator for example
|
||||
|
@ -177,14 +185,14 @@ session = coreemu.create_session()
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create switch
|
||||
options = NodeOptions(x=200, y=200)
|
||||
switch = session.add_node(SwitchNode, options=options)
|
||||
position = Position(x=200, y=200)
|
||||
switch = session.add_node(SwitchNode, position=position)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position)
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position)
|
||||
|
||||
# link nodes to switch
|
||||
iface1 = ip_prefixes.create_iface(n1)
|
||||
|
@ -203,13 +211,14 @@ session.shutdown()
|
|||
```
|
||||
|
||||
### WLAN Example
|
||||
|
||||
```python
|
||||
# required imports
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.location.mobility import BasicRangeModel
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
from core.nodes.network import WlanNode
|
||||
|
||||
# ip nerator for example
|
||||
|
@ -223,14 +232,16 @@ session = coreemu.create_session()
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create wlan
|
||||
options = NodeOptions(x=200, y=200)
|
||||
wlan = session.add_node(WlanNode, options=options)
|
||||
position = Position(x=200, y=200)
|
||||
wlan = session.add_node(WlanNode, position=position)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr", x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(model="mdr", x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position, options=options)
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
# configuring wlan
|
||||
session.mobility.set_model_config(wlan.id, BasicRangeModel.name, {
|
||||
|
@ -263,6 +274,7 @@ For EMANE you can import and use one of the existing models and
|
|||
use its name for configuration.
|
||||
|
||||
Current models:
|
||||
|
||||
* core.emane.ieee80211abg.EmaneIeee80211abgModel
|
||||
* core.emane.rfpipe.EmaneRfPipeModel
|
||||
* core.emane.tdma.EmaneTdmaModel
|
||||
|
@ -281,9 +293,9 @@ will use the defaults. When no configuration is used, the defaults are used.
|
|||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.data import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.base import CoreNode, Position
|
||||
|
||||
# ip nerator for example
|
||||
ip_prefixes = IpPrefixes(ip4_prefix="10.0.0.0/24")
|
||||
|
@ -300,25 +312,29 @@ session.location.refscale = 150.0
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create emane
|
||||
options = NodeOptions(x=200, y=200, emane=EmaneIeee80211abgModel.name)
|
||||
emane = session.add_node(EmaneNet, options=options)
|
||||
options = EmaneNet.create_options()
|
||||
options.emane_model = EmaneIeee80211abgModel.name
|
||||
position = Position(x=200, y=200)
|
||||
emane = session.add_node(EmaneNet, position=position, options=options)
|
||||
|
||||
# create nodes
|
||||
options = NodeOptions(model="mdr", x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, options=options)
|
||||
options = NodeOptions(model="mdr", x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, options=options)
|
||||
options = CoreNode.create_options()
|
||||
options.model = "mdr"
|
||||
position = Position(x=100, y=100)
|
||||
n1 = session.add_node(CoreNode, position=position, options=options)
|
||||
position = Position(x=300, y=100)
|
||||
n2 = session.add_node(CoreNode, position=position, options=options)
|
||||
|
||||
# configure general emane settings
|
||||
config = session.emane.get_configs()
|
||||
config.update({
|
||||
"eventservicettl": "2"
|
||||
"eventservicettl": "2"
|
||||
})
|
||||
|
||||
# configure emane model settings
|
||||
# using a dict mapping currently support values as strings
|
||||
session.emane.set_model_config(emane.id, EmaneIeee80211abgModel.name, {
|
||||
"unicastrate": "3",
|
||||
"unicastrate": "3",
|
||||
})
|
||||
|
||||
# link nodes to emane
|
||||
|
@ -338,6 +354,7 @@ session.shutdown()
|
|||
```
|
||||
|
||||
EMANE Model Configuration:
|
||||
|
||||
```python
|
||||
from core import utils
|
||||
|
||||
|
@ -358,6 +375,7 @@ Configuring the files of a service results in a specific hard coded script being
|
|||
generated, instead of the default scripts, that may leverage dynamic generation.
|
||||
|
||||
The following features can be configured for a service:
|
||||
|
||||
* configs - files that will be generated
|
||||
* dirs - directories that will be mounted unique to the node
|
||||
* startup - commands to run start a service
|
||||
|
@ -365,6 +383,7 @@ The following features can be configured for a service:
|
|||
* shutdown - commands to run to stop a service
|
||||
|
||||
Editing service properties:
|
||||
|
||||
```python
|
||||
# configure a service, for a node, for a given session
|
||||
session.services.set_service(node_id, service_name)
|
||||
|
@ -380,6 +399,7 @@ When editing a service file, it must be the name of `config`
|
|||
file that the service will generate.
|
||||
|
||||
Editing a service file:
|
||||
|
||||
```python
|
||||
# to edit the contents of a generated file you can specify
|
||||
# the service, the file name, and its contents
|
||||
|
@ -397,10 +417,12 @@ File versions of the network examples can be found
|
|||
[here](https://github.com/coreemu/core/tree/master/daemon/examples/python).
|
||||
|
||||
## Executing Scripts from GUI
|
||||
|
||||
To execute a python script from a GUI you need have the following.
|
||||
|
||||
The builtin name check here to know it is being executed from the GUI, this can
|
||||
be avoided if your script does not use a name check.
|
||||
|
||||
```python
|
||||
if __name__ in ["__main__", "__builtin__"]:
|
||||
main()
|
||||
|
|
Loading…
Add table
Reference in a new issue