refactored some future naming to be more consistent, added new data objects to pass into coreemu api to help make scripting easier, set sessions to master by default now

This commit is contained in:
Blake J. Harnden 2018-04-24 16:24:54 -07:00
parent 1404ca19c5
commit 3ea885e2eb
9 changed files with 550 additions and 449 deletions

View file

@ -9,8 +9,8 @@ from core.coreobj import PyCoreNode, PyCoreNet
from core.data import NodeData
from core.emane.nodes import EmaneNode
from core.enumerations import NodeTypes, EventTypes, LinkTypes
from core.future.futuredata import InterfaceData, LinkOptions
from core.misc import nodeutils
from core.misc.ipaddress import Ipv4Prefix
from core.netns.nodes import CoreNode
from core.session import Session
from core.xml.xmlparser import core_document_parser
@ -36,62 +36,13 @@ signal.signal(signal.SIGUSR1, signal_handler)
signal.signal(signal.SIGUSR2, signal_handler)
class InterfaceData(object):
"""
Convenience class for storing interface data.
"""
def __init__(self, _id, name, mac, ip4, ip4_mask, ip6, ip6_mask):
"""
Creates an InterfaceData object.
:param int _id:
:param str name:
:param str mac:
:param str ip4:
:param int ip4_mask:
:param str ip6:
:param int ip6_mask:
"""
self.id = _id
self.name = name
self.mac = mac
self.ip4 = ip4
self.ip4_mask = ip4_mask
self.ip6 = ip6
self.ip6_mask = ip6_mask
def has_ip4(self):
return all([self.ip4, self.ip4_mask])
def has_ip6(self):
return all([self.ip6, self.ip6_mask])
def ip4_address(self):
if self.has_ip4():
return "%s/%s" % (self.ip4, self.ip4_mask)
else:
return None
def ip6_address(self):
if self.has_ip6():
return "%s/%s" % (self.ip6, self.ip6_mask)
else:
return None
def get_addresses(self):
ip4 = self.ip4_address()
ip6 = self.ip6_address()
return [i for i in [ip4, ip6] if i]
def get_interfaces(link_data):
"""
Creates interface data objects for the interfaces defined within link data.
:param core.data.LinkData link_data: data to create interface data from
:return: interface one and two data
:rtype: tuple[InterfaceData]
:rtype: tuple[core.future.futuredata.InterfaceData]
"""
interface_one = InterfaceData(
_id=link_data.interface1_id,
@ -120,7 +71,7 @@ def create_interface(node, network, interface_data):
:param node: node to create interface for
:param network: network to associate interface with
:param InterfaceData interface_data: interface data
:param core.future.futuredata.InterfaceData interface_data: interface data
:return: created interface
"""
node.newnetif(
@ -133,24 +84,24 @@ def create_interface(node, network, interface_data):
return node.netif(interface_data.id, network)
def link_config(network, interface, link_data, devname=None, interface_two=None):
def link_config(network, interface, link_options, devname=None, interface_two=None):
"""
Convenience method for configuring a link,
:param network: network to configure link for
:param interface: interface to configure
:param core.data.LinkData link_data: data to configure link with
:param core.future.futuredata.LinkOptions link_options: data to configure link with
:param str devname: device name, default is None
:param interface_two: other interface associated, default is None
:return: nothing
"""
config = {
"netif": interface,
"bw": link_data.bandwidth,
"delay": link_data.delay,
"loss": link_data.per,
"duplicate": link_data.dup,
"jitter": link_data.jitter,
"bw": link_options.bandwidth,
"delay": link_options.delay,
"loss": link_options.per,
"duplicate": link_options.dup,
"jitter": link_options.jitter,
"netif2": interface_two
}
@ -192,12 +143,6 @@ class IdGen(object):
return self.id
class FutureIpv4Prefix(Ipv4Prefix):
def get_address(self, node_id):
address = self.addr(node_id)
return "%s/%s" % (address, self.prefixlen)
class FutureSession(Session):
def __init__(self, session_id, config=None, persistent=True, mkdir=True):
super(FutureSession, self).__init__(session_id, config, persistent, mkdir)
@ -214,39 +159,37 @@ class FutureSession(Session):
"host": ("DefaultRoute", "SSH"),
}
def link_nodes(self, link_data):
def _link_nodes(self, node_one_id, node_two_id):
"""
Convenience method for retrieving nodes within link data.
:param core.data.LinkData link_data: data to retrieve nodes from
:return: nodes, network nodes if presetn, and tunnel
:param int node_one_id: node one id
:param int node_two_id: node two id
:return: nodes, network nodes if present, and tunnel if present
:rtype: tuple
"""
logger.info("link message between node1(%s:%s) and node2(%s:%s)",
link_data.node1_id, link_data.interface1_id, link_data.node2_id, link_data.interface2_id)
logger.info("link message between node1(%s) and node2(%s)", node_one_id, node_two_id)
# values to fill
net_one = None
net_two = None
# retrieve node one
n1_id = link_data.node1_id
n2_id = link_data.node2_id
node_one = self.get_object(n1_id)
node_two = self.get_object(n2_id)
node_one = self.get_object(node_one_id)
node_two = self.get_object(node_two_id)
# both node ids are provided
tunnel = self.broker.gettunnel(n1_id, n2_id)
tunnel = self.broker.gettunnel(node_one_id, node_two_id)
logger.info("tunnel between nodes: %s", tunnel)
if nodeutils.is_node(tunnel, NodeTypes.TAP_BRIDGE):
net_one = tunnel
if tunnel.remotenum == n1_id:
if tunnel.remotenum == node_one_id:
node_one = None
else:
node_two = None
# physical node connected via gre tap tunnel
elif tunnel:
if tunnel.remotenum == n1_id:
if tunnel.remotenum == node_one_id:
node_one = None
else:
node_two = None
@ -296,18 +239,19 @@ class FutureSession(Session):
else:
raise ValueError("no common network found for wireless link/unlink")
def link_add(self, link_data):
def add_link(self, node_one_id, node_two_id, interface_one=None, interface_two=None, link_options=LinkOptions()):
"""
Add a link between nodes.
:param core.data.LinkData link_data: data to create a link with
:return: nothing
:param int node_one_id: node one id
:param int node_two_id: node two id
:param core.future.futuredata.InterfaceData interface_one: node one interface data, defaults to none
:param core.future.futuredata.InterfaceData interface_two: node two interface data, defaults to none
:param core.future.futuredata.LinkOptions link_options: data for creating link, defaults to no options
:return:
"""
# interface data
interface_one_data, interface_two_data = get_interfaces(link_data)
# get node objects identified by link data
node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data)
node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id)
if node_one:
node_one.lock.acquire()
@ -316,7 +260,7 @@ class FutureSession(Session):
try:
# wireless link
if link_data.link_type == LinkTypes.WIRELESS.value:
if link_options.type == LinkTypes.WIRELESS:
objects = [node_one, node_two, net_one, net_two]
self._link_wireless(objects, connect=True)
# wired link
@ -329,14 +273,14 @@ class FutureSession(Session):
# node to network
if node_one and net_one:
interface = create_interface(node_one, net_one, interface_one_data)
link_config(net_one, interface, link_data)
interface = create_interface(node_one, net_one, interface_one)
link_config(net_one, interface, link_options)
# network to node
if node_two and net_one:
interface = create_interface(node_two, net_one, interface_two_data)
if not link_data.unidirectional:
link_config(net_one, interface, link_data)
interface = create_interface(node_two, net_one, interface_two)
if not link_options.unidirectional:
link_config(net_one, interface, link_options)
# network to network
if net_one and net_two:
@ -345,23 +289,23 @@ class FutureSession(Session):
else:
interface = net_one.linknet(net_two)
link_config(net_one, interface, link_data)
link_config(net_one, interface, link_options)
if not link_data.unidirectional:
if not link_options.unidirectional:
interface.swapparams("_params_up")
link_config(net_two, interface, link_data, devname=interface.name)
link_config(net_two, interface, link_options, devname=interface.name)
interface.swapparams("_params_up")
# a tunnel node was found for the nodes
addresses = []
if not node_one and net_one:
addresses.extend(interface_one_data.get_addresses())
if not node_one and all([net_one, interface_one]):
addresses.extend(interface_one.get_addresses())
if not node_two and net_two:
addresses.extend(interface_two_data.get_addresses())
if not node_two and all([net_two, interface_two]):
addresses.extend(interface_two.get_addresses())
# tunnel node logic
key = link_data.key
key = link_options.key
if key and nodeutils.is_node(net_one, NodeTypes.TUNNEL):
net_one.setkey(key)
if addresses:
@ -374,31 +318,35 @@ class FutureSession(Session):
# physical node connected with tunnel
if not net_one and not net_two and (node_one or node_two):
if node_one and nodeutils.is_node(node_one, NodeTypes.PHYSICAL):
addresses = interface_one_data.get_addresses()
node_one.adoptnetif(tunnel, link_data.interface1_id, link_data.interface1_mac, addresses)
link_config(node_one, tunnel, link_data)
addresses = interface_one.get_addresses()
node_one.adoptnetif(tunnel, interface_one.id, interface_one.mac, addresses)
link_config(node_one, tunnel, link_options)
elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL):
addresses = interface_two_data.get_addresses()
node_two.adoptnetif(tunnel, link_data.interface2_id, link_data.interface2_mac, addresses)
link_config(node_two, tunnel, link_data)
addresses = interface_two.get_addresses()
node_two.adoptnetif(tunnel, interface_two.id, interface_two.mac, addresses)
link_config(node_two, tunnel, link_options)
finally:
if node_one:
node_one.lock.release()
if node_two:
node_two.lock.release()
def link_delete(self, link_data):
def delete_link(self, node_one_id, node_two_id, interface_one_id, interface_two_id, link_type=LinkTypes.WIRED):
"""
Delete a link between nodes.
:param core.data.LinkData link_data: data to delete link with
:param int node_one_id: node one id
:param int node_two_id: node two id
:param int interface_one_id: interface id for node one
:param int interface_two_id: interface id for node two
:param core.enumerations.LinkTypes link_type: link type to delete
:return: nothing
"""
# interface data
interface_one_data, interface_two_data = get_interfaces(link_data)
# interface_one_data, interface_two_data = get_interfaces(link_data)
# get node objects identified by link data
node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data)
node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id)
if node_one:
node_one.lock.acquire()
@ -407,7 +355,7 @@ class FutureSession(Session):
try:
# wireless link
if link_data.link_type == LinkTypes.WIRELESS.value:
if link_type == LinkTypes.WIRELESS:
objects = [node_one, node_two, net_one, net_two]
self._link_wireless(objects, connect=False)
# wired link
@ -415,8 +363,8 @@ class FutureSession(Session):
if all([node_one, node_two]):
# TODO: fix this for the case where ifindex[1,2] are not specified
# a wired unlink event, delete the connecting bridge
interface_one = node_one.netif(interface_one_data.id)
interface_two = node_two.netif(interface_two_data.id)
interface_one = node_one.netif(interface_one_id)
interface_two = node_two.netif(interface_two_id)
# get interfaces from common network, if no network node
# otherwise get interfaces between a node and network
@ -446,18 +394,22 @@ class FutureSession(Session):
if node_two:
node_two.lock.release()
def link_update(self, link_data):
def update_link(self, node_one_id, node_two_id, link_options, interface_one_id=None, interface_two_id=None):
"""
Update link information between nodes.
:param core.data.LinkData link_data: data to update link with
:param int node_one_id: node one id
:param int node_two_id: node two id
:param int interface_one_id: interface id for node one
:param int interface_two_id: interface id for node two
:param core.future.futuredata.LinkOptions link_options: data to update link with
:return: nothing
"""
# interface data
interface_one_data, interface_two_data = get_interfaces(link_data)
# interface_one_data, interface_two_data = get_interfaces(link_data)
# get node objects identified by link data
node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data)
node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id)
if node_one:
node_one.lock.acquire()
@ -466,7 +418,7 @@ class FutureSession(Session):
try:
# wireless link
if link_data.link_type == LinkTypes.WIRELESS.value:
if link_options.type == LinkTypes.WIRELESS.value:
raise ValueError("cannot update wireless link")
else:
if not node_one and not node_two:
@ -484,37 +436,37 @@ class FutureSession(Session):
if upstream:
interface.swapparams("_params_up")
link_config(net_one, interface, link_data, devname=interface.name)
link_config(net_one, interface, link_options, devname=interface.name)
interface.swapparams("_params_up")
else:
link_config(net_one, interface, link_data)
link_config(net_one, interface, link_options)
if not link_data.unidirectional:
if not link_options.unidirectional:
if upstream:
link_config(net_two, interface, link_data)
link_config(net_two, interface, link_options)
else:
interface.swapparams("_params_up")
link_config(net_two, interface, link_data, devname=interface.name)
link_config(net_two, interface, link_options, devname=interface.name)
interface.swapparams("_params_up")
else:
raise ValueError("modify link for unknown nodes")
elif not node_one:
# node1 = layer 2node, node2 = layer3 node
interface = node_two.netif(interface_two_data.id, net_one)
link_config(net_one, interface, link_data)
interface = node_two.netif(interface_two_id, net_one)
link_config(net_one, interface, link_options)
elif not node_two:
# node2 = layer 2node, node1 = layer3 node
interface = node_one.netif(interface_one_data.id, net_one)
link_config(net_one, interface, link_data)
interface = node_one.netif(interface_one_id, net_one)
link_config(net_one, interface, link_options)
else:
common_networks = node_one.commonnets(node_two)
for net_one, interface_one, interface_two in common_networks:
if interface_one_data.id and interface_one_data.id != node_one.getifindex(interface_one):
if interface_one_id and interface_one_id != node_one.getifindex(interface_one):
continue
link_config(net_one, interface_one, link_data, interface_two=interface_two)
if not link_data.unidirectional:
link_config(net_one, interface_two, link_data, interface_two=interface_one)
link_config(net_one, interface_one, link_options, interface_two=interface_two)
if not link_options.unidirectional:
link_config(net_one, interface_two, link_options, interface_two=interface_one)
else:
raise ValueError("no common network found")
finally:
@ -523,30 +475,29 @@ class FutureSession(Session):
if node_two:
node_two.lock.release()
def node_add(self, node_data):
def add_node(self, node_options):
"""
Add a node to the session, based on the provided node data.
:param core.data.NodeData node_data: data to create node with
:return: nothing
:param core.future.futuredata.NodeOptions node_options: data to create node with
:return: created node
"""
# retrieve node class for given node type
try:
node_type = NodeTypes(node_data.node_type)
node_class = nodeutils.get_node_class(node_type)
node_class = nodeutils.get_node_class(node_options.type)
except KeyError:
logger.error("invalid node type to create: %s", node_data.node_type)
logger.error("invalid node type to create: %s", node_options.type)
return None
# set node start based on current session state, override and check when rj45
start = self.state > EventTypes.DEFINITION_STATE.value
enable_rj45 = getattr(self.options, "enablerj45", "0") == "1"
if node_type == NodeTypes.RJ45 and not enable_rj45:
if node_options.type == NodeTypes.RJ45 and not enable_rj45:
start = False
# determine node id
node_id = node_data.id
node_id = node_options.id
if not node_id:
while True:
node_id = self.node_id_gen.next()
@ -554,7 +505,7 @@ class FutureSession(Session):
break
# generate name if not provided
name = node_data.name
name = node_options.name
if not name:
name = "%s%s" % (node_class.__name__, node_id)
@ -563,18 +514,18 @@ class FutureSession(Session):
node = self.add_object(cls=node_class, objid=node_id, name=name, start=start)
# set node attributes
node.type = node_data.model or "router"
node.icon = node_data.icon
node.canvas = node_data.canvas
node.opaque = node_data.opaque
node.type = node_options.model or "router"
node.icon = node_options.icon
node.canvas = node_options.canvas
node.opaque = node_options.opaque
# set node position and broadcast it
self.node_set_position(node, node_data)
self.set_node_position(node, node_options)
# add services to default and physical nodes only
services = node_data.services
if node_type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]:
logger.info("setting model (%s) with services (%s)", node.type, services)
if node_options.type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]:
logger.info("setting model (%s) with services (%s)", node.type, node_options.services)
services = "|".join(node_options.services) or None
self.services.addservicestonode(node, node.type, services)
# boot nodes if created after runtime, LcxNodes, Physical, and RJ45 are all PyCoreNodes
@ -586,35 +537,35 @@ class FutureSession(Session):
# TODO: common method to both Physical and LxcNodes, but not the common PyCoreNode
node.boot()
# return node id, in case it was generated
return node_id
return node
def node_update(self, node_data):
def update_node(self, node_options):
"""
Update node information.
:param core.data.NodeData node_data: data to update node with
:param core.future.futuredata.NodeOptions node_options: data to update node with
:return: nothing
"""
try:
# get node to update
node = self.get_object(node_data.id)
node = self.get_object(node_options.id)
# set node position and broadcast it
self.node_set_position(node, node_data)
self.set_node_position(node, node_options)
# update attributes
node.canvas = node_data.canvas
node.icon = node_data.icon
node.canvas = node_options.canvas
node.icon = node_options.icon
except KeyError:
logger.error("failure to update node that does not exist: %s", node_data.id)
logger.error("failure to update node that does not exist: %s", node_options.id)
def node_delete(self, node_id):
def delete_node(self, node_id):
"""
Delete a node from the session and check if session should shutdown, if no nodes are left.
:param int node_id:
:return: True if node deleted, False otherwise
:rtype: bool
"""
# delete node and check for session shutdown if a node was removed
result = self.custom_delete_object(node_id)
@ -622,20 +573,20 @@ class FutureSession(Session):
self.check_shutdown()
return result
def node_set_position(self, node, node_data):
def set_node_position(self, node, node_options):
"""
Set position for a node, use lat/lon/alt if needed.
:param node: node to set position for
:param NodeData node_data: data for node
:param core.future.futuredata.NodeOptions node_options: data for node
:return: nothing
"""
# extract location values
x = node_data.x_position
y = node_data.y_position
lat = node_data.latitude
lon = node_data.longitude
alt = node_data.altitude
x = node_options.x
y = node_options.y
lat = node_options.lat
lon = node_options.lon
alt = node_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])
@ -741,7 +692,7 @@ class FutureSession(Session):
doc = core_document_writer(self, version)
doc.writexml(file_name)
def hook_add(self, state, file_name, source_name, data):
def add_hook(self, state, file_name, source_name, data):
"""
Store a hook from a received file message.
@ -755,7 +706,7 @@ class FutureSession(Session):
state = ":%s" % state
self.set_hook(state, file_name, source_name, data)
def node_service_file(self, node_id, service_name, file_name, source_name, data):
def add_node_service_file(self, node_id, service_name, file_name, source_name, data):
"""
Add a service file for a node.
@ -770,7 +721,7 @@ class FutureSession(Session):
service_name = ":%s" % service_name
self.services.setservicefile(node_id, service_name, file_name, source_name, data)
def node_file(self, node_id, source_name, file_name, data):
def add_node_file(self, node_id, source_name, file_name, data):
"""
Add a file to a node.
@ -874,16 +825,16 @@ class FutureSession(Session):
self.set_emane_model(emane_network, model)
return emane_network
def set_emane_model(self, emane_node, model):
def set_emane_model(self, emane_node, emane_model):
"""
Set emane model for a given emane node.
:param emane_node: emane node to set model for
:param model: emane model to set
:param emane_model: emane model to set
:return: nothing
"""
values = list(model.getdefaultvalues())
self.emane.setconfig(emane_node.objid, model.name, values)
values = list(emane_model.getdefaultvalues())
self.emane.setconfig(emane_node.objid, emane_model.name, values)
class CoreEmu(object):
@ -921,7 +872,7 @@ class CoreEmu(object):
session.shutdown()
self.sessions.clear()
def create_session(self, _id=None, master=False):
def create_session(self, _id=None, master=True):
"""
Create a new CORE session, set to master if running standalone.
@ -981,15 +932,16 @@ class CoreEmu(object):
for common_network, interface_one, interface_two in node.commonnets(network):
common_network.link(interface_one, interface_two)
def add_interface(self, network, node, prefix):
def add_interface(self, network, node, prefixes):
"""
Convenience method for adding an interface with a prefix based on node id.
:param network: network to add interface with
:param node: node to add interface to
:param prefix: prefix to get address from for interface
:param core.future.futuredata.IpPrefixes prefixes: to get address from for interface
:return: created interface
"""
address = prefix.get_address(node.objid)
interface_index = node.newnetif(network, [address])
interface_data = prefixes.create_interface(node)
logger.info("adding interface: %s", interface_data.get_addresses())
interface_index = node.newnetif(network, interface_data.get_addresses(), ifindex=interface_data.id)
return node.netif(interface_index)

View file

@ -0,0 +1,225 @@
from core.enumerations import LinkTypes
from core.misc.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress
class NodeOptions(object):
"""
Options for creating and updating nodes within core.
"""
def __init__(self, _type=None, _id=None, name=None, model=None):
"""
Create a NodeOptions object.
:param core.enumerations.NodeType _type: type of node to create
:param int _id: id for node being created, defaults to generated id
:param str name: name of node, defaults to node class name postfix with its id
:param str model: model to use for this node, defines services
"""
self.id = _id
self.name = name
self.type = _type
self.model = model
self.canvas = None
self.icon = None
self.opaque = None
self.services = []
self.x = None
self.y = None
self.lat = None
self.lon = None
self.alt = None
self.emulation_id = None
self.emulation_server = None
def set_position(self, x, y):
"""
Convenience method for setting position.
:param int x: x position
:param int y: y position
:return: nothing
"""
self.x = x
self.y = y
def set_location(self, lat, lon, alt):
"""
Convenience method for setting location.
:param float lat: latitude
:param float lon: longitude
:param float alt: altitude
:return: nothing
"""
self.lat = lat
self.lon = lon
self.alt = alt
class LinkOptions(object):
"""
Options for creating and updating links within core.
"""
def __init__(self, _type=LinkTypes.WIRED):
"""
Create a LinkOptions object.
:param core.enumerations.LinkTypes _type: type of link, defaults to wired
"""
self.type = _type
self.session = None
self.delay = None
self.bandwidth = None
self.per = None
self.dup = None
self.jitter = None
self.mer = None
self.burst = None
self.mburst = None
self.gui_attributes = None
self.unidirectional = None
self.emulation_id = None
self.network_id = None
self.key = None
self.opaque = None
class IpPrefixes(object):
"""
Convenience class to help generate IP4 and IP6 addresses for nodes within CORE.
"""
def __init__(self, ip4_prefix=None, ip6_prefix=None):
"""
Creates an IpPrefixes object.
:param str ip4_prefix: ip4 prefix to use for generation
:param str ip6_prefix: ip6 prefix to use for generation
:raises ValueError: when both ip4 and ip6 prefixes have not been provided
"""
if not ip4_prefix and not ip6_prefix:
raise ValueError("ip4 or ip6 must be provided")
self.ip4 = None
if ip4_prefix:
self.ip4 = Ipv4Prefix(ip4_prefix)
self.ip6 = None
if ip6_prefix:
self.ip6 = Ipv6Prefix(ip6_prefix)
def ip4_address(self, node):
"""
Convenience method to return the IP4 address for a node.
:param node: node to get IP4 address for
:return: IP4 address or None
:rtype: str
"""
if not self.ip4:
raise ValueError("ip4 prefixes have not been set")
return str(self.ip4.addr(node.objid))
def ip6_address(self, node):
"""
Convenience method to return the IP6 address for a node.
:param node: node to get IP6 address for
:return: IP4 address or None
:rtype: str
"""
if not self.ip6:
raise ValueError("ip6 prefixes have not been set")
return str(self.ip6.addr(node.objid))
def create_interface(self, node, name=None, mac=None):
"""
Creates interface data for linking nodes, using the nodes unique id for generation, along with a random
mac address, unless provided.
:param core.coreobj.PyCoreNode node: node to create interface for
:param str name: name to set for interface, default is eth{id}
:param str mac: mac address to use for this interface, default is random generation
:return: new interface data for the provided node
:rtype: InterfaceData
"""
# interface id
inteface_id = node.newifindex()
# generate ip4 data
ip4 = None
ip4_mask = None
if self.ip4:
ip4 = str(self.ip4.addr(node.objid))
ip4_mask = self.ip4.prefixlen
# generate ip6 data
ip6 = None
ip6_mask = None
if self.ip6:
ip6 = str(self.ip6.addr(node.objid))
ip6_mask = self.ip6.prefixlen
# random mac
if not mac:
mac = str(MacAddress.random())
return InterfaceData(
_id=inteface_id,
name=name,
ip4=ip4,
ip4_mask=ip4_mask,
ip6=ip6,
ip6_mask=ip6_mask,
mac=mac
)
class InterfaceData(object):
"""
Convenience class for storing interface data.
"""
def __init__(self, _id, name, mac, ip4, ip4_mask, ip6, ip6_mask):
"""
Creates an InterfaceData object.
:param int _id:
:param str name:
:param str mac:
:param str ip4:
:param int ip4_mask:
:param str ip6:
:param int ip6_mask:
"""
self.id = _id
self.name = name
self.mac = mac
self.ip4 = ip4
self.ip4_mask = ip4_mask
self.ip6 = ip6
self.ip6_mask = ip6_mask
def has_ip4(self):
return all([self.ip4, self.ip4_mask])
def has_ip6(self):
return all([self.ip6, self.ip6_mask])
def ip4_address(self):
if self.has_ip4():
return "%s/%s" % (self.ip4, self.ip4_mask)
else:
return None
def ip6_address(self):
if self.has_ip6():
return "%s/%s" % (self.ip6, self.ip6_mask)
else:
return None
def get_addresses(self):
ip4 = self.ip4_address()
ip6 = self.ip6_address()
return [i for i in [ip4, ip6] if i]

View file

@ -14,10 +14,9 @@ import time
from core import logger
from core.api import coreapi
from core.coreserver import CoreServer
from core.data import ConfigData, LinkData
from core.data import ConfigData
from core.data import EventData
from core.data import NodeData
from core.enumerations import ConfigTlvs
from core.enumerations import ConfigTlvs, LinkTypes
from core.enumerations import EventTlvs
from core.enumerations import EventTypes
from core.enumerations import ExceptionTlvs
@ -30,6 +29,7 @@ from core.enumerations import NodeTlvs
from core.enumerations import NodeTypes
from core.enumerations import RegisterTlvs
from core.enumerations import SessionTlvs
from core.future.futuredata import NodeOptions, LinkOptions, InterfaceData
from core.misc import nodeutils
from core.misc import structutils
from core.misc import utils
@ -566,7 +566,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
port = self.request.getpeername()[1]
# TODO: add shutdown handler for session
self.session = self.coreemu.create_session(port)
self.session = self.coreemu.create_session(port, master=False)
# self.session.shutdown_handlers.append(self.session_shutdown)
logger.info("created new session for client: %s", self.session.session_id)
@ -642,44 +642,58 @@ class FutureHandler(SocketServer.BaseRequestHandler):
logger.warn("ignoring invalid message: add and delete flag both set")
return ()
# create node data from message data
node_data = NodeData(
id=message.get_tlv(NodeTlvs.NUMBER.value),
x_position=message.get_tlv(NodeTlvs.X_POSITION.value),
y_position=message.get_tlv(NodeTlvs.Y_POSITION.value),
canvas=message.get_tlv(NodeTlvs.CANVAS.value),
icon=message.get_tlv(NodeTlvs.ICON.value),
latitude=message.get_tlv(NodeTlvs.LATITUDE.value),
longitude=message.get_tlv(NodeTlvs.LONGITUDE.value),
altitude=message.get_tlv(NodeTlvs.ALTITUDE.value),
node_type=message.get_tlv(NodeTlvs.TYPE.value),
node_type = None
node_type_value = message.get_tlv(NodeTlvs.TYPE.value)
if node_type_value is not None:
node_type = NodeTypes(node_type_value)
node_options = NodeOptions(
_type=node_type,
_id=message.get_tlv(NodeTlvs.NUMBER.value),
name=message.get_tlv(NodeTlvs.NAME.value),
model=message.get_tlv(NodeTlvs.MODEL.value),
opaque=message.get_tlv(NodeTlvs.OPAQUE.value),
services=message.get_tlv(NodeTlvs.SERVICES.value),
model=message.get_tlv(NodeTlvs.MODEL.value)
)
node_options.set_position(
x=message.get_tlv(NodeTlvs.X_POSITION.value),
y=message.get_tlv(NodeTlvs.Y_POSITION.value)
)
node_options.set_location(
lat=message.get_tlv(NodeTlvs.LATITUDE.value),
lon=message.get_tlv(NodeTlvs.LONGITUDE.value),
alt=message.get_tlv(NodeTlvs.ALTITUDE.value)
)
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)
services = message.get_tlv(NodeTlvs.SERVICES.value)
if services:
node_options.services = services.split("|")
if message.flags & MessageFlags.ADD.value:
node_id = self.session.node_add(node_data)
if node_id:
node = self.session.add_node(node_options)
if node:
if message.flags & MessageFlags.STRING.value:
self.node_status_request[node_id] = True
self.node_status_request[node.objid] = True
if self.session.state == EventTypes.RUNTIME_STATE.value:
self.send_node_emulation_id(node_id)
self.send_node_emulation_id(node.objid)
elif message.flags & MessageFlags.DELETE.value:
with self._shutdown_lock:
result = self.session.node_delete(node_data.id)
result = self.session.delete_node(node_options.id)
# if we deleted a node broadcast out its removal
if result and message.flags & MessageFlags.STRING.value:
tlvdata = ""
tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_data.id)
tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_options.id)
flags = MessageFlags.DELETE.value | MessageFlags.LOCAL.value
replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata))
# node update
else:
self.session.node_update(node_data)
self.session.update_node(node_options)
return replies
@ -690,47 +704,56 @@ class FutureHandler(SocketServer.BaseRequestHandler):
:param coreapi.CoreLinkMessage message: link message to handle
:return: link message replies
"""
link_data = LinkData(
session=message.get_tlv(LinkTlvs.SESSION.value),
link_type=message.get_tlv(LinkTlvs.TYPE.value),
node1_id=message.get_tlv(LinkTlvs.N1_NUMBER.value),
node2_id=message.get_tlv(LinkTlvs.N2_NUMBER.value),
delay=message.get_tlv(LinkTlvs.DELAY.value),
bandwidth=message.get_tlv(LinkTlvs.BANDWIDTH.value),
per=message.get_tlv(LinkTlvs.PER.value),
dup=message.get_tlv(LinkTlvs.DUP.value),
jitter=message.get_tlv(LinkTlvs.JITTER.value),
mer=message.get_tlv(LinkTlvs.MER.value),
burst=message.get_tlv(LinkTlvs.BURST.value),
mburst=message.get_tlv(LinkTlvs.MBURST.value),
gui_attributes=message.get_tlv(LinkTlvs.GUI_ATTRIBUTES.value),
unidirectional=message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value),
emulation_id=message.get_tlv(LinkTlvs.EMULATION_ID.value),
network_id=message.get_tlv(LinkTlvs.NETWORK_ID.value),
key=message.get_tlv(LinkTlvs.KEY.value),
opaque=message.get_tlv(LinkTlvs.OPAQUE.value),
interface1_id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value),
interface1_name=message.get_tlv(LinkTlvs.INTERFACE1_NAME.value),
interface1_ip4=message.get_tlv(LinkTlvs.INTERFACE1_IP4.value),
interface1_ip4_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value),
interface1_mac=message.get_tlv(LinkTlvs.INTERFACE1_MAC.value),
interface1_ip6=message.get_tlv(LinkTlvs.INTERFACE1_IP6.value),
interface1_ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value),
interface2_id=message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value),
interface2_name=message.get_tlv(LinkTlvs.INTERFACE2_NAME.value),
interface2_ip4=message.get_tlv(LinkTlvs.INTERFACE2_IP4.value),
interface2_ip4_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value),
interface2_mac=message.get_tlv(LinkTlvs.INTERFACE2_MAC.value),
interface2_ip6=message.get_tlv(LinkTlvs.INTERFACE2_IP6.value),
interface2_ip6_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP6_MASK.value),
node_one_id = message.get_tlv(LinkTlvs.N1_NUMBER.value)
node_two_id = message.get_tlv(LinkTlvs.N2_NUMBER.value)
interface_one = InterfaceData(
_id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value),
name=message.get_tlv(LinkTlvs.INTERFACE1_NAME.value),
mac=message.get_tlv(LinkTlvs.INTERFACE1_MAC.value),
ip4=message.get_tlv(LinkTlvs.INTERFACE1_IP4.value),
ip4_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value),
ip6=message.get_tlv(LinkTlvs.INTERFACE1_IP6.value),
ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value),
)
interface_two = InterfaceData(
_id=message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value),
name=message.get_tlv(LinkTlvs.INTERFACE2_NAME.value),
mac=message.get_tlv(LinkTlvs.INTERFACE2_MAC.value),
ip4=message.get_tlv(LinkTlvs.INTERFACE2_IP4.value),
ip4_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value),
ip6=message.get_tlv(LinkTlvs.INTERFACE2_IP6.value),
ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value),
)
link_type = None
link_type_value = message.get_tlv(LinkTlvs.TYPE.value)
if link_type_value is not None:
link_type = LinkTypes(link_type_value)
link_options = LinkOptions(_type=link_type)
link_options.delay = message.get_tlv(LinkTlvs.DELAY.value)
link_options.bandwidth = message.get_tlv(LinkTlvs.BANDWIDTH.value)
link_options.session = message.get_tlv(LinkTlvs.SESSION.value)
link_options.per = message.get_tlv(LinkTlvs.PER.value)
link_options.dup = message.get_tlv(LinkTlvs.DUP.value)
link_options.jitter = message.get_tlv(LinkTlvs.JITTER.value)
link_options.mer = message.get_tlv(LinkTlvs.MER.value)
link_options.burst = message.get_tlv(LinkTlvs.BURST.value)
link_options.mburst = message.get_tlv(LinkTlvs.MBURST.value)
link_options.gui_attributes = message.get_tlv(LinkTlvs.GUI_ATTRIBUTES.value)
link_options.unidirectional = message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value)
link_options.emulation_id = message.get_tlv(LinkTlvs.EMULATION_ID.value)
link_options.network_id = message.get_tlv(LinkTlvs.NETWORK_ID.value)
link_options.key = message.get_tlv(LinkTlvs.KEY.value)
link_options.opaque = message.get_tlv(LinkTlvs.OPAQUE.value)
if message.flags & MessageFlags.ADD.value:
self.session.link_add(link_data)
self.session.add_link(node_one_id, node_two_id, interface_one, interface_two, link_options)
elif message.flags & MessageFlags.DELETE.value:
self.session.link_delete(link_data)
self.session.delete_link(node_one_id, node_two_id, interface_one.id, interface_two.id)
else:
self.session.link_update(link_data)
self.session.update_link(node_one_id, node_two_id, interface_one.id, interface_two.id, link_options)
return ()
@ -829,7 +852,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
file_name = sys.argv[0]
if os.path.splitext(file_name)[1].lower() == ".xml":
session = self.coreemu.create_session()
session = self.coreemu.create_session(master=False)
try:
session.open_xml(file_name, start=True)
except:
@ -962,7 +985,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
if file_type is not None:
if file_type.startswith("service:"):
_, service_name = file_type.split(':')[:2]
self.session.node_service_file(node_num, service_name, file_name, source_name, data)
self.session.add_node_service_file(node_num, service_name, file_name, source_name, data)
return ()
elif file_type.startswith("hook:"):
_, state = file_type.split(':')[:2]
@ -970,7 +993,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
logger.error("error setting hook having state '%s'", state)
return ()
state = int(state)
self.session.hook_add(state, file_name, source_name, data)
self.session.add_hook(state, file_name, source_name, data)
return ()
# writing a file to the host

View file

@ -6,12 +6,13 @@ import datetime
import parser
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.future.coreemu import FutureIpv4Prefix, CoreEmu
from core.future.coreemu import CoreEmu
from core.future.futuredata import IpPrefixes
def example(options):
# ip generator for example
prefix = FutureIpv4Prefix("10.83.0.0/16")
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
# create emulator instance for creating sessions and utility methods
coreemu = CoreEmu()
@ -27,8 +28,8 @@ def example(options):
# create nodes
for i in xrange(options.nodes):
node = session.create_emane_node()
coreemu.add_interface(emane_network, node, prefix)
node.setposition(x=150 * (i + 1), y=150)
coreemu.add_interface(emane_network, node, prefixes)
# instantiate session
session.instantiate()
@ -39,7 +40,7 @@ def example(options):
# shutdown session
raw_input("press enter to exit...")
session.shutdown()
coreemu.shutdown()
def main():

View file

@ -8,13 +8,14 @@
import datetime
import parser
from core.future.coreemu import FutureIpv4Prefix, CoreEmu
from core.future.coreemu import CoreEmu
from core.future.futuredata import IpPrefixes
from core.netns.nodes import CoreNode, SwitchNode
def example(options):
# ip generator for example
prefix = FutureIpv4Prefix("10.83.0.0/16")
prefixes = IpPrefixes("10.83.0.0/16")
# create emulator instance for creating sessions and utility methods
coreemu = CoreEmu()
@ -26,7 +27,7 @@ def example(options):
# create nodes
for _ in xrange(options.nodes):
node = session.create_node(cls=CoreNode)
coreemu.add_interface(switch_network, node, prefix)
coreemu.add_interface(switch_network, node, prefixes)
# instantiate session
session.instantiate()
@ -37,13 +38,13 @@ def example(options):
print "starting iperf server on node: %s" % first_node.name
first_node.cmd(["iperf", "-s", "-D"])
address = str(prefix.addr(first_node.objid))
address = prefixes.ip4_address(first_node)
print "node %s connecting to %s" % (last_node.name, address)
last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address])
first_node.cmd(["killall", "-9", "iperf"])
# shutdown session
session.shutdown()
coreemu.shutdown()
def main():

View file

@ -8,41 +8,32 @@
import datetime
import parser
from core.data import NodeData, LinkData
from core.enumerations import NodeTypes, EventTypes
from core.future.coreemu import FutureIpv4Prefix, CoreEmu
from core.future.coreemu import CoreEmu
from core.future.futuredata import IpPrefixes, NodeOptions
def example(options):
# ip generator for example
prefix = FutureIpv4Prefix("10.83.0.0/16")
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
# create emulator instance for creating sessions and utility methods
coreemu = CoreEmu()
session = coreemu.create_session(master=True)
session = coreemu.create_session()
# must be in configuration state for nodes to start, when using "node_add" below
session.set_state(EventTypes.CONFIGURATION_STATE.value)
# create switch network node
node_data = NodeData(node_type=NodeTypes.SWITCH.value)
switch_id = session.node_add(node_data)
node_options = NodeOptions(_type=NodeTypes.SWITCH)
switch = session.add_node(node_options)
# create nodes
for _ in xrange(options.nodes):
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_id = session.node_add(node_data)
node = session.get_object(node_id)
inteface_index = node.newifindex()
address = prefix.addr(node_id)
link_data = LinkData(
node1_id=node_id,
node2_id=switch_id,
interface1_id=inteface_index,
interface1_ip4=str(address),
interface1_ip4_mask=prefix.prefixlen,
)
session.link_add(link_data)
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node = session.add_node(node_options)
interface = prefixes.create_interface(node)
session.add_link(node.objid, switch.objid, interface_one=interface)
# instantiate session
session.instantiate()
@ -53,9 +44,9 @@ def example(options):
print "starting iperf server on node: %s" % first_node.name
first_node.cmd(["iperf", "-s", "-D"])
address = str(prefix.addr(first_node.objid))
print "node %s connecting to %s" % (last_node.name, address)
last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address])
first_node_address = prefixes.ip4_address(first_node)
print "node %s connecting to %s" % (last_node.name, first_node_address)
last_node.client.icmd(["iperf", "-t", str(options.time), "-c", first_node_address])
first_node.cmd(["killall", "-9", "iperf"])
# shutdown session

View file

@ -5,17 +5,13 @@
# and repeat for minnodes <= n <= maxnodes with a step size of
# nodestep
import datetime
import parser
from core.data import NodeData, LinkData
from core.enumerations import NodeTypes, EventTypes
from core.future.coreemu import FutureIpv4Prefix, CoreEmu
from core.future.futuredata import IpPrefixes, NodeOptions
def example(nodes):
# ip generator for example
prefix = FutureIpv4Prefix("10.83.0.0/16")
prefixes = IpPrefixes("10.83.0.0/16")
# create emulator instance for creating sessions and utility methods
coreemu = globals()["coreemu"]
@ -25,24 +21,15 @@ def example(nodes):
session.set_state(EventTypes.CONFIGURATION_STATE.value)
# create switch network node
node_data = NodeData(node_type=NodeTypes.SWITCH.value)
switch_id = session.node_add(node_data)
node_options = NodeOptions(_type=NodeTypes.SWITCH)
switch = session.add_node(node_options)
# create nodes
for _ in xrange(nodes):
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_id = session.node_add(node_data)
node = session.get_object(node_id)
inteface_index = node.newifindex()
address = prefix.addr(node_id)
link_data = LinkData(
node1_id=node_id,
node2_id=switch_id,
interface1_id=inteface_index,
interface1_ip4=str(address),
interface1_ip4_mask=prefix.prefixlen,
)
session.link_add(link_data)
node_options = NodeOptions(_type=NodeTypes.DEFAULT.value)
node = session.add_node(node_options)
interface = prefixes.create_interface(node)
session.add_link(node.objid, switch.objid, interface_one=interface)
# instantiate session
session.instantiate()

View file

@ -8,14 +8,15 @@
import datetime
import parser
from core.future.coreemu import FutureIpv4Prefix, CoreEmu
from core.future.coreemu import CoreEmu
from core.future.futuredata import IpPrefixes
from core.mobility import BasicRangeModel
from core.netns.nodes import WlanNode, CoreNode
def example(options):
# ip generator for example
prefix = FutureIpv4Prefix("10.83.0.0/16")
prefixes = IpPrefixes("10.83.0.0/16")
# create emulator instance for creating sessions and utility methods
coreemu = CoreEmu()
@ -29,7 +30,7 @@ def example(options):
wireless_nodes = []
for _ in xrange(options.nodes):
node = session.create_node(cls=CoreNode)
coreemu.add_interface(wlan_network, node, prefix)
coreemu.add_interface(wlan_network, node, prefixes)
wireless_nodes.append(node)
# link all created nodes with the wireless network
@ -44,13 +45,13 @@ def example(options):
print "starting iperf server on node: %s" % first_node.name
first_node.cmd(["iperf", "-s", "-D"])
address = str(prefix.addr(first_node.objid))
address = prefixes.ip4_address(first_node)
print "node %s connecting to %s" % (last_node.name, address)
last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address])
first_node.cmd(["killall", "-9", "iperf"])
# shutdown session
session.shutdown()
coreemu.shutdown()
def main():

View file

@ -3,9 +3,9 @@ import time
import pytest
from core.data import NodeData, LinkData
from core.enumerations import NodeTypes, EventTypes
from core.future.coreemu import CoreEmu, FutureIpv4Prefix
from core.future.coreemu import CoreEmu
from core.future.futuredata import IpPrefixes, NodeOptions, LinkOptions
from core.misc import utils
@ -13,7 +13,7 @@ from core.misc import utils
def future_session():
# use coreemu and create a session
coreemu = CoreEmu()
session = coreemu.create_session(master=True)
session = coreemu.create_session()
session.set_state(EventTypes.CONFIGURATION_STATE.value)
# return created session
@ -41,16 +41,15 @@ class TestFuture:
@pytest.mark.parametrize("model", MODELS)
def test_node_add(self, future_session, model):
# given
node_data = NodeData(node_type=NodeTypes.DEFAULT.value, model=model)
node_options = NodeOptions(_type=NodeTypes.DEFAULT, model=model)
# when
node_id = future_session.node_add(node_data)
node = future_session.add_node(node_options)
# give time for node services to boot
time.sleep(1)
# then
node = future_session.get_object(node_id)
assert node
assert os.path.exists(node.nodedir)
assert node.alive()
@ -60,187 +59,116 @@ class TestFuture:
def test_node_update(self, future_session):
# given
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_id = future_session.node_add(node_data)
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node = future_session.add_node(node_options)
position_value = 100
update_data = NodeData(
id=node_id,
x_position=position_value,
y_position=position_value
)
update_options = NodeOptions(_id=node.objid)
update_options.set_position(x=position_value, y=position_value)
# when
future_session.node_update(update_data)
future_session.update_node(update_options)
# then
node = future_session.get_object(node_id)
assert node.position.x == position_value
assert node.position.y == position_value
def test_node_delete(self, future_session):
# given
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_id = future_session.node_add(node_data)
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node = future_session.add_node(node_options)
# when
future_session.node_delete(node_id)
future_session.delete_node(node.objid)
# then
with pytest.raises(KeyError):
future_session.get_object(node_id)
future_session.get_object(node.objid)
@pytest.mark.parametrize("net_type", NET_TYPES)
def test_net(self, future_session, net_type):
# given
node_data = NodeData(node_type=net_type.value)
node_options = NodeOptions(_type=net_type)
# when
node_id = future_session.node_add(node_data)
node = future_session.add_node(node_options)
# then
node = future_session.get_object(node_id)
assert node
assert node.up
assert utils.check_cmd(["brctl", "show", node.brname])
def test_ptp(self, future_session):
# given
prefix = FutureIpv4Prefix("10.83.0.0/16")
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_one_id = future_session.node_add(node_data)
node_two_id = future_session.node_add(node_data)
node_one = future_session.get_object(node_one_id)
inteface_one_index = node_one.newifindex()
address_one = prefix.addr(node_one_id)
node_two = future_session.get_object(node_two_id)
inteface_two_index = node_two.newifindex()
address_two = prefix.addr(node_two_id)
link_data = LinkData(
node1_id=node_one_id,
node2_id=node_two_id,
interface1_id=inteface_one_index,
interface1_ip4=str(address_one),
interface1_ip4_mask=prefix.prefixlen,
interface2_id=inteface_two_index,
interface2_ip4=str(address_two),
interface2_ip4_mask=prefix.prefixlen,
)
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node_one = future_session.add_node(node_options)
node_two = future_session.add_node(node_options)
interface_one = prefixes.create_interface(node_one)
inteface_two = prefixes.create_interface(node_two)
# when
future_session.link_add(link_data)
future_session.add_link(node_one.objid, node_two.objid, interface_one, inteface_two)
# then
assert node_one.netif(inteface_one_index)
assert node_two.netif(inteface_two_index)
assert node_one.netif(interface_one.id)
assert node_two.netif(inteface_two.id)
def test_node_to_net(self, future_session):
# given
prefix = FutureIpv4Prefix("10.83.0.0/16")
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_one = future_session.node_add(node_data)
node_data = NodeData(node_type=NodeTypes.SWITCH.value)
node_two = future_session.node_add(node_data)
node = future_session.get_object(node_one)
inteface_index = node.newifindex()
address = prefix.addr(node_one)
link_data = LinkData(
node1_id=node_one,
node2_id=node_two,
interface1_id=inteface_index,
interface1_ip4=str(address),
interface1_ip4_mask=prefix.prefixlen,
)
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node_one = future_session.add_node(node_options)
node_options = NodeOptions(_type=NodeTypes.SWITCH)
node_two = future_session.add_node(node_options)
interface_one = prefixes.create_interface(node_one)
# when
future_session.link_add(link_data)
future_session.add_link(node_one.objid, node_two.objid, interface_one)
# then
node_two = future_session.get_object(node_two)
assert node_two.all_link_data(0)
assert node.netif(inteface_index)
assert node_one.netif(interface_one.id)
def test_net_to_node(self, future_session):
# given
prefix = FutureIpv4Prefix("10.83.0.0/16")
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
node_data = NodeData(node_type=NodeTypes.SWITCH.value)
node_one = future_session.node_add(node_data)
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_two = future_session.node_add(node_data)
node = future_session.get_object(node_two)
inteface_index = node.newifindex()
address = prefix.addr(node_two)
link_data = LinkData(
node1_id=node_one,
node2_id=node_two,
interface2_id=inteface_index,
interface2_ip4=str(address),
interface2_ip4_mask=prefix.prefixlen,
)
node_options = NodeOptions(_type=NodeTypes.SWITCH)
node_one = future_session.add_node(node_options)
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node_two = future_session.add_node(node_options)
interface_two = prefixes.create_interface(node_two)
# when
future_session.link_add(link_data)
future_session.add_link(node_one.objid, node_two.objid, interface_two=interface_two)
# then
node_one = future_session.get_object(node_one)
assert node_one.all_link_data(0)
assert node.netif(inteface_index)
assert node_two.netif(interface_two.id)
def test_net_to_net(self, future_session):
# given
node_data = NodeData(node_type=NodeTypes.SWITCH.value)
node_one = future_session.node_add(node_data)
node_data = NodeData(node_type=NodeTypes.SWITCH.value)
node_two = future_session.node_add(node_data)
link_data = LinkData(
node1_id=node_one,
node2_id=node_two,
)
node_options = NodeOptions(_type=NodeTypes.SWITCH)
node_one = future_session.add_node(node_options)
node_options = NodeOptions(_type=NodeTypes.SWITCH)
node_two = future_session.add_node(node_options)
# when
future_session.link_add(link_data)
future_session.add_link(node_one.objid, node_two.objid)
# then
node_one = future_session.get_object(node_one)
assert node_one.all_link_data(0)
def test_link_update(self, future_session):
# given
prefix = FutureIpv4Prefix("10.83.0.0/16")
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_one = future_session.node_add(node_data)
node_data = NodeData(node_type=NodeTypes.SWITCH.value)
node_two = future_session.node_add(node_data)
node = future_session.get_object(node_one)
inteface_index = node.newifindex()
address = prefix.addr(node_one)
link_data = LinkData(
node1_id=node_one,
node2_id=node_two,
interface1_id=inteface_index,
interface1_ip4=str(address),
interface1_ip4_mask=prefix.prefixlen,
)
future_session.link_add(link_data)
update_data = LinkData(
node1_id=node_one,
node2_id=node_two,
interface1_id=inteface_index,
delay=50,
bandwidth=5000000,
per=25,
dup=25
)
interface = node.netif(inteface_index)
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node_one = future_session.add_node(node_options)
node_options = NodeOptions(_type=NodeTypes.SWITCH)
node_two = future_session.add_node(node_options)
interface_one = prefixes.create_interface(node_one)
future_session.add_link(node_one.objid, node_two.objid, interface_one)
interface = node_one.netif(interface_one.id)
output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname])
assert "delay" not in output
assert "rate" not in output
@ -248,7 +176,13 @@ class TestFuture:
assert "duplicate" not in output
# when
future_session.link_update(update_data)
link_options = LinkOptions()
link_options.delay = 50
link_options.bandwidth = 5000000
link_options.per = 25
link_options.dup = 25
future_session.update_link(node_one.objid, node_two.objid,
interface_one_id=interface_one.id, link_options=link_options)
# then
output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname])
@ -259,35 +193,21 @@ class TestFuture:
def test_link_delete(self, future_session):
# given
prefix = FutureIpv4Prefix("10.83.0.0/16")
node_data = NodeData(node_type=NodeTypes.DEFAULT.value)
node_one_id = future_session.node_add(node_data)
node_two_id = future_session.node_add(node_data)
node_one = future_session.get_object(node_one_id)
inteface_one_index = node_one.newifindex()
address_one = prefix.addr(node_one_id)
node_two = future_session.get_object(node_two_id)
inteface_two_index = node_two.newifindex()
address_two = prefix.addr(node_two_id)
link_data = LinkData(
node1_id=node_one_id,
node2_id=node_two_id,
interface1_id=inteface_one_index,
interface1_ip4=str(address_one),
interface1_ip4_mask=prefix.prefixlen,
interface2_id=inteface_two_index,
interface2_ip4=str(address_two),
interface2_ip4_mask=prefix.prefixlen,
)
future_session.link_add(link_data)
assert node_one.netif(inteface_one_index)
assert node_two.netif(inteface_two_index)
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node_one = future_session.add_node(node_options)
node_two = future_session.add_node(node_options)
interface_one = prefixes.create_interface(node_one)
interface_two = prefixes.create_interface(node_two)
future_session.add_link(node_one.objid, node_two.objid, interface_one, interface_two)
assert node_one.netif(interface_one.id)
assert node_two.netif(interface_two.id)
assert future_session.get_node_count() == 3
# when
future_session.link_delete(link_data)
future_session.delete_link(node_one.objid, node_two.objid, interface_one.id, interface_two.id)
# then
assert not node_one.netif(inteface_one_index)
assert not node_two.netif(inteface_two_index)
assert not node_one.netif(interface_one.id)
assert not node_two.netif(interface_two.id)
assert future_session.get_node_count() == 2