Initial
This commit is contained in:
161
lxc_ls.py
Normal file
161
lxc_ls.py
Normal file
@@ -0,0 +1,161 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, messagebox
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
class LXCInfoGUI:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.column_width = 120
|
||||
columns = ('Host Name', 'Pool', 'IP Address', 'Nesting / Protect', 'OS', 'Status')
|
||||
self.tree = ttk.Treeview(self.parent, columns=columns, show='headings')
|
||||
|
||||
for col in columns:
|
||||
self.tree.heading(col, text=col, command=lambda c=col: self.column_sort(c, False))
|
||||
self.tree.column(col, width=self.column_width, anchor='w')
|
||||
|
||||
self.tree.pack(padx=10, pady=10)
|
||||
|
||||
self.tree.bind("<Double-1>", self.on_tree_double_click)
|
||||
|
||||
self.refresh_button = ttk.Button(self.parent, text='Aktualisieren', command=self.refresh_info)
|
||||
self.refresh_button.pack(pady=10)
|
||||
|
||||
self.parent.after(10000, self.auto_refresh_info)
|
||||
|
||||
self.refresh_info()
|
||||
|
||||
self.context_menu = tk.Menu(self.parent, tearoff=0)
|
||||
self.configure_context_menu()
|
||||
|
||||
self.tree.bind("<Button-3>", self.show_context_menu)
|
||||
|
||||
def configure_context_menu(self):
|
||||
menu_items = [
|
||||
("Start", self.start_container),
|
||||
("Stoppen", self.stop_container),
|
||||
("Löschen", self.delete_container),
|
||||
None, # Separator
|
||||
("ProtecNO", self.set_protection_no),
|
||||
("ProtectYES", self.set_protection_yes)
|
||||
]
|
||||
|
||||
for item in menu_items:
|
||||
if item:
|
||||
label, command = item
|
||||
self.context_menu.add_command(label=label, command=command)
|
||||
else:
|
||||
self.context_menu.add_separator()
|
||||
|
||||
def show_context_menu(self, event):
|
||||
self.context_menu.post(event.x_root, event.y_root)
|
||||
|
||||
def run_command(self, command):
|
||||
try:
|
||||
result = subprocess.run(command, stdout=subprocess.PIPE, text=True, shell=True, check=True)
|
||||
return result.stdout.strip()
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Fehler beim Ausführen des Befehls: {e}")
|
||||
return ""
|
||||
|
||||
def get_lxc_info(self):
|
||||
command_output = self.run_command(
|
||||
"lxc list -f json | jq -cr '(.[] | [.name, .expanded_devices.root.pool, "
|
||||
"(.state.network.eth0.addresses // [] | map(select(.family == \"inet\").address) | join(\", \")), "
|
||||
"(.config.\"security.nesting\" // false), (.config.\"security.protection.delete\" // false), "
|
||||
".config.\"image.os\", .config.\"image.release\", .state.status])'"
|
||||
)
|
||||
try:
|
||||
lxc_info = [json.loads(line) for line in command_output.splitlines()]
|
||||
lxc_info.sort(key=lambda x: x[7] != 'Stopped')
|
||||
return lxc_info
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Fehler beim Dekodieren von JSON: {e}")
|
||||
return []
|
||||
|
||||
def refresh_info(self):
|
||||
for item in self.tree.get_children():
|
||||
self.tree.delete(item)
|
||||
|
||||
lxc_info = self.get_lxc_info()
|
||||
|
||||
self.tree.tag_configure('oddrow', background='#f0f0f0')
|
||||
self.tree.tag_configure('evenrow', background='white')
|
||||
|
||||
for i, container_info in enumerate(lxc_info):
|
||||
container_name, pool, ip_address, nesting, protection, os, release, status = container_info
|
||||
tags = ('oddrow', 'evenrow')[i % 2]
|
||||
self.tree.insert('', 'end', values=(container_name, pool, ip_address, f"{nesting}/{protection}",
|
||||
f"{os} {release}", status), tags=tags)
|
||||
|
||||
def auto_refresh_info(self):
|
||||
self.refresh_info()
|
||||
self.parent.after(10000, self.auto_refresh_info)
|
||||
|
||||
def on_tree_double_click(self, event):
|
||||
item = self.tree.selection()[0]
|
||||
container_name = self.tree.item(item, 'values')[0]
|
||||
status = self.tree.item(item, 'values')[5]
|
||||
|
||||
if status == 'Running':
|
||||
response = messagebox.askyesno("Container stoppen", f"Soll der Container '{container_name}' gestoppt werden?")
|
||||
if response:
|
||||
self.run_command(f"lxc stop {container_name}")
|
||||
elif status == 'Stopped':
|
||||
response = messagebox.askyesno("Container starten", f"Soll der Container '{container_name}' gestartet werden?")
|
||||
if response:
|
||||
self.run_command(f"lxc start {container_name}")
|
||||
|
||||
def start_container(self):
|
||||
item = self.tree.selection()[0]
|
||||
container_name = self.tree.item(item, 'values')[0]
|
||||
response = messagebox.askyesno("Container starten", f"Soll der Container '{container_name}' gestartet werden?")
|
||||
if response:
|
||||
self.run_command(f"lxc start {container_name}")
|
||||
|
||||
def stop_container(self):
|
||||
item = self.tree.selection()[0]
|
||||
container_name = self.tree.item(item, 'values')[0]
|
||||
response = messagebox.askyesno("Container stoppen", f"Soll der Container '{container_name}' gestoppt werden?")
|
||||
if response:
|
||||
self.run_command(f"lxc stop {container_name}")
|
||||
|
||||
def delete_container(self):
|
||||
item = self.tree.selection()[0]
|
||||
container_name = self.tree.item(item, 'values')[0]
|
||||
status = self.tree.item(item, 'values')[5]
|
||||
|
||||
if status == 'Running':
|
||||
response = messagebox.askyesno("Container löschen", f"Der Container '{container_name}' ist noch aktiv. Möchten Sie ihn trotzdem löschen?")
|
||||
if response:
|
||||
self.run_command(f"lxc stop {container_name}")
|
||||
self.run_command(f"lxc delete {container_name}")
|
||||
else:
|
||||
response = messagebox.askyesno("Container löschen", f"Soll der Container '{container_name}' gelöscht werden?")
|
||||
if response:
|
||||
self.run_command(f"lxc delete {container_name}")
|
||||
|
||||
def set_protection_no(self):
|
||||
self.set_protection(False)
|
||||
|
||||
def set_protection_yes(self):
|
||||
self.set_protection(True)
|
||||
|
||||
def set_protection(self, enable_protection):
|
||||
item = self.tree.selection()[0]
|
||||
container_name = self.tree.item(item, 'values')[0]
|
||||
|
||||
protection_setting = "true" if enable_protection else "false"
|
||||
self.run_command(f"lxc config set {container_name} security.protection.delete={protection_setting}")
|
||||
|
||||
def column_sort(self, col, reverse):
|
||||
l = [(self.tree.set(k, col), k) for k in self.tree.get_children('')]
|
||||
l.sort(reverse=reverse)
|
||||
|
||||
for index, (val, k) in enumerate(l):
|
||||
self.tree.move(k, '', index)
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
app = LXCInfoGUI(root)
|
||||
root.mainloop()
|
||||
Reference in New Issue
Block a user