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.data import NodeData
from core.emane.nodes import EmaneNode from core.emane.nodes import EmaneNode
from core.enumerations import NodeTypes, EventTypes, LinkTypes from core.enumerations import NodeTypes, EventTypes, LinkTypes
from core.future.futuredata import InterfaceData, LinkOptions
from core.misc import nodeutils from core.misc import nodeutils
from core.misc.ipaddress import Ipv4Prefix
from core.netns.nodes import CoreNode from core.netns.nodes import CoreNode
from core.session import Session from core.session import Session
from core.xml.xmlparser import core_document_parser from core.xml.xmlparser import core_document_parser
@ -36,62 +36,13 @@ signal.signal(signal.SIGUSR1, signal_handler)
signal.signal(signal.SIGUSR2, 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): def get_interfaces(link_data):
""" """
Creates interface data objects for the interfaces defined within 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 :param core.data.LinkData link_data: data to create interface data from
:return: interface one and two data :return: interface one and two data
:rtype: tuple[InterfaceData] :rtype: tuple[core.future.futuredata.InterfaceData]
""" """
interface_one = InterfaceData( interface_one = InterfaceData(
_id=link_data.interface1_id, _id=link_data.interface1_id,
@ -120,7 +71,7 @@ def create_interface(node, network, interface_data):
:param node: node to create interface for :param node: node to create interface for
:param network: network to associate interface with :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 :return: created interface
""" """
node.newnetif( node.newnetif(
@ -133,24 +84,24 @@ def create_interface(node, network, interface_data):
return node.netif(interface_data.id, network) 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, Convenience method for configuring a link,
:param network: network to configure link for :param network: network to configure link for
:param interface: interface to configure :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 str devname: device name, default is None
:param interface_two: other interface associated, default is None :param interface_two: other interface associated, default is None
:return: nothing :return: nothing
""" """
config = { config = {
"netif": interface, "netif": interface,
"bw": link_data.bandwidth, "bw": link_options.bandwidth,
"delay": link_data.delay, "delay": link_options.delay,
"loss": link_data.per, "loss": link_options.per,
"duplicate": link_data.dup, "duplicate": link_options.dup,
"jitter": link_data.jitter, "jitter": link_options.jitter,
"netif2": interface_two "netif2": interface_two
} }
@ -192,12 +143,6 @@ class IdGen(object):
return self.id 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): class FutureSession(Session):
def __init__(self, session_id, config=None, persistent=True, mkdir=True): def __init__(self, session_id, config=None, persistent=True, mkdir=True):
super(FutureSession, self).__init__(session_id, config, persistent, mkdir) super(FutureSession, self).__init__(session_id, config, persistent, mkdir)
@ -214,39 +159,37 @@ class FutureSession(Session):
"host": ("DefaultRoute", "SSH"), "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. Convenience method for retrieving nodes within link data.
:param core.data.LinkData link_data: data to retrieve nodes from :param int node_one_id: node one id
:return: nodes, network nodes if presetn, and tunnel :param int node_two_id: node two id
:return: nodes, network nodes if present, and tunnel if present
:rtype: tuple :rtype: tuple
""" """
logger.info("link message between node1(%s:%s) and node2(%s:%s)", logger.info("link message between node1(%s) and node2(%s)", node_one_id, node_two_id)
link_data.node1_id, link_data.interface1_id, link_data.node2_id, link_data.interface2_id)
# values to fill # values to fill
net_one = None net_one = None
net_two = None net_two = None
# retrieve node one # retrieve node one
n1_id = link_data.node1_id node_one = self.get_object(node_one_id)
n2_id = link_data.node2_id node_two = self.get_object(node_two_id)
node_one = self.get_object(n1_id)
node_two = self.get_object(n2_id)
# both node ids are provided # 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) logger.info("tunnel between nodes: %s", tunnel)
if nodeutils.is_node(tunnel, NodeTypes.TAP_BRIDGE): if nodeutils.is_node(tunnel, NodeTypes.TAP_BRIDGE):
net_one = tunnel net_one = tunnel
if tunnel.remotenum == n1_id: if tunnel.remotenum == node_one_id:
node_one = None node_one = None
else: else:
node_two = None node_two = None
# physical node connected via gre tap tunnel # physical node connected via gre tap tunnel
elif tunnel: elif tunnel:
if tunnel.remotenum == n1_id: if tunnel.remotenum == node_one_id:
node_one = None node_one = None
else: else:
node_two = None node_two = None
@ -296,18 +239,19 @@ class FutureSession(Session):
else: else:
raise ValueError("no common network found for wireless link/unlink") 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. Add a link between nodes.
:param core.data.LinkData link_data: data to create a link with :param int node_one_id: node one id
:return: nothing :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 # 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: if node_one:
node_one.lock.acquire() node_one.lock.acquire()
@ -316,7 +260,7 @@ class FutureSession(Session):
try: try:
# wireless link # 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] objects = [node_one, node_two, net_one, net_two]
self._link_wireless(objects, connect=True) self._link_wireless(objects, connect=True)
# wired link # wired link
@ -329,14 +273,14 @@ class FutureSession(Session):
# node to network # node to network
if node_one and net_one: if node_one and net_one:
interface = create_interface(node_one, net_one, interface_one_data) interface = create_interface(node_one, net_one, interface_one)
link_config(net_one, interface, link_data) link_config(net_one, interface, link_options)
# network to node # network to node
if node_two and net_one: if node_two and net_one:
interface = create_interface(node_two, net_one, interface_two_data) interface = create_interface(node_two, net_one, interface_two)
if not link_data.unidirectional: if not link_options.unidirectional:
link_config(net_one, interface, link_data) link_config(net_one, interface, link_options)
# network to network # network to network
if net_one and net_two: if net_one and net_two:
@ -345,23 +289,23 @@ class FutureSession(Session):
else: else:
interface = net_one.linknet(net_two) 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") 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") interface.swapparams("_params_up")
# a tunnel node was found for the nodes # a tunnel node was found for the nodes
addresses = [] addresses = []
if not node_one and net_one: if not node_one and all([net_one, interface_one]):
addresses.extend(interface_one_data.get_addresses()) addresses.extend(interface_one.get_addresses())
if not node_two and net_two: if not node_two and all([net_two, interface_two]):
addresses.extend(interface_two_data.get_addresses()) addresses.extend(interface_two.get_addresses())
# tunnel node logic # tunnel node logic
key = link_data.key key = link_options.key
if key and nodeutils.is_node(net_one, NodeTypes.TUNNEL): if key and nodeutils.is_node(net_one, NodeTypes.TUNNEL):
net_one.setkey(key) net_one.setkey(key)
if addresses: if addresses:
@ -374,31 +318,35 @@ class FutureSession(Session):
# physical node connected with tunnel # physical node connected with tunnel
if not net_one and not net_two and (node_one or node_two): 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): if node_one and nodeutils.is_node(node_one, NodeTypes.PHYSICAL):
addresses = interface_one_data.get_addresses() addresses = interface_one.get_addresses()
node_one.adoptnetif(tunnel, link_data.interface1_id, link_data.interface1_mac, addresses) node_one.adoptnetif(tunnel, interface_one.id, interface_one.mac, addresses)
link_config(node_one, tunnel, link_data) link_config(node_one, tunnel, link_options)
elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL): elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL):
addresses = interface_two_data.get_addresses() addresses = interface_two.get_addresses()
node_two.adoptnetif(tunnel, link_data.interface2_id, link_data.interface2_mac, addresses) node_two.adoptnetif(tunnel, interface_two.id, interface_two.mac, addresses)
link_config(node_two, tunnel, link_data) link_config(node_two, tunnel, link_options)
finally: finally:
if node_one: if node_one:
node_one.lock.release() node_one.lock.release()
if node_two: if node_two:
node_two.lock.release() 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. 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 :return: nothing
""" """
# interface data # 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 # 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: if node_one:
node_one.lock.acquire() node_one.lock.acquire()
@ -407,7 +355,7 @@ class FutureSession(Session):
try: try:
# wireless link # wireless link
if link_data.link_type == LinkTypes.WIRELESS.value: if link_type == LinkTypes.WIRELESS:
objects = [node_one, node_two, net_one, net_two] objects = [node_one, node_two, net_one, net_two]
self._link_wireless(objects, connect=False) self._link_wireless(objects, connect=False)
# wired link # wired link
@ -415,8 +363,8 @@ class FutureSession(Session):
if all([node_one, node_two]): if all([node_one, node_two]):
# TODO: fix this for the case where ifindex[1,2] are not specified # TODO: fix this for the case where ifindex[1,2] are not specified
# a wired unlink event, delete the connecting bridge # a wired unlink event, delete the connecting bridge
interface_one = node_one.netif(interface_one_data.id) interface_one = node_one.netif(interface_one_id)
interface_two = node_two.netif(interface_two_data.id) interface_two = node_two.netif(interface_two_id)
# get interfaces from common network, if no network node # get interfaces from common network, if no network node
# otherwise get interfaces between a node and network # otherwise get interfaces between a node and network
@ -446,18 +394,22 @@ class FutureSession(Session):
if node_two: if node_two:
node_two.lock.release() 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. 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 :return: nothing
""" """
# interface data # 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 # 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: if node_one:
node_one.lock.acquire() node_one.lock.acquire()
@ -466,7 +418,7 @@ class FutureSession(Session):
try: try:
# wireless link # wireless link
if link_data.link_type == LinkTypes.WIRELESS.value: if link_options.type == LinkTypes.WIRELESS.value:
raise ValueError("cannot update wireless link") raise ValueError("cannot update wireless link")
else: else:
if not node_one and not node_two: if not node_one and not node_two:
@ -484,37 +436,37 @@ class FutureSession(Session):
if upstream: if upstream:
interface.swapparams("_params_up") 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") interface.swapparams("_params_up")
else: 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: if upstream:
link_config(net_two, interface, link_data) link_config(net_two, interface, link_options)
else: else:
interface.swapparams("_params_up") 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") interface.swapparams("_params_up")
else: else:
raise ValueError("modify link for unknown nodes") raise ValueError("modify link for unknown nodes")
elif not node_one: elif not node_one:
# node1 = layer 2node, node2 = layer3 node # node1 = layer 2node, node2 = layer3 node
interface = node_two.netif(interface_two_data.id, net_one) interface = node_two.netif(interface_two_id, net_one)
link_config(net_one, interface, link_data) link_config(net_one, interface, link_options)
elif not node_two: elif not node_two:
# node2 = layer 2node, node1 = layer3 node # node2 = layer 2node, node1 = layer3 node
interface = node_one.netif(interface_one_data.id, net_one) interface = node_one.netif(interface_one_id, net_one)
link_config(net_one, interface, link_data) link_config(net_one, interface, link_options)
else: else:
common_networks = node_one.commonnets(node_two) common_networks = node_one.commonnets(node_two)
for net_one, interface_one, interface_two in common_networks: 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 continue
link_config(net_one, interface_one, link_data, interface_two=interface_two) link_config(net_one, interface_one, link_options, interface_two=interface_two)
if not link_data.unidirectional: if not link_options.unidirectional:
link_config(net_one, interface_two, link_data, interface_two=interface_one) link_config(net_one, interface_two, link_options, interface_two=interface_one)
else: else:
raise ValueError("no common network found") raise ValueError("no common network found")
finally: finally:
@ -523,30 +475,29 @@ class FutureSession(Session):
if node_two: if node_two:
node_two.lock.release() 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. Add a node to the session, based on the provided node data.
:param core.data.NodeData node_data: data to create node with :param core.future.futuredata.NodeOptions node_options: data to create node with
:return: nothing :return: created node
""" """
# retrieve node class for given node type # retrieve node class for given node type
try: try:
node_type = NodeTypes(node_data.node_type) node_class = nodeutils.get_node_class(node_options.type)
node_class = nodeutils.get_node_class(node_type)
except KeyError: 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 return None
# set node start based on current session state, override and check when rj45 # set node start based on current session state, override and check when rj45
start = self.state > EventTypes.DEFINITION_STATE.value start = self.state > EventTypes.DEFINITION_STATE.value
enable_rj45 = getattr(self.options, "enablerj45", "0") == "1" 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 start = False
# determine node id # determine node id
node_id = node_data.id node_id = node_options.id
if not node_id: if not node_id:
while True: while True:
node_id = self.node_id_gen.next() node_id = self.node_id_gen.next()
@ -554,7 +505,7 @@ class FutureSession(Session):
break break
# generate name if not provided # generate name if not provided
name = node_data.name name = node_options.name
if not name: if not name:
name = "%s%s" % (node_class.__name__, node_id) 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) node = self.add_object(cls=node_class, objid=node_id, name=name, start=start)
# set node attributes # set node attributes
node.type = node_data.model or "router" node.type = node_options.model or "router"
node.icon = node_data.icon node.icon = node_options.icon
node.canvas = node_data.canvas node.canvas = node_options.canvas
node.opaque = node_data.opaque node.opaque = node_options.opaque
# set node position and broadcast it # 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 # add services to default and physical nodes only
services = node_data.services if node_options.type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]:
if node_type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: logger.info("setting model (%s) with services (%s)", node.type, node_options.services)
logger.info("setting model (%s) with services (%s)", node.type, services) services = "|".join(node_options.services) or None
self.services.addservicestonode(node, node.type, services) self.services.addservicestonode(node, node.type, services)
# boot nodes if created after runtime, LcxNodes, Physical, and RJ45 are all PyCoreNodes # 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 # TODO: common method to both Physical and LxcNodes, but not the common PyCoreNode
node.boot() node.boot()
# return node id, in case it was generated return node
return node_id
def node_update(self, node_data): def update_node(self, node_options):
""" """
Update node information. 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 :return: nothing
""" """
try: try:
# get node to update # get node to update
node = self.get_object(node_data.id) node = self.get_object(node_options.id)
# set node position and broadcast it # set node position and broadcast it
self.node_set_position(node, node_data) self.set_node_position(node, node_options)
# update attributes # update attributes
node.canvas = node_data.canvas node.canvas = node_options.canvas
node.icon = node_data.icon node.icon = node_options.icon
except KeyError: 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. Delete a node from the session and check if session should shutdown, if no nodes are left.
:param int node_id: :param int node_id:
:return: True if node deleted, False otherwise :return: True if node deleted, False otherwise
:rtype: bool
""" """
# delete node and check for session shutdown if a node was removed # delete node and check for session shutdown if a node was removed
result = self.custom_delete_object(node_id) result = self.custom_delete_object(node_id)
@ -622,20 +573,20 @@ class FutureSession(Session):
self.check_shutdown() self.check_shutdown()
return result 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. Set position for a node, use lat/lon/alt if needed.
:param node: node to set position for :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 :return: nothing
""" """
# extract location values # extract location values
x = node_data.x_position x = node_options.x
y = node_data.y_position y = node_options.y
lat = node_data.latitude lat = node_options.lat
lon = node_data.longitude lon = node_options.lon
alt = node_data.altitude alt = node_options.alt
# check if we need to generate position from lat/lon/alt # check if we need to generate position from lat/lon/alt
has_empty_position = all(i is None for i in [x, y]) 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 = core_document_writer(self, version)
doc.writexml(file_name) 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. Store a hook from a received file message.
@ -755,7 +706,7 @@ class FutureSession(Session):
state = ":%s" % state state = ":%s" % state
self.set_hook(state, file_name, source_name, data) 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. Add a service file for a node.
@ -770,7 +721,7 @@ class FutureSession(Session):
service_name = ":%s" % service_name service_name = ":%s" % service_name
self.services.setservicefile(node_id, service_name, file_name, source_name, data) 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. Add a file to a node.
@ -874,16 +825,16 @@ class FutureSession(Session):
self.set_emane_model(emane_network, model) self.set_emane_model(emane_network, model)
return emane_network 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. Set emane model for a given emane node.
:param emane_node: emane node to set model for :param emane_node: emane node to set model for
:param model: emane model to set :param emane_model: emane model to set
:return: nothing :return: nothing
""" """
values = list(model.getdefaultvalues()) values = list(emane_model.getdefaultvalues())
self.emane.setconfig(emane_node.objid, model.name, values) self.emane.setconfig(emane_node.objid, emane_model.name, values)
class CoreEmu(object): class CoreEmu(object):
@ -921,7 +872,7 @@ class CoreEmu(object):
session.shutdown() session.shutdown()
self.sessions.clear() 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. 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): for common_network, interface_one, interface_two in node.commonnets(network):
common_network.link(interface_one, interface_two) 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. Convenience method for adding an interface with a prefix based on node id.
:param network: network to add interface with :param network: network to add interface with
:param node: node to add interface to :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 :return: created interface
""" """
address = prefix.get_address(node.objid) interface_data = prefixes.create_interface(node)
interface_index = node.newnetif(network, [address]) 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) 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 import logger
from core.api import coreapi from core.api import coreapi
from core.coreserver import CoreServer 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 EventData
from core.data import NodeData from core.enumerations import ConfigTlvs, LinkTypes
from core.enumerations import ConfigTlvs
from core.enumerations import EventTlvs from core.enumerations import EventTlvs
from core.enumerations import EventTypes from core.enumerations import EventTypes
from core.enumerations import ExceptionTlvs from core.enumerations import ExceptionTlvs
@ -30,6 +29,7 @@ from core.enumerations import NodeTlvs
from core.enumerations import NodeTypes from core.enumerations import NodeTypes
from core.enumerations import RegisterTlvs from core.enumerations import RegisterTlvs
from core.enumerations import SessionTlvs from core.enumerations import SessionTlvs
from core.future.futuredata import NodeOptions, LinkOptions, InterfaceData
from core.misc import nodeutils from core.misc import nodeutils
from core.misc import structutils from core.misc import structutils
from core.misc import utils from core.misc import utils
@ -566,7 +566,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
port = self.request.getpeername()[1] port = self.request.getpeername()[1]
# TODO: add shutdown handler for session # 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) # self.session.shutdown_handlers.append(self.session_shutdown)
logger.info("created new session for client: %s", self.session.session_id) 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") logger.warn("ignoring invalid message: add and delete flag both set")
return () return ()
# create node data from message data node_type = None
node_data = NodeData( node_type_value = message.get_tlv(NodeTlvs.TYPE.value)
id=message.get_tlv(NodeTlvs.NUMBER.value), if node_type_value is not None:
x_position=message.get_tlv(NodeTlvs.X_POSITION.value), node_type = NodeTypes(node_type_value)
y_position=message.get_tlv(NodeTlvs.Y_POSITION.value),
canvas=message.get_tlv(NodeTlvs.CANVAS.value), node_options = NodeOptions(
icon=message.get_tlv(NodeTlvs.ICON.value), _type=node_type,
latitude=message.get_tlv(NodeTlvs.LATITUDE.value), _id=message.get_tlv(NodeTlvs.NUMBER.value),
longitude=message.get_tlv(NodeTlvs.LONGITUDE.value),
altitude=message.get_tlv(NodeTlvs.ALTITUDE.value),
node_type=message.get_tlv(NodeTlvs.TYPE.value),
name=message.get_tlv(NodeTlvs.NAME.value), name=message.get_tlv(NodeTlvs.NAME.value),
model=message.get_tlv(NodeTlvs.MODEL.value), model=message.get_tlv(NodeTlvs.MODEL.value)
opaque=message.get_tlv(NodeTlvs.OPAQUE.value),
services=message.get_tlv(NodeTlvs.SERVICES.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: if message.flags & MessageFlags.ADD.value:
node_id = self.session.node_add(node_data) node = self.session.add_node(node_options)
if node_id: if node:
if message.flags & MessageFlags.STRING.value: 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: 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: elif message.flags & MessageFlags.DELETE.value:
with self._shutdown_lock: 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 we deleted a node broadcast out its removal
if result and message.flags & MessageFlags.STRING.value: if result and message.flags & MessageFlags.STRING.value:
tlvdata = "" 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 flags = MessageFlags.DELETE.value | MessageFlags.LOCAL.value
replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata)) replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata))
# node update # node update
else: else:
self.session.node_update(node_data) self.session.update_node(node_options)
return replies return replies
@ -690,47 +704,56 @@ class FutureHandler(SocketServer.BaseRequestHandler):
:param coreapi.CoreLinkMessage message: link message to handle :param coreapi.CoreLinkMessage message: link message to handle
:return: link message replies :return: link message replies
""" """
link_data = LinkData( node_one_id = message.get_tlv(LinkTlvs.N1_NUMBER.value)
session=message.get_tlv(LinkTlvs.SESSION.value), node_two_id = message.get_tlv(LinkTlvs.N2_NUMBER.value)
link_type=message.get_tlv(LinkTlvs.TYPE.value),
node1_id=message.get_tlv(LinkTlvs.N1_NUMBER.value), interface_one = InterfaceData(
node2_id=message.get_tlv(LinkTlvs.N2_NUMBER.value), _id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value),
delay=message.get_tlv(LinkTlvs.DELAY.value), name=message.get_tlv(LinkTlvs.INTERFACE1_NAME.value),
bandwidth=message.get_tlv(LinkTlvs.BANDWIDTH.value), mac=message.get_tlv(LinkTlvs.INTERFACE1_MAC.value),
per=message.get_tlv(LinkTlvs.PER.value), ip4=message.get_tlv(LinkTlvs.INTERFACE1_IP4.value),
dup=message.get_tlv(LinkTlvs.DUP.value), ip4_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value),
jitter=message.get_tlv(LinkTlvs.JITTER.value), ip6=message.get_tlv(LinkTlvs.INTERFACE1_IP6.value),
mer=message.get_tlv(LinkTlvs.MER.value), ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value),
burst=message.get_tlv(LinkTlvs.BURST.value), )
mburst=message.get_tlv(LinkTlvs.MBURST.value), interface_two = InterfaceData(
gui_attributes=message.get_tlv(LinkTlvs.GUI_ATTRIBUTES.value), _id=message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value),
unidirectional=message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value), name=message.get_tlv(LinkTlvs.INTERFACE2_NAME.value),
emulation_id=message.get_tlv(LinkTlvs.EMULATION_ID.value), mac=message.get_tlv(LinkTlvs.INTERFACE2_MAC.value),
network_id=message.get_tlv(LinkTlvs.NETWORK_ID.value), ip4=message.get_tlv(LinkTlvs.INTERFACE2_IP4.value),
key=message.get_tlv(LinkTlvs.KEY.value), ip4_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value),
opaque=message.get_tlv(LinkTlvs.OPAQUE.value), ip6=message.get_tlv(LinkTlvs.INTERFACE2_IP6.value),
interface1_id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value), ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.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),
) )
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: 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: 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: 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 () return ()
@ -829,7 +852,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
file_name = sys.argv[0] file_name = sys.argv[0]
if os.path.splitext(file_name)[1].lower() == ".xml": if os.path.splitext(file_name)[1].lower() == ".xml":
session = self.coreemu.create_session() session = self.coreemu.create_session(master=False)
try: try:
session.open_xml(file_name, start=True) session.open_xml(file_name, start=True)
except: except:
@ -962,7 +985,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
if file_type is not None: if file_type is not None:
if file_type.startswith("service:"): if file_type.startswith("service:"):
_, service_name = file_type.split(':')[:2] _, 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 () return ()
elif file_type.startswith("hook:"): elif file_type.startswith("hook:"):
_, state = file_type.split(':')[:2] _, state = file_type.split(':')[:2]
@ -970,7 +993,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
logger.error("error setting hook having state '%s'", state) logger.error("error setting hook having state '%s'", state)
return () return ()
state = int(state) state = int(state)
self.session.hook_add(state, file_name, source_name, data) self.session.add_hook(state, file_name, source_name, data)
return () return ()
# writing a file to the host # writing a file to the host

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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