updates to make future apis a bit better, updated handlers and all tests to account for changes

This commit is contained in:
Blake J. Harnden 2018-04-25 10:55:48 -07:00
parent 3ea885e2eb
commit c0b450789a
9 changed files with 94 additions and 155 deletions

View file

@ -7,11 +7,9 @@ import core.services
from core import logger
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.future.futuredata import InterfaceData, LinkOptions, NodeOptions
from core.misc import nodeutils
from core.netns.nodes import CoreNode
from core.session import Session
from core.xml.xmlparser import core_document_parser
from core.xml.xmlwriter import core_document_writer
@ -475,46 +473,47 @@ class FutureSession(Session):
if node_two:
node_two.lock.release()
def add_node(self, node_options):
def add_node(self, _type=NodeTypes.DEFAULT, _id=None, node_options=NodeOptions()):
"""
Add a node to the session, based on the provided node data.
:param core.enumerations.NodeTypes _type: type of node to create
:param int _id: id for node, defaults to None for generated id
:param core.future.futuredata.NodeOptions node_options: data to create node with
:return: created node
"""
# retrieve node class for given node type
try:
node_class = nodeutils.get_node_class(node_options.type)
node_class = nodeutils.get_node_class(_type)
except KeyError:
logger.error("invalid node type to create: %s", node_options.type)
logger.error("invalid node type to create: %s", _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_options.type == NodeTypes.RJ45 and not enable_rj45:
if _type == NodeTypes.RJ45 and not enable_rj45:
start = False
# determine node id
node_id = node_options.id
if not node_id:
if not _id:
while True:
node_id = self.node_id_gen.next()
if node_id not in self.objects:
_id = self.node_id_gen.next()
if _id not in self.objects:
break
# generate name if not provided
name = node_options.name
if not name:
name = "%s%s" % (node_class.__name__, node_id)
name = "%s%s" % (node_class.__name__, _id)
# create node
logger.info("creating node(%s) id(%s) name(%s) start(%s)", node_class, node_id, name, start)
node = self.add_object(cls=node_class, objid=node_id, name=name, start=start)
logger.info("creating node(%s) id(%s) name(%s) start(%s)", node_class, _id, name, start)
node = self.add_object(cls=node_class, objid=_id, name=name, start=start)
# set node attributes
node.type = node_options.model or "router"
node.type = node_options.model
node.icon = node_options.icon
node.canvas = node_options.canvas
node.opaque = node_options.opaque
@ -523,7 +522,7 @@ class FutureSession(Session):
self.set_node_position(node, node_options)
# add services to default and physical nodes only
if node_options.type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]:
if _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)
@ -539,16 +538,19 @@ class FutureSession(Session):
return node
def update_node(self, node_options):
def update_node(self, node_id, node_options):
"""
Update node information.
:param int node_id: id of node to update
:param core.future.futuredata.NodeOptions node_options: data to update node with
:return: nothing
:return: True if node updated, False otherwise
:rtype: bool
"""
result = False
try:
# get node to update
node = self.get_object(node_options.id)
node = self.get_object(node_id)
# set node position and broadcast it
self.set_node_position(node, node_options)
@ -556,14 +558,19 @@ class FutureSession(Session):
# update attributes
node.canvas = node_options.canvas
node.icon = node_options.icon
# set node as updated successfully
result = True
except KeyError:
logger.error("failure to update node that does not exist: %s", node_options.id)
return result
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:
:param int node_id: id of node to delete
:return: True if node deleted, False otherwise
:rtype: bool
"""
@ -796,23 +803,26 @@ class FutureSession(Session):
return node
def create_emane_node(self, name=None):
def create_emane_node(self, _id=None, node_options=NodeOptions()):
"""
Create an EMANE node for use within an EMANE network.
:param str name: name to five node
:return: CoreNode
:param int _id: int for node, defaults to None and will be generated
:param core.future.futuredata.NodeOptions node_options: options for emane node, model will always be "mdr"
:return: new emane node
:rtype: core.netns.nodes.CoreNode
"""
return self.create_node(cls=CoreNode, name=name, model="mdr")
node_options.model = "mdr"
return self.add_node(_type=NodeTypes.DEFAULT, _id=_id, node_options=node_options)
def create_emane_network(self, model, geo_reference, geo_scale=None, name=None):
def create_emane_network(self, model, geo_reference, geo_scale=None, node_options=NodeOptions()):
"""
Convenience method for creating an emane network.
:param model: emane model to use for emane network
:param geo_reference: geo reference point to use for emane node locations
:param geo_scale: geo scale to use for emane node locations, defaults to 1.0
:param name: name for emane network, defaults to node class name
:param core.future.futuredata.NodeOptions node_options: options for emane node being created
:return: create emane network
"""
# required to be set for emane to function properly
@ -821,7 +831,7 @@ class FutureSession(Session):
self.location.refscale = geo_scale
# create and return network
emane_network = self.create_node(cls=EmaneNode, name=name)
emane_network = self.add_node(_type=NodeTypes.EMANE, node_options=node_options)
self.set_emane_model(emane_network, model)
return emane_network

View file

@ -7,18 +7,14 @@ class NodeOptions(object):
Options for creating and updating nodes within core.
"""
def __init__(self, _type=None, _id=None, name=None, model=None):
def __init__(self, name=None, model="router"):
"""
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
:param str model: model to use for this node, defines services, defaults to "router"
"""
self.id = _id
self.name = name
self.type = _type
self.model = model
self.canvas = None
self.icon = None

View file

@ -647,9 +647,9 @@ class FutureHandler(SocketServer.BaseRequestHandler):
if node_type_value is not None:
node_type = NodeTypes(node_type_value)
node_id = message.get_tlv(NodeTlvs.NUMBER.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)
)
@ -674,7 +674,7 @@ class FutureHandler(SocketServer.BaseRequestHandler):
node_options.services = services.split("|")
if message.flags & MessageFlags.ADD.value:
node = self.session.add_node(node_options)
node = self.session.add_node(node_type, node_id, node_options)
if node:
if message.flags & MessageFlags.STRING.value:
self.node_status_request[node.objid] = True
@ -683,17 +683,17 @@ class FutureHandler(SocketServer.BaseRequestHandler):
self.send_node_emulation_id(node.objid)
elif message.flags & MessageFlags.DELETE.value:
with self._shutdown_lock:
result = self.session.delete_node(node_options.id)
result = self.session.delete_node(node_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_options.id)
tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_id)
flags = MessageFlags.DELETE.value | MessageFlags.LOCAL.value
replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata))
# node update
else:
self.session.update_node(node_options)
self.session.update_node(node_id, node_options)
return replies

View file

@ -6,6 +6,7 @@ import datetime
import parser
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.enumerations import EventTypes
from core.future.coreemu import CoreEmu
from core.future.futuredata import IpPrefixes
@ -18,6 +19,9 @@ def example(options):
coreemu = CoreEmu()
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 emane network node
emane_network = session.create_emane_network(
model=EmaneIeee80211abgModel,
@ -29,7 +33,8 @@ def example(options):
for i in xrange(options.nodes):
node = session.create_emane_node()
node.setposition(x=150 * (i + 1), y=150)
coreemu.add_interface(emane_network, node, prefixes)
interface = prefixes.create_interface(node)
session.add_link(node.objid, emane_network.objid, interface_one=interface)
# instantiate session
session.instantiate()

View file

@ -1,60 +0,0 @@
#!/usr/bin/python
#
# run iperf to measure the effective throughput between two nodes when
# n nodes are connected to a virtual wlan; run test for testsec
# and repeat for minnodes <= n <= maxnodes with a step size of
# nodestep
import datetime
import parser
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
prefixes = IpPrefixes("10.83.0.0/16")
# create emulator instance for creating sessions and utility methods
coreemu = CoreEmu()
session = coreemu.create_session()
# create switch network node
switch_network = session.create_node(cls=SwitchNode)
# create nodes
for _ in xrange(options.nodes):
node = session.create_node(cls=CoreNode)
coreemu.add_interface(switch_network, node, prefixes)
# instantiate session
session.instantiate()
# get nodes to run example
first_node = session.get_object(2)
last_node = session.get_object(options.nodes + 1)
print "starting iperf server on node: %s" % first_node.name
first_node.cmd(["iperf", "-s", "-D"])
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
coreemu.shutdown()
def main():
options = parser.parse_options("switch")
start = datetime.datetime.now()
print "running switch example: nodes(%s) time(%s)" % (options.nodes, options.time)
example(options)
print "elapsed time: %s" % (datetime.datetime.now() - start)
if __name__ == "__main__":
main()

View file

@ -10,7 +10,7 @@ import datetime
import parser
from core.enumerations import NodeTypes, EventTypes
from core.future.coreemu import CoreEmu
from core.future.futuredata import IpPrefixes, NodeOptions
from core.future.futuredata import IpPrefixes
def example(options):
@ -25,13 +25,11 @@ def example(options):
session.set_state(EventTypes.CONFIGURATION_STATE.value)
# create switch network node
node_options = NodeOptions(_type=NodeTypes.SWITCH)
switch = session.add_node(node_options)
switch = session.add_node(_type=NodeTypes.SWITCH)
# create nodes
for _ in xrange(options.nodes):
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node = session.add_node(node_options)
node = session.add_node()
interface = prefixes.create_interface(node)
session.add_link(node.objid, switch.objid, interface_one=interface)

View file

@ -6,7 +6,7 @@
# nodestep
from core.enumerations import NodeTypes, EventTypes
from core.future.futuredata import IpPrefixes, NodeOptions
from core.future.futuredata import IpPrefixes
def example(nodes):
@ -15,19 +15,17 @@ def example(nodes):
# create emulator instance for creating sessions and utility methods
coreemu = globals()["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_options = NodeOptions(_type=NodeTypes.SWITCH)
switch = session.add_node(node_options)
switch = session.add_node(_type=NodeTypes.SWITCH)
# create nodes
for _ in xrange(nodes):
node_options = NodeOptions(_type=NodeTypes.DEFAULT.value)
node = session.add_node(node_options)
node = session.add_node()
interface = prefixes.create_interface(node)
session.add_link(node.objid, switch.objid, interface_one=interface)

View file

@ -8,10 +8,10 @@
import datetime
import parser
from core.enumerations import NodeTypes, EventTypes
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):
@ -22,19 +22,23 @@ def example(options):
coreemu = CoreEmu()
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 wlan network node
wlan_network = session.create_node(cls=WlanNode)
coreemu.set_wireless_model(wlan_network, BasicRangeModel)
wlan = session.add_node(_type=NodeTypes.WIRELESS_LAN)
coreemu.set_wireless_model(wlan, BasicRangeModel)
# create nodes
wireless_nodes = []
for _ in xrange(options.nodes):
node = session.create_node(cls=CoreNode)
coreemu.add_interface(wlan_network, node, prefixes)
node = session.add_node()
interface = prefixes.create_interface(node)
session.add_link(node.objid, wlan.objid, interface_one=interface)
wireless_nodes.append(node)
# link all created nodes with the wireless network
coreemu.wireless_link_all(wlan_network, wireless_nodes)
coreemu.wireless_link_all(wlan, wireless_nodes)
# instantiate session
session.instantiate()

View file

@ -23,6 +23,8 @@ def future_session():
coreemu.shutdown()
IP4_PREFIX = "10.83.0.0/16"
MODELS = [
"router",
"host",
@ -41,10 +43,10 @@ class TestFuture:
@pytest.mark.parametrize("model", MODELS)
def test_node_add(self, future_session, model):
# given
node_options = NodeOptions(_type=NodeTypes.DEFAULT, model=model)
node_options = NodeOptions(model=model)
# when
node = future_session.add_node(node_options)
node = future_session.add_node(node_options=node_options)
# give time for node services to boot
time.sleep(1)
@ -59,14 +61,13 @@ class TestFuture:
def test_node_update(self, future_session):
# given
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node = future_session.add_node(node_options)
node = future_session.add_node()
position_value = 100
update_options = NodeOptions(_id=node.objid)
update_options = NodeOptions()
update_options.set_position(x=position_value, y=position_value)
# when
future_session.update_node(update_options)
future_session.update_node(node.objid, update_options)
# then
assert node.position.x == position_value
@ -74,8 +75,7 @@ class TestFuture:
def test_node_delete(self, future_session):
# given
node_options = NodeOptions(_type=NodeTypes.DEFAULT)
node = future_session.add_node(node_options)
node = future_session.add_node()
# when
future_session.delete_node(node.objid)
@ -87,10 +87,9 @@ class TestFuture:
@pytest.mark.parametrize("net_type", NET_TYPES)
def test_net(self, future_session, net_type):
# given
node_options = NodeOptions(_type=net_type)
# when
node = future_session.add_node(node_options)
node = future_session.add_node(_type=net_type)
# then
assert node
@ -99,10 +98,9 @@ class TestFuture:
def test_ptp(self, future_session):
# given
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)
prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX)
node_one = future_session.add_node()
node_two = future_session.add_node()
interface_one = prefixes.create_interface(node_one)
inteface_two = prefixes.create_interface(node_two)
@ -115,11 +113,9 @@ class TestFuture:
def test_node_to_net(self, future_session):
# given
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)
prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX)
node_one = future_session.add_node()
node_two = future_session.add_node(_type=NodeTypes.SWITCH)
interface_one = prefixes.create_interface(node_one)
# when
@ -131,12 +127,9 @@ class TestFuture:
def test_net_to_node(self, future_session):
# given
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
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)
prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX)
node_one = future_session.add_node(_type=NodeTypes.SWITCH)
node_two = future_session.add_node()
interface_two = prefixes.create_interface(node_two)
# when
@ -148,10 +141,8 @@ class TestFuture:
def test_net_to_net(self, future_session):
# given
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)
node_one = future_session.add_node(_type=NodeTypes.SWITCH)
node_two = future_session.add_node(_type=NodeTypes.SWITCH)
# when
future_session.add_link(node_one.objid, node_two.objid)
@ -161,11 +152,9 @@ class TestFuture:
def test_link_update(self, future_session):
# given
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)
prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX)
node_one = future_session.add_node()
node_two = future_session.add_node(_type=NodeTypes.SWITCH)
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)
@ -193,10 +182,9 @@ class TestFuture:
def test_link_delete(self, future_session):
# given
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)
prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX)
node_one = future_session.add_node()
node_two = future_session.add_node()
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)