예제 #1
0
    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(1, weight=1)
        label = ttk.Label(self.top,
                          text=f"{self.service} - {self.file_name}",
                          anchor=tk.CENTER)
        label.grid(sticky="ew", pady=PADY)

        listbox_scroll = ListboxScroll(self.top)
        listbox_scroll.grid(sticky="nsew", pady=PADY)
        self.listbox = listbox_scroll.listbox
        for canvas_node in self.app.canvas.nodes.values():
            file_configs = canvas_node.service_file_configs.get(self.service)
            if not file_configs:
                continue
            data = file_configs.get(self.file_name)
            if not data:
                continue
            name = canvas_node.core_node.name
            self.nodes[name] = canvas_node.id
            self.listbox.insert(tk.END, name)

        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Copy", command=self.click_copy)
        button.grid(row=0, column=0, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="View", command=self.click_view)
        button.grid(row=0, column=1, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=2, sticky="ew")
예제 #2
0
    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        listbox_scroll = ListboxScroll(self.top)
        listbox_scroll.grid(sticky=tk.NSEW, pady=PADY)
        self.listbox = listbox_scroll.listbox
        self.listbox.bind("<<ListboxSelect>>", self.select)
        session = self.app.core.session
        for file in session.hooks:
            self.listbox.insert(tk.END, file)

        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Create", command=self.click_create)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        self.edit_button = ttk.Button(frame,
                                      text="Edit",
                                      state=tk.DISABLED,
                                      command=self.click_edit)
        self.edit_button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        self.delete_button = ttk.Button(frame,
                                        text="Delete",
                                        state=tk.DISABLED,
                                        command=self.click_delete)
        self.delete_button.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            text="Cancel",
                            command=lambda: self.destroy())
        button.grid(row=0, column=3, sticky=tk.EW)
예제 #3
0
    def draw_node_config(self) -> None:
        frame = ttk.LabelFrame(self.top, text="Nodes", padding=FRAME_PAD)
        frame.grid(sticky=tk.NSEW, pady=PADY)
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(0, weight=1)

        self.nodes_list = ListboxScroll(frame)
        self.nodes_list.grid(row=0, column=0, sticky=tk.NSEW, padx=PADX)
        self.nodes_list.listbox.bind("<<ListboxSelect>>",
                                     self.handle_node_select)
        for name in sorted(self.app.core.custom_nodes):
            self.nodes_list.listbox.insert(tk.END, name)

        frame = ttk.Frame(frame)
        frame.grid(row=0, column=2, sticky=tk.NSEW)
        frame.columnconfigure(0, weight=1)
        entry = ttk.Entry(frame, textvariable=self.name)
        entry.grid(sticky=tk.EW, pady=PADY)
        self.image_button = ttk.Button(frame,
                                       text="Icon",
                                       compound=tk.LEFT,
                                       command=self.click_icon)
        self.image_button.grid(sticky=tk.EW, pady=PADY)
        button = ttk.Button(frame,
                            text="Services",
                            command=self.click_services)
        button.grid(sticky=tk.EW)
예제 #4
0
    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        frame = ttk.Frame(self.top)
        frame.grid(stick="nsew", pady=PADY)
        frame.rowconfigure(0, weight=1)
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        label_frame = ttk.LabelFrame(frame, text="Groups", padding=FRAME_PAD)
        label_frame.grid(row=0, column=0, sticky=tk.NSEW)
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.groups = ListboxScroll(label_frame)
        self.groups.grid(sticky=tk.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)

        label_frame = ttk.LabelFrame(frame, text="Services")
        label_frame.grid(row=0, column=1, sticky=tk.NSEW)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        self.services = CheckboxList(label_frame,
                                     self.app,
                                     clicked=self.service_clicked,
                                     padding=FRAME_PAD)
        self.services.grid(sticky=tk.NSEW)

        label_frame = ttk.LabelFrame(frame, text="Selected", padding=FRAME_PAD)
        label_frame.grid(row=0, column=2, sticky=tk.NSEW)
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.current = ListboxScroll(label_frame)
        self.current.grid(sticky=tk.NSEW)
        for service in sorted(self.current_services):
            self.current.listbox.insert(tk.END, service)
            if self.is_custom_service(service):
                self.current.listbox.itemconfig(tk.END, bg="green")

        frame = ttk.Frame(self.top)
        frame.grid(stick="ew")
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame,
                            text="Configure",
                            command=self.click_configure)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Save", command=self.click_save)
        button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Remove", command=self.click_remove)
        button.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
        button.grid(row=0, column=3, sticky=tk.EW)

        # trigger group change
        self.handle_group_change()
예제 #5
0
    def draw_tab_validation(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.EW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Validation", sticky=tk.NSEW)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)

        label = ttk.Label(frame, text="Validation Time")
        label.grid(row=0, column=0, sticky=tk.W, padx=PADX)
        self.validation_time_entry = ttk.Entry(frame)
        self.validation_time_entry.insert("end", self.validation_time)
        self.validation_time_entry.config(state=tk.DISABLED)
        self.validation_time_entry.grid(row=0, column=1, sticky=tk.EW, pady=PADY)

        label = ttk.Label(frame, text="Validation Mode")
        label.grid(row=1, column=0, sticky=tk.W, padx=PADX)
        if self.validation_mode == ServiceValidationMode.BLOCKING:
            mode = "BLOCKING"
        elif self.validation_mode == ServiceValidationMode.NON_BLOCKING:
            mode = "NON_BLOCKING"
        else:
            mode = "TIMER"
        self.validation_mode_entry = ttk.Entry(
            frame, textvariable=tk.StringVar(value=mode)
        )
        self.validation_mode_entry.insert("end", mode)
        self.validation_mode_entry.config(state=tk.DISABLED)
        self.validation_mode_entry.grid(row=1, column=1, sticky=tk.EW, pady=PADY)

        label = ttk.Label(frame, text="Validation Period")
        label.grid(row=2, column=0, sticky=tk.W, padx=PADX)
        self.validation_period_entry = ttk.Entry(
            frame, state=tk.DISABLED, textvariable=self.validation_period
        )
        self.validation_period_entry.grid(row=2, column=1, sticky=tk.EW, pady=PADY)

        label_frame = ttk.LabelFrame(tab, text="Executables", padding=FRAME_PAD)
        label_frame.grid(sticky=tk.NSEW, pady=PADY)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        listbox_scroll = ListboxScroll(label_frame)
        listbox_scroll.grid(sticky=tk.NSEW)
        tab.rowconfigure(listbox_scroll.grid_info()["row"], weight=1)
        for executable in self.executables:
            listbox_scroll.listbox.insert("end", executable)

        label_frame = ttk.LabelFrame(tab, text="Dependencies", padding=FRAME_PAD)
        label_frame.grid(sticky=tk.NSEW, pady=PADY)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        listbox_scroll = ListboxScroll(label_frame)
        listbox_scroll.grid(sticky=tk.NSEW)
        tab.rowconfigure(listbox_scroll.grid_info()["row"], weight=1)
        for dependency in self.dependencies:
            listbox_scroll.listbox.insert("end", dependency)
예제 #6
0
    def draw_tab_startstop(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        for i in range(3):
            tab.rowconfigure(i, weight=1)
        self.notebook.add(tab, text="Startup/Shutdown")
        commands = []
        # tab 3
        for i in range(3):
            label_frame = None
            if i == 0:
                label_frame = ttk.LabelFrame(tab,
                                             text="Startup Commands",
                                             padding=FRAME_PAD)
                commands = self.startup_commands
            elif i == 1:
                label_frame = ttk.LabelFrame(tab,
                                             text="Shutdown Commands",
                                             padding=FRAME_PAD)
                commands = self.shutdown_commands
            elif i == 2:
                label_frame = ttk.LabelFrame(tab,
                                             text="Validation Commands",
                                             padding=FRAME_PAD)
                commands = self.validation_commands
            label_frame.columnconfigure(0, weight=1)
            label_frame.rowconfigure(1, weight=1)
            label_frame.grid(row=i, column=0, sticky=tk.NSEW, pady=PADY)

            frame = ttk.Frame(label_frame)
            frame.grid(row=0, column=0, sticky=tk.NSEW, pady=PADY)
            frame.columnconfigure(0, weight=1)
            entry = ttk.Entry(frame, textvariable=tk.StringVar())
            entry.grid(row=0, column=0, stick="ew", padx=PADX)
            button = ttk.Button(frame, image=self.documentnew_img)
            button.bind("<Button-1>", self.add_command)
            button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
            button = ttk.Button(frame, image=self.editdelete_img)
            button.grid(row=0, column=2, sticky=tk.EW)
            button.bind("<Button-1>", self.delete_command)
            listbox_scroll = ListboxScroll(label_frame)
            listbox_scroll.listbox.bind("<<ListboxSelect>>", self.update_entry)
            for command in commands:
                listbox_scroll.listbox.insert("end", command)
            listbox_scroll.listbox.config(height=4)
            listbox_scroll.grid(row=1, column=0, sticky=tk.NSEW)
            if i == 0:
                self.startup_commands_listbox = listbox_scroll.listbox
            elif i == 1:
                self.shutdown_commands_listbox = listbox_scroll.listbox
            elif i == 2:
                self.validate_commands_listbox = listbox_scroll.listbox
예제 #7
0
    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        frame = ttk.LabelFrame(self.top)
        frame.grid(stick="nsew", pady=PADY)
        frame.rowconfigure(0, weight=1)
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        label_frame = ttk.LabelFrame(frame, text="Groups", padding=FRAME_PAD)
        label_frame.grid(row=0, column=0, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.groups = ListboxScroll(label_frame)
        self.groups.grid(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)

        label_frame = ttk.LabelFrame(frame, text="Services")
        label_frame.grid(row=0, column=1, sticky="nsew")
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        self.services = CheckboxList(label_frame,
                                     self.app,
                                     clicked=self.service_clicked,
                                     padding=FRAME_PAD)
        self.services.grid(sticky="nsew")

        label_frame = ttk.LabelFrame(frame, text="Selected", padding=FRAME_PAD)
        label_frame.grid(row=0, column=2, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.current = ListboxScroll(label_frame)
        self.current.grid(sticky="nsew")
        for service in sorted(self.current_services):
            self.current.listbox.insert(tk.END, service)

        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.destroy)
        button.grid(row=0, column=0, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
        button.grid(row=0, column=1, sticky="ew")

        # trigger group change
        self.groups.listbox.event_generate("<<ListboxSelect>>")
예제 #8
0
 def draw_listbox(self) -> None:
     listbox_scroll = ListboxScroll(self.top)
     listbox_scroll.grid(sticky="nsew", pady=PADY)
     listbox_scroll.columnconfigure(0, weight=1)
     listbox_scroll.rowconfigure(0, weight=1)
     self.observers = listbox_scroll.listbox
     self.observers.grid(row=0, column=0, sticky="nsew")
     self.observers.bind("<<ListboxSelect>>", self.handle_observer_change)
     for name in sorted(self.app.core.custom_observers):
         self.observers.insert(tk.END, name)
예제 #9
0
    def draw_servers(self) -> None:
        listbox_scroll = ListboxScroll(self.top)
        listbox_scroll.grid(pady=PADY, sticky=tk.NSEW)
        listbox_scroll.columnconfigure(0, weight=1)
        listbox_scroll.rowconfigure(0, weight=1)

        self.servers = listbox_scroll.listbox
        self.servers.grid(row=0, column=0, sticky=tk.NSEW)
        self.servers.bind("<<ListboxSelect>>", self.handle_server_change)

        for server in self.app.core.servers:
            self.servers.insert(tk.END, server)
예제 #10
0
파일: runtool.py 프로젝트: q9512268/core
    def draw_nodes_frame(self) -> None:
        labeled_frame = ttk.LabelFrame(self.top, text="Nodes", padding=FRAME_PAD)
        labeled_frame.grid(row=0, column=1, sticky=tk.NSEW)
        labeled_frame.columnconfigure(0, weight=1)
        labeled_frame.rowconfigure(0, weight=1)

        self.node_list = ListboxScroll(labeled_frame)
        self.node_list.listbox.config(selectmode=tk.MULTIPLE)
        self.node_list.grid(sticky=tk.NSEW, pady=PADY)
        for n in sorted(self.executable_nodes.keys()):
            self.node_list.listbox.insert(tk.END, n)

        button_frame = ttk.Frame(labeled_frame, padding=FRAME_PAD)
        button_frame.grid(sticky=tk.NSEW)
        button_frame.columnconfigure(0, weight=1)
        button_frame.columnconfigure(1, weight=1)

        button = ttk.Button(button_frame, text="All", command=self.click_all)
        button.grid(sticky=tk.NSEW, padx=PADX)
        button = ttk.Button(button_frame, text="None", command=self.click_none)
        button.grid(row=0, column=1, sticky=tk.NSEW)
예제 #11
0
 def draw_tab_startstop(self) -> None:
     tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
     tab.grid(sticky=tk.NSEW)
     tab.columnconfigure(0, weight=1)
     for i in range(3):
         tab.rowconfigure(i, weight=1)
     self.notebook.add(tab, text="Startup/Shutdown")
     commands = []
     # tab 3
     for i in range(3):
         label_frame = None
         if i == 0:
             label_frame = ttk.LabelFrame(
                 tab, text="Startup Commands", padding=FRAME_PAD
             )
             commands = self.startup_commands
         elif i == 1:
             label_frame = ttk.LabelFrame(
                 tab, text="Shutdown Commands", padding=FRAME_PAD
             )
             commands = self.shutdown_commands
         elif i == 2:
             label_frame = ttk.LabelFrame(
                 tab, text="Validation Commands", padding=FRAME_PAD
             )
             commands = self.validation_commands
         label_frame.columnconfigure(0, weight=1)
         label_frame.rowconfigure(0, weight=1)
         label_frame.grid(row=i, column=0, sticky=tk.NSEW, pady=PADY)
         listbox_scroll = ListboxScroll(label_frame)
         for command in commands:
             listbox_scroll.listbox.insert("end", command)
         listbox_scroll.listbox.config(height=4)
         listbox_scroll.grid(sticky=tk.NSEW)
         if i == 0:
             self.startup_commands_listbox = listbox_scroll.listbox
         elif i == 1:
             self.shutdown_commands_listbox = listbox_scroll.listbox
         elif i == 2:
             self.validate_commands_listbox = listbox_scroll.listbox
예제 #12
0
    def draw_tab_directories(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        tab.rowconfigure(2, weight=1)
        self.notebook.add(tab, text="Directories")

        label = ttk.Label(
            tab,
            text=
            "Directories required by this service that are unique for each node.",
        )
        label.grid(row=0, column=0, sticky=tk.EW)
        frame = ttk.Frame(tab, padding=FRAME_PAD)
        frame.columnconfigure(0, weight=1)
        frame.grid(row=1, column=0, sticky=tk.NSEW)
        var = tk.StringVar(value="")
        self.directory_entry = ttk.Entry(frame, textvariable=var)
        self.directory_entry.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            text="...",
                            command=self.find_directory_button)
        button.grid(row=0, column=1, sticky=tk.EW)
        self.dir_list = ListboxScroll(tab)
        self.dir_list.grid(row=2, column=0, sticky=tk.NSEW, pady=PADY)
        self.dir_list.listbox.bind("<<ListboxSelect>>", self.directory_select)
        for d in self.temp_directories:
            self.dir_list.listbox.insert("end", d)

        frame = ttk.Frame(tab)
        frame.grid(row=3, column=0, sticky=tk.NSEW)
        frame.columnconfigure(0, weight=1)
        frame.columnconfigure(1, weight=1)
        button = ttk.Button(frame, text="Add", command=self.add_directory)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            text="Remove",
                            command=self.remove_directory)
        button.grid(row=0, column=1, sticky=tk.EW)
예제 #13
0
파일: nodeservice.py 프로젝트: tinchoa/core
class NodeServiceDialog(Dialog):
    def __init__(self, master, app, canvas_node, services=None):
        title = f"{canvas_node.core_node.name} Services"
        super().__init__(master, app, title, modal=True)
        self.app = app
        self.canvas_node = canvas_node
        self.node_id = canvas_node.core_node.id
        self.groups = None
        self.services = None
        self.current = None
        if services is None:
            services = canvas_node.core_node.services
            model = canvas_node.core_node.model
            if len(services) == 0:
                services = set(self.app.core.default_services[model])
            else:
                services = set(services)

        self.current_services = services
        self.draw()

    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        frame = ttk.Frame(self.top)
        frame.grid(stick="nsew", pady=PADY)
        frame.rowconfigure(0, weight=1)
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        label_frame = ttk.LabelFrame(frame, text="Groups", padding=FRAME_PAD)
        label_frame.grid(row=0, column=0, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.groups = ListboxScroll(label_frame)
        self.groups.grid(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)

        label_frame = ttk.LabelFrame(frame, text="Services")
        label_frame.grid(row=0, column=1, sticky="nsew")
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        self.services = CheckboxList(
            label_frame, self.app, clicked=self.service_clicked, padding=FRAME_PAD
        )
        self.services.grid(sticky="nsew")

        label_frame = ttk.LabelFrame(frame, text="Selected", padding=FRAME_PAD)
        label_frame.grid(row=0, column=2, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.current = ListboxScroll(label_frame)
        self.current.grid(sticky="nsew")
        for service in sorted(self.current_services):
            self.current.listbox.insert(tk.END, service)

        frame = ttk.Frame(self.top)
        frame.grid(stick="ew")
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Configure", command=self.click_configure)
        button.grid(row=0, column=0, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Save", command=self.click_save)
        button.grid(row=0, column=1, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
        button.grid(row=0, column=2, sticky="ew")

        # trigger group change
        self.groups.listbox.event_generate("<<ListboxSelect>>")

    def handle_group_change(self, event):
        selection = self.groups.listbox.curselection()
        if selection:
            index = selection[0]
            group = self.groups.listbox.get(index)
            self.services.clear()
            for name in sorted(self.app.core.services[group]):
                checked = name in self.current_services
                self.services.add(name, checked)

    def service_clicked(self, name, var):
        if var.get() and name not in self.current_services:
            self.current_services.add(name)
        elif not var.get() and name in self.current_services:
            self.current_services.remove(name)
        self.current.listbox.delete(0, tk.END)
        for name in sorted(self.current_services):
            self.current.listbox.insert(tk.END, name)
        self.canvas_node.core_node.services[:] = self.current_services

    def click_configure(self):
        current_selection = self.current.listbox.curselection()
        if len(current_selection):
            dialog = ServiceConfigDialog(
                master=self,
                app=self.app,
                service_name=self.current.listbox.get(current_selection[0]),
                node_id=self.node_id,
            )
            dialog.show()
        else:
            messagebox.showinfo(
                "Node service configuration", "Select a service to configure"
            )

    def click_save(self):
        if (
            self.current_services
            != self.app.core.default_services[self.canvas_node.core_node.model]
        ):
            self.canvas_node.core_node.services[:] = self.current_services
        else:
            if len(self.canvas_node.core_node.services) > 0:
                self.canvas_node.core_node.services[:] = []
        self.destroy()

    def click_cancel(self):
        self.current_services = None
        self.destroy()
예제 #14
0
class ServicesSelectDialog(Dialog):
    def __init__(self, master: tk.BaseWidget, app: "Application",
                 current_services: Set[str]) -> None:
        super().__init__(app, "Node Services", master=master)
        self.groups: Optional[ListboxScroll] = None
        self.services: Optional[CheckboxList] = None
        self.current: Optional[ListboxScroll] = None
        self.current_services: Set[str] = current_services
        self.draw()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        frame = ttk.LabelFrame(self.top)
        frame.grid(stick=tk.NSEW, pady=PADY)
        frame.rowconfigure(0, weight=1)
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        label_frame = ttk.LabelFrame(frame, text="Groups", padding=FRAME_PAD)
        label_frame.grid(row=0, column=0, sticky=tk.NSEW)
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.groups = ListboxScroll(label_frame)
        self.groups.grid(sticky=tk.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)

        label_frame = ttk.LabelFrame(frame, text="Services")
        label_frame.grid(row=0, column=1, sticky=tk.NSEW)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        self.services = CheckboxList(label_frame,
                                     self.app,
                                     clicked=self.service_clicked,
                                     padding=FRAME_PAD)
        self.services.grid(sticky=tk.NSEW)

        label_frame = ttk.LabelFrame(frame, text="Selected", padding=FRAME_PAD)
        label_frame.grid(row=0, column=2, sticky=tk.NSEW)
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.current = ListboxScroll(label_frame)
        self.current.grid(sticky=tk.NSEW)
        for service in sorted(self.current_services):
            self.current.listbox.insert(tk.END, service)

        frame = ttk.Frame(self.top)
        frame.grid(stick=tk.EW)
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Save", command=self.destroy)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
        button.grid(row=0, column=1, sticky=tk.EW)

        # trigger group change
        self.groups.listbox.event_generate("<<ListboxSelect>>")

    def handle_group_change(self, event: tk.Event) -> None:
        selection = self.groups.listbox.curselection()
        if selection:
            index = selection[0]
            group = self.groups.listbox.get(index)
            self.services.clear()
            for name in sorted(self.app.core.services[group]):
                checked = name in self.current_services
                self.services.add(name, checked)

    def service_clicked(self, name: str, var: tk.BooleanVar) -> None:
        if var.get() and name not in self.current_services:
            self.current_services.add(name)
        elif not var.get() and name in self.current_services:
            self.current_services.remove(name)
        self.current.listbox.delete(0, tk.END)
        for name in sorted(self.current_services):
            self.current.listbox.insert(tk.END, name)

    def click_cancel(self) -> None:
        self.current_services = None
        self.destroy()
예제 #15
0
파일: runtool.py 프로젝트: q9512268/core
class RunToolDialog(Dialog):
    def __init__(self, app: "Application") -> None:
        super().__init__(app, "Run Tool")
        self.cmd: tk.StringVar = tk.StringVar(value="ps ax")
        self.result: Optional[CodeText] = None
        self.node_list: Optional[ListboxScroll] = None
        self.executable_nodes: Dict[str, int] = {}
        self.store_nodes()
        self.draw()

    def store_nodes(self) -> None:
        """
        store all CORE nodes (nodes that execute commands) from all existing nodes
        """
        for node in self.app.core.session.nodes.values():
            if NodeUtils.is_container_node(node.type):
                self.executable_nodes[node.name] = node.id

    def draw(self) -> None:
        self.top.rowconfigure(0, weight=1)
        self.top.columnconfigure(0, weight=1)
        self.draw_command_frame()
        self.draw_nodes_frame()

    def draw_command_frame(self) -> None:
        # the main frame
        frame = ttk.Frame(self.top)
        frame.grid(row=0, column=0, sticky=tk.NSEW, padx=PADX)
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(1, weight=1)

        labeled_frame = ttk.LabelFrame(frame, text="Command", padding=FRAME_PAD)
        labeled_frame.grid(sticky=tk.EW, pady=PADY)
        labeled_frame.rowconfigure(0, weight=1)
        labeled_frame.columnconfigure(0, weight=1)
        entry = ttk.Entry(labeled_frame, textvariable=self.cmd)
        entry.grid(sticky=tk.EW)

        # results frame
        labeled_frame = ttk.LabelFrame(frame, text="Output", padding=FRAME_PAD)
        labeled_frame.grid(sticky=tk.NSEW, pady=PADY)
        labeled_frame.columnconfigure(0, weight=1)
        labeled_frame.rowconfigure(0, weight=1)

        self.result = CodeText(labeled_frame)
        self.result.text.config(state=tk.DISABLED, height=15)
        self.result.grid(sticky=tk.NSEW, pady=PADY)
        button_frame = ttk.Frame(labeled_frame)
        button_frame.grid(sticky=tk.NSEW)
        button_frame.columnconfigure(0, weight=1)
        button_frame.columnconfigure(1, weight=1)
        button = ttk.Button(button_frame, text="Run", command=self.click_run)
        button.grid(sticky=tk.EW, padx=PADX)
        button = ttk.Button(button_frame, text="Close", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)

    def draw_nodes_frame(self) -> None:
        labeled_frame = ttk.LabelFrame(self.top, text="Nodes", padding=FRAME_PAD)
        labeled_frame.grid(row=0, column=1, sticky=tk.NSEW)
        labeled_frame.columnconfigure(0, weight=1)
        labeled_frame.rowconfigure(0, weight=1)

        self.node_list = ListboxScroll(labeled_frame)
        self.node_list.listbox.config(selectmode=tk.MULTIPLE)
        self.node_list.grid(sticky=tk.NSEW, pady=PADY)
        for n in sorted(self.executable_nodes.keys()):
            self.node_list.listbox.insert(tk.END, n)

        button_frame = ttk.Frame(labeled_frame, padding=FRAME_PAD)
        button_frame.grid(sticky=tk.NSEW)
        button_frame.columnconfigure(0, weight=1)
        button_frame.columnconfigure(1, weight=1)

        button = ttk.Button(button_frame, text="All", command=self.click_all)
        button.grid(sticky=tk.NSEW, padx=PADX)
        button = ttk.Button(button_frame, text="None", command=self.click_none)
        button.grid(row=0, column=1, sticky=tk.NSEW)

    def click_all(self) -> None:
        self.node_list.listbox.selection_set(0, self.node_list.listbox.size() - 1)

    def click_none(self) -> None:
        self.node_list.listbox.selection_clear(0, self.node_list.listbox.size() - 1)

    def click_run(self) -> None:
        """
        Run the command on each of the selected nodes and display the output to result
        text box.
        """
        command = self.cmd.get().strip()
        self.result.text.config(state=tk.NORMAL)
        self.result.text.delete("1.0", tk.END)
        for selection in self.node_list.listbox.curselection():
            node_name = self.node_list.listbox.get(selection)
            node_id = self.executable_nodes[node_name]
            response = self.app.core.client.node_command(
                self.app.core.session.id, node_id, command
            )
            self.result.text.insert(
                tk.END, f"> {node_name} > {command}:\n{response.output}\n"
            )
        self.result.text.config(state=tk.DISABLED)
예제 #16
0
class CustomNodesDialog(Dialog):
    def __init__(self, app: "Application") -> None:
        super().__init__(app, "Custom Nodes")
        self.edit_button: Optional[ttk.Button] = None
        self.delete_button: Optional[ttk.Button] = None
        self.nodes_list: Optional[ListboxScroll] = None
        self.name: tk.StringVar = tk.StringVar()
        self.image_button: Optional[ttk.Button] = None
        self.image: Optional[PhotoImage] = None
        self.image_file: Optional[str] = None
        self.services: Set[str] = set()
        self.selected: Optional[str] = None
        self.selected_index: Optional[int] = None
        self.draw()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.draw_node_config()
        self.draw_node_buttons()
        self.draw_buttons()

    def draw_node_config(self) -> None:
        frame = ttk.LabelFrame(self.top, text="Nodes", padding=FRAME_PAD)
        frame.grid(sticky=tk.NSEW, pady=PADY)
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(0, weight=1)

        self.nodes_list = ListboxScroll(frame)
        self.nodes_list.grid(row=0, column=0, sticky=tk.NSEW, padx=PADX)
        self.nodes_list.listbox.bind("<<ListboxSelect>>",
                                     self.handle_node_select)
        for name in sorted(self.app.core.custom_nodes):
            self.nodes_list.listbox.insert(tk.END, name)

        frame = ttk.Frame(frame)
        frame.grid(row=0, column=2, sticky=tk.NSEW)
        frame.columnconfigure(0, weight=1)
        entry = ttk.Entry(frame, textvariable=self.name)
        entry.grid(sticky=tk.EW, pady=PADY)
        self.image_button = ttk.Button(frame,
                                       text="Icon",
                                       compound=tk.LEFT,
                                       command=self.click_icon)
        self.image_button.grid(sticky=tk.EW, pady=PADY)
        button = ttk.Button(frame,
                            text="Services",
                            command=self.click_services)
        button.grid(sticky=tk.EW)

    def draw_node_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW, pady=PADY)
        for i in range(3):
            frame.columnconfigure(i, weight=1)

        button = ttk.Button(frame, text="Create", command=self.click_create)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)

        self.edit_button = ttk.Button(frame,
                                      text="Edit",
                                      state=tk.DISABLED,
                                      command=self.click_edit)
        self.edit_button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)

        self.delete_button = ttk.Button(frame,
                                        text="Delete",
                                        state=tk.DISABLED,
                                        command=self.click_delete)
        self.delete_button.grid(row=0, column=2, sticky=tk.EW)

    def draw_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.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=tk.EW, padx=PADX)

        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)

    def reset_values(self) -> None:
        self.name.set("")
        self.image = None
        self.image_file = None
        self.services = set()
        self.image_button.config(image="")

    def click_icon(self) -> None:
        file_path = image_chooser(self, ICONS_PATH)
        if file_path:
            image = Images.create(file_path, nodeutils.ICON_SIZE)
            self.image = image
            self.image_file = file_path
            self.image_button.config(image=self.image)

    def click_services(self) -> None:
        dialog = ServicesSelectDialog(self, self.app, self.services)
        dialog.show()
        if dialog.current_services is not None:
            self.services.clear()
            self.services.update(dialog.current_services)

    def click_save(self) -> None:
        self.app.guiconfig.nodes.clear()
        for name in self.app.core.custom_nodes:
            node_draw = self.app.core.custom_nodes[name]
            custom_node = CustomNode(name, node_draw.image_file,
                                     list(node_draw.services))
            self.app.guiconfig.nodes.append(custom_node)
        logging.info("saving custom nodes: %s", self.app.guiconfig.nodes)
        self.app.save_config()
        self.destroy()

    def click_create(self) -> None:
        name = self.name.get()
        if name not in self.app.core.custom_nodes:
            image_file = Path(self.image_file).stem
            custom_node = CustomNode(name, image_file, list(self.services))
            node_draw = NodeDraw.from_custom(custom_node)
            logging.info(
                "created new custom node (%s), image file (%s), services: (%s)",
                name,
                image_file,
                self.services,
            )
            self.app.core.custom_nodes[name] = node_draw
            self.nodes_list.listbox.insert(tk.END, name)
            self.reset_values()

    def click_edit(self) -> None:
        name = self.name.get()
        if self.selected:
            previous_name = self.selected
            self.selected = name
            node_draw = self.app.core.custom_nodes.pop(previous_name)
            node_draw.model = name
            node_draw.image_file = Path(self.image_file).stem
            node_draw.image = self.image
            node_draw.services = self.services
            logging.debug(
                "edit custom node (%s), image: (%s), services (%s)",
                name,
                self.image_file,
                self.services,
            )
            self.app.core.custom_nodes[name] = node_draw
            self.nodes_list.listbox.delete(self.selected_index)
            self.nodes_list.listbox.insert(self.selected_index, name)
            self.nodes_list.listbox.selection_set(self.selected_index)

    def click_delete(self) -> None:
        if self.selected and self.selected in self.app.core.custom_nodes:
            self.nodes_list.listbox.delete(self.selected_index)
            del self.app.core.custom_nodes[self.selected]
            self.reset_values()
            self.nodes_list.listbox.selection_clear(0, tk.END)
            self.nodes_list.listbox.event_generate("<<ListboxSelect>>")

    def handle_node_select(self, event: tk.Event) -> None:
        selection = self.nodes_list.listbox.curselection()
        if selection:
            self.selected_index = selection[0]
            self.selected = self.nodes_list.listbox.get(self.selected_index)
            node_draw = self.app.core.custom_nodes[self.selected]
            self.name.set(node_draw.model)
            self.services = node_draw.services
            self.image = node_draw.image
            self.image_file = node_draw.image_file
            self.image_button.config(image=self.image)
            self.edit_button.config(state=tk.NORMAL)
            self.delete_button.config(state=tk.NORMAL)
        else:
            self.selected = None
            self.selected_index = None
            self.edit_button.config(state=tk.DISABLED)
            self.delete_button.config(state=tk.DISABLED)
예제 #17
0
파일: ipdialog.py 프로젝트: walterhil/core
class IpConfigDialog(Dialog):
    def __init__(self, app: "Application") -> None:
        super().__init__(app, "IP Configuration")
        self.ip4 = self.app.guiconfig.ips.ip4
        self.ip6 = self.app.guiconfig.ips.ip6
        self.ip4s = self.app.guiconfig.ips.ip4s
        self.ip6s = self.app.guiconfig.ips.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()
예제 #18
0
파일: ipdialog.py 프로젝트: walterhil/core
    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")
예제 #19
0
    def draw(self):
        self.top.columnconfigure(0, weight=1)
        row = 0

        # field frame
        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        frame.columnconfigure(1, weight=1)

        # icon field
        label = ttk.Label(frame, text="Icon")
        label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY)
        self.image_button = ttk.Button(
            frame,
            text="Icon",
            image=self.image,
            compound=tk.NONE,
            command=self.click_icon,
        )
        self.image_button.grid(row=row, column=1, sticky="ew")
        row += 1

        # name field
        label = ttk.Label(frame, text="Name")
        label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY)
        entry = ttk.Entry(
            frame,
            textvariable=self.name,
            validate="key",
            validatecommand=(self.app.validation.name, "%P"),
        )
        entry.bind(
            "<FocusOut>",
            lambda event: self.app.validation.focus_out(event, "noname"))
        entry.grid(row=row, column=1, sticky="ew")
        row += 1

        # node type field
        if NodeUtils.is_model_node(self.node.type):
            label = ttk.Label(frame, text="Type")
            label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY)
            combobox = ttk.Combobox(
                frame,
                textvariable=self.type,
                values=list(NodeUtils.NODE_MODELS),
                state="readonly",
            )
            combobox.grid(row=row, column=1, sticky="ew")
            row += 1

        # container image field
        if NodeUtils.is_image_node(self.node.type):
            label = ttk.Label(frame, text="Image")
            label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY)
            entry = ttk.Entry(frame, textvariable=self.container_image)
            entry.grid(row=row, column=1, sticky="ew")
            row += 1

        if NodeUtils.is_container_node(self.node.type):
            # server
            frame.grid(sticky="ew")
            frame.columnconfigure(1, weight=1)
            label = ttk.Label(frame, text="Server")
            label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY)
            servers = ["localhost"]
            servers.extend(list(sorted(self.app.core.servers.keys())))
            combobox = ttk.Combobox(frame,
                                    textvariable=self.server,
                                    values=servers,
                                    state="readonly")
            combobox.grid(row=row, column=1, sticky="ew")
            row += 1

        if NodeUtils.is_rj45_node(self.node.type):
            response = self.app.core.client.get_interfaces()
            logging.debug("host machine available interfaces: %s", response)
            interfaces = ListboxScroll(frame)
            interfaces.grid(row=row,
                            column=0,
                            columnspan=2,
                            sticky="ew",
                            padx=PADX,
                            pady=PADY)
            for inf in sorted(response.interfaces[:]):
                interfaces.listbox.insert(tk.END, inf)
            row += 1
            interfaces.listbox.bind("<<ListboxSelect>>", self.interface_select)

        # interfaces
        if self.canvas_node.interfaces:
            self.draw_interfaces()

        self.draw_spacer()
        self.draw_buttons()
예제 #20
0
class ServiceConfigDialog(Dialog):
    def __init__(self, master: tk.BaseWidget, app: "Application",
                 service_name: str, node: Node) -> None:
        title = f"{service_name} Service"
        super().__init__(app, title, master=master)
        self.core: "CoreClient" = app.core
        self.node: Node = node
        self.service_name: str = service_name
        self.radiovar: tk.IntVar = tk.IntVar(value=2)
        self.metadata: str = ""
        self.filenames: List[str] = []
        self.dependencies: List[str] = []
        self.executables: List[str] = []
        self.startup_commands: List[str] = []
        self.validation_commands: List[str] = []
        self.shutdown_commands: List[str] = []
        self.default_startup: List[str] = []
        self.default_validate: List[str] = []
        self.default_shutdown: List[str] = []
        self.validation_mode: Optional[ServiceValidationMode] = None
        self.validation_time: Optional[int] = None
        self.validation_period: Optional[float] = None
        self.directory_entry: Optional[ttk.Entry] = None
        self.default_directories: List[str] = []
        self.temp_directories: List[str] = []
        self.documentnew_img: PhotoImage = self.app.get_icon(
            ImageEnum.DOCUMENTNEW, ICON_SIZE)
        self.editdelete_img: PhotoImage = self.app.get_icon(
            ImageEnum.EDITDELETE, ICON_SIZE)
        self.notebook: Optional[ttk.Notebook] = None
        self.metadata_entry: Optional[ttk.Entry] = None
        self.filename_combobox: Optional[ttk.Combobox] = None
        self.dir_list: Optional[ListboxScroll] = None
        self.startup_commands_listbox: Optional[tk.Listbox] = None
        self.shutdown_commands_listbox: Optional[tk.Listbox] = None
        self.validate_commands_listbox: Optional[tk.Listbox] = None
        self.validation_time_entry: Optional[ttk.Entry] = None
        self.validation_mode_entry: Optional[ttk.Entry] = None
        self.service_file_data: Optional[CodeText] = None
        self.validation_period_entry: Optional[ttk.Entry] = None
        self.original_service_files: Dict[str, str] = {}
        self.default_config: Optional[NodeServiceData] = None
        self.temp_service_files: Dict[str, str] = {}
        self.modified_files: Set[str] = set()
        self.has_error: bool = False
        self.load()
        if not self.has_error:
            self.draw()

    def load(self) -> None:
        try:
            self.app.core.create_nodes_and_links()
            default_config = self.app.core.get_node_service(
                self.node.id, self.service_name)
            self.default_startup = default_config.startup[:]
            self.default_validate = default_config.validate[:]
            self.default_shutdown = default_config.shutdown[:]
            self.default_directories = default_config.dirs[:]
            custom_service_config = self.node.service_configs.get(
                self.service_name)
            self.default_config = default_config
            service_config = (custom_service_config
                              if custom_service_config else default_config)
            self.dependencies = service_config.dependencies[:]
            self.executables = service_config.executables[:]
            self.metadata = service_config.meta
            self.filenames = service_config.configs[:]
            self.startup_commands = service_config.startup[:]
            self.validation_commands = service_config.validate[:]
            self.shutdown_commands = service_config.shutdown[:]
            self.validation_mode = service_config.validation_mode
            self.validation_time = service_config.validation_timer
            self.temp_directories = service_config.dirs[:]
            self.original_service_files = {
                x: self.app.core.get_node_service_file(self.node.id,
                                                       self.service_name, x)
                for x in default_config.configs
            }
            self.temp_service_files = dict(self.original_service_files)

            file_configs = self.node.service_file_configs.get(
                self.service_name, {})
            for file, data in file_configs.items():
                self.temp_service_files[file] = data
        except grpc.RpcError as e:
            self.app.show_grpc_exception("Get Node Service Error", e)
            self.has_error = True

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(1, weight=1)

        # draw metadata
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)
        label = ttk.Label(frame, text="Meta-data")
        label.grid(row=0, column=0, sticky=tk.W, padx=PADX)
        self.metadata_entry = ttk.Entry(frame, textvariable=self.metadata)
        self.metadata_entry.grid(row=0, column=1, sticky=tk.EW)

        # draw notebook
        self.notebook = ttk.Notebook(self.top)
        self.notebook.grid(sticky=tk.NSEW, pady=PADY)
        self.draw_tab_files()
        self.draw_tab_directories()
        self.draw_tab_startstop()
        self.draw_tab_configuration()

        self.draw_buttons()

    def draw_tab_files(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Files")

        label = ttk.Label(
            tab,
            text="Config files and scripts that are generated for this service."
        )
        label.grid()

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)
        label = ttk.Label(frame, text="File Name")
        label.grid(row=0, column=0, padx=PADX, sticky=tk.W)
        self.filename_combobox = ttk.Combobox(frame, values=self.filenames)
        self.filename_combobox.bind("<<ComboboxSelected>>",
                                    self.display_service_file_data)
        self.filename_combobox.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            image=self.documentnew_img,
                            command=self.add_filename)
        button.grid(row=0, column=2, padx=PADX)
        button = ttk.Button(frame,
                            image=self.editdelete_img,
                            command=self.delete_filename)
        button.grid(row=0, column=3)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)
        button = ttk.Radiobutton(
            frame,
            variable=self.radiovar,
            text="Copy Source File",
            value=1,
            state=tk.DISABLED,
        )
        button.grid(row=0, column=0, sticky=tk.W, padx=PADX)
        entry = ttk.Entry(frame, state=tk.DISABLED)
        entry.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        image = Images.get(ImageEnum.FILEOPEN, 16)
        button = ttk.Button(frame, image=image)
        button.image = image
        button.grid(row=0, column=2)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(0, weight=1)
        button = ttk.Radiobutton(
            frame,
            variable=self.radiovar,
            text="Use text below for file contents",
            value=2,
        )
        button.grid(row=0, column=0, sticky=tk.EW)
        image = Images.get(ImageEnum.FILEOPEN, 16)
        button = ttk.Button(frame, image=image)
        button.image = image
        button.grid(row=0, column=1)
        image = Images.get(ImageEnum.DOCUMENTSAVE, 16)
        button = ttk.Button(frame, image=image)
        button.image = image
        button.grid(row=0, column=2)

        self.service_file_data = CodeText(tab)
        self.service_file_data.grid(sticky=tk.NSEW)
        tab.rowconfigure(self.service_file_data.grid_info()["row"], weight=1)
        if len(self.filenames) > 0:
            self.filename_combobox.current(0)
            self.service_file_data.text.delete(1.0, "end")
            self.service_file_data.text.insert(
                "end", self.temp_service_files[self.filenames[0]])
        self.service_file_data.text.bind("<FocusOut>",
                                         self.update_temp_service_file_data)

    def draw_tab_directories(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        tab.rowconfigure(2, weight=1)
        self.notebook.add(tab, text="Directories")

        label = ttk.Label(
            tab,
            text=
            "Directories required by this service that are unique for each node.",
        )
        label.grid(row=0, column=0, sticky=tk.EW)
        frame = ttk.Frame(tab, padding=FRAME_PAD)
        frame.columnconfigure(0, weight=1)
        frame.grid(row=1, column=0, sticky=tk.NSEW)
        var = tk.StringVar(value="")
        self.directory_entry = ttk.Entry(frame, textvariable=var)
        self.directory_entry.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            text="...",
                            command=self.find_directory_button)
        button.grid(row=0, column=1, sticky=tk.EW)
        self.dir_list = ListboxScroll(tab)
        self.dir_list.grid(row=2, column=0, sticky=tk.NSEW, pady=PADY)
        self.dir_list.listbox.bind("<<ListboxSelect>>", self.directory_select)
        for d in self.temp_directories:
            self.dir_list.listbox.insert("end", d)

        frame = ttk.Frame(tab)
        frame.grid(row=3, column=0, sticky=tk.NSEW)
        frame.columnconfigure(0, weight=1)
        frame.columnconfigure(1, weight=1)
        button = ttk.Button(frame, text="Add", command=self.add_directory)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            text="Remove",
                            command=self.remove_directory)
        button.grid(row=0, column=1, sticky=tk.EW)

    def draw_tab_startstop(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        for i in range(3):
            tab.rowconfigure(i, weight=1)
        self.notebook.add(tab, text="Startup/Shutdown")
        commands = []
        # tab 3
        for i in range(3):
            label_frame = None
            if i == 0:
                label_frame = ttk.LabelFrame(tab,
                                             text="Startup Commands",
                                             padding=FRAME_PAD)
                commands = self.startup_commands
            elif i == 1:
                label_frame = ttk.LabelFrame(tab,
                                             text="Shutdown Commands",
                                             padding=FRAME_PAD)
                commands = self.shutdown_commands
            elif i == 2:
                label_frame = ttk.LabelFrame(tab,
                                             text="Validation Commands",
                                             padding=FRAME_PAD)
                commands = self.validation_commands
            label_frame.columnconfigure(0, weight=1)
            label_frame.rowconfigure(1, weight=1)
            label_frame.grid(row=i, column=0, sticky=tk.NSEW, pady=PADY)

            frame = ttk.Frame(label_frame)
            frame.grid(row=0, column=0, sticky=tk.NSEW, pady=PADY)
            frame.columnconfigure(0, weight=1)
            entry = ttk.Entry(frame, textvariable=tk.StringVar())
            entry.grid(row=0, column=0, stick="ew", padx=PADX)
            button = ttk.Button(frame, image=self.documentnew_img)
            button.bind("<Button-1>", self.add_command)
            button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
            button = ttk.Button(frame, image=self.editdelete_img)
            button.grid(row=0, column=2, sticky=tk.EW)
            button.bind("<Button-1>", self.delete_command)
            listbox_scroll = ListboxScroll(label_frame)
            listbox_scroll.listbox.bind("<<ListboxSelect>>", self.update_entry)
            for command in commands:
                listbox_scroll.listbox.insert("end", command)
            listbox_scroll.listbox.config(height=4)
            listbox_scroll.grid(row=1, column=0, sticky=tk.NSEW)
            if i == 0:
                self.startup_commands_listbox = listbox_scroll.listbox
            elif i == 1:
                self.shutdown_commands_listbox = listbox_scroll.listbox
            elif i == 2:
                self.validate_commands_listbox = listbox_scroll.listbox

    def draw_tab_configuration(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Configuration", sticky=tk.NSEW)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)

        label = ttk.Label(frame, text="Validation Time")
        label.grid(row=0, column=0, sticky=tk.W, padx=PADX)
        self.validation_time_entry = ttk.Entry(frame)
        self.validation_time_entry.insert("end", self.validation_time)
        self.validation_time_entry.config(state=tk.DISABLED)
        self.validation_time_entry.grid(row=0,
                                        column=1,
                                        sticky=tk.EW,
                                        pady=PADY)

        label = ttk.Label(frame, text="Validation Mode")
        label.grid(row=1, column=0, sticky=tk.W, padx=PADX)
        if self.validation_mode == ServiceValidationMode.BLOCKING:
            mode = "BLOCKING"
        elif self.validation_mode == ServiceValidationMode.NON_BLOCKING:
            mode = "NON_BLOCKING"
        else:
            mode = "TIMER"
        self.validation_mode_entry = ttk.Entry(
            frame, textvariable=tk.StringVar(value=mode))
        self.validation_mode_entry.insert("end", mode)
        self.validation_mode_entry.config(state=tk.DISABLED)
        self.validation_mode_entry.grid(row=1,
                                        column=1,
                                        sticky=tk.EW,
                                        pady=PADY)

        label = ttk.Label(frame, text="Validation Period")
        label.grid(row=2, column=0, sticky=tk.W, padx=PADX)
        self.validation_period_entry = ttk.Entry(frame,
                                                 state=tk.DISABLED,
                                                 textvariable=tk.StringVar())
        self.validation_period_entry.grid(row=2,
                                          column=1,
                                          sticky=tk.EW,
                                          pady=PADY)

        label_frame = ttk.LabelFrame(tab,
                                     text="Executables",
                                     padding=FRAME_PAD)
        label_frame.grid(sticky=tk.NSEW, pady=PADY)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        listbox_scroll = ListboxScroll(label_frame)
        listbox_scroll.grid(sticky=tk.NSEW)
        tab.rowconfigure(listbox_scroll.grid_info()["row"], weight=1)
        for executable in self.executables:
            listbox_scroll.listbox.insert("end", executable)

        label_frame = ttk.LabelFrame(tab,
                                     text="Dependencies",
                                     padding=FRAME_PAD)
        label_frame.grid(sticky=tk.NSEW, pady=PADY)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        listbox_scroll = ListboxScroll(label_frame)
        listbox_scroll.grid(sticky=tk.NSEW)
        tab.rowconfigure(listbox_scroll.grid_info()["row"], weight=1)
        for dependency in self.dependencies:
            listbox_scroll.listbox.insert("end", dependency)

    def draw_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            text="Defaults",
                            command=self.click_defaults)
        button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Copy...", command=self.click_copy)
        button.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=3, sticky=tk.EW)

    def add_filename(self) -> None:
        filename = self.filename_combobox.get()
        if filename not in self.filename_combobox["values"]:
            self.filename_combobox["values"] += (filename, )
            self.filename_combobox.set(filename)
            self.temp_service_files[
                filename] = self.service_file_data.text.get(1.0, "end")
        else:
            logging.debug("file already existed")

    def delete_filename(self) -> None:
        cbb = self.filename_combobox
        filename = cbb.get()
        if filename in cbb["values"]:
            cbb["values"] = tuple([x for x in cbb["values"] if x != filename])
        cbb.set("")
        self.service_file_data.text.delete(1.0, "end")
        self.temp_service_files.pop(filename, None)
        if filename in self.modified_files:
            self.modified_files.remove(filename)

    @classmethod
    def add_command(cls, event: tk.Event) -> None:
        frame_contains_button = event.widget.master
        listbox = frame_contains_button.master.grid_slaves(row=1,
                                                           column=0)[0].listbox
        command_to_add = frame_contains_button.grid_slaves(row=0,
                                                           column=0)[0].get()
        if command_to_add == "":
            return
        for cmd in listbox.get(0, tk.END):
            if cmd == command_to_add:
                return
        listbox.insert(tk.END, command_to_add)

    @classmethod
    def update_entry(cls, event: tk.Event) -> None:
        listbox = event.widget
        current_selection = listbox.curselection()
        if len(current_selection) > 0:
            cmd = listbox.get(current_selection[0])
            entry = listbox.master.master.grid_slaves(
                row=0, column=0)[0].grid_slaves(row=0, column=0)[0]
            entry.delete(0, "end")
            entry.insert(0, cmd)

    @classmethod
    def delete_command(cls, event: tk.Event) -> None:
        button = event.widget
        frame_contains_button = button.master
        listbox = frame_contains_button.master.grid_slaves(row=1,
                                                           column=0)[0].listbox
        current_selection = listbox.curselection()
        if len(current_selection) > 0:
            listbox.delete(current_selection[0])
            entry = frame_contains_button.grid_slaves(row=0, column=0)[0]
            entry.delete(0, tk.END)

    def click_apply(self) -> None:
        if (not self.is_custom_command() and not self.is_custom_service_file()
                and not self.has_new_files()
                and not self.is_custom_directory()):
            self.node.service_configs.pop(self.service_name, None)
            self.current_service_color("")
            self.destroy()
            return

        try:
            if (self.is_custom_command() or self.has_new_files()
                    or self.is_custom_directory()):
                startup, validate, shutdown = self.get_commands()
                config = self.core.set_node_service(
                    self.node.id,
                    self.service_name,
                    dirs=self.temp_directories,
                    files=list(self.filename_combobox["values"]),
                    startups=startup,
                    validations=validate,
                    shutdowns=shutdown,
                )
                self.node.service_configs[self.service_name] = config
            for file in self.modified_files:
                file_configs = self.node.service_file_configs.setdefault(
                    self.service_name, {})
                file_configs[file] = self.temp_service_files[file]
                # TODO: check if this is really needed
                self.app.core.set_node_service_file(
                    self.node.id, self.service_name, file,
                    self.temp_service_files[file])
            self.current_service_color("green")
        except grpc.RpcError as e:
            self.app.show_grpc_exception("Save Service Config Error", e)
        self.destroy()

    def display_service_file_data(self, event: tk.Event) -> None:
        filename = self.filename_combobox.get()
        self.service_file_data.text.delete(1.0, "end")
        self.service_file_data.text.insert("end",
                                           self.temp_service_files[filename])

    def update_temp_service_file_data(self, event: tk.Event) -> None:
        filename = self.filename_combobox.get()
        self.temp_service_files[filename] = self.service_file_data.text.get(
            1.0, "end")
        if self.temp_service_files[
                filename] != self.original_service_files.get(filename, ""):
            self.modified_files.add(filename)
        else:
            self.modified_files.discard(filename)

    def is_custom_command(self) -> bool:
        startup, validate, shutdown = self.get_commands()
        return (set(self.default_startup) != set(startup)
                or set(self.default_validate) != set(validate)
                or set(self.default_shutdown) != set(shutdown))

    def has_new_files(self) -> bool:
        return set(self.filenames) != set(self.filename_combobox["values"])

    def is_custom_service_file(self) -> bool:
        return len(self.modified_files) > 0

    def is_custom_directory(self) -> bool:
        return set(self.default_directories) != set(
            self.dir_list.listbox.get(0, "end"))

    def click_defaults(self) -> None:
        """
        clears out any custom configuration permanently
        """
        # clear coreclient data
        self.node.service_configs.pop(self.service_name, None)
        file_configs = self.node.service_file_configs.pop(
            self.service_name, {})
        file_configs.pop(self.service_name, None)
        self.temp_service_files = dict(self.original_service_files)
        self.modified_files.clear()

        # reset files tab
        files = list(self.default_config.configs[:])
        self.filenames = files
        self.filename_combobox.config(values=files)
        self.service_file_data.text.delete(1.0, "end")
        if len(files) > 0:
            filename = files[0]
            self.filename_combobox.set(filename)
            self.service_file_data.text.insert(
                "end", self.temp_service_files[filename])

        # reset commands
        self.startup_commands_listbox.delete(0, tk.END)
        self.validate_commands_listbox.delete(0, tk.END)
        self.shutdown_commands_listbox.delete(0, tk.END)
        for cmd in self.default_startup:
            self.startup_commands_listbox.insert(tk.END, cmd)
        for cmd in self.default_validate:
            self.validate_commands_listbox.insert(tk.END, cmd)
        for cmd in self.default_shutdown:
            self.shutdown_commands_listbox.insert(tk.END, cmd)

        # reset directories
        self.directory_entry.delete(0, "end")
        self.dir_list.listbox.delete(0, "end")
        self.temp_directories = list(self.default_directories)
        for d in self.default_directories:
            self.dir_list.listbox.insert("end", d)

        self.current_service_color("")

    def click_copy(self) -> None:
        file_name = self.filename_combobox.get()
        dialog = CopyServiceConfigDialog(self.app, self, self.node.name,
                                         self.service_name, file_name)
        dialog.show()

    @classmethod
    def append_commands(cls, commands: List[str], listbox: tk.Listbox,
                        to_add: List[str]) -> None:
        for cmd in to_add:
            commands.append(cmd)
            listbox.insert(tk.END, cmd)

    def get_commands(self) -> Tuple[List[str], List[str], List[str]]:
        startup = self.startup_commands_listbox.get(0, "end")
        shutdown = self.shutdown_commands_listbox.get(0, "end")
        validate = self.validate_commands_listbox.get(0, "end")
        return startup, validate, shutdown

    def find_directory_button(self) -> None:
        d = filedialog.askdirectory(initialdir="/")
        self.directory_entry.delete(0, "end")
        self.directory_entry.insert("end", d)

    def add_directory(self) -> None:
        d = self.directory_entry.get()
        if os.path.isdir(d):
            if d not in self.temp_directories:
                self.dir_list.listbox.insert("end", d)
                self.temp_directories.append(d)

    def remove_directory(self) -> None:
        d = self.directory_entry.get()
        dirs = self.dir_list.listbox.get(0, "end")
        if d and d in self.temp_directories:
            self.temp_directories.remove(d)
            try:
                i = dirs.index(d)
                self.dir_list.listbox.delete(i)
            except ValueError:
                logging.debug("directory is not in the list")
        self.directory_entry.delete(0, "end")

    def directory_select(self, event) -> None:
        i = self.dir_list.listbox.curselection()
        if i:
            d = self.dir_list.listbox.get(i)
            self.directory_entry.delete(0, "end")
            self.directory_entry.insert("end", d)

    def current_service_color(self, color="") -> None:
        """
        change the current service label color
        """
        listbox = self.master.current.listbox
        services = listbox.get(0, tk.END)
        listbox.itemconfig(services.index(self.service_name), bg=color)
예제 #21
0
class NodeServiceDialog(Dialog):
    def __init__(self, app: "Application", node: Node) -> None:
        title = f"{node.name} Services (Deprecated)"
        super().__init__(app, title)
        self.node: Node = node
        self.groups: Optional[ListboxScroll] = None
        self.services: Optional[CheckboxList] = None
        self.current: Optional[ListboxScroll] = None
        services = set(node.services)
        self.current_services: Set[str] = services
        self.protocol("WM_DELETE_WINDOW", self.click_cancel)
        self.draw()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        frame = ttk.Frame(self.top)
        frame.grid(stick="nsew", pady=PADY)
        frame.rowconfigure(0, weight=1)
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        label_frame = ttk.LabelFrame(frame, text="Groups", padding=FRAME_PAD)
        label_frame.grid(row=0, column=0, sticky=tk.NSEW)
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.groups = ListboxScroll(label_frame)
        self.groups.grid(sticky=tk.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)

        label_frame = ttk.LabelFrame(frame, text="Services")
        label_frame.grid(row=0, column=1, sticky=tk.NSEW)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        self.services = CheckboxList(label_frame,
                                     self.app,
                                     clicked=self.service_clicked,
                                     padding=FRAME_PAD)
        self.services.grid(sticky=tk.NSEW)

        label_frame = ttk.LabelFrame(frame, text="Selected", padding=FRAME_PAD)
        label_frame.grid(row=0, column=2, sticky=tk.NSEW)
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.current = ListboxScroll(label_frame)
        self.current.grid(sticky=tk.NSEW)
        for service in sorted(self.current_services):
            self.current.listbox.insert(tk.END, service)
            if self.is_custom_service(service):
                self.current.listbox.itemconfig(tk.END, bg="green")

        frame = ttk.Frame(self.top)
        frame.grid(stick="ew")
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame,
                            text="Configure",
                            command=self.click_configure)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Save", command=self.click_save)
        button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Remove", command=self.click_remove)
        button.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
        button.grid(row=0, column=3, sticky=tk.EW)

        # trigger group change
        self.handle_group_change()

    def handle_group_change(self, event: tk.Event = None) -> None:
        selection = self.groups.listbox.curselection()
        if selection:
            index = selection[0]
            group = self.groups.listbox.get(index)
            self.services.clear()
            for name in sorted(self.app.core.services[group]):
                checked = name in self.current_services
                self.services.add(name, checked)

    def service_clicked(self, name: str, var: tk.IntVar) -> None:
        if var.get() and name not in self.current_services:
            self.current_services.add(name)
        elif not var.get() and name in self.current_services:
            self.current_services.remove(name)
            self.node.service_configs.pop(name, None)
            self.node.service_file_configs.pop(name, None)
        self.current.listbox.delete(0, tk.END)
        for name in sorted(self.current_services):
            self.current.listbox.insert(tk.END, name)
            if self.is_custom_service(name):
                self.current.listbox.itemconfig(tk.END, bg="green")
        self.node.services = self.current_services.copy()

    def click_configure(self) -> None:
        current_selection = self.current.listbox.curselection()
        if len(current_selection):
            dialog = ServiceConfigDialog(
                self,
                self.app,
                self.current.listbox.get(current_selection[0]),
                self.node,
            )

            # if error occurred when creating ServiceConfigDialog, don't show the dialog
            if not dialog.has_error:
                dialog.show()
            else:
                dialog.destroy()
        else:
            messagebox.showinfo("Service Configuration",
                                "Select a service to configure",
                                parent=self)

    def click_cancel(self) -> None:
        self.destroy()

    def click_save(self) -> None:
        self.node.services = self.current_services.copy()
        self.destroy()

    def click_remove(self) -> None:
        cur = self.current.listbox.curselection()
        if cur:
            service = self.current.listbox.get(cur[0])
            self.current.listbox.delete(cur[0])
            self.current_services.remove(service)
            self.node.service_configs.pop(service, None)
            self.node.service_file_configs.pop(service, None)
            for checkbutton in self.services.frame.winfo_children():
                if checkbutton["text"] == service:
                    checkbutton.invoke()
                    return

    def is_custom_service(self, service: str) -> bool:
        has_service_config = service in self.node.service_configs
        has_file_config = service in self.node.service_file_configs
        return has_service_config or has_file_config
예제 #22
0
    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        row = 0

        # field states
        state = tk.DISABLED if self.app.core.is_runtime() else tk.NORMAL
        combo_state = tk.DISABLED if self.app.core.is_runtime() else "readonly"

        # field frame
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        frame.columnconfigure(1, weight=1)

        # icon field
        label = ttk.Label(frame, text="Icon")
        label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY)
        self.image_button = ttk.Button(
            frame,
            text="Icon",
            image=self.image,
            compound=tk.NONE,
            command=self.click_icon,
        )
        self.image_button.grid(row=row, column=1, sticky=tk.EW)
        row += 1

        # name field
        label = ttk.Label(frame, text="Name")
        label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY)
        entry = validation.NodeNameEntry(frame,
                                         textvariable=self.name,
                                         state=state)
        entry.grid(row=row, column=1, sticky=tk.EW)
        row += 1

        # node type field
        if NodeUtils.is_model_node(self.node.type):
            label = ttk.Label(frame, text="Type")
            label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY)
            combobox = ttk.Combobox(
                frame,
                textvariable=self.type,
                values=list(NodeUtils.NODE_MODELS),
                state=combo_state,
            )
            combobox.grid(row=row, column=1, sticky=tk.EW)
            row += 1

        # container image field
        if NodeUtils.is_image_node(self.node.type):
            label = ttk.Label(frame, text="Image")
            label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY)
            entry = ttk.Entry(frame,
                              textvariable=self.container_image,
                              state=state)
            entry.grid(row=row, column=1, sticky=tk.EW)
            row += 1

        if NodeUtils.is_container_node(self.node.type):
            # server
            frame.grid(sticky=tk.EW)
            frame.columnconfigure(1, weight=1)
            label = ttk.Label(frame, text="Server")
            label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY)
            servers = ["localhost"]
            servers.extend(list(sorted(self.app.core.servers.keys())))
            combobox = ttk.Combobox(frame,
                                    textvariable=self.server,
                                    values=servers,
                                    state=combo_state)
            combobox.grid(row=row, column=1, sticky=tk.EW)
            row += 1

        if NodeUtils.is_rj45_node(self.node.type):
            response = self.app.core.client.get_ifaces()
            logging.debug("host machine available interfaces: %s", response)
            ifaces = ListboxScroll(frame)
            ifaces.listbox.config(state=state)
            ifaces.grid(row=row,
                        column=0,
                        columnspan=2,
                        sticky=tk.EW,
                        padx=PADX,
                        pady=PADY)
            for inf in sorted(response.ifaces[:]):
                ifaces.listbox.insert(tk.END, inf)
            row += 1
            ifaces.listbox.bind("<<ListboxSelect>>", self.iface_select)

        # interfaces
        if self.canvas_node.ifaces:
            self.draw_ifaces()

        self.draw_spacer()
        self.draw_buttons()
예제 #23
0
class NodeConfigServiceDialog(Dialog):
    def __init__(
        self,
        master: Any,
        app: "Application",
        canvas_node: "CanvasNode",
        services: Set[str] = None,
    ):
        title = f"{canvas_node.core_node.name} Config Services"
        super().__init__(master, app, title, modal=True)
        self.app = app
        self.canvas_node = canvas_node
        self.node_id = canvas_node.core_node.id
        self.groups = None
        self.services = None
        self.current = None
        if services is None:
            services = set(canvas_node.core_node.config_services)
        self.current_services = services
        self.draw()

    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        frame = ttk.Frame(self.top)
        frame.grid(stick="nsew", pady=PADY)
        frame.rowconfigure(0, weight=1)
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        label_frame = ttk.LabelFrame(frame, text="Groups", padding=FRAME_PAD)
        label_frame.grid(row=0, column=0, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.groups = ListboxScroll(label_frame)
        self.groups.grid(sticky="nsew")
        for group in sorted(self.app.core.config_services_groups):
            self.groups.listbox.insert(tk.END, group)
        self.groups.listbox.bind("<<ListboxSelect>>", self.handle_group_change)
        self.groups.listbox.selection_set(0)

        label_frame = ttk.LabelFrame(frame, text="Services")
        label_frame.grid(row=0, column=1, sticky="nsew")
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        self.services = CheckboxList(
            label_frame, self.app, clicked=self.service_clicked, padding=FRAME_PAD
        )
        self.services.grid(sticky="nsew")

        label_frame = ttk.LabelFrame(frame, text="Selected", padding=FRAME_PAD)
        label_frame.grid(row=0, column=2, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.current = ListboxScroll(label_frame)
        self.current.grid(sticky="nsew")
        for service in sorted(self.current_services):
            self.current.listbox.insert(tk.END, service)
            if self.is_custom_service(service):
                self.current.listbox.itemconfig(tk.END, bg="green")

        frame = ttk.Frame(self.top)
        frame.grid(stick="ew")
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Configure", command=self.click_configure)
        button.grid(row=0, column=0, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Save", command=self.click_save)
        button.grid(row=0, column=1, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Remove", command=self.click_remove)
        button.grid(row=0, column=2, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
        button.grid(row=0, column=3, sticky="ew")

        # trigger group change
        self.groups.listbox.event_generate("<<ListboxSelect>>")

    def handle_group_change(self, event: tk.Event = None):
        selection = self.groups.listbox.curselection()
        if selection:
            index = selection[0]
            group = self.groups.listbox.get(index)
            self.services.clear()
            for name in sorted(self.app.core.config_services_groups[group]):
                checked = name in self.current_services
                self.services.add(name, checked)

    def service_clicked(self, name: str, var: tk.IntVar):
        if var.get() and name not in self.current_services:
            self.current_services.add(name)
        elif not var.get() and name in self.current_services:
            self.current_services.remove(name)
        self.current.listbox.delete(0, tk.END)
        for name in sorted(self.current_services):
            self.current.listbox.insert(tk.END, name)
            if self.is_custom_service(name):
                self.current.listbox.itemconfig(tk.END, bg="green")
        self.canvas_node.core_node.config_services[:] = self.current_services

    def click_configure(self):
        current_selection = self.current.listbox.curselection()
        if len(current_selection):
            dialog = ConfigServiceConfigDialog(
                master=self,
                app=self.app,
                service_name=self.current.listbox.get(current_selection[0]),
                node_id=self.node_id,
            )
            if not dialog.has_error:
                dialog.show()
        else:
            messagebox.showinfo(
                "Node service configuration", "Select a service to configure"
            )

    def click_save(self):
        self.canvas_node.core_node.config_services[:] = self.current_services
        logging.info(
            "saved node config services: %s", self.canvas_node.core_node.config_services
        )
        self.destroy()

    def click_cancel(self):
        self.current_services = None
        self.destroy()

    def click_remove(self):
        cur = self.current.listbox.curselection()
        if cur:
            service = self.current.listbox.get(cur[0])
            self.current.listbox.delete(cur[0])
            self.current_services.remove(service)
            for checkbutton in self.services.frame.winfo_children():
                if checkbutton["text"] == service:
                    checkbutton.invoke()
                    return

    def is_custom_service(self, service: str) -> bool:
        node_configs = self.app.core.config_service_configs.get(self.node_id, {})
        service_config = node_configs.get(service)
        if node_configs and service_config:
            return True
        else:
            return False
예제 #24
0
class NodeServiceDialog(Dialog):
    def __init__(
        self,
        master: Any,
        app: "Application",
        canvas_node: "CanvasNode",
        services: Set[str] = None,
    ):
        title = f"{canvas_node.core_node.name} Services"
        super().__init__(master, app, title, modal=True)
        self.app = app
        self.canvas_node = canvas_node
        self.node_id = canvas_node.core_node.id
        self.groups = None
        self.services = None
        self.current = None
        if services is None:
            services = canvas_node.core_node.services
            model = canvas_node.core_node.model
            if len(services) == 0:
                # not custom node type and node's services haven't been modified before
                if not NodeUtils.is_custom(
                        canvas_node.core_node.model
                ) and not self.app.core.service_been_modified(self.node_id):
                    services = set(self.app.core.default_services[model])
                # services of default type nodes were modified to be empty
                elif canvas_node.core_node.id in self.app.core.modified_service_nodes:
                    services = set()
                else:
                    services = set(
                        NodeUtils.get_custom_node_services(
                            self.app.guiconfig, model))
            else:
                services = set(services)
        self.current_services = services
        self.draw()

    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        frame = ttk.Frame(self.top)
        frame.grid(stick="nsew", pady=PADY)
        frame.rowconfigure(0, weight=1)
        for i in range(3):
            frame.columnconfigure(i, weight=1)
        label_frame = ttk.LabelFrame(frame, text="Groups", padding=FRAME_PAD)
        label_frame.grid(row=0, column=0, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.groups = ListboxScroll(label_frame)
        self.groups.grid(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)

        label_frame = ttk.LabelFrame(frame, text="Services")
        label_frame.grid(row=0, column=1, sticky="nsew")
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        self.services = CheckboxList(label_frame,
                                     self.app,
                                     clicked=self.service_clicked,
                                     padding=FRAME_PAD)
        self.services.grid(sticky="nsew")

        label_frame = ttk.LabelFrame(frame, text="Selected", padding=FRAME_PAD)
        label_frame.grid(row=0, column=2, sticky="nsew")
        label_frame.rowconfigure(0, weight=1)
        label_frame.columnconfigure(0, weight=1)
        self.current = ListboxScroll(label_frame)
        self.current.grid(sticky="nsew")
        for service in sorted(self.current_services):
            self.current.listbox.insert(tk.END, service)
            if self.is_custom_service(service):
                self.current.listbox.itemconfig(tk.END, bg="green")

        frame = ttk.Frame(self.top)
        frame.grid(stick="ew")
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame,
                            text="Configure",
                            command=self.click_configure)
        button.grid(row=0, column=0, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Save", command=self.click_save)
        button.grid(row=0, column=1, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Remove", command=self.click_remove)
        button.grid(row=0, column=2, sticky="ew", padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
        button.grid(row=0, column=3, sticky="ew")

        # trigger group change
        self.groups.listbox.event_generate("<<ListboxSelect>>")

    def handle_group_change(self, event: tk.Event = None):
        selection = self.groups.listbox.curselection()
        if selection:
            index = selection[0]
            group = self.groups.listbox.get(index)
            self.services.clear()
            for name in sorted(self.app.core.services[group]):
                checked = name in self.current_services
                self.services.add(name, checked)

    def service_clicked(self, name: str, var: tk.IntVar):
        if var.get() and name not in self.current_services:
            self.current_services.add(name)
        elif not var.get() and name in self.current_services:
            self.current_services.remove(name)
        self.current.listbox.delete(0, tk.END)
        for name in sorted(self.current_services):
            self.current.listbox.insert(tk.END, name)
            if self.is_custom_service(name):
                self.current.listbox.itemconfig(tk.END, bg="green")
        self.canvas_node.core_node.services[:] = self.current_services

    def click_configure(self):
        current_selection = self.current.listbox.curselection()
        if len(current_selection):
            dialog = ServiceConfigDialog(
                master=self,
                app=self.app,
                service_name=self.current.listbox.get(current_selection[0]),
                node_id=self.node_id,
            )

            # if error occurred when creating ServiceConfigDialog, don't show the dialog
            if not dialog.has_error:
                dialog.show()
            else:
                dialog.destroy()
        else:
            messagebox.showinfo("Node service configuration",
                                "Select a service to configure")

    def click_save(self):
        # if node is custom type or current services are not the default services then set core node services and add node to modified services node set
        if (self.canvas_node.core_node.model
                not in self.app.core.default_services
                or self.current_services != self.app.core.default_services[
                    self.canvas_node.core_node.model]):
            self.canvas_node.core_node.services[:] = self.current_services
            self.app.core.modified_service_nodes.add(
                self.canvas_node.core_node.id)
        else:
            if len(self.canvas_node.core_node.services) > 0:
                self.canvas_node.core_node.services[:] = []
        self.destroy()

    def click_cancel(self):
        self.current_services = None
        self.destroy()

    def click_remove(self):
        cur = self.current.listbox.curselection()
        if cur:
            service = self.current.listbox.get(cur[0])
            self.current.listbox.delete(cur[0])
            self.current_services.remove(service)
            for checkbutton in self.services.frame.winfo_children():
                if checkbutton["text"] == service:
                    checkbutton.invoke()
                    return

    def is_custom_service(self, service: str) -> bool:
        service_configs = self.app.core.service_configs
        file_configs = self.app.core.file_configs
        if self.node_id in service_configs and service in service_configs[
                self.node_id]:
            return True
        if (self.node_id in file_configs
                and service in file_configs[self.node_id]
                and file_configs[self.node_id][service]):
            return True
        return False