fix merge conflict

This commit is contained in:
Huy Pham 2020-03-04 14:27:29 -08:00
commit 95d36a1792
9 changed files with 224 additions and 42 deletions

View file

@ -16,6 +16,7 @@ MOBILITY_PATH = HOME_PATH.joinpath("mobility")
XMLS_PATH = HOME_PATH.joinpath("xmls") XMLS_PATH = HOME_PATH.joinpath("xmls")
CONFIG_PATH = HOME_PATH.joinpath("gui.yaml") CONFIG_PATH = HOME_PATH.joinpath("gui.yaml")
LOG_PATH = HOME_PATH.joinpath("gui.log") LOG_PATH = HOME_PATH.joinpath("gui.log")
SCRIPT_PATH = HOME_PATH.joinpath("scripts")
# local paths # local paths
DATA_PATH = Path(__file__).parent.joinpath("data") DATA_PATH = Path(__file__).parent.joinpath("data")
@ -25,17 +26,16 @@ LOCAL_XMLS_PATH = DATA_PATH.joinpath("xmls").absolute()
LOCAL_MOBILITY_PATH = DATA_PATH.joinpath("mobility").absolute() LOCAL_MOBILITY_PATH = DATA_PATH.joinpath("mobility").absolute()
# configuration data # configuration data
TERMINALS = [ TERMINALS = {
"$TERM", "xterm": "xterm -e",
"gnome-terminal --window --", "aterm": "aterm -e",
"lxterminal -e", "eterm": "eterm -e",
"konsole -e", "rxvt": "rxvt -e",
"xterm -e", "konsole": "konsole -e",
"aterm -e", "lxterminal": "lxterminal -e",
"eterm -e", "xfce4-terminal": "xfce4-terminal -x",
"rxvt -e", "gnome-terminal": "gnome-terminal --window --",
"xfce4-terminal -x", }
]
EDITORS = ["$EDITOR", "vim", "emacs", "gedit", "nano", "vi"] EDITORS = ["$EDITOR", "vim", "emacs", "gedit", "nano", "vi"]
@ -50,6 +50,14 @@ def copy_files(current_path, new_path):
shutil.copy(current_file, new_file) shutil.copy(current_file, new_file)
def find_terminal():
for term in sorted(TERMINALS):
cmd = TERMINALS[term]
if shutil.which(term):
return cmd
return None
def check_directory(): def check_directory():
if HOME_PATH.exists(): if HOME_PATH.exists():
return return
@ -60,16 +68,14 @@ def check_directory():
ICONS_PATH.mkdir() ICONS_PATH.mkdir()
MOBILITY_PATH.mkdir() MOBILITY_PATH.mkdir()
XMLS_PATH.mkdir() XMLS_PATH.mkdir()
SCRIPT_PATH.mkdir()
copy_files(LOCAL_ICONS_PATH, ICONS_PATH) copy_files(LOCAL_ICONS_PATH, ICONS_PATH)
copy_files(LOCAL_BACKGROUND_PATH, BACKGROUNDS_PATH) copy_files(LOCAL_BACKGROUND_PATH, BACKGROUNDS_PATH)
copy_files(LOCAL_XMLS_PATH, XMLS_PATH) copy_files(LOCAL_XMLS_PATH, XMLS_PATH)
copy_files(LOCAL_MOBILITY_PATH, MOBILITY_PATH) copy_files(LOCAL_MOBILITY_PATH, MOBILITY_PATH)
if "TERM" in os.environ: terminal = find_terminal()
terminal = TERMINALS[0]
else:
terminal = TERMINALS[1]
if "EDITOR" in os.environ: if "EDITOR" in os.environ:
editor = EDITORS[0] editor = EDITORS[0]
else: else:

View file

@ -5,6 +5,7 @@ import json
import logging import logging
import os import os
from pathlib import Path from pathlib import Path
from tkinter import messagebox
from typing import TYPE_CHECKING, Dict, List from typing import TYPE_CHECKING, Dict, List
import grpc import grpc
@ -38,17 +39,6 @@ OBSERVERS = {
"IPSec policies": "setkey -DP", "IPSec policies": "setkey -DP",
} }
DEFAULT_TERMS = {
"xterm": "xterm -e",
"aterm": "aterm -e",
"eterm": "eterm -e",
"rxvt": "rxvt -e",
"konsole": "konsole -e",
"lxterminal": "lxterminal -e",
"xfce4-terminal": "xfce4-terminal -x",
"gnome-terminal": "gnome-terminal --window--",
}
class CoreServer: class CoreServer:
def __init__(self, name: str, address: str, port: int): def __init__(self, name: str, address: str, port: int):
@ -571,11 +561,15 @@ class CoreClient:
def launch_terminal(self, node_id: int): def launch_terminal(self, node_id: int):
try: try:
terminal = self.app.guiconfig["preferences"]["terminal"] terminal = self.app.guiconfig["preferences"]["terminal"]
if not terminal:
messagebox.showerror(
"Terminal Error",
"No terminal set, please set within the preferences menu",
parent=self.app,
)
return
response = self.client.get_node_terminal(self.session_id, node_id) response = self.client.get_node_terminal(self.session_id, node_id)
output = os.popen(f"echo {terminal}").read()[:-1] cmd = f"{terminal} {response.terminal} &"
if output in DEFAULT_TERMS:
terminal = DEFAULT_TERMS[output]
cmd = f'{terminal} "{response.terminal}" &'
logging.info("launching terminal %s", cmd) logging.info("launching terminal %s", cmd)
os.system(cmd) os.system(cmd)
except grpc.RpcError as e: except grpc.RpcError as e:
@ -1069,3 +1063,9 @@ class CoreClient:
def service_been_modified(self, node_id: int) -> bool: def service_been_modified(self, node_id: int) -> bool:
return node_id in self.modified_service_nodes return node_id in self.modified_service_nodes
def execute_script(self, script):
response = self.client.execute_script(script)
logging.info("execute python script %s", response)
if response.session_id != -1:
self.join_session(response.session_id)

View file

@ -0,0 +1,85 @@
import logging
import tkinter as tk
from tkinter import filedialog, ttk
from core.gui.appconfig import SCRIPT_PATH
from core.gui.dialogs.dialog import Dialog
from core.gui.themes import FRAME_PAD, PADX
class ExecutePythonDialog(Dialog):
def __init__(self, master, app):
super().__init__(master, app, "Execute Python Script", modal=True)
self.app = app
self.with_options = tk.IntVar(value=0)
self.options = tk.StringVar(value="")
self.option_entry = None
self.file_entry = None
self.draw()
def draw(self):
i = 0
frame = ttk.Frame(self.top, padding=FRAME_PAD)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
frame.grid(row=i, column=0, sticky="nsew")
i = i + 1
var = tk.StringVar(value="")
self.file_entry = ttk.Entry(frame, textvariable=var)
self.file_entry.grid(row=0, column=0, sticky="ew")
button = ttk.Button(frame, text="...", command=self.select_file)
button.grid(row=0, column=1, sticky="ew")
self.top.columnconfigure(0, weight=1)
button = ttk.Checkbutton(
self.top,
text="With Options",
variable=self.with_options,
command=self.add_options,
)
button.grid(row=i, column=0, sticky="ew")
i = i + 1
label = ttk.Label(
self.top, text="Any command-line options for running the Python script"
)
label.grid(row=i, column=0, sticky="ew")
i = i + 1
self.option_entry = ttk.Entry(
self.top, textvariable=self.options, state="disabled"
)
self.option_entry.grid(row=i, column=0, sticky="ew")
i = i + 1
frame = ttk.Frame(self.top, padding=FRAME_PAD)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
frame.grid(row=i, column=0)
button = ttk.Button(frame, text="Execute", command=self.script_execute)
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", padx=PADX)
def add_options(self):
if self.with_options.get():
self.option_entry.configure(state="normal")
else:
self.option_entry.configure(state="disabled")
def select_file(self):
file = filedialog.askopenfilename(
parent=self.top,
initialdir=str(SCRIPT_PATH),
title="Open python script",
filetypes=((".py Files", "*.py"), ("All Files", "*")),
)
if file:
self.file_entry.delete(0, "end")
self.file_entry.insert("end", file)
def script_execute(self):
file = self.file_entry.get()
options = self.option_entry.get()
logging.info("Execute %s with options %s", file, options)
self.app.core.execute_script(file)
self.destroy()

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

@ -56,9 +56,8 @@ class PreferencesDialog(Dialog):
label = ttk.Label(frame, text="Terminal") label = ttk.Label(frame, text="Terminal")
label.grid(row=2, column=0, pady=PADY, padx=PADX, sticky="w") label.grid(row=2, column=0, pady=PADY, padx=PADX, sticky="w")
combobox = ttk.Combobox( terminals = sorted(appconfig.TERMINALS.values())
frame, textvariable=self.terminal, values=appconfig.TERMINALS combobox = ttk.Combobox(frame, textvariable=self.terminal, values=terminals)
)
combobox.grid(row=2, column=1, sticky="ew") combobox.grid(row=2, column=1, sticky="ew")
label = ttk.Label(frame, text="3D GUI") label = ttk.Label(frame, text="3D GUI")

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)

View file

@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
import core.gui.menuaction as action import core.gui.menuaction as action
from core.gui.coreclient import OBSERVERS from core.gui.coreclient import OBSERVERS
from core.gui.dialogs.executepython import ExecutePythonDialog
if TYPE_CHECKING: if TYPE_CHECKING:
from core.gui.app import Application from core.gui.app import Application
@ -69,7 +70,7 @@ class Menubar(tk.Menu):
menu.add_cascade(label="Recent files", menu=self.recent_menu) menu.add_cascade(label="Recent files", menu=self.recent_menu)
menu.add_separator() menu.add_separator()
menu.add_command(label="Export Python script...", state=tk.DISABLED) menu.add_command(label="Export Python script...", state=tk.DISABLED)
menu.add_command(label="Execute XML or Python script...", state=tk.DISABLED) menu.add_command(label="Execute Python script...", command=self.execute_python)
menu.add_command( menu.add_command(
label="Execute Python script with options...", state=tk.DISABLED label="Execute Python script with options...", state=tk.DISABLED
) )
@ -443,6 +444,10 @@ class Menubar(tk.Menu):
else: else:
self.menuaction.file_save_as_xml() self.menuaction.file_save_as_xml()
def execute_python(self):
dialog = ExecutePythonDialog(self.app, self.app)
dialog.show()
def change_menubar_item_state(self, is_runtime: bool): def change_menubar_item_state(self, is_runtime: bool):
for i in range(self.edit_menu.index("end")): for i in range(self.edit_menu.index("end")):
try: try:

View file

@ -19,7 +19,7 @@ PATH="/sbin:/bin:/usr/sbin:/usr/bin"
export PATH export PATH
if [ "z$1" = "z-d" ]; then if [ "z$1" = "z-d" ]; then
pypids=`pidof python python2` pypids=`pidof python3 python`
for p in $pypids; do for p in $pypids; do
grep -q core-daemon /proc/$p/cmdline grep -q core-daemon /proc/$p/cmdline
if [ $? = 0 ]; then if [ $? = 0 ]; then