Merge branch 'coretk' into coretk-validation
This commit is contained in:
commit
2292001e17
13 changed files with 346 additions and 235 deletions
|
@ -6,7 +6,6 @@ import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tkinter import messagebox
|
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
|
|
||||||
|
@ -14,6 +13,7 @@ from core.api.grpc import client, core_pb2
|
||||||
from coretk import appconfig
|
from coretk import appconfig
|
||||||
from coretk.dialogs.mobilityplayer import MobilityPlayer
|
from coretk.dialogs.mobilityplayer import MobilityPlayer
|
||||||
from coretk.dialogs.sessions import SessionsDialog
|
from coretk.dialogs.sessions import SessionsDialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.graph import tags
|
from coretk.graph import tags
|
||||||
from coretk.graph.shape import AnnotationData, Shape
|
from coretk.graph.shape import AnnotationData, Shape
|
||||||
from coretk.graph.shapeutils import ShapeType
|
from coretk.graph.shapeutils import ShapeType
|
||||||
|
@ -196,85 +196,92 @@ class CoreClient:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
# get session data
|
# get session data
|
||||||
response = self.client.get_session(self.session_id)
|
try:
|
||||||
session = response.session
|
response = self.client.get_session(self.session_id)
|
||||||
self.state = session.state
|
session = response.session
|
||||||
self.client.events(self.session_id, self.handle_events)
|
self.state = session.state
|
||||||
self.client.throughputs(self.handle_throughputs)
|
self.client.events(self.session_id, self.handle_events)
|
||||||
|
self.client.throughputs(self.handle_throughputs)
|
||||||
|
|
||||||
# get location
|
# get location
|
||||||
if query_location:
|
if query_location:
|
||||||
response = self.client.get_session_location(self.session_id)
|
response = self.client.get_session_location(self.session_id)
|
||||||
self.location = response.location
|
self.location = response.location
|
||||||
|
|
||||||
# get emane models
|
# get emane models
|
||||||
response = self.client.get_emane_models(self.session_id)
|
response = self.client.get_emane_models(self.session_id)
|
||||||
self.emane_models = response.models
|
self.emane_models = response.models
|
||||||
|
|
||||||
# get hooks
|
# get hooks
|
||||||
response = self.client.get_hooks(self.session_id)
|
response = self.client.get_hooks(self.session_id)
|
||||||
for hook in response.hooks:
|
for hook in response.hooks:
|
||||||
self.hooks[hook.file] = hook
|
self.hooks[hook.file] = hook
|
||||||
|
|
||||||
# get mobility configs
|
# get mobility configs
|
||||||
response = self.client.get_mobility_configs(self.session_id)
|
response = self.client.get_mobility_configs(self.session_id)
|
||||||
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)
|
||||||
self.emane_config = response.config
|
self.emane_config = response.config
|
||||||
|
|
||||||
# get emane model config
|
# get emane model config
|
||||||
response = self.client.get_emane_model_configs(self.session_id)
|
response = self.client.get_emane_model_configs(self.session_id)
|
||||||
for _id in response.configs:
|
for _id in response.configs:
|
||||||
config = response.configs[_id]
|
config = response.configs[_id]
|
||||||
interface = None
|
interface = None
|
||||||
node_id = _id
|
node_id = _id
|
||||||
if _id >= 1000:
|
if _id >= 1000:
|
||||||
interface = _id % 1000
|
interface = _id % 1000
|
||||||
node_id = int(_id / 1000)
|
node_id = int(_id / 1000)
|
||||||
self.set_emane_model_config(node_id, config.model, config.config, interface)
|
self.set_emane_model_config(
|
||||||
|
node_id, config.model, config.config, interface
|
||||||
|
)
|
||||||
|
|
||||||
# save and retrieve data, needed for session nodes
|
# save and retrieve data, needed for session nodes
|
||||||
for node in session.nodes:
|
for node in session.nodes:
|
||||||
# get node service config and file config
|
# get node service config and file config
|
||||||
self.created_nodes.add(node.id)
|
self.created_nodes.add(node.id)
|
||||||
|
|
||||||
# get wlan configs for wlan nodes
|
# get wlan configs for wlan 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)
|
||||||
self.wlan_configs[node.id] = response.config
|
self.wlan_configs[node.id] = response.config
|
||||||
# retrieve service configurations data for default nodes
|
# retrieve service configurations data for default nodes
|
||||||
elif node.type == core_pb2.NodeType.DEFAULT:
|
elif node.type == core_pb2.NodeType.DEFAULT:
|
||||||
for service in node.services:
|
for service in node.services:
|
||||||
response = self.client.get_node_service(
|
response = self.client.get_node_service(
|
||||||
self.session_id, node.id, service
|
self.session_id, node.id, service
|
||||||
)
|
|
||||||
if node.id not in self.service_configs:
|
|
||||||
self.service_configs[node.id] = {}
|
|
||||||
self.service_configs[node.id][service] = response.service
|
|
||||||
for file in response.service.configs:
|
|
||||||
response = self.client.get_node_service_file(
|
|
||||||
self.session_id, node.id, service, file
|
|
||||||
)
|
)
|
||||||
if node.id not in self.file_configs:
|
if node.id not in self.service_configs:
|
||||||
self.file_configs[node.id] = {}
|
self.service_configs[node.id] = {}
|
||||||
if service not in self.file_configs[node.id]:
|
self.service_configs[node.id][service] = response.service
|
||||||
self.file_configs[node.id][service] = {}
|
for file in response.service.configs:
|
||||||
self.file_configs[node.id][service][file] = response.data
|
response = self.client.get_node_service_file(
|
||||||
|
self.session_id, node.id, service, file
|
||||||
|
)
|
||||||
|
if node.id not in self.file_configs:
|
||||||
|
self.file_configs[node.id] = {}
|
||||||
|
if service not in self.file_configs[node.id]:
|
||||||
|
self.file_configs[node.id][service] = {}
|
||||||
|
self.file_configs[node.id][service][file] = response.data
|
||||||
|
|
||||||
# store links as created links
|
# store links as created links
|
||||||
for link in session.links:
|
for link in session.links:
|
||||||
self.created_links.add(tuple(sorted([link.node_one_id, link.node_two_id])))
|
self.created_links.add(
|
||||||
|
tuple(sorted([link.node_one_id, link.node_two_id]))
|
||||||
|
)
|
||||||
|
|
||||||
# draw session
|
# draw session
|
||||||
self.app.canvas.reset_and_redraw(session)
|
self.app.canvas.reset_and_redraw(session)
|
||||||
|
|
||||||
# get metadata
|
# get metadata
|
||||||
response = self.client.get_session_metadata(self.session_id)
|
response = self.client.get_session_metadata(self.session_id)
|
||||||
self.parse_metadata(response.config)
|
self.parse_metadata(response.config)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
# update ui to represent current state
|
# update ui to represent current state
|
||||||
if self.is_runtime():
|
if self.is_runtime():
|
||||||
|
@ -353,25 +360,31 @@ class CoreClient:
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
response = self.client.create_session()
|
try:
|
||||||
logging.info("created session: %s", response)
|
response = self.client.create_session()
|
||||||
location_config = self.app.guiconfig["location"]
|
logging.info("created session: %s", response)
|
||||||
self.location = core_pb2.SessionLocation(
|
location_config = self.app.guiconfig["location"]
|
||||||
x=location_config["x"],
|
self.location = core_pb2.SessionLocation(
|
||||||
y=location_config["y"],
|
x=location_config["x"],
|
||||||
z=location_config["z"],
|
y=location_config["y"],
|
||||||
lat=location_config["lat"],
|
z=location_config["z"],
|
||||||
lon=location_config["lon"],
|
lat=location_config["lat"],
|
||||||
alt=location_config["alt"],
|
lon=location_config["lon"],
|
||||||
scale=location_config["scale"],
|
alt=location_config["alt"],
|
||||||
)
|
scale=location_config["scale"],
|
||||||
self.join_session(response.session_id, query_location=False)
|
)
|
||||||
|
self.join_session(response.session_id, query_location=False)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def delete_session(self, session_id=None):
|
def delete_session(self, session_id=None):
|
||||||
if session_id is None:
|
if session_id is None:
|
||||||
session_id = self.session_id
|
session_id = self.session_id
|
||||||
response = self.client.delete_session(session_id)
|
try:
|
||||||
logging.info("Deleted session result: %s", response)
|
response = self.client.delete_session(session_id)
|
||||||
|
logging.info("deleted session result: %s", response)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def set_up(self):
|
def set_up(self):
|
||||||
"""
|
"""
|
||||||
|
@ -403,21 +416,15 @@ class CoreClient:
|
||||||
x.node_type: set(x.services) for x in response.defaults
|
x.node_type: set(x.services) for x in response.defaults
|
||||||
}
|
}
|
||||||
except grpc.RpcError as e:
|
except grpc.RpcError as e:
|
||||||
if e.code() == grpc.StatusCode.UNAVAILABLE:
|
show_grpc_error(e)
|
||||||
|
|
||||||
messagebox.showerror("Server Error", "CORE Daemon Unavailable")
|
|
||||||
else:
|
|
||||||
messagebox.showerror("GRPC Error", e.details())
|
|
||||||
self.app.close()
|
self.app.close()
|
||||||
|
|
||||||
def get_session_state(self):
|
|
||||||
response = self.client.get_session(self.session_id)
|
|
||||||
logging.info("get session: %s", response)
|
|
||||||
return response.session.state
|
|
||||||
|
|
||||||
def edit_node(self, node_id, x, y):
|
def edit_node(self, node_id, x, y):
|
||||||
position = core_pb2.Position(x=x, y=y)
|
position = core_pb2.Position(x=x, y=y)
|
||||||
self.client.edit_node(self.session_id, node_id, position, source="gui")
|
try:
|
||||||
|
self.client.edit_node(self.session_id, node_id, position, source="gui")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def start_session(self):
|
def start_session(self):
|
||||||
nodes = [x.core_node for x in self.canvas_nodes.values()]
|
nodes = [x.core_node for x in self.canvas_nodes.values()]
|
||||||
|
@ -436,39 +443,51 @@ class CoreClient:
|
||||||
emane_config = None
|
emane_config = None
|
||||||
|
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
response = self.client.start_session(
|
try:
|
||||||
self.session_id,
|
response = self.client.start_session(
|
||||||
nodes,
|
self.session_id,
|
||||||
links,
|
nodes,
|
||||||
self.location,
|
links,
|
||||||
hooks,
|
self.location,
|
||||||
emane_config,
|
hooks,
|
||||||
emane_model_configs,
|
emane_config,
|
||||||
wlan_configs,
|
emane_model_configs,
|
||||||
mobility_configs,
|
wlan_configs,
|
||||||
service_configs,
|
mobility_configs,
|
||||||
file_configs,
|
service_configs,
|
||||||
)
|
file_configs,
|
||||||
self.set_metadata()
|
)
|
||||||
process_time = time.perf_counter() - start
|
self.set_metadata()
|
||||||
logging.debug("start session(%s), result: %s", self.session_id, response.result)
|
process_time = time.perf_counter() - start
|
||||||
self.app.statusbar.start_session_callback(process_time)
|
logging.debug(
|
||||||
|
"start session(%s), result: %s", self.session_id, response.result
|
||||||
|
)
|
||||||
|
self.app.statusbar.start_session_callback(process_time)
|
||||||
|
|
||||||
# display mobility players
|
# display mobility players
|
||||||
for node_id, config in self.mobility_configs.items():
|
for node_id, config in self.mobility_configs.items():
|
||||||
canvas_node = self.canvas_nodes[node_id]
|
canvas_node = self.canvas_nodes[node_id]
|
||||||
mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config)
|
mobility_player = MobilityPlayer(
|
||||||
mobility_player.show()
|
self.app, self.app, canvas_node, config
|
||||||
self.mobility_players[node_id] = mobility_player
|
)
|
||||||
|
mobility_player.show()
|
||||||
|
self.mobility_players[node_id] = mobility_player
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def stop_session(self, session_id=None):
|
def stop_session(self, session_id=None):
|
||||||
if not session_id:
|
if not session_id:
|
||||||
session_id = self.session_id
|
session_id = self.session_id
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
response = self.client.stop_session(session_id)
|
try:
|
||||||
process_time = time.perf_counter() - start
|
response = self.client.stop_session(session_id)
|
||||||
self.app.statusbar.stop_session_callback(process_time)
|
logging.debug(
|
||||||
logging.debug("stopped session(%s), result: %s", session_id, response.result)
|
"stopped session(%s), result: %s", session_id, response.result
|
||||||
|
)
|
||||||
|
process_time = time.perf_counter() - start
|
||||||
|
self.app.statusbar.stop_session_callback(process_time)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def set_metadata(self):
|
def set_metadata(self):
|
||||||
# create canvas data
|
# create canvas data
|
||||||
|
@ -492,9 +511,12 @@ class CoreClient:
|
||||||
logging.info("set session metadata: %s", response)
|
logging.info("set session metadata: %s", response)
|
||||||
|
|
||||||
def launch_terminal(self, node_id):
|
def launch_terminal(self, node_id):
|
||||||
response = self.client.get_node_terminal(self.session_id, node_id)
|
try:
|
||||||
logging.info("get terminal %s", response.terminal)
|
response = self.client.get_node_terminal(self.session_id, node_id)
|
||||||
os.system(f"xterm -e {response.terminal} &")
|
logging.info("get terminal %s", response.terminal)
|
||||||
|
os.system(f"xterm -e {response.terminal} &")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def save_xml(self, file_path):
|
def save_xml(self, file_path):
|
||||||
"""
|
"""
|
||||||
|
@ -503,9 +525,11 @@ class CoreClient:
|
||||||
:param str file_path: file path that user pick
|
:param str file_path: file path that user pick
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
response = self.client.save_xml(self.session_id, file_path)
|
try:
|
||||||
logging.info("saved xml(%s): %s", file_path, response)
|
response = self.client.save_xml(self.session_id, file_path)
|
||||||
self.client.events(self.session_id, self.handle_events)
|
logging.info("saved xml(%s): %s", file_path, response)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def open_xml(self, file_path):
|
def open_xml(self, file_path):
|
||||||
"""
|
"""
|
||||||
|
@ -514,9 +538,12 @@ class CoreClient:
|
||||||
:param str file_path: file to open
|
:param str file_path: file to open
|
||||||
:return: session id
|
:return: session id
|
||||||
"""
|
"""
|
||||||
response = self.client.open_xml(file_path)
|
try:
|
||||||
logging.debug("open xml: %s", response)
|
response = self.client.open_xml(file_path)
|
||||||
self.join_session(response.session_id)
|
logging.debug("open xml: %s", response)
|
||||||
|
self.join_session(response.session_id)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def get_node_service(self, node_id, service_name):
|
def get_node_service(self, node_id, service_name):
|
||||||
response = self.client.get_node_service(self.session_id, node_id, service_name)
|
response = self.client.get_node_service(self.session_id, node_id, service_name)
|
||||||
|
@ -553,7 +580,7 @@ class CoreClient:
|
||||||
"""
|
"""
|
||||||
node_protos = [x.core_node for x in self.canvas_nodes.values()]
|
node_protos = [x.core_node for x in self.canvas_nodes.values()]
|
||||||
link_protos = list(self.links.values())
|
link_protos = list(self.links.values())
|
||||||
if self.get_session_state() != core_pb2.SessionState.DEFINITION:
|
if self.state != core_pb2.SessionState.DEFINITION:
|
||||||
self.client.set_session_state(
|
self.client.set_session_state(
|
||||||
self.session_id, core_pb2.SessionState.DEFINITION
|
self.session_id, core_pb2.SessionState.DEFINITION
|
||||||
)
|
)
|
||||||
|
@ -590,7 +617,7 @@ class CoreClient:
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
logging.debug("Close grpc")
|
logging.debug("close grpc")
|
||||||
self.client.close()
|
self.client.close()
|
||||||
|
|
||||||
def next_node_id(self):
|
def next_node_id(self):
|
||||||
|
|
|
@ -6,7 +6,10 @@ import tkinter as tk
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
from coretk.widgets import ConfigFrame
|
from coretk.widgets import ConfigFrame
|
||||||
|
|
||||||
|
@ -52,9 +55,13 @@ class EmaneModelDialog(Dialog):
|
||||||
self.model = f"emane_{model}"
|
self.model = f"emane_{model}"
|
||||||
self.interface = interface
|
self.interface = interface
|
||||||
self.config_frame = None
|
self.config_frame = None
|
||||||
self.config = self.app.core.get_emane_model_config(
|
try:
|
||||||
self.node.id, self.model, self.interface
|
self.config = self.app.core.get_emane_model_config(
|
||||||
)
|
self.node.id, self.model, self.interface
|
||||||
|
)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
self.destroy()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
|
|
|
@ -3,7 +3,10 @@ mobility configuration
|
||||||
"""
|
"""
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.widgets import ConfigFrame
|
from coretk.widgets import ConfigFrame
|
||||||
|
|
||||||
PAD = 5
|
PAD = 5
|
||||||
|
@ -20,7 +23,11 @@ class MobilityConfigDialog(Dialog):
|
||||||
self.canvas_node = canvas_node
|
self.canvas_node = canvas_node
|
||||||
self.node = canvas_node.core_node
|
self.node = canvas_node.core_node
|
||||||
self.config_frame = None
|
self.config_frame = None
|
||||||
self.config = self.app.core.get_mobility_config(self.node.id)
|
try:
|
||||||
|
self.config = self.app.core.get_mobility_config(self.node.id)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
self.destroy()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from core.api.grpc.core_pb2 import MobilityAction
|
from core.api.grpc.core_pb2 import MobilityAction
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
|
|
||||||
PAD = 5
|
PAD = 5
|
||||||
|
@ -50,6 +53,7 @@ class MobilityPlayerDialog(Dialog):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
master, app, f"{canvas_node.core_node.name} Mobility Player", modal=False
|
master, app, f"{canvas_node.core_node.name} Mobility Player", modal=False
|
||||||
)
|
)
|
||||||
|
self.geometry("")
|
||||||
self.canvas_node = canvas_node
|
self.canvas_node = canvas_node
|
||||||
self.node = canvas_node.core_node
|
self.node = canvas_node.core_node
|
||||||
self.config = config
|
self.config = config
|
||||||
|
@ -123,20 +127,29 @@ class MobilityPlayerDialog(Dialog):
|
||||||
def click_play(self):
|
def click_play(self):
|
||||||
self.set_play()
|
self.set_play()
|
||||||
session_id = self.app.core.session_id
|
session_id = self.app.core.session_id
|
||||||
self.app.core.client.mobility_action(
|
try:
|
||||||
session_id, self.node.id, MobilityAction.START
|
self.app.core.client.mobility_action(
|
||||||
)
|
session_id, self.node.id, MobilityAction.START
|
||||||
|
)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def click_pause(self):
|
def click_pause(self):
|
||||||
self.set_pause()
|
self.set_pause()
|
||||||
session_id = self.app.core.session_id
|
session_id = self.app.core.session_id
|
||||||
self.app.core.client.mobility_action(
|
try:
|
||||||
session_id, self.node.id, MobilityAction.PAUSE
|
self.app.core.client.mobility_action(
|
||||||
)
|
session_id, self.node.id, MobilityAction.PAUSE
|
||||||
|
)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def click_stop(self):
|
def click_stop(self):
|
||||||
self.set_stop()
|
self.set_stop()
|
||||||
session_id = self.app.core.session_id
|
session_id = self.app.core.session_id
|
||||||
self.app.core.client.mobility_action(
|
try:
|
||||||
session_id, self.node.id, MobilityAction.STOP
|
self.app.core.client.mobility_action(
|
||||||
)
|
session_id, self.node.id, MobilityAction.STOP
|
||||||
|
)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
|
@ -3,8 +3,11 @@ import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
from coretk.widgets import CodeText, ListboxScroll
|
from coretk.widgets import CodeText, ListboxScroll
|
||||||
|
|
||||||
|
@ -47,44 +50,48 @@ class ServiceConfiguration(Dialog):
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
# create nodes and links in definition state for getting and setting service file
|
try:
|
||||||
self.app.core.create_nodes_and_links()
|
# create nodes and links in definition state for getting and setting service file
|
||||||
|
self.app.core.create_nodes_and_links()
|
||||||
service_configs = self.app.core.service_configs
|
service_configs = self.app.core.service_configs
|
||||||
if (
|
if (
|
||||||
self.node_id in service_configs
|
self.node_id in service_configs
|
||||||
and self.service_name in service_configs[self.node_id]
|
and self.service_name in service_configs[self.node_id]
|
||||||
):
|
):
|
||||||
service_config = self.app.core.service_configs[self.node_id][
|
service_config = self.app.core.service_configs[self.node_id][
|
||||||
self.service_name
|
self.service_name
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
service_config = self.app.core.get_node_service(
|
service_config = self.app.core.get_node_service(
|
||||||
self.node_id, self.service_name
|
self.node_id, self.service_name
|
||||||
)
|
)
|
||||||
self.dependencies = [x for x in service_config.dependencies]
|
self.dependencies = [x for x in service_config.dependencies]
|
||||||
self.executables = [x for x in service_config.executables]
|
self.executables = [x for x in service_config.executables]
|
||||||
self.metadata = service_config.meta
|
self.metadata = service_config.meta
|
||||||
self.filenames = [x for x in service_config.configs]
|
self.filenames = [x for x in service_config.configs]
|
||||||
self.startup_commands = [x for x in service_config.startup]
|
self.startup_commands = [x for x in service_config.startup]
|
||||||
self.validation_commands = [x for x in service_config.validate]
|
self.validation_commands = [x for x in service_config.validate]
|
||||||
self.shutdown_commands = [x for x in service_config.shutdown]
|
self.shutdown_commands = [x for x in service_config.shutdown]
|
||||||
self.validation_mode = service_config.validation_mode
|
self.validation_mode = service_config.validation_mode
|
||||||
self.validation_time = service_config.validation_timer
|
self.validation_time = service_config.validation_timer
|
||||||
self.original_service_files = {
|
self.original_service_files = {
|
||||||
x: self.app.core.get_node_service_file(self.node_id, self.service_name, x)
|
x: self.app.core.get_node_service_file(
|
||||||
for x in self.filenames
|
self.node_id, self.service_name, x
|
||||||
}
|
)
|
||||||
self.temp_service_files = {
|
for x in self.filenames
|
||||||
x: self.original_service_files[x] for x in self.original_service_files
|
}
|
||||||
}
|
self.temp_service_files = {
|
||||||
file_configs = self.app.core.file_configs
|
x: self.original_service_files[x] for x in self.original_service_files
|
||||||
if (
|
}
|
||||||
self.node_id in file_configs
|
file_configs = self.app.core.file_configs
|
||||||
and self.service_name in file_configs[self.node_id]
|
if (
|
||||||
):
|
self.node_id in file_configs
|
||||||
for file, data in file_configs[self.node_id][self.service_name].items():
|
and self.service_name in file_configs[self.node_id]
|
||||||
self.temp_service_files[file] = data
|
):
|
||||||
|
for file, data in file_configs[self.node_id][self.service_name].items():
|
||||||
|
self.temp_service_files[file] = data
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
# self.columnconfigure(1, weight=1)
|
# self.columnconfigure(1, weight=1)
|
||||||
|
@ -366,30 +373,33 @@ class ServiceConfiguration(Dialog):
|
||||||
startup_commands = self.startup_commands_listbox.get(0, "end")
|
startup_commands = self.startup_commands_listbox.get(0, "end")
|
||||||
shutdown_commands = self.shutdown_commands_listbox.get(0, "end")
|
shutdown_commands = self.shutdown_commands_listbox.get(0, "end")
|
||||||
validate_commands = self.validate_commands_listbox.get(0, "end")
|
validate_commands = self.validate_commands_listbox.get(0, "end")
|
||||||
config = self.core.set_node_service(
|
try:
|
||||||
self.node_id,
|
config = self.core.set_node_service(
|
||||||
self.service_name,
|
self.node_id,
|
||||||
startup_commands,
|
self.service_name,
|
||||||
validate_commands,
|
startup_commands,
|
||||||
shutdown_commands,
|
validate_commands,
|
||||||
)
|
shutdown_commands,
|
||||||
if self.node_id not in service_configs:
|
|
||||||
service_configs[self.node_id] = {}
|
|
||||||
if self.service_name not in service_configs[self.node_id]:
|
|
||||||
self.app.core.service_configs[self.node_id][self.service_name] = config
|
|
||||||
for file in self.modified_files:
|
|
||||||
file_configs = self.app.core.file_configs
|
|
||||||
if self.node_id not in file_configs:
|
|
||||||
file_configs[self.node_id] = {}
|
|
||||||
if self.service_name not in file_configs[self.node_id]:
|
|
||||||
file_configs[self.node_id][self.service_name] = {}
|
|
||||||
file_configs[self.node_id][self.service_name][
|
|
||||||
file
|
|
||||||
] = self.temp_service_files[file]
|
|
||||||
|
|
||||||
self.app.core.set_node_service_file(
|
|
||||||
self.node_id, self.service_name, file, self.temp_service_files[file]
|
|
||||||
)
|
)
|
||||||
|
if self.node_id not in service_configs:
|
||||||
|
service_configs[self.node_id] = {}
|
||||||
|
if self.service_name not in service_configs[self.node_id]:
|
||||||
|
self.app.core.service_configs[self.node_id][self.service_name] = config
|
||||||
|
for file in self.modified_files:
|
||||||
|
file_configs = self.app.core.file_configs
|
||||||
|
if self.node_id not in file_configs:
|
||||||
|
file_configs[self.node_id] = {}
|
||||||
|
if self.service_name not in file_configs[self.node_id]:
|
||||||
|
file_configs[self.node_id][self.service_name] = {}
|
||||||
|
file_configs[self.node_id][self.service_name][
|
||||||
|
file
|
||||||
|
] = self.temp_service_files[file]
|
||||||
|
|
||||||
|
self.app.core.set_node_service_file(
|
||||||
|
self.node_id, self.service_name, file, self.temp_service_files[file]
|
||||||
|
)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
def display_service_file_data(self, event):
|
def display_service_file_data(self, event):
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import logging
|
import logging
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.widgets import ConfigFrame
|
from coretk.widgets import ConfigFrame
|
||||||
|
|
||||||
PAD_X = 2
|
PAD_X = 2
|
||||||
|
@ -12,17 +15,23 @@ class SessionOptionsDialog(Dialog):
|
||||||
def __init__(self, master, app):
|
def __init__(self, master, app):
|
||||||
super().__init__(master, app, "Session Options", modal=True)
|
super().__init__(master, app, "Session Options", modal=True)
|
||||||
self.config_frame = None
|
self.config_frame = None
|
||||||
|
self.config = self.get_config()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
|
def get_config(self):
|
||||||
|
try:
|
||||||
|
session_id = self.app.core.session_id
|
||||||
|
response = self.app.core.client.get_session_options(session_id)
|
||||||
|
return response.config
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.top.columnconfigure(0, weight=1)
|
self.top.columnconfigure(0, weight=1)
|
||||||
self.top.rowconfigure(0, weight=1)
|
self.top.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
session_id = self.app.core.session_id
|
self.config_frame = ConfigFrame(self.top, self.app, config=self.config)
|
||||||
response = self.app.core.client.get_session_options(session_id)
|
|
||||||
logging.info("session options: %s", response)
|
|
||||||
|
|
||||||
self.config_frame = ConfigFrame(self.top, self.app, config=response.config)
|
|
||||||
self.config_frame.draw_config()
|
self.config_frame.draw_config()
|
||||||
self.config_frame.grid(sticky="nsew")
|
self.config_frame.grid(sticky="nsew")
|
||||||
|
|
||||||
|
@ -37,7 +46,10 @@ class SessionOptionsDialog(Dialog):
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
config = self.config_frame.parse_config()
|
config = self.config_frame.parse_config()
|
||||||
session_id = self.app.core.session_id
|
try:
|
||||||
response = self.app.core.client.set_session_options(session_id, config)
|
session_id = self.app.core.session_id
|
||||||
logging.info("saved session config: %s", response)
|
response = self.app.core.client.set_session_options(session_id, config)
|
||||||
|
logging.info("saved session config: %s", response)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
|
@ -3,8 +3,11 @@ import threading
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,8 +17,18 @@ class SessionsDialog(Dialog):
|
||||||
self.selected = False
|
self.selected = False
|
||||||
self.selected_id = None
|
self.selected_id = None
|
||||||
self.tree = None
|
self.tree = None
|
||||||
|
self.sessions = self.get_sessions()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
|
def get_sessions(self):
|
||||||
|
try:
|
||||||
|
response = self.app.core.client.get_sessions()
|
||||||
|
logging.info("sessions: %s", response)
|
||||||
|
return response.sessions
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.top.columnconfigure(0, weight=1)
|
self.top.columnconfigure(0, weight=1)
|
||||||
self.draw_description()
|
self.draw_description()
|
||||||
|
@ -48,9 +61,7 @@ class SessionsDialog(Dialog):
|
||||||
self.tree.column("nodes", stretch=tk.YES)
|
self.tree.column("nodes", stretch=tk.YES)
|
||||||
self.tree.heading("nodes", text="Node Count")
|
self.tree.heading("nodes", text="Node Count")
|
||||||
|
|
||||||
response = self.app.core.client.get_sessions()
|
for index, session in enumerate(self.sessions):
|
||||||
logging.info("sessions: %s", response)
|
|
||||||
for index, session in enumerate(response.sessions):
|
|
||||||
state_name = core_pb2.SessionState.Enum.Name(session.state)
|
state_name = core_pb2.SessionState.Enum.Name(session.state)
|
||||||
self.tree.insert(
|
self.tree.insert(
|
||||||
"",
|
"",
|
||||||
|
|
|
@ -4,7 +4,10 @@ wlan configuration
|
||||||
|
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.widgets import ConfigFrame
|
from coretk.widgets import ConfigFrame
|
||||||
|
|
||||||
PAD = 5
|
PAD = 5
|
||||||
|
@ -18,7 +21,11 @@ class WlanConfigDialog(Dialog):
|
||||||
self.canvas_node = canvas_node
|
self.canvas_node = canvas_node
|
||||||
self.node = canvas_node.core_node
|
self.node = canvas_node.core_node
|
||||||
self.config_frame = None
|
self.config_frame = None
|
||||||
self.config = self.app.core.get_wlan_config(self.node.id)
|
try:
|
||||||
|
self.config = self.app.core.get_wlan_config(self.node.id)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
self.destroy()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
|
|
8
coretk/coretk/errors.py
Normal file
8
coretk/coretk/errors.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
from tkinter import messagebox
|
||||||
|
|
||||||
|
|
||||||
|
def show_grpc_error(e):
|
||||||
|
title = [x.capitalize() for x in e.code().name.lower().split("_")]
|
||||||
|
title = " ".join(title)
|
||||||
|
title = f"GRPC {title}"
|
||||||
|
messagebox.showerror(title, e.details())
|
|
@ -2,11 +2,14 @@ import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import font
|
from tkinter import font
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
from core.api.grpc.core_pb2 import NodeType
|
from core.api.grpc.core_pb2 import NodeType
|
||||||
from coretk.dialogs.emaneconfig import EmaneConfigDialog
|
from coretk.dialogs.emaneconfig import EmaneConfigDialog
|
||||||
from coretk.dialogs.mobilityconfig import MobilityConfigDialog
|
from coretk.dialogs.mobilityconfig import MobilityConfigDialog
|
||||||
from coretk.dialogs.nodeconfig import NodeConfigDialog
|
from coretk.dialogs.nodeconfig import NodeConfigDialog
|
||||||
from coretk.dialogs.wlanconfig import WlanConfigDialog
|
from coretk.dialogs.wlanconfig import WlanConfigDialog
|
||||||
|
from coretk.errors import show_grpc_error
|
||||||
from coretk.graph import tags
|
from coretk.graph import tags
|
||||||
from coretk.graph.enums import GraphMode
|
from coretk.graph.enums import GraphMode
|
||||||
from coretk.graph.tooltip import CanvasTooltip
|
from coretk.graph.tooltip import CanvasTooltip
|
||||||
|
@ -138,8 +141,11 @@ class CanvasNode:
|
||||||
if self.app.core.is_runtime() and self.app.core.observer:
|
if self.app.core.is_runtime() and self.app.core.observer:
|
||||||
self.tooltip.text.set("waiting...")
|
self.tooltip.text.set("waiting...")
|
||||||
self.tooltip.on_enter(event)
|
self.tooltip.on_enter(event)
|
||||||
output = self.app.core.run(self.core_node.id)
|
try:
|
||||||
self.tooltip.text.set(output)
|
output = self.app.core.run(self.core_node.id)
|
||||||
|
self.tooltip.text.set(output)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
show_grpc_error(e)
|
||||||
|
|
||||||
def on_leave(self, event):
|
def on_leave(self, event):
|
||||||
self.tooltip.on_leave(event)
|
self.tooltip.on_leave(event)
|
||||||
|
|
|
@ -10,7 +10,6 @@ from tkinter import filedialog, messagebox
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
|
|
||||||
from core.api.grpc import core_pb2
|
|
||||||
from coretk.appconfig import XML_PATH
|
from coretk.appconfig import XML_PATH
|
||||||
from coretk.dialogs.about import AboutDialog
|
from coretk.dialogs.about import AboutDialog
|
||||||
from coretk.dialogs.canvasbackground import CanvasBackgroundDialog
|
from coretk.dialogs.canvasbackground import CanvasBackgroundDialog
|
||||||
|
@ -52,12 +51,7 @@ class MenuAction:
|
||||||
"menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program"
|
"menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program"
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
state = self.app.core.get_session_state()
|
if not self.app.core.is_runtime():
|
||||||
|
|
||||||
if (
|
|
||||||
state == core_pb2.SessionState.SHUTDOWN
|
|
||||||
or state == core_pb2.SessionState.DEFINITION
|
|
||||||
):
|
|
||||||
self.app.core.delete_session()
|
self.app.core.delete_session()
|
||||||
if quitapp:
|
if quitapp:
|
||||||
self.app.quit()
|
self.app.quit()
|
||||||
|
@ -73,7 +67,7 @@ class MenuAction:
|
||||||
elif quitapp:
|
elif quitapp:
|
||||||
self.app.quit()
|
self.app.quit()
|
||||||
except grpc.RpcError:
|
except grpc.RpcError:
|
||||||
logging.error("error getting session state")
|
logging.exception("error deleting session")
|
||||||
if quitapp:
|
if quitapp:
|
||||||
self.app.quit()
|
self.app.quit()
|
||||||
|
|
||||||
|
|
|
@ -195,24 +195,29 @@ In order to be able to do use the Bird Internet Routing Protocol, you must modif
|
||||||
### FRRouting
|
### FRRouting
|
||||||
FRRouting is a routing software package that provides TCP/IP based routing services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more. FRR also supports special BGP Route Reflector and Route Server behavior. In addition to traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols. With an SNMP daemon that supports the AgentX protocol, FRR provides routing protocol MIB read-only access (SNMP Support).
|
FRRouting is a routing software package that provides TCP/IP based routing services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more. FRR also supports special BGP Route Reflector and Route Server behavior. In addition to traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols. With an SNMP daemon that supports the AgentX protocol, FRR provides routing protocol MIB read-only access (SNMP Support).
|
||||||
|
|
||||||
FRR currently supports the following protocols:
|
FRR (as of v7.2) currently supports the following protocols:
|
||||||
* BGP
|
* BGPv4
|
||||||
* OSPFv2
|
* OSPFv2
|
||||||
* OSPFv3
|
* OSPFv3
|
||||||
* RIPv1
|
* RIPv1/v2/ng
|
||||||
* RIPv2
|
|
||||||
* RIPng
|
|
||||||
* IS-IS
|
* IS-IS
|
||||||
* PIM-SM/MSDP
|
* PIM-SM/MSDP/BSM(AutoRP)
|
||||||
* LDP
|
* LDP
|
||||||
* BFD
|
* BFD
|
||||||
* Babel
|
* Babel
|
||||||
* PBR
|
* PBR
|
||||||
* OpenFabric
|
* OpenFabric
|
||||||
|
* VRRPv2/v3
|
||||||
* EIGRP (alpha)
|
* EIGRP (alpha)
|
||||||
* NHRP (alpha)
|
* NHRP (alpha)
|
||||||
|
|
||||||
#### FRRouting Package Install
|
#### FRRouting Package Install
|
||||||
|
Ubuntu 19.10 and later
|
||||||
|
```shell
|
||||||
|
sudo apt update && sudo apt install frr
|
||||||
|
```
|
||||||
|
|
||||||
|
Ubuntu 16.04 and Ubuntu 18.04
|
||||||
```shell
|
```shell
|
||||||
sudo apt install curl
|
sudo apt install curl
|
||||||
curl -s https://deb.frrouting.org/frr/keys.asc | sudo apt-key add -
|
curl -s https://deb.frrouting.org/frr/keys.asc | sudo apt-key add -
|
||||||
|
@ -220,6 +225,10 @@ FRRVER="frr-stable"
|
||||||
echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER | sudo tee -a /etc/apt/sources.list.d/frr.list
|
echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER | sudo tee -a /etc/apt/sources.list.d/frr.list
|
||||||
sudo apt update && sudo apt install frr frr-pythontools
|
sudo apt update && sudo apt install frr frr-pythontools
|
||||||
```
|
```
|
||||||
|
Fedora 31
|
||||||
|
```shell
|
||||||
|
sudo dnf update && sudo dnf install frr
|
||||||
|
```
|
||||||
|
|
||||||
#### FRRouting Source Code Install
|
#### FRRouting Source Code Install
|
||||||
Building FRR from source is the best way to ensure you have the latest features and bug fixes. Details for each supported platform, including dependency package listings, permissions, and other gotchas, are in the developer’s documentation.
|
Building FRR from source is the best way to ensure you have the latest features and bug fixes. Details for each supported platform, including dependency package listings, permissions, and other gotchas, are in the developer’s documentation.
|
||||||
|
|
|
@ -35,7 +35,7 @@ corestart() {
|
||||||
echo "$NAME already started"
|
echo "$NAME already started"
|
||||||
else
|
else
|
||||||
echo "starting $NAME"
|
echo "starting $NAME"
|
||||||
sudo $CMD 2>&1 >> "$LOG" &
|
$CMD 2>&1 >> "$LOG" &
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo $! > "$PIDFILE"
|
echo $! > "$PIDFILE"
|
||||||
|
|
Loading…
Reference in a new issue