Merge branch 'develop' into coretk
This commit is contained in:
commit
e19e8c12f7
66 changed files with 1702 additions and 1695 deletions
10
.github/workflows/daemon-checks.yml
vendored
10
.github/workflows/daemon-checks.yml
vendored
|
@ -17,6 +17,8 @@ jobs:
|
|||
pip install pipenv
|
||||
cd daemon
|
||||
cp setup.py.in setup.py
|
||||
cp core/constants.py.in core/constants.py
|
||||
sed -i 's/True/False/g' core/constants.py
|
||||
pipenv install --dev
|
||||
- name: isort
|
||||
run: |
|
||||
|
@ -30,3 +32,11 @@ jobs:
|
|||
run: |
|
||||
cd daemon
|
||||
pipenv run flake8
|
||||
- name: grpc
|
||||
run: |
|
||||
cd daemon/proto
|
||||
pipenv run python -m grpc_tools.protoc -I . --python_out=.. --grpc_python_out=.. core/api/grpc/core.proto
|
||||
- name: test
|
||||
run: |
|
||||
cd daemon
|
||||
pipenv run test --mock
|
||||
|
|
|
@ -14,7 +14,7 @@ from core.api.grpc import core_pb2, core_pb2_grpc
|
|||
from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress
|
||||
|
||||
|
||||
class InterfaceHelper(object):
|
||||
class InterfaceHelper:
|
||||
"""
|
||||
Convenience class to help generate IP4 and IP6 addresses for gRPC clients.
|
||||
"""
|
||||
|
@ -133,7 +133,7 @@ def start_streamer(stream, handler):
|
|||
thread.start()
|
||||
|
||||
|
||||
class CoreGrpcClient(object):
|
||||
class CoreGrpcClient:
|
||||
"""
|
||||
Provides convenience methods for interfacing with the CORE grpc server.
|
||||
"""
|
||||
|
@ -148,6 +148,57 @@ class CoreGrpcClient(object):
|
|||
self.stub = None
|
||||
self.channel = None
|
||||
|
||||
def start_session(
|
||||
self,
|
||||
session_id,
|
||||
nodes,
|
||||
links,
|
||||
location=None,
|
||||
hooks=None,
|
||||
emane_config=None,
|
||||
emane_model_configs=None,
|
||||
wlan_configs=None,
|
||||
mobility_configs=None,
|
||||
):
|
||||
"""
|
||||
Start a session.
|
||||
|
||||
:param int session_id: id of session
|
||||
:param list nodes: list of nodes to create
|
||||
:param list links: list of links to create
|
||||
:param core_pb2.SessionLocation location: location to set
|
||||
:param list[core_pb2.Hook] hooks: session hooks to set
|
||||
:param dict emane_config: emane configuration to set
|
||||
:param list emane_model_configs: emane model configurations to set
|
||||
:param list wlan_configs: wlan configurations to set
|
||||
:param list mobility_configs: mobility configurations to set
|
||||
:return: start session response
|
||||
:rtype: core_pb2.StartSessionResponse
|
||||
"""
|
||||
request = core_pb2.StartSessionRequest(
|
||||
session_id=session_id,
|
||||
nodes=nodes,
|
||||
links=links,
|
||||
location=location,
|
||||
hooks=hooks,
|
||||
emane_config=emane_config,
|
||||
emane_model_configs=emane_model_configs,
|
||||
wlan_configs=wlan_configs,
|
||||
mobility_configs=mobility_configs,
|
||||
)
|
||||
return self.stub.StartSession(request)
|
||||
|
||||
def stop_session(self, session_id):
|
||||
"""
|
||||
Stop a running session.
|
||||
|
||||
:param int session_id: id of session
|
||||
:return: stop session response
|
||||
:rtype: core_pb2.StopSessionResponse
|
||||
"""
|
||||
request = core_pb2.StopSessionRequest(session_id=session_id)
|
||||
return self.stub.StopSession(request)
|
||||
|
||||
def create_session(self, session_id=None):
|
||||
"""
|
||||
Create a session.
|
||||
|
@ -204,18 +255,6 @@ class CoreGrpcClient(object):
|
|||
request = core_pb2.GetSessionOptionsRequest(session_id=session_id)
|
||||
return self.stub.GetSessionOptions(request)
|
||||
|
||||
def get_session_options_group(self, session_id):
|
||||
"""
|
||||
Retrieve session options in a group list.
|
||||
|
||||
:param int session_id: id of session
|
||||
:return: response with a list of configuration groups
|
||||
:rtype: core_pb2.GetSessionOptionsGroupResponse
|
||||
:raises grpc.RpcError: when session doesn't exist
|
||||
"""
|
||||
request = core_pb2.GetSessionOptionsGroupRequest(session_id=session_id)
|
||||
return self.stub.GetSessionOptionsGroup(request)
|
||||
|
||||
def set_session_options(self, session_id, config):
|
||||
"""
|
||||
Set options for a session.
|
||||
|
@ -231,6 +270,33 @@ class CoreGrpcClient(object):
|
|||
)
|
||||
return self.stub.SetSessionOptions(request)
|
||||
|
||||
def get_session_metadata(self, session_id):
|
||||
"""
|
||||
Retrieve session metadata as a dict with id mapping.
|
||||
|
||||
:param int session_id: id of session
|
||||
:return: response with metadata dict
|
||||
:rtype: core_pb2.GetSessionMetadataResponse
|
||||
:raises grpc.RpcError: when session doesn't exist
|
||||
"""
|
||||
request = core_pb2.GetSessionMetadataRequest(session_id=session_id)
|
||||
return self.stub.GetSessionMetadata(request)
|
||||
|
||||
def set_session_metadata(self, session_id, config):
|
||||
"""
|
||||
Set metadata for a session.
|
||||
|
||||
:param int session_id: id of session
|
||||
:param dict[str, str] config: configuration values to set
|
||||
:return: response with result of success or failure
|
||||
:rtype: core_pb2.SetSessionMetadataResponse
|
||||
:raises grpc.RpcError: when session doesn't exist
|
||||
"""
|
||||
request = core_pb2.SetSessionMetadataRequest(
|
||||
session_id=session_id, config=config
|
||||
)
|
||||
return self.stub.SetSessionMetadata(request)
|
||||
|
||||
def get_session_location(self, session_id):
|
||||
"""
|
||||
Get session location.
|
||||
|
@ -269,9 +335,11 @@ class CoreGrpcClient(object):
|
|||
:rtype: core_pb2.SetSessionLocationResponse
|
||||
:raises grpc.RpcError: when session doesn't exist
|
||||
"""
|
||||
position = core_pb2.SessionPosition(x=x, y=y, z=z, lat=lat, lon=lon, alt=alt)
|
||||
location = core_pb2.SessionLocation(
|
||||
x=x, y=y, z=z, lat=lat, lon=lon, alt=alt, scale=scale
|
||||
)
|
||||
request = core_pb2.SetSessionLocationRequest(
|
||||
session_id=session_id, position=position, scale=scale
|
||||
session_id=session_id, location=location
|
||||
)
|
||||
return self.stub.SetSessionLocation(request)
|
||||
|
||||
|
@ -587,8 +655,9 @@ class CoreGrpcClient(object):
|
|||
:rtype: core_pb2.SetMobilityConfigResponse
|
||||
:raises grpc.RpcError: when session or node doesn't exist
|
||||
"""
|
||||
mobility_config = core_pb2.MobilityConfig(node_id=node_id, config=config)
|
||||
request = core_pb2.SetMobilityConfigRequest(
|
||||
session_id=session_id, node_id=node_id, config=config
|
||||
session_id=session_id, mobility_config=mobility_config
|
||||
)
|
||||
return self.stub.SetMobilityConfig(request)
|
||||
|
||||
|
@ -772,8 +841,9 @@ class CoreGrpcClient(object):
|
|||
:rtype: core_pb2.SetWlanConfigResponse
|
||||
:raises grpc.RpcError: when session doesn't exist
|
||||
"""
|
||||
wlan_config = core_pb2.WlanConfig(node_id=node_id, config=config)
|
||||
request = core_pb2.SetWlanConfigRequest(
|
||||
session_id=session_id, node_id=node_id, config=config
|
||||
session_id=session_id, wlan_config=wlan_config
|
||||
)
|
||||
return self.stub.SetWlanConfig(request)
|
||||
|
||||
|
@ -846,12 +916,11 @@ class CoreGrpcClient(object):
|
|||
:rtype: core_pb2.SetEmaneModelConfigResponse
|
||||
:raises grpc.RpcError: when session doesn't exist
|
||||
"""
|
||||
model_config = core_pb2.EmaneModelConfig(
|
||||
node_id=node_id, model=model, config=config, interface_id=interface_id
|
||||
)
|
||||
request = core_pb2.SetEmaneModelConfigRequest(
|
||||
session_id=session_id,
|
||||
node_id=node_id,
|
||||
model=model,
|
||||
config=config,
|
||||
interface_id=interface_id,
|
||||
session_id=session_id, emane_model_config=model_config
|
||||
)
|
||||
return self.stub.SetEmaneModelConfig(request)
|
||||
|
||||
|
|
321
daemon/core/api/grpc/grpcutils.py
Normal file
321
daemon/core/api/grpc/grpcutils.py
Normal file
|
@ -0,0 +1,321 @@
|
|||
import logging
|
||||
import time
|
||||
|
||||
from core import utils
|
||||
from core.api.grpc import core_pb2
|
||||
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
||||
from core.emulator.enumerations import LinkTypes, NodeTypes
|
||||
from core.nodes.base import CoreNetworkBase
|
||||
from core.nodes.ipaddress import MacAddress
|
||||
|
||||
WORKERS = 10
|
||||
|
||||
|
||||
def add_node_data(node_proto):
|
||||
"""
|
||||
Convert node protobuf message to data for creating a node.
|
||||
|
||||
:param core_pb2.Node node_proto: node proto message
|
||||
:return: node type, id, and options
|
||||
:rtype: tuple
|
||||
"""
|
||||
_id = node_proto.id
|
||||
_type = node_proto.type
|
||||
if _type is None:
|
||||
_type = NodeTypes.DEFAULT.value
|
||||
_type = NodeTypes(_type)
|
||||
|
||||
options = NodeOptions(name=node_proto.name, model=node_proto.model)
|
||||
options.icon = node_proto.icon
|
||||
options.opaque = node_proto.opaque
|
||||
options.image = node_proto.image
|
||||
options.services = node_proto.services
|
||||
if node_proto.server:
|
||||
options.server = node_proto.server
|
||||
|
||||
position = node_proto.position
|
||||
options.set_position(position.x, position.y)
|
||||
options.set_location(position.lat, position.lon, position.alt)
|
||||
return _type, _id, options
|
||||
|
||||
|
||||
def link_interface(interface_proto):
|
||||
"""
|
||||
Create interface data from interface proto.
|
||||
|
||||
:param core_pb2.Interface interface_proto: interface proto
|
||||
:return: interface data
|
||||
:rtype: InterfaceData
|
||||
"""
|
||||
interface = None
|
||||
if interface_proto:
|
||||
name = interface_proto.name
|
||||
if name == "":
|
||||
name = None
|
||||
mac = interface_proto.mac
|
||||
if mac == "":
|
||||
mac = None
|
||||
else:
|
||||
mac = MacAddress.from_string(mac)
|
||||
interface = InterfaceData(
|
||||
_id=interface_proto.id,
|
||||
name=name,
|
||||
mac=mac,
|
||||
ip4=interface_proto.ip4,
|
||||
ip4_mask=interface_proto.ip4mask,
|
||||
ip6=interface_proto.ip6,
|
||||
ip6_mask=interface_proto.ip6mask,
|
||||
)
|
||||
return interface
|
||||
|
||||
|
||||
def add_link_data(link_proto):
|
||||
"""
|
||||
Convert link proto to link interfaces and options data.
|
||||
|
||||
:param core_pb2.Link link_proto: link proto
|
||||
:return: link interfaces and options
|
||||
:rtype: tuple
|
||||
"""
|
||||
interface_one = link_interface(link_proto.interface_one)
|
||||
interface_two = link_interface(link_proto.interface_two)
|
||||
|
||||
link_type = None
|
||||
link_type_value = link_proto.type
|
||||
if link_type_value is not None:
|
||||
link_type = LinkTypes(link_type_value)
|
||||
|
||||
options = LinkOptions(_type=link_type)
|
||||
options_data = link_proto.options
|
||||
if options_data:
|
||||
options.delay = options_data.delay
|
||||
options.bandwidth = options_data.bandwidth
|
||||
options.per = options_data.per
|
||||
options.dup = options_data.dup
|
||||
options.jitter = options_data.jitter
|
||||
options.mer = options_data.mer
|
||||
options.burst = options_data.burst
|
||||
options.mburst = options_data.mburst
|
||||
options.unidirectional = options_data.unidirectional
|
||||
options.key = options_data.key
|
||||
options.opaque = options_data.opaque
|
||||
|
||||
return interface_one, interface_two, options
|
||||
|
||||
|
||||
def create_nodes(session, node_protos):
|
||||
"""
|
||||
Create nodes using a thread pool and wait for completion.
|
||||
|
||||
:param core.emulator.session.Session session: session to create nodes in
|
||||
:param list[core_pb2.Node] node_protos: node proto messages
|
||||
:return: results and exceptions for created nodes
|
||||
:rtype: tuple
|
||||
"""
|
||||
funcs = []
|
||||
for node_proto in node_protos:
|
||||
_type, _id, options = add_node_data(node_proto)
|
||||
args = (_type, _id, options)
|
||||
funcs.append((session.add_node, args, {}))
|
||||
start = time.monotonic()
|
||||
results, exceptions = utils.threadpool(funcs)
|
||||
total = time.monotonic() - start
|
||||
logging.debug("grpc created nodes time: %s", total)
|
||||
return results, exceptions
|
||||
|
||||
|
||||
def create_links(session, link_protos):
|
||||
"""
|
||||
Create nodes using a thread pool and wait for completion.
|
||||
|
||||
:param core.emulator.session.Session session: session to create nodes in
|
||||
:param list[core_pb2.Link] link_protos: link proto messages
|
||||
:return: results and exceptions for created links
|
||||
:rtype: tuple
|
||||
"""
|
||||
funcs = []
|
||||
for link_proto in link_protos:
|
||||
node_one_id = link_proto.node_one_id
|
||||
node_two_id = link_proto.node_two_id
|
||||
interface_one, interface_two, options = add_link_data(link_proto)
|
||||
args = (node_one_id, node_two_id, interface_one, interface_two, options)
|
||||
funcs.append((session.add_link, args, {}))
|
||||
start = time.monotonic()
|
||||
results, exceptions = utils.threadpool(funcs)
|
||||
total = time.monotonic() - start
|
||||
logging.debug("grpc created links time: %s", total)
|
||||
return results, exceptions
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
"""
|
||||
Convert value into string.
|
||||
|
||||
:param value: value
|
||||
:return: string conversion of the value
|
||||
:rtype: str
|
||||
"""
|
||||
if value is not None:
|
||||
value = str(value)
|
||||
return value
|
||||
|
||||
|
||||
def get_config_options(config, configurable_options):
|
||||
"""
|
||||
Retrieve configuration options in a form that is used by the grpc server.
|
||||
|
||||
:param dict config: configuration
|
||||
:param core.config.ConfigurableOptions configurable_options: configurable options
|
||||
:return: mapping of configuration ids to configuration options
|
||||
:rtype: dict[str,core.api.grpc.core_pb2.ConfigOption]
|
||||
"""
|
||||
results = {}
|
||||
for configuration in configurable_options.configurations():
|
||||
value = config[configuration.id]
|
||||
config_option = core_pb2.ConfigOption(
|
||||
label=configuration.label,
|
||||
name=configuration.id,
|
||||
value=value,
|
||||
type=configuration.type.value,
|
||||
select=configuration.options,
|
||||
)
|
||||
results[configuration.id] = config_option
|
||||
for config_group in configurable_options.config_groups():
|
||||
start = config_group.start - 1
|
||||
stop = config_group.stop
|
||||
options = list(results.values())[start:stop]
|
||||
for option in options:
|
||||
option.group = config_group.name
|
||||
return results
|
||||
|
||||
|
||||
def get_links(session, node):
|
||||
"""
|
||||
Retrieve a list of links for grpc to use
|
||||
|
||||
:param core.emulator.Session session: node's section
|
||||
:param core.nodes.base.CoreNode node: node to get links from
|
||||
:return: [core.api.grpc.core_pb2.Link]
|
||||
"""
|
||||
links = []
|
||||
for link_data in node.all_link_data(0):
|
||||
link = convert_link(session, link_data)
|
||||
links.append(link)
|
||||
return links
|
||||
|
||||
|
||||
def get_emane_model_id(node_id, interface_id):
|
||||
"""
|
||||
Get EMANE model id
|
||||
|
||||
:param int node_id: node id
|
||||
:param int interface_id: interface id
|
||||
:return: EMANE model id
|
||||
:rtype: int
|
||||
"""
|
||||
if interface_id >= 0:
|
||||
return node_id * 1000 + interface_id
|
||||
else:
|
||||
return node_id
|
||||
|
||||
|
||||
def convert_link(session, link_data):
|
||||
"""
|
||||
Convert link_data into core protobuf Link
|
||||
|
||||
:param core.emulator.session.Session session:
|
||||
:param core.emulator.data.LinkData link_data:
|
||||
:return: core protobuf Link
|
||||
:rtype: core.api.grpc.core_pb2.Link
|
||||
"""
|
||||
interface_one = None
|
||||
if link_data.interface1_id is not None:
|
||||
node = session.get_node(link_data.node1_id)
|
||||
interface_name = None
|
||||
if not isinstance(node, CoreNetworkBase):
|
||||
interface = node.netif(link_data.interface1_id)
|
||||
interface_name = interface.name
|
||||
interface_one = core_pb2.Interface(
|
||||
id=link_data.interface1_id,
|
||||
name=interface_name,
|
||||
mac=convert_value(link_data.interface1_mac),
|
||||
ip4=convert_value(link_data.interface1_ip4),
|
||||
ip4mask=link_data.interface1_ip4_mask,
|
||||
ip6=convert_value(link_data.interface1_ip6),
|
||||
ip6mask=link_data.interface1_ip6_mask,
|
||||
)
|
||||
|
||||
interface_two = None
|
||||
if link_data.interface2_id is not None:
|
||||
node = session.get_node(link_data.node2_id)
|
||||
interface_name = None
|
||||
if not isinstance(node, CoreNetworkBase):
|
||||
interface = node.netif(link_data.interface2_id)
|
||||
interface_name = interface.name
|
||||
interface_two = core_pb2.Interface(
|
||||
id=link_data.interface2_id,
|
||||
name=interface_name,
|
||||
mac=convert_value(link_data.interface2_mac),
|
||||
ip4=convert_value(link_data.interface2_ip4),
|
||||
ip4mask=link_data.interface2_ip4_mask,
|
||||
ip6=convert_value(link_data.interface2_ip6),
|
||||
ip6mask=link_data.interface2_ip6_mask,
|
||||
)
|
||||
|
||||
options = core_pb2.LinkOptions(
|
||||
opaque=link_data.opaque,
|
||||
jitter=link_data.jitter,
|
||||
key=link_data.key,
|
||||
mburst=link_data.mburst,
|
||||
mer=link_data.mer,
|
||||
per=link_data.per,
|
||||
bandwidth=link_data.bandwidth,
|
||||
burst=link_data.burst,
|
||||
delay=link_data.delay,
|
||||
dup=link_data.dup,
|
||||
unidirectional=link_data.unidirectional,
|
||||
)
|
||||
|
||||
return core_pb2.Link(
|
||||
type=link_data.link_type,
|
||||
node_one_id=link_data.node1_id,
|
||||
node_two_id=link_data.node2_id,
|
||||
interface_one=interface_one,
|
||||
interface_two=interface_two,
|
||||
options=options,
|
||||
)
|
||||
|
||||
|
||||
def get_net_stats():
|
||||
"""
|
||||
Retrieve status about the current interfaces in the system
|
||||
|
||||
:return: send and receive status of the interfaces in the system
|
||||
:rtype: dict
|
||||
"""
|
||||
with open("/proc/net/dev", "r") as f:
|
||||
data = f.readlines()[2:]
|
||||
|
||||
stats = {}
|
||||
for line in data:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
line = line.split()
|
||||
line[0] = line[0].strip(":")
|
||||
stats[line[0]] = {"rx": float(line[1]), "tx": float(line[9])}
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
def session_location(session, location):
|
||||
"""
|
||||
Set session location based on location proto.
|
||||
|
||||
:param core.emulator.session.Session session: session for location
|
||||
:param core_pb2.SessionLocation location: location to set
|
||||
:return: nothing
|
||||
"""
|
||||
session.location.refxyz = (location.x, location.y, location.z)
|
||||
session.location.setrefgeo(location.lat, location.lon, location.alt)
|
||||
session.location.refscale = location.scale
|
|
@ -9,7 +9,14 @@ from queue import Empty, Queue
|
|||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc import core_pb2, core_pb2_grpc
|
||||
from core.api.grpc import core_pb2, core_pb2_grpc, grpcutils
|
||||
from core.api.grpc.grpcutils import (
|
||||
convert_value,
|
||||
get_config_options,
|
||||
get_emane_model_id,
|
||||
get_links,
|
||||
get_net_stats,
|
||||
)
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.data import (
|
||||
ConfigData,
|
||||
|
@ -19,13 +26,11 @@ from core.emulator.data import (
|
|||
LinkData,
|
||||
NodeData,
|
||||
)
|
||||
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
||||
from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags, NodeTypes
|
||||
from core.emulator.emudata import LinkOptions, NodeOptions
|
||||
from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
from core.nodes.base import CoreNetworkBase
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.ipaddress import MacAddress
|
||||
from core.nodes.lxd import LxcNode
|
||||
from core.services.coreservices import ServiceManager
|
||||
|
||||
|
@ -33,167 +38,6 @@ _ONE_DAY_IN_SECONDS = 60 * 60 * 24
|
|||
_INTERFACE_REGEX = re.compile(r"\d+")
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
"""
|
||||
Convert value into string.
|
||||
|
||||
:param value: value
|
||||
:return: string conversion of the value
|
||||
:rtype: str
|
||||
"""
|
||||
if value is not None:
|
||||
value = str(value)
|
||||
return value
|
||||
|
||||
|
||||
def get_config_options(config, configurable_options):
|
||||
"""
|
||||
Retrieve configuration options in a form that is used by the grpc server.
|
||||
|
||||
:param dict config: configuration
|
||||
:param core.config.ConfigurableOptions configurable_options: configurable options
|
||||
:return: mapping of configuration ids to configuration options
|
||||
:rtype: dict[str,core.api.grpc.core_pb2.ConfigOption]
|
||||
"""
|
||||
results = {}
|
||||
for configuration in configurable_options.configurations():
|
||||
value = config[configuration.id]
|
||||
config_option = core_pb2.ConfigOption(
|
||||
label=configuration.label,
|
||||
name=configuration.id,
|
||||
value=value,
|
||||
type=configuration.type.value,
|
||||
select=configuration.options,
|
||||
)
|
||||
results[configuration.id] = config_option
|
||||
for config_group in configurable_options.config_groups():
|
||||
start = config_group.start - 1
|
||||
stop = config_group.stop
|
||||
options = list(results.values())[start:stop]
|
||||
for option in options:
|
||||
option.group = config_group.name
|
||||
return results
|
||||
|
||||
|
||||
def get_links(session, node):
|
||||
"""
|
||||
Retrieve a list of links for grpc to use
|
||||
|
||||
:param core.emulator.Session session: node's section
|
||||
:param core.nodes.base.CoreNode node: node to get links from
|
||||
:return: [core.api.grpc.core_pb2.Link]
|
||||
"""
|
||||
links = []
|
||||
for link_data in node.all_link_data(0):
|
||||
link = convert_link(session, link_data)
|
||||
links.append(link)
|
||||
return links
|
||||
|
||||
|
||||
def get_emane_model_id(node_id, interface_id):
|
||||
"""
|
||||
Get EMANE model id
|
||||
|
||||
:param int node_id: node id
|
||||
:param int interface_id: interface id
|
||||
:return: EMANE model id
|
||||
:rtype: int
|
||||
"""
|
||||
if interface_id >= 0:
|
||||
return node_id * 1000 + interface_id
|
||||
else:
|
||||
return node_id
|
||||
|
||||
|
||||
def convert_link(session, link_data):
|
||||
"""
|
||||
Convert link_data into core protobuf Link
|
||||
|
||||
:param core.emulator.session.Session session:
|
||||
:param core.emulator.data.LinkData link_data:
|
||||
:return: core protobuf Link
|
||||
:rtype: core.api.grpc.core_pb2.Link
|
||||
"""
|
||||
interface_one = None
|
||||
if link_data.interface1_id is not None:
|
||||
node = session.get_node(link_data.node1_id)
|
||||
interface_name = None
|
||||
if not isinstance(node, CoreNetworkBase):
|
||||
interface = node.netif(link_data.interface1_id)
|
||||
interface_name = interface.name
|
||||
interface_one = core_pb2.Interface(
|
||||
id=link_data.interface1_id,
|
||||
name=interface_name,
|
||||
mac=convert_value(link_data.interface1_mac),
|
||||
ip4=convert_value(link_data.interface1_ip4),
|
||||
ip4mask=link_data.interface1_ip4_mask,
|
||||
ip6=convert_value(link_data.interface1_ip6),
|
||||
ip6mask=link_data.interface1_ip6_mask,
|
||||
)
|
||||
|
||||
interface_two = None
|
||||
if link_data.interface2_id is not None:
|
||||
node = session.get_node(link_data.node2_id)
|
||||
interface_name = None
|
||||
if not isinstance(node, CoreNetworkBase):
|
||||
interface = node.netif(link_data.interface2_id)
|
||||
interface_name = interface.name
|
||||
interface_two = core_pb2.Interface(
|
||||
id=link_data.interface2_id,
|
||||
name=interface_name,
|
||||
mac=convert_value(link_data.interface2_mac),
|
||||
ip4=convert_value(link_data.interface2_ip4),
|
||||
ip4mask=link_data.interface2_ip4_mask,
|
||||
ip6=convert_value(link_data.interface2_ip6),
|
||||
ip6mask=link_data.interface2_ip6_mask,
|
||||
)
|
||||
|
||||
options = core_pb2.LinkOptions(
|
||||
opaque=link_data.opaque,
|
||||
jitter=link_data.jitter,
|
||||
key=link_data.key,
|
||||
mburst=link_data.mburst,
|
||||
mer=link_data.mer,
|
||||
per=link_data.per,
|
||||
bandwidth=link_data.bandwidth,
|
||||
burst=link_data.burst,
|
||||
delay=link_data.delay,
|
||||
dup=link_data.dup,
|
||||
unidirectional=link_data.unidirectional,
|
||||
)
|
||||
|
||||
return core_pb2.Link(
|
||||
type=link_data.link_type,
|
||||
node_one_id=link_data.node1_id,
|
||||
node_two_id=link_data.node2_id,
|
||||
interface_one=interface_one,
|
||||
interface_two=interface_two,
|
||||
options=options,
|
||||
)
|
||||
|
||||
|
||||
def get_net_stats():
|
||||
"""
|
||||
Retrieve status about the current interfaces in the system
|
||||
|
||||
:return: send and receive status of the interfaces in the system
|
||||
:rtype: dict
|
||||
"""
|
||||
with open("/proc/net/dev", "r") as f:
|
||||
data = f.readlines()[2:]
|
||||
|
||||
stats = {}
|
||||
for line in data:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
line = line.split()
|
||||
line[0] = line[0].strip(":")
|
||||
stats[line[0]] = {"rx": float(line[1]), "tx": float(line[9])}
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||
"""
|
||||
Create CoreGrpcServer instance
|
||||
|
@ -202,7 +46,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
|
||||
def __init__(self, coreemu):
|
||||
super(CoreGrpcServer, self).__init__()
|
||||
super().__init__()
|
||||
self.coreemu = coreemu
|
||||
self.running = True
|
||||
self.server = None
|
||||
|
@ -237,7 +81,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
|
||||
:param int session_id: session id
|
||||
:param grpc.ServicerContext context:
|
||||
:return: session object that satisfies. If session not found then raise an exception.
|
||||
:return: session object that satisfies, if session not found then raise an
|
||||
exception
|
||||
:rtype: core.emulator.session.Session
|
||||
"""
|
||||
session = self.coreemu.sessions.get(session_id)
|
||||
|
@ -260,6 +105,80 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
except CoreError:
|
||||
context.abort(grpc.StatusCode.NOT_FOUND, f"node {node_id} not found")
|
||||
|
||||
def StartSession(self, request, context):
|
||||
"""
|
||||
Start a session.
|
||||
|
||||
:param core.api.grpc.core_pb2.StartSessionRequest request: start session request
|
||||
:param context: grcp context
|
||||
:return: start session response
|
||||
:rtype: core.api.grpc.core_pb2.StartSessionResponse
|
||||
"""
|
||||
logging.debug("start session: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
|
||||
# clear previous state and setup for creation
|
||||
session.clear()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
if not os.path.exists(session.session_dir):
|
||||
os.mkdir(session.session_dir)
|
||||
|
||||
# location
|
||||
if request.HasField("location"):
|
||||
grpcutils.session_location(session, request.location)
|
||||
|
||||
# add all hooks
|
||||
for hook in request.hooks:
|
||||
session.add_hook(hook.state, hook.file, None, hook.data)
|
||||
|
||||
# create nodes
|
||||
grpcutils.create_nodes(session, request.nodes)
|
||||
|
||||
# emane configs
|
||||
config = session.emane.get_configs()
|
||||
config.update(request.emane_config)
|
||||
for config in request.emane_model_configs:
|
||||
_id = get_emane_model_id(config.node_id, config.interface_id)
|
||||
session.emane.set_model_config(_id, config.model, config.config)
|
||||
|
||||
# wlan configs
|
||||
for config in request.wlan_configs:
|
||||
session.mobility.set_model_config(
|
||||
config.node_id, BasicRangeModel.name, config.config
|
||||
)
|
||||
|
||||
# mobility configs
|
||||
for config in request.mobility_configs:
|
||||
session.mobility.set_model_config(
|
||||
config.node_id, Ns2ScriptedMobility.name, config.config
|
||||
)
|
||||
|
||||
# create links
|
||||
grpcutils.create_links(session, request.links)
|
||||
|
||||
# set to instantiation and start
|
||||
session.set_state(EventTypes.INSTANTIATION_STATE)
|
||||
session.instantiate()
|
||||
|
||||
return core_pb2.StartSessionResponse(result=True)
|
||||
|
||||
def StopSession(self, request, context):
|
||||
"""
|
||||
Stop a running session.
|
||||
|
||||
:param core.api.grpc.core_pb2.StopSessionRequest request: stop session request
|
||||
:param context: grcp context
|
||||
:return: stop session response
|
||||
:rtype: core.api.grpc.core_pb2.StopSessionResponse
|
||||
"""
|
||||
logging.debug("stop session: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
session.data_collect()
|
||||
session.set_state(EventTypes.DATACOLLECT_STATE)
|
||||
session.clear()
|
||||
session.set_state(EventTypes.SHUTDOWN_STATE)
|
||||
return core_pb2.StopSessionResponse(result=True)
|
||||
|
||||
def CreateSession(self, request, context):
|
||||
"""
|
||||
Create a session
|
||||
|
@ -326,10 +245,11 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
session = self.get_session(request.session_id, context)
|
||||
x, y, z = session.location.refxyz
|
||||
lat, lon, alt = session.location.refgeo
|
||||
position = core_pb2.SessionPosition(x=x, y=y, z=z, lat=lat, lon=lon, alt=alt)
|
||||
return core_pb2.GetSessionLocationResponse(
|
||||
position=position, scale=session.location.refscale
|
||||
scale = session.location.refscale
|
||||
location = core_pb2.SessionLocation(
|
||||
x=x, y=y, z=z, lat=lat, lon=lon, alt=alt, scale=scale
|
||||
)
|
||||
return core_pb2.GetSessionLocationResponse(location=location)
|
||||
|
||||
def SetSessionLocation(self, request, context):
|
||||
"""
|
||||
|
@ -342,15 +262,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logging.debug("set session location: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
session.location.refxyz = (
|
||||
request.position.x,
|
||||
request.position.y,
|
||||
request.position.z,
|
||||
)
|
||||
session.location.setrefgeo(
|
||||
request.position.lat, request.position.lon, request.position.alt
|
||||
)
|
||||
session.location.refscale = request.scale
|
||||
grpcutils.session_location(session, request.location)
|
||||
return core_pb2.SetSessionLocationResponse(result=True)
|
||||
|
||||
def SetSessionState(self, request, context):
|
||||
|
@ -419,6 +331,34 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
config.update(request.config)
|
||||
return core_pb2.SetSessionOptionsResponse(result=True)
|
||||
|
||||
def GetSessionMetadata(self, request, context):
|
||||
"""
|
||||
Retrieve session metadata.
|
||||
|
||||
:param core.api.grpc.core_pb2.GetSessionMetadata request: get session metadata
|
||||
request
|
||||
:param grpc.ServicerContext context: context object
|
||||
:return: get session metadata response
|
||||
:rtype: core.api.grpc.core_pb2.GetSessionMetadata
|
||||
"""
|
||||
logging.debug("get session metadata: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
return core_pb2.GetSessionMetadataResponse(config=session.metadata)
|
||||
|
||||
def SetSessionMetadata(self, request, context):
|
||||
"""
|
||||
Update a session's metadata.
|
||||
|
||||
:param core.api.grpc.core_pb2.SetSessionMetadata request: set metadata request
|
||||
:param grpc.ServicerContext context: context object
|
||||
:return: set metadata response
|
||||
:rtype: core.api.grpc.core_pb2.SetSessionMetadataResponse
|
||||
"""
|
||||
logging.debug("set session metadata: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
session.metadata = dict(request.config)
|
||||
return core_pb2.SetSessionMetadataResponse(result=True)
|
||||
|
||||
def GetSession(self, request, context):
|
||||
"""
|
||||
Retrieve requested session
|
||||
|
@ -761,32 +701,12 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logging.debug("add node: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
|
||||
node_proto = request.node
|
||||
node_id = node_proto.id
|
||||
node_type = node_proto.type
|
||||
if node_type is None:
|
||||
node_type = NodeTypes.DEFAULT.value
|
||||
node_type = NodeTypes(node_type)
|
||||
|
||||
node_options = NodeOptions(name=node_proto.name, model=node_proto.model)
|
||||
node_options.icon = node_proto.icon
|
||||
node_options.opaque = node_proto.opaque
|
||||
node_options.image = node_proto.image
|
||||
node_options.services = node_proto.services
|
||||
if node_proto.server:
|
||||
node_options.emulation_server = node_proto.server
|
||||
|
||||
position = node_proto.position
|
||||
node_options.set_position(position.x, position.y)
|
||||
node_options.set_location(position.lat, position.lon, position.alt)
|
||||
node = session.add_node(_type=node_type, _id=node_id, node_options=node_options)
|
||||
|
||||
_type, _id, options = grpcutils.add_node_data(request.node)
|
||||
node = session.add_node(_type=_type, _id=_id, options=options)
|
||||
# configure emane if provided
|
||||
emane_model = node_proto.emane
|
||||
emane_model = request.node.emane
|
||||
if emane_model:
|
||||
session.emane.set_model_config(node_id, emane_model)
|
||||
|
||||
session.emane.set_model_config(id, emane_model)
|
||||
return core_pb2.AddNodeResponse(node_id=node.id)
|
||||
|
||||
def GetNode(self, request, context):
|
||||
|
@ -856,18 +776,18 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
logging.debug("edit node: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
node = self.get_node(session, request.node_id, context)
|
||||
node_options = NodeOptions()
|
||||
node_options.icon = request.icon
|
||||
options = NodeOptions()
|
||||
options.icon = request.icon
|
||||
x = request.position.x
|
||||
y = request.position.y
|
||||
node_options.set_position(x, y)
|
||||
options.set_position(x, y)
|
||||
lat = request.position.lat
|
||||
lon = request.position.lon
|
||||
alt = request.position.alt
|
||||
node_options.set_location(lat, lon, alt)
|
||||
options.set_location(lat, lon, alt)
|
||||
result = True
|
||||
try:
|
||||
session.update_node(node.id, node_options)
|
||||
session.edit_node(node.id, options)
|
||||
node_data = node.data(0)
|
||||
session.broadcast_node(node_data)
|
||||
except CoreError:
|
||||
|
@ -944,82 +864,16 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
:rtype: core.api.grpc.AddLinkResponse
|
||||
"""
|
||||
logging.debug("add link: %s", request)
|
||||
# validate session and nodes
|
||||
session = self.get_session(request.session_id, context)
|
||||
|
||||
# validate node exist
|
||||
self.get_node(session, request.link.node_one_id, context)
|
||||
self.get_node(session, request.link.node_two_id, context)
|
||||
|
||||
node_one_id = request.link.node_one_id
|
||||
node_two_id = request.link.node_two_id
|
||||
|
||||
interface_one = None
|
||||
interface_one_data = request.link.interface_one
|
||||
if interface_one_data:
|
||||
name = interface_one_data.name
|
||||
if name == "":
|
||||
name = None
|
||||
mac = interface_one_data.mac
|
||||
if mac == "":
|
||||
mac = None
|
||||
else:
|
||||
mac = MacAddress.from_string(mac)
|
||||
interface_one = InterfaceData(
|
||||
_id=interface_one_data.id,
|
||||
name=name,
|
||||
mac=mac,
|
||||
ip4=interface_one_data.ip4,
|
||||
ip4_mask=interface_one_data.ip4mask,
|
||||
ip6=interface_one_data.ip6,
|
||||
ip6_mask=interface_one_data.ip6mask,
|
||||
)
|
||||
|
||||
interface_two = None
|
||||
interface_two_data = request.link.interface_two
|
||||
if interface_two_data:
|
||||
name = interface_two_data.name
|
||||
if name == "":
|
||||
name = None
|
||||
mac = interface_two_data.mac
|
||||
if mac == "":
|
||||
mac = None
|
||||
else:
|
||||
mac = MacAddress.from_string(mac)
|
||||
interface_two = InterfaceData(
|
||||
_id=interface_two_data.id,
|
||||
name=name,
|
||||
mac=mac,
|
||||
ip4=interface_two_data.ip4,
|
||||
ip4_mask=interface_two_data.ip4mask,
|
||||
ip6=interface_two_data.ip6,
|
||||
ip6_mask=interface_two_data.ip6mask,
|
||||
)
|
||||
|
||||
link_type = None
|
||||
link_type_value = request.link.type
|
||||
if link_type_value is not None:
|
||||
link_type = LinkTypes(link_type_value)
|
||||
|
||||
options_data = request.link.options
|
||||
link_options = LinkOptions(_type=link_type)
|
||||
if options_data:
|
||||
link_options.delay = options_data.delay
|
||||
link_options.bandwidth = options_data.bandwidth
|
||||
link_options.per = options_data.per
|
||||
link_options.dup = options_data.dup
|
||||
link_options.jitter = options_data.jitter
|
||||
link_options.mer = options_data.mer
|
||||
link_options.burst = options_data.burst
|
||||
link_options.mburst = options_data.mburst
|
||||
link_options.unidirectional = options_data.unidirectional
|
||||
link_options.key = options_data.key
|
||||
link_options.opaque = options_data.opaque
|
||||
|
||||
interface_one, interface_two, options = grpcutils.add_link_data(request.link)
|
||||
session.add_link(
|
||||
node_one_id,
|
||||
node_two_id,
|
||||
interface_one,
|
||||
interface_two,
|
||||
link_options=link_options,
|
||||
node_one_id, node_two_id, interface_one, interface_two, link_options=options
|
||||
)
|
||||
return core_pb2.AddLinkResponse(result=True)
|
||||
|
||||
|
@ -1166,8 +1020,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logging.debug("set mobility config: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
mobility_config = request.mobility_config
|
||||
session.mobility.set_model_config(
|
||||
request.node_id, Ns2ScriptedMobility.name, request.config
|
||||
mobility_config.node_id, Ns2ScriptedMobility.name, mobility_config.config
|
||||
)
|
||||
return core_pb2.SetMobilityConfigResponse(result=True)
|
||||
|
||||
|
@ -1408,12 +1263,13 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logging.debug("set wlan config: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
wlan_config = request.wlan_config
|
||||
session.mobility.set_model_config(
|
||||
request.node_id, BasicRangeModel.name, request.config
|
||||
wlan_config.node_id, BasicRangeModel.name, wlan_config.config
|
||||
)
|
||||
if session.state == EventTypes.RUNTIME_STATE.value:
|
||||
node = self.get_node(session, request.node_id, context)
|
||||
node.updatemodel(request.config)
|
||||
node = self.get_node(session, wlan_config.node_id, context)
|
||||
node.updatemodel(wlan_config.config)
|
||||
return core_pb2.SetWlanConfigResponse(result=True)
|
||||
|
||||
def GetEmaneConfig(self, request, context):
|
||||
|
@ -1494,8 +1350,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logging.debug("set emane model config: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
_id = get_emane_model_id(request.node_id, request.interface_id)
|
||||
session.emane.set_model_config(_id, request.model, request.config)
|
||||
model_config = request.emane_model_config
|
||||
_id = get_emane_model_id(model_config.node_id, model_config.interface_id)
|
||||
session.emane.set_model_config(_id, model_config.model, model_config.config)
|
||||
return core_pb2.SetEmaneModelConfigResponse(result=True)
|
||||
|
||||
def GetEmaneModelConfigs(self, request, context):
|
||||
|
|
|
@ -27,7 +27,7 @@ from core.emulator.enumerations import (
|
|||
from core.nodes.ipaddress import IpAddress, MacAddress
|
||||
|
||||
|
||||
class CoreTlvData(object):
|
||||
class CoreTlvData:
|
||||
"""
|
||||
Helper base class used for packing and unpacking values using struct.
|
||||
"""
|
||||
|
@ -94,12 +94,12 @@ class CoreTlvDataObj(CoreTlvData):
|
|||
"""
|
||||
Convenience method for packing custom object data.
|
||||
|
||||
:param obj: custom object to pack
|
||||
:param value: custom object to pack
|
||||
:return: length of data and the packed data itself
|
||||
:rtype: tuple
|
||||
"""
|
||||
value = cls.get_value(value)
|
||||
return super(CoreTlvDataObj, cls).pack(value)
|
||||
return super().pack(value)
|
||||
|
||||
@classmethod
|
||||
def unpack(cls, data):
|
||||
|
@ -109,7 +109,7 @@ class CoreTlvDataObj(CoreTlvData):
|
|||
:param data: data to unpack custom object from
|
||||
:return: unpacked custom object
|
||||
"""
|
||||
data = super(CoreTlvDataObj, cls).unpack(data)
|
||||
data = super().unpack(data)
|
||||
return cls.new_obj(data)
|
||||
|
||||
@staticmethod
|
||||
|
@ -348,7 +348,7 @@ class CoreTlvDataMacAddr(CoreTlvDataObj):
|
|||
return MacAddress(address=value[2:])
|
||||
|
||||
|
||||
class CoreTlv(object):
|
||||
class CoreTlv:
|
||||
"""
|
||||
Base class for representing CORE TLVs.
|
||||
"""
|
||||
|
@ -670,7 +670,7 @@ class CoreExceptionTlv(CoreTlv):
|
|||
}
|
||||
|
||||
|
||||
class CoreMessage(object):
|
||||
class CoreMessage:
|
||||
"""
|
||||
Base class for representing CORE messages.
|
||||
"""
|
||||
|
|
|
@ -83,13 +83,9 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
self.handler_threads.append(thread)
|
||||
thread.start()
|
||||
|
||||
self.master = False
|
||||
self.session = None
|
||||
self.session_clients = {}
|
||||
|
||||
# core emulator
|
||||
self.coreemu = server.coreemu
|
||||
|
||||
utils.close_onexec(request.fileno())
|
||||
socketserver.BaseRequestHandler.__init__(self, request, client_address, server)
|
||||
|
||||
|
@ -127,7 +123,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
for thread in self.handler_threads:
|
||||
logging.info("waiting for thread: %s", thread.getName())
|
||||
thread.join(timeout)
|
||||
if thread.isAlive():
|
||||
if thread.is_alive():
|
||||
logging.warning(
|
||||
"joining %s failed: still alive after %s sec",
|
||||
thread.getName(),
|
||||
|
@ -434,9 +430,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
tlv_data += coreapi.CoreRegisterTlv.pack(
|
||||
self.session.options.config_type, self.session.options.name
|
||||
)
|
||||
tlv_data += coreapi.CoreRegisterTlv.pack(
|
||||
self.session.metadata.config_type, self.session.metadata.name
|
||||
)
|
||||
tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.UTILITY.value, "metadata")
|
||||
|
||||
return coreapi.CoreRegMessage.pack(MessageFlags.ADD.value, tlv_data)
|
||||
|
||||
|
@ -591,12 +585,8 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
port = self.request.getpeername()[1]
|
||||
|
||||
# TODO: add shutdown handler for session
|
||||
self.session = self.coreemu.create_session(port, master=False)
|
||||
self.session = self.coreemu.create_session(port)
|
||||
logging.debug("created new session for client: %s", self.session.id)
|
||||
|
||||
if self.master:
|
||||
logging.debug("session set to master")
|
||||
self.session.master = True
|
||||
clients = self.session_clients.setdefault(self.session.id, [])
|
||||
clients.append(self)
|
||||
|
||||
|
@ -698,12 +688,12 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
|
||||
node_id = message.get_tlv(NodeTlvs.NUMBER.value)
|
||||
|
||||
node_options = NodeOptions(
|
||||
options = NodeOptions(
|
||||
name=message.get_tlv(NodeTlvs.NAME.value),
|
||||
model=message.get_tlv(NodeTlvs.MODEL.value),
|
||||
)
|
||||
|
||||
node_options.set_position(
|
||||
options.set_position(
|
||||
x=message.get_tlv(NodeTlvs.X_POSITION.value),
|
||||
y=message.get_tlv(NodeTlvs.Y_POSITION.value),
|
||||
)
|
||||
|
@ -717,19 +707,19 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
alt = message.get_tlv(NodeTlvs.ALTITUDE.value)
|
||||
if alt is not None:
|
||||
alt = float(alt)
|
||||
node_options.set_location(lat=lat, lon=lon, alt=alt)
|
||||
options.set_location(lat=lat, lon=lon, alt=alt)
|
||||
|
||||
node_options.icon = message.get_tlv(NodeTlvs.ICON.value)
|
||||
node_options.canvas = message.get_tlv(NodeTlvs.CANVAS.value)
|
||||
node_options.opaque = message.get_tlv(NodeTlvs.OPAQUE.value)
|
||||
node_options.emulation_server = message.get_tlv(NodeTlvs.EMULATION_SERVER.value)
|
||||
options.icon = message.get_tlv(NodeTlvs.ICON.value)
|
||||
options.canvas = message.get_tlv(NodeTlvs.CANVAS.value)
|
||||
options.opaque = message.get_tlv(NodeTlvs.OPAQUE.value)
|
||||
options.server = message.get_tlv(NodeTlvs.EMULATION_SERVER.value)
|
||||
|
||||
services = message.get_tlv(NodeTlvs.SERVICES.value)
|
||||
if services:
|
||||
node_options.services = services.split("|")
|
||||
options.services = services.split("|")
|
||||
|
||||
if message.flags & MessageFlags.ADD.value:
|
||||
node = self.session.add_node(node_type, node_id, node_options)
|
||||
node = self.session.add_node(node_type, node_id, options)
|
||||
if node:
|
||||
if message.flags & MessageFlags.STRING.value:
|
||||
self.node_status_request[node.id] = True
|
||||
|
@ -748,7 +738,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata))
|
||||
# node update
|
||||
else:
|
||||
self.session.update_node(node_id, node_options)
|
||||
self.session.edit_node(node_id, options)
|
||||
|
||||
return replies
|
||||
|
||||
|
@ -942,7 +932,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
file_name = sys.argv[0]
|
||||
|
||||
if os.path.splitext(file_name)[1].lower() == ".xml":
|
||||
session = self.coreemu.create_session(master=False)
|
||||
session = self.coreemu.create_session()
|
||||
try:
|
||||
session.open_xml(file_name)
|
||||
except Exception:
|
||||
|
@ -1012,17 +1002,6 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
logging.debug("ignoring Register message")
|
||||
else:
|
||||
# register capabilities with the GUI
|
||||
self.master = True
|
||||
|
||||
# find the session containing this client and set the session to master
|
||||
for _id in self.coreemu.sessions:
|
||||
clients = self.session_clients.get(_id, [])
|
||||
if self in clients:
|
||||
session = self.coreemu.sessions[_id]
|
||||
logging.debug("setting session to master: %s", session.id)
|
||||
session.master = True
|
||||
break
|
||||
|
||||
replies.append(self.register())
|
||||
replies.append(self.session_message())
|
||||
|
||||
|
@ -1065,7 +1044,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
replies = self.handle_config_session(message_type, config_data)
|
||||
elif config_data.object == self.session.location.name:
|
||||
self.handle_config_location(message_type, config_data)
|
||||
elif config_data.object == self.session.metadata.name:
|
||||
elif config_data.object == "metadata":
|
||||
replies = self.handle_config_metadata(message_type, config_data)
|
||||
elif config_data.object == "broker":
|
||||
self.handle_config_broker(message_type, config_data)
|
||||
|
@ -1092,10 +1071,14 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
|
||||
if message_type == ConfigFlags.RESET:
|
||||
node_id = config_data.node
|
||||
self.session.location.reset()
|
||||
self.session.services.reset()
|
||||
if node_id is not None:
|
||||
self.session.mobility.config_reset(node_id)
|
||||
self.session.emane.config_reset(node_id)
|
||||
else:
|
||||
self.session.location.reset()
|
||||
self.session.services.reset()
|
||||
self.session.mobility.config_reset()
|
||||
self.session.emane.config_reset()
|
||||
else:
|
||||
raise Exception(f"cant handle config all: {message_type}")
|
||||
|
||||
|
@ -1147,7 +1130,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
replies = []
|
||||
if message_type == ConfigFlags.REQUEST:
|
||||
node_id = config_data.node
|
||||
metadata_configs = self.session.metadata.get_configs()
|
||||
metadata_configs = self.session.metadata
|
||||
if metadata_configs is None:
|
||||
metadata_configs = {}
|
||||
data_values = "|".join(
|
||||
|
@ -1157,7 +1140,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
config_response = ConfigData(
|
||||
message_type=0,
|
||||
node=node_id,
|
||||
object=self.session.metadata.name,
|
||||
object="metadata",
|
||||
type=ConfigFlags.NONE.value,
|
||||
data_types=data_types,
|
||||
data_values=data_values,
|
||||
|
@ -1167,7 +1150,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
values = ConfigShim.str_to_dict(config_data.data_values)
|
||||
for key in values:
|
||||
value = values[key]
|
||||
self.session.metadata.set_config(key, value)
|
||||
self.session.metadata[key] = value
|
||||
return replies
|
||||
|
||||
def handle_config_broker(self, message_type, config_data):
|
||||
|
@ -1437,11 +1420,6 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
config = ConfigShim.str_to_dict(values_str)
|
||||
self.session.emane.set_configs(config)
|
||||
|
||||
# extra logic to start slave Emane object after nemid has been configured from the master
|
||||
if message_type == ConfigFlags.UPDATE and self.session.master is False:
|
||||
# instantiation was previously delayed by setup returning Emane.NOT_READY
|
||||
self.session.instantiate()
|
||||
|
||||
return replies
|
||||
|
||||
def handle_config_emane_models(self, message_type, config_data):
|
||||
|
@ -1609,20 +1587,11 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
for _id in self.session.nodes:
|
||||
self.send_node_emulation_id(_id)
|
||||
elif event_type == EventTypes.RUNTIME_STATE:
|
||||
if self.session.master:
|
||||
logging.warning(
|
||||
"Unexpected event message: RUNTIME state received at session master"
|
||||
)
|
||||
else:
|
||||
# master event queue is started in session.checkruntime()
|
||||
self.session.start_events()
|
||||
logging.warning("Unexpected event message: RUNTIME state received")
|
||||
elif event_type == EventTypes.DATACOLLECT_STATE:
|
||||
self.session.data_collect()
|
||||
elif event_type == EventTypes.SHUTDOWN_STATE:
|
||||
if self.session.master:
|
||||
logging.warning(
|
||||
"Unexpected event message: SHUTDOWN state received at session master"
|
||||
)
|
||||
logging.warning("Unexpected event message: SHUTDOWN state received")
|
||||
elif event_type in {
|
||||
EventTypes.START,
|
||||
EventTypes.STOP,
|
||||
|
@ -1820,9 +1789,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
# set session to join
|
||||
self.session = session
|
||||
|
||||
# add client to session broker and set master if needed
|
||||
if self.master:
|
||||
self.session.master = True
|
||||
# add client to session broker
|
||||
clients = self.session_clients.setdefault(self.session.id, [])
|
||||
clients.append(self)
|
||||
|
||||
|
@ -1982,18 +1949,17 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
self.session.broadcast_config(config_data)
|
||||
|
||||
# send session metadata
|
||||
metadata_configs = self.session.metadata.get_configs()
|
||||
metadata_configs = self.session.metadata
|
||||
if metadata_configs:
|
||||
data_values = "|".join(
|
||||
[f"{x}={metadata_configs[x]}" for x in metadata_configs]
|
||||
)
|
||||
data_types = tuple(
|
||||
ConfigDataTypes.STRING.value
|
||||
for _ in self.session.metadata.get_configs()
|
||||
ConfigDataTypes.STRING.value for _ in self.session.metadata
|
||||
)
|
||||
config_data = ConfigData(
|
||||
message_type=0,
|
||||
object=self.session.metadata.name,
|
||||
object="metadata",
|
||||
type=ConfigFlags.NONE.value,
|
||||
data_types=data_types,
|
||||
data_values=data_values,
|
||||
|
@ -2018,7 +1984,6 @@ class CoreUdpHandler(CoreHandler):
|
|||
MessageTypes.EVENT.value: self.handle_event_message,
|
||||
MessageTypes.SESSION.value: self.handle_session_message,
|
||||
}
|
||||
self.master = False
|
||||
self.session = None
|
||||
self.coreemu = server.mainserver.coreemu
|
||||
socketserver.BaseRequestHandler.__init__(self, request, client_address, server)
|
||||
|
|
|
@ -24,7 +24,7 @@ def convert_node(node_data):
|
|||
(NodeTlvs.IP6_ADDRESS, node_data.ip6_address),
|
||||
(NodeTlvs.MODEL, node_data.model),
|
||||
(NodeTlvs.EMULATION_ID, node_data.emulation_id),
|
||||
(NodeTlvs.EMULATION_SERVER, node_data.emulation_server),
|
||||
(NodeTlvs.EMULATION_SERVER, node_data.server),
|
||||
(NodeTlvs.SESSION, node_data.session),
|
||||
(NodeTlvs.X_POSITION, node_data.x_position),
|
||||
(NodeTlvs.Y_POSITION, node_data.y_position),
|
||||
|
|
|
@ -8,7 +8,7 @@ from collections import OrderedDict
|
|||
from core.emulator.data import ConfigData
|
||||
|
||||
|
||||
class ConfigShim(object):
|
||||
class ConfigShim:
|
||||
"""
|
||||
Provides helper methods for converting newer configuration values into TLV compatible formats.
|
||||
"""
|
||||
|
@ -102,7 +102,7 @@ class ConfigShim(object):
|
|||
)
|
||||
|
||||
|
||||
class Configuration(object):
|
||||
class Configuration:
|
||||
"""
|
||||
Represents a configuration options.
|
||||
"""
|
||||
|
@ -131,7 +131,7 @@ class Configuration(object):
|
|||
return f"{self.__class__.__name__}(id={self.id}, type={self.type}, default={self.default}, options={self.options})"
|
||||
|
||||
|
||||
class ConfigurableManager(object):
|
||||
class ConfigurableManager:
|
||||
"""
|
||||
Provides convenience methods for storing and retrieving configuration options for nodes.
|
||||
"""
|
||||
|
@ -240,7 +240,7 @@ class ConfigurableManager(object):
|
|||
return self.node_configurations.get(node_id)
|
||||
|
||||
|
||||
class ConfigGroup(object):
|
||||
class ConfigGroup:
|
||||
"""
|
||||
Defines configuration group tabs used for display by ConfigurationOptions.
|
||||
"""
|
||||
|
@ -258,7 +258,7 @@ class ConfigGroup(object):
|
|||
self.stop = stop
|
||||
|
||||
|
||||
class ConfigurableOptions(object):
|
||||
class ConfigurableOptions:
|
||||
"""
|
||||
Provides a base for defining configuration options within CORE.
|
||||
"""
|
||||
|
@ -309,7 +309,7 @@ class ModelManager(ConfigurableManager):
|
|||
"""
|
||||
Creates a ModelManager object.
|
||||
"""
|
||||
super(ModelManager, self).__init__()
|
||||
super().__init__()
|
||||
self.models = {}
|
||||
self.node_models = {}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ class EmaneManager(ModelManager):
|
|||
:param core.session.Session session: session this manager is tied to
|
||||
:return: nothing
|
||||
"""
|
||||
super(EmaneManager, self).__init__()
|
||||
super().__init__()
|
||||
self.session = session
|
||||
self._emane_nets = {}
|
||||
self._emane_node_lock = threading.Lock()
|
||||
|
@ -128,7 +128,7 @@ class EmaneManager(ModelManager):
|
|||
return config
|
||||
|
||||
def config_reset(self, node_id=None):
|
||||
super(EmaneManager, self).config_reset(node_id)
|
||||
super().config_reset(node_id)
|
||||
self.set_configs(self.emane_config.default_values())
|
||||
|
||||
def emane_check(self):
|
||||
|
@ -269,12 +269,9 @@ class EmaneManager(ModelManager):
|
|||
|
||||
# control network bridge required for EMANE 0.9.2
|
||||
# - needs to exist when eventservice binds to it (initeventservice)
|
||||
if self.session.master:
|
||||
otadev = self.get_config("otamanagerdevice")
|
||||
netidx = self.session.get_control_net_index(otadev)
|
||||
logging.debug(
|
||||
"emane ota manager device: index(%s) otadev(%s)", netidx, otadev
|
||||
)
|
||||
logging.debug("emane ota manager device: index(%s) otadev(%s)", netidx, otadev)
|
||||
if netidx < 0:
|
||||
logging.error(
|
||||
"EMANE cannot start, check core config. invalid OTA device provided: %s",
|
||||
|
@ -376,7 +373,6 @@ class EmaneManager(ModelManager):
|
|||
with self._emane_node_lock:
|
||||
self._emane_nets.clear()
|
||||
|
||||
# don't clear self._ifccounts here; NEM counts are needed for buildxml
|
||||
self.platformport = self.session.options.get_config_int(
|
||||
"emane_platform_port", 8100
|
||||
)
|
||||
|
@ -585,7 +581,7 @@ class EmaneManager(ModelManager):
|
|||
args = f"{emanecmd} -f {log_file} {platform_xml}"
|
||||
output = node.cmd(args)
|
||||
logging.info("node(%s) emane daemon running: %s", node.name, args)
|
||||
logging.info("node(%s) emane daemon output: %s", node.name, output)
|
||||
logging.debug("node(%s) emane daemon output: %s", node.name, output)
|
||||
|
||||
if not run_emane_on_host:
|
||||
return
|
||||
|
@ -871,7 +867,7 @@ class EmaneGlobalModel(EmaneModel):
|
|||
]
|
||||
|
||||
def __init__(self, session, _id=None):
|
||||
super(EmaneGlobalModel, self).__init__(session, _id)
|
||||
super().__init__(session, _id)
|
||||
|
||||
def build_xml_files(self, config, interface=None):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -19,4 +19,4 @@ class EmaneIeee80211abgModel(emanemodel.EmaneModel):
|
|||
cls.mac_defaults["pcrcurveuri"] = os.path.join(
|
||||
emane_prefix, "share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml"
|
||||
)
|
||||
super(EmaneIeee80211abgModel, cls).load(emane_prefix)
|
||||
super().load(emane_prefix)
|
||||
|
|
|
@ -30,7 +30,7 @@ class EmaneNet(CoreNetworkBase):
|
|||
is_emane = True
|
||||
|
||||
def __init__(self, session, _id=None, name=None, start=True, server=None):
|
||||
super(EmaneNet, self).__init__(session, _id, name, start, server)
|
||||
super().__init__(session, _id, name, start, server)
|
||||
self.conf = ""
|
||||
self.up = False
|
||||
self.nemidmap = {}
|
||||
|
|
|
@ -19,4 +19,4 @@ class EmaneRfPipeModel(emanemodel.EmaneModel):
|
|||
cls.mac_defaults["pcrcurveuri"] = os.path.join(
|
||||
emane_prefix, "share/emane/xml/models/mac/rfpipe/rfpipepcr.xml"
|
||||
)
|
||||
super(EmaneRfPipeModel, cls).load(emane_prefix)
|
||||
super().load(emane_prefix)
|
||||
|
|
|
@ -32,7 +32,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
|
|||
emane_prefix,
|
||||
"share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml",
|
||||
)
|
||||
super(EmaneTdmaModel, cls).load(emane_prefix)
|
||||
super().load(emane_prefix)
|
||||
cls.mac_config.insert(
|
||||
0,
|
||||
Configuration(
|
||||
|
|
|
@ -29,7 +29,7 @@ signal.signal(signal.SIGUSR1, signal_handler)
|
|||
signal.signal(signal.SIGUSR2, signal_handler)
|
||||
|
||||
|
||||
class CoreEmu(object):
|
||||
class CoreEmu:
|
||||
"""
|
||||
Provides logic for creating and configuring CORE sessions and the nodes within them.
|
||||
"""
|
||||
|
@ -49,7 +49,7 @@ class CoreEmu(object):
|
|||
self.config = config
|
||||
|
||||
# session management
|
||||
self.session_id_gen = IdGen(_id=0)
|
||||
self.session_id_gen = IdGen()
|
||||
self.sessions = {}
|
||||
|
||||
# load services
|
||||
|
@ -79,18 +79,18 @@ class CoreEmu(object):
|
|||
:return: nothing
|
||||
"""
|
||||
logging.info("shutting down all sessions")
|
||||
self.session_id_gen.id = 0
|
||||
sessions = self.sessions.copy()
|
||||
self.sessions.clear()
|
||||
for _id in sessions:
|
||||
session = sessions[_id]
|
||||
session.shutdown()
|
||||
|
||||
def create_session(self, _id=None, master=True, _cls=Session):
|
||||
def create_session(self, _id=None, _cls=Session):
|
||||
"""
|
||||
Create a new CORE session, set to master if running standalone.
|
||||
Create a new CORE session.
|
||||
|
||||
:param int _id: session id for new session
|
||||
:param bool master: sets session to master
|
||||
:param class _cls: Session class to use
|
||||
:return: created session
|
||||
:rtype: EmuSession
|
||||
|
@ -103,9 +103,6 @@ class CoreEmu(object):
|
|||
|
||||
session = _cls(_id, config=self.config)
|
||||
logging.info("created session: %s", _id)
|
||||
if master:
|
||||
session.master = True
|
||||
|
||||
self.sessions[_id] = session
|
||||
return session
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ NodeData = collections.namedtuple(
|
|||
"ip6_address",
|
||||
"model",
|
||||
"emulation_id",
|
||||
"emulation_server",
|
||||
"server",
|
||||
"session",
|
||||
"x_position",
|
||||
"y_position",
|
||||
|
|
|
@ -21,7 +21,7 @@ LOCK = threading.Lock()
|
|||
CMD_HIDE = True
|
||||
|
||||
|
||||
class DistributedServer(object):
|
||||
class DistributedServer:
|
||||
"""
|
||||
Provides distributed server interactions.
|
||||
"""
|
||||
|
@ -101,7 +101,7 @@ class DistributedServer(object):
|
|||
os.unlink(temp.name)
|
||||
|
||||
|
||||
class DistributedController(object):
|
||||
class DistributedController:
|
||||
"""
|
||||
Provides logic for dealing with remote tunnels and distributed servers.
|
||||
"""
|
||||
|
|
|
@ -4,7 +4,7 @@ from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress
|
|||
from core.nodes.physical import PhysicalNode
|
||||
|
||||
|
||||
class IdGen(object):
|
||||
class IdGen:
|
||||
def __init__(self, _id=0):
|
||||
self.id = _id
|
||||
|
||||
|
@ -29,7 +29,7 @@ def create_interface(node, network, interface_data):
|
|||
ifindex=interface_data.id,
|
||||
ifname=interface_data.name,
|
||||
)
|
||||
return node.netif(interface_data.id, network)
|
||||
return node.netif(interface_data.id)
|
||||
|
||||
|
||||
def link_config(network, interface, link_options, devname=None, interface_two=None):
|
||||
|
@ -61,7 +61,7 @@ def link_config(network, interface, link_options, devname=None, interface_two=No
|
|||
network.linkconfig(**config)
|
||||
|
||||
|
||||
class NodeOptions(object):
|
||||
class NodeOptions:
|
||||
"""
|
||||
Options for creating and updating nodes within core.
|
||||
"""
|
||||
|
@ -87,7 +87,7 @@ class NodeOptions(object):
|
|||
self.lon = None
|
||||
self.alt = None
|
||||
self.emulation_id = None
|
||||
self.emulation_server = None
|
||||
self.server = None
|
||||
self.image = image
|
||||
|
||||
def set_position(self, x, y):
|
||||
|
@ -115,7 +115,7 @@ class NodeOptions(object):
|
|||
self.alt = alt
|
||||
|
||||
|
||||
class LinkOptions(object):
|
||||
class LinkOptions:
|
||||
"""
|
||||
Options for creating and updating links within core.
|
||||
"""
|
||||
|
@ -145,7 +145,7 @@ class LinkOptions(object):
|
|||
self.opaque = None
|
||||
|
||||
|
||||
class IpPrefixes(object):
|
||||
class IpPrefixes:
|
||||
"""
|
||||
Convenience class to help generate IP4 and IP6 addresses for nodes within CORE.
|
||||
"""
|
||||
|
@ -236,7 +236,7 @@ class IpPrefixes(object):
|
|||
)
|
||||
|
||||
|
||||
class InterfaceData(object):
|
||||
class InterfaceData:
|
||||
"""
|
||||
Convenience class for storing interface data.
|
||||
"""
|
||||
|
|
|
@ -73,18 +73,15 @@ class NodeTypes(Enum):
|
|||
|
||||
DEFAULT = 0
|
||||
PHYSICAL = 1
|
||||
TBD = 3
|
||||
SWITCH = 4
|
||||
HUB = 5
|
||||
WIRELESS_LAN = 6
|
||||
RJ45 = 7
|
||||
TUNNEL = 8
|
||||
KTUNNEL = 9
|
||||
EMANE = 10
|
||||
TAP_BRIDGE = 11
|
||||
PEER_TO_PEER = 12
|
||||
CONTROL_NET = 13
|
||||
EMANE_NET = 14
|
||||
DOCKER = 15
|
||||
LXC = 16
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import subprocess
|
|||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
from multiprocessing.pool import ThreadPool
|
||||
|
||||
from core import constants, utils
|
||||
from core.emane.emanemanager import EmaneManager
|
||||
|
@ -27,7 +26,7 @@ from core.emulator.emudata import (
|
|||
link_config,
|
||||
)
|
||||
from core.emulator.enumerations import EventTypes, ExceptionLevels, LinkTypes, NodeTypes
|
||||
from core.emulator.sessionconfig import SessionConfig, SessionMetaData
|
||||
from core.emulator.sessionconfig import SessionConfig
|
||||
from core.errors import CoreError
|
||||
from core.location.corelocation import CoreLocation
|
||||
from core.location.event import EventLoop
|
||||
|
@ -55,15 +54,12 @@ from core.xml.corexml import CoreXmlReader, CoreXmlWriter
|
|||
NODES = {
|
||||
NodeTypes.DEFAULT: CoreNode,
|
||||
NodeTypes.PHYSICAL: PhysicalNode,
|
||||
NodeTypes.TBD: None,
|
||||
NodeTypes.SWITCH: SwitchNode,
|
||||
NodeTypes.HUB: HubNode,
|
||||
NodeTypes.WIRELESS_LAN: WlanNode,
|
||||
NodeTypes.RJ45: Rj45Node,
|
||||
NodeTypes.TUNNEL: TunnelNode,
|
||||
NodeTypes.KTUNNEL: None,
|
||||
NodeTypes.EMANE: EmaneNet,
|
||||
NodeTypes.EMANE_NET: None,
|
||||
NodeTypes.TAP_BRIDGE: GreTapBridge,
|
||||
NodeTypes.PEER_TO_PEER: PtpNet,
|
||||
NodeTypes.CONTROL_NET: CtrlNet,
|
||||
|
@ -74,7 +70,7 @@ NODES_TYPE = {NODES[x]: x for x in NODES}
|
|||
CTRL_NET_ID = 9001
|
||||
|
||||
|
||||
class Session(object):
|
||||
class Session:
|
||||
"""
|
||||
CORE session manager.
|
||||
"""
|
||||
|
@ -88,7 +84,6 @@ class Session(object):
|
|||
:param bool mkdir: flag to determine if a directory should be made
|
||||
"""
|
||||
self.id = _id
|
||||
self.master = False
|
||||
|
||||
# define and create session directory when desired
|
||||
self.session_dir = os.path.join(tempfile.gettempdir(), f"pycore.{self.id}")
|
||||
|
@ -134,7 +129,7 @@ class Session(object):
|
|||
for key in config:
|
||||
value = config[key]
|
||||
self.options.set_config(key, value)
|
||||
self.metadata = SessionMetaData()
|
||||
self.metadata = {}
|
||||
|
||||
# distributed support and logic
|
||||
self.distributed = DistributedController(self)
|
||||
|
@ -243,7 +238,6 @@ class Session(object):
|
|||
)
|
||||
return node_one, node_two, net_one, net_two, tunnel
|
||||
|
||||
# TODO: this doesn't appear to ever be used, EMANE or basic wireless range
|
||||
def _link_wireless(self, objects, connect):
|
||||
"""
|
||||
Objects to deal with when connecting/disconnecting wireless links.
|
||||
|
@ -358,11 +352,7 @@ class Session(object):
|
|||
net_one.name,
|
||||
net_two.name,
|
||||
)
|
||||
if isinstance(net_two, Rj45Node):
|
||||
interface = net_two.linknet(net_one)
|
||||
else:
|
||||
interface = net_one.linknet(net_two)
|
||||
|
||||
link_config(net_one, interface, link_options)
|
||||
|
||||
if not link_options.unidirectional:
|
||||
|
@ -597,11 +587,11 @@ class Session(object):
|
|||
raise CoreError("modify link for unknown nodes")
|
||||
elif not node_one:
|
||||
# node1 = layer 2node, node2 = layer3 node
|
||||
interface = node_two.netif(interface_two_id, net_one)
|
||||
interface = node_two.netif(interface_two_id)
|
||||
link_config(net_one, interface, link_options)
|
||||
elif not node_two:
|
||||
# node2 = layer 2node, node1 = layer3 node
|
||||
interface = node_one.netif(interface_one_id, net_one)
|
||||
interface = node_one.netif(interface_one_id)
|
||||
link_config(net_one, interface, link_options)
|
||||
else:
|
||||
common_networks = node_one.commonnets(node_two)
|
||||
|
@ -634,13 +624,13 @@ class Session(object):
|
|||
if node_two:
|
||||
node_two.lock.release()
|
||||
|
||||
def add_node(self, _type=NodeTypes.DEFAULT, _id=None, node_options=None, _cls=None):
|
||||
def add_node(self, _type=NodeTypes.DEFAULT, _id=None, options=None, _cls=None):
|
||||
"""
|
||||
Add a node to the session, based on the provided node data.
|
||||
|
||||
:param core.emulator.enumerations.NodeTypes _type: type of node to create
|
||||
:param int _id: id for node, defaults to None for generated id
|
||||
:param core.emulator.emudata.NodeOptions node_options: data to create node with
|
||||
:param core.emulator.emudata.NodeOptions options: data to create node with
|
||||
:param class _cls: optional custom class to use for a created node
|
||||
:return: created node
|
||||
:raises core.CoreError: when an invalid node type is given
|
||||
|
@ -666,18 +656,16 @@ class Session(object):
|
|||
break
|
||||
|
||||
# generate name if not provided
|
||||
if not node_options:
|
||||
node_options = NodeOptions()
|
||||
name = node_options.name
|
||||
if not options:
|
||||
options = NodeOptions()
|
||||
name = options.name
|
||||
if not name:
|
||||
name = f"{node_class.__name__}{_id}"
|
||||
|
||||
# verify distributed server
|
||||
server = self.distributed.servers.get(node_options.emulation_server)
|
||||
if node_options.emulation_server is not None and server is None:
|
||||
raise CoreError(
|
||||
f"invalid distributed server: {node_options.emulation_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}")
|
||||
|
||||
# create node
|
||||
logging.info(
|
||||
|
@ -693,7 +681,7 @@ class Session(object):
|
|||
_id=_id,
|
||||
name=name,
|
||||
start=start,
|
||||
image=node_options.image,
|
||||
image=options.image,
|
||||
server=server,
|
||||
)
|
||||
else:
|
||||
|
@ -702,20 +690,20 @@ class Session(object):
|
|||
)
|
||||
|
||||
# set node attributes
|
||||
node.icon = node_options.icon
|
||||
node.canvas = node_options.canvas
|
||||
node.opaque = node_options.opaque
|
||||
node.icon = options.icon
|
||||
node.canvas = options.canvas
|
||||
node.opaque = options.opaque
|
||||
|
||||
# set node position and broadcast it
|
||||
self.set_node_position(node, node_options)
|
||||
self.set_node_position(node, options)
|
||||
|
||||
# add services to needed nodes
|
||||
if isinstance(node, (CoreNode, PhysicalNode, DockerNode, LxcNode)):
|
||||
node.type = node_options.model
|
||||
node.type = options.model
|
||||
logging.debug("set node type: %s", node.type)
|
||||
self.services.add_services(node, node.type, node_options.services)
|
||||
self.services.add_services(node, node.type, options.services)
|
||||
|
||||
# boot nodes if created after runtime, CoreNodes, Physical, and RJ45 are all nodes
|
||||
# boot nodes after runtime, CoreNodes, Physical, and RJ45 are all nodes
|
||||
is_boot_node = isinstance(node, CoreNodeBase) and not isinstance(node, Rj45Node)
|
||||
if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node:
|
||||
self.write_nodes()
|
||||
|
@ -724,12 +712,12 @@ class Session(object):
|
|||
|
||||
return node
|
||||
|
||||
def update_node(self, node_id, node_options):
|
||||
def edit_node(self, node_id, options):
|
||||
"""
|
||||
Update node information.
|
||||
Edit node information.
|
||||
|
||||
:param int node_id: id of node to update
|
||||
:param core.emulator.emudata.NodeOptions node_options: data to update node with
|
||||
:param core.emulator.emudata.NodeOptions options: data to update node with
|
||||
:return: True if node updated, False otherwise
|
||||
:rtype: bool
|
||||
:raises core.CoreError: when node to update does not exist
|
||||
|
@ -738,26 +726,26 @@ class Session(object):
|
|||
node = self.get_node(node_id)
|
||||
|
||||
# set node position and broadcast it
|
||||
self.set_node_position(node, node_options)
|
||||
self.set_node_position(node, options)
|
||||
|
||||
# update attributes
|
||||
node.canvas = node_options.canvas
|
||||
node.icon = node_options.icon
|
||||
node.canvas = options.canvas
|
||||
node.icon = options.icon
|
||||
|
||||
def set_node_position(self, node, node_options):
|
||||
def set_node_position(self, node, options):
|
||||
"""
|
||||
Set position for a node, use lat/lon/alt if needed.
|
||||
|
||||
:param node: node to set position for
|
||||
:param core.emulator.emudata.NodeOptions node_options: data for node
|
||||
:param core.emulator.emudata.NodeOptions options: data for node
|
||||
:return: nothing
|
||||
"""
|
||||
# extract location values
|
||||
x = node_options.x
|
||||
y = node_options.y
|
||||
lat = node_options.lat
|
||||
lon = node_options.lon
|
||||
alt = node_options.alt
|
||||
x = options.x
|
||||
y = options.y
|
||||
lat = options.lat
|
||||
lon = options.lon
|
||||
alt = options.alt
|
||||
|
||||
# check if we need to generate position from lat/lon/alt
|
||||
has_empty_position = all(i is None for i in [x, y])
|
||||
|
@ -886,10 +874,15 @@ class Session(object):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
self.emane.shutdown()
|
||||
self.delete_nodes()
|
||||
self.distributed.shutdown()
|
||||
self.del_hooks()
|
||||
self.emane.reset()
|
||||
self.emane.config_reset()
|
||||
self.location.reset()
|
||||
self.services.reset()
|
||||
self.mobility.config_reset()
|
||||
|
||||
def start_events(self):
|
||||
"""
|
||||
|
@ -908,49 +901,18 @@ class Session(object):
|
|||
"""
|
||||
self.mobility.handleevent(event_data)
|
||||
|
||||
def create_wireless_node(self, _id=None, node_options=None):
|
||||
def set_location(self, lat, lon, alt, scale):
|
||||
"""
|
||||
Create a wireless node for use within an wireless/EMANE networks.
|
||||
Set session geospatial location.
|
||||
|
||||
:param int _id: int for node, defaults to None and will be generated
|
||||
:param core.emulator.emudata.NodeOptions node_options: options for emane node, model will always be "mdr"
|
||||
:return: new emane node
|
||||
:rtype: core.nodes.network.WlanNode
|
||||
:param float lat: latitude
|
||||
:param float lon: longitude
|
||||
:param float alt: altitude
|
||||
:param float scale: reference scale
|
||||
:return: nothing
|
||||
"""
|
||||
if not node_options:
|
||||
node_options = NodeOptions()
|
||||
node_options.model = "mdr"
|
||||
return self.add_node(
|
||||
_type=NodeTypes.DEFAULT, _id=_id, node_options=node_options
|
||||
)
|
||||
|
||||
def create_emane_network(
|
||||
self,
|
||||
model,
|
||||
geo_reference,
|
||||
geo_scale=None,
|
||||
node_options=NodeOptions(),
|
||||
config=None,
|
||||
):
|
||||
"""
|
||||
Convenience method for creating an emane network.
|
||||
|
||||
:param model: emane model to use for emane network
|
||||
:param geo_reference: geo reference point to use for emane node locations
|
||||
:param geo_scale: geo scale to use for emane node locations, defaults to 1.0
|
||||
:param core.emulator.emudata.NodeOptions node_options: options for emane node being created
|
||||
:param dict config: emane model configuration
|
||||
:return: create emane network
|
||||
"""
|
||||
# required to be set for emane to function properly
|
||||
self.location.setrefgeo(*geo_reference)
|
||||
if geo_scale:
|
||||
self.location.refscale = geo_scale
|
||||
|
||||
# create and return network
|
||||
emane_network = self.add_node(_type=NodeTypes.EMANE, node_options=node_options)
|
||||
self.emane.set_model(emane_network, model, config)
|
||||
return emane_network
|
||||
self.location.setrefgeo(lat, lon, alt)
|
||||
self.location.refscale = scale
|
||||
|
||||
def shutdown(self):
|
||||
"""
|
||||
|
@ -960,13 +922,11 @@ class Session(object):
|
|||
self.set_state(EventTypes.DATACOLLECT_STATE, send_event=True)
|
||||
self.set_state(EventTypes.SHUTDOWN_STATE, send_event=True)
|
||||
|
||||
# shutdown/cleanup feature helpers
|
||||
self.emane.shutdown()
|
||||
self.sdt.shutdown()
|
||||
# clear out current core session
|
||||
self.clear()
|
||||
|
||||
# remove and shutdown all nodes and tunnels
|
||||
self.delete_nodes()
|
||||
self.distributed.shutdown()
|
||||
# shutdown sdt
|
||||
self.sdt.shutdown()
|
||||
|
||||
# remove this sessions working directory
|
||||
preserve = self.options.get_config("preservedir") == "1"
|
||||
|
@ -1389,26 +1349,28 @@ class Session(object):
|
|||
"""
|
||||
# delete node and check for session shutdown if a node was removed
|
||||
logging.info("deleting node(%s)", _id)
|
||||
result = False
|
||||
node = None
|
||||
with self._nodes_lock:
|
||||
if _id in self.nodes:
|
||||
node = self.nodes.pop(_id)
|
||||
node.shutdown()
|
||||
result = True
|
||||
|
||||
if result:
|
||||
if node:
|
||||
node.shutdown()
|
||||
self.check_shutdown()
|
||||
|
||||
return result
|
||||
return node is not None
|
||||
|
||||
def delete_nodes(self):
|
||||
"""
|
||||
Clear the nodes dictionary, and call shutdown for each node.
|
||||
"""
|
||||
with self._nodes_lock:
|
||||
funcs = []
|
||||
while self.nodes:
|
||||
_, node = self.nodes.popitem()
|
||||
node.shutdown()
|
||||
funcs.append((node.shutdown, [], {}))
|
||||
utils.threadpool(funcs)
|
||||
self.node_id_gen.id = 0
|
||||
|
||||
def write_nodes(self):
|
||||
"""
|
||||
|
@ -1547,11 +1509,13 @@ class Session(object):
|
|||
|
||||
# stop node services
|
||||
with self._nodes_lock:
|
||||
funcs = []
|
||||
for node_id in self.nodes:
|
||||
node = self.nodes[node_id]
|
||||
# TODO: determine if checking for CoreNode alone is ok
|
||||
if isinstance(node, CoreNodeBase):
|
||||
self.services.stop_services(node)
|
||||
args = (node,)
|
||||
funcs.append((self.services.stop_services, args, {}))
|
||||
utils.threadpool(funcs)
|
||||
|
||||
# shutdown emane
|
||||
self.emane.shutdown()
|
||||
|
@ -1559,7 +1523,8 @@ class Session(object):
|
|||
# update control interface hosts
|
||||
self.update_control_interface_hosts(remove=True)
|
||||
|
||||
# remove all four possible control networks. Does nothing if ctrlnet is not installed.
|
||||
# remove all four possible control networks. Does nothing if ctrlnet is not
|
||||
# installed.
|
||||
self.add_remove_control_interface(node=None, net_index=0, remove=True)
|
||||
self.add_remove_control_interface(node=None, net_index=1, remove=True)
|
||||
self.add_remove_control_interface(node=None, net_index=2, remove=True)
|
||||
|
@ -1590,6 +1555,18 @@ class Session(object):
|
|||
ssid = (self.id >> 8) ^ (self.id & ((1 << 8) - 1))
|
||||
return f"{ssid:x}"
|
||||
|
||||
def boot_node(self, node):
|
||||
"""
|
||||
Boot node by adding a control interface when necessary and starting
|
||||
node services.
|
||||
|
||||
:param core.nodes.base.CoreNodeBase node: node to boot
|
||||
:return: nothing
|
||||
"""
|
||||
logging.info("booting node(%s): %s", node.name, [x.name for x in node.services])
|
||||
self.add_remove_control_interface(node=node, remove=False)
|
||||
self.services.boot_services(node)
|
||||
|
||||
def boot_nodes(self):
|
||||
"""
|
||||
Invoke the boot() procedure for all nodes and send back node
|
||||
|
@ -1597,29 +1574,18 @@ class Session(object):
|
|||
request flag.
|
||||
"""
|
||||
with self._nodes_lock:
|
||||
pool = ThreadPool()
|
||||
results = []
|
||||
|
||||
start = time.time()
|
||||
funcs = []
|
||||
start = time.monotonic()
|
||||
for _id in self.nodes:
|
||||
node = self.nodes[_id]
|
||||
if isinstance(node, CoreNodeBase) and not isinstance(node, Rj45Node):
|
||||
# add a control interface if configured
|
||||
logging.info(
|
||||
"booting node(%s): %s",
|
||||
node.name,
|
||||
[x.name for x in node.services],
|
||||
)
|
||||
self.add_remove_control_interface(node=node, remove=False)
|
||||
result = pool.apply_async(self.services.boot_services, (node,))
|
||||
results.append(result)
|
||||
|
||||
pool.close()
|
||||
pool.join()
|
||||
for result in results:
|
||||
result.get()
|
||||
logging.debug("boot run time: %s", time.time() - start)
|
||||
|
||||
args = (node,)
|
||||
funcs.append((self.boot_node, args, {}))
|
||||
results, exceptions = utils.threadpool(funcs)
|
||||
total = time.monotonic() - start
|
||||
logging.debug("boot run time: %s", total)
|
||||
if exceptions:
|
||||
raise CoreError(exceptions)
|
||||
self.update_control_interface_hosts()
|
||||
|
||||
def get_control_net_prefixes(self):
|
||||
|
@ -1732,28 +1698,19 @@ class Session(object):
|
|||
prefixes = prefix_spec.split()
|
||||
if len(prefixes) > 1:
|
||||
# a list of per-host prefixes is provided
|
||||
assign_address = True
|
||||
if self.master:
|
||||
try:
|
||||
# split first (master) entry into server and prefix
|
||||
prefix = prefixes[0].split(":", 1)[1]
|
||||
except IndexError:
|
||||
# no server name. possibly only one server
|
||||
prefix = prefixes[0]
|
||||
|
||||
# len(prefixes) == 1
|
||||
else:
|
||||
# TODO: can we get the server name from the servers.conf or from the node
|
||||
# assignments?o
|
||||
# with one prefix, only master gets a ctrlnet address
|
||||
assign_address = self.master
|
||||
prefix = prefixes[0]
|
||||
|
||||
logging.info(
|
||||
"controlnet(%s) prefix(%s) assign(%s) updown(%s) serverintf(%s)",
|
||||
"controlnet(%s) prefix(%s) updown(%s) serverintf(%s)",
|
||||
_id,
|
||||
prefix,
|
||||
assign_address,
|
||||
updown_script,
|
||||
server_interface,
|
||||
)
|
||||
|
@ -1761,7 +1718,7 @@ class Session(object):
|
|||
cls=CtrlNet,
|
||||
_id=_id,
|
||||
prefix=prefix,
|
||||
assign_address=assign_address,
|
||||
assign_address=True,
|
||||
updown_script=updown_script,
|
||||
serverintf=server_interface,
|
||||
)
|
||||
|
@ -1778,7 +1735,7 @@ class Session(object):
|
|||
If conf_reqd is False, the control network may be built even
|
||||
when the user has not configured one (e.g. for EMANE.)
|
||||
|
||||
:param core.nodes.base.CoreNode node: node to add or remove control interface
|
||||
:param core.nodes.base.CoreNodeBase node: node to add or remove control interface
|
||||
:param int net_index: network index
|
||||
:param bool remove: flag to check if it should be removed
|
||||
:param bool conf_required: flag to check if conf is required
|
||||
|
|
|
@ -61,7 +61,7 @@ class SessionConfig(ConfigurableManager, ConfigurableOptions):
|
|||
config_type = RegisterTlvs.UTILITY.value
|
||||
|
||||
def __init__(self):
|
||||
super(SessionConfig, self).__init__()
|
||||
super().__init__()
|
||||
self.set_configs(self.default_values())
|
||||
|
||||
def get_config(
|
||||
|
@ -71,9 +71,7 @@ class SessionConfig(ConfigurableManager, ConfigurableOptions):
|
|||
config_type=ConfigurableManager._default_type,
|
||||
default=None,
|
||||
):
|
||||
value = super(SessionConfig, self).get_config(
|
||||
_id, node_id, config_type, default
|
||||
)
|
||||
value = super().get_config(_id, node_id, config_type, default)
|
||||
if value == "":
|
||||
value = default
|
||||
return value
|
||||
|
@ -89,14 +87,3 @@ class SessionConfig(ConfigurableManager, ConfigurableOptions):
|
|||
if value is not None:
|
||||
value = int(value)
|
||||
return value
|
||||
|
||||
|
||||
class SessionMetaData(ConfigurableManager):
|
||||
"""
|
||||
Metadata is simply stored in a configs[] dict. Key=value pairs are
|
||||
passed in from configure messages destined to the "metadata" object.
|
||||
The data is not otherwise interpreted or processed.
|
||||
"""
|
||||
|
||||
name = "metadata"
|
||||
config_type = RegisterTlvs.UTILITY.value
|
||||
|
|
|
@ -11,7 +11,7 @@ from core.emulator.enumerations import RegisterTlvs
|
|||
from core.location import utm
|
||||
|
||||
|
||||
class CoreLocation(object):
|
||||
class CoreLocation:
|
||||
"""
|
||||
Member of session class for handling global location data. This keeps
|
||||
track of a latitude/longitude/altitude reference point and scale in
|
||||
|
|
|
@ -23,7 +23,7 @@ class Timer(threading.Thread):
|
|||
:param args: function arguments
|
||||
:param kwargs: function keyword arguments
|
||||
"""
|
||||
super(Timer, self).__init__()
|
||||
super().__init__()
|
||||
self.interval = interval
|
||||
self.function = function
|
||||
|
||||
|
@ -70,7 +70,7 @@ class Timer(threading.Thread):
|
|||
|
||||
|
||||
@total_ordering
|
||||
class Event(object):
|
||||
class Event:
|
||||
"""
|
||||
Provides event objects that can be used within the EventLoop class.
|
||||
"""
|
||||
|
@ -118,7 +118,7 @@ class Event(object):
|
|||
self.canceled = True
|
||||
|
||||
|
||||
class EventLoop(object):
|
||||
class EventLoop:
|
||||
"""
|
||||
Provides an event loop for running events.
|
||||
"""
|
||||
|
|
|
@ -38,7 +38,7 @@ class MobilityManager(ModelManager):
|
|||
|
||||
:param core.emulator.session.Session session: session this manager is tied to
|
||||
"""
|
||||
super(MobilityManager, self).__init__()
|
||||
super().__init__()
|
||||
self.session = session
|
||||
self.models[BasicRangeModel.name] = BasicRangeModel
|
||||
self.models[Ns2ScriptedMobility.name] = Ns2ScriptedMobility
|
||||
|
@ -302,7 +302,7 @@ class BasicRangeModel(WirelessModel):
|
|||
:param core.session.Session session: related core session
|
||||
:param int _id: object id
|
||||
"""
|
||||
super(BasicRangeModel, self).__init__(session=session, _id=_id)
|
||||
super().__init__(session, _id)
|
||||
self.session = session
|
||||
self.wlan = session.get_node(_id)
|
||||
self._netifs = {}
|
||||
|
@ -535,7 +535,7 @@ class BasicRangeModel(WirelessModel):
|
|||
|
||||
|
||||
@total_ordering
|
||||
class WayPoint(object):
|
||||
class WayPoint:
|
||||
"""
|
||||
Maintains information regarding waypoints.
|
||||
"""
|
||||
|
@ -587,8 +587,7 @@ class WayPointMobility(WirelessModel):
|
|||
:param int _id: object id
|
||||
:return:
|
||||
"""
|
||||
super(WayPointMobility, self).__init__(session=session, _id=_id)
|
||||
|
||||
super().__init__(session=session, _id=_id)
|
||||
self.state = self.STATE_STOPPED
|
||||
self.queue = []
|
||||
self.queue_copy = []
|
||||
|
@ -945,7 +944,7 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
:param core.emulator.session.Session session: CORE session instance
|
||||
:param int _id: object id
|
||||
"""
|
||||
super(Ns2ScriptedMobility, self).__init__(session=session, _id=_id)
|
||||
super().__init__(session, _id)
|
||||
self._netifs = {}
|
||||
self._netifslock = threading.Lock()
|
||||
|
||||
|
@ -1137,7 +1136,7 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
"""
|
||||
logging.info("starting script")
|
||||
laststate = self.state
|
||||
super(Ns2ScriptedMobility, self).start()
|
||||
super().start()
|
||||
if laststate == self.STATE_PAUSED:
|
||||
self.statescript("unpause")
|
||||
|
||||
|
@ -1147,7 +1146,7 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
super(Ns2ScriptedMobility, self).run()
|
||||
super().run()
|
||||
self.statescript("run")
|
||||
|
||||
def pause(self):
|
||||
|
@ -1156,7 +1155,7 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
super(Ns2ScriptedMobility, self).pause()
|
||||
super().pause()
|
||||
self.statescript("pause")
|
||||
|
||||
def stop(self, move_initial=True):
|
||||
|
@ -1166,7 +1165,7 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
:param bool move_initial: flag to check if we should move node to initial position
|
||||
:return: nothing
|
||||
"""
|
||||
super(Ns2ScriptedMobility, self).stop(move_initial=move_initial)
|
||||
super().stop(move_initial=move_initial)
|
||||
self.statescript("stop")
|
||||
|
||||
def statescript(self, typestr):
|
||||
|
|
|
@ -21,7 +21,7 @@ from core.nodes.netclient import get_net_client
|
|||
_DEFAULT_MTU = 1500
|
||||
|
||||
|
||||
class NodeBase(object):
|
||||
class NodeBase:
|
||||
"""
|
||||
Base class for CORE nodes (nodes and networks)
|
||||
"""
|
||||
|
@ -139,7 +139,7 @@ class NodeBase(object):
|
|||
if sort:
|
||||
return [self._netif[x] for x in sorted(self._netif)]
|
||||
else:
|
||||
return self._netif.values()
|
||||
return list(self._netif.values())
|
||||
|
||||
def numnetif(self):
|
||||
"""
|
||||
|
@ -158,11 +158,9 @@ class NodeBase(object):
|
|||
:return: interface index if found, -1 otherwise
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
for ifindex in self._netif:
|
||||
if self._netif[ifindex] is netif:
|
||||
return ifindex
|
||||
|
||||
return -1
|
||||
|
||||
def newifindex(self):
|
||||
|
@ -194,9 +192,9 @@ class NodeBase(object):
|
|||
|
||||
x, y, _ = self.getposition()
|
||||
model = self.type
|
||||
emulation_server = None
|
||||
server = None
|
||||
if self.server is not None:
|
||||
emulation_server = self.server.name
|
||||
server = self.server.name
|
||||
|
||||
services = self.services
|
||||
if services is not None:
|
||||
|
@ -217,7 +215,7 @@ class NodeBase(object):
|
|||
longitude=lon,
|
||||
altitude=alt,
|
||||
model=model,
|
||||
emulation_server=emulation_server,
|
||||
server=server,
|
||||
services=services,
|
||||
)
|
||||
|
||||
|
@ -252,7 +250,7 @@ class CoreNodeBase(NodeBase):
|
|||
:param core.emulator.distributed.DistributedServer server: remote server node
|
||||
will run on, default is None for localhost
|
||||
"""
|
||||
super(CoreNodeBase, self).__init__(session, _id, name, start, server)
|
||||
super().__init__(session, _id, name, start, server)
|
||||
self.services = []
|
||||
self.nodedir = None
|
||||
self.tmpnodedir = False
|
||||
|
@ -294,7 +292,6 @@ class CoreNodeBase(NodeBase):
|
|||
if ifindex in self._netif:
|
||||
raise ValueError(f"ifindex {ifindex} already exists")
|
||||
self._netif[ifindex] = netif
|
||||
# TODO: this should have probably been set ahead, seems bad to me, check for failure and fix
|
||||
netif.netindex = ifindex
|
||||
|
||||
def delnetif(self, ifindex):
|
||||
|
@ -310,13 +307,11 @@ class CoreNodeBase(NodeBase):
|
|||
netif.shutdown()
|
||||
del netif
|
||||
|
||||
# TODO: net parameter is not used, remove
|
||||
def netif(self, ifindex, net=None):
|
||||
def netif(self, ifindex):
|
||||
"""
|
||||
Retrieve network interface.
|
||||
|
||||
:param int ifindex: index of interface to retrieve
|
||||
:param core.nodes.interface.CoreInterface net: network node
|
||||
:return: network interface, or None if not found
|
||||
:rtype: core.nodes.interface.CoreInterface
|
||||
"""
|
||||
|
@ -357,7 +352,7 @@ class CoreNodeBase(NodeBase):
|
|||
:param z: z position
|
||||
:return: nothing
|
||||
"""
|
||||
changed = super(CoreNodeBase, self).setposition(x, y, z)
|
||||
changed = super().setposition(x, y, z)
|
||||
if changed:
|
||||
for netif in self.netifs(sort=True):
|
||||
netif.setposition(x, y, z)
|
||||
|
@ -435,7 +430,7 @@ class CoreNode(CoreNodeBase):
|
|||
:param core.emulator.distributed.DistributedServer server: remote server node
|
||||
will run on, default is None for localhost
|
||||
"""
|
||||
super(CoreNode, self).__init__(session, _id, name, start, server)
|
||||
super().__init__(session, _id, name, start, server)
|
||||
self.nodedir = nodedir
|
||||
self.ctrlchnlname = os.path.abspath(
|
||||
os.path.join(self.session.session_dir, self.name)
|
||||
|
@ -632,15 +627,14 @@ class CoreNode(CoreNodeBase):
|
|||
:rtype: int
|
||||
"""
|
||||
with self.lock:
|
||||
return super(CoreNode, self).newifindex()
|
||||
return super().newifindex()
|
||||
|
||||
def newveth(self, ifindex=None, ifname=None, net=None):
|
||||
def newveth(self, ifindex=None, ifname=None):
|
||||
"""
|
||||
Create a new interface.
|
||||
|
||||
:param int ifindex: index for the new interface
|
||||
:param str ifname: name for the new interface
|
||||
:param core.nodes.base.CoreNetworkBase net: network to associate interface with
|
||||
:return: nothing
|
||||
"""
|
||||
with self.lock:
|
||||
|
@ -692,13 +686,12 @@ class CoreNode(CoreNodeBase):
|
|||
|
||||
return ifindex
|
||||
|
||||
def newtuntap(self, ifindex=None, ifname=None, net=None):
|
||||
def newtuntap(self, ifindex=None, ifname=None):
|
||||
"""
|
||||
Create a new tunnel tap.
|
||||
|
||||
:param int ifindex: interface index
|
||||
:param str ifname: interface name
|
||||
:param net: network to associate with
|
||||
:return: interface index
|
||||
:rtype: int
|
||||
"""
|
||||
|
@ -803,7 +796,7 @@ class CoreNode(CoreNodeBase):
|
|||
with self.lock:
|
||||
# TODO: emane specific code
|
||||
if net.is_emane is True:
|
||||
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
|
||||
ifindex = self.newtuntap(ifindex, ifname)
|
||||
# TUN/TAP is not ready for addressing yet; the device may
|
||||
# take some time to appear, and installing it into a
|
||||
# namespace after it has been bound removes addressing;
|
||||
|
@ -815,7 +808,7 @@ class CoreNode(CoreNodeBase):
|
|||
netif.addaddr(address)
|
||||
return ifindex
|
||||
else:
|
||||
ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net)
|
||||
ifindex = self.newveth(ifindex, ifname)
|
||||
|
||||
if net is not None:
|
||||
self.attachnet(ifindex, net)
|
||||
|
@ -930,7 +923,7 @@ class CoreNetworkBase(NodeBase):
|
|||
:param core.emulator.distributed.DistributedServer server: remote server node
|
||||
will run on, default is None for localhost
|
||||
"""
|
||||
super(CoreNetworkBase, self).__init__(session, _id, name, start, server)
|
||||
super().__init__(session, _id, name, start, server)
|
||||
self._linked = {}
|
||||
self._linked_lock = threading.Lock()
|
||||
|
||||
|
@ -1072,7 +1065,7 @@ class CoreNetworkBase(NodeBase):
|
|||
return all_links
|
||||
|
||||
|
||||
class Position(object):
|
||||
class Position:
|
||||
"""
|
||||
Helper class for Cartesian coordinate position
|
||||
"""
|
||||
|
|
|
@ -8,7 +8,7 @@ from core import utils
|
|||
from core.constants import VCMD_BIN
|
||||
|
||||
|
||||
class VnodeClient(object):
|
||||
class VnodeClient:
|
||||
"""
|
||||
Provides client functionality for interacting with a virtual node.
|
||||
"""
|
||||
|
|
|
@ -10,7 +10,7 @@ from core.nodes.base import CoreNode
|
|||
from core.nodes.netclient import get_net_client
|
||||
|
||||
|
||||
class DockerClient(object):
|
||||
class DockerClient:
|
||||
def __init__(self, name, image, run):
|
||||
self.name = name
|
||||
self.image = image
|
||||
|
@ -96,9 +96,7 @@ class DockerNode(CoreNode):
|
|||
if image is None:
|
||||
image = "ubuntu"
|
||||
self.image = image
|
||||
super(DockerNode, self).__init__(
|
||||
session, _id, name, nodedir, bootsh, start, server
|
||||
)
|
||||
super().__init__(session, _id, name, nodedir, bootsh, start, server)
|
||||
|
||||
def create_node_net_client(self, use_ovs):
|
||||
"""
|
||||
|
|
|
@ -10,7 +10,7 @@ from core.errors import CoreCommandError
|
|||
from core.nodes.netclient import get_net_client
|
||||
|
||||
|
||||
class CoreInterface(object):
|
||||
class CoreInterface:
|
||||
"""
|
||||
Base class for network interfaces.
|
||||
"""
|
||||
|
@ -40,8 +40,10 @@ class CoreInterface(object):
|
|||
self.poshook = lambda a, b, c, d: None
|
||||
# used with EMANE
|
||||
self.transport_type = None
|
||||
# interface index on the network
|
||||
# node interface index
|
||||
self.netindex = None
|
||||
# net interface index
|
||||
self.netifi = None
|
||||
# index used to find flow data
|
||||
self.flow_id = None
|
||||
self.server = server
|
||||
|
@ -230,7 +232,7 @@ class Veth(CoreInterface):
|
|||
:raises CoreCommandError: when there is a command exception
|
||||
"""
|
||||
# note that net arg is ignored
|
||||
CoreInterface.__init__(self, session, node, name, mtu, server)
|
||||
super().__init__(session, node, name, mtu, server)
|
||||
self.localname = localname
|
||||
self.up = False
|
||||
if start:
|
||||
|
@ -291,7 +293,7 @@ class TunTap(CoreInterface):
|
|||
will run on, default is None for localhost
|
||||
:param bool start: start flag
|
||||
"""
|
||||
CoreInterface.__init__(self, session, node, name, mtu, server)
|
||||
super().__init__(session, node, name, mtu, server)
|
||||
self.localname = localname
|
||||
self.up = False
|
||||
self.transport_type = "virtual"
|
||||
|
@ -474,7 +476,7 @@ class GreTap(CoreInterface):
|
|||
will run on, default is None for localhost
|
||||
:raises CoreCommandError: when there is a command exception
|
||||
"""
|
||||
CoreInterface.__init__(self, session, node, name, mtu, server)
|
||||
super().__init__(session, node, name, mtu, server)
|
||||
if _id is None:
|
||||
# from PyCoreObj
|
||||
_id = ((id(self) >> 16) ^ (id(self) & 0xFFFF)) & 0xFFFF
|
||||
|
|
|
@ -9,7 +9,7 @@ import struct
|
|||
from socket import AF_INET, AF_INET6
|
||||
|
||||
|
||||
class MacAddress(object):
|
||||
class MacAddress:
|
||||
"""
|
||||
Provides mac address utilities for use within core.
|
||||
"""
|
||||
|
@ -77,7 +77,7 @@ class MacAddress(object):
|
|||
return cls(tmpbytes[2:])
|
||||
|
||||
|
||||
class IpAddress(object):
|
||||
class IpAddress:
|
||||
"""
|
||||
Provides ip utilities and functionality for use within core.
|
||||
"""
|
||||
|
@ -202,7 +202,7 @@ class IpAddress(object):
|
|||
return struct.unpack("!I", value)[0]
|
||||
|
||||
|
||||
class IpPrefix(object):
|
||||
class IpPrefix:
|
||||
"""
|
||||
Provides ip address generation and prefix utilities.
|
||||
"""
|
||||
|
@ -401,7 +401,7 @@ class Ipv4Prefix(IpPrefix):
|
|||
|
||||
:param str prefixstr: ip prefix
|
||||
"""
|
||||
IpPrefix.__init__(self, AF_INET, prefixstr)
|
||||
super().__init__(AF_INET, prefixstr)
|
||||
|
||||
|
||||
class Ipv6Prefix(IpPrefix):
|
||||
|
@ -415,7 +415,7 @@ class Ipv6Prefix(IpPrefix):
|
|||
|
||||
:param str prefixstr: ip prefix
|
||||
"""
|
||||
IpPrefix.__init__(self, AF_INET6, prefixstr)
|
||||
super().__init__(AF_INET6, prefixstr)
|
||||
|
||||
|
||||
def is_ip_address(af, addrstr):
|
||||
|
|
|
@ -10,7 +10,7 @@ from core.errors import CoreCommandError
|
|||
from core.nodes.base import CoreNode
|
||||
|
||||
|
||||
class LxdClient(object):
|
||||
class LxdClient:
|
||||
def __init__(self, name, image, run):
|
||||
self.name = name
|
||||
self.image = image
|
||||
|
@ -89,9 +89,7 @@ class LxcNode(CoreNode):
|
|||
if image is None:
|
||||
image = "ubuntu"
|
||||
self.image = image
|
||||
super(LxcNode, self).__init__(
|
||||
session, _id, name, nodedir, bootsh, start, server
|
||||
)
|
||||
super().__init__(session, _id, name, nodedir, bootsh, start, server)
|
||||
|
||||
def alive(self):
|
||||
"""
|
||||
|
@ -217,6 +215,6 @@ class LxcNode(CoreNode):
|
|||
self.cmd(f"chmod {mode:o} {filename}")
|
||||
|
||||
def addnetif(self, netif, ifindex):
|
||||
super(LxcNode, self).addnetif(netif, ifindex)
|
||||
super().addnetif(netif, ifindex)
|
||||
# adding small delay to allow time for adding addresses to work correctly
|
||||
time.sleep(0.5)
|
||||
|
|
|
@ -19,7 +19,7 @@ def get_net_client(use_ovs, run):
|
|||
return LinuxNetClient(run)
|
||||
|
||||
|
||||
class LinuxNetClient(object):
|
||||
class LinuxNetClient:
|
||||
"""
|
||||
Client for creating Linux bridges and ip interfaces for nodes.
|
||||
"""
|
||||
|
|
|
@ -21,7 +21,7 @@ from core.nodes.netclient import get_net_client
|
|||
ebtables_lock = threading.Lock()
|
||||
|
||||
|
||||
class EbtablesQueue(object):
|
||||
class EbtablesQueue:
|
||||
"""
|
||||
Helper class for queuing up ebtables commands into rate-limited
|
||||
atomic commits. This improves performance and reliability when there are
|
||||
|
@ -257,7 +257,7 @@ class CoreNetwork(CoreNetworkBase):
|
|||
will run on, default is None for localhost
|
||||
:param policy: network policy
|
||||
"""
|
||||
CoreNetworkBase.__init__(self, session, _id, name, start, server)
|
||||
super().__init__(session, _id, name, start, server)
|
||||
if name is None:
|
||||
name = str(self.id)
|
||||
if policy is not None:
|
||||
|
@ -337,8 +337,6 @@ class CoreNetwork(CoreNetworkBase):
|
|||
del self.session
|
||||
self.up = False
|
||||
|
||||
# TODO: this depends on a subtype with localname defined, seems like the
|
||||
# wrong place for this to live
|
||||
def attach(self, netif):
|
||||
"""
|
||||
Attach a network interface.
|
||||
|
@ -348,8 +346,7 @@ class CoreNetwork(CoreNetworkBase):
|
|||
"""
|
||||
if self.up:
|
||||
netif.net_client.create_interface(self.brname, netif.localname)
|
||||
|
||||
CoreNetworkBase.attach(self, netif)
|
||||
super().attach(netif)
|
||||
|
||||
def detach(self, netif):
|
||||
"""
|
||||
|
@ -360,8 +357,7 @@ class CoreNetwork(CoreNetworkBase):
|
|||
"""
|
||||
if self.up:
|
||||
netif.net_client.delete_interface(self.brname, netif.localname)
|
||||
|
||||
CoreNetworkBase.detach(self, netif)
|
||||
super().detach(netif)
|
||||
|
||||
def linked(self, netif1, netif2):
|
||||
"""
|
||||
|
@ -654,7 +650,7 @@ class GreTapBridge(CoreNetwork):
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
CoreNetwork.startup(self)
|
||||
super().startup()
|
||||
if self.gretap:
|
||||
self.attach(self.gretap)
|
||||
|
||||
|
@ -668,7 +664,7 @@ class GreTapBridge(CoreNetwork):
|
|||
self.detach(self.gretap)
|
||||
self.gretap.shutdown()
|
||||
self.gretap = None
|
||||
CoreNetwork.shutdown(self)
|
||||
super().shutdown()
|
||||
|
||||
def addrconfig(self, addrlist):
|
||||
"""
|
||||
|
@ -755,7 +751,7 @@ class CtrlNet(CoreNetwork):
|
|||
self.assign_address = assign_address
|
||||
self.updown_script = updown_script
|
||||
self.serverintf = serverintf
|
||||
CoreNetwork.__init__(self, session, _id, name, start, server)
|
||||
super().__init__(session, _id, name, start, server)
|
||||
|
||||
def add_addresses(self, address):
|
||||
"""
|
||||
|
@ -786,8 +782,7 @@ class CtrlNet(CoreNetwork):
|
|||
if self.net_client.existing_bridges(self.id):
|
||||
raise CoreError(f"old bridges exist for node: {self.id}")
|
||||
|
||||
CoreNetwork.startup(self)
|
||||
|
||||
super().startup()
|
||||
logging.info("added control network bridge: %s %s", self.brname, self.prefix)
|
||||
|
||||
if self.hostid and self.assign_address:
|
||||
|
@ -835,7 +830,7 @@ class CtrlNet(CoreNetwork):
|
|||
except CoreCommandError:
|
||||
logging.exception("error issuing shutdown script shutdown")
|
||||
|
||||
CoreNetwork.shutdown(self)
|
||||
super().shutdown()
|
||||
|
||||
def all_link_data(self, flags):
|
||||
"""
|
||||
|
@ -866,8 +861,7 @@ class PtpNet(CoreNetwork):
|
|||
raise ValueError(
|
||||
"Point-to-point links support at most 2 network interfaces"
|
||||
)
|
||||
|
||||
CoreNetwork.attach(self, netif)
|
||||
super().attach(netif)
|
||||
|
||||
def data(self, message_type, lat=None, lon=None, alt=None):
|
||||
"""
|
||||
|
@ -1007,22 +1001,13 @@ class HubNode(CoreNetwork):
|
|||
policy = "ACCEPT"
|
||||
type = "hub"
|
||||
|
||||
def __init__(self, session, _id=None, name=None, start=True, server=None):
|
||||
def startup(self):
|
||||
"""
|
||||
Creates a HubNode instance.
|
||||
Startup for a hub node, that disables mac learning after normal startup.
|
||||
|
||||
:param core.session.Session session: core session instance
|
||||
:param int _id: node id
|
||||
:param str name: node namee
|
||||
:param bool start: start flag
|
||||
:param core.emulator.distributed.DistributedServer server: remote server node
|
||||
will run on, default is None for localhost
|
||||
:raises CoreCommandError: when there is a command exception
|
||||
:return: nothing
|
||||
"""
|
||||
CoreNetwork.__init__(self, session, _id, name, start, server)
|
||||
|
||||
# TODO: move to startup method
|
||||
if start:
|
||||
super().startup()
|
||||
self.net_client.disable_mac_learning(self.brname)
|
||||
|
||||
|
||||
|
@ -1050,24 +1035,28 @@ class WlanNode(CoreNetwork):
|
|||
will run on, default is None for localhost
|
||||
:param policy: wlan policy
|
||||
"""
|
||||
CoreNetwork.__init__(self, session, _id, name, start, server, policy)
|
||||
# wireless model such as basic range
|
||||
super().__init__(session, _id, name, start, server, policy)
|
||||
# wireless and mobility models (BasicRangeModel, Ns2WaypointMobility)
|
||||
self.model = None
|
||||
# mobility model such as scripted
|
||||
self.mobility = None
|
||||
|
||||
# TODO: move to startup method
|
||||
if start:
|
||||
def startup(self):
|
||||
"""
|
||||
Startup for a wlan node, that disables mac learning after normal startup.
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
super().startup()
|
||||
self.net_client.disable_mac_learning(self.brname)
|
||||
|
||||
def attach(self, netif):
|
||||
"""
|
||||
Attach a network interface.
|
||||
|
||||
:param core.nodes.interface.CoreInterface netif: network interface
|
||||
:param core.nodes.interface.Veth netif: network interface
|
||||
:return: nothing
|
||||
"""
|
||||
CoreNetwork.attach(self, netif)
|
||||
super().attach(netif)
|
||||
if self.model:
|
||||
netif.poshook = self.model.position_callback
|
||||
if netif.node is None:
|
||||
|
@ -1099,12 +1088,12 @@ class WlanNode(CoreNetwork):
|
|||
|
||||
def update_mobility(self, config):
|
||||
if not self.mobility:
|
||||
raise ValueError("no mobility set to update for node(%s)", self.id)
|
||||
raise ValueError(f"no mobility set to update for node({self.id})")
|
||||
self.mobility.update_config(config)
|
||||
|
||||
def updatemodel(self, config):
|
||||
if not self.model:
|
||||
raise ValueError("no model set to update for node(%s)", self.id)
|
||||
raise ValueError(f"no model set to update for node({self.id})")
|
||||
logging.debug(
|
||||
"node(%s) updating model(%s): %s", self.id, self.model.name, config
|
||||
)
|
||||
|
@ -1122,11 +1111,9 @@ class WlanNode(CoreNetwork):
|
|||
:return: list of link data
|
||||
:rtype: list[core.emulator.data.LinkData]
|
||||
"""
|
||||
all_links = CoreNetwork.all_link_data(self, flags)
|
||||
|
||||
all_links = super().all_link_data(flags)
|
||||
if self.model:
|
||||
all_links.extend(self.model.all_link_data(flags))
|
||||
|
||||
return all_links
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ class PhysicalNode(CoreNodeBase):
|
|||
def __init__(
|
||||
self, session, _id=None, name=None, nodedir=None, start=True, server=None
|
||||
):
|
||||
CoreNodeBase.__init__(self, session, _id, name, start, server)
|
||||
super().__init__(session, _id, name, start, server)
|
||||
if not self.server:
|
||||
raise CoreError("physical nodes must be assigned to a remote server")
|
||||
self.nodedir = nodedir
|
||||
|
|
|
@ -24,7 +24,7 @@ from core.nodes.network import WlanNode
|
|||
|
||||
|
||||
# TODO: A named tuple may be more appropriate, than abusing a class dict like this
|
||||
class Bunch(object):
|
||||
class Bunch:
|
||||
"""
|
||||
Helper class for recording a collection of attributes.
|
||||
"""
|
||||
|
@ -38,7 +38,7 @@ class Bunch(object):
|
|||
self.__dict__.update(kwargs)
|
||||
|
||||
|
||||
class Sdt(object):
|
||||
class Sdt:
|
||||
"""
|
||||
Helper class for exporting session objects to NRL"s SDT3D.
|
||||
The connect() method initializes the display, and can be invoked
|
||||
|
|
|
@ -10,7 +10,6 @@ services.
|
|||
import enum
|
||||
import logging
|
||||
import time
|
||||
from multiprocessing.pool import ThreadPool
|
||||
|
||||
from core import utils
|
||||
from core.constants import which
|
||||
|
@ -29,7 +28,7 @@ class ServiceMode(enum.Enum):
|
|||
TIMER = 2
|
||||
|
||||
|
||||
class ServiceDependencies(object):
|
||||
class ServiceDependencies:
|
||||
"""
|
||||
Can generate boot paths for services, based on their dependencies. Will validate
|
||||
that all services will be booted and that all dependencies exist within the services provided.
|
||||
|
@ -127,7 +126,7 @@ class ServiceDependencies(object):
|
|||
return self.path
|
||||
|
||||
|
||||
class ServiceShim(object):
|
||||
class ServiceShim:
|
||||
keys = [
|
||||
"dirs",
|
||||
"files",
|
||||
|
@ -235,7 +234,7 @@ class ServiceShim(object):
|
|||
return servicesstring[1].split(",")
|
||||
|
||||
|
||||
class ServiceManager(object):
|
||||
class ServiceManager:
|
||||
"""
|
||||
Manages services available for CORE nodes to use.
|
||||
"""
|
||||
|
@ -306,7 +305,7 @@ class ServiceManager(object):
|
|||
return service_errors
|
||||
|
||||
|
||||
class CoreServices(object):
|
||||
class CoreServices:
|
||||
"""
|
||||
Class for interacting with a list of available startup services for
|
||||
nodes. Mostly used to convert a CoreService into a Config API
|
||||
|
@ -462,18 +461,14 @@ class CoreServices(object):
|
|||
:param core.netns.vnode.LxcNode node: node to start services on
|
||||
:return: nothing
|
||||
"""
|
||||
pool = ThreadPool()
|
||||
results = []
|
||||
|
||||
funcs = []
|
||||
boot_paths = ServiceDependencies(node.services).boot_paths()
|
||||
for boot_path in boot_paths:
|
||||
result = pool.apply_async(self._start_boot_paths, (node, boot_path))
|
||||
results.append(result)
|
||||
|
||||
pool.close()
|
||||
pool.join()
|
||||
for result in results:
|
||||
result.get()
|
||||
args = (node, boot_path)
|
||||
funcs.append((self._start_boot_paths, args, {}))
|
||||
result, exceptions = utils.threadpool(funcs)
|
||||
if exceptions:
|
||||
raise ServiceBootError(exceptions)
|
||||
|
||||
def _start_boot_paths(self, node, boot_path):
|
||||
"""
|
||||
|
@ -791,7 +786,7 @@ class CoreServices(object):
|
|||
node.nodefile(file_name, cfg)
|
||||
|
||||
|
||||
class CoreService(object):
|
||||
class CoreService:
|
||||
"""
|
||||
Parent class used for defining services.
|
||||
"""
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
Miscellaneous utility functions, wrappers around some subprocess procedures.
|
||||
"""
|
||||
|
||||
import concurrent.futures
|
||||
import fcntl
|
||||
import hashlib
|
||||
import importlib
|
||||
|
@ -223,34 +224,6 @@ def cmd(args, env=None, cwd=None, wait=True, shell=False):
|
|||
raise CoreCommandError(-1, args)
|
||||
|
||||
|
||||
def hex_dump(s, bytes_per_word=2, words_per_line=8):
|
||||
"""
|
||||
Hex dump of a string.
|
||||
|
||||
:param str s: string to hex dump
|
||||
:param bytes_per_word: number of bytes per word
|
||||
:param words_per_line: number of words per line
|
||||
:return: hex dump of string
|
||||
"""
|
||||
dump = ""
|
||||
count = 0
|
||||
total_bytes = bytes_per_word * words_per_line
|
||||
|
||||
while s:
|
||||
line = s[:total_bytes]
|
||||
s = s[total_bytes:]
|
||||
tmp = map(
|
||||
lambda x: (f"{bytes_per_word:02x}" * bytes_per_word) % x,
|
||||
zip(*[iter(map(ord, line))] * bytes_per_word),
|
||||
)
|
||||
if len(line) % 2:
|
||||
tmp.append(f"{ord(line[-1]):x}")
|
||||
tmp = " ".join(tmp)
|
||||
dump += f"0x{count:08x}: {tmp}\n"
|
||||
count += len(line)
|
||||
return dump[:-1]
|
||||
|
||||
|
||||
def file_munge(pathname, header, text):
|
||||
"""
|
||||
Insert text at the end of a file, surrounded by header comments.
|
||||
|
@ -409,3 +382,29 @@ def load_logging_config(config_path):
|
|||
with open(config_path, "r") as log_config_file:
|
||||
log_config = json.load(log_config_file)
|
||||
logging.config.dictConfig(log_config)
|
||||
|
||||
|
||||
def threadpool(funcs, workers=10):
|
||||
"""
|
||||
Run provided functions, arguments, and keywords within a threadpool
|
||||
collecting results and exceptions.
|
||||
|
||||
:param iter funcs: iterable that provides a func, args, kwargs
|
||||
:param int workers: number of workers for the threadpool
|
||||
:return: results and exceptions from running functions with args and kwargs
|
||||
:rtype: tuple
|
||||
"""
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as executor:
|
||||
futures = []
|
||||
for func, args, kwargs in funcs:
|
||||
future = executor.submit(func, *args, **kwargs)
|
||||
futures.append(future)
|
||||
results = []
|
||||
exceptions = []
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
try:
|
||||
result = future.result()
|
||||
results.append(result)
|
||||
except Exception as e:
|
||||
exceptions.append(e)
|
||||
return results, exceptions
|
||||
|
|
|
@ -104,7 +104,7 @@ def add_configuration(parent, name, value):
|
|||
add_attribute(config_element, "value", value)
|
||||
|
||||
|
||||
class NodeElement(object):
|
||||
class NodeElement:
|
||||
def __init__(self, session, node, element_name):
|
||||
self.session = session
|
||||
self.node = node
|
||||
|
@ -131,7 +131,7 @@ class NodeElement(object):
|
|||
add_attribute(position, "alt", alt)
|
||||
|
||||
|
||||
class ServiceElement(object):
|
||||
class ServiceElement:
|
||||
def __init__(self, service):
|
||||
self.service = service
|
||||
self.element = etree.Element("service")
|
||||
|
@ -197,7 +197,7 @@ class ServiceElement(object):
|
|||
|
||||
class DeviceElement(NodeElement):
|
||||
def __init__(self, session, node):
|
||||
super(DeviceElement, self).__init__(session, node, "device")
|
||||
super().__init__(session, node, "device")
|
||||
add_attribute(self.element, "type", node.type)
|
||||
self.add_services()
|
||||
|
||||
|
@ -212,7 +212,7 @@ class DeviceElement(NodeElement):
|
|||
|
||||
class NetworkElement(NodeElement):
|
||||
def __init__(self, session, node):
|
||||
super(NetworkElement, self).__init__(session, node, "network")
|
||||
super().__init__(session, node, "network")
|
||||
model = getattr(self.node, "model", None)
|
||||
if model:
|
||||
add_attribute(self.element, "model", model.name)
|
||||
|
@ -232,7 +232,7 @@ class NetworkElement(NodeElement):
|
|||
add_attribute(self.element, "type", node_type)
|
||||
|
||||
|
||||
class CoreXmlWriter(object):
|
||||
class CoreXmlWriter:
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
self.scenario = etree.Element("scenario")
|
||||
|
@ -313,13 +313,13 @@ class CoreXmlWriter(object):
|
|||
def write_session_metadata(self):
|
||||
# metadata
|
||||
metadata_elements = etree.Element("session_metadata")
|
||||
config = self.session.metadata.get_configs()
|
||||
config = self.session.metadata
|
||||
if not config:
|
||||
return
|
||||
|
||||
for _id in config:
|
||||
value = config[_id]
|
||||
add_configuration(metadata_elements, _id, value)
|
||||
for key in config:
|
||||
value = config[key]
|
||||
add_configuration(metadata_elements, key, value)
|
||||
|
||||
if metadata_elements.getchildren():
|
||||
self.scenario.append(metadata_elements)
|
||||
|
@ -527,7 +527,7 @@ class CoreXmlWriter(object):
|
|||
return link_element
|
||||
|
||||
|
||||
class CoreXmlReader(object):
|
||||
class CoreXmlReader:
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
self.scenario = None
|
||||
|
@ -574,7 +574,7 @@ class CoreXmlReader(object):
|
|||
value = data.get("value")
|
||||
configs[name] = value
|
||||
logging.info("reading session metadata: %s", configs)
|
||||
self.session.metadata.set_configs(configs)
|
||||
self.session.metadata = configs
|
||||
|
||||
def read_session_options(self):
|
||||
session_options = self.scenario.find("session_options")
|
||||
|
@ -737,53 +737,51 @@ class CoreXmlReader(object):
|
|||
node_id = get_int(device_element, "id")
|
||||
name = device_element.get("name")
|
||||
model = device_element.get("type")
|
||||
node_options = NodeOptions(name, model)
|
||||
options = NodeOptions(name, model)
|
||||
|
||||
service_elements = device_element.find("services")
|
||||
if service_elements is not None:
|
||||
node_options.services = [
|
||||
x.get("name") for x in service_elements.iterchildren()
|
||||
]
|
||||
options.services = [x.get("name") for x in service_elements.iterchildren()]
|
||||
|
||||
position_element = device_element.find("position")
|
||||
if position_element is not None:
|
||||
x = get_int(position_element, "x")
|
||||
y = get_int(position_element, "y")
|
||||
if all([x, y]):
|
||||
node_options.set_position(x, y)
|
||||
options.set_position(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]):
|
||||
node_options.set_location(lat, lon, alt)
|
||||
options.set_location(lat, lon, alt)
|
||||
|
||||
logging.info("reading node id(%s) model(%s) name(%s)", node_id, model, name)
|
||||
self.session.add_node(_id=node_id, node_options=node_options)
|
||||
self.session.add_node(_id=node_id, options=options)
|
||||
|
||||
def read_network(self, network_element):
|
||||
node_id = get_int(network_element, "id")
|
||||
name = network_element.get("name")
|
||||
node_type = NodeTypes[network_element.get("type")]
|
||||
node_options = NodeOptions(name)
|
||||
options = NodeOptions(name)
|
||||
|
||||
position_element = network_element.find("position")
|
||||
if position_element is not None:
|
||||
x = get_int(position_element, "x")
|
||||
y = get_int(position_element, "y")
|
||||
if all([x, y]):
|
||||
node_options.set_position(x, y)
|
||||
options.set_position(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]):
|
||||
node_options.set_location(lat, lon, alt)
|
||||
options.set_location(lat, lon, alt)
|
||||
|
||||
logging.info(
|
||||
"reading node id(%s) node_type(%s) name(%s)", node_id, node_type, name
|
||||
)
|
||||
self.session.add_node(_type=node_type, _id=node_id, node_options=node_options)
|
||||
self.session.add_node(_type=node_type, _id=node_id, options=options)
|
||||
|
||||
def read_links(self):
|
||||
link_elements = self.scenario.find("links")
|
||||
|
|
|
@ -84,7 +84,7 @@ def get_ipv4_addresses(hostname):
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
class CoreXmlDeployment(object):
|
||||
class CoreXmlDeployment:
|
||||
def __init__(self, session, scenario):
|
||||
self.session = session
|
||||
self.scenario = scenario
|
||||
|
|
|
@ -15,7 +15,7 @@ if __name__ == "__main__":
|
|||
options = NodeOptions(model=None, image="ubuntu")
|
||||
|
||||
# create node one
|
||||
node_one = session.add_node(_type=NodeTypes.DOCKER, node_options=options)
|
||||
node_one = session.add_node(_type=NodeTypes.DOCKER, options=options)
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
||||
# create node two
|
||||
|
|
|
@ -17,11 +17,11 @@ if __name__ == "__main__":
|
|||
options = NodeOptions(model=None, image="ubuntu")
|
||||
|
||||
# create node one
|
||||
node_one = session.add_node(_type=NodeTypes.DOCKER, node_options=options)
|
||||
node_one = session.add_node(_type=NodeTypes.DOCKER, options=options)
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
||||
# create node two
|
||||
node_two = session.add_node(_type=NodeTypes.DOCKER, node_options=options)
|
||||
node_two = session.add_node(_type=NodeTypes.DOCKER, options=options)
|
||||
interface_two = prefixes.create_interface(node_two)
|
||||
|
||||
# add link
|
||||
|
|
|
@ -19,11 +19,11 @@ if __name__ == "__main__":
|
|||
switch = session.add_node(_type=NodeTypes.SWITCH)
|
||||
|
||||
# node one
|
||||
node_one = session.add_node(_type=NodeTypes.DOCKER, node_options=options)
|
||||
node_one = session.add_node(_type=NodeTypes.DOCKER, options=options)
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
||||
# node two
|
||||
node_two = session.add_node(_type=NodeTypes.DOCKER, node_options=options)
|
||||
node_two = session.add_node(_type=NodeTypes.DOCKER, options=options)
|
||||
interface_two = prefixes.create_interface(node_two)
|
||||
|
||||
# node three
|
||||
|
|
54
daemon/examples/grpc/large.py
Normal file
54
daemon/examples/grpc/large.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
import logging
|
||||
|
||||
from core.api.grpc import client, core_pb2
|
||||
|
||||
|
||||
def log_event(event):
|
||||
logging.info("event: %s", event)
|
||||
|
||||
|
||||
def main():
|
||||
core = client.CoreGrpcClient()
|
||||
|
||||
with core.context_connect():
|
||||
# create session
|
||||
response = core.create_session()
|
||||
session_id = response.session_id
|
||||
logging.info("created session: %s", response)
|
||||
|
||||
# create nodes for session
|
||||
nodes = []
|
||||
position = core_pb2.Position(x=50, y=100)
|
||||
switch = core_pb2.Node(id=1, type=core_pb2.NodeType.SWITCH, position=position)
|
||||
nodes.append(switch)
|
||||
for i in range(2, 50):
|
||||
position = core_pb2.Position(x=50 + 50 * i, y=50)
|
||||
node = core_pb2.Node(id=i, position=position, model="PC")
|
||||
nodes.append(node)
|
||||
|
||||
# create links
|
||||
interface_helper = client.InterfaceHelper(ip4_prefix="10.83.0.0/16")
|
||||
links = []
|
||||
for node in nodes:
|
||||
interface_one = interface_helper.create_interface(node.id, 0)
|
||||
link = core_pb2.Link(
|
||||
type=core_pb2.LinkType.WIRED,
|
||||
node_one_id=node.id,
|
||||
node_two_id=switch.id,
|
||||
interface_one=interface_one,
|
||||
)
|
||||
links.append(link)
|
||||
|
||||
# start session
|
||||
response = core.start_session(session_id, nodes, links)
|
||||
logging.info("started session: %s", response)
|
||||
|
||||
input("press enter to shutdown session")
|
||||
|
||||
response = core.stop_session(session_id)
|
||||
logging.info("stop sessionL %s", response)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
main()
|
|
@ -15,7 +15,7 @@ if __name__ == "__main__":
|
|||
options = NodeOptions(image="ubuntu")
|
||||
|
||||
# create node one
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, options=options)
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
||||
# create node two
|
||||
|
|
|
@ -17,11 +17,11 @@ if __name__ == "__main__":
|
|||
options = NodeOptions(image="ubuntu:18.04")
|
||||
|
||||
# create node one
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, options=options)
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
||||
# create node two
|
||||
node_two = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
node_two = session.add_node(_type=NodeTypes.LXC, options=options)
|
||||
interface_two = prefixes.create_interface(node_two)
|
||||
|
||||
# add link
|
||||
|
|
|
@ -19,11 +19,11 @@ if __name__ == "__main__":
|
|||
switch = session.add_node(_type=NodeTypes.SWITCH)
|
||||
|
||||
# node one
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, options=options)
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
||||
# node two
|
||||
node_two = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
node_two = session.add_node(_type=NodeTypes.LXC, options=options)
|
||||
interface_two = prefixes.create_interface(node_two)
|
||||
|
||||
# node three
|
||||
|
|
|
@ -31,11 +31,11 @@ def main(args):
|
|||
# create local node, switch, and remote nodes
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
node_one = session.add_node(node_options=options)
|
||||
node_one = session.add_node(options=options)
|
||||
emane_net = session.add_node(_type=NodeTypes.EMANE)
|
||||
session.emane.set_model(emane_net, EmaneIeee80211abgModel)
|
||||
options.emulation_server = server_name
|
||||
node_two = session.add_node(node_options=options)
|
||||
options.server = server_name
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
# create node interfaces and link
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
|
|
@ -23,9 +23,9 @@ def main(args):
|
|||
|
||||
# create local node, switch, and remote nodes
|
||||
options = NodeOptions(image="ubuntu:18.04")
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
options.emulation_server = server_name
|
||||
node_two = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, options=options)
|
||||
options.server = server_name
|
||||
node_two = session.add_node(_type=NodeTypes.LXC, options=options)
|
||||
|
||||
# create node interfaces and link
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
|
|
@ -23,9 +23,9 @@ def main(args):
|
|||
|
||||
# create local node, switch, and remote nodes
|
||||
options = NodeOptions()
|
||||
node_one = session.add_node(node_options=options)
|
||||
options.emulation_server = server_name
|
||||
node_two = session.add_node(node_options=options)
|
||||
node_one = session.add_node(options=options)
|
||||
options.server = server_name
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
# create node interfaces and link
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
|
|
@ -27,8 +27,8 @@ def main(args):
|
|||
node_one = session.add_node()
|
||||
switch = session.add_node(_type=NodeTypes.SWITCH)
|
||||
options = NodeOptions()
|
||||
options.emulation_server = server_name
|
||||
node_two = session.add_node(node_options=options)
|
||||
options.server = server_name
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
# create node interfaces and link
|
||||
interface_one = prefixes.create_interface(node_one)
|
||||
|
|
|
@ -4,11 +4,11 @@ import parser
|
|||
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.emudata import IpPrefixes
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.emulator.emudata import IpPrefixes, NodeOptions
|
||||
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||
|
||||
|
||||
def example(options):
|
||||
def example(args):
|
||||
# ip generator for example
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
|
||||
|
@ -20,14 +20,16 @@ def example(options):
|
|||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
|
||||
# create emane network node
|
||||
emane_network = session.create_emane_network(
|
||||
model=EmaneIeee80211abgModel, geo_reference=(47.57917, -122.13232, 2.00000)
|
||||
)
|
||||
emane_network.setposition(x=80, y=50)
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions()
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(_type=NodeTypes.EMANE, options=options)
|
||||
session.emane.set_model(emane_network, EmaneIeee80211abgModel)
|
||||
|
||||
# create nodes
|
||||
for i in range(options.nodes):
|
||||
node = session.create_wireless_node()
|
||||
options = NodeOptions(model="mdr")
|
||||
for i in range(args.nodes):
|
||||
node = session.add_node(options=options)
|
||||
node.setposition(x=150 * (i + 1), y=150)
|
||||
interface = prefixes.create_interface(node)
|
||||
session.add_link(node.id, emane_network.id, interface_one=interface)
|
||||
|
@ -42,12 +44,12 @@ def example(options):
|
|||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
options = parser.parse_options("emane80211")
|
||||
args = parser.parse("emane80211")
|
||||
start = datetime.datetime.now()
|
||||
logging.info(
|
||||
"running emane 80211 example: nodes(%s) time(%s)", options.nodes, options.time
|
||||
"running emane 80211 example: nodes(%s) time(%s)", args.nodes, args.time
|
||||
)
|
||||
example(options)
|
||||
example(args)
|
||||
logging.info("elapsed time: %s", datetime.datetime.now() - start)
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ DEFAULT_TIME = 10
|
|||
DEFAULT_STEP = 1
|
||||
|
||||
|
||||
def parse_options(name):
|
||||
def parse(name):
|
||||
parser = argparse.ArgumentParser(description=f"Run {name} example")
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
|
@ -22,11 +22,11 @@ def parse_options(name):
|
|||
help="example iperf run time in seconds",
|
||||
)
|
||||
|
||||
options = parser.parse_args()
|
||||
args = parser.parse_args()
|
||||
|
||||
if options.nodes < 2:
|
||||
parser.error(f"invalid min number of nodes: {options.nodes}")
|
||||
if options.time < 1:
|
||||
parser.error(f"invalid test time: {options.time}")
|
||||
if args.nodes < 2:
|
||||
parser.error(f"invalid min number of nodes: {args.nodes}")
|
||||
if args.time < 1:
|
||||
parser.error(f"invalid test time: {args.time}")
|
||||
|
||||
return options
|
||||
return args
|
||||
|
|
|
@ -7,7 +7,7 @@ from core.emulator.emudata import IpPrefixes
|
|||
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||
|
||||
|
||||
def example(options):
|
||||
def example(args):
|
||||
# ip generator for example
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
|
||||
|
@ -22,7 +22,7 @@ def example(options):
|
|||
switch = session.add_node(_type=NodeTypes.SWITCH)
|
||||
|
||||
# create nodes
|
||||
for _ in range(options.nodes):
|
||||
for _ in range(args.nodes):
|
||||
node = session.add_node()
|
||||
interface = prefixes.create_interface(node)
|
||||
session.add_link(node.id, switch.id, interface_one=interface)
|
||||
|
@ -32,13 +32,13 @@ def example(options):
|
|||
|
||||
# get nodes to run example
|
||||
first_node = session.get_node(2)
|
||||
last_node = session.get_node(options.nodes + 1)
|
||||
last_node = session.get_node(args.nodes + 1)
|
||||
|
||||
logging.info("starting iperf server on node: %s", first_node.name)
|
||||
first_node.cmd("iperf -s -D")
|
||||
first_node_address = prefixes.ip4_address(first_node)
|
||||
logging.info("node %s connecting to %s", last_node.name, first_node_address)
|
||||
output = last_node.cmd(f"iperf -t {options.time} -c {first_node_address}")
|
||||
output = last_node.cmd(f"iperf -t {args.time} -c {first_node_address}")
|
||||
logging.info(output)
|
||||
first_node.cmd("killall -9 iperf")
|
||||
|
||||
|
@ -48,12 +48,10 @@ def example(options):
|
|||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
options = parser.parse_options("switch")
|
||||
args = parser.parse("switch")
|
||||
start = datetime.datetime.now()
|
||||
logging.info(
|
||||
"running switch example: nodes(%s) time(%s)", options.nodes, options.time
|
||||
)
|
||||
example(options)
|
||||
logging.info("running switch example: nodes(%s) time(%s)", args.nodes, args.time)
|
||||
example(args)
|
||||
logging.info("elapsed time: %s", datetime.datetime.now() - start)
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ from core.emulator.enumerations import EventTypes, NodeTypes
|
|||
from core.location.mobility import BasicRangeModel
|
||||
|
||||
|
||||
def example(options):
|
||||
def example(args):
|
||||
# ip generator for example
|
||||
prefixes = IpPrefixes("10.83.0.0/16")
|
||||
|
||||
|
@ -24,10 +24,10 @@ def example(options):
|
|||
session.mobility.set_model(wlan, BasicRangeModel)
|
||||
|
||||
# create nodes, must set a position for wlan basic range model
|
||||
node_options = NodeOptions()
|
||||
node_options.set_position(0, 0)
|
||||
for _ in range(options.nodes):
|
||||
node = session.add_node(node_options=node_options)
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
for _ in range(args.nodes):
|
||||
node = session.add_node(options=options)
|
||||
interface = prefixes.create_interface(node)
|
||||
session.add_link(node.id, wlan.id, interface_one=interface)
|
||||
|
||||
|
@ -36,13 +36,14 @@ def example(options):
|
|||
|
||||
# get nodes for example run
|
||||
first_node = session.get_node(2)
|
||||
last_node = session.get_node(options.nodes + 1)
|
||||
last_node = session.get_node(args.nodes + 1)
|
||||
|
||||
logging.info("starting iperf server on node: %s", first_node.name)
|
||||
first_node.cmd("iperf -s -D")
|
||||
address = prefixes.ip4_address(first_node)
|
||||
logging.info("node %s connecting to %s", last_node.name, address)
|
||||
last_node.cmd(f"iperf -t {options.time} -c {address}")
|
||||
output = last_node.cmd(f"iperf -t {args.time} -c {address}")
|
||||
logging.info(output)
|
||||
first_node.cmd("killall -9 iperf")
|
||||
|
||||
# shutdown session
|
||||
|
@ -51,13 +52,11 @@ def example(options):
|
|||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
options = parser.parse_options("wlan")
|
||||
args = parser.parse("wlan")
|
||||
|
||||
start = datetime.datetime.now()
|
||||
logging.info(
|
||||
"running wlan example: nodes(%s) time(%s)", options.nodes, options.time
|
||||
)
|
||||
example(options)
|
||||
logging.info("running wlan example: nodes(%s) time(%s)", args.nodes, args.time)
|
||||
example(args)
|
||||
logging.info("elapsed time: %s", datetime.datetime.now() - start)
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@ option java_outer_classname = "CoreProto";
|
|||
|
||||
service CoreApi {
|
||||
// session rpc
|
||||
rpc StartSession (StartSessionRequest) returns (StartSessionResponse) {
|
||||
}
|
||||
rpc StopSession (StopSessionRequest) returns (StopSessionResponse) {
|
||||
}
|
||||
rpc CreateSession (CreateSessionRequest) returns (CreateSessionResponse) {
|
||||
}
|
||||
rpc DeleteSession (DeleteSessionRequest) returns (DeleteSessionResponse) {
|
||||
|
@ -19,6 +23,10 @@ service CoreApi {
|
|||
}
|
||||
rpc SetSessionOptions (SetSessionOptionsRequest) returns (SetSessionOptionsResponse) {
|
||||
}
|
||||
rpc SetSessionMetadata (SetSessionMetadataRequest) returns (SetSessionMetadataResponse) {
|
||||
}
|
||||
rpc GetSessionMetadata (GetSessionMetadataRequest) returns (GetSessionMetadataResponse) {
|
||||
}
|
||||
rpc GetSessionLocation (GetSessionLocationRequest) returns (GetSessionLocationResponse) {
|
||||
}
|
||||
rpc SetSessionLocation (SetSessionLocationRequest) returns (SetSessionLocationResponse) {
|
||||
|
@ -126,6 +134,30 @@ service CoreApi {
|
|||
}
|
||||
|
||||
// rpc request/response messages
|
||||
message StartSessionRequest {
|
||||
int32 session_id = 1;
|
||||
repeated Node nodes = 2;
|
||||
repeated Link links = 3;
|
||||
repeated Hook hooks = 4;
|
||||
SessionLocation location = 5;
|
||||
map<string, string> emane_config = 6;
|
||||
repeated WlanConfig wlan_configs = 7;
|
||||
repeated EmaneModelConfig emane_model_configs = 8;
|
||||
repeated MobilityConfig mobility_configs = 9;
|
||||
}
|
||||
|
||||
message StartSessionResponse {
|
||||
bool result = 1;
|
||||
}
|
||||
|
||||
message StopSessionRequest {
|
||||
int32 session_id = 1;
|
||||
}
|
||||
|
||||
message StopSessionResponse {
|
||||
bool result = 1;
|
||||
}
|
||||
|
||||
message CreateSessionRequest {
|
||||
int32 session_id = 1;
|
||||
}
|
||||
|
@ -175,19 +207,34 @@ message SetSessionOptionsResponse {
|
|||
bool result = 1;
|
||||
}
|
||||
|
||||
message SetSessionMetadataRequest {
|
||||
int32 session_id = 1;
|
||||
map<string, string> config = 2;
|
||||
}
|
||||
|
||||
message SetSessionMetadataResponse {
|
||||
bool result = 1;
|
||||
}
|
||||
|
||||
message GetSessionMetadataRequest {
|
||||
int32 session_id = 1;
|
||||
}
|
||||
|
||||
message GetSessionMetadataResponse {
|
||||
map<string, string> config = 1;
|
||||
}
|
||||
|
||||
message GetSessionLocationRequest {
|
||||
int32 session_id = 1;
|
||||
}
|
||||
|
||||
message GetSessionLocationResponse {
|
||||
SessionPosition position = 1;
|
||||
float scale = 2;
|
||||
SessionLocation location = 1;
|
||||
}
|
||||
|
||||
message SetSessionLocationRequest {
|
||||
int32 session_id = 1;
|
||||
SessionPosition position = 2;
|
||||
float scale = 3;
|
||||
SessionLocation location = 2;
|
||||
}
|
||||
|
||||
message SetSessionLocationResponse {
|
||||
|
@ -442,8 +489,7 @@ message GetMobilityConfigResponse {
|
|||
|
||||
message SetMobilityConfigRequest {
|
||||
int32 session_id = 1;
|
||||
int32 node_id = 2;
|
||||
map<string, string> config = 3;
|
||||
MobilityConfig mobility_config = 2;
|
||||
}
|
||||
|
||||
message SetMobilityConfigResponse {
|
||||
|
@ -553,8 +599,7 @@ message GetWlanConfigResponse {
|
|||
|
||||
message SetWlanConfigRequest {
|
||||
int32 session_id = 1;
|
||||
int32 node_id = 2;
|
||||
map<string, string> config = 3;
|
||||
WlanConfig wlan_config = 2;
|
||||
}
|
||||
|
||||
message SetWlanConfigResponse {
|
||||
|
@ -599,10 +644,7 @@ message GetEmaneModelConfigResponse {
|
|||
|
||||
message SetEmaneModelConfigRequest {
|
||||
int32 session_id = 1;
|
||||
int32 node_id = 2;
|
||||
int32 interface_id = 3;
|
||||
string model = 4;
|
||||
map<string, string> config = 5;
|
||||
EmaneModelConfig emane_model_config = 2;
|
||||
}
|
||||
|
||||
message SetEmaneModelConfigResponse {
|
||||
|
@ -659,6 +701,23 @@ message EmaneLinkResponse {
|
|||
}
|
||||
|
||||
// data structures for messages below
|
||||
message WlanConfig {
|
||||
int32 node_id = 1;
|
||||
map<string, string> config = 2;
|
||||
}
|
||||
|
||||
message MobilityConfig {
|
||||
int32 node_id = 1;
|
||||
map<string, string> config = 2;
|
||||
}
|
||||
|
||||
message EmaneModelConfig {
|
||||
int32 node_id = 1;
|
||||
int32 interface_id = 2;
|
||||
string model = 3;
|
||||
map<string, string> config = 4;
|
||||
}
|
||||
|
||||
message MessageType {
|
||||
enum Enum {
|
||||
NONE = 0;
|
||||
|
@ -695,18 +754,15 @@ message NodeType {
|
|||
enum Enum {
|
||||
DEFAULT = 0;
|
||||
PHYSICAL = 1;
|
||||
TBD = 3;
|
||||
SWITCH = 4;
|
||||
HUB = 5;
|
||||
WIRELESS_LAN = 6;
|
||||
RJ45 = 7;
|
||||
TUNNEL = 8;
|
||||
KTUNNEL = 9;
|
||||
EMANE = 10;
|
||||
TAP_BRIDGE = 11;
|
||||
PEER_TO_PEER = 12;
|
||||
CONTROL_NET = 13;
|
||||
EMANE_NET = 14;
|
||||
DOCKER = 15;
|
||||
LXC = 16;
|
||||
}
|
||||
|
@ -853,13 +909,14 @@ message Interface {
|
|||
int32 mtu = 10;
|
||||
}
|
||||
|
||||
message SessionPosition {
|
||||
message SessionLocation {
|
||||
float x = 1;
|
||||
float y = 2;
|
||||
float z = 3;
|
||||
float lat = 4;
|
||||
float lon = 5;
|
||||
float alt = 6;
|
||||
float scale = 7;
|
||||
}
|
||||
|
||||
message Position {
|
||||
|
|
|
@ -14,7 +14,7 @@ from core import services
|
|||
from core.constants import CORE_CONF_DIR
|
||||
|
||||
|
||||
class FileUpdater(object):
|
||||
class FileUpdater:
|
||||
"""
|
||||
Helper class for changing configuration files.
|
||||
"""
|
||||
|
|
|
@ -2,189 +2,140 @@
|
|||
Unit test fixture module.
|
||||
"""
|
||||
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
from mock.mock import MagicMock
|
||||
|
||||
from core.api.grpc.client import InterfaceHelper
|
||||
from core.api.grpc.server import CoreGrpcServer
|
||||
from core.api.tlv.coreapi import CoreConfMessage, CoreEventMessage
|
||||
from core.api.tlv.corehandlers import CoreHandler
|
||||
from core.api.tlv.coreserver import CoreServer
|
||||
from core.emane.emanemanager import EmaneManager
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.distributed import DistributedServer
|
||||
from core.emulator.emudata import IpPrefixes
|
||||
from core.emulator.enumerations import CORE_API_PORT, ConfigTlvs, EventTlvs, EventTypes
|
||||
from core.nodes import ipaddress
|
||||
from core.services.coreservices import ServiceManager
|
||||
from core.emulator.enumerations import EventTypes
|
||||
from core.emulator.session import Session
|
||||
from core.nodes.base import CoreNode
|
||||
|
||||
EMANE_SERVICES = "zebra|OSPFv3MDR|IPForward"
|
||||
|
||||
|
||||
class CoreServerTest(object):
|
||||
def __init__(self, port=CORE_API_PORT):
|
||||
self.host = "localhost"
|
||||
self.port = port
|
||||
address = (self.host, self.port)
|
||||
self.server = CoreServer(
|
||||
address, CoreHandler, {"numthreads": 1, "daemonize": False}
|
||||
)
|
||||
class PatchManager:
|
||||
def __init__(self):
|
||||
self.patches = []
|
||||
|
||||
self.distributed_server = "core2"
|
||||
self.prefix = ipaddress.Ipv4Prefix("10.83.0.0/16")
|
||||
self.session = None
|
||||
self.request_handler = None
|
||||
def patch_obj(self, _cls, attribute):
|
||||
p = mock.patch.object(_cls, attribute)
|
||||
p.start()
|
||||
self.patches.append(p)
|
||||
|
||||
def setup_handler(self):
|
||||
self.session = self.server.coreemu.create_session(1)
|
||||
request_mock = MagicMock()
|
||||
request_mock.fileno = MagicMock(return_value=1)
|
||||
self.request_handler = CoreHandler(request_mock, "", self.server)
|
||||
self.request_handler.session = self.session
|
||||
self.request_handler.add_session_handlers()
|
||||
|
||||
def setup(self, distributed_address):
|
||||
# validate address
|
||||
assert distributed_address, "distributed server address was not provided"
|
||||
|
||||
# create session
|
||||
self.session = self.server.coreemu.create_session(1)
|
||||
|
||||
# create request handler
|
||||
request_mock = MagicMock()
|
||||
request_mock.fileno = MagicMock(return_value=1)
|
||||
self.request_handler = CoreHandler(request_mock, "", self.server)
|
||||
self.request_handler.session = self.session
|
||||
self.request_handler.add_session_handlers()
|
||||
|
||||
# have broker handle a configuration state change
|
||||
self.session.set_state(EventTypes.DEFINITION_STATE)
|
||||
message = CoreEventMessage.create(
|
||||
0, [(EventTlvs.TYPE, EventTypes.CONFIGURATION_STATE.value)]
|
||||
)
|
||||
self.request_handler.handle_message(message)
|
||||
|
||||
# add broker server for distributed core
|
||||
distributed = f"{self.distributed_server}:{distributed_address}:{self.port}"
|
||||
message = CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
(ConfigTlvs.OBJECT, "broker"),
|
||||
(ConfigTlvs.TYPE, 0),
|
||||
(ConfigTlvs.DATA_TYPES, (10,)),
|
||||
(ConfigTlvs.VALUES, distributed),
|
||||
],
|
||||
)
|
||||
self.request_handler.handle_message(message)
|
||||
|
||||
# set session location
|
||||
message = CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
(ConfigTlvs.OBJECT, "location"),
|
||||
(ConfigTlvs.TYPE, 0),
|
||||
(ConfigTlvs.DATA_TYPES, (9, 9, 9, 9, 9, 9)),
|
||||
(ConfigTlvs.VALUES, "0|0| 47.5766974863|-122.125920191|0.0|150.0"),
|
||||
],
|
||||
)
|
||||
self.request_handler.handle_message(message)
|
||||
|
||||
# set services for host nodes
|
||||
message = CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
(ConfigTlvs.SESSION, str(self.session.id)),
|
||||
(ConfigTlvs.OBJECT, "services"),
|
||||
(ConfigTlvs.TYPE, 0),
|
||||
(ConfigTlvs.DATA_TYPES, (10, 10, 10)),
|
||||
(ConfigTlvs.VALUES, "host|DefaultRoute|SSH"),
|
||||
],
|
||||
)
|
||||
self.request_handler.handle_message(message)
|
||||
def patch(self, func):
|
||||
p = mock.patch(func)
|
||||
p.start()
|
||||
self.patches.append(p)
|
||||
|
||||
def shutdown(self):
|
||||
self.server.coreemu.shutdown()
|
||||
self.server.server_close()
|
||||
for p in self.patches:
|
||||
p.stop()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def grpc_server():
|
||||
coremu = CoreEmu()
|
||||
grpc_server = CoreGrpcServer(coremu)
|
||||
class MockServer:
|
||||
def __init__(self, config, coreemu):
|
||||
self.config = config
|
||||
self.coreemu = coreemu
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def patcher(request):
|
||||
patch_manager = PatchManager()
|
||||
patch_manager.patch_obj(DistributedServer, "remote_cmd")
|
||||
if request.config.getoption("mock"):
|
||||
patch_manager.patch("os.mkdir")
|
||||
patch_manager.patch("core.utils.cmd")
|
||||
patch_manager.patch("core.nodes.netclient.get_net_client")
|
||||
patch_manager.patch_obj(CoreNode, "nodefile")
|
||||
patch_manager.patch_obj(Session, "write_state")
|
||||
patch_manager.patch_obj(Session, "write_nodes")
|
||||
patch_manager.patch_obj(EmaneManager, "buildxml")
|
||||
yield patch_manager
|
||||
patch_manager.shutdown()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def global_coreemu(patcher):
|
||||
coreemu = CoreEmu(config={"emane_prefix": "/usr"})
|
||||
yield coreemu
|
||||
coreemu.shutdown()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def global_session(request, patcher, global_coreemu):
|
||||
mkdir = not request.config.getoption("mock")
|
||||
session = Session(1000, {"emane_prefix": "/usr"}, mkdir)
|
||||
yield session
|
||||
session.shutdown()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def ip_prefixes():
|
||||
return IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def interface_helper():
|
||||
return InterfaceHelper(ip4_prefix="10.83.0.0/16")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def module_grpc(global_coreemu):
|
||||
grpc_server = CoreGrpcServer(global_coreemu)
|
||||
thread = threading.Thread(target=grpc_server.listen, args=("localhost:50051",))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
time.sleep(0.1)
|
||||
yield grpc_server
|
||||
coremu.shutdown()
|
||||
grpc_server.server.stop(None)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def module_coretlv(patcher, global_coreemu, global_session):
|
||||
request_mock = MagicMock()
|
||||
request_mock.fileno = MagicMock(return_value=1)
|
||||
server = MockServer({"numthreads": "1"}, global_coreemu)
|
||||
request_handler = CoreHandler(request_mock, "", server)
|
||||
request_handler.session = global_session
|
||||
request_handler.add_session_handlers()
|
||||
yield request_handler
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def session():
|
||||
# use coreemu and create a session
|
||||
coreemu = CoreEmu(config={"emane_prefix": "/usr"})
|
||||
session_fixture = coreemu.create_session()
|
||||
session_fixture.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
assert os.path.exists(session_fixture.session_dir)
|
||||
def grpc_server(module_grpc):
|
||||
yield module_grpc
|
||||
module_grpc.coreemu.shutdown()
|
||||
|
||||
# return created session
|
||||
yield session_fixture
|
||||
|
||||
# clear session configurations
|
||||
session_fixture.location.reset()
|
||||
session_fixture.services.reset()
|
||||
session_fixture.mobility.config_reset()
|
||||
session_fixture.emane.config_reset()
|
||||
@pytest.fixture
|
||||
def session(global_session):
|
||||
global_session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
yield global_session
|
||||
global_session.clear()
|
||||
|
||||
# shutdown coreemu
|
||||
|
||||
@pytest.fixture
|
||||
def coretlv(module_coretlv):
|
||||
session = module_coretlv.session
|
||||
coreemu = module_coretlv.coreemu
|
||||
coreemu.sessions[session.id] = session
|
||||
yield module_coretlv
|
||||
coreemu.shutdown()
|
||||
|
||||
# clear services, since they will be reloaded
|
||||
ServiceManager.services.clear()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ip_prefixes():
|
||||
return IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def interface_helper():
|
||||
return InterfaceHelper(ip4_prefix="10.83.0.0/16")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def cored():
|
||||
# create and return server
|
||||
server = CoreServerTest()
|
||||
yield server
|
||||
|
||||
# cleanup
|
||||
server.shutdown()
|
||||
|
||||
# cleanup services
|
||||
ServiceManager.services.clear()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def coreserver():
|
||||
# create and return server
|
||||
server = CoreServerTest()
|
||||
server.setup_handler()
|
||||
yield server
|
||||
|
||||
# cleanup
|
||||
server.shutdown()
|
||||
|
||||
# cleanup services
|
||||
ServiceManager.services.clear()
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--distributed", help="distributed server address")
|
||||
parser.addoption("--mock", action="store_true", help="run without mocking")
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
|
|
|
@ -1,354 +0,0 @@
|
|||
"""
|
||||
Unit tests for testing CORE with distributed networks.
|
||||
"""
|
||||
from core.api.tlv.coreapi import (
|
||||
CoreConfMessage,
|
||||
CoreEventMessage,
|
||||
CoreExecMessage,
|
||||
CoreLinkMessage,
|
||||
CoreNodeMessage,
|
||||
)
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emulator.enumerations import (
|
||||
ConfigFlags,
|
||||
ConfigTlvs,
|
||||
EventTlvs,
|
||||
EventTypes,
|
||||
ExecuteTlvs,
|
||||
LinkTlvs,
|
||||
LinkTypes,
|
||||
MessageFlags,
|
||||
NodeTlvs,
|
||||
NodeTypes,
|
||||
)
|
||||
from core.nodes.ipaddress import IpAddress, MacAddress
|
||||
|
||||
|
||||
def set_emane_model(node_id, model):
|
||||
return CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
(ConfigTlvs.NODE, node_id),
|
||||
(ConfigTlvs.OBJECT, model),
|
||||
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def node_message(
|
||||
_id, name, emulation_server=None, node_type=NodeTypes.DEFAULT, model=None
|
||||
):
|
||||
"""
|
||||
Convenience method for creating a node TLV messages.
|
||||
|
||||
:param int _id: node id
|
||||
:param str name: node name
|
||||
:param str emulation_server: distributed server name, if desired
|
||||
:param core.emulator.enumerations.NodeTypes node_type: node type
|
||||
:param str model: model for node
|
||||
:return: tlv message
|
||||
:rtype: core.api.tlv.coreapi.CoreNodeMessage
|
||||
"""
|
||||
values = [
|
||||
(NodeTlvs.NUMBER, _id),
|
||||
(NodeTlvs.TYPE, node_type.value),
|
||||
(NodeTlvs.NAME, name),
|
||||
(NodeTlvs.EMULATION_SERVER, emulation_server),
|
||||
(NodeTlvs.X_POSITION, 0),
|
||||
(NodeTlvs.Y_POSITION, 0),
|
||||
]
|
||||
|
||||
if model:
|
||||
values.append((NodeTlvs.MODEL, model))
|
||||
|
||||
return CoreNodeMessage.create(MessageFlags.ADD.value, values)
|
||||
|
||||
|
||||
def link_message(
|
||||
n1,
|
||||
n2,
|
||||
intf_one=None,
|
||||
address_one=None,
|
||||
intf_two=None,
|
||||
address_two=None,
|
||||
key=None,
|
||||
mask=24,
|
||||
):
|
||||
"""
|
||||
Convenience method for creating link TLV messages.
|
||||
|
||||
:param int n1: node one id
|
||||
:param int n2: node two id
|
||||
:param int intf_one: node one interface id
|
||||
:param core.nodes.ipaddress.IpAddress address_one: node one ip4 address
|
||||
:param int intf_two: node two interface id
|
||||
:param core.nodes.ipaddress.IpAddress address_two: node two ip4 address
|
||||
:param int key: tunnel key for link if needed
|
||||
:param int mask: ip4 mask to use for link
|
||||
:return: tlv mesage
|
||||
:rtype: core.api.tlv.coreapi.CoreLinkMessage
|
||||
"""
|
||||
mac_one, mac_two = None, None
|
||||
if address_one:
|
||||
mac_one = MacAddress.random()
|
||||
if address_two:
|
||||
mac_two = MacAddress.random()
|
||||
|
||||
values = [
|
||||
(LinkTlvs.N1_NUMBER, n1),
|
||||
(LinkTlvs.N2_NUMBER, n2),
|
||||
(LinkTlvs.DELAY, 0),
|
||||
(LinkTlvs.BANDWIDTH, 0),
|
||||
(LinkTlvs.PER, "0"),
|
||||
(LinkTlvs.DUP, "0"),
|
||||
(LinkTlvs.JITTER, 0),
|
||||
(LinkTlvs.TYPE, LinkTypes.WIRED.value),
|
||||
(LinkTlvs.INTERFACE1_NUMBER, intf_one),
|
||||
(LinkTlvs.INTERFACE1_IP4, address_one),
|
||||
(LinkTlvs.INTERFACE1_IP4_MASK, mask),
|
||||
(LinkTlvs.INTERFACE1_MAC, mac_one),
|
||||
(LinkTlvs.INTERFACE2_NUMBER, intf_two),
|
||||
(LinkTlvs.INTERFACE2_IP4, address_two),
|
||||
(LinkTlvs.INTERFACE2_IP4_MASK, mask),
|
||||
(LinkTlvs.INTERFACE2_MAC, mac_two),
|
||||
]
|
||||
|
||||
if key:
|
||||
values.append((LinkTlvs.KEY, key))
|
||||
|
||||
return CoreLinkMessage.create(MessageFlags.ADD.value, values)
|
||||
|
||||
|
||||
def command_message(node, command):
|
||||
"""
|
||||
Create an execute command TLV message.
|
||||
|
||||
:param node: node to execute command for
|
||||
:param command: command to execute
|
||||
:return: tlv message
|
||||
:rtype: core.api.tlv.coreapi.CoreExecMessage
|
||||
"""
|
||||
flags = MessageFlags.STRING.value | MessageFlags.TEXT.value
|
||||
return CoreExecMessage.create(
|
||||
flags,
|
||||
[
|
||||
(ExecuteTlvs.NODE, node.id),
|
||||
(ExecuteTlvs.NUMBER, 1),
|
||||
(ExecuteTlvs.COMMAND, command),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def state_message(state):
|
||||
"""
|
||||
Create a event TLV message for a new state.
|
||||
|
||||
:param core.enumerations.EventTypes state: state to create message for
|
||||
:return: tlv message
|
||||
:rtype: core.api.tlv.coreapi.CoreEventMessage
|
||||
"""
|
||||
return CoreEventMessage.create(0, [(EventTlvs.TYPE, state.value)])
|
||||
|
||||
|
||||
def validate_response(replies, _):
|
||||
"""
|
||||
Patch method for handling dispatch replies within a CoreRequestHandler to validate a response.
|
||||
|
||||
:param tuple replies: replies to handle
|
||||
:param _: nothing
|
||||
:return: nothing
|
||||
"""
|
||||
response = replies[0]
|
||||
header = response[: CoreExecMessage.header_len]
|
||||
tlv_data = response[CoreExecMessage.header_len :]
|
||||
response = CoreExecMessage(MessageFlags.TEXT, header, tlv_data)
|
||||
assert not response.get_tlv(ExecuteTlvs.STATUS.value)
|
||||
|
||||
|
||||
class TestDistributed:
|
||||
def test_switch(self, cored, distributed_address):
|
||||
"""
|
||||
Test creating a distributed switch network.
|
||||
|
||||
:param core.api.tlv.coreserver.CoreServer conftest.Core cored: core daemon server to test with
|
||||
:param str distributed_address: distributed server to test against
|
||||
"""
|
||||
# initialize server for testing
|
||||
cored.setup(distributed_address)
|
||||
|
||||
# create local node
|
||||
message = node_message(_id=1, name="n1", model="host")
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# create distributed node and assign to distributed server
|
||||
message = node_message(
|
||||
_id=2, name="n2", emulation_server=cored.distributed_server, model="host"
|
||||
)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# create distributed switch and assign to distributed server
|
||||
message = node_message(_id=3, name="n3", node_type=NodeTypes.SWITCH)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# link message one
|
||||
ip4_address = cored.prefix.addr(1)
|
||||
message = link_message(n1=1, n2=3, intf_one=0, address_one=ip4_address)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# link message two
|
||||
ip4_address = cored.prefix.addr(2)
|
||||
message = link_message(n1=3, n2=2, intf_two=0, address_two=ip4_address)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# change session to instantiation state
|
||||
message = state_message(EventTypes.INSTANTIATION_STATE)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# test a ping command
|
||||
node_one = cored.session.get_node(1)
|
||||
message = command_message(node_one, f"ping -c 5 {ip4_address}")
|
||||
cored.request_handler.dispatch_replies = validate_response
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
def test_emane(self, cored, distributed_address):
|
||||
"""
|
||||
Test creating a distributed emane network.
|
||||
|
||||
:param core.api.tlv.coreserver.CoreServer conftest.Core cored: core daemon server to test with
|
||||
:param str distributed_address: distributed server to test against
|
||||
"""
|
||||
# initialize server for testing
|
||||
cored.setup(distributed_address)
|
||||
|
||||
# configure required controlnet
|
||||
cored.session.options.set_config(
|
||||
"controlnet", "core1:172.16.1.0/24 core2:172.16.2.0/24"
|
||||
)
|
||||
|
||||
# create local node
|
||||
message = node_message(_id=1, name="n1", model="mdr")
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# create distributed node and assign to distributed server
|
||||
message = node_message(
|
||||
_id=2, name="n2", emulation_server=cored.distributed_server, model="mdr"
|
||||
)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# create distributed switch and assign to distributed server
|
||||
message = node_message(_id=3, name="n3", node_type=NodeTypes.EMANE)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# set emane model
|
||||
message = set_emane_model(3, EmaneIeee80211abgModel.name)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# link message one
|
||||
ip4_address = cored.prefix.addr(1)
|
||||
message = link_message(n1=1, n2=3, intf_one=0, address_one=ip4_address, mask=32)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# link message two
|
||||
ip4_address = cored.prefix.addr(2)
|
||||
message = link_message(n1=2, n2=3, intf_one=0, address_one=ip4_address, mask=32)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# change session to instantiation state
|
||||
message = state_message(EventTypes.INSTANTIATION_STATE)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# test a ping command
|
||||
node_one = cored.session.get_node(1)
|
||||
message = command_message(node_one, f"ping -c 5 {ip4_address}")
|
||||
cored.request_handler.dispatch_replies = validate_response
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
def test_prouter(self, cored, distributed_address):
|
||||
"""
|
||||
Test creating a distributed prouter node.
|
||||
|
||||
:param core.coreserver.CoreServer Core cored: core daemon server to test with
|
||||
:param str distributed_address: distributed server to test against
|
||||
"""
|
||||
# initialize server for testing
|
||||
cored.setup(distributed_address)
|
||||
|
||||
# create local node
|
||||
message = node_message(_id=1, name="n1", model="host")
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# create distributed node and assign to distributed server
|
||||
message = node_message(
|
||||
_id=2,
|
||||
name="n2",
|
||||
emulation_server=cored.distributed_server,
|
||||
node_type=NodeTypes.PHYSICAL,
|
||||
model="prouter",
|
||||
)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# create distributed switch and assign to distributed server
|
||||
message = node_message(_id=3, name="n3", node_type=NodeTypes.SWITCH)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# link message one
|
||||
ip4_address = cored.prefix.addr(1)
|
||||
message = link_message(n1=1, n2=3, intf_one=0, address_one=ip4_address)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# link message two
|
||||
ip4_address = cored.prefix.addr(2)
|
||||
message = link_message(n1=3, n2=2, intf_two=0, address_two=ip4_address)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# change session to instantiation state
|
||||
message = state_message(EventTypes.INSTANTIATION_STATE)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# test a ping command
|
||||
node_one = cored.session.get_node(1)
|
||||
message = command_message(node_one, f"ping -c 5 {ip4_address}")
|
||||
cored.request_handler.dispatch_replies = validate_response
|
||||
cored.request_handler.handle_message(message)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
def test_tunnel(self, cored, distributed_address):
|
||||
"""
|
||||
Test session broker creation.
|
||||
|
||||
:param core.coreserver.CoreServer Core cored: core daemon server to test with
|
||||
:param str distributed_address: distributed server to test against
|
||||
"""
|
||||
# initialize server for testing
|
||||
cored.setup(distributed_address)
|
||||
|
||||
# create local node
|
||||
message = node_message(_id=1, name="n1", model="host")
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# create distributed node and assign to distributed server
|
||||
message = node_message(
|
||||
_id=2,
|
||||
name=distributed_address,
|
||||
emulation_server=cored.distributed_server,
|
||||
node_type=NodeTypes.TUNNEL,
|
||||
)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# link message one
|
||||
ip4_address = cored.prefix.addr(1)
|
||||
address_two = IpAddress.from_string(distributed_address)
|
||||
message = link_message(
|
||||
n1=1,
|
||||
n2=2,
|
||||
intf_one=0,
|
||||
address_one=ip4_address,
|
||||
intf_two=0,
|
||||
address_two=address_two,
|
||||
key=1,
|
||||
)
|
||||
cored.request_handler.handle_message(message)
|
||||
|
||||
# change session to instantiation state
|
||||
message = state_message(EventTypes.INSTANTIATION_STATE)
|
||||
cored.request_handler.handle_message(message)
|
|
@ -12,6 +12,7 @@ from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
|||
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
|
||||
|
||||
_EMANE_MODELS = [
|
||||
|
@ -46,10 +47,11 @@ class TestEmane:
|
|||
"""
|
||||
|
||||
# create emane node for networking the core nodes
|
||||
emane_network = session.create_emane_network(
|
||||
model, geo_reference=(47.57917, -122.13232, 2.00000)
|
||||
)
|
||||
emane_network.setposition(x=80, y=50)
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions()
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(_type=NodeTypes.EMANE, options=options)
|
||||
session.emane.set_model(emane_network, model)
|
||||
|
||||
# configure tdma
|
||||
if model == EmaneTdmaModel:
|
||||
|
@ -60,11 +62,11 @@ class TestEmane:
|
|||
)
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions()
|
||||
node_options.set_position(150, 150)
|
||||
node_one = session.create_wireless_node(node_options=node_options)
|
||||
node_options.set_position(300, 150)
|
||||
node_two = session.create_wireless_node(node_options=node_options)
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(150, 150)
|
||||
node_one = session.add_node(options=options)
|
||||
options.set_position(300, 150)
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
for i, node in enumerate([node_one, node_two]):
|
||||
node.setposition(x=150 * (i + 1), y=150)
|
||||
|
@ -87,19 +89,22 @@ class TestEmane:
|
|||
:param ip_prefixes: generates ip addresses for nodes
|
||||
"""
|
||||
# create emane node for networking the core nodes
|
||||
emane_network = session.create_emane_network(
|
||||
EmaneIeee80211abgModel,
|
||||
geo_reference=(47.57917, -122.13232, 2.00000),
|
||||
config={"test": "1"},
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions()
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(_type=NodeTypes.EMANE, options=options)
|
||||
config_key = "txpower"
|
||||
config_value = "10"
|
||||
session.emane.set_model(
|
||||
emane_network, EmaneIeee80211abgModel, {config_key: config_value}
|
||||
)
|
||||
emane_network.setposition(x=80, y=50)
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions()
|
||||
node_options.set_position(150, 150)
|
||||
node_one = session.create_wireless_node(node_options=node_options)
|
||||
node_options.set_position(300, 150)
|
||||
node_two = session.create_wireless_node(node_options=node_options)
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(150, 150)
|
||||
node_one = session.add_node(options=options)
|
||||
options.set_position(300, 150)
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
for i, node in enumerate([node_one, node_two]):
|
||||
node.setposition(x=150 * (i + 1), y=150)
|
||||
|
@ -137,11 +142,11 @@ class TestEmane:
|
|||
|
||||
# retrieve configuration we set originally
|
||||
value = str(
|
||||
session.emane.get_config("test", emane_id, EmaneIeee80211abgModel.name)
|
||||
session.emane.get_config(config_key, emane_id, EmaneIeee80211abgModel.name)
|
||||
)
|
||||
|
||||
# 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 value == "1"
|
||||
assert value == config_value
|
||||
|
|
|
@ -20,7 +20,7 @@ _WIRED = [NodeTypes.PEER_TO_PEER, NodeTypes.HUB, NodeTypes.SWITCH]
|
|||
def ping(from_node, to_node, ip_prefixes):
|
||||
address = ip_prefixes.ip4_address(to_node)
|
||||
try:
|
||||
from_node.cmd(f"ping -c 3 {address}")
|
||||
from_node.cmd(f"ping -c 1 {address}")
|
||||
status = 0
|
||||
except CoreCommandError as e:
|
||||
status = e.returncode
|
||||
|
@ -57,14 +57,14 @@ class TestCore:
|
|||
status = ping(node_one, node_two, ip_prefixes)
|
||||
assert not status
|
||||
|
||||
def test_vnode_client(self, session, ip_prefixes):
|
||||
def test_vnode_client(self, request, session, ip_prefixes):
|
||||
"""
|
||||
Test vnode client methods.
|
||||
|
||||
:param request: pytest request
|
||||
:param session: session for test
|
||||
:param ip_prefixes: generates ip addresses for nodes
|
||||
"""
|
||||
|
||||
# create ptp
|
||||
ptp_node = session.add_node(_type=NodeTypes.PEER_TO_PEER)
|
||||
|
||||
|
@ -87,6 +87,7 @@ class TestCore:
|
|||
assert client.connected()
|
||||
|
||||
# validate command
|
||||
if not request.config.getoption("mock"):
|
||||
assert client.check_cmd("echo hello") == "hello"
|
||||
|
||||
def test_netif(self, session, ip_prefixes):
|
||||
|
@ -146,10 +147,10 @@ class TestCore:
|
|||
session.mobility.set_model(wlan_node, BasicRangeModel)
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions()
|
||||
node_options.set_position(0, 0)
|
||||
node_one = session.create_wireless_node(node_options=node_options)
|
||||
node_two = session.create_wireless_node(node_options=node_options)
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
node_one = session.add_node(options=options)
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
# link nodes
|
||||
for node in [node_one, node_two]:
|
||||
|
@ -176,10 +177,10 @@ class TestCore:
|
|||
session.mobility.set_model(wlan_node, BasicRangeModel)
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions()
|
||||
node_options.set_position(0, 0)
|
||||
node_one = session.create_wireless_node(node_options=node_options)
|
||||
node_two = session.create_wireless_node(node_options=node_options)
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
node_one = session.add_node(options=options)
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
# link nodes
|
||||
for node in [node_one, node_two]:
|
||||
|
|
39
daemon/tests/test_distributed.py
Normal file
39
daemon/tests/test_distributed.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
from core.emulator.emudata import NodeOptions
|
||||
from core.emulator.enumerations import NodeTypes
|
||||
|
||||
|
||||
class TestDistributed:
|
||||
def test_remote_node(self, session):
|
||||
# given
|
||||
server_name = "core2"
|
||||
host = "127.0.0.1"
|
||||
|
||||
# when
|
||||
session.distributed.add_server(server_name, host)
|
||||
options = NodeOptions()
|
||||
options.server = server_name
|
||||
node = session.add_node(options=options)
|
||||
|
||||
# then
|
||||
assert node.server is not None
|
||||
assert node.server.name == server_name
|
||||
assert node.server.host == host
|
||||
|
||||
def test_remote_bridge(self, session):
|
||||
# given
|
||||
server_name = "core2"
|
||||
host = "127.0.0.1"
|
||||
session.distributed.address = host
|
||||
|
||||
# when
|
||||
session.distributed.add_server(server_name, host)
|
||||
options = NodeOptions()
|
||||
options.server = server_name
|
||||
node = session.add_node(_type=NodeTypes.HUB, options=options)
|
||||
session.instantiate()
|
||||
|
||||
# then
|
||||
assert node.server is not None
|
||||
assert node.server.name == server_name
|
||||
assert node.server.host == host
|
||||
assert len(session.distributed.tunnels) > 0
|
|
@ -3,9 +3,10 @@ from queue import Queue
|
|||
|
||||
import grpc
|
||||
import pytest
|
||||
from mock import patch
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from core.api.grpc.client import CoreGrpcClient
|
||||
from core.api.grpc.client import CoreGrpcClient, InterfaceHelper
|
||||
from core.config import ConfigShim
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emulator.data import EventData
|
||||
|
@ -18,9 +19,127 @@ from core.emulator.enumerations import (
|
|||
)
|
||||
from core.errors import CoreError
|
||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
from core.xml.corexml import CoreXmlWriter
|
||||
|
||||
|
||||
class TestGrpc:
|
||||
def test_start_session(self, grpc_server):
|
||||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
nodes = []
|
||||
position = core_pb2.Position(x=50, y=100)
|
||||
node_one = core_pb2.Node(id=1, position=position, model="PC")
|
||||
position = core_pb2.Position(x=100, y=100)
|
||||
node_two = core_pb2.Node(id=2, position=position, model="PC")
|
||||
position = core_pb2.Position(x=200, y=200)
|
||||
wlan_node = core_pb2.Node(
|
||||
id=3, type=NodeTypes.WIRELESS_LAN.value, position=position
|
||||
)
|
||||
nodes.extend([node_one, node_two, wlan_node])
|
||||
links = []
|
||||
interface_helper = InterfaceHelper(ip4_prefix="10.83.0.0/16")
|
||||
interface_one = interface_helper.create_interface(node_one.id, 0)
|
||||
interface_two = interface_helper.create_interface(node_two.id, 0)
|
||||
link = core_pb2.Link(
|
||||
type=core_pb2.LinkType.WIRED,
|
||||
node_one_id=node_one.id,
|
||||
node_two_id=node_two.id,
|
||||
interface_one=interface_one,
|
||||
interface_two=interface_two,
|
||||
)
|
||||
links.append(link)
|
||||
hooks = []
|
||||
hook = core_pb2.Hook(
|
||||
state=core_pb2.SessionState.RUNTIME, file="echo.sh", data="echo hello"
|
||||
)
|
||||
hooks.append(hook)
|
||||
location_x = 5
|
||||
location_y = 10
|
||||
location_z = 15
|
||||
location_lat = 20
|
||||
location_lon = 30
|
||||
location_alt = 40
|
||||
location_scale = 5
|
||||
location = core_pb2.SessionLocation(
|
||||
x=location_x,
|
||||
y=location_y,
|
||||
z=location_z,
|
||||
lat=location_lat,
|
||||
lon=location_lon,
|
||||
alt=location_alt,
|
||||
scale=location_scale,
|
||||
)
|
||||
emane_config_key = "platform_id_start"
|
||||
emane_config_value = "2"
|
||||
emane_config = {emane_config_key: emane_config_value}
|
||||
model_configs = []
|
||||
model_node_id = 20
|
||||
model_config_key = "bandwidth"
|
||||
model_config_value = "500000"
|
||||
model_config = core_pb2.EmaneModelConfig(
|
||||
node_id=model_node_id,
|
||||
interface_id=-1,
|
||||
model=EmaneIeee80211abgModel.name,
|
||||
config={model_config_key: model_config_value},
|
||||
)
|
||||
model_configs.append(model_config)
|
||||
wlan_configs = []
|
||||
wlan_config_key = "range"
|
||||
wlan_config_value = "333"
|
||||
wlan_config = core_pb2.WlanConfig(
|
||||
node_id=wlan_node.id, config={wlan_config_key: wlan_config_value}
|
||||
)
|
||||
wlan_configs.append(wlan_config)
|
||||
mobility_config_key = "refresh_ms"
|
||||
mobility_config_value = "60"
|
||||
mobility_configs = []
|
||||
mobility_config = core_pb2.MobilityConfig(
|
||||
node_id=wlan_node.id, config={mobility_config_key: mobility_config_value}
|
||||
)
|
||||
mobility_configs.append(mobility_config)
|
||||
|
||||
# when
|
||||
with patch.object(CoreXmlWriter, "write"):
|
||||
with client.context_connect():
|
||||
client.start_session(
|
||||
session.id,
|
||||
nodes,
|
||||
links,
|
||||
location,
|
||||
hooks,
|
||||
emane_config,
|
||||
model_configs,
|
||||
wlan_configs,
|
||||
mobility_configs,
|
||||
)
|
||||
|
||||
# then
|
||||
assert node_one.id in session.nodes
|
||||
assert node_two.id in session.nodes
|
||||
assert wlan_node.id in session.nodes
|
||||
assert session.nodes[node_one.id].netif(0) is not None
|
||||
assert session.nodes[node_two.id].netif(0) is not None
|
||||
hook_file, hook_data = session._hooks[core_pb2.SessionState.RUNTIME][0]
|
||||
assert hook_file == hook.file
|
||||
assert hook_data == hook.data
|
||||
assert session.location.refxyz == (location_x, location_y, location_z)
|
||||
assert session.location.refgeo == (location_lat, location_lon, location_alt)
|
||||
assert session.location.refscale == location_scale
|
||||
assert session.emane.get_config(emane_config_key) == emane_config_value
|
||||
set_wlan_config = session.mobility.get_model_config(
|
||||
wlan_node.id, BasicRangeModel.name
|
||||
)
|
||||
assert set_wlan_config[wlan_config_key] == wlan_config_value
|
||||
set_mobility_config = session.mobility.get_model_config(
|
||||
wlan_node.id, Ns2ScriptedMobility.name
|
||||
)
|
||||
assert set_mobility_config[mobility_config_key] == mobility_config_value
|
||||
set_model_config = session.emane.get_model_config(
|
||||
model_node_id, EmaneIeee80211abgModel.name
|
||||
)
|
||||
assert set_model_config[model_config_key] == model_config_value
|
||||
|
||||
@pytest.mark.parametrize("session_id", [None, 6013])
|
||||
def test_create_session(self, grpc_server, session_id):
|
||||
# given
|
||||
|
@ -112,13 +231,13 @@ class TestGrpc:
|
|||
response = client.get_session_location(session.id)
|
||||
|
||||
# then
|
||||
assert response.scale == 1.0
|
||||
assert response.position.x == 0
|
||||
assert response.position.y == 0
|
||||
assert response.position.z == 0
|
||||
assert response.position.lat == 0
|
||||
assert response.position.lon == 0
|
||||
assert response.position.alt == 0
|
||||
assert response.location.scale == 1.0
|
||||
assert response.location.x == 0
|
||||
assert response.location.y == 0
|
||||
assert response.location.z == 0
|
||||
assert response.location.lat == 0
|
||||
assert response.location.lon == 0
|
||||
assert response.location.alt == 0
|
||||
|
||||
def test_set_session_location(self, grpc_server):
|
||||
# given
|
||||
|
@ -164,6 +283,36 @@ class TestGrpc:
|
|||
config = session.options.get_configs()
|
||||
assert len(config) > 0
|
||||
|
||||
def test_set_session_metadata(self, grpc_server):
|
||||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
|
||||
# then
|
||||
key = "meta1"
|
||||
value = "value1"
|
||||
with client.context_connect():
|
||||
response = client.set_session_metadata(session.id, {key: value})
|
||||
|
||||
# then
|
||||
assert response.result is True
|
||||
assert session.metadata[key] == value
|
||||
|
||||
def test_get_session_metadata(self, grpc_server):
|
||||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
key = "meta1"
|
||||
value = "value1"
|
||||
session.metadata[key] = value
|
||||
|
||||
# then
|
||||
with client.context_connect():
|
||||
response = client.get_session_metadata(session.id)
|
||||
|
||||
# then
|
||||
assert response.config[key] == value
|
||||
|
||||
def test_set_session_state(self, grpc_server):
|
||||
# given
|
||||
client = CoreGrpcClient()
|
||||
|
@ -240,13 +389,16 @@ class TestGrpc:
|
|||
with pytest.raises(CoreError):
|
||||
assert session.get_node(node.id)
|
||||
|
||||
def test_node_command(self, grpc_server):
|
||||
def test_node_command(self, request, grpc_server):
|
||||
if request.config.getoption("mock"):
|
||||
pytest.skip("mocking calls")
|
||||
|
||||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
node_options = NodeOptions(model="Host")
|
||||
node = session.add_node(node_options=node_options)
|
||||
options = NodeOptions(model="Host")
|
||||
node = session.add_node(options=options)
|
||||
session.instantiate()
|
||||
output = "hello world"
|
||||
|
||||
|
@ -263,8 +415,8 @@ class TestGrpc:
|
|||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
node_options = NodeOptions(model="Host")
|
||||
node = session.add_node(node_options=node_options)
|
||||
options = NodeOptions(model="Host")
|
||||
node = session.add_node(options=options)
|
||||
session.instantiate()
|
||||
|
||||
# then
|
||||
|
@ -524,9 +676,9 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
emane_network = session.create_emane_network(
|
||||
model=EmaneIeee80211abgModel, geo_reference=(47.57917, -122.13232, 2.00000)
|
||||
)
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
emane_network = session.add_node(_type=NodeTypes.EMANE)
|
||||
session.emane.set_model(emane_network, EmaneIeee80211abgModel)
|
||||
config_key = "platform_id_start"
|
||||
config_value = "2"
|
||||
session.emane.set_model_config(
|
||||
|
@ -548,9 +700,9 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
emane_network = session.create_emane_network(
|
||||
model=EmaneIeee80211abgModel, geo_reference=(47.57917, -122.13232, 2.00000)
|
||||
)
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
emane_network = session.add_node(_type=NodeTypes.EMANE)
|
||||
session.emane.set_model(emane_network, EmaneIeee80211abgModel)
|
||||
config_key = "bandwidth"
|
||||
config_value = "900000"
|
||||
|
||||
|
@ -574,9 +726,9 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
emane_network = session.create_emane_network(
|
||||
model=EmaneIeee80211abgModel, geo_reference=(47.57917, -122.13232, 2.00000)
|
||||
)
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
emane_network = session.add_node(_type=NodeTypes.EMANE)
|
||||
session.emane.set_model(emane_network, EmaneIeee80211abgModel)
|
||||
|
||||
# then
|
||||
with client.context_connect():
|
||||
|
@ -834,7 +986,10 @@ class TestGrpc:
|
|||
# then
|
||||
queue.get(timeout=5)
|
||||
|
||||
def test_throughputs(self, grpc_server):
|
||||
def test_throughputs(self, request, grpc_server):
|
||||
if request.config.getoption("mock"):
|
||||
pytest.skip("mocking calls")
|
||||
|
||||
# given
|
||||
client = CoreGrpcClient()
|
||||
grpc_server.coreemu.create_session()
|
||||
|
|
|
@ -6,6 +6,7 @@ import time
|
|||
|
||||
import mock
|
||||
import pytest
|
||||
from mock import MagicMock
|
||||
|
||||
from core.api.tlv import coreapi
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
|
@ -42,10 +43,9 @@ class TestGui:
|
|||
(NodeTypes.SWITCH, None),
|
||||
(NodeTypes.WIRELESS_LAN, None),
|
||||
(NodeTypes.TUNNEL, None),
|
||||
(NodeTypes.RJ45, None),
|
||||
],
|
||||
)
|
||||
def test_node_add(self, coreserver, node_type, model):
|
||||
def test_node_add(self, coretlv, node_type, model):
|
||||
node_id = 1
|
||||
message = coreapi.CoreNodeMessage.create(
|
||||
MessageFlags.ADD.value,
|
||||
|
@ -59,13 +59,13 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.get_node(node_id) is not None
|
||||
assert coretlv.session.get_node(node_id) is not None
|
||||
|
||||
def test_node_update(self, coreserver):
|
||||
def test_node_update(self, coretlv):
|
||||
node_id = 1
|
||||
coreserver.session.add_node(_id=node_id)
|
||||
coretlv.session.add_node(_id=node_id)
|
||||
x = 50
|
||||
y = 100
|
||||
message = coreapi.CoreNodeMessage.create(
|
||||
|
@ -77,30 +77,30 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
node = coreserver.session.get_node(node_id)
|
||||
node = coretlv.session.get_node(node_id)
|
||||
assert node is not None
|
||||
assert node.position.x == x
|
||||
assert node.position.y == y
|
||||
|
||||
def test_node_delete(self, coreserver):
|
||||
def test_node_delete(self, coretlv):
|
||||
node_id = 1
|
||||
coreserver.session.add_node(_id=node_id)
|
||||
coretlv.session.add_node(_id=node_id)
|
||||
message = coreapi.CoreNodeMessage.create(
|
||||
MessageFlags.DELETE.value, [(NodeTlvs.NUMBER, node_id)]
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
with pytest.raises(CoreError):
|
||||
coreserver.session.get_node(node_id)
|
||||
coretlv.session.get_node(node_id)
|
||||
|
||||
def test_link_add_node_to_net(self, coreserver):
|
||||
def test_link_add_node_to_net(self, coretlv):
|
||||
node_one = 1
|
||||
coreserver.session.add_node(_id=node_one)
|
||||
coretlv.session.add_node(_id=node_one)
|
||||
switch = 2
|
||||
coreserver.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
coretlv.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
ip_prefix = Ipv4Prefix("10.0.0.0/24")
|
||||
interface_one = ip_prefix.addr(node_one)
|
||||
message = coreapi.CoreLinkMessage.create(
|
||||
|
@ -114,17 +114,17 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
|
||||
def test_link_add_net_to_node(self, coreserver):
|
||||
def test_link_add_net_to_node(self, coretlv):
|
||||
node_one = 1
|
||||
coreserver.session.add_node(_id=node_one)
|
||||
coretlv.session.add_node(_id=node_one)
|
||||
switch = 2
|
||||
coreserver.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
coretlv.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
ip_prefix = Ipv4Prefix("10.0.0.0/24")
|
||||
interface_one = ip_prefix.addr(node_one)
|
||||
message = coreapi.CoreLinkMessage.create(
|
||||
|
@ -138,17 +138,17 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
|
||||
def test_link_add_node_to_node(self, coreserver):
|
||||
def test_link_add_node_to_node(self, coretlv):
|
||||
node_one = 1
|
||||
coreserver.session.add_node(_id=node_one)
|
||||
coretlv.session.add_node(_id=node_one)
|
||||
node_two = 2
|
||||
coreserver.session.add_node(_id=node_two)
|
||||
coretlv.session.add_node(_id=node_two)
|
||||
ip_prefix = Ipv4Prefix("10.0.0.0/24")
|
||||
interface_one = ip_prefix.addr(node_one)
|
||||
interface_two = ip_prefix.addr(node_two)
|
||||
|
@ -166,19 +166,19 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
all_links = []
|
||||
for node_id in coreserver.session.nodes:
|
||||
node = coreserver.session.nodes[node_id]
|
||||
for node_id in coretlv.session.nodes:
|
||||
node = coretlv.session.nodes[node_id]
|
||||
all_links += node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
|
||||
def test_link_update(self, coreserver):
|
||||
def test_link_update(self, coretlv):
|
||||
node_one = 1
|
||||
coreserver.session.add_node(_id=node_one)
|
||||
coretlv.session.add_node(_id=node_one)
|
||||
switch = 2
|
||||
coreserver.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
coretlv.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
ip_prefix = Ipv4Prefix("10.0.0.0/24")
|
||||
interface_one = ip_prefix.addr(node_one)
|
||||
message = coreapi.CoreLinkMessage.create(
|
||||
|
@ -191,8 +191,8 @@ class TestGui:
|
|||
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
coretlv.handle_message(message)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
link = all_links[0]
|
||||
|
@ -208,19 +208,19 @@ class TestGui:
|
|||
(LinkTlvs.BANDWIDTH, bandwidth),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
link = all_links[0]
|
||||
assert link.bandwidth == bandwidth
|
||||
|
||||
def test_link_delete_node_to_node(self, coreserver):
|
||||
def test_link_delete_node_to_node(self, coretlv):
|
||||
node_one = 1
|
||||
coreserver.session.add_node(_id=node_one)
|
||||
coretlv.session.add_node(_id=node_one)
|
||||
node_two = 2
|
||||
coreserver.session.add_node(_id=node_two)
|
||||
coretlv.session.add_node(_id=node_two)
|
||||
ip_prefix = Ipv4Prefix("10.0.0.0/24")
|
||||
interface_one = ip_prefix.addr(node_one)
|
||||
interface_two = ip_prefix.addr(node_two)
|
||||
|
@ -236,10 +236,10 @@ class TestGui:
|
|||
(LinkTlvs.INTERFACE2_IP4_MASK, 24),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
all_links = []
|
||||
for node_id in coreserver.session.nodes:
|
||||
node = coreserver.session.nodes[node_id]
|
||||
for node_id in coretlv.session.nodes:
|
||||
node = coretlv.session.nodes[node_id]
|
||||
all_links += node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
|
||||
|
@ -252,19 +252,19 @@ class TestGui:
|
|||
(LinkTlvs.INTERFACE2_NUMBER, 0),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
all_links = []
|
||||
for node_id in coreserver.session.nodes:
|
||||
node = coreserver.session.nodes[node_id]
|
||||
for node_id in coretlv.session.nodes:
|
||||
node = coretlv.session.nodes[node_id]
|
||||
all_links += node.all_link_data(0)
|
||||
assert len(all_links) == 0
|
||||
|
||||
def test_link_delete_node_to_net(self, coreserver):
|
||||
def test_link_delete_node_to_net(self, coretlv):
|
||||
node_one = 1
|
||||
coreserver.session.add_node(_id=node_one)
|
||||
coretlv.session.add_node(_id=node_one)
|
||||
switch = 2
|
||||
coreserver.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
coretlv.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
ip_prefix = Ipv4Prefix("10.0.0.0/24")
|
||||
interface_one = ip_prefix.addr(node_one)
|
||||
message = coreapi.CoreLinkMessage.create(
|
||||
|
@ -277,8 +277,8 @@ class TestGui:
|
|||
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
coretlv.handle_message(message)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
|
||||
|
@ -290,17 +290,17 @@ class TestGui:
|
|||
(LinkTlvs.INTERFACE1_NUMBER, 0),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 0
|
||||
|
||||
def test_link_delete_net_to_node(self, coreserver):
|
||||
def test_link_delete_net_to_node(self, coretlv):
|
||||
node_one = 1
|
||||
coreserver.session.add_node(_id=node_one)
|
||||
coretlv.session.add_node(_id=node_one)
|
||||
switch = 2
|
||||
coreserver.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
coretlv.session.add_node(_id=switch, _type=NodeTypes.SWITCH)
|
||||
ip_prefix = Ipv4Prefix("10.0.0.0/24")
|
||||
interface_one = ip_prefix.addr(node_one)
|
||||
message = coreapi.CoreLinkMessage.create(
|
||||
|
@ -313,8 +313,8 @@ class TestGui:
|
|||
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
coretlv.handle_message(message)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 1
|
||||
|
||||
|
@ -326,58 +326,58 @@ class TestGui:
|
|||
(LinkTlvs.INTERFACE2_NUMBER, 0),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
switch_node = coreserver.session.get_node(switch)
|
||||
switch_node = coretlv.session.get_node(switch)
|
||||
all_links = switch_node.all_link_data(0)
|
||||
assert len(all_links) == 0
|
||||
|
||||
def test_session_update(self, coreserver):
|
||||
session_id = coreserver.session.id
|
||||
def test_session_update(self, coretlv):
|
||||
session_id = coretlv.session.id
|
||||
name = "test"
|
||||
message = coreapi.CoreSessionMessage.create(
|
||||
0, [(SessionTlvs.NUMBER, str(session_id)), (SessionTlvs.NAME, name)]
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.name == name
|
||||
assert coretlv.session.name == name
|
||||
|
||||
def test_session_query(self, coreserver):
|
||||
coreserver.request_handler.dispatch_replies = mock.MagicMock()
|
||||
def test_session_query(self, coretlv):
|
||||
coretlv.dispatch_replies = mock.MagicMock()
|
||||
message = coreapi.CoreSessionMessage.create(MessageFlags.STRING.value, [])
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
args, _ = coreserver.request_handler.dispatch_replies.call_args
|
||||
args, _ = coretlv.dispatch_replies.call_args
|
||||
replies = args[0]
|
||||
assert len(replies) == 1
|
||||
|
||||
def test_session_join(self, coreserver):
|
||||
coreserver.request_handler.dispatch_replies = mock.MagicMock()
|
||||
session_id = coreserver.session.id
|
||||
def test_session_join(self, coretlv):
|
||||
coretlv.dispatch_replies = mock.MagicMock()
|
||||
session_id = coretlv.session.id
|
||||
message = coreapi.CoreSessionMessage.create(
|
||||
MessageFlags.ADD.value, [(SessionTlvs.NUMBER, str(session_id))]
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.request_handler.session.id == session_id
|
||||
assert coretlv.session.id == session_id
|
||||
|
||||
def test_session_delete(self, coreserver):
|
||||
assert len(coreserver.server.coreemu.sessions) == 1
|
||||
session_id = coreserver.session.id
|
||||
def test_session_delete(self, coretlv):
|
||||
assert len(coretlv.coreemu.sessions) == 1
|
||||
session_id = coretlv.session.id
|
||||
message = coreapi.CoreSessionMessage.create(
|
||||
MessageFlags.DELETE.value, [(SessionTlvs.NUMBER, str(session_id))]
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert len(coreserver.server.coreemu.sessions) == 0
|
||||
assert len(coretlv.coreemu.sessions) == 0
|
||||
|
||||
def test_file_hook_add(self, coreserver):
|
||||
def test_file_hook_add(self, coretlv):
|
||||
state = EventTypes.DATACOLLECT_STATE.value
|
||||
assert coreserver.session._hooks.get(state) is None
|
||||
assert coretlv.session._hooks.get(state) is None
|
||||
file_name = "test.sh"
|
||||
file_data = "echo hello"
|
||||
message = coreapi.CoreFileMessage.create(
|
||||
|
@ -389,16 +389,16 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
hooks = coreserver.session._hooks.get(state)
|
||||
hooks = coretlv.session._hooks.get(state)
|
||||
assert len(hooks) == 1
|
||||
name, data = hooks[0]
|
||||
assert file_name == name
|
||||
assert file_data == data
|
||||
|
||||
def test_file_service_file_set(self, coreserver):
|
||||
node = coreserver.session.add_node()
|
||||
def test_file_service_file_set(self, coretlv):
|
||||
node = coretlv.session.add_node()
|
||||
service = "DefaultRoute"
|
||||
file_name = "defaultroute.sh"
|
||||
file_data = "echo hello"
|
||||
|
@ -412,16 +412,16 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
service_file = coreserver.session.services.get_service_file(
|
||||
service_file = coretlv.session.services.get_service_file(
|
||||
node, service, file_name
|
||||
)
|
||||
assert file_data == service_file.data
|
||||
|
||||
def test_file_node_file_copy(self, coreserver):
|
||||
def test_file_node_file_copy(self, request, coretlv):
|
||||
file_name = "/var/log/test/node.log"
|
||||
node = coreserver.session.add_node()
|
||||
node = coretlv.session.add_node()
|
||||
node.makenodedir()
|
||||
file_data = "echo hello"
|
||||
message = coreapi.CoreFileMessage.create(
|
||||
|
@ -433,17 +433,17 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
if not request.config.getoption("mock"):
|
||||
directory, basename = os.path.split(file_name)
|
||||
created_directory = directory[1:].replace("/", ".")
|
||||
create_path = os.path.join(node.nodedir, created_directory, basename)
|
||||
assert os.path.exists(create_path)
|
||||
|
||||
def test_exec_node_tty(self, coreserver):
|
||||
coreserver.request_handler.dispatch_replies = mock.MagicMock()
|
||||
node = coreserver.session.add_node()
|
||||
node.startup()
|
||||
def test_exec_node_tty(self, coretlv):
|
||||
coretlv.dispatch_replies = mock.MagicMock()
|
||||
node = coretlv.session.add_node()
|
||||
message = coreapi.CoreExecMessage.create(
|
||||
MessageFlags.TTY.value,
|
||||
[
|
||||
|
@ -453,49 +453,51 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
args, _ = coreserver.request_handler.dispatch_replies.call_args
|
||||
args, _ = coretlv.dispatch_replies.call_args
|
||||
replies = args[0]
|
||||
assert len(replies) == 1
|
||||
|
||||
def test_exec_local_command(self, coreserver):
|
||||
coreserver.request_handler.dispatch_replies = mock.MagicMock()
|
||||
node = coreserver.session.add_node()
|
||||
node.startup()
|
||||
def test_exec_local_command(self, request, coretlv):
|
||||
if request.config.getoption("mock"):
|
||||
pytest.skip("mocking calls")
|
||||
|
||||
coretlv.dispatch_replies = mock.MagicMock()
|
||||
node = coretlv.session.add_node()
|
||||
cmd = "echo hello"
|
||||
message = coreapi.CoreExecMessage.create(
|
||||
MessageFlags.TEXT.value | MessageFlags.LOCAL.value,
|
||||
[
|
||||
(ExecuteTlvs.NODE, node.id),
|
||||
(ExecuteTlvs.NUMBER, 1),
|
||||
(ExecuteTlvs.COMMAND, "echo hello"),
|
||||
(ExecuteTlvs.COMMAND, cmd),
|
||||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
args, _ = coreserver.request_handler.dispatch_replies.call_args
|
||||
args, _ = coretlv.dispatch_replies.call_args
|
||||
replies = args[0]
|
||||
assert len(replies) == 1
|
||||
|
||||
def test_exec_node_command(self, coreserver):
|
||||
coreserver.request_handler.dispatch_replies = mock.MagicMock()
|
||||
node = coreserver.session.add_node()
|
||||
node.startup()
|
||||
def test_exec_node_command(self, coretlv):
|
||||
coretlv.dispatch_replies = mock.MagicMock()
|
||||
node = coretlv.session.add_node()
|
||||
cmd = "echo hello"
|
||||
message = coreapi.CoreExecMessage.create(
|
||||
MessageFlags.TEXT.value,
|
||||
[
|
||||
(ExecuteTlvs.NODE, node.id),
|
||||
(ExecuteTlvs.NUMBER, 1),
|
||||
(ExecuteTlvs.COMMAND, "echo hello"),
|
||||
(ExecuteTlvs.COMMAND, cmd),
|
||||
],
|
||||
)
|
||||
node.cmd = MagicMock(return_value="hello")
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
args, _ = coreserver.request_handler.dispatch_replies.call_args
|
||||
replies = args[0]
|
||||
assert len(replies) == 1
|
||||
node.cmd.assert_called_with(cmd)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"state",
|
||||
|
@ -507,16 +509,16 @@ class TestGui:
|
|||
EventTypes.DEFINITION_STATE,
|
||||
],
|
||||
)
|
||||
def test_event_state(self, coreserver, state):
|
||||
def test_event_state(self, coretlv, state):
|
||||
message = coreapi.CoreEventMessage.create(0, [(EventTlvs.TYPE, state.value)])
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.state == state.value
|
||||
assert coretlv.session.state == state.value
|
||||
|
||||
def test_event_schedule(self, coreserver):
|
||||
coreserver.session.add_event = mock.MagicMock()
|
||||
node = coreserver.session.add_node()
|
||||
def test_event_schedule(self, coretlv):
|
||||
coretlv.session.add_event = mock.MagicMock()
|
||||
node = coretlv.session.add_node()
|
||||
message = coreapi.CoreEventMessage.create(
|
||||
MessageFlags.ADD.value,
|
||||
[
|
||||
|
@ -528,37 +530,37 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.session.add_event.assert_called_once()
|
||||
coretlv.session.add_event.assert_called_once()
|
||||
|
||||
def test_event_save_xml(self, coreserver, tmpdir):
|
||||
xml_file = tmpdir.join("session.xml")
|
||||
def test_event_save_xml(self, coretlv, tmpdir):
|
||||
xml_file = tmpdir.join("coretlv.session.xml")
|
||||
file_path = xml_file.strpath
|
||||
coreserver.session.add_node()
|
||||
coretlv.session.add_node()
|
||||
message = coreapi.CoreEventMessage.create(
|
||||
0,
|
||||
[(EventTlvs.TYPE, EventTypes.FILE_SAVE.value), (EventTlvs.NAME, file_path)],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert os.path.exists(file_path)
|
||||
|
||||
def test_event_open_xml(self, coreserver, tmpdir):
|
||||
xml_file = tmpdir.join("session.xml")
|
||||
def test_event_open_xml(self, coretlv, tmpdir):
|
||||
xml_file = tmpdir.join("coretlv.session.xml")
|
||||
file_path = xml_file.strpath
|
||||
node = coreserver.session.add_node()
|
||||
coreserver.session.save_xml(file_path)
|
||||
coreserver.session.delete_node(node.id)
|
||||
node = coretlv.session.add_node()
|
||||
coretlv.session.save_xml(file_path)
|
||||
coretlv.session.delete_node(node.id)
|
||||
message = coreapi.CoreEventMessage.create(
|
||||
0,
|
||||
[(EventTlvs.TYPE, EventTypes.FILE_OPEN.value), (EventTlvs.NAME, file_path)],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.get_node(node.id)
|
||||
assert coretlv.session.get_node(node.id)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"state",
|
||||
|
@ -570,10 +572,9 @@ class TestGui:
|
|||
EventTypes.RECONFIGURE,
|
||||
],
|
||||
)
|
||||
def test_event_service(self, coreserver, state):
|
||||
coreserver.session.broadcast_event = mock.MagicMock()
|
||||
node = coreserver.session.add_node()
|
||||
node.startup()
|
||||
def test_event_service(self, coretlv, state):
|
||||
coretlv.session.broadcast_event = mock.MagicMock()
|
||||
node = coretlv.session.add_node()
|
||||
message = coreapi.CoreEventMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -583,9 +584,9 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.session.broadcast_event.assert_called_once()
|
||||
coretlv.session.broadcast_event.assert_called_once()
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"state",
|
||||
|
@ -597,69 +598,60 @@ class TestGui:
|
|||
EventTypes.RECONFIGURE,
|
||||
],
|
||||
)
|
||||
def test_event_mobility(self, coreserver, state):
|
||||
def test_event_mobility(self, coretlv, state):
|
||||
message = coreapi.CoreEventMessage.create(
|
||||
0, [(EventTlvs.TYPE, state.value), (EventTlvs.NAME, "mobility:ns2script")]
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
def test_register_gui(self, coreserver):
|
||||
coreserver.request_handler.master = False
|
||||
def test_register_gui(self, coretlv):
|
||||
message = coreapi.CoreRegMessage.create(0, [(RegisterTlvs.GUI, "gui")])
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
|
||||
assert coreserver.request_handler.master is True
|
||||
|
||||
def test_register_xml(self, coreserver, tmpdir):
|
||||
xml_file = tmpdir.join("session.xml")
|
||||
def test_register_xml(self, coretlv, tmpdir):
|
||||
xml_file = tmpdir.join("coretlv.session.xml")
|
||||
file_path = xml_file.strpath
|
||||
node = coreserver.session.add_node()
|
||||
coreserver.session.save_xml(file_path)
|
||||
coreserver.session.delete_node(node.id)
|
||||
node = coretlv.session.add_node()
|
||||
coretlv.session.save_xml(file_path)
|
||||
coretlv.session.delete_node(node.id)
|
||||
message = coreapi.CoreRegMessage.create(
|
||||
0, [(RegisterTlvs.EXECUTE_SERVER, file_path)]
|
||||
)
|
||||
coreserver.session.instantiate()
|
||||
coretlv.session.instantiate()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.server.coreemu.sessions[2].get_node(node.id)
|
||||
assert coretlv.coreemu.sessions[1].get_node(node.id)
|
||||
|
||||
def test_register_python(self, coreserver, tmpdir):
|
||||
def test_register_python(self, coretlv, tmpdir):
|
||||
xml_file = tmpdir.join("test.py")
|
||||
file_path = xml_file.strpath
|
||||
with open(file_path, "w") as f:
|
||||
f.write("coreemu = globals()['coreemu']\n")
|
||||
f.write("session = coreemu.sessions[1]\n")
|
||||
f.write(f"session = coreemu.sessions[{coretlv.session.id}]\n")
|
||||
f.write("session.add_node()\n")
|
||||
message = coreapi.CoreRegMessage.create(
|
||||
0, [(RegisterTlvs.EXECUTE_SERVER, file_path)]
|
||||
)
|
||||
coreserver.session.instantiate()
|
||||
coretlv.session.instantiate()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert len(coreserver.session.nodes) == 1
|
||||
assert len(coretlv.session.nodes) == 1
|
||||
|
||||
def test_config_all(self, coreserver):
|
||||
node = coreserver.session.add_node()
|
||||
def test_config_all(self, coretlv):
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
MessageFlags.ADD.value,
|
||||
[
|
||||
(ConfigTlvs.OBJECT, "all"),
|
||||
(ConfigTlvs.NODE, node.id),
|
||||
(ConfigTlvs.TYPE, ConfigFlags.RESET.value),
|
||||
],
|
||||
[(ConfigTlvs.OBJECT, "all"), (ConfigTlvs.TYPE, ConfigFlags.RESET.value)],
|
||||
)
|
||||
coreserver.session.location.reset = mock.MagicMock()
|
||||
coretlv.session.location.refxyz = (10, 10, 10)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.session.location.reset.assert_called_once()
|
||||
assert coretlv.session.location.refxyz == (0, 0, 0)
|
||||
|
||||
def test_config_options_request(self, coreserver):
|
||||
def test_config_options_request(self, coretlv):
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -667,13 +659,13 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_broadcast_config = mock.MagicMock()
|
||||
coretlv.handle_broadcast_config = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_broadcast_config.assert_called_once()
|
||||
coretlv.handle_broadcast_config.assert_called_once()
|
||||
|
||||
def test_config_options_update(self, coreserver):
|
||||
def test_config_options_update(self, coretlv):
|
||||
test_key = "test"
|
||||
test_value = "test"
|
||||
values = {test_key: test_value}
|
||||
|
@ -686,11 +678,11 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.options.get_config(test_key) == test_value
|
||||
assert coretlv.session.options.get_config(test_key) == test_value
|
||||
|
||||
def test_config_location_reset(self, coreserver):
|
||||
def test_config_location_reset(self, coretlv):
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -698,13 +690,13 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.RESET.value),
|
||||
],
|
||||
)
|
||||
coreserver.session.location.refxyz = (10, 10, 10)
|
||||
coretlv.session.location.refxyz = (10, 10, 10)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.location.refxyz == (0, 0, 0)
|
||||
assert coretlv.session.location.refxyz == (0, 0, 0)
|
||||
|
||||
def test_config_location_update(self, coreserver):
|
||||
def test_config_location_update(self, coretlv):
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -714,13 +706,13 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.location.refxyz == (10, 10, 0.0)
|
||||
assert coreserver.session.location.refgeo == (70, 50, 0)
|
||||
assert coreserver.session.location.refscale == 0.5
|
||||
assert coretlv.session.location.refxyz == (10, 10, 0.0)
|
||||
assert coretlv.session.location.refgeo == (70, 50, 0)
|
||||
assert coretlv.session.location.refscale == 0.5
|
||||
|
||||
def test_config_metadata_request(self, coreserver):
|
||||
def test_config_metadata_request(self, coretlv):
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -728,13 +720,13 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_broadcast_config = mock.MagicMock()
|
||||
coretlv.handle_broadcast_config = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_broadcast_config.assert_called_once()
|
||||
coretlv.handle_broadcast_config.assert_called_once()
|
||||
|
||||
def test_config_metadata_update(self, coreserver):
|
||||
def test_config_metadata_update(self, coretlv):
|
||||
test_key = "test"
|
||||
test_value = "test"
|
||||
values = {test_key: test_value}
|
||||
|
@ -747,11 +739,11 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.metadata.get_config(test_key) == test_value
|
||||
assert coretlv.session.metadata[test_key] == test_value
|
||||
|
||||
def test_config_broker_request(self, coreserver):
|
||||
def test_config_broker_request(self, coretlv):
|
||||
server = "test"
|
||||
host = "10.0.0.1"
|
||||
port = 50000
|
||||
|
@ -763,13 +755,13 @@ class TestGui:
|
|||
(ConfigTlvs.VALUES, f"{server}:{host}:{port}"),
|
||||
],
|
||||
)
|
||||
coreserver.session.distributed.add_server = mock.MagicMock()
|
||||
coretlv.session.distributed.add_server = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.session.distributed.add_server.assert_called_once_with(server, host)
|
||||
coretlv.session.distributed.add_server.assert_called_once_with(server, host)
|
||||
|
||||
def test_config_services_request_all(self, coreserver):
|
||||
def test_config_services_request_all(self, coretlv):
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -777,14 +769,14 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_broadcast_config = mock.MagicMock()
|
||||
coretlv.handle_broadcast_config = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_broadcast_config.assert_called_once()
|
||||
coretlv.handle_broadcast_config.assert_called_once()
|
||||
|
||||
def test_config_services_request_specific(self, coreserver):
|
||||
node = coreserver.session.add_node()
|
||||
def test_config_services_request_specific(self, coretlv):
|
||||
node = coretlv.session.add_node()
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -794,14 +786,14 @@ class TestGui:
|
|||
(ConfigTlvs.OPAQUE, "service:DefaultRoute"),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_broadcast_config = mock.MagicMock()
|
||||
coretlv.handle_broadcast_config = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_broadcast_config.assert_called_once()
|
||||
coretlv.handle_broadcast_config.assert_called_once()
|
||||
|
||||
def test_config_services_request_specific_file(self, coreserver):
|
||||
node = coreserver.session.add_node()
|
||||
def test_config_services_request_specific_file(self, coretlv):
|
||||
node = coretlv.session.add_node()
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -811,16 +803,16 @@ class TestGui:
|
|||
(ConfigTlvs.OPAQUE, "service:DefaultRoute:defaultroute.sh"),
|
||||
],
|
||||
)
|
||||
coreserver.session.broadcast_file = mock.MagicMock()
|
||||
coretlv.session.broadcast_file = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.session.broadcast_file.assert_called_once()
|
||||
coretlv.session.broadcast_file.assert_called_once()
|
||||
|
||||
def test_config_services_reset(self, coreserver):
|
||||
node = coreserver.session.add_node()
|
||||
def test_config_services_reset(self, coretlv):
|
||||
node = coretlv.session.add_node()
|
||||
service = "DefaultRoute"
|
||||
coreserver.session.services.set_service(node.id, service)
|
||||
coretlv.session.services.set_service(node.id, service)
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -828,14 +820,14 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.RESET.value),
|
||||
],
|
||||
)
|
||||
assert coreserver.session.services.get_service(node.id, service) is not None
|
||||
assert coretlv.session.services.get_service(node.id, service) is not None
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.services.get_service(node.id, service) is None
|
||||
assert coretlv.session.services.get_service(node.id, service) is None
|
||||
|
||||
def test_config_services_set(self, coreserver):
|
||||
node = coreserver.session.add_node()
|
||||
def test_config_services_set(self, coretlv):
|
||||
node = coretlv.session.add_node()
|
||||
service = "DefaultRoute"
|
||||
values = {"meta": "metadata"}
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
|
@ -848,14 +840,14 @@ class TestGui:
|
|||
(ConfigTlvs.VALUES, dict_to_str(values)),
|
||||
],
|
||||
)
|
||||
assert coreserver.session.services.get_service(node.id, service) is None
|
||||
assert coretlv.session.services.get_service(node.id, service) is None
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert coreserver.session.services.get_service(node.id, service) is not None
|
||||
assert coretlv.session.services.get_service(node.id, service) is not None
|
||||
|
||||
def test_config_mobility_reset(self, coreserver):
|
||||
wlan = coreserver.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
def test_config_mobility_reset(self, coretlv):
|
||||
wlan = coretlv.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -863,15 +855,15 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.RESET.value),
|
||||
],
|
||||
)
|
||||
coreserver.session.mobility.set_model_config(wlan.id, BasicRangeModel.name, {})
|
||||
assert len(coreserver.session.mobility.node_configurations) == 1
|
||||
coretlv.session.mobility.set_model_config(wlan.id, BasicRangeModel.name, {})
|
||||
assert len(coretlv.session.mobility.node_configurations) == 1
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
assert len(coreserver.session.mobility.node_configurations) == 0
|
||||
assert len(coretlv.session.mobility.node_configurations) == 0
|
||||
|
||||
def test_config_mobility_model_request(self, coreserver):
|
||||
wlan = coreserver.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
def test_config_mobility_model_request(self, coretlv):
|
||||
wlan = coretlv.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -880,14 +872,14 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_broadcast_config = mock.MagicMock()
|
||||
coretlv.handle_broadcast_config = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_broadcast_config.assert_called_once()
|
||||
coretlv.handle_broadcast_config.assert_called_once()
|
||||
|
||||
def test_config_mobility_model_update(self, coreserver):
|
||||
wlan = coreserver.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
def test_config_mobility_model_update(self, coretlv):
|
||||
wlan = coretlv.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
config_key = "range"
|
||||
config_value = "1000"
|
||||
values = {config_key: config_value}
|
||||
|
@ -901,15 +893,15 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
config = coreserver.session.mobility.get_model_config(
|
||||
config = coretlv.session.mobility.get_model_config(
|
||||
wlan.id, BasicRangeModel.name
|
||||
)
|
||||
assert config[config_key] == config_value
|
||||
|
||||
def test_config_emane_model_request(self, coreserver):
|
||||
wlan = coreserver.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
def test_config_emane_model_request(self, coretlv):
|
||||
wlan = coretlv.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -918,14 +910,14 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_broadcast_config = mock.MagicMock()
|
||||
coretlv.handle_broadcast_config = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_broadcast_config.assert_called_once()
|
||||
coretlv.handle_broadcast_config.assert_called_once()
|
||||
|
||||
def test_config_emane_model_update(self, coreserver):
|
||||
wlan = coreserver.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
def test_config_emane_model_update(self, coretlv):
|
||||
wlan = coretlv.session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
config_key = "distance"
|
||||
config_value = "50051"
|
||||
values = {config_key: config_value}
|
||||
|
@ -939,14 +931,14 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
config = coreserver.session.emane.get_model_config(
|
||||
config = coretlv.session.emane.get_model_config(
|
||||
wlan.id, EmaneIeee80211abgModel.name
|
||||
)
|
||||
assert config[config_key] == config_value
|
||||
|
||||
def test_config_emane_request(self, coreserver):
|
||||
def test_config_emane_request(self, coretlv):
|
||||
message = coreapi.CoreConfMessage.create(
|
||||
0,
|
||||
[
|
||||
|
@ -954,13 +946,13 @@ class TestGui:
|
|||
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
|
||||
],
|
||||
)
|
||||
coreserver.request_handler.handle_broadcast_config = mock.MagicMock()
|
||||
coretlv.handle_broadcast_config = mock.MagicMock()
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
coreserver.request_handler.handle_broadcast_config.assert_called_once()
|
||||
coretlv.handle_broadcast_config.assert_called_once()
|
||||
|
||||
def test_config_emane_update(self, coreserver):
|
||||
def test_config_emane_update(self, coretlv):
|
||||
config_key = "eventservicedevice"
|
||||
config_value = "eth4"
|
||||
values = {config_key: config_value}
|
||||
|
@ -973,7 +965,7 @@ class TestGui:
|
|||
],
|
||||
)
|
||||
|
||||
coreserver.request_handler.handle_message(message)
|
||||
coretlv.handle_message(message)
|
||||
|
||||
config = coreserver.session.emane.get_configs()
|
||||
config = coretlv.session.emane.get_configs()
|
||||
assert config[config_key] == config_value
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
import os
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from core import utils
|
||||
from core.emulator.emudata import NodeOptions
|
||||
from core.emulator.enumerations import NodeTypes
|
||||
from core.errors import CoreError
|
||||
|
||||
MODELS = ["router", "host", "PC", "mdr"]
|
||||
|
||||
NET_TYPES = [NodeTypes.SWITCH, NodeTypes.HUB, NodeTypes.WIRELESS_LAN]
|
||||
|
||||
|
||||
|
@ -17,20 +12,15 @@ class TestNodes:
|
|||
@pytest.mark.parametrize("model", MODELS)
|
||||
def test_node_add(self, session, model):
|
||||
# given
|
||||
node_options = NodeOptions(model=model)
|
||||
options = NodeOptions(model=model)
|
||||
|
||||
# when
|
||||
node = session.add_node(node_options=node_options)
|
||||
|
||||
# give time for node services to boot
|
||||
time.sleep(1)
|
||||
node = session.add_node(options=options)
|
||||
|
||||
# then
|
||||
assert node
|
||||
assert os.path.exists(node.nodedir)
|
||||
assert node.alive()
|
||||
assert node.up
|
||||
assert node.cmd("ip address show lo")
|
||||
|
||||
def test_node_update(self, session):
|
||||
# given
|
||||
|
@ -40,7 +30,7 @@ class TestNodes:
|
|||
update_options.set_position(x=position_value, y=position_value)
|
||||
|
||||
# when
|
||||
session.update_node(node.id, update_options)
|
||||
session.edit_node(node.id, update_options)
|
||||
|
||||
# then
|
||||
assert node.position.x == position_value
|
||||
|
@ -67,4 +57,3 @@ class TestNodes:
|
|||
# then
|
||||
assert node
|
||||
assert node.up
|
||||
assert utils.cmd(f"brctl show {node.brname}")
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import os
|
||||
|
||||
import pytest
|
||||
from mock import MagicMock
|
||||
|
||||
from core.errors import CoreCommandError
|
||||
from core.services.coreservices import CoreService, ServiceDependencies, ServiceManager
|
||||
|
||||
_PATH = os.path.abspath(os.path.dirname(__file__))
|
||||
|
@ -88,7 +90,7 @@ class TestServices:
|
|||
assert node.services
|
||||
assert len(node.services) == total_service + 2
|
||||
|
||||
def test_service_file(self, session):
|
||||
def test_service_file(self, request, session):
|
||||
# given
|
||||
ServiceManager.add_services(_SERVICES_PATH)
|
||||
my_service = ServiceManager.get(SERVICE_ONE)
|
||||
|
@ -100,6 +102,7 @@ class TestServices:
|
|||
session.services.create_service_files(node, my_service)
|
||||
|
||||
# then
|
||||
if not request.config.getoption("mock"):
|
||||
assert os.path.exists(file_path)
|
||||
|
||||
def test_service_validate(self, session):
|
||||
|
@ -121,6 +124,7 @@ class TestServices:
|
|||
my_service = ServiceManager.get(SERVICE_TWO)
|
||||
node = session.add_node()
|
||||
session.services.create_service_files(node, my_service)
|
||||
node.cmd = MagicMock(side_effect=CoreCommandError(-1, "invalid"))
|
||||
|
||||
# when
|
||||
status = session.services.validate_service(node, my_service)
|
||||
|
@ -147,6 +151,7 @@ class TestServices:
|
|||
my_service = ServiceManager.get(SERVICE_TWO)
|
||||
node = session.add_node()
|
||||
session.services.create_service_files(node, my_service)
|
||||
node.cmd = MagicMock(side_effect=CoreCommandError(-1, "invalid"))
|
||||
|
||||
# when
|
||||
status = session.services.startup_service(node, my_service, wait=True)
|
||||
|
@ -173,6 +178,7 @@ class TestServices:
|
|||
my_service = ServiceManager.get(SERVICE_TWO)
|
||||
node = session.add_node()
|
||||
session.services.create_service_files(node, my_service)
|
||||
node.cmd = MagicMock(side_effect=CoreCommandError(-1, "invalid"))
|
||||
|
||||
# when
|
||||
status = session.services.stop_service(node, my_service)
|
||||
|
@ -216,17 +222,6 @@ class TestServices:
|
|||
custom_service_two = session.services.get_service(node_two.id, my_service.name)
|
||||
session.services.create_service_files(node_two, custom_service_two)
|
||||
|
||||
# then
|
||||
file_path_one = node_one.hostfilename(file_name)
|
||||
assert os.path.exists(file_path_one)
|
||||
with open(file_path_one, "r") as custom_file:
|
||||
assert custom_file.read() == file_data_one
|
||||
|
||||
file_path_two = node_two.hostfilename(file_name)
|
||||
assert os.path.exists(file_path_two)
|
||||
with open(file_path_two, "r") as custom_file:
|
||||
assert custom_file.read() == file_data_two
|
||||
|
||||
def test_service_import(self):
|
||||
"""
|
||||
Test importing a custom service.
|
||||
|
|
|
@ -108,8 +108,8 @@ class TestXml:
|
|||
ptp_node = session.add_node(_type=NodeTypes.PEER_TO_PEER)
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions(model="host")
|
||||
node_one = session.add_node(node_options=node_options)
|
||||
options = NodeOptions(model="host")
|
||||
node_one = session.add_node(options=options)
|
||||
node_two = session.add_node()
|
||||
|
||||
# link nodes to ptp net
|
||||
|
@ -174,10 +174,10 @@ class TestXml:
|
|||
session.mobility.set_model(wlan_node, BasicRangeModel, {"test": "1"})
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions()
|
||||
node_options.set_position(0, 0)
|
||||
node_one = session.create_wireless_node(node_options=node_options)
|
||||
node_two = session.create_wireless_node(node_options=node_options)
|
||||
options = NodeOptions(model="mdr")
|
||||
options.set_position(0, 0)
|
||||
node_one = session.add_node(options=options)
|
||||
node_two = session.add_node(options=options)
|
||||
|
||||
# link nodes
|
||||
for node in [node_one, node_two]:
|
||||
|
|
|
@ -108,13 +108,12 @@ Examples for configuring custom emane model settings.
|
|||
# create session and emane network
|
||||
coreemu = CoreEmu()
|
||||
session = coreemu.create_session()
|
||||
emane_network = session.create_emane_network(
|
||||
model=EmaneIeee80211abgModel,
|
||||
geo_reference=(47.57917, -122.13232, 2.00000)
|
||||
)
|
||||
emane_network.setposition(x=80, y=50)
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions()
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(_type=NodeTypes.EMANE, options=options)
|
||||
|
||||
# set custom emane model config
|
||||
config = {}
|
||||
session.emane.set_model_config(emane_network.id, EmaneIeee80211abgModel.name, config)
|
||||
session.emane.set_model(emane_network, EmaneIeee80211abgModel, config)
|
||||
```
|
||||
|
|
|
@ -60,7 +60,7 @@ class CoreNs3Node(CoreNode, ns.network.Node):
|
|||
|
||||
if not isinstance(net, CoreNs3Net):
|
||||
return CoreNode.newnetif(self, net, addrlist, hwaddr, ifindex, ifname)
|
||||
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
|
||||
ifindex = self.newtuntap(ifindex, ifname)
|
||||
self.attachnet(ifindex, net)
|
||||
netif = self.netif(ifindex)
|
||||
netif.sethwaddr(hwaddr)
|
||||
|
@ -68,7 +68,7 @@ class CoreNs3Node(CoreNode, ns.network.Node):
|
|||
netif.addaddr(addr)
|
||||
|
||||
addrstr = netif.addrlist[0]
|
||||
(addr, mask) = addrstr.split('/')
|
||||
addr, mask = addrstr.split('/')
|
||||
tap = net._tapdevs[netif]
|
||||
tap.SetAttribute(
|
||||
"IpAddress",
|
||||
|
@ -76,9 +76,9 @@ class CoreNs3Node(CoreNode, ns.network.Node):
|
|||
)
|
||||
tap.SetAttribute(
|
||||
"Netmask",
|
||||
ns.network.Ipv4MaskValue(ns.network.Ipv4Mask("/" + mask))
|
||||
ns.network.Ipv4MaskValue(ns.network.Ipv4Mask(f"/{mask}"))
|
||||
)
|
||||
ns.core.Simulator.Schedule(ns.core.Time('0'), netif.install)
|
||||
ns.core.Simulator.Schedule(ns.core.Time("0"), netif.install)
|
||||
return ifindex
|
||||
|
||||
def getns3position(self):
|
||||
|
@ -118,7 +118,7 @@ class CoreNs3Net(CoreNetworkBase):
|
|||
type = "wlan"
|
||||
|
||||
def __init__(
|
||||
self, session, _id=None, name=None, start=True, server=None, policy=None
|
||||
self, session, _id=None, name=None, start=True, server=None
|
||||
):
|
||||
CoreNetworkBase.__init__(self, session, _id, name, start, server)
|
||||
self.tapbridge = ns.tap_bridge.TapBridgeHelper()
|
||||
|
|
Loading…
Reference in a new issue