updates to emane model config storage, fixes to reconnecting to a wlan session

This commit is contained in:
Blake Harnden 2019-11-21 16:41:38 -08:00
parent b983a09ae7
commit 97cb1444f3
9 changed files with 111 additions and 203 deletions

View file

@ -6,7 +6,6 @@ import os
from core.api.grpc import client, core_pb2 from core.api.grpc import client, core_pb2
from coretk.dialogs.sessions import SessionsDialog from coretk.dialogs.sessions import SessionsDialog
from coretk.emaneodelnodeconfig import EmaneModelNodeConfig
from coretk.interface import InterfaceManager from coretk.interface import InterfaceManager
from coretk.nodeutils import NodeDraw, NodeUtils from coretk.nodeutils import NodeDraw, NodeUtils
from coretk.servicefileconfig import ServiceFileConfig from coretk.servicefileconfig import ServiceFileConfig
@ -72,7 +71,6 @@ class CoreClient:
self.wlan_configs = {} self.wlan_configs = {}
self.mobility_configs = {} self.mobility_configs = {}
self.emane_model_configs = {} self.emane_model_configs = {}
self.emaneconfig_management = EmaneModelNodeConfig(app)
self.emane_config = None self.emane_config = None
self.serviceconfig_manager = ServiceNodeConfig(app) self.serviceconfig_manager = ServiceNodeConfig(app)
self.servicefileconfig_manager = ServiceFileConfig() self.servicefileconfig_manager = ServiceFileConfig()
@ -104,7 +102,7 @@ class CoreClient:
def handle_events(self, event): def handle_events(self, event):
logging.info("event: %s", event) logging.info("event: %s", event)
if event.HasField("link_event"): if event.HasField("link_event"):
self.app.canvas.wireless_draw.hangle_link_event(event.link_event) self.app.canvas.wireless_draw.handle_link_event(event.link_event)
elif event.HasField("session_event"): elif event.HasField("session_event"):
if event.session_event.event <= core_pb2.SessionState.SHUTDOWN: if event.session_event.event <= core_pb2.SessionState.SHUTDOWN:
self.state = event.session_event.event self.state = event.session_event.event
@ -153,7 +151,6 @@ class CoreClient:
# get hooks # get hooks
response = self.client.get_hooks(self.session_id) response = self.client.get_hooks(self.session_id)
logging.info("joined session hooks: %s", response)
for hook in response.hooks: for hook in response.hooks:
self.hooks[hook.file] = hook self.hooks[hook.file] = hook
@ -161,19 +158,16 @@ class CoreClient:
for node in session.nodes: for node in session.nodes:
if node.type == core_pb2.NodeType.WIRELESS_LAN: if node.type == core_pb2.NodeType.WIRELESS_LAN:
response = self.client.get_wlan_config(self.session_id, node.id) response = self.client.get_wlan_config(self.session_id, node.id)
logging.debug("wlan config(%s): %s", node.id, response)
self.wlan_configs[node.id] = response.config self.wlan_configs[node.id] = response.config
# get mobility configs # get mobility configs
response = self.client.get_mobility_configs(self.session_id) response = self.client.get_mobility_configs(self.session_id)
logging.debug("mobility configs: %s", response)
for node_id in response.configs: for node_id in response.configs:
node_config = response.configs[node_id].config node_config = response.configs[node_id].config
self.mobility_configs[node_id] = node_config self.mobility_configs[node_id] = node_config
# get emane config # get emane config
response = self.client.get_emane_config(self.session_id) response = self.client.get_emane_config(self.session_id)
logging.debug("emane config: %s", response)
self.emane_config = response.config self.emane_config = response.config
# get emane model config # get emane model config
@ -462,10 +456,6 @@ class CoreClient:
emane=emane, emane=emane,
) )
# set default emane configuration for emane node
if node_type == core_pb2.NodeType.EMANE:
self.emaneconfig_management.set_default_config(node_id)
# set default service configurations # set default service configurations
# TODO: need to deal with this and custom node cases # TODO: need to deal with this and custom node cases
if node_type == core_pb2.NodeType.DEFAULT: if node_type == core_pb2.NodeType.DEFAULT:
@ -492,50 +482,28 @@ class CoreClient:
:return: nothing :return: nothing
""" """
# delete the nodes # delete the nodes
for node_id in node_ids: for i in node_ids:
try: try:
del self.canvas_nodes[node_id] del self.canvas_nodes[i]
self.reusable.append(node_id) self.reusable.append(i)
if i in self.mobility_configs:
del self.mobility_configs[i]
if i in self.wlan_configs:
del self.wlan_configs[i]
for key in list(self.emane_model_configs):
node_id, _, _ = key
if node_id == i:
del self.emane_model_configs[key]
except KeyError: except KeyError:
logging.error("invalid canvas id: %s", node_id) logging.error("invalid canvas id: %s", i)
self.reusable.sort() self.reusable.sort()
# delete the edges and interfaces # delete the edges and interfaces
node_interface_pairs = []
for i in edge_tokens: for i in edge_tokens:
try: try:
link = self.links.pop(i) self.links.pop(i)
if link.interface_one is not None:
node_interface_pairs.append(
(link.node_one_id, link.interface_one.id)
)
if link.interface_two is not None:
node_interface_pairs.append(
(link.node_two_id, link.interface_two.id)
)
except KeyError: except KeyError:
logging.error("coreclient.py invalid edge token ") logging.error("invalid edge token: %s", i)
# delete global emane config if there no longer exist any emane cloud
# TODO: should not need to worry about this
node_types = [x.core_node.type for x in self.canvas_nodes.values()]
if core_pb2.NodeType.EMANE not in node_types:
self.emane_config = None
# delete any mobility configuration, wlan configuration
for i in node_ids:
if i in self.mobility_configs:
del self.mobility_configs[i]
if i in self.wlan_configs:
del self.wlan_configs[i]
# delete emane configurations
for i in node_interface_pairs:
if i in self.emaneconfig_management.configurations:
self.emaneconfig_management.configurations.pop(i)
for i in node_ids:
if tuple([i, None]) in self.emaneconfig_management.configurations:
self.emaneconfig_management.configurations.pop(tuple([i, None]))
def create_interface(self, canvas_node): def create_interface(self, canvas_node):
interface = None interface = None
@ -609,13 +577,11 @@ class CoreClient:
def get_emane_model_configs_proto(self): def get_emane_model_configs_proto(self):
configs = [] configs = []
emane_configs = self.emaneconfig_management.configurations for key, config in self.emane_model_configs.items():
for key, value in emane_configs.items(): node_id, model, interface = key
node_id, interface_id = key config = {x: config[x].value for x in config}
model, options = value
config = {x: options[x].value for x in options}
config_proto = core_pb2.EmaneModelConfig( config_proto = core_pb2.EmaneModelConfig(
node_id=node_id, interface_id=interface_id, model=model, config=config node_id=node_id, interface_id=interface, model=model, config=config
) )
configs.append(config_proto) configs.append(config_proto)
return configs return configs
@ -669,3 +635,17 @@ class CoreClient:
response = self.client.get_mobility_config(self.session_id, node_id) response = self.client.get_mobility_config(self.session_id, node_id)
config = response.config config = response.config
return config return config
def get_emane_model_config(self, node_id, model, interface=None):
config = self.emane_model_configs.get((node_id, model, interface))
if not config:
if interface is None:
interface = -1
response = self.client.get_emane_model_config(
self.session_id, node_id, model, interface
)
config = response.config
return config
def set_emane_model_config(self, node_id, model, config, interface=None):
self.emane_model_configs[(node_id, model, interface)] = config

View file

@ -46,16 +46,15 @@ class GlobalEmaneDialog(Dialog):
class EmaneModelDialog(Dialog): class EmaneModelDialog(Dialog):
def __init__(self, master, app, node, model): def __init__(self, master, app, node, model, interface=None):
super().__init__(master, app, f"{node.name} {model} Configuration", modal=True) super().__init__(master, app, f"{node.name} {model} Configuration", modal=True)
self.node = node self.node = node
self.model = f"emane_{model}" self.model = f"emane_{model}"
self.interface = interface
self.config_frame = None self.config_frame = None
session_id = self.app.core.session_id self.config = self.app.core.get_emane_model_config(
response = self.app.core.client.get_emane_model_config( self.node.id, self.model, self.interface
session_id, self.node.id, self.model
) )
self.config = response.config
self.draw() self.draw()
def draw(self): def draw(self):
@ -79,8 +78,8 @@ class EmaneModelDialog(Dialog):
def click_apply(self): def click_apply(self):
self.config_frame.parse_config() self.config_frame.parse_config()
self.app.core.emaneconfig_management.set_custom_emane_cloud_config( self.app.core.set_emane_model_config(
self.node.id, self.model self.node.id, self.model, self.config, self.interface
) )
self.destroy() self.destroy()

View file

@ -1,78 +0,0 @@
"""
emane model configurations
"""
import logging
class EmaneModelNodeConfig:
def __init__(self, app):
"""
create an instance for EmaneModelNodeConfig
:param app: application
"""
# dict(tuple(node_id, interface_id, model) : config)
self.configurations = {}
# dict(int, list(int)) stores emane node maps to mdr nodes that are linked to that emane node
self.links = {}
self.app = app
def set_default_config(self, node_id):
"""
set a default emane configuration for a newly created emane
:param int node_id: node id
:return: nothing
"""
session_id = self.app.core.session_id
client = self.app.core.client
default_emane_model = self.app.core.emane_models[0]
response = client.get_emane_model_config(
session_id, node_id, default_emane_model
)
logging.info(
"emanemodelnodeconfig.py get emane model config (%s), result: %s",
node_id,
response,
)
self.configurations[tuple([node_id, None])] = tuple(
[default_emane_model, response.config]
)
self.links[node_id] = []
def set_default_for_mdr(self, emane_node_id, mdr_node_id, interface_id):
"""
set emane configuration of an mdr node on the correct interface
:param int emane_node_id: emane node id
:param int mdr_node_id: mdr node id
:param int interface_id: interface id
:return: nothing
"""
self.configurations[tuple([mdr_node_id, interface_id])] = self.configurations[
tuple([emane_node_id, None])
]
self.links[emane_node_id].append(tuple([mdr_node_id, interface_id]))
def set_custom_emane_cloud_config(self, emane_node_id, model_name):
"""
set custom configuration for an emane node, if model is changed, update the nodes connected to that emane node
:param int emane_node_id: emane node id
:param str model_name: model name
:return: nothing
"""
prev_model_name = self.configurations[tuple([emane_node_id, None])][0]
session_id = self.app.core.session_id
response = self.app.core.client.get_emane_model_config(
session_id, emane_node_id, model_name
)
self.configurations[tuple([emane_node_id, None])] = tuple(
[model_name, response.config]
)
if prev_model_name != model_name:
for k in self.links[emane_node_id]:
self.configurations[k] = tuple([model_name, response.config])

View file

@ -176,48 +176,53 @@ class CanvasGraph(tk.Canvas):
node_one = canvas_node_one.core_node node_one = canvas_node_one.core_node
canvas_node_two = self.core.canvas_nodes[link.node_two_id] canvas_node_two = self.core.canvas_nodes[link.node_two_id]
node_two = canvas_node_two.core_node node_two = canvas_node_two.core_node
is_wired = link.type == core_pb2.LinkType.WIRED if link.type == core_pb2.LinkType.WIRELESS:
edge = CanvasEdge( self.wireless_draw.add_connection(link.node_one_id, link.node_two_id)
node_one.position.x, else:
node_one.position.y, is_node_one_wireless = NodeUtils.is_wireless_node(node_one.type)
node_two.position.x, is_node_two_wireless = NodeUtils.is_wireless_node(node_two.type)
node_two.position.y, has_no_wireless = not (is_node_one_wireless or is_node_two_wireless)
canvas_node_one.id, edge = CanvasEdge(
self, node_one.position.x,
is_wired=is_wired, node_one.position.y,
) node_two.position.x,
edge.token = tuple(sorted((canvas_node_one.id, canvas_node_two.id))) node_two.position.y,
edge.dst = canvas_node_two.id canvas_node_one.id,
canvas_node_one.edges.add(edge) self,
canvas_node_two.edges.add(edge) is_wired=has_no_wireless,
self.edges[edge.token] = edge )
self.core.links[edge.token] = link edge.token = tuple(sorted((canvas_node_one.id, canvas_node_two.id)))
self.helper.redraw_antenna(link, canvas_node_one, canvas_node_two) edge.dst = canvas_node_two.id
canvas_node_one.edges.add(edge)
canvas_node_two.edges.add(edge)
self.edges[edge.token] = edge
self.core.links[edge.token] = link
self.helper.redraw_antenna(canvas_node_one, canvas_node_two)
# TODO add back the link info to grpc manager also redraw # TODO add back the link info to grpc manager also redraw
# TODO will include throughput and ipv6 in the future # TODO will include throughput and ipv6 in the future
interface_one = link.interface_one interface_one = link.interface_one
interface_two = link.interface_two interface_two = link.interface_two
ip4_src = None ip4_src = None
ip4_dst = None ip4_dst = None
ip6_src = None ip6_src = None
ip6_dst = None ip6_dst = None
if interface_one is not None: if interface_one is not None:
ip4_src = interface_one.ip4 ip4_src = interface_one.ip4
ip6_src = interface_one.ip6 ip6_src = interface_one.ip6
if interface_two is not None: if interface_two is not None:
ip4_dst = interface_two.ip4 ip4_dst = interface_two.ip4
ip6_dst = interface_two.ip6 ip6_dst = interface_two.ip6
edge.link_info = LinkInfo( edge.link_info = LinkInfo(
canvas=self, canvas=self,
edge=edge, edge=edge,
ip4_src=ip4_src, ip4_src=ip4_src,
ip6_src=ip6_src, ip6_src=ip6_src,
ip4_dst=ip4_dst, ip4_dst=ip4_dst,
ip6_dst=ip6_dst, ip6_dst=ip6_dst,
) )
canvas_node_one.interfaces.append(interface_one) canvas_node_one.interfaces.append(interface_one)
canvas_node_two.interfaces.append(interface_two) canvas_node_two.interfaces.append(interface_two)
# raise the nodes so they on top of the links # raise the nodes so they on top of the links
self.tag_raise("node") self.tag_raise("node")

View file

@ -4,8 +4,8 @@ Some graph helper functions
import logging import logging
import tkinter as tk import tkinter as tk
from core.api.grpc import core_pb2
from coretk.images import ImageEnum, Images from coretk.images import ImageEnum, Images
from coretk.nodeutils import NodeUtils
CANVAS_COMPONENT_TAGS = ["edge", "node", "nodename", "wallpaper", "linkinfo"] CANVAS_COMPONENT_TAGS = ["edge", "node", "nodename", "wallpaper", "linkinfo"]
@ -31,34 +31,30 @@ class GraphHelper:
def draw_wireless_case(self, src_id, dst_id, edge): def draw_wireless_case(self, src_id, dst_id, edge):
src_node_type = self.canvas.nodes[src_id].core_node.type src_node_type = self.canvas.nodes[src_id].core_node.type
dst_node_type = self.canvas.nodes[dst_id].core_node.type dst_node_type = self.canvas.nodes[dst_id].core_node.type
is_src_wlan = src_node_type == core_pb2.NodeType.WIRELESS_LAN is_src_wireless = NodeUtils.is_wireless_node(src_node_type)
is_dst_wlan = dst_node_type == core_pb2.NodeType.WIRELESS_LAN is_dst_wireless = NodeUtils.is_wireless_node(dst_node_type)
if is_src_wlan or is_dst_wlan: if is_src_wireless or is_dst_wireless:
self.canvas.itemconfig(edge.id, state=tk.HIDDEN) self.canvas.itemconfig(edge.id, state=tk.HIDDEN)
edge.wired = False edge.wired = False
if edge.token not in self.canvas.edges: if edge.token not in self.canvas.edges:
if is_src_wlan and is_dst_wlan: if is_src_wireless and is_dst_wireless:
self.canvas.nodes[src_id].antenna_draw.add_antenna() self.canvas.nodes[src_id].antenna_draw.add_antenna()
elif is_src_wlan: elif is_src_wireless:
self.canvas.nodes[dst_id].antenna_draw.add_antenna() self.canvas.nodes[dst_id].antenna_draw.add_antenna()
else: else:
self.canvas.nodes[src_id].antenna_draw.add_antenna() self.canvas.nodes[src_id].antenna_draw.add_antenna()
edge.wired = True edge.wired = True
def redraw_antenna(self, link, node_one, node_two): def redraw_antenna(self, node_one, node_two):
is_node_one_wlan = node_one.core_node.type == core_pb2.NodeType.WIRELESS_LAN is_node_one_wireless = NodeUtils.is_wireless_node(node_one.core_node.type)
is_node_two_wlan = node_two.core_node.type == core_pb2.NodeType.WIRELESS_LAN is_node_two_wireless = NodeUtils.is_wireless_node(node_two.core_node.type)
if link.type == core_pb2.LinkType.WIRELESS: if is_node_one_wireless or is_node_two_wireless:
if is_node_one_wlan and is_node_two_wlan: if is_node_one_wireless and not is_node_two_wireless:
node_one.antenna_draw.add_antenna()
elif is_node_one_wlan and not is_node_two_wlan:
node_two.antenna_draw.add_antenna() node_two.antenna_draw.add_antenna()
elif not is_node_one_wlan and is_node_two_wlan: elif not is_node_one_wireless and is_node_two_wireless:
node_one.antenna_draw.add_antenna() node_one.antenna_draw.add_antenna()
else: else:
logging.error( logging.error("bad link between two wireless nodes")
"graph_helper.py WIRELESS link but both nodes are non-wireless node"
)
def update_wlan_connection(self, old_x, old_y, new_x, new_y, edge_ids): def update_wlan_connection(self, old_x, old_y, new_x, new_y, edge_ids):
for eid in edge_ids: for eid in edge_ids:

View file

@ -18,7 +18,6 @@ class LinkInfo:
""" """
self.canvas = canvas self.canvas = canvas
self.edge = edge self.edge = edge
# self.edge_id = edge.id
self.radius = 37 self.radius = 37
self.core = self.canvas.core self.core = self.canvas.core

View file

@ -46,6 +46,7 @@ class NodeUtils:
NODE_ICONS = {} NODE_ICONS = {}
CONTAINER_NODES = {NodeType.DEFAULT, NodeType.DOCKER, NodeType.LXC} CONTAINER_NODES = {NodeType.DEFAULT, NodeType.DOCKER, NodeType.LXC}
IMAGE_NODES = {NodeType.DOCKER, NodeType.LXC} IMAGE_NODES = {NodeType.DOCKER, NodeType.LXC}
WIRELESS_NODES = {NodeType.WIRELESS_LAN, NodeType.EMANE}
NODE_MODELS = {"router", "host", "PC", "mdr", "prouter"} NODE_MODELS = {"router", "host", "PC", "mdr", "prouter"}
@classmethod @classmethod
@ -60,8 +61,14 @@ class NodeUtils:
def is_image_node(cls, node_type): def is_image_node(cls, node_type):
return node_type in cls.IMAGE_NODES return node_type in cls.IMAGE_NODES
@classmethod
def is_wireless_node(cls, node_type):
return node_type in cls.WIRELESS_NODES
@classmethod @classmethod
def node_icon(cls, node_type, model): def node_icon(cls, node_type, model):
if model == "":
model = None
return cls.NODE_ICONS[(node_type, model)] return cls.NODE_ICONS[(node_type, model)]
@classmethod @classmethod

View file

@ -11,7 +11,7 @@ class WirelessConnection:
# map a (node_one_id, node_two_id) to a wlan canvas id # map a (node_one_id, node_two_id) to a wlan canvas id
self.map = {} self.map = {}
def add_wlan_connection(self, node_one_id, node_two_id): def add_connection(self, node_one_id, node_two_id):
canvas_node_one = self.core.canvas_nodes[node_one_id] canvas_node_one = self.core.canvas_nodes[node_one_id]
canvas_node_two = self.core.canvas_nodes[node_two_id] canvas_node_two = self.core.canvas_nodes[node_two_id]
key = tuple(sorted((node_one_id, node_two_id))) key = tuple(sorted((node_one_id, node_two_id)))
@ -25,7 +25,7 @@ class WirelessConnection:
canvas_node_one.wlans.append(wlan_canvas_id) canvas_node_one.wlans.append(wlan_canvas_id)
canvas_node_two.wlans.append(wlan_canvas_id) canvas_node_two.wlans.append(wlan_canvas_id)
def delete_wlan_connection(self, node_one_id, node_two_id): def delete_connection(self, node_one_id, node_two_id):
canvas_node_one = self.core.canvas_nodes[node_one_id] canvas_node_one = self.core.canvas_nodes[node_one_id]
canvas_node_two = self.core.canvas_nodes[node_two_id] canvas_node_two = self.core.canvas_nodes[node_two_id]
key = tuple(sorted((node_one_id, node_two_id))) key = tuple(sorted((node_one_id, node_two_id)))
@ -35,13 +35,13 @@ class WirelessConnection:
self.canvas.delete(wlan_canvas_id) self.canvas.delete(wlan_canvas_id)
self.map.pop(key, None) self.map.pop(key, None)
def hangle_link_event(self, link_event): def handle_link_event(self, link_event):
if link_event.message_type == core_pb2.MessageType.ADD: if link_event.message_type == core_pb2.MessageType.ADD:
self.add_wlan_connection( self.add_connection(
link_event.link.node_one_id, link_event.link.node_two_id link_event.link.node_one_id, link_event.link.node_two_id
) )
if link_event.message_type == core_pb2.MessageType.DELETE: if link_event.message_type == core_pb2.MessageType.DELETE:
self.delete_wlan_connection( self.delete_connection(
link_event.link.node_one_id, link_event.link.node_two_id link_event.link.node_one_id, link_event.link.node_two_id
) )

View file

@ -1017,7 +1017,7 @@ class WlanNode(CoreNetwork):
""" """
apitype = NodeTypes.WIRELESS_LAN.value apitype = NodeTypes.WIRELESS_LAN.value
linktype = LinkTypes.WIRELESS.value linktype = LinkTypes.WIRED.value
policy = "DROP" policy = "DROP"
type = "wlan" type = "wlan"