draw node service configurations

This commit is contained in:
Huy Pham 2019-11-11 10:57:26 -08:00
parent dbaf5dad91
commit 13a7aa73a1
5 changed files with 312 additions and 131 deletions

View file

@ -11,6 +11,7 @@ from coretk.emaneodelnodeconfig import EmaneModelNodeConfig
from coretk.images import Images from coretk.images import Images
from coretk.interface import Interface, InterfaceManager from coretk.interface import Interface, InterfaceManager
from coretk.mobilitynodeconfig import MobilityNodeConfig from coretk.mobilitynodeconfig import MobilityNodeConfig
from coretk.servicenodeconfig import ServiceNodeConfig
from coretk.wlannodeconfig import WlanNodeConfig from coretk.wlannodeconfig import WlanNodeConfig
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel", "emane"] link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel", "emane"]
@ -104,6 +105,7 @@ class CoreClient:
self.mobilityconfig_management = MobilityNodeConfig() self.mobilityconfig_management = MobilityNodeConfig()
self.emaneconfig_management = EmaneModelNodeConfig(app) self.emaneconfig_management = EmaneModelNodeConfig(app)
self.emane_config = None self.emane_config = None
self.serviceconfig_manager = ServiceNodeConfig(app)
def read_config(self): def read_config(self):
# read distributed server # read distributed server
@ -327,6 +329,13 @@ class CoreClient:
) )
logging.debug("Start session %s, result: %s", self.session_id, response.result) logging.debug("Start session %s, result: %s", self.session_id, response.result)
response = self.client.get_service_defaults(self.session_id)
for default in response.defaults:
print(default.node_type)
print(default.services)
response = self.client.get_node_service(self.session_id, 5, "FTP")
print(response)
def stop_session(self): def stop_session(self):
response = self.client.stop_session(session_id=self.session_id) response = self.client.stop_session(session_id=self.session_id)
logging.debug("coregrpc.py Stop session, result: %s", response.result) logging.debug("coregrpc.py Stop session, result: %s", response.result)
@ -453,6 +462,12 @@ class CoreClient:
if node_type == core_pb2.NodeType.EMANE: if node_type == core_pb2.NodeType.EMANE:
self.emaneconfig_management.set_default_config(nid) self.emaneconfig_management.set_default_config(nid)
# set default service configurations
if node_type == core_pb2.NodeType.DEFAULT:
self.serviceconfig_manager.node_default_services_configuration(
node_id=nid, node_model=node_model
)
self.nodes[canvas_id] = create_node self.nodes[canvas_id] = create_node
self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id) self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id)
logging.debug( logging.debug(

View file

@ -3,7 +3,7 @@ from tkinter import ttk
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.dialogs.icondialog import IconDialog from coretk.dialogs.icondialog import IconDialog
from coretk.dialogs.nodeservice import NodeServicesDialog from coretk.dialogs.nodeservice import NodeService
NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"] NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"]
DEFAULTNODES = ["router", "host", "PC"] DEFAULTNODES = ["router", "host", "PC"]
@ -87,7 +87,7 @@ class NodeConfigDialog(Dialog):
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
def click_services(self): def click_services(self):
dialog = NodeServicesDialog(self, self.app, self.canvas_node) dialog = NodeService(self, self.app, self.canvas_node)
dialog.show() dialog.show()
def click_icon(self): def click_icon(self):

View file

@ -5,154 +5,98 @@ import tkinter as tk
from tkinter import messagebox from tkinter import messagebox
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.dialogs.serviceconfiguration import ServiceConfiguration
from coretk.widgets import CheckboxList, ListboxScroll
class NodeServicesDialog(Dialog): class NodeService(Dialog):
def __init__(self, master, app, canvas_node): def __init__(self, master, app, canvas_node, current_services=set()):
super().__init__(master, app, "Node Services", modal=True) super().__init__(master, app, "Node Services", modal=True)
self.canvas_node = canvas_node self.canvas_node = canvas_node
self.core_groups = [] self.groups = None
self.service_to_config = None self.services = None
self.config_frame = None self.current = None
self.services_list = None self.current_services = current_services
self.draw() self.draw()
def draw(self): def draw(self):
self.columnconfigure(0, weight=1) self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1) self.rowconfigure(0, weight=1)
self.config_frame = tk.Frame(self)
self.config_frame.columnconfigure(0, weight=1)
self.config_frame.columnconfigure(1, weight=1)
self.config_frame.columnconfigure(2, weight=1)
self.config_frame.rowconfigure(0, weight=1)
self.config_frame.grid(row=0, column=0, sticky="nsew")
self.draw_group()
self.draw_services()
self.draw_current_services()
self.draw_buttons()
def draw_group(self):
"""
draw the group tab
:return: nothing
"""
frame = tk.Frame(self.config_frame)
frame.columnconfigure(0, weight=1)
frame.rowconfigure(1, weight=1)
frame.grid(row=0, column=0, padx=3, pady=3, sticky="nsew")
label = tk.Label(frame, text="Group")
label.grid(row=0, column=0, sticky="ew")
scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL)
scrollbar.grid(row=1, column=1, sticky="ns")
listbox = tk.Listbox(
frame,
selectmode=tk.SINGLE,
yscrollcommand=scrollbar.set,
relief=tk.FLAT,
highlightthickness=0.5,
bd=0,
)
listbox.grid(row=1, column=0, sticky="nsew")
listbox.bind("<<ListboxSelect>>", self.handle_group_change)
for group in sorted(self.app.core.services):
listbox.insert(tk.END, group)
scrollbar.config(command=listbox.yview)
def draw_services(self):
frame = tk.Frame(self.config_frame)
frame.columnconfigure(0, weight=1)
frame.rowconfigure(1, weight=1)
frame.grid(row=0, column=1, padx=3, pady=3, sticky="nsew")
label = tk.Label(frame, text="Group services")
label.grid(row=0, column=0, sticky="ew")
scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL)
scrollbar.grid(row=1, column=1, sticky="ns")
self.services_list = tk.Listbox(
frame,
selectmode=tk.SINGLE,
yscrollcommand=scrollbar.set,
relief=tk.FLAT,
highlightthickness=0.5,
bd=0,
)
self.services_list.grid(row=1, column=0, sticky="nsew")
self.services_list.bind("<<ListboxSelect>>", self.handle_service_change)
scrollbar.config(command=self.services_list.yview)
def draw_current_services(self):
frame = tk.Frame(self.config_frame)
frame.columnconfigure(0, weight=1)
frame.rowconfigure(1, weight=1)
frame.grid(row=0, column=2, padx=3, pady=3, sticky="nsew")
label = tk.Label(frame, text="Current services")
label.grid(row=0, column=0, sticky="ew")
scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL)
scrollbar.grid(row=1, column=1, sticky="ns")
listbox = tk.Listbox(
frame,
selectmode=tk.MULTIPLE,
yscrollcommand=scrollbar.set,
relief=tk.FLAT,
highlightthickness=0.5,
bd=0,
)
listbox.grid(row=1, column=0, sticky="nsew")
scrollbar.config(command=listbox.yview)
def draw_buttons(self):
frame = tk.Frame(self) frame = tk.Frame(self)
frame.columnconfigure(0, weight=1) frame.grid(stick="nsew")
frame.columnconfigure(1, weight=1) frame.rowconfigure(0, weight=1)
frame.columnconfigure(2, weight=1) for i in range(3):
frame.grid(row=1, column=0, sticky="ew") frame.columnconfigure(i, weight=1)
self.groups = ListboxScroll(frame, text="Groups")
self.groups.grid(row=0, column=0, sticky="nsew")
for group in sorted(self.app.core.services):
self.groups.listbox.insert(tk.END, group)
self.groups.listbox.bind("<<ListboxSelect>>", self.handle_group_change)
self.groups.listbox.selection_set(0)
self.services = CheckboxList(
frame, text="Services", clicked=self.service_clicked
)
self.services.grid(row=0, column=1, sticky="nsew")
self.current = ListboxScroll(frame, text="Selected")
self.current.grid(row=0, column=2, sticky="nsew")
for service in sorted(self.current_services):
self.current.listbox.insert(tk.END, service)
frame = tk.Frame(self)
frame.grid(stick="ew")
for i in range(3):
frame.columnconfigure(i, weight=1)
button = tk.Button(frame, text="Configure", command=self.click_configure) button = tk.Button(frame, text="Configure", command=self.click_configure)
button.grid(row=0, column=0, sticky="ew") button.grid(row=0, column=0, sticky="ew")
button = tk.Button(frame, text="Save", command=self.click_save)
button = tk.Button(frame, text="Apply")
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
button = tk.Button(frame, text="Cancel", command=self.click_cancel)
button = tk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=2, sticky="ew") button.grid(row=0, column=2, sticky="ew")
# trigger group change
self.groups.listbox.event_generate("<<ListboxSelect>>")
def handle_group_change(self, event): def handle_group_change(self, event):
listbox = event.widget selection = self.groups.listbox.curselection()
cur_selection = listbox.curselection() if selection:
if cur_selection: index = selection[0]
s = listbox.get(listbox.curselection()) group = self.groups.listbox.get(index)
self.display_group_services(s) self.services.clear()
for service in sorted(self.app.core.services[group], key=lambda x: x.name):
checked = service.name in self.current_services
self.services.add(service.name, checked)
def display_group_services(self, group_name): def service_clicked(self, name, var):
self.services_list.delete(0, tk.END) if var.get() and name not in self.current_services:
for service in sorted(self.app.core.services[group_name], key=lambda x: x.name): self.current_services.add(name)
self.services_list.insert(tk.END, service.name) elif not var.get() and name in self.current_services:
self.current_services.remove(name)
def handle_service_change(self, event): self.current.listbox.delete(0, tk.END)
print("select group service") for name in sorted(self.current_services):
listbox = event.widget self.current.listbox.insert(tk.END, name)
cur_selection = listbox.curselection()
if cur_selection:
s = listbox.get(listbox.curselection())
self.service_to_config = s
else:
self.service_to_config = None
def click_configure(self): def click_configure(self):
if self.service_to_config is None: current_selection = self.current.listbox.curselection()
messagebox.showinfo("CORE info", "Choose a service to configure.") if len(current_selection):
dialog = ServiceConfiguration(
master=self,
app=self.app,
service_name=self.current.listbox.get(current_selection[0]),
canvas_node=self.canvas_node,
)
dialog.show()
else: else:
print(self.service_to_config) messagebox.showinfo(
"Node service configuration", "Select a service to configure"
)
def click_save(self):
print("not implemented")
print(self.current_services)
def click_cancel(self):
self.current_services = None
self.destroy()

View file

@ -0,0 +1,185 @@
"Service configuration dialog"
import tkinter as tk
from tkinter import ttk
from coretk.dialogs.dialog import Dialog
from coretk.images import ImageEnum, Images
from coretk.widgets import ListboxScroll
class ServiceConfiguration(Dialog):
def __init__(self, master, app, service_name, canvas_node):
super().__init__(master, app, service_name + " service", modal=True)
self.app = app
self.service_name = service_name
self.metadata = tk.StringVar()
self.filename = tk.StringVar()
self.radiovar = tk.IntVar()
self.radiovar.set(1)
self.startup_index = tk.IntVar()
self.start_time = tk.IntVar()
self.documentnew_img = Images.get(ImageEnum.DOCUMENTNEW)
self.editdelete_img = Images.get(ImageEnum.EDITDELETE)
self.draw()
def draw(self):
# self.columnconfigure(1, weight=1)
frame = tk.Frame(self)
frame1 = tk.Frame(frame)
label = tk.Label(frame1, text=self.service_name)
label.grid(row=0, column=0, sticky="ew")
frame1.grid(row=0, column=0)
frame2 = tk.Frame(frame)
# frame2.columnconfigure(0, weight=1)
# frame2.columnconfigure(1, weight=4)
label = tk.Label(frame2, text="Meta-data")
label.grid(row=0, column=0)
entry = tk.Entry(frame2, textvariable=self.metadata)
entry.grid(row=0, column=1)
frame2.grid(row=1, column=0)
frame.grid(row=0, column=0)
frame = tk.Frame(self)
tab_parent = ttk.Notebook(frame)
tab1 = ttk.Frame(tab_parent)
tab2 = ttk.Frame(tab_parent)
tab3 = ttk.Frame(tab_parent)
tab1.columnconfigure(0, weight=1)
tab2.columnconfigure(0, weight=1)
tab3.columnconfigure(0, weight=1)
tab_parent.add(tab1, text="Files", sticky="nsew")
tab_parent.add(tab2, text="Directories", sticky="nsew")
tab_parent.add(tab3, text="Startup/shutdown", sticky="nsew")
tab_parent.grid(row=0, column=0, sticky="nsew")
frame.grid(row=1, column=0, sticky="nsew")
# tab 1
label = tk.Label(
tab1, text="Config files and scripts that are generated for this service."
)
label.grid(row=0, column=0, sticky="nsew")
frame = tk.Frame(tab1)
label = tk.Label(frame, text="File name: ")
label.grid(row=0, column=0)
entry = tk.Entry(frame, textvariable=self.filename)
entry.grid(row=0, column=1)
button = tk.Button(frame, image=self.documentnew_img)
button.grid(row=0, column=2)
button = tk.Button(frame, image=self.editdelete_img)
button.grid(row=0, column=3)
frame.grid(row=1, column=0, sticky="nsew")
frame = tk.Frame(tab1)
button = tk.Radiobutton(
frame,
variable=self.radiovar,
text="Copy this source file:",
indicatoron=True,
)
button.grid(row=0, column=0)
entry = tk.Entry(frame, state=tk.DISABLED)
entry.grid(row=0, column=1)
button = tk.Button(frame, text="not implemented")
button.grid(row=0, column=2)
frame.grid(row=2, column=0, sticky="nsew")
frame = tk.Frame(tab1)
button = tk.Radiobutton(
frame,
variable=self.radiovar,
text="Use text below for file contents:",
indicatoron=True,
)
button.grid(row=0, column=0)
button = tk.Button(frame, text="not implemented")
button.grid(row=0, column=1)
button = tk.Button(frame, text="not implemented")
button.grid(row=0, column=2)
frame.grid(row=3, column=0, sticky="nsew")
# tab 2
label = tk.Label(
tab2,
text="Directories required by this service that are unique for each node.",
)
label.grid(row=0, column=0, sticky="nsew")
# tab 3
label_frame = tk.LabelFrame(tab3, text="Startup commands")
label_frame.columnconfigure(0, weight=1)
frame = tk.Frame(label_frame)
frame.columnconfigure(0, weight=1)
entry = tk.Entry(frame, textvariable=tk.StringVar())
entry.grid(row=0, column=0, stick="nsew")
button = tk.Button(frame, image=self.documentnew_img)
button.grid(row=0, column=1, sticky="nsew")
button = tk.Button(frame, image=self.editdelete_img)
button.grid(row=0, column=2, sticky="nsew")
frame.grid(row=0, column=0, sticky="nsew")
listbox_scroll = ListboxScroll(label_frame)
listbox_scroll.listbox.config(height=4)
listbox_scroll.grid(row=1, column=0, sticky="nsew")
label_frame.grid(row=2, column=0, sticky="nsew")
label_frame = tk.LabelFrame(tab3, text="Shutdown commands")
label_frame.columnconfigure(0, weight=1)
frame = tk.Frame(label_frame)
frame.columnconfigure(0, weight=1)
entry = tk.Entry(frame, textvariable=tk.StringVar())
entry.grid(row=0, column=0, sticky="nsew")
button = tk.Button(frame, image=self.documentnew_img)
button.grid(row=0, column=1, sticky="nsew")
button = tk.Button(frame, image=self.editdelete_img)
button.grid(row=0, column=2, sticky="nsew")
frame.grid(row=0, column=0, sticky="nsew")
listbox_scroll = ListboxScroll(label_frame)
listbox_scroll.listbox.config(height=4)
listbox_scroll.grid(row=1, column=0, sticky="nsew")
label_frame.grid(row=3, column=0, sticky="nsew")
label_frame = tk.LabelFrame(tab3, text="Validate commands")
label_frame.columnconfigure(0, weight=1)
frame = tk.Frame(label_frame)
frame.columnconfigure(0, weight=1)
entry = tk.Entry(frame, textvariable=tk.StringVar())
entry.grid(row=0, column=0, sticky="nsew")
button = tk.Button(frame, image=self.documentnew_img)
button.grid(row=0, column=1, sticky="nsew")
button = tk.Button(frame, image=self.editdelete_img)
button.grid(row=0, column=2, sticky="nsew")
frame.grid(row=0, column=0, sticky="nsew")
listbox_scroll = ListboxScroll(label_frame)
listbox_scroll.listbox.config(height=4)
listbox_scroll.grid(row=1, column=0, sticky="nsew")
label_frame.grid(row=4, column=0, sticky="nsew")
button = tk.Button(
self, text="onle store values that have changed from their defaults"
)
button.grid(row=2, column=0)
frame = tk.Frame(self)
button = tk.Button(frame, text="Apply", command=self.click_apply)
button.grid(row=0, column=0, sticky="nsew")
button = tk.Button(frame, text="Dafults", command=self.click_defaults)
button.grid(row=0, column=1, sticky="nsew")
button = tk.Button(frame, text="Copy...", command=self.click_copy)
button.grid(row=0, column=2, sticky="nsew")
button = tk.Button(frame, text="Cancel", command=self.click_cancel)
button.grid(row=0, column=3, sticky="nsew")
frame.grid(row=3, column=0)
def click_apply(self, event):
print("not implemented")
def click_defaults(self, event):
print("not implemented")
def click_copy(self, event):
print("not implemented")
def click_cancel(self, event):
print("not implemented")

View file

@ -0,0 +1,37 @@
"""
service node configuration
"""
import logging
class ServiceNodeConfig:
def __init__(self, app):
self.app = app
self.configurations = {}
self.default_services = {}
def node_default_services_configuration(self, node_id, node_model):
"""
set the default configurations for the default services of a node
:param coretk.graph.CanvasNode canvas_node: canvas node object
:return: nothing
"""
session_id = self.app.core.session_id
client = self.app.core.client
if len(self.default_services) == 0:
response = client.get_service_defaults(session_id)
logging.info("session default services: %s", response)
for default in response.defaults:
self.default_services[default.node_type] = default.services
self.configurations[node_id] = {}
for default in self.default_services[node_model]:
response = client.get_node_service(session_id, node_id, default)
logging.info(
"servicenodeconfig.py get node service (%s), result: %s",
node_id,
response,
)
self.configurations[node_id][default] = response.service