pygui moved observers to menu class, added initial functioning ip address tool

This commit is contained in:
Blake Harnden 2020-04-21 22:56:56 -07:00
parent 20ecdf70d0
commit ba6a6f06b1
7 changed files with 254 additions and 29 deletions

View file

@ -37,6 +37,10 @@ TERMINALS = {
"gnome-terminal": "gnome-terminal --window --",
}
EDITORS = ["$EDITOR", "vim", "emacs", "gedit", "nano", "vi"]
DEFAULT_IP4S = ["10.0.0.0", "192.168.0.0", "172.16.0.0"]
DEFAULT_IP4 = DEFAULT_IP4S[0]
DEFAULT_IP6S = ["2001::", "2002::", "a::"]
DEFAULT_IP6 = DEFAULT_IP6S[0]
class IndentDumper(yaml.Dumper):
@ -98,11 +102,17 @@ def check_directory():
"alt": 2.0,
"scale": 150.0,
},
"servers": [{"name": "example", "address": "127.0.0.1", "port": 50051}],
"servers": [],
"nodes": [],
"recentfiles": [],
"observers": [{"name": "hello", "cmd": "echo hello"}],
"observers": [],
"scale": 1.0,
"ips": {
"ip4": DEFAULT_IP4,
"ip6": DEFAULT_IP6,
"ip4s": DEFAULT_IP4S,
"ip6s": DEFAULT_IP6S,
},
}
save(config)

View file

@ -31,17 +31,6 @@ if TYPE_CHECKING:
from core.gui.app import Application
GUI_SOURCE = "gui"
OBSERVERS = {
"List Processes": "ps",
"Show Interfaces": "ip address",
"IPV4 Routes": "ip -4 ro",
"IPV6 Routes": "ip -6 ro",
"Listening Sockets": "netstat -tuwnl",
"IPv4 MFC Entries": "ip -4 mroute show",
"IPv6 MFC Entries": "ip -6 mroute show",
"Firewall Rules": "iptables -L",
"IPSec Policies": "setkey -DP",
}
class CoreServer:

View file

@ -0,0 +1,153 @@
import tkinter as tk
from tkinter import messagebox, ttk
from typing import TYPE_CHECKING
import netaddr
from core.gui import appconfig
from core.gui.dialogs.dialog import Dialog
from core.gui.themes import FRAME_PAD, PADX, PADY
from core.gui.widgets import ListboxScroll
if TYPE_CHECKING:
from core.gui.app import Application
class IpConfigDialog(Dialog):
def __init__(self, master: "Application", app: "Application") -> None:
super().__init__(master, app, "IP Configuration", modal=True)
ip_config = self.app.guiconfig.setdefault("ips")
self.ip4 = ip_config.setdefault("ip4", appconfig.DEFAULT_IP4)
self.ip6 = ip_config.setdefault("ip6", appconfig.DEFAULT_IP6)
self.ip4s = ip_config.setdefault("ip4s", appconfig.DEFAULT_IP4S)
self.ip6s = ip_config.setdefault("ip6s", appconfig.DEFAULT_IP6S)
self.ip4_entry = None
self.ip4_listbox = None
self.ip6_entry = None
self.ip6_listbox = None
self.draw()
def draw(self) -> None:
self.top.columnconfigure(0, weight=1)
self.top.rowconfigure(0, weight=1)
# draw ip4 and ip6 lists
frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
frame.rowconfigure(0, weight=1)
frame.grid(sticky="nsew", pady=PADY)
ip4_frame = ttk.LabelFrame(frame, text="IPv4", padding=FRAME_PAD)
ip4_frame.columnconfigure(0, weight=1)
ip4_frame.rowconfigure(0, weight=1)
ip4_frame.grid(row=0, column=0, stick="nsew")
self.ip4_listbox = ListboxScroll(ip4_frame)
self.ip4_listbox.listbox.bind("<<ListboxSelect>>", self.select_ip4)
self.ip4_listbox.grid(sticky="nsew", pady=PADY)
for index, ip4 in enumerate(self.ip4s):
self.ip4_listbox.listbox.insert(tk.END, ip4)
if self.ip4 == ip4:
self.ip4_listbox.listbox.select_set(index)
self.ip4_entry = ttk.Entry(ip4_frame)
self.ip4_entry.grid(sticky="ew", pady=PADY)
ip4_button_frame = ttk.Frame(ip4_frame)
ip4_button_frame.columnconfigure(0, weight=1)
ip4_button_frame.columnconfigure(1, weight=1)
ip4_button_frame.grid(sticky="ew")
ip4_add = ttk.Button(ip4_button_frame, text="Add", command=self.click_add_ip4)
ip4_add.grid(row=0, column=0, sticky="ew")
ip4_del = ttk.Button(
ip4_button_frame, text="Delete", command=self.click_del_ip4
)
ip4_del.grid(row=0, column=1, sticky="ew")
ip6_frame = ttk.LabelFrame(frame, text="IPv6", padding=FRAME_PAD)
ip6_frame.columnconfigure(0, weight=1)
ip6_frame.rowconfigure(0, weight=1)
ip6_frame.grid(row=0, column=1, stick="nsew")
self.ip6_listbox = ListboxScroll(ip6_frame)
self.ip6_listbox.listbox.bind("<<ListboxSelect>>", self.select_ip6)
self.ip6_listbox.grid(sticky="nsew", pady=PADY)
for index, ip6 in enumerate(self.ip6s):
self.ip6_listbox.listbox.insert(tk.END, ip6)
if self.ip6 == ip6:
self.ip6_listbox.listbox.select_set(index)
self.ip6_entry = ttk.Entry(ip6_frame)
self.ip6_entry.grid(sticky="ew", pady=PADY)
ip6_button_frame = ttk.Frame(ip6_frame)
ip6_button_frame.columnconfigure(0, weight=1)
ip6_button_frame.columnconfigure(1, weight=1)
ip6_button_frame.grid(sticky="ew")
ip6_add = ttk.Button(ip6_button_frame, text="Add", command=self.click_add_ip6)
ip6_add.grid(row=0, column=0, sticky="ew")
ip6_del = ttk.Button(
ip6_button_frame, text="Delete", command=self.click_del_ip6
)
ip6_del.grid(row=0, column=1, sticky="ew")
# draw buttons
frame = ttk.Frame(self.top)
frame.grid(stick="ew")
for i in range(2):
frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Save", command=self.click_save)
button.grid(row=0, column=0, sticky="ew", padx=PADX)
button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew")
def click_add_ip4(self) -> None:
ip4 = self.ip4_entry.get()
if not ip4 or not netaddr.valid_ipv4(ip4):
messagebox.showerror("IPv4 Error", f"Invalid IPv4 {ip4}")
else:
self.ip4_listbox.listbox.insert(tk.END, ip4)
def click_del_ip4(self) -> None:
if self.ip4_listbox.listbox.size() == 1:
messagebox.showerror("IPv4 Error", "Must have at least one address")
else:
selection = self.ip4_listbox.listbox.curselection()
self.ip4_listbox.listbox.delete(selection)
self.ip4_listbox.listbox.select_set(0)
def click_add_ip6(self) -> None:
ip6 = self.ip6_entry.get()
if not ip6 or not netaddr.valid_ipv6(ip6):
messagebox.showerror("IPv6 Error", f"Invalid IPv6 {ip6}")
else:
self.ip6_listbox.listbox.insert(tk.END, ip6)
def click_del_ip6(self) -> None:
if self.ip6_listbox.listbox.size() == 1:
messagebox.showerror("IPv6 Error", "Must have at least one address")
else:
selection = self.ip6_listbox.listbox.curselection()
self.ip6_listbox.listbox.delete(selection)
self.ip6_listbox.listbox.select_set(0)
def select_ip4(self, _event: tk.Event) -> None:
selection = self.ip4_listbox.listbox.curselection()
self.ip4 = self.ip4_listbox.listbox.get(selection)
def select_ip6(self, _event: tk.Event) -> None:
selection = self.ip6_listbox.listbox.curselection()
self.ip6 = self.ip6_listbox.listbox.get(selection)
def click_save(self) -> None:
ip4s = []
for index in range(self.ip4_listbox.listbox.size()):
ip4 = self.ip4_listbox.listbox.get(index)
ip4s.append(ip4)
ip6s = []
for index in range(self.ip6_listbox.listbox.size()):
ip6 = self.ip6_listbox.listbox.get(index)
ip6s.append(ip6)
ip_config = self.app.guiconfig["ips"]
ip_config["ip4"] = self.ip4
ip_config["ip6"] = self.ip6
ip_config["ip4s"] = ip4s
ip_config["ip6s"] = ip6s
self.app.core.interfaces_manager.update_ips(self.ip4, self.ip6)
self.app.save_config()
self.destroy()

View file

@ -0,0 +1,49 @@
from tkinter import ttk
from typing import TYPE_CHECKING
from core.gui.dialogs.dialog import Dialog
from core.gui.themes import PADX, PADY
if TYPE_CHECKING:
from core.gui.app import Application
class MacConfigDialog(Dialog):
def __init__(self, master: "Application", app: "Application") -> None:
super().__init__(master, app, "MAC Configuration", modal=True)
self.draw()
def draw(self) -> None:
self.top.columnconfigure(0, weight=1)
self.top.rowconfigure(0, weight=1)
# draw explanation label
text = (
"MAC addresses will be generated for nodes starting with the\n"
"provided value below and increment by value in order."
)
label = ttk.Label(self.top, text=text)
label.grid(sticky="ew", pady=PADY)
# draw input
frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
frame.grid(stick="ew", pady=PADY)
label = ttk.Label(frame, text="Starting MAC")
label.grid(row=0, column=0, sticky="ew", padx=PADX)
entry = ttk.Entry(frame)
entry.grid(row=0, column=1, sticky="ew")
# draw buttons
frame = ttk.Frame(self.top)
frame.grid(stick="ew")
for i in range(2):
frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Save", command=self.click_save)
button.grid(row=0, column=0, sticky="ew", padx=PADX)
button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew")
def click_save(self) -> None:
pass

View file

@ -32,21 +32,22 @@ class Subnets:
class InterfaceManager:
def __init__(
self,
app: "Application",
ip4: str = "10.0.0.0",
ip4_mask: int = 24,
ip6: str = "2001::",
ip6_mask=64,
) -> None:
def __init__(self, app: "Application") -> None:
self.app = app
self.ip4_mask = ip4_mask
self.ip6_mask = ip6_mask
self.ip4_subnets = IPNetwork(f"{ip4}/{ip4_mask}")
self.ip6_subnets = IPNetwork(f"{ip6}/{ip6_mask}")
ip_config = self.app.guiconfig.get("ips", {})
ip4 = ip_config.get("ip4", "10.0.0.0")
ip6 = ip_config.get("ip6", "2001::")
self.ip4_mask = 24
self.ip6_mask = 64
self.ip4_subnets = IPNetwork(f"{ip4}/{self.ip4_mask}")
self.ip6_subnets = IPNetwork(f"{ip6}/{self.ip6_mask}")
self.current_subnets = None
def update_ips(self, ip4: str, ip6: str) -> None:
self.reset()
self.ip4_subnets = IPNetwork(f"{ip4}/{self.ip4_mask}")
self.ip6_subnets = IPNetwork(f"{ip6}/{self.ip6_mask}")
def next_subnets(self) -> Subnets:
# define currently used subnets
used_subnets = set()

View file

@ -7,12 +7,13 @@ from tkinter import filedialog, messagebox
from typing import TYPE_CHECKING
from core.gui.appconfig import XMLS_PATH
from core.gui.coreclient import OBSERVERS
from core.gui.dialogs.about import AboutDialog
from core.gui.dialogs.canvassizeandscale import SizeAndScaleDialog
from core.gui.dialogs.canvaswallpaper import CanvasWallpaperDialog
from core.gui.dialogs.executepython import ExecutePythonDialog
from core.gui.dialogs.hooks import HooksDialog
from core.gui.dialogs.ipdialog import IpConfigDialog
from core.gui.dialogs.macdialog import MacConfigDialog
from core.gui.dialogs.observers import ObserverDialog
from core.gui.dialogs.preferences import PreferencesDialog
from core.gui.dialogs.servers import ServersDialog
@ -26,6 +27,17 @@ if TYPE_CHECKING:
from core.gui.app import Application
MAX_FILES = 3
OBSERVERS = {
"List Processes": "ps",
"Show Interfaces": "ip address",
"IPV4 Routes": "ip -4 ro",
"IPV6 Routes": "ip -6 ro",
"Listening Sockets": "netstat -tuwnl",
"IPv4 MFC Entries": "ip -4 mroute show",
"IPv6 MFC Entries": "ip -6 mroute show",
"Firewall Rules": "iptables -L",
"IPSec Policies": "setkey -DP",
}
class Menubar(tk.Menu):
@ -173,8 +185,8 @@ class Menubar(tk.Menu):
"""
menu = tk.Menu(self)
menu.add_command(label="Auto Grid", command=self.click_autogrid)
menu.add_command(label="IP Addresses", state=tk.DISABLED)
menu.add_command(label="MAC Addresses", state=tk.DISABLED)
menu.add_command(label="IP Addresses", command=self.click_ip_config)
menu.add_command(label="MAC Addresses", command=self.click_mac_config)
self.add_cascade(label="Tools", menu=menu)
def create_observer_widgets_menu(self, widget_menu: tk.Menu) -> None:
@ -465,3 +477,11 @@ class Menubar(tk.Menu):
def click_edge_label_change(self) -> None:
for edge in self.canvas.edges.values():
edge.draw_labels()
def click_mac_config(self) -> None:
dialog = MacConfigDialog(self.app, self.app)
dialog.show()
def click_ip_config(self) -> None:
dialog = IpConfigDialog(self.app, self.app)
dialog.show()

View file

@ -203,7 +203,10 @@ class ListboxScroll(ttk.Frame):
self.scrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL)
self.scrollbar.grid(row=0, column=1, sticky="ns")
self.listbox = tk.Listbox(
self, selectmode=tk.SINGLE, yscrollcommand=self.scrollbar.set
self,
selectmode=tk.BROWSE,
yscrollcommand=self.scrollbar.set,
exportselection=False,
)
themes.style_listbox(self.listbox)
self.listbox.grid(row=0, column=0, sticky="nsew")