init tools repo

This commit is contained in:
2025-11-23 19:57:05 +01:00
commit d778206940
35 changed files with 6197 additions and 0 deletions

View File

@@ -0,0 +1,220 @@
import sys
import os
import re # We need the regex module for easier parsing
from PyQt6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QLineEdit, QLabel, QPushButton, QTextEdit, QMessageBox
)
from PyQt6.QtCore import Qt
class SSHConfigManager(QWidget):
# --- Configuration for the Jump Host ---
JUMP_HOST_NAME = "asf-jump"
JUMP_HOST_DETAILS = f"""
Host {JUMP_HOST_NAME}
Hostname asf-server.duckdns.org
Port 49152
User asf
"""
def __init__(self):
super().__init__()
self.setWindowTitle("SSH Config Manager (PyQt6)")
self.setMinimumWidth(500)
self.config_path = os.path.expanduser("~/.ssh/config")
self.init_ui()
# Ensure directory and file exist
os.makedirs(os.path.dirname(self.config_path), exist_ok=True)
if not os.path.exists(self.config_path):
with open(self.config_path, 'w') as f:
f.write("")
self.ensure_jump_host_defined() # Check and add jump host immediately
self.load_config()
def init_ui(self):
main_layout = QVBoxLayout()
# --- 1. Input Fields for New VM ---
input_group = QVBoxLayout()
input_group.addWidget(QLabel("## 🛠️ Add New VM Entry"))
self.host_input = QLineEdit()
self.host_input.setPlaceholderText("Host (e.g., vm-test1)")
self.port_input = QLineEdit()
self.port_input.setPlaceholderText("Port (e.g., 6002)")
self.user_input = QLineEdit()
self.user_input.setPlaceholderText("User (e.g., asf_user)")
self.proxy_input = QLineEdit()
self.proxy_input.setPlaceholderText(f"ProxyJump (Default: {self.JUMP_HOST_NAME})")
self.proxy_input.setText(self.JUMP_HOST_NAME) # Pre-fill the jump host name
input_group.addWidget(self.host_input)
input_group.addWidget(self.port_input)
input_group.addWidget(self.user_input)
input_group.addWidget(self.proxy_input)
add_button = QPushButton(" Add VM & Save Config")
add_button.clicked.connect(self.add_vm_entry)
input_group.addWidget(add_button)
main_layout.addLayout(input_group)
main_layout.addWidget(QLabel("---"))
# --- 2. Existing Config Viewer ---
main_layout.addWidget(QLabel("## 📜 Current ~/.ssh/config Content"))
self.config_viewer = QTextEdit()
self.config_viewer.setReadOnly(True)
self.config_viewer.setMinimumHeight(150)
main_layout.addWidget(self.config_viewer)
# --- 3. Connection Instructions & Display ---
main_layout.addWidget(QLabel("## 🔗 Connection Info"))
info_layout = QHBoxLayout()
info_layout.addWidget(QLabel("Select VM Host:"))
self.vm_select = QLineEdit()
self.vm_select.setPlaceholderText("Enter Host name (e.g., vm-test1)")
info_layout.addWidget(self.vm_select)
show_button = QPushButton("Show Commands")
show_button.clicked.connect(self.show_connection_commands)
info_layout.addWidget(show_button)
main_layout.addLayout(info_layout)
self.command_output = QTextEdit()
self.command_output.setReadOnly(True)
self.command_output.setMinimumHeight(100)
main_layout.addWidget(self.command_output)
self.setLayout(main_layout)
def load_config(self):
"""Loads the current config file content into the viewer."""
try:
with open(self.config_path, 'r') as f:
content = f.read()
self.config_viewer.setText(content)
except Exception as e:
self.config_viewer.setText(f"Error loading config: {e}")
def ensure_jump_host_defined(self):
"""Checks if the JUMP_HOST_NAME is defined and adds it if missing."""
try:
with open(self.config_path, 'r+') as f:
content = f.read()
# Use regex to find if the Host definition already exists
if re.search(rf"^Host\s+{re.escape(self.JUMP_HOST_NAME)}\s*$", content, re.MULTILINE | re.IGNORECASE):
# print("Jump host already defined.") # For debugging
return
# If not found, append the definition to the beginning of the file
f.seek(0)
f.write(self.JUMP_HOST_DETAILS + "\n" + content)
f.truncate()
QMessageBox.information(self, "Setup Complete",
f"Automatically added the '{self.JUMP_HOST_NAME}' jump host definition to the config file.")
except Exception as e:
QMessageBox.critical(self, "Setup Error", f"Failed to ensure jump host definition: {e}")
def add_vm_entry(self):
"""Validates inputs, formats the entry, and appends it to the config file."""
host = self.host_input.text().strip()
port = self.port_input.text().strip()
user = self.user_input.text().strip()
proxy = self.proxy_input.text().strip()
if not all([host, port, user, proxy]):
QMessageBox.warning(self, "Input Error", "All fields must be filled out.")
return
# Ensure jump host is defined before adding dependent VMs
self.ensure_jump_host_defined()
new_entry = f"""
Host {host}
Hostname 127.0.0.1
Port {port}
User {user}
ProxyJump {proxy}
"""
try:
with open(self.config_path, 'a') as f:
f.write(new_entry)
QMessageBox.information(self, "Success", f"VM '{host}' successfully added to {self.config_path}!")
self.load_config() # Refresh the viewer
# Clear inputs
self.host_input.clear()
self.port_input.clear()
self.user_input.clear()
self.proxy_input.setText(self.JUMP_HOST_NAME) # Reset ProxyJump field
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to save file: {e}")
def show_connection_commands(self):
"""Generates and displays the connection commands for the selected VM."""
host = self.vm_select.text().strip()
if not host:
self.command_output.setText("Please enter a Host name to look up.")
return
ssh_port = None
try:
with open(self.config_path, 'r') as f:
content = f.read().splitlines()
# Simple line-by-line parser to find the port
current_host = None
for line in content:
line = line.strip()
if line.startswith('Host '):
current_host = line.split()[1]
elif current_host == host and line.startswith('Port '):
ssh_port = line.split()[1]
break
except Exception:
self.command_output.setText(f"Error reading config file to find port for {host}.")
return
if not ssh_port:
self.command_output.setText(f"Host '{host}' not found or Port not specified in config.")
return
# VNC Port (Assuming VNC Port = SSH Port - 1000, based on your ranges 6002/5002)
vnc_port = int(ssh_port) - 1000
# 2. Generate Commands
commands = f"""
✅ **SSH Command** (for direct console access via Jump Host):
ssh {host}
🖥️ **VNC Command** (for secure graphical access via SSH Tunnel):
1. Establish the tunnel (keep this window open/running):
ssh -L 5900:127.0.0.1:{vnc_port} {host} -N &
2. Connect VNC Client to your local machine:
VNC Host/Port: 127.0.0.1:5900
"""
self.command_output.setText(commands)
if __name__ == '__main__':
app = QApplication(sys.argv)
manager = SSHConfigManager()
manager.show()
sys.exit(app.exec())