changes to support better type checking for retrieving an arbitrary node from a session, get_node now requires an expected class that the node would be an instance of, if the returned node is not an instance a CoreError is thrown, this also helps editors pick up expected types to account for variable/function usage better as well
This commit is contained in:
parent
19ee367dc5
commit
d5254e6a91
21 changed files with 149 additions and 126 deletions
daemon
core
api
emane
emulator
location
nodes
plugins
services
xml
examples/python
tests
|
@ -6,7 +6,7 @@ import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from typing import Type, TypeVar
|
from typing import Type
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
from grpc import ServicerContext
|
from grpc import ServicerContext
|
||||||
|
@ -109,7 +109,7 @@ from core.emulator.coreemu import CoreEmu
|
||||||
from core.emulator.data import LinkData
|
from core.emulator.data import LinkData
|
||||||
from core.emulator.emudata import LinkOptions, NodeOptions
|
from core.emulator.emudata import LinkOptions, NodeOptions
|
||||||
from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags
|
from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import NT, Session
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||||
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase
|
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase
|
||||||
|
@ -118,7 +118,6 @@ from core.services.coreservices import ServiceManager
|
||||||
|
|
||||||
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
|
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
|
||||||
_INTERFACE_REGEX = re.compile(r"veth(?P<node>[0-9a-fA-F]+)")
|
_INTERFACE_REGEX = re.compile(r"veth(?P<node>[0-9a-fA-F]+)")
|
||||||
T = TypeVar("T")
|
|
||||||
|
|
||||||
|
|
||||||
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
|
@ -174,36 +173,22 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
def get_node(
|
def get_node(
|
||||||
self,
|
self, session: Session, node_id: int, context: ServicerContext, _class: Type[NT]
|
||||||
session: Session,
|
) -> NT:
|
||||||
node_id: int,
|
|
||||||
context: ServicerContext,
|
|
||||||
node_class: Type[T],
|
|
||||||
) -> T:
|
|
||||||
"""
|
"""
|
||||||
Retrieve node given session and node id
|
Retrieve node given session and node id
|
||||||
|
|
||||||
:param session: session that has the node
|
:param session: session that has the node
|
||||||
:param node_id: node id
|
:param node_id: node id
|
||||||
:param context: request
|
:param context: request
|
||||||
:param node_class: type of node we are expecting
|
:param _class: type of node we are expecting
|
||||||
:return: node object that satisfies. If node not found then raise an exception.
|
:return: node object that satisfies. If node not found then raise an exception.
|
||||||
:raises Exception: raises grpc exception when node does not exist
|
:raises Exception: raises grpc exception when node does not exist
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
node = session.get_node(node_id)
|
return session.get_node(node_id, _class)
|
||||||
if isinstance(node, node_class):
|
except CoreError as e:
|
||||||
return node
|
context.abort(grpc.StatusCode.NOT_FOUND, str(e))
|
||||||
else:
|
|
||||||
actual = node.__class__.__name__
|
|
||||||
expected = node_class.__name__
|
|
||||||
context.abort(
|
|
||||||
grpc.StatusCode.NOT_FOUND,
|
|
||||||
f"node({node_id}) class({actual}) "
|
|
||||||
f"was not expected class({expected})",
|
|
||||||
)
|
|
||||||
except CoreError:
|
|
||||||
context.abort(grpc.StatusCode.NOT_FOUND, f"node {node_id} not found")
|
|
||||||
|
|
||||||
def validate_service(
|
def validate_service(
|
||||||
self, name: str, context: ServicerContext
|
self, name: str, context: ServicerContext
|
||||||
|
|
|
@ -41,6 +41,7 @@ from core.emulator.enumerations import (
|
||||||
)
|
)
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
from core.location.mobility import BasicRangeModel
|
from core.location.mobility import BasicRangeModel
|
||||||
|
from core.nodes.base import CoreNodeBase, NodeBase
|
||||||
from core.nodes.network import WlanNode
|
from core.nodes.network import WlanNode
|
||||||
from core.services.coreservices import ServiceManager, ServiceShim
|
from core.services.coreservices import ServiceManager, ServiceShim
|
||||||
|
|
||||||
|
@ -836,7 +837,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(node_num)
|
node = self.session.get_node(node_num, CoreNodeBase)
|
||||||
|
|
||||||
# build common TLV items for reply
|
# build common TLV items for reply
|
||||||
tlv_data = b""
|
tlv_data = b""
|
||||||
|
@ -1228,7 +1229,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
||||||
if not node_id:
|
if not node_id:
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, CoreNodeBase)
|
||||||
if node is None:
|
if node is None:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"request to configure service for unknown node %s", node_id
|
"request to configure service for unknown node %s", node_id
|
||||||
|
@ -1373,7 +1374,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
||||||
self.session.mobility.set_model_config(node_id, object_name, parsed_config)
|
self.session.mobility.set_model_config(node_id, object_name, parsed_config)
|
||||||
if self.session.state == EventTypes.RUNTIME_STATE and parsed_config:
|
if self.session.state == EventTypes.RUNTIME_STATE and parsed_config:
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, WlanNode)
|
||||||
if object_name == BasicRangeModel.name:
|
if object_name == BasicRangeModel.name:
|
||||||
node.updatemodel(parsed_config)
|
node.updatemodel(parsed_config)
|
||||||
except CoreError:
|
except CoreError:
|
||||||
|
@ -1553,7 +1554,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
||||||
logging.debug("handling event %s at %s", event_type.name, time.ctime())
|
logging.debug("handling event %s at %s", event_type.name, time.ctime())
|
||||||
if event_type.value <= EventTypes.SHUTDOWN_STATE.value:
|
if event_type.value <= EventTypes.SHUTDOWN_STATE.value:
|
||||||
if node_id is not None:
|
if node_id is not None:
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, NodeBase)
|
||||||
|
|
||||||
# configure mobility models for WLAN added during runtime
|
# configure mobility models for WLAN added during runtime
|
||||||
if event_type == EventTypes.INSTANTIATION_STATE and isinstance(
|
if event_type == EventTypes.INSTANTIATION_STATE and isinstance(
|
||||||
|
@ -1647,7 +1648,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
||||||
name = event_data.name
|
name = event_data.name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, CoreNodeBase)
|
||||||
except CoreError:
|
except CoreError:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"ignoring event for service '%s', unknown node '%s'", name, node_id
|
"ignoring event for service '%s', unknown node '%s'", name, node_id
|
||||||
|
@ -1883,7 +1884,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
||||||
data_types = tuple(
|
data_types = tuple(
|
||||||
repeat(ConfigDataTypes.STRING.value, len(ServiceShim.keys))
|
repeat(ConfigDataTypes.STRING.value, len(ServiceShim.keys))
|
||||||
)
|
)
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, CoreNodeBase)
|
||||||
values = ServiceShim.tovaluelist(node, service)
|
values = ServiceShim.tovaluelist(node, service)
|
||||||
config_data = ConfigData(
|
config_data = ConfigData(
|
||||||
message_type=0,
|
message_type=0,
|
||||||
|
|
|
@ -10,6 +10,7 @@ from lxml import etree
|
||||||
|
|
||||||
from core.config import ConfigGroup, Configuration
|
from core.config import ConfigGroup, Configuration
|
||||||
from core.emane import emanemanifest, emanemodel
|
from core.emane import emanemanifest, emanemodel
|
||||||
|
from core.emane.nodes import EmaneNet
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
from core.xml import emanexml
|
from core.xml import emanexml
|
||||||
|
|
||||||
|
@ -137,7 +138,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
# TODO: batch these into multiple events per transmission
|
# TODO: batch these into multiple events per transmission
|
||||||
# TODO: may want to split out seconds portion of delay and jitter
|
# TODO: may want to split out seconds portion of delay and jitter
|
||||||
event = CommEffectEvent()
|
event = CommEffectEvent()
|
||||||
emane_node = self.session.get_node(self.id)
|
emane_node = self.session.get_node(self.id, EmaneNet)
|
||||||
nemid = emane_node.getnemid(netif)
|
nemid = emane_node.getnemid(netif)
|
||||||
nemid2 = emane_node.getnemid(netif2)
|
nemid2 = emane_node.getnemid(netif2)
|
||||||
mbw = bw
|
mbw = bw
|
||||||
|
|
|
@ -21,7 +21,7 @@ from core.emane.rfpipe import EmaneRfPipeModel
|
||||||
from core.emane.tdma import EmaneTdmaModel
|
from core.emane.tdma import EmaneTdmaModel
|
||||||
from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs
|
from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode, NodeBase
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
from core.nodes.network import CtrlNet
|
from core.nodes.network import CtrlNet
|
||||||
from core.xml import emanexml
|
from core.xml import emanexml
|
||||||
|
@ -801,8 +801,8 @@ class EmaneManager(ModelManager):
|
||||||
zbit_check = z.bit_length() > 16 or z < 0
|
zbit_check = z.bit_length() > 16 or z < 0
|
||||||
if any([xbit_check, ybit_check, zbit_check]):
|
if any([xbit_check, ybit_check, zbit_check]):
|
||||||
logging.error(
|
logging.error(
|
||||||
"Unable to build node location message, received lat/long/alt exceeds coordinate "
|
"Unable to build node location message, received lat/long/alt "
|
||||||
"space: NEM %s (%d, %d, %d)",
|
"exceeds coordinate space: NEM %s (%d, %d, %d)",
|
||||||
nemid,
|
nemid,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
@ -812,7 +812,7 @@ class EmaneManager(ModelManager):
|
||||||
|
|
||||||
# generate a node message for this location update
|
# generate a node message for this location update
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(n)
|
node = self.session.get_node(n, NodeBase)
|
||||||
except CoreError:
|
except CoreError:
|
||||||
logging.exception(
|
logging.exception(
|
||||||
"location event NEM %s has no corresponding node %s", nemid, n
|
"location event NEM %s has no corresponding node %s", nemid, n
|
||||||
|
|
|
@ -7,6 +7,7 @@ from typing import Dict, List
|
||||||
|
|
||||||
from core.config import ConfigGroup, Configuration
|
from core.config import ConfigGroup, Configuration
|
||||||
from core.emane import emanemanifest
|
from core.emane import emanemanifest
|
||||||
|
from core.emane.nodes import EmaneNet
|
||||||
from core.emulator.enumerations import ConfigDataTypes
|
from core.emulator.enumerations import ConfigDataTypes
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
from core.location.mobility import WirelessModel
|
from core.location.mobility import WirelessModel
|
||||||
|
@ -148,7 +149,7 @@ class EmaneModel(WirelessModel):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
wlan = self.session.get_node(self.id)
|
wlan = self.session.get_node(self.id, EmaneNet)
|
||||||
wlan.setnempositions(moved_netifs)
|
wlan.setnempositions(moved_netifs)
|
||||||
except CoreError:
|
except CoreError:
|
||||||
logging.exception("error during update")
|
logging.exception("error during update")
|
||||||
|
|
|
@ -244,7 +244,7 @@ class DistributedController:
|
||||||
)
|
)
|
||||||
return key & 0xFFFFFFFF
|
return key & 0xFFFFFFFF
|
||||||
|
|
||||||
def get_tunnel(self, n1_id: int, n2_id: int) -> Tuple[GreTap, GreTap]:
|
def get_tunnel(self, n1_id: int, n2_id: int) -> GreTap:
|
||||||
"""
|
"""
|
||||||
Return the GreTap between two nodes if it exists.
|
Return the GreTap between two nodes if it exists.
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type, TypeVar
|
||||||
|
|
||||||
from core import constants, utils
|
from core import constants, utils
|
||||||
from core.emane.emanemanager import EmaneManager
|
from core.emane.emanemanager import EmaneManager
|
||||||
|
@ -77,6 +77,7 @@ NODES = {
|
||||||
NODES_TYPE = {NODES[x]: x for x in NODES}
|
NODES_TYPE = {NODES[x]: x for x in NODES}
|
||||||
CTRL_NET_ID = 9001
|
CTRL_NET_ID = 9001
|
||||||
LINK_COLORS = ["green", "blue", "orange", "purple", "turquoise"]
|
LINK_COLORS = ["green", "blue", "orange", "purple", "turquoise"]
|
||||||
|
NT = TypeVar("NT", bound=NodeBase)
|
||||||
|
|
||||||
|
|
||||||
class Session:
|
class Session:
|
||||||
|
@ -194,7 +195,7 @@ class Session:
|
||||||
def _link_nodes(
|
def _link_nodes(
|
||||||
self, node_one_id: int, node_two_id: int
|
self, node_one_id: int, node_two_id: int
|
||||||
) -> Tuple[
|
) -> Tuple[
|
||||||
CoreNode, CoreNode, CoreNetworkBase, CoreNetworkBase, Tuple[GreTap, GreTap]
|
Optional[NodeBase], Optional[NodeBase], CoreNetworkBase, CoreNetworkBase, GreTap
|
||||||
]:
|
]:
|
||||||
"""
|
"""
|
||||||
Convenience method for retrieving nodes within link data.
|
Convenience method for retrieving nodes within link data.
|
||||||
|
@ -212,8 +213,8 @@ class Session:
|
||||||
net_two = None
|
net_two = None
|
||||||
|
|
||||||
# retrieve node one
|
# retrieve node one
|
||||||
node_one = self.get_node(node_one_id)
|
node_one = self.get_node(node_one_id, NodeBase)
|
||||||
node_two = self.get_node(node_two_id)
|
node_two = self.get_node(node_two_id, NodeBase)
|
||||||
|
|
||||||
# both node ids are provided
|
# both node ids are provided
|
||||||
tunnel = self.distributed.get_tunnel(node_one_id, node_two_id)
|
tunnel = self.distributed.get_tunnel(node_one_id, node_two_id)
|
||||||
|
@ -225,6 +226,7 @@ class Session:
|
||||||
else:
|
else:
|
||||||
node_two = None
|
node_two = None
|
||||||
# physical node connected via gre tap tunnel
|
# physical node connected via gre tap tunnel
|
||||||
|
# TODO: double check this cases type
|
||||||
elif tunnel:
|
elif tunnel:
|
||||||
if tunnel.remotenum == node_one_id:
|
if tunnel.remotenum == node_one_id:
|
||||||
node_one = None
|
node_one = None
|
||||||
|
@ -777,7 +779,7 @@ class Session:
|
||||||
:raises core.CoreError: when node to update does not exist
|
:raises core.CoreError: when node to update does not exist
|
||||||
"""
|
"""
|
||||||
# get node to update
|
# get node to update
|
||||||
node = self.get_node(node_id)
|
node = self.get_node(node_id, NodeBase)
|
||||||
|
|
||||||
# set node position and broadcast it
|
# set node position and broadcast it
|
||||||
self.set_node_position(node, options)
|
self.set_node_position(node, options)
|
||||||
|
@ -908,9 +910,7 @@ class Session:
|
||||||
:param data: file data
|
:param data: file data
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
node = self.get_node(node_id, CoreNodeBase)
|
||||||
node = self.get_node(node_id)
|
|
||||||
|
|
||||||
if source_name is not None:
|
if source_name is not None:
|
||||||
node.addfile(source_name, file_name)
|
node.addfile(source_name, file_name)
|
||||||
elif data is not None:
|
elif data is not None:
|
||||||
|
@ -1381,17 +1381,23 @@ class Session:
|
||||||
self.nodes[node.id] = node
|
self.nodes[node.id] = node
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def get_node(self, _id: int) -> NodeBase:
|
def get_node(self, _id: int, _class: Type[NT]) -> NT:
|
||||||
"""
|
"""
|
||||||
Get a session node.
|
Get a session node.
|
||||||
|
|
||||||
:param _id: node id to retrieve
|
:param _id: node id to retrieve
|
||||||
|
:param _class: expected node class
|
||||||
:return: node for the given id
|
:return: node for the given id
|
||||||
:raises core.CoreError: when node does not exist
|
:raises core.CoreError: when node does not exist
|
||||||
"""
|
"""
|
||||||
if _id not in self.nodes:
|
if _id not in self.nodes:
|
||||||
raise CoreError(f"unknown node id {_id}")
|
raise CoreError(f"unknown node id {_id}")
|
||||||
return self.nodes[_id]
|
node = self.nodes[_id]
|
||||||
|
if not isinstance(node, _class):
|
||||||
|
actual = node.__class__.__name__
|
||||||
|
expected = _class.__name__
|
||||||
|
raise CoreError(f"node class({actual}) is not expected({expected})")
|
||||||
|
return node
|
||||||
|
|
||||||
def delete_node(self, _id: int) -> bool:
|
def delete_node(self, _id: int) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -1709,10 +1715,7 @@ class Session:
|
||||||
:return: control net
|
:return: control net
|
||||||
:raises CoreError: when control net is not found
|
:raises CoreError: when control net is not found
|
||||||
"""
|
"""
|
||||||
node = self.get_node(CTRL_NET_ID + net_index)
|
return self.get_node(CTRL_NET_ID + net_index, CtrlNet)
|
||||||
if not isinstance(node, CtrlNet):
|
|
||||||
raise CoreError("node is not a valid CtrlNet: %s", node.name)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def add_remove_control_net(
|
def add_remove_control_net(
|
||||||
self, net_index: int, remove: bool = False, conf_required: bool = True
|
self, net_index: int, remove: bool = False, conf_required: bool = True
|
||||||
|
@ -1959,7 +1962,7 @@ class Session:
|
||||||
if not node_id:
|
if not node_id:
|
||||||
utils.mute_detach(data)
|
utils.mute_detach(data)
|
||||||
else:
|
else:
|
||||||
node = self.get_node(node_id)
|
node = self.get_node(node_id, CoreNodeBase)
|
||||||
node.cmd(data, wait=False)
|
node.cmd(data, wait=False)
|
||||||
|
|
||||||
def get_link_color(self, network_id: int) -> str:
|
def get_link_color(self, network_id: int) -> str:
|
||||||
|
|
|
@ -24,6 +24,7 @@ from core.emulator.enumerations import (
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
from core.nodes.base import CoreNode, NodeBase
|
from core.nodes.base import CoreNode, NodeBase
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
|
from core.nodes.network import WlanNode
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
|
@ -75,7 +76,7 @@ class MobilityManager(ModelManager):
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, WlanNode)
|
||||||
except CoreError:
|
except CoreError:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"skipping mobility configuration for unknown node: %s", node_id
|
"skipping mobility configuration for unknown node: %s", node_id
|
||||||
|
@ -103,9 +104,8 @@ class MobilityManager(ModelManager):
|
||||||
event_type = event_data.event_type
|
event_type = event_data.event_type
|
||||||
node_id = event_data.node
|
node_id = event_data.node
|
||||||
name = event_data.name
|
name = event_data.name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, WlanNode)
|
||||||
except CoreError:
|
except CoreError:
|
||||||
logging.exception(
|
logging.exception(
|
||||||
"Ignoring event for model '%s', unknown node '%s'", name, node_id
|
"Ignoring event for model '%s', unknown node '%s'", name, node_id
|
||||||
|
@ -190,7 +190,7 @@ class MobilityManager(ModelManager):
|
||||||
"""
|
"""
|
||||||
for node_id in self.nodes():
|
for node_id in self.nodes():
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, WlanNode)
|
||||||
except CoreError:
|
except CoreError:
|
||||||
continue
|
continue
|
||||||
if node.model:
|
if node.model:
|
||||||
|
@ -299,7 +299,7 @@ class BasicRangeModel(WirelessModel):
|
||||||
"""
|
"""
|
||||||
super().__init__(session, _id)
|
super().__init__(session, _id)
|
||||||
self.session = session
|
self.session = session
|
||||||
self.wlan = session.get_node(_id)
|
self.wlan = session.get_node(_id, WlanNode)
|
||||||
self._netifs = {}
|
self._netifs = {}
|
||||||
self._netifslock = threading.Lock()
|
self._netifslock = threading.Lock()
|
||||||
self.range = 0
|
self.range = 0
|
||||||
|
@ -590,7 +590,7 @@ class WayPointMobility(WirelessModel):
|
||||||
self.initial = {}
|
self.initial = {}
|
||||||
self.lasttime = None
|
self.lasttime = None
|
||||||
self.endtime = None
|
self.endtime = None
|
||||||
self.wlan = session.get_node(_id)
|
self.wlan = session.get_node(_id, WlanNode)
|
||||||
# these are really set in child class via confmatrix
|
# these are really set in child class via confmatrix
|
||||||
self.loop = False
|
self.loop = False
|
||||||
self.refresh_ms = 50
|
self.refresh_ms = 50
|
||||||
|
|
|
@ -433,6 +433,28 @@ class CoreNodeBase(NodeBase):
|
||||||
common.append((netif1.net, netif1, netif2))
|
common.append((netif1.net, netif1, netif2))
|
||||||
return common
|
return common
|
||||||
|
|
||||||
|
def nodefile(self, filename: str, contents: str, mode: int = 0o644) -> None:
|
||||||
|
"""
|
||||||
|
Create a node file with a given mode.
|
||||||
|
|
||||||
|
:param filename: name of file to create
|
||||||
|
:param contents: contents of file
|
||||||
|
:param mode: mode for file
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def addfile(self, srcname: str, filename: str) -> None:
|
||||||
|
"""
|
||||||
|
Add a file.
|
||||||
|
|
||||||
|
:param srcname: source file name
|
||||||
|
:param filename: file name to add
|
||||||
|
:return: nothing
|
||||||
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def cmd(self, args: str, wait: bool = True, shell: bool = False) -> str:
|
def cmd(self, args: str, wait: bool = True, shell: bool = False) -> str:
|
||||||
"""
|
"""
|
||||||
Runs a command within a node container.
|
Runs a command within a node container.
|
||||||
|
|
|
@ -296,7 +296,6 @@ class Rj45Node(CoreNodeBase, CoreInterface):
|
||||||
self.localname = name
|
self.localname = name
|
||||||
self.old_up = False
|
self.old_up = False
|
||||||
self.old_addrs = []
|
self.old_addrs = []
|
||||||
|
|
||||||
if start:
|
if start:
|
||||||
self.startup()
|
self.startup()
|
||||||
|
|
||||||
|
|
|
@ -344,7 +344,7 @@ class Sdt:
|
||||||
"""
|
"""
|
||||||
result = False
|
result = False
|
||||||
try:
|
try:
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, NodeBase)
|
||||||
result = isinstance(node, (WlanNode, EmaneNet))
|
result = isinstance(node, (WlanNode, EmaneNet))
|
||||||
except CoreError:
|
except CoreError:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from core.emane.nodes import EmaneNet
|
from core.emane.nodes import EmaneNet
|
||||||
|
from core.errors import CoreError
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
from core.xml import emanexml
|
from core.xml import emanexml
|
||||||
|
|
||||||
|
@ -20,8 +21,8 @@ class EmaneTransportService(CoreService):
|
||||||
if filename == cls.configs[0]:
|
if filename == cls.configs[0]:
|
||||||
transport_commands = []
|
transport_commands = []
|
||||||
for interface in node.netifs(sort=True):
|
for interface in node.netifs(sort=True):
|
||||||
network_node = node.session.get_node(interface.net.id)
|
try:
|
||||||
if isinstance(network_node, EmaneNet):
|
network_node = node.session.get_node(interface.net.id, EmaneNet)
|
||||||
config = node.session.emane.get_configs(
|
config = node.session.emane.get_configs(
|
||||||
network_node.id, network_node.model.name
|
network_node.id, network_node.model.name
|
||||||
)
|
)
|
||||||
|
@ -32,6 +33,8 @@ class EmaneTransportService(CoreService):
|
||||||
% nem_id
|
% nem_id
|
||||||
)
|
)
|
||||||
transport_commands.append(command)
|
transport_commands.append(command)
|
||||||
|
except CoreError:
|
||||||
|
pass
|
||||||
transport_commands = "\n".join(transport_commands)
|
transport_commands = "\n".join(transport_commands)
|
||||||
return """
|
return """
|
||||||
emanegentransportxml -o ../ ../platform%s.xml
|
emanegentransportxml -o ../ ../platform%s.xml
|
||||||
|
|
|
@ -10,7 +10,7 @@ from core.emulator.data import LinkData
|
||||||
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
||||||
from core.emulator.enumerations import EventTypes, NodeTypes
|
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||||
from core.errors import CoreXmlError
|
from core.errors import CoreXmlError
|
||||||
from core.nodes.base import CoreNetworkBase, CoreNodeBase, NodeBase
|
from core.nodes.base import CoreNodeBase, NodeBase
|
||||||
from core.nodes.docker import DockerNode
|
from core.nodes.docker import DockerNode
|
||||||
from core.nodes.lxd import LxcNode
|
from core.nodes.lxd import LxcNode
|
||||||
from core.nodes.network import CtrlNet, WlanNode
|
from core.nodes.network import CtrlNet, WlanNode
|
||||||
|
@ -505,9 +505,9 @@ class CoreXmlWriter:
|
||||||
ip6_mask: int,
|
ip6_mask: int,
|
||||||
) -> etree.Element:
|
) -> etree.Element:
|
||||||
interface = etree.Element(element_name)
|
interface = etree.Element(element_name)
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, NodeBase)
|
||||||
interface_name = None
|
interface_name = None
|
||||||
if not isinstance(node, CoreNetworkBase):
|
if isinstance(node, CoreNodeBase):
|
||||||
node_interface = node.netif(interface_id)
|
node_interface = node.netif(interface_id)
|
||||||
interface_name = node_interface.name
|
interface_name = node_interface.name
|
||||||
|
|
||||||
|
@ -523,7 +523,6 @@ class CoreXmlWriter:
|
||||||
add_attribute(interface, "ip4_mask", ip4_mask)
|
add_attribute(interface, "ip4_mask", ip4_mask)
|
||||||
add_attribute(interface, "ip6", ip6)
|
add_attribute(interface, "ip6", ip6)
|
||||||
add_attribute(interface, "ip6_mask", ip6_mask)
|
add_attribute(interface, "ip6_mask", ip6_mask)
|
||||||
|
|
||||||
return interface
|
return interface
|
||||||
|
|
||||||
def create_link_element(self, link_data: LinkData) -> etree.Element:
|
def create_link_element(self, link_data: LinkData) -> etree.Element:
|
||||||
|
@ -560,8 +559,8 @@ class CoreXmlWriter:
|
||||||
link_element.append(interface_two)
|
link_element.append(interface_two)
|
||||||
|
|
||||||
# check for options, don't write for emane/wlan links
|
# check for options, don't write for emane/wlan links
|
||||||
node_one = self.session.get_node(link_data.node1_id)
|
node_one = self.session.get_node(link_data.node1_id, NodeBase)
|
||||||
node_two = self.session.get_node(link_data.node2_id)
|
node_two = self.session.get_node(link_data.node2_id, NodeBase)
|
||||||
is_node_one_wireless = isinstance(node_one, (WlanNode, EmaneNet))
|
is_node_one_wireless = isinstance(node_one, (WlanNode, EmaneNet))
|
||||||
is_node_two_wireless = isinstance(node_two, (WlanNode, EmaneNet))
|
is_node_two_wireless = isinstance(node_two, (WlanNode, EmaneNet))
|
||||||
if not any([is_node_one_wireless, is_node_two_wireless]):
|
if not any([is_node_one_wireless, is_node_two_wireless]):
|
||||||
|
@ -902,7 +901,7 @@ class CoreXmlReader:
|
||||||
for configservice_element in configservice_configs.iterchildren():
|
for configservice_element in configservice_configs.iterchildren():
|
||||||
name = configservice_element.get("name")
|
name = configservice_element.get("name")
|
||||||
node_id = get_int(configservice_element, "node")
|
node_id = get_int(configservice_element, "node")
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id, CoreNodeBase)
|
||||||
service = node.config_services[name]
|
service = node.config_services[name]
|
||||||
|
|
||||||
configs_element = configservice_element.find("configs")
|
configs_element = configservice_element.find("configs")
|
||||||
|
|
|
@ -11,6 +11,7 @@ from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||||
from core.emulator.coreemu import CoreEmu
|
from core.emulator.coreemu import CoreEmu
|
||||||
from core.emulator.emudata import IpPrefixes, NodeOptions
|
from core.emulator.emudata import IpPrefixes, NodeOptions
|
||||||
from core.emulator.enumerations import EventTypes, NodeTypes
|
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
|
|
||||||
NODES = 2
|
NODES = 2
|
||||||
EMANE_DELAY = 10
|
EMANE_DELAY = 10
|
||||||
|
@ -51,8 +52,8 @@ def main():
|
||||||
time.sleep(EMANE_DELAY)
|
time.sleep(EMANE_DELAY)
|
||||||
|
|
||||||
# get nodes to run example
|
# get nodes to run example
|
||||||
first_node = session.get_node(1)
|
first_node = session.get_node(1, CoreNode)
|
||||||
last_node = session.get_node(NODES)
|
last_node = session.get_node(NODES, CoreNode)
|
||||||
address = prefixes.ip4_address(first_node)
|
address = prefixes.ip4_address(first_node)
|
||||||
logging.info("node %s pinging %s", last_node.name, address)
|
logging.info("node %s pinging %s", last_node.name, address)
|
||||||
output = last_node.cmd(f"ping -c 3 {address}")
|
output = last_node.cmd(f"ping -c 3 {address}")
|
||||||
|
|
|
@ -8,6 +8,7 @@ import logging
|
||||||
from core.emulator.coreemu import CoreEmu
|
from core.emulator.coreemu import CoreEmu
|
||||||
from core.emulator.emudata import IpPrefixes
|
from core.emulator.emudata import IpPrefixes
|
||||||
from core.emulator.enumerations import EventTypes, NodeTypes
|
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
|
|
||||||
NODES = 2
|
NODES = 2
|
||||||
|
|
||||||
|
@ -36,8 +37,8 @@ def main():
|
||||||
session.instantiate()
|
session.instantiate()
|
||||||
|
|
||||||
# get nodes to run example
|
# get nodes to run example
|
||||||
first_node = session.get_node(1)
|
first_node = session.get_node(1, CoreNode)
|
||||||
last_node = session.get_node(NODES)
|
last_node = session.get_node(NODES, CoreNode)
|
||||||
address = prefixes.ip4_address(first_node)
|
address = prefixes.ip4_address(first_node)
|
||||||
logging.info("node %s pinging %s", last_node.name, address)
|
logging.info("node %s pinging %s", last_node.name, address)
|
||||||
output = last_node.cmd(f"ping -c 3 {address}")
|
output = last_node.cmd(f"ping -c 3 {address}")
|
||||||
|
|
|
@ -9,6 +9,7 @@ from core.emulator.coreemu import CoreEmu
|
||||||
from core.emulator.emudata import IpPrefixes, NodeOptions
|
from core.emulator.emudata import IpPrefixes, NodeOptions
|
||||||
from core.emulator.enumerations import EventTypes, NodeTypes
|
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||||
from core.location.mobility import BasicRangeModel
|
from core.location.mobility import BasicRangeModel
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
|
|
||||||
NODES = 2
|
NODES = 2
|
||||||
|
|
||||||
|
@ -40,8 +41,8 @@ def main():
|
||||||
session.instantiate()
|
session.instantiate()
|
||||||
|
|
||||||
# get nodes for example run
|
# get nodes for example run
|
||||||
first_node = session.get_node(1)
|
first_node = session.get_node(1, CoreNode)
|
||||||
last_node = session.get_node(NODES)
|
last_node = session.get_node(NODES, CoreNode)
|
||||||
address = prefixes.ip4_address(first_node)
|
address = prefixes.ip4_address(first_node)
|
||||||
logging.info("node %s pinging %s", last_node.name, address)
|
logging.info("node %s pinging %s", last_node.name, address)
|
||||||
output = last_node.cmd(f"ping -c 3 {address}")
|
output = last_node.cmd(f"ping -c 3 {address}")
|
||||||
|
|
|
@ -9,11 +9,13 @@ import pytest
|
||||||
from core.emane.bypass import EmaneBypassModel
|
from core.emane.bypass import EmaneBypassModel
|
||||||
from core.emane.commeffect import EmaneCommEffectModel
|
from core.emane.commeffect import EmaneCommEffectModel
|
||||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||||
|
from core.emane.nodes import EmaneNet
|
||||||
from core.emane.rfpipe import EmaneRfPipeModel
|
from core.emane.rfpipe import EmaneRfPipeModel
|
||||||
from core.emane.tdma import EmaneTdmaModel
|
from core.emane.tdma import EmaneTdmaModel
|
||||||
from core.emulator.emudata import NodeOptions
|
from core.emulator.emudata import NodeOptions
|
||||||
from core.emulator.enumerations import NodeTypes
|
from core.emulator.enumerations import NodeTypes
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
|
|
||||||
_EMANE_MODELS = [
|
_EMANE_MODELS = [
|
||||||
EmaneIeee80211abgModel,
|
EmaneIeee80211abgModel,
|
||||||
|
@ -133,9 +135,9 @@ class TestEmane:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, CoreNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, CoreNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
@ -146,7 +148,7 @@ class TestEmane:
|
||||||
)
|
)
|
||||||
|
|
||||||
# verify nodes and configuration were restored
|
# verify nodes and configuration were restored
|
||||||
assert session.get_node(n1_id)
|
assert session.get_node(n1_id, CoreNode)
|
||||||
assert session.get_node(n2_id)
|
assert session.get_node(n2_id, CoreNode)
|
||||||
assert session.get_node(emane_id)
|
assert session.get_node(emane_id, EmaneNet)
|
||||||
assert value == config_value
|
assert value == config_value
|
||||||
|
|
|
@ -19,6 +19,7 @@ from core.emulator.emudata import NodeOptions
|
||||||
from core.emulator.enumerations import EventTypes, ExceptionLevels, NodeTypes
|
from core.emulator.enumerations import EventTypes, ExceptionLevels, NodeTypes
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
from core.xml.corexml import CoreXmlWriter
|
from core.xml.corexml import CoreXmlWriter
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,7 +356,7 @@ class TestGrpc:
|
||||||
|
|
||||||
# then
|
# then
|
||||||
assert response.node_id is not None
|
assert response.node_id is not None
|
||||||
assert session.get_node(response.node_id) is not None
|
assert session.get_node(response.node_id, CoreNode) is not None
|
||||||
|
|
||||||
def test_get_node(self, grpc_server):
|
def test_get_node(self, grpc_server):
|
||||||
# given
|
# given
|
||||||
|
@ -402,7 +403,7 @@ class TestGrpc:
|
||||||
assert response.result is expected
|
assert response.result is expected
|
||||||
if expected is True:
|
if expected is True:
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert session.get_node(node.id)
|
assert session.get_node(node.id, CoreNode)
|
||||||
|
|
||||||
def test_node_command(self, request, grpc_server):
|
def test_node_command(self, request, grpc_server):
|
||||||
if request.config.getoption("mock"):
|
if request.config.getoption("mock"):
|
||||||
|
|
|
@ -24,6 +24,8 @@ from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||||
from core.emulator.enumerations import EventTypes, MessageFlags, NodeTypes, RegisterTlvs
|
from core.emulator.enumerations import EventTypes, MessageFlags, NodeTypes, RegisterTlvs
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
from core.location.mobility import BasicRangeModel
|
from core.location.mobility import BasicRangeModel
|
||||||
|
from core.nodes.base import CoreNode, NodeBase
|
||||||
|
from core.nodes.network import SwitchNode
|
||||||
|
|
||||||
|
|
||||||
def dict_to_str(values):
|
def dict_to_str(values):
|
||||||
|
@ -57,8 +59,7 @@ class TestGui:
|
||||||
)
|
)
|
||||||
|
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
assert coretlv.session.get_node(node_id, NodeBase) is not None
|
||||||
assert coretlv.session.get_node(node_id) is not None
|
|
||||||
|
|
||||||
def test_node_update(self, coretlv):
|
def test_node_update(self, coretlv):
|
||||||
node_id = 1
|
node_id = 1
|
||||||
|
@ -76,7 +77,7 @@ class TestGui:
|
||||||
|
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
node = coretlv.session.get_node(node_id)
|
node = coretlv.session.get_node(node_id, NodeBase)
|
||||||
assert node is not None
|
assert node is not None
|
||||||
assert node.position.x == x
|
assert node.position.x == x
|
||||||
assert node.position.y == y
|
assert node.position.y == y
|
||||||
|
@ -91,7 +92,7 @@ class TestGui:
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
coretlv.session.get_node(node_id)
|
coretlv.session.get_node(node_id, NodeBase)
|
||||||
|
|
||||||
def test_link_add_node_to_net(self, coretlv):
|
def test_link_add_node_to_net(self, coretlv):
|
||||||
node_one = 1
|
node_one = 1
|
||||||
|
@ -113,7 +114,7 @@ class TestGui:
|
||||||
|
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 1
|
assert len(all_links) == 1
|
||||||
|
|
||||||
|
@ -137,7 +138,7 @@ class TestGui:
|
||||||
|
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 1
|
assert len(all_links) == 1
|
||||||
|
|
||||||
|
@ -189,7 +190,7 @@ class TestGui:
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 1
|
assert len(all_links) == 1
|
||||||
link = all_links[0]
|
link = all_links[0]
|
||||||
|
@ -207,7 +208,7 @@ class TestGui:
|
||||||
)
|
)
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 1
|
assert len(all_links) == 1
|
||||||
link = all_links[0]
|
link = all_links[0]
|
||||||
|
@ -275,7 +276,7 @@ class TestGui:
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 1
|
assert len(all_links) == 1
|
||||||
|
|
||||||
|
@ -289,7 +290,7 @@ class TestGui:
|
||||||
)
|
)
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 0
|
assert len(all_links) == 0
|
||||||
|
|
||||||
|
@ -311,7 +312,7 @@ class TestGui:
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 1
|
assert len(all_links) == 1
|
||||||
|
|
||||||
|
@ -325,7 +326,7 @@ class TestGui:
|
||||||
)
|
)
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
switch_node = coretlv.session.get_node(switch)
|
switch_node = coretlv.session.get_node(switch, SwitchNode)
|
||||||
all_links = switch_node.all_link_data()
|
all_links = switch_node.all_link_data()
|
||||||
assert len(all_links) == 0
|
assert len(all_links) == 0
|
||||||
|
|
||||||
|
@ -556,8 +557,7 @@ class TestGui:
|
||||||
)
|
)
|
||||||
|
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
assert coretlv.session.get_node(node.id, NodeBase)
|
||||||
assert coretlv.session.get_node(node.id)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"state",
|
"state",
|
||||||
|
@ -619,7 +619,7 @@ class TestGui:
|
||||||
|
|
||||||
coretlv.handle_message(message)
|
coretlv.handle_message(message)
|
||||||
|
|
||||||
assert coretlv.coreemu.sessions[1].get_node(node.id)
|
assert coretlv.coreemu.sessions[1].get_node(node.id, CoreNode)
|
||||||
|
|
||||||
def test_register_python(self, coretlv, tmpdir):
|
def test_register_python(self, coretlv, tmpdir):
|
||||||
xml_file = tmpdir.join("test.py")
|
xml_file = tmpdir.join("test.py")
|
||||||
|
|
|
@ -3,6 +3,7 @@ import pytest
|
||||||
from core.emulator.emudata import NodeOptions
|
from core.emulator.emudata import NodeOptions
|
||||||
from core.emulator.enumerations import NodeTypes
|
from core.emulator.enumerations import NodeTypes
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
|
|
||||||
MODELS = ["router", "host", "PC", "mdr"]
|
MODELS = ["router", "host", "PC", "mdr"]
|
||||||
NET_TYPES = [NodeTypes.SWITCH, NodeTypes.HUB, NodeTypes.WIRELESS_LAN]
|
NET_TYPES = [NodeTypes.SWITCH, NodeTypes.HUB, NodeTypes.WIRELESS_LAN]
|
||||||
|
@ -45,7 +46,7 @@ class TestNodes:
|
||||||
|
|
||||||
# then
|
# then
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
session.get_node(node.id)
|
session.get_node(node.id, CoreNode)
|
||||||
|
|
||||||
def test_node_sethwaddr(self, session):
|
def test_node_sethwaddr(self, session):
|
||||||
# given
|
# given
|
||||||
|
|
|
@ -6,6 +6,8 @@ from core.emulator.emudata import LinkOptions, NodeOptions
|
||||||
from core.emulator.enumerations import EventTypes, NodeTypes
|
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
from core.location.mobility import BasicRangeModel
|
from core.location.mobility import BasicRangeModel
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
|
from core.nodes.network import SwitchNode, WlanNode
|
||||||
from core.services.utility import SshService
|
from core.services.utility import SshService
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,16 +93,16 @@ class TestXml:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, CoreNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, CoreNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
|
||||||
# verify nodes have been recreated
|
# verify nodes have been recreated
|
||||||
assert session.get_node(n1_id)
|
assert session.get_node(n1_id, CoreNode)
|
||||||
assert session.get_node(n2_id)
|
assert session.get_node(n2_id, CoreNode)
|
||||||
|
|
||||||
def test_xml_ptp_services(self, session, tmpdir, ip_prefixes):
|
def test_xml_ptp_services(self, session, tmpdir, ip_prefixes):
|
||||||
"""
|
"""
|
||||||
|
@ -152,9 +154,9 @@ class TestXml:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, CoreNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, CoreNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
@ -163,8 +165,8 @@ class TestXml:
|
||||||
service = session.services.get_service(node_one.id, SshService.name)
|
service = session.services.get_service(node_one.id, SshService.name)
|
||||||
|
|
||||||
# verify nodes have been recreated
|
# verify nodes have been recreated
|
||||||
assert session.get_node(n1_id)
|
assert session.get_node(n1_id, CoreNode)
|
||||||
assert session.get_node(n2_id)
|
assert session.get_node(n2_id, CoreNode)
|
||||||
assert service.config_data.get(service_file) == file_data
|
assert service.config_data.get(service_file) == file_data
|
||||||
|
|
||||||
def test_xml_mobility(self, session, tmpdir, ip_prefixes):
|
def test_xml_mobility(self, session, tmpdir, ip_prefixes):
|
||||||
|
@ -212,9 +214,9 @@ class TestXml:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, CoreNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, CoreNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
@ -223,9 +225,9 @@ class TestXml:
|
||||||
value = str(session.mobility.get_config("test", wlan_id, BasicRangeModel.name))
|
value = str(session.mobility.get_config("test", wlan_id, BasicRangeModel.name))
|
||||||
|
|
||||||
# verify nodes and configuration were restored
|
# verify nodes and configuration were restored
|
||||||
assert session.get_node(n1_id)
|
assert session.get_node(n1_id, CoreNode)
|
||||||
assert session.get_node(n2_id)
|
assert session.get_node(n2_id, CoreNode)
|
||||||
assert session.get_node(wlan_id)
|
assert session.get_node(wlan_id, WlanNode)
|
||||||
assert value == "1"
|
assert value == "1"
|
||||||
|
|
||||||
def test_network_to_network(self, session, tmpdir):
|
def test_network_to_network(self, session, tmpdir):
|
||||||
|
@ -263,16 +265,16 @@ class TestXml:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, SwitchNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, SwitchNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
|
||||||
# verify nodes have been recreated
|
# verify nodes have been recreated
|
||||||
switch_one = session.get_node(n1_id)
|
switch_one = session.get_node(n1_id, SwitchNode)
|
||||||
switch_two = session.get_node(n2_id)
|
switch_two = session.get_node(n2_id, SwitchNode)
|
||||||
assert switch_one
|
assert switch_one
|
||||||
assert switch_two
|
assert switch_two
|
||||||
assert len(switch_one.all_link_data() + switch_two.all_link_data()) == 1
|
assert len(switch_one.all_link_data() + switch_two.all_link_data()) == 1
|
||||||
|
@ -322,16 +324,16 @@ class TestXml:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, CoreNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, SwitchNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
|
||||||
# verify nodes have been recreated
|
# verify nodes have been recreated
|
||||||
assert session.get_node(n1_id)
|
assert session.get_node(n1_id, CoreNode)
|
||||||
assert session.get_node(n2_id)
|
assert session.get_node(n2_id, SwitchNode)
|
||||||
links = []
|
links = []
|
||||||
for node_id in session.nodes:
|
for node_id in session.nodes:
|
||||||
node = session.nodes[node_id]
|
node = session.nodes[node_id]
|
||||||
|
@ -389,16 +391,16 @@ class TestXml:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, CoreNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, CoreNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
|
||||||
# verify nodes have been recreated
|
# verify nodes have been recreated
|
||||||
assert session.get_node(n1_id)
|
assert session.get_node(n1_id, CoreNode)
|
||||||
assert session.get_node(n2_id)
|
assert session.get_node(n2_id, CoreNode)
|
||||||
links = []
|
links = []
|
||||||
for node_id in session.nodes:
|
for node_id in session.nodes:
|
||||||
node = session.nodes[node_id]
|
node = session.nodes[node_id]
|
||||||
|
@ -471,16 +473,16 @@ class TestXml:
|
||||||
|
|
||||||
# verify nodes have been removed from session
|
# verify nodes have been removed from session
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n1_id)
|
assert not session.get_node(n1_id, CoreNode)
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
assert not session.get_node(n2_id)
|
assert not session.get_node(n2_id, CoreNode)
|
||||||
|
|
||||||
# load saved xml
|
# load saved xml
|
||||||
session.open_xml(file_path, start=True)
|
session.open_xml(file_path, start=True)
|
||||||
|
|
||||||
# verify nodes have been recreated
|
# verify nodes have been recreated
|
||||||
assert session.get_node(n1_id)
|
assert session.get_node(n1_id, CoreNode)
|
||||||
assert session.get_node(n2_id)
|
assert session.get_node(n2_id, CoreNode)
|
||||||
links = []
|
links = []
|
||||||
for node_id in session.nodes:
|
for node_id in session.nodes:
|
||||||
node = session.nodes[node_id]
|
node = session.nodes[node_id]
|
||||||
|
|
Loading…
Add table
Reference in a new issue