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:
Blake Harnden 2020-05-20 14:44:34 -07:00
parent 19ee367dc5
commit d5254e6a91
21 changed files with 149 additions and 126 deletions

View file

@ -6,7 +6,7 @@ import tempfile
import threading
import time
from concurrent import futures
from typing import Type, TypeVar
from typing import Type
import grpc
from grpc import ServicerContext
@ -109,7 +109,7 @@ from core.emulator.coreemu import CoreEmu
from core.emulator.data import LinkData
from core.emulator.emudata import LinkOptions, NodeOptions
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.location.mobility import BasicRangeModel, Ns2ScriptedMobility
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
_INTERFACE_REGEX = re.compile(r"veth(?P<node>[0-9a-fA-F]+)")
T = TypeVar("T")
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
@ -174,36 +173,22 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
return session
def get_node(
self,
session: Session,
node_id: int,
context: ServicerContext,
node_class: Type[T],
) -> T:
self, session: Session, node_id: int, context: ServicerContext, _class: Type[NT]
) -> NT:
"""
Retrieve node given session and node id
:param session: session that has the node
:param node_id: node id
: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.
:raises Exception: raises grpc exception when node does not exist
"""
try:
node = session.get_node(node_id)
if isinstance(node, node_class):
return node
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")
return session.get_node(node_id, _class)
except CoreError as e:
context.abort(grpc.StatusCode.NOT_FOUND, str(e))
def validate_service(
self, name: str, context: ServicerContext

View file

@ -41,6 +41,7 @@ from core.emulator.enumerations import (
)
from core.errors import CoreCommandError, CoreError
from core.location.mobility import BasicRangeModel
from core.nodes.base import CoreNodeBase, NodeBase
from core.nodes.network import WlanNode
from core.services.coreservices import ServiceManager, ServiceShim
@ -836,7 +837,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
return ()
try:
node = self.session.get_node(node_num)
node = self.session.get_node(node_num, CoreNodeBase)
# build common TLV items for reply
tlv_data = b""
@ -1228,7 +1229,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
if not node_id:
return replies
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, CoreNodeBase)
if node is None:
logging.warning(
"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)
if self.session.state == EventTypes.RUNTIME_STATE and parsed_config:
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, WlanNode)
if object_name == BasicRangeModel.name:
node.updatemodel(parsed_config)
except CoreError:
@ -1553,7 +1554,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
logging.debug("handling event %s at %s", event_type.name, time.ctime())
if event_type.value <= EventTypes.SHUTDOWN_STATE.value:
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
if event_type == EventTypes.INSTANTIATION_STATE and isinstance(
@ -1647,7 +1648,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
name = event_data.name
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, CoreNodeBase)
except CoreError:
logging.warning(
"ignoring event for service '%s', unknown node '%s'", name, node_id
@ -1883,7 +1884,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
data_types = tuple(
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)
config_data = ConfigData(
message_type=0,

View file

@ -10,6 +10,7 @@ from lxml import etree
from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest, emanemodel
from core.emane.nodes import EmaneNet
from core.nodes.interface import CoreInterface
from core.xml import emanexml
@ -137,7 +138,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
# TODO: batch these into multiple events per transmission
# TODO: may want to split out seconds portion of delay and jitter
event = CommEffectEvent()
emane_node = self.session.get_node(self.id)
emane_node = self.session.get_node(self.id, EmaneNet)
nemid = emane_node.getnemid(netif)
nemid2 = emane_node.getnemid(netif2)
mbw = bw

View file

@ -21,7 +21,7 @@ from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel
from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs
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.network import CtrlNet
from core.xml import emanexml
@ -801,8 +801,8 @@ class EmaneManager(ModelManager):
zbit_check = z.bit_length() > 16 or z < 0
if any([xbit_check, ybit_check, zbit_check]):
logging.error(
"Unable to build node location message, received lat/long/alt exceeds coordinate "
"space: NEM %s (%d, %d, %d)",
"Unable to build node location message, received lat/long/alt "
"exceeds coordinate space: NEM %s (%d, %d, %d)",
nemid,
x,
y,
@ -812,7 +812,7 @@ class EmaneManager(ModelManager):
# generate a node message for this location update
try:
node = self.session.get_node(n)
node = self.session.get_node(n, NodeBase)
except CoreError:
logging.exception(
"location event NEM %s has no corresponding node %s", nemid, n

View file

@ -7,6 +7,7 @@ from typing import Dict, List
from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest
from core.emane.nodes import EmaneNet
from core.emulator.enumerations import ConfigDataTypes
from core.errors import CoreError
from core.location.mobility import WirelessModel
@ -148,7 +149,7 @@ class EmaneModel(WirelessModel):
:return: nothing
"""
try:
wlan = self.session.get_node(self.id)
wlan = self.session.get_node(self.id, EmaneNet)
wlan.setnempositions(moved_netifs)
except CoreError:
logging.exception("error during update")

View file

@ -244,7 +244,7 @@ class DistributedController:
)
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.

View file

@ -12,7 +12,7 @@ import subprocess
import tempfile
import threading
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.emane.emanemanager import EmaneManager
@ -77,6 +77,7 @@ NODES = {
NODES_TYPE = {NODES[x]: x for x in NODES}
CTRL_NET_ID = 9001
LINK_COLORS = ["green", "blue", "orange", "purple", "turquoise"]
NT = TypeVar("NT", bound=NodeBase)
class Session:
@ -194,7 +195,7 @@ class Session:
def _link_nodes(
self, node_one_id: int, node_two_id: int
) -> Tuple[
CoreNode, CoreNode, CoreNetworkBase, CoreNetworkBase, Tuple[GreTap, GreTap]
Optional[NodeBase], Optional[NodeBase], CoreNetworkBase, CoreNetworkBase, GreTap
]:
"""
Convenience method for retrieving nodes within link data.
@ -212,8 +213,8 @@ class Session:
net_two = None
# retrieve node one
node_one = self.get_node(node_one_id)
node_two = self.get_node(node_two_id)
node_one = self.get_node(node_one_id, NodeBase)
node_two = self.get_node(node_two_id, NodeBase)
# both node ids are provided
tunnel = self.distributed.get_tunnel(node_one_id, node_two_id)
@ -225,6 +226,7 @@ class Session:
else:
node_two = None
# physical node connected via gre tap tunnel
# TODO: double check this cases type
elif tunnel:
if tunnel.remotenum == node_one_id:
node_one = None
@ -777,7 +779,7 @@ class Session:
:raises core.CoreError: when node to update does not exist
"""
# get node to update
node = self.get_node(node_id)
node = self.get_node(node_id, NodeBase)
# set node position and broadcast it
self.set_node_position(node, options)
@ -908,9 +910,7 @@ class Session:
:param data: file data
:return: nothing
"""
node = self.get_node(node_id)
node = self.get_node(node_id, CoreNodeBase)
if source_name is not None:
node.addfile(source_name, file_name)
elif data is not None:
@ -1381,17 +1381,23 @@ class Session:
self.nodes[node.id] = node
return node
def get_node(self, _id: int) -> NodeBase:
def get_node(self, _id: int, _class: Type[NT]) -> NT:
"""
Get a session node.
:param _id: node id to retrieve
:param _class: expected node class
:return: node for the given id
:raises core.CoreError: when node does not exist
"""
if _id not in self.nodes:
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:
"""
@ -1709,10 +1715,7 @@ class Session:
:return: control net
:raises CoreError: when control net is not found
"""
node = self.get_node(CTRL_NET_ID + net_index)
if not isinstance(node, CtrlNet):
raise CoreError("node is not a valid CtrlNet: %s", node.name)
return node
return self.get_node(CTRL_NET_ID + net_index, CtrlNet)
def add_remove_control_net(
self, net_index: int, remove: bool = False, conf_required: bool = True
@ -1959,7 +1962,7 @@ class Session:
if not node_id:
utils.mute_detach(data)
else:
node = self.get_node(node_id)
node = self.get_node(node_id, CoreNodeBase)
node.cmd(data, wait=False)
def get_link_color(self, network_id: int) -> str:

View file

@ -24,6 +24,7 @@ from core.emulator.enumerations import (
from core.errors import CoreError
from core.nodes.base import CoreNode, NodeBase
from core.nodes.interface import CoreInterface
from core.nodes.network import WlanNode
if TYPE_CHECKING:
from core.emulator.session import Session
@ -75,7 +76,7 @@ class MobilityManager(ModelManager):
)
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, WlanNode)
except CoreError:
logging.warning(
"skipping mobility configuration for unknown node: %s", node_id
@ -103,9 +104,8 @@ class MobilityManager(ModelManager):
event_type = event_data.event_type
node_id = event_data.node
name = event_data.name
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, WlanNode)
except CoreError:
logging.exception(
"Ignoring event for model '%s', unknown node '%s'", name, node_id
@ -190,7 +190,7 @@ class MobilityManager(ModelManager):
"""
for node_id in self.nodes():
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, WlanNode)
except CoreError:
continue
if node.model:
@ -299,7 +299,7 @@ class BasicRangeModel(WirelessModel):
"""
super().__init__(session, _id)
self.session = session
self.wlan = session.get_node(_id)
self.wlan = session.get_node(_id, WlanNode)
self._netifs = {}
self._netifslock = threading.Lock()
self.range = 0
@ -590,7 +590,7 @@ class WayPointMobility(WirelessModel):
self.initial = {}
self.lasttime = 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
self.loop = False
self.refresh_ms = 50

View file

@ -433,6 +433,28 @@ class CoreNodeBase(NodeBase):
common.append((netif1.net, netif1, netif2))
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:
"""
Runs a command within a node container.

View file

@ -296,7 +296,6 @@ class Rj45Node(CoreNodeBase, CoreInterface):
self.localname = name
self.old_up = False
self.old_addrs = []
if start:
self.startup()

View file

@ -344,7 +344,7 @@ class Sdt:
"""
result = False
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, NodeBase)
result = isinstance(node, (WlanNode, EmaneNet))
except CoreError:
pass

View file

@ -1,4 +1,5 @@
from core.emane.nodes import EmaneNet
from core.errors import CoreError
from core.services.coreservices import CoreService
from core.xml import emanexml
@ -20,8 +21,8 @@ class EmaneTransportService(CoreService):
if filename == cls.configs[0]:
transport_commands = []
for interface in node.netifs(sort=True):
network_node = node.session.get_node(interface.net.id)
if isinstance(network_node, EmaneNet):
try:
network_node = node.session.get_node(interface.net.id, EmaneNet)
config = node.session.emane.get_configs(
network_node.id, network_node.model.name
)
@ -32,6 +33,8 @@ class EmaneTransportService(CoreService):
% nem_id
)
transport_commands.append(command)
except CoreError:
pass
transport_commands = "\n".join(transport_commands)
return """
emanegentransportxml -o ../ ../platform%s.xml

View file

@ -10,7 +10,7 @@ from core.emulator.data import LinkData
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes
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.lxd import LxcNode
from core.nodes.network import CtrlNet, WlanNode
@ -505,9 +505,9 @@ class CoreXmlWriter:
ip6_mask: int,
) -> etree.Element:
interface = etree.Element(element_name)
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, NodeBase)
interface_name = None
if not isinstance(node, CoreNetworkBase):
if isinstance(node, CoreNodeBase):
node_interface = node.netif(interface_id)
interface_name = node_interface.name
@ -523,7 +523,6 @@ class CoreXmlWriter:
add_attribute(interface, "ip4_mask", ip4_mask)
add_attribute(interface, "ip6", ip6)
add_attribute(interface, "ip6_mask", ip6_mask)
return interface
def create_link_element(self, link_data: LinkData) -> etree.Element:
@ -560,8 +559,8 @@ class CoreXmlWriter:
link_element.append(interface_two)
# check for options, don't write for emane/wlan links
node_one = self.session.get_node(link_data.node1_id)
node_two = self.session.get_node(link_data.node2_id)
node_one = self.session.get_node(link_data.node1_id, NodeBase)
node_two = self.session.get_node(link_data.node2_id, NodeBase)
is_node_one_wireless = isinstance(node_one, (WlanNode, EmaneNet))
is_node_two_wireless = isinstance(node_two, (WlanNode, EmaneNet))
if not any([is_node_one_wireless, is_node_two_wireless]):
@ -902,7 +901,7 @@ class CoreXmlReader:
for configservice_element in configservice_configs.iterchildren():
name = configservice_element.get("name")
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]
configs_element = configservice_element.find("configs")

View file

@ -11,6 +11,7 @@ from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes
from core.nodes.base import CoreNode
NODES = 2
EMANE_DELAY = 10
@ -51,8 +52,8 @@ def main():
time.sleep(EMANE_DELAY)
# get nodes to run example
first_node = session.get_node(1)
last_node = session.get_node(NODES)
first_node = session.get_node(1, CoreNode)
last_node = session.get_node(NODES, CoreNode)
address = prefixes.ip4_address(first_node)
logging.info("node %s pinging %s", last_node.name, address)
output = last_node.cmd(f"ping -c 3 {address}")

View file

@ -8,6 +8,7 @@ import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes
from core.emulator.enumerations import EventTypes, NodeTypes
from core.nodes.base import CoreNode
NODES = 2
@ -36,8 +37,8 @@ def main():
session.instantiate()
# get nodes to run example
first_node = session.get_node(1)
last_node = session.get_node(NODES)
first_node = session.get_node(1, CoreNode)
last_node = session.get_node(NODES, CoreNode)
address = prefixes.ip4_address(first_node)
logging.info("node %s pinging %s", last_node.name, address)
output = last_node.cmd(f"ping -c 3 {address}")

View file

@ -9,6 +9,7 @@ from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes
from core.location.mobility import BasicRangeModel
from core.nodes.base import CoreNode
NODES = 2
@ -40,8 +41,8 @@ def main():
session.instantiate()
# get nodes for example run
first_node = session.get_node(1)
last_node = session.get_node(NODES)
first_node = session.get_node(1, CoreNode)
last_node = session.get_node(NODES, CoreNode)
address = prefixes.ip4_address(first_node)
logging.info("node %s pinging %s", last_node.name, address)
output = last_node.cmd(f"ping -c 3 {address}")

View file

@ -9,11 +9,13 @@ import pytest
from core.emane.bypass import EmaneBypassModel
from core.emane.commeffect import EmaneCommEffectModel
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet
from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel
from core.emulator.emudata import NodeOptions
from core.emulator.enumerations import NodeTypes
from core.errors import CoreCommandError, CoreError
from core.nodes.base import CoreNode
_EMANE_MODELS = [
EmaneIeee80211abgModel,
@ -133,9 +135,9 @@ class TestEmane:
# verify nodes have been removed from session
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, CoreNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, CoreNode)
# load saved xml
session.open_xml(file_path, start=True)
@ -146,7 +148,7 @@ class TestEmane:
)
# verify nodes and configuration were restored
assert session.get_node(n1_id)
assert session.get_node(n2_id)
assert session.get_node(emane_id)
assert session.get_node(n1_id, CoreNode)
assert session.get_node(n2_id, CoreNode)
assert session.get_node(emane_id, EmaneNet)
assert value == config_value

View file

@ -19,6 +19,7 @@ from core.emulator.emudata import NodeOptions
from core.emulator.enumerations import EventTypes, ExceptionLevels, NodeTypes
from core.errors import CoreError
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
from core.nodes.base import CoreNode
from core.xml.corexml import CoreXmlWriter
@ -355,7 +356,7 @@ class TestGrpc:
# then
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):
# given
@ -402,7 +403,7 @@ class TestGrpc:
assert response.result is expected
if expected is True:
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):
if request.config.getoption("mock"):

View file

@ -24,6 +24,8 @@ from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.enumerations import EventTypes, MessageFlags, NodeTypes, RegisterTlvs
from core.errors import CoreError
from core.location.mobility import BasicRangeModel
from core.nodes.base import CoreNode, NodeBase
from core.nodes.network import SwitchNode
def dict_to_str(values):
@ -57,8 +59,7 @@ class TestGui:
)
coretlv.handle_message(message)
assert coretlv.session.get_node(node_id) is not None
assert coretlv.session.get_node(node_id, NodeBase) is not None
def test_node_update(self, coretlv):
node_id = 1
@ -76,7 +77,7 @@ class TestGui:
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.position.x == x
assert node.position.y == y
@ -91,7 +92,7 @@ class TestGui:
coretlv.handle_message(message)
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):
node_one = 1
@ -113,7 +114,7 @@ class TestGui:
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()
assert len(all_links) == 1
@ -137,7 +138,7 @@ class TestGui:
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()
assert len(all_links) == 1
@ -189,7 +190,7 @@ class TestGui:
],
)
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()
assert len(all_links) == 1
link = all_links[0]
@ -207,7 +208,7 @@ class TestGui:
)
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()
assert len(all_links) == 1
link = all_links[0]
@ -275,7 +276,7 @@ class TestGui:
],
)
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()
assert len(all_links) == 1
@ -289,7 +290,7 @@ class TestGui:
)
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()
assert len(all_links) == 0
@ -311,7 +312,7 @@ class TestGui:
],
)
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()
assert len(all_links) == 1
@ -325,7 +326,7 @@ class TestGui:
)
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()
assert len(all_links) == 0
@ -556,8 +557,7 @@ class TestGui:
)
coretlv.handle_message(message)
assert coretlv.session.get_node(node.id)
assert coretlv.session.get_node(node.id, NodeBase)
@pytest.mark.parametrize(
"state",
@ -619,7 +619,7 @@ class TestGui:
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):
xml_file = tmpdir.join("test.py")

View file

@ -3,6 +3,7 @@ import pytest
from core.emulator.emudata import NodeOptions
from core.emulator.enumerations import NodeTypes
from core.errors import CoreError
from core.nodes.base import CoreNode
MODELS = ["router", "host", "PC", "mdr"]
NET_TYPES = [NodeTypes.SWITCH, NodeTypes.HUB, NodeTypes.WIRELESS_LAN]
@ -45,7 +46,7 @@ class TestNodes:
# then
with pytest.raises(CoreError):
session.get_node(node.id)
session.get_node(node.id, CoreNode)
def test_node_sethwaddr(self, session):
# given

View file

@ -6,6 +6,8 @@ from core.emulator.emudata import LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes
from core.errors import CoreError
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
@ -91,16 +93,16 @@ class TestXml:
# verify nodes have been removed from session
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, CoreNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, CoreNode)
# load saved xml
session.open_xml(file_path, start=True)
# verify nodes have been recreated
assert session.get_node(n1_id)
assert session.get_node(n2_id)
assert session.get_node(n1_id, CoreNode)
assert session.get_node(n2_id, CoreNode)
def test_xml_ptp_services(self, session, tmpdir, ip_prefixes):
"""
@ -152,9 +154,9 @@ class TestXml:
# verify nodes have been removed from session
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, CoreNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, CoreNode)
# load saved xml
session.open_xml(file_path, start=True)
@ -163,8 +165,8 @@ class TestXml:
service = session.services.get_service(node_one.id, SshService.name)
# verify nodes have been recreated
assert session.get_node(n1_id)
assert session.get_node(n2_id)
assert session.get_node(n1_id, CoreNode)
assert session.get_node(n2_id, CoreNode)
assert service.config_data.get(service_file) == file_data
def test_xml_mobility(self, session, tmpdir, ip_prefixes):
@ -212,9 +214,9 @@ class TestXml:
# verify nodes have been removed from session
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, CoreNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, CoreNode)
# load saved xml
session.open_xml(file_path, start=True)
@ -223,9 +225,9 @@ class TestXml:
value = str(session.mobility.get_config("test", wlan_id, BasicRangeModel.name))
# verify nodes and configuration were restored
assert session.get_node(n1_id)
assert session.get_node(n2_id)
assert session.get_node(wlan_id)
assert session.get_node(n1_id, CoreNode)
assert session.get_node(n2_id, CoreNode)
assert session.get_node(wlan_id, WlanNode)
assert value == "1"
def test_network_to_network(self, session, tmpdir):
@ -263,16 +265,16 @@ class TestXml:
# verify nodes have been removed from session
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, SwitchNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, SwitchNode)
# load saved xml
session.open_xml(file_path, start=True)
# verify nodes have been recreated
switch_one = session.get_node(n1_id)
switch_two = session.get_node(n2_id)
switch_one = session.get_node(n1_id, SwitchNode)
switch_two = session.get_node(n2_id, SwitchNode)
assert switch_one
assert switch_two
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
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, CoreNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, SwitchNode)
# load saved xml
session.open_xml(file_path, start=True)
# verify nodes have been recreated
assert session.get_node(n1_id)
assert session.get_node(n2_id)
assert session.get_node(n1_id, CoreNode)
assert session.get_node(n2_id, SwitchNode)
links = []
for node_id in session.nodes:
node = session.nodes[node_id]
@ -389,16 +391,16 @@ class TestXml:
# verify nodes have been removed from session
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, CoreNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, CoreNode)
# load saved xml
session.open_xml(file_path, start=True)
# verify nodes have been recreated
assert session.get_node(n1_id)
assert session.get_node(n2_id)
assert session.get_node(n1_id, CoreNode)
assert session.get_node(n2_id, CoreNode)
links = []
for node_id in session.nodes:
node = session.nodes[node_id]
@ -471,16 +473,16 @@ class TestXml:
# verify nodes have been removed from session
with pytest.raises(CoreError):
assert not session.get_node(n1_id)
assert not session.get_node(n1_id, CoreNode)
with pytest.raises(CoreError):
assert not session.get_node(n2_id)
assert not session.get_node(n2_id, CoreNode)
# load saved xml
session.open_xml(file_path, start=True)
# verify nodes have been recreated
assert session.get_node(n1_id)
assert session.get_node(n2_id)
assert session.get_node(n1_id, CoreNode)
assert session.get_node(n2_id, CoreNode)
links = []
for node_id in session.nodes:
node = session.nodes[node_id]