Compare commits

...

2 commits

4 changed files with 197 additions and 7 deletions

View file

@ -1,4 +1,5 @@
import tkinter as tk import tkinter as tk
import webbrowser
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -41,3 +42,7 @@ class Dialog(tk.Toplevel):
frame.grid(row=row, sticky="nsew") frame.grid(row=row, sticky="nsew")
frame.rowconfigure(0, weight=1) frame.rowconfigure(0, weight=1)
self.top.rowconfigure(frame.grid_info()["row"], weight=1) self.top.rowconfigure(frame.grid_info()["row"], weight=1)
@classmethod
def navigate_link(cls, link: str):
webbrowser.open_new(link)

View file

@ -3,6 +3,7 @@ emane configuration
""" """
import tkinter as tk import tkinter as tk
import webbrowser import webbrowser
from enum import Enum
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
@ -20,6 +21,18 @@ if TYPE_CHECKING:
from core.gui.graph.node import CanvasNode from core.gui.graph.node import CanvasNode
class EmaneModelEnum(Enum):
RFPIPE = "emane_rfpipe"
IEEE80211ABG = "emane_ieee80211abg"
COMMEFFECT = "emane_commeffect"
BYPASS = "emane_bypass"
TDMA = "emane_tdma"
def get_model(enum_class: EmaneModelEnum):
return enum_class.value
class GlobalEmaneDialog(Dialog): class GlobalEmaneDialog(Dialog):
def __init__(self, master: Any, app: "Application"): def __init__(self, master: Any, app: "Application"):
super().__init__(master, app, "EMANE Configuration", modal=True) super().__init__(master, app, "EMANE Configuration", modal=True)
@ -38,7 +51,7 @@ class GlobalEmaneDialog(Dialog):
def draw_buttons(self): def draw_buttons(self):
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.grid(sticky="ew") frame.grid(sticky="ew")
for i in range(2): for i in range(3):
frame.columnconfigure(i, weight=1) frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Apply", command=self.click_apply) button = ttk.Button(frame, text="Apply", command=self.click_apply)
button.grid(row=0, column=0, sticky="ew", padx=PADX) button.grid(row=0, column=0, sticky="ew", padx=PADX)
@ -46,6 +59,15 @@ class GlobalEmaneDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=self.destroy) button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
button = ttk.Button(
frame,
text="Info Link",
command=lambda: self.navigate_link(
"https://github.com/adjacentlink/emane/wiki/Configuring-the-Emulator"
),
)
button.grid(row=0, column=2, sticky="ew")
def click_apply(self): def click_apply(self):
self.config_frame.parse_config() self.config_frame.parse_config()
self.destroy() self.destroy()
@ -86,7 +108,7 @@ class EmaneModelDialog(Dialog):
def draw_buttons(self): def draw_buttons(self):
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.grid(sticky="ew") frame.grid(sticky="ew")
for i in range(2): for i in range(3):
frame.columnconfigure(i, weight=1) frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Apply", command=self.click_apply) button = ttk.Button(frame, text="Apply", command=self.click_apply)
button.grid(row=0, column=0, sticky="ew", padx=PADX) button.grid(row=0, column=0, sticky="ew", padx=PADX)
@ -94,6 +116,9 @@ class EmaneModelDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=self.destroy) button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
button = ttk.Button(frame, text="Info Link ", command=self.wiki_link)
button.grid(row=0, column=2, sticky="ew")
def click_apply(self): def click_apply(self):
self.config_frame.parse_config() self.config_frame.parse_config()
self.app.core.set_emane_model_config( self.app.core.set_emane_model_config(
@ -101,6 +126,24 @@ class EmaneModelDialog(Dialog):
) )
self.destroy() self.destroy()
def wiki_link(self):
if self.model == get_model(EmaneModelEnum.RFPIPE):
self.navigate_link(
"https://github.com/adjacentlink/emane/wiki/RF-Pipe-Model"
)
elif self.model == get_model(EmaneModelEnum.COMMEFFECT):
self.navigate_link(
"https://github.com/adjacentlink/emane/wiki/Comm-Effect-Model"
)
elif self.model == get_model(EmaneModelEnum.TDMA):
self.navigate_link("https://github.com/adjacentlink/emane/wiki/TDMA-Model")
elif self.model == get_model(EmaneModelEnum.IEEE80211ABG):
self.navigate_link(
"https://github.com/adjacentlink/emane/wiki/IEEE-802.11abg-Model"
)
else:
return
class EmaneConfigDialog(Dialog): class EmaneConfigDialog(Dialog):
def __init__( def __init__(

View file

@ -133,11 +133,12 @@ class NodeServiceDialog(Dialog):
def click_configure(self): def click_configure(self):
current_selection = self.current.listbox.curselection() current_selection = self.current.listbox.curselection()
service_name = self.current.listbox.get(current_selection[0])
if len(current_selection): if len(current_selection):
dialog = ServiceConfigDialog( dialog = ServiceConfigDialog(
master=self, master=self,
app=self.app, app=self.app,
service_name=self.current.listbox.get(current_selection[0]), service_name=service_name,
node_id=self.node_id, node_id=self.node_id,
) )
dialog.show() dialog.show()

View file

@ -65,7 +65,7 @@ class ServiceConfigDialog(Dialog):
self.temp_service_files = {} self.temp_service_files = {}
self.modified_files = set() self.modified_files = set()
self.load() self.load()
self.draw() # self.draw()
def load(self): def load(self):
try: try:
@ -108,8 +108,12 @@ class ServiceConfigDialog(Dialog):
): ):
for file, data in file_configs[self.node_id][self.service_name].items(): for file, data in file_configs[self.node_id][self.service_name].items():
self.temp_service_files[file] = data self.temp_service_files[file] = data
self.draw()
except grpc.RpcError as e: except grpc.RpcError as e:
show_grpc_error(e) if not self.is_ipsec():
show_grpc_error(e)
else:
self.draw()
def draw(self): def draw(self):
self.top.columnconfigure(0, weight=1) self.top.columnconfigure(0, weight=1)
@ -127,13 +131,139 @@ class ServiceConfigDialog(Dialog):
# draw notebook # draw notebook
self.notebook = ttk.Notebook(self.top) self.notebook = ttk.Notebook(self.top)
self.notebook.grid(sticky="nsew", pady=PADY) self.notebook.grid(sticky="nsew", pady=PADY)
self.draw_tab_files() if not self.is_ipsec():
self.draw_tab_files()
else:
self.draw_ipsec_tab()
self.draw_tab_directories() self.draw_tab_directories()
self.draw_tab_startstop() self.draw_tab_startstop()
self.draw_tab_configuration() self.draw_tab_configuration()
self.draw_buttons() self.draw_buttons()
def draw_ipsec_tab(self):
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
tab.grid(sticky="nsew")
tab.columnconfigure(0, weight=1)
self.notebook.add(tab, text="IPsec")
text = (
"This IPsec service helper will assist with building an ipsec.sh file (located on the Files tab).\nThe IPsec service builds ESP tunnels between"
"the specified peers using the racoon IKEv2\nkeying daemon. You need to provide keys and the addresses of peers, along with the\nsubnet to tunnel."
)
label = ttk.Label(tab, text=text)
label.grid(row=0, column=0, sticky="nsew")
label_frame = ttk.LabelFrame(tab, text="Keys", padding=FRAME_PAD)
label_frame.grid(row=1, column=0, sticky="nsew")
label_frame.columnconfigure(0, weight=1)
for i in range(3):
label_frame.rowconfigure(i, weight=1)
frame = ttk.Frame(label_frame, padding=FRAME_PAD)
frame.grid(row=0, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=2)
frame.columnconfigure(2, weight=1)
label = ttk.Label(frame, text="Key directory: ")
label.grid(row=0, column=0, sticky="ew")
entry = ttk.Entry(frame)
entry.grid(row=0, column=1, stick="ew")
button = ttk.Button(frame, text="...")
button.grid(row=0, column=2, sticky="ew")
frame = ttk.Frame(label_frame, padding=FRAME_PAD)
frame.grid(row=1, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
label = ttk.Label(frame, text="Key base name: ")
label.grid(row=0, column=0, sticky="ew")
entry = ttk.Entry(frame)
entry.grid(row=0, column=1, sticky="ew")
text = (
"The (name).pem x509 certificate and (name).key RSA private key need to exist in the\n"
"specified directory. These can be generated using the openssl tool. Also, a ca-cert.pem\n"
"file should exist in the key directory for the CA that issue the certs."
)
label = ttk.Label(label_frame, text=text, padding=FRAME_PAD)
label.grid(row=2, column=0, sticky="ew")
label_frame = ttk.LabelFrame(
tab, text="IPsec Tunnel Endpoints", padding=FRAME_PAD
)
label_frame.grid(row=2, column=0, sticky="nsew")
i = 0
text = (
"(1) Define tunnel endpoints (select peer node using the button, then select"
"address from the list)"
)
label = ttk.Label(label_frame, text=text, padding=FRAME_PAD)
label.grid(row=i, column=0, sticky="nsew")
i = i + 1
frame = ttk.Frame(label_frame, padding=FRAME_PAD)
frame.grid(row=i, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
i = i + 1
label = ttk.Label(frame, text="Local: ")
label.grid(row=0, column=0, sticky="ew")
combobox = ttk.Combobox(frame)
combobox.grid(row=0, column=1, sticky="ew")
frame = ttk.Frame(label_frame, padding=FRAME_PAD)
frame.grid(row=i, column=0, sticky="nsew")
i = i + 1
label = ttk.Label(frame, text="Peer node: (none)")
label.grid(row=0, column=0)
frame = ttk.Frame(label_frame, padding=FRAME_PAD)
frame.grid(row=i, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
i = i + 1
label = ttk.Label(frame, text="Peer: ")
label.grid(row=0, column=0, sticky="ew")
combobox = ttk.Combobox(frame)
combobox.grid(row=0, column=1, sticky="ew")
text = "(2) Select endpoints below and add the subnets to be encrypted"
label = ttk.Label(label_frame, text=text, padding=FRAME_PAD)
label.grid(row=i, column=0, sticky="ew")
i = i + i
frame = ttk.Frame(label_frame, padding=FRAME_PAD)
frame.grid(row=i, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
i = i + 1
label = ttk.Label(frame, text="Local subnet: ")
label.grid(row=0, column=0, sticky="ew")
combobox = ttk.Combobox(frame)
combobox.grid(row=0, column=1, sticky="ew")
frame = ttk.Frame(label_frame, padding=FRAME_PAD)
frame.grid(row=i, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
i = i + 1
label = ttk.Label(frame, text="Remote subnet: ")
label.grid(row=0, column=0, sticky="ew")
combobox = ttk.Combobox(frame)
combobox.grid(row=0, column=1, sticky="ew")
frame = ttk.Frame(tab, padding=FRAME_PAD)
frame.grid(row=3, column=0, sticky="nsew")
for i in range(2):
frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Trash")
button.grid(row=0, column=0, sticky="ew")
button = ttk.Button(frame, text="Generate ipsec.sh")
button.grid(row=0, column=1, sticky="ew")
def draw_tab_files(self): def draw_tab_files(self):
tab = ttk.Frame(self.notebook, padding=FRAME_PAD) tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
tab.grid(sticky="nsew") tab.grid(sticky="nsew")
@ -342,7 +472,7 @@ class ServiceConfigDialog(Dialog):
def draw_buttons(self): def draw_buttons(self):
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.grid(sticky="ew") frame.grid(sticky="ew")
for i in range(4): for i in range(5):
frame.columnconfigure(i, weight=1) frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Apply", command=self.click_apply) button = ttk.Button(frame, text="Apply", command=self.click_apply)
button.grid(row=0, column=0, sticky="ew", padx=PADX) button.grid(row=0, column=0, sticky="ew", padx=PADX)
@ -352,6 +482,14 @@ class ServiceConfigDialog(Dialog):
button.grid(row=0, column=2, sticky="ew", padx=PADX) button.grid(row=0, column=2, sticky="ew", padx=PADX)
button = ttk.Button(frame, text="Cancel", command=self.destroy) button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=3, sticky="ew") button.grid(row=0, column=3, sticky="ew")
button = ttk.Button(
frame,
text="Info Link",
command=lambda: self.navigate_link(
"http://coreemu.github.io/core/services.html"
),
)
button.grid(row=0, column=4, sticky="ew")
def add_filename(self, event: tk.Event): def add_filename(self, event: tk.Event):
# not worry about it for now # not worry about it for now
@ -504,3 +642,6 @@ class ServiceConfigDialog(Dialog):
for cmd in to_add: for cmd in to_add:
commands.append(cmd) commands.append(cmd)
listbox.insert(tk.END, cmd) listbox.insert(tk.END, cmd)
def is_ipsec(self):
return self.service_name == "IPsec"