Merge branch 'coretk' of https://github.com/coreemu/core into coretk
This commit is contained in:
commit
b9a5c428cc
5 changed files with 107 additions and 47 deletions
|
@ -1,12 +1,14 @@
|
|||
"""
|
||||
Incorporate grpc into python tkinter GUI
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
|
||||
from core.api.grpc import client, core_pb2
|
||||
from coretk.dialogs.mobilityplayer import MobilityPlayerDialog
|
||||
from coretk import appconfig
|
||||
from coretk.dialogs.mobilityplayer import MobilityPlayer
|
||||
from coretk.dialogs.sessions import SessionsDialog
|
||||
from coretk.interface import InterfaceManager
|
||||
from coretk.nodeutils import NodeDraw, NodeUtils
|
||||
|
@ -141,6 +143,8 @@ class CoreClient:
|
|||
logging.warning("unknown session event: %s", session_event)
|
||||
elif event.HasField("node_event"):
|
||||
self.handle_node_event(event.node_event)
|
||||
elif event.HasField("config_event"):
|
||||
logging.info("config event: %s", event)
|
||||
else:
|
||||
logging.info("unhandled event: %s", event)
|
||||
|
||||
|
@ -164,7 +168,7 @@ class CoreClient:
|
|||
x = event.node.position.x
|
||||
y = event.node.position.y
|
||||
canvas_node = self.canvas_nodes[node_id]
|
||||
canvas_node.move(x, y)
|
||||
canvas_node.move(x, y, update=False)
|
||||
|
||||
def handle_throughputs(self, event):
|
||||
interface_throughputs = event.interface_throughputs
|
||||
|
@ -189,7 +193,6 @@ class CoreClient:
|
|||
|
||||
# get session data
|
||||
response = self.client.get_session(self.session_id)
|
||||
logging.info("joining session(%s): %s", self.session_id, response)
|
||||
session = response.session
|
||||
self.state = session.state
|
||||
self.client.events(self.session_id, self.handle_events)
|
||||
|
@ -208,12 +211,6 @@ class CoreClient:
|
|||
for hook in response.hooks:
|
||||
self.hooks[hook.file] = hook
|
||||
|
||||
# get wlan configs
|
||||
for node in session.nodes:
|
||||
if node.type == core_pb2.NodeType.WIRELESS_LAN:
|
||||
response = self.client.get_wlan_config(self.session_id, node.id)
|
||||
self.wlan_configs[node.id] = response.config
|
||||
|
||||
# get mobility configs
|
||||
response = self.client.get_mobility_configs(self.session_id)
|
||||
for node_id in response.configs:
|
||||
|
@ -235,16 +232,17 @@ class CoreClient:
|
|||
node_id = int(_id / 1000)
|
||||
self.set_emane_model_config(node_id, config.model, config.config, interface)
|
||||
|
||||
# draw session
|
||||
self.app.canvas.reset_and_redraw(session)
|
||||
|
||||
# get node service config and file config
|
||||
# save and retrieve data, needed for session nodes
|
||||
for node in session.nodes:
|
||||
# get node service config and file config
|
||||
self.created_nodes.add(node.id)
|
||||
for link in session.links:
|
||||
self.created_links.add(tuple(sorted([link.node_one_id, link.node_two_id])))
|
||||
for node in session.nodes:
|
||||
if node.type == core_pb2.NodeType.DEFAULT:
|
||||
|
||||
# get wlan configs for wlan nodes
|
||||
if node.type == core_pb2.NodeType.WIRELESS_LAN:
|
||||
response = self.client.get_wlan_config(self.session_id, node.id)
|
||||
self.wlan_configs[node.id] = response.config
|
||||
# retrieve service configurations data for default nodes
|
||||
elif node.type == core_pb2.NodeType.DEFAULT:
|
||||
for service in node.services:
|
||||
response = self.client.get_node_service(
|
||||
self.session_id, node.id, service
|
||||
|
@ -262,6 +260,17 @@ class CoreClient:
|
|||
self.file_configs[node.id][service] = {}
|
||||
self.file_configs[node.id][service][file] = response.data
|
||||
|
||||
# store links as created links
|
||||
for link in session.links:
|
||||
self.created_links.add(tuple(sorted([link.node_one_id, link.node_two_id])))
|
||||
|
||||
# draw session
|
||||
self.app.canvas.reset_and_redraw(session)
|
||||
|
||||
# get metadata
|
||||
response = self.client.get_session_metadata(self.session_id)
|
||||
self.parse_metadata(response.config)
|
||||
|
||||
if self.is_runtime():
|
||||
self.app.toolbar.runtime_frame.tkraise()
|
||||
else:
|
||||
|
@ -271,6 +280,18 @@ class CoreClient:
|
|||
def is_runtime(self):
|
||||
return self.state == core_pb2.SessionState.RUNTIME
|
||||
|
||||
def parse_metadata(self, config):
|
||||
# canvas settings
|
||||
canvas_config = config.get("canvas")
|
||||
if canvas_config:
|
||||
logging.info("canvas metadata: %s", canvas_config)
|
||||
canvas_config = json.loads(canvas_config)
|
||||
wallpaper_style = canvas_config["wallpaper-style"]
|
||||
self.app.canvas.scale_option.set(wallpaper_style)
|
||||
wallpaper = canvas_config["wallpaper"]
|
||||
wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
|
||||
self.app.canvas.set_wallpaper(wallpaper)
|
||||
|
||||
def create_new_session(self):
|
||||
"""
|
||||
Create a new session
|
||||
|
@ -372,9 +393,9 @@ class CoreClient:
|
|||
# display mobility players
|
||||
for node_id, config in self.mobility_configs.items():
|
||||
canvas_node = self.canvas_nodes[node_id]
|
||||
dialog = MobilityPlayerDialog(self.app, self.app, canvas_node, config)
|
||||
dialog.show()
|
||||
self.mobility_players[node_id] = dialog
|
||||
mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config)
|
||||
mobility_player.show()
|
||||
self.mobility_players[node_id] = mobility_player
|
||||
|
||||
def stop_session(self, session_id=None):
|
||||
if not session_id:
|
||||
|
|
|
@ -269,7 +269,7 @@ router ospf6
|
|||
<configuration name="annotation a0" value="{iconcoords {612.0 492.0}} {type text} {label {wireless network}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {effects {bold}} {canvas c1}"/>
|
||||
<configuration name="annotation a1" value="{iconcoords {142.0 112.0 393.0 291.0}} {type rectangle} {label {}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {color #ebebde} {width 1} {border #ffffff} {rad 25} {canvas c1}"/>
|
||||
<configuration name="annotation a2" value="{iconcoords {492.0 384.0}} {type text} {label {gateway}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {effects {bold}} {canvas c1}"/>
|
||||
<configuration name="canvas c1" value="{name {Canvas1}} {wallpaper-style {upperleft}} {wallpaper {sample1-bg.gif}}"/>
|
||||
<configuration name="canvas" value='{"name": "Canvas1", "wallpaper-style": 1, "wallpaper": "sample1-bg.gif"}'/>
|
||||
<configuration name="global_options" value="interface_names=no ip_addresses=yes ipv6_addresses=no node_labels=yes link_labels=yes show_api=no background_images=no annotations=yes grid=no traffic_start=0"/>
|
||||
</session_metadata>
|
||||
<default_services>
|
||||
|
|
|
@ -5,14 +5,11 @@ import logging
|
|||
import tkinter as tk
|
||||
from tkinter import filedialog, ttk
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from coretk.appconfig import BACKGROUNDS_PATH
|
||||
from coretk.dialogs.dialog import Dialog
|
||||
from coretk.images import Images
|
||||
|
||||
PADX = 5
|
||||
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
|
||||
|
||||
|
||||
class CanvasBackgroundDialog(Dialog):
|
||||
|
@ -178,23 +175,11 @@ class CanvasBackgroundDialog(Dialog):
|
|||
|
||||
filename = self.filename.get()
|
||||
if not filename:
|
||||
self.canvas.delete(self.canvas.wallpaper_id)
|
||||
self.canvas.wallpaper = None
|
||||
self.canvas.wallpaper_file = None
|
||||
self.destroy()
|
||||
return
|
||||
try:
|
||||
img = Image.open(filename)
|
||||
self.canvas.wallpaper = img
|
||||
self.canvas.wallpaper_file = filename
|
||||
self.canvas.redraw()
|
||||
for component in ABOVE_WALLPAPER:
|
||||
self.canvas.tag_raise(component)
|
||||
filename = None
|
||||
|
||||
try:
|
||||
self.canvas.set_wallpaper(filename)
|
||||
except FileNotFoundError:
|
||||
logging.error("invalid background: %s", filename)
|
||||
if self.canvas.wallpaper_id:
|
||||
self.canvas.delete(self.canvas.wallpaper_id)
|
||||
self.canvas.wallpaper_id = None
|
||||
self.canvas.wallpaper_file = None
|
||||
|
||||
self.destroy()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from core.api.grpc.core_pb2 import MobilityAction
|
||||
from coretk.dialogs.dialog import Dialog
|
||||
from coretk.images import ImageEnum, Images
|
||||
|
||||
|
@ -9,6 +9,42 @@ PAD = 5
|
|||
ICON_SIZE = 16
|
||||
|
||||
|
||||
class MobilityPlayer:
|
||||
def __init__(self, master, app, canvas_node, config):
|
||||
self.master = master
|
||||
self.app = app
|
||||
self.canvas_node = canvas_node
|
||||
self.config = config
|
||||
self.dialog = None
|
||||
self.state = None
|
||||
|
||||
def show(self):
|
||||
if self.dialog:
|
||||
self.dialog.destroy()
|
||||
self.dialog = MobilityPlayerDialog(
|
||||
self.master, self.app, self.canvas_node, self.config
|
||||
)
|
||||
if self.state == MobilityAction.START:
|
||||
self.set_play()
|
||||
elif self.state == MobilityAction.PAUSE:
|
||||
self.set_pause()
|
||||
else:
|
||||
self.set_stop()
|
||||
self.dialog.show()
|
||||
|
||||
def set_play(self):
|
||||
self.dialog.set_play()
|
||||
self.state = MobilityAction.START
|
||||
|
||||
def set_pause(self):
|
||||
self.dialog.set_pause()
|
||||
self.state = MobilityAction.PAUSE
|
||||
|
||||
def set_stop(self):
|
||||
self.dialog.set_stop()
|
||||
self.state = MobilityAction.STOP
|
||||
|
||||
|
||||
class MobilityPlayerDialog(Dialog):
|
||||
def __init__(self, master, app, canvas_node, config):
|
||||
super().__init__(
|
||||
|
@ -88,19 +124,19 @@ class MobilityPlayerDialog(Dialog):
|
|||
self.set_play()
|
||||
session_id = self.app.core.session_id
|
||||
self.app.core.client.mobility_action(
|
||||
session_id, self.node.id, core_pb2.MobilityAction.START
|
||||
session_id, self.node.id, MobilityAction.START
|
||||
)
|
||||
|
||||
def click_pause(self):
|
||||
self.set_pause()
|
||||
session_id = self.app.core.session_id
|
||||
self.app.core.client.mobility_action(
|
||||
session_id, self.node.id, core_pb2.MobilityAction.PAUSE
|
||||
session_id, self.node.id, MobilityAction.PAUSE
|
||||
)
|
||||
|
||||
def click_stop(self):
|
||||
self.set_stop()
|
||||
session_id = self.app.core.session_id
|
||||
self.app.core.client.mobility_action(
|
||||
session_id, self.node.id, core_pb2.MobilityAction.STOP
|
||||
session_id, self.node.id, MobilityAction.STOP
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ import logging
|
|||
import tkinter as tk
|
||||
from tkinter import font
|
||||
|
||||
from PIL import ImageTk
|
||||
from PIL import Image, ImageTk
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from core.api.grpc.core_pb2 import NodeType
|
||||
|
@ -21,6 +21,7 @@ from coretk.nodeutils import NodeUtils
|
|||
from coretk.shape import Shape
|
||||
|
||||
NODE_TEXT_OFFSET = 5
|
||||
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
|
||||
|
||||
|
||||
class GraphMode(enum.Enum):
|
||||
|
@ -598,6 +599,21 @@ class CanvasGraph(tk.Canvas):
|
|||
else:
|
||||
self.itemconfig("gridline", state=tk.HIDDEN)
|
||||
|
||||
def set_wallpaper(self, filename):
|
||||
logging.info("setting wallpaper: %s", filename)
|
||||
if filename is not None:
|
||||
img = Image.open(filename)
|
||||
self.wallpaper = img
|
||||
self.wallpaper_file = filename
|
||||
self.redraw()
|
||||
for component in ABOVE_WALLPAPER:
|
||||
self.tag_raise(component)
|
||||
else:
|
||||
if self.wallpaper_id is not None:
|
||||
self.delete(self.wallpaper_id)
|
||||
self.wallpaper = None
|
||||
self.wallpaper_file = None
|
||||
|
||||
def is_selection_mode(self):
|
||||
return self.mode == GraphMode.SELECT
|
||||
|
||||
|
@ -711,7 +727,7 @@ class CanvasNode:
|
|||
self.canvas.itemconfig(self.id, image=self.image)
|
||||
self.canvas.itemconfig(self.text_id, text=self.core_node.name)
|
||||
|
||||
def move(self, x, y):
|
||||
def move(self, x, y, update=True):
|
||||
old_x = self.core_node.position.x
|
||||
old_y = self.core_node.position.y
|
||||
x_offset = x - old_x
|
||||
|
@ -735,7 +751,7 @@ class CanvasNode:
|
|||
self.canvas.coords(edge.id, x, y, x2, y2)
|
||||
else:
|
||||
self.canvas.coords(edge.id, x1, y1, x, y)
|
||||
if self.app.core.is_runtime():
|
||||
if self.app.core.is_runtime() and update:
|
||||
self.app.core.edit_node(self.core_node.id, int(x), int(y))
|
||||
|
||||
def on_enter(self, event):
|
||||
|
@ -812,6 +828,8 @@ class CanvasNode:
|
|||
|
||||
def show_mobility_player(self):
|
||||
self.canvas.context = None
|
||||
mobility_player = self.app.core.mobility_players[self.core_node.id]
|
||||
mobility_player.show()
|
||||
|
||||
def show_emane_config(self):
|
||||
self.canvas.context = None
|
||||
|
|
Loading…
Add table
Reference in a new issue