updated new gui to properly update modified addresses for nodes, added validation for ip4/ip6, fixed redrawing edge labels when node addresses change

This commit is contained in:
Blake Harnden 2020-03-04 11:38:24 -08:00
parent 4093b2244a
commit 0d4a86f10e
3 changed files with 94 additions and 7 deletions

View file

@ -1,9 +1,11 @@
import logging import logging
import tkinter as tk import tkinter as tk
from functools import partial from functools import partial
from tkinter import ttk from tkinter import messagebox, ttk
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import netaddr
from core.gui import nodeutils from core.gui import nodeutils
from core.gui.appconfig import ICONS_PATH from core.gui.appconfig import ICONS_PATH
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
@ -18,6 +20,58 @@ if TYPE_CHECKING:
from core.gui.graph.node import CanvasNode from core.gui.graph.node import CanvasNode
def check_ip6(parent, name: str, value: str) -> bool:
title = f"IP6 Error for {name}"
if not value:
messagebox.showerror(title, "Empty Value", parent=parent)
return False
values = value.split("/")
if len(values) != 2:
messagebox.showerror(
title, "Must be in the format address/prefix", parent=parent
)
return False
addr, mask = values
if not netaddr.valid_ipv6(addr):
messagebox.showerror(title, "Invalid IP6 address", parent=parent)
return False
try:
mask = int(mask)
if not (0 <= mask <= 128):
messagebox.showerror(title, "Mask must be between 0-128", parent=parent)
return False
except ValueError:
messagebox.showerror(title, "Invalid Mask", parent=parent)
return False
return True
def check_ip4(parent, name: str, value: str) -> bool:
title = f"IP4 Error for {name}"
if not value:
messagebox.showerror(title, "Empty Value", parent=parent)
return False
values = value.split("/")
if len(values) != 2:
messagebox.showerror(
title, "Must be in the format address/prefix", parent=parent
)
return False
addr, mask = values
if not netaddr.valid_ipv4(addr):
messagebox.showerror(title, "Invalid IP4 address", parent=parent)
return False
try:
mask = int(mask)
if not (0 <= mask <= 32):
messagebox.showerror(title, "Mask must be between 0-32", parent=parent)
return False
except ValueError:
messagebox.showerror(title, "Invalid mask", parent=parent)
return False
return True
def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry): def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry):
logging.info("mac auto clicked") logging.info("mac auto clicked")
if is_auto.get(): if is_auto.get():
@ -203,7 +257,6 @@ class NodeConfigDialog(Dialog):
label.grid(row=row, column=0, padx=PADX, pady=PADY) label.grid(row=row, column=0, padx=PADX, pady=PADY)
ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}") ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}")
entry = ttk.Entry(tab, textvariable=ip4) entry = ttk.Entry(tab, textvariable=ip4)
entry.bind("<FocusOut>", self.app.validation.ip_focus_out)
entry.grid(row=row, column=1, columnspan=2, sticky="ew") entry.grid(row=row, column=1, columnspan=2, sticky="ew")
row += 1 row += 1
@ -211,7 +264,6 @@ class NodeConfigDialog(Dialog):
label.grid(row=row, column=0, padx=PADX, pady=PADY) label.grid(row=row, column=0, padx=PADX, pady=PADY)
ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}") ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}")
entry = ttk.Entry(tab, textvariable=ip6) entry = ttk.Entry(tab, textvariable=ip6)
entry.bind("<FocusOut>", self.app.validation.ip_focus_out)
entry.grid(row=row, column=1, columnspan=2, sticky="ew") entry.grid(row=row, column=1, columnspan=2, sticky="ew")
self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6) self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6)
@ -240,6 +292,8 @@ class NodeConfigDialog(Dialog):
self.image_file = file_path self.image_file = file_path
def config_apply(self): def config_apply(self):
error = False
# update core node # update core node
self.node.name = self.name.get() self.node.name = self.name.get()
if NodeUtils.is_image_node(self.node.type): if NodeUtils.is_image_node(self.node.type):
@ -255,9 +309,31 @@ class NodeConfigDialog(Dialog):
# update canvas node # update canvas node
self.canvas_node.image = self.image self.canvas_node.image = self.image
# update node interface data
for interface in self.canvas_node.interfaces:
data = self.interfaces[interface.id]
if check_ip4(self, interface.name, data.ip4.get()):
ip4, ip4mask = data.ip4.get().split("/")
interface.ip4 = ip4
interface.ip4mask = int(ip4mask)
else:
error = True
data.ip4.set(f"{interface.ip4}/{interface.ip4mask}")
break
if check_ip6(self, interface.name, data.ip6.get()):
ip6, ip6mask = data.ip6.get().split("/")
interface.ip6 = ip6
interface.ip6mask = int(ip6mask)
interface.mac = data.mac.get()
else:
error = True
data.ip6.set(f"{interface.ip6}/{interface.ip6mask}")
break
# redraw # redraw
self.canvas_node.redraw() if not error:
self.destroy() self.canvas_node.redraw()
self.destroy()
def interface_select(self, event: tk.Event): def interface_select(self, event: tk.Event):
listbox = event.widget listbox = event.widget

View file

@ -107,8 +107,7 @@ class CanvasEdge:
y = (y1 + y2) / 2 y = (y1 + y2) / 2
return x, y return x, y
def draw_labels(self): def create_labels(self):
x1, y1, x2, y2 = self.get_coordinates()
label_one = None label_one = None
if self.link.HasField("interface_one"): if self.link.HasField("interface_one"):
label_one = ( label_one = (
@ -121,6 +120,11 @@ class CanvasEdge:
f"{self.link.interface_two.ip4}/{self.link.interface_two.ip4mask}\n" f"{self.link.interface_two.ip4}/{self.link.interface_two.ip4mask}\n"
f"{self.link.interface_two.ip6}/{self.link.interface_two.ip6mask}\n" f"{self.link.interface_two.ip6}/{self.link.interface_two.ip6mask}\n"
) )
return label_one, label_two
def draw_labels(self):
x1, y1, x2, y2 = self.get_coordinates()
label_one, label_two = self.create_labels()
self.text_src = self.canvas.create_text( self.text_src = self.canvas.create_text(
x1, x1,
y1, y1,
@ -138,6 +142,11 @@ class CanvasEdge:
tags=tags.LINK_INFO, tags=tags.LINK_INFO,
) )
def redraw(self):
label_one, label_two = self.create_labels()
self.canvas.itemconfig(self.text_src, text=label_one)
self.canvas.itemconfig(self.text_dst, text=label_two)
def update_labels(self): def update_labels(self):
""" """
Move edge labels based on current position. Move edge labels based on current position.

View file

@ -107,6 +107,8 @@ class CanvasNode:
def redraw(self): def redraw(self):
self.canvas.itemconfig(self.id, image=self.image) self.canvas.itemconfig(self.id, image=self.image)
self.canvas.itemconfig(self.text_id, text=self.core_node.name) self.canvas.itemconfig(self.text_id, text=self.core_node.name)
for edge in self.edges:
edge.redraw()
def _get_label_y(self): def _get_label_y(self):
image_box = self.canvas.bbox(self.id) image_box = self.canvas.bbox(self.id)