new file: add_domain.py
new file: admin-helper.py new file: admin_helper.txt new file: custom_update_lsp.sh new file: custom_update_lsp.txt new file: custom_update_sns.sh new file: puppet_connect.bin new file: puppet_connect.py
This commit is contained in:
+205
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
import tkinter.ttk as ttk
|
||||
import urllib.request
|
||||
import json
|
||||
import tempfile
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import threading
|
||||
from urllib.parse import urljoin
|
||||
|
||||
# Список серверов
|
||||
SERVERS = [
|
||||
{"name": "Гринатом (МСК)", "url": "http://gren-s-synd01.gk.rosatom.local/admin_helper/"},
|
||||
{"name": "Гринатом (НН)", "url": "http://grenn-s-synd01.gk.rosatom.local/admin_helper/"},
|
||||
{"name": "ГК Росатом", "url": "http://gkrs-s-synd01.gk.rosatom.local/admin_helper/"},
|
||||
]
|
||||
|
||||
# Имя файла описания (manifest)
|
||||
MANIFEST_FILE = "scripts.json"
|
||||
|
||||
class AdminHelper:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("Admin Helper (Linux)")
|
||||
self.root.geometry("500x450")
|
||||
|
||||
# --- Верхняя панель (Выпадающий список) ---
|
||||
self.server_frame = tk.Frame(root, pady=10, bg="#f0f0f0")
|
||||
self.server_frame.pack(fill='x')
|
||||
tk.Label(self.server_frame, text="Сервер:", bg="#f0f0f0", font=("Arial", 10, "bold")).pack(side='left', padx=5)
|
||||
# Создаем выпадающий список
|
||||
server_names = [s['name'] for s in SERVERS]
|
||||
self.server_combo = ttk.Combobox(
|
||||
self.server_frame,
|
||||
values=server_names,
|
||||
state="readonly", # Запрещаем ручной ввод, можно только выбирать
|
||||
width=30
|
||||
)
|
||||
self.server_combo.pack(side='left', padx=5)
|
||||
# Если есть серверы, выбираем первый по умолчанию
|
||||
if server_names:
|
||||
self.server_combo.current(0)
|
||||
# Кнопка "Загрузить" для явного вызова
|
||||
self.btn_connect = tk.Button(
|
||||
self.server_frame,
|
||||
text="Загрузить скрипты",
|
||||
command=self.on_server_select
|
||||
)
|
||||
self.btn_connect.pack(side='left', padx=5)
|
||||
self.server_combo.bind("<<ComboboxSelected>>")
|
||||
self.active_server_label = tk.Label(root, text="Выберите сервер", fg="blue")
|
||||
self.active_server_label.pack(pady=(0, 10))
|
||||
|
||||
# --- Основная часть (Скролл) ---
|
||||
self.main_frame = tk.Frame(root)
|
||||
self.main_frame.pack(expand=True, fill='both')
|
||||
|
||||
self.label_title = tk.Label(
|
||||
self.main_frame,
|
||||
text="Выберите действие",
|
||||
font=("Arial", 14)
|
||||
)
|
||||
self.label_title.pack(pady=10)
|
||||
|
||||
self.canvas = tk.Canvas(self.main_frame)
|
||||
self.scrollbar = tk.Scrollbar(self.main_frame, orient="vertical", command=self.canvas.yview)
|
||||
self.scrollable_frame = tk.Frame(self.canvas)
|
||||
|
||||
self.scrollable_frame.bind(
|
||||
"<Configure>",
|
||||
lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all"))
|
||||
)
|
||||
|
||||
self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
|
||||
self.canvas.configure(yscrollcommand=self.scrollbar.set)
|
||||
|
||||
self.canvas.pack(side="left", fill="both", expand=True, padx=20)
|
||||
self.scrollbar.pack(side="right", fill="y")
|
||||
|
||||
self.status_label = tk.Label(root, text="Ожидание...", bd=1, relief=tk.SUNKEN, anchor=tk.W)
|
||||
self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
|
||||
|
||||
def on_server_select(self, event=None):
|
||||
"""Срабатывает при выборе сервера из списка"""
|
||||
selected_name = self.server_combo.get()
|
||||
|
||||
# Ищем данные сервера в общем списке по имени
|
||||
server_info = next((s for s in SERVERS if s['name'] == selected_name), None)
|
||||
|
||||
if server_info:
|
||||
self.connect_to_server(server_info)
|
||||
else:
|
||||
self.status_label.config(text="Ошибка: сервер не найден")
|
||||
|
||||
def connect_to_server(self, server_info):
|
||||
base_url = server_info['url']
|
||||
name = server_info['name']
|
||||
self.active_server_label.config(text=f"Активен: {name}")
|
||||
|
||||
# Очистка
|
||||
for widget in self.scrollable_frame.winfo_children():
|
||||
widget.destroy()
|
||||
|
||||
self.status_label.config(text=f"Загрузка {MANIFEST_FILE}...")
|
||||
thread = threading.Thread(target=self.load_scripts_from_json, args=(base_url,), daemon=True)
|
||||
thread.start()
|
||||
|
||||
def download_content(self, url):
|
||||
"""Универсальный загрузчик (текст или бинарник)"""
|
||||
try:
|
||||
headers = {'User-Agent': 'Mozilla/5.0'}
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
with urllib.request.urlopen(req) as response:
|
||||
return response.read()
|
||||
except Exception as e:
|
||||
print(f"Ошибка загрузки {url}: {e}")
|
||||
return None
|
||||
|
||||
def load_scripts_from_json(self, base_url):
|
||||
# 1. Формируем ссылку на JSON-файл
|
||||
manifest_url = urljoin(base_url, MANIFEST_FILE)
|
||||
json_data = self.download_content(manifest_url)
|
||||
|
||||
if not json_data:
|
||||
self.root.after(0, lambda: self.status_label.config(text="Ошибка: не найден scripts.json"))
|
||||
return
|
||||
|
||||
# 2. Парсим JSON
|
||||
try:
|
||||
script_list = json.loads(json_data)
|
||||
except json.JSONDecodeError:
|
||||
self.root.after(0, lambda: self.status_label.config(text="Ошибка: неверный формат JSON"))
|
||||
return
|
||||
|
||||
# 3. Проходим по списку и скачиваем файлы
|
||||
count = 0
|
||||
for item in script_list:
|
||||
name = item.get('name', 'Без имени')
|
||||
filename = item.get('file')
|
||||
|
||||
if not filename:
|
||||
continue
|
||||
|
||||
script_url = urljoin(base_url, filename)
|
||||
content = self.download_content(script_url)
|
||||
|
||||
if content:
|
||||
# Определяем тип по расширению
|
||||
file_ext = filename.split('.')[-1].lower()
|
||||
|
||||
# Создаем кнопку
|
||||
self.root.after(0, lambda n=name, c=content, f=filename, ext=file_ext: self.create_action_button(n, c, f, ext))
|
||||
count += 1
|
||||
|
||||
if count == 0:
|
||||
self.root.after(0, lambda: self.status_label.config(text="Нет доступных скриптов"))
|
||||
else:
|
||||
self.root.after(0, lambda: self.status_label.config(text=f"Загружено: {count} скриптов"))
|
||||
|
||||
def create_action_button(self, text, content, filename, ext):
|
||||
btn = tk.Button(
|
||||
self.scrollable_frame,
|
||||
text=text,
|
||||
width=40,
|
||||
height=2,
|
||||
anchor="w"
|
||||
)
|
||||
btn.config(command=lambda c=content, f=filename, e=ext: self.run_file(c, f, e))
|
||||
|
||||
btn.pack(pady=2, fill='x')
|
||||
|
||||
def run_file(self, content, filename, ext):
|
||||
try:
|
||||
# Создаем временный файл
|
||||
with tempfile.NamedTemporaryFile(mode='wb', suffix=f'.{ext}', delete=False) as tmp_file:
|
||||
tmp_file.write(content)
|
||||
tmp_path = tmp_file.name
|
||||
|
||||
# Логика запуска для Linux
|
||||
if ext == 'bin':
|
||||
# 1. Делаем файл исполняемым (chmod +x)
|
||||
os.chmod(tmp_path, 0o755)
|
||||
# 2. Запускаем напрямую
|
||||
subprocess.Popen([tmp_path])
|
||||
|
||||
elif ext == 'sh':
|
||||
os.chmod(tmp_path, 0o755)
|
||||
subprocess.Popen(['xterm', '-e', tmp_path])
|
||||
|
||||
else:
|
||||
messagebox.showwarning("Внимание", f"Неизвестный тип файла: {ext}")
|
||||
|
||||
# ИЗМЕНЕНИЕ: Убрали всплывающее окно, просто пишем в статус-бар
|
||||
self.status_label.config(text=f"Запущен: {filename}")
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("Ошибка", f"Не удалось запустить: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
app = AdminHelper(root)
|
||||
root.mainloop()
|
||||
Reference in New Issue
Block a user