Anpassungen hinzufügen von ssh-key und anpassung der out.csv

This commit is contained in:
2025-09-26 15:51:04 +02:00
parent 55035ba890
commit 7e4ef95c37
3 changed files with 163 additions and 14 deletions

View File

@@ -37,6 +37,7 @@ Führen Sie `setup_host.py` aus. Das Skript akzeptiert verschiedene Argumente, u
* `-b`, `--basename`: Der Basisname für die Container, falls die Vorlage `{basename}` enthält. (Standard: `vm`)
* `--no-port-forward`: Deaktiviert die SSH-Port-Weiterleitung.
* `--port-start`: Der Start-Port für die SSH-Weiterleitung, falls diese aktiv ist. (Standard: `2201`)
* `--ssh-pub-key-file`: Pfad zu einem öffentlichen SSH-Schlüssel, der für den Benutzer `jonnybravo` hinterlegt werden soll. (Standard: `~/.ssh/id_rsa.pub`)
---

View File

@@ -44,6 +44,7 @@ def main():
parser.add_argument("password", help="Das gewünschte root-Passwort.")
parser.add_argument("hostname", help="Der Hostname für diesen Container.")
parser.add_argument("distro", help="Die Distribution des Containers (z.B. 'arch', 'ubuntu').")
parser.add_argument("ssh_key", nargs='?', default="", help="Der öffentliche SSH-Schlüssel für den Benutzer 'jonnybravo'.")
args = parser.parse_args()
root_password = args.password
@@ -132,7 +133,18 @@ def main():
wheel_group_equivalent = "wheel" if distro in ["arch", "fedora"] else "sudo"
run_command(f"useradd -m -G {config['user_groups']} -s /bin/bash jonnybravo", "Benutzer 'jonnybravo' hinzufügen")
run_command("passwd jonnybravo", "Passwort für jonnybravo setzen", input_str=password_input)
# SSH-Schlüssel für jonnybravo einrichten
if args.ssh_key:
print("--- Richte SSH-Schlüssel für Benutzer 'jonnybravo' ein ---")
ssh_dir = "/home/jonnybravo/.ssh"
authorized_keys_file = os.path.join(ssh_dir, "authorized_keys")
run_command(f"mkdir -p {ssh_dir}", f"Erstelle Verzeichnis {ssh_dir}")
run_command(f"echo '{args.ssh_key}' > {authorized_keys_file}", f"Schreibe Schlüssel nach {authorized_keys_file}")
run_command(f"chown -R jonnybravo:jonnybravo {ssh_dir}", f"Setze Eigentümer für {ssh_dir}")
run_command(f"chmod 700 {ssh_dir}", f"Setze Berechtigungen für {ssh_dir}")
run_command(f"chmod 600 {authorized_keys_file}", f"Setze Berechtigungen für {authorized_keys_file}")
if wheel_group_equivalent == "wheel":
run_command("echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/wheel_nopasswd", "Passwortloses sudo für Gruppe 'wheel' aktivieren")
else: # sudo group

View File

@@ -1,12 +1,13 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# geschrieben vmit der Hilfe von Gemini2.5-pro
import subprocess
import os
import sys
import argparse
import time
import json
import pylxd
def run_command(command_str, description, ignore_errors=False):
@@ -75,6 +76,9 @@ def get_container_ip(container_name):
def main():
os.environ['PYLXD_WARNINGS'] = 'none'
host_folder = "/home/jonnybravo/lxc_folder"
parser = argparse.ArgumentParser(
description="Erstellt und konfiguriert mehrere LXD-Container.")
parser.add_argument("-c", "--count", type=int, default=1,
@@ -91,6 +95,8 @@ def main():
help="Zu verwendendes Image (z.B. images:archlinux, ubuntu:22.04).")
parser.add_argument("--no-port-forward", action="store_true",
help="Überspringt die Einrichtung der SSH-Port-Weiterleitung.")
parser.add_argument("--ssh-pub-key-file", default="~/.ssh/ansible-test.pub",
help="Pfad zur öffentlichen SSH-Schlüsseldatei, die für den Benutzer 'jonnybravo' autorisiert werden soll.")
args = parser.parse_args()
if args.count > 1 and '{i}' not in args.hostname_template:
@@ -99,15 +105,139 @@ def main():
sys.exit(1)
run_command("command -v lxc >/dev/null", "Prüfe, ob LXD installiert ist")
print("LXD ist verfügbar. WICHTIG: Es wird davon ausgegangen, dass 'lxd init' bereits ausgeführt wurde.")
client = pylxd.Client(project='default')
# Überprüfe, ob das Profil 'myprofile' existiert, und erstelle es, falls nicht
try:
client.profiles.get("myprofile")
print("\n--- Profil 'myprofile' existiert bereits. Aktualisiere es. ---")
profile = client.profiles.get("myprofile")
profile.config = {"security.nesting": "true",
"security.privileged": "true"}
profile.devices = {
"root": {
"path": "/",
"pool": "default",
"type": "disk",
},
"eth0": {
"name": "eth0",
"network": "lxdbr0",
"type": "nic",
},
"public": {
"path": "/public",
"source": host_folder,
"type": "disk",
}
}
profile.save()
except pylxd.exceptions.NotFound:
print("\n--- Profil 'myprofile' nicht gefunden. Erstelle es. ---")
profile_config = {"security.nesting": "true",
"security.privileged": "true"}
profile_devices = {
"root": {
"path": "/",
"pool": "default",
"type": "disk",
},
"eth0": {
"name": "eth0",
"network": "lxdbr0",
"type": "nic",
},
"public": {
"path": "/public",
"source": host_folder,
"type": "disk",
}
}
client.profiles.create("myprofile", profile_config, profile_devices)
# Erstelle den Ordner auf dem Host, falls er nicht existiert
if not os.path.exists(host_folder):
print(f"--- Erstelle Host-Ordner: {host_folder} ---")
os.makedirs(host_folder)
else:
print(f"--- Host-Ordner {host_folder} existiert bereits. ---")
# Konfiguriere lxdbr0, falls nicht bereits geschehen
try:
run_command("lxc network show lxdbr0",
"Prüfe, ob lxdbr0 existiert", ignore_errors=True)
except subprocess.CalledProcessError:
print("\n--- lxdbr0 nicht gefunden. Konfiguriere es. ---")
run_command("lxc network set lxdbr0 ipv4.address 10.0.4.1/24",
"Setze IPv4-Adresse für lxdbr0")
run_command("lxc network set lxdbr0 ipv4.nat true",
"Aktiviere IPv4-NAT für lxdbr0")
run_command("lxc network set lxdbr0 ipv6.address none",
"Deaktiviere IPv6 für lxdbr0")
else:
print("\n--- lxdbr0 existiert bereits. ---")
# Lese den öffentlichen SSH-Schlüssel
ssh_key_path = os.path.expanduser(args.ssh_pub_key_file)
ssh_key_content = ""
if os.path.exists(ssh_key_path):
with open(ssh_key_path, 'r') as f:
ssh_key_content = f.read().strip()
print(f"--- SSH-Schlüssel von {ssh_key_path} geladen. ---")
else:
print(f"--- WARNUNG: SSH-Schlüsseldatei nicht gefunden unter {
ssh_key_path}. Der Schlüssel wird nicht kopiert. ---")
# Importiere pylxd und initialisiere den Client
# client = pylxd.Client() # Dies sollte bereits oben geschehen sein
# Initialisiere LXD, falls nicht bereits geschehen
# try:
# client.api.get('/')
# print("\n--- LXD ist bereits initialisiert. ---")
# except pylxd.exceptions.ClientConnectionFailed:
# print("\n--- LXD ist nicht initialisiert. Initialisiere es. ---")
# run_command("lxd init --auto", "Initialisiere LXD")
# Erstelle den 'out'-Ordner, falls er nicht existiert
if not os.path.exists("out"):
os.makedirs("out")
# Bereinige die CSV-Datei von alten Einträgen
csv_path = "out/clients.csv"
if os.path.exists(csv_path):
print(f"\n--- Bereinige {csv_path} von alten Einträgen ---")
try:
result = run_command("lxc list --format json",
"Frage alle Container ab", ignore_errors=True)
if result and result.returncode == 0:
existing_containers = {c['name']
for c in json.loads(result.stdout)}
valid_clients = []
with open(csv_path, 'r') as f:
lines = f.readlines()
if lines:
header = lines[0]
valid_clients.append(header)
for line in lines[1:]:
try:
name = line.strip().split(',')[0]
if name in existing_containers:
valid_clients.append(line)
except IndexError:
pass # Ignoriere leere oder fehlerhafte Zeilen
with open(csv_path, 'w') as f:
f.writelines(valid_clients)
print(f"--- {csv_path} erfolgreich bereinigt. ---")
except (json.JSONDecodeError, FileNotFoundError):
print(f"--- WARNUNG: Konnte {csv_path} nicht bereinigen. ---")
# Stelle sicher, dass die CSV-Datei existiert und einen Header hat
if not os.path.exists(csv_path) or os.path.getsize(csv_path) == 0:
with open(csv_path, "w") as f:
f.write("name,ip\n")
elif not os.path.isdir("out"):
# os.remove("out")
os.makedirs("out")
clients = []
@@ -117,10 +247,17 @@ def main():
print(f"{'=' * 20} ERSTELLE CONTAINER: {vm_name} {'=' * 20}")
run_command(f"lxc delete {vm_name} --force",
f"{vm_name} vorsorglich löschen", ignore_errors=True)
try:
client.containers.get(vm_name)
print(
f"--- HINWEIS: Container '{vm_name}' existiert bereits und wird übersprungen. ---")
continue
except pylxd.exceptions.NotFound:
pass
run_command(f"lxc launch {args.image} {
vm_name}", f"Starte {vm_name} von Image")
vm_name} -p myprofile", f"Starte {vm_name} von Image mit myprofile")
wait_for_network(vm_name)
distro_id_command = "lxc exec {} -- cat /etc/os-release | grep '^ID=' | cut -d'=' -f2"
@@ -130,11 +267,11 @@ def main():
install_cmd = ""
if distro_id == "arch":
install_cmd = "pacman -Sy --noconfirm python"
install_cmd = "pacman -Sy --noconfirm python vim "
elif distro_id in ["ubuntu", "debian"]:
install_cmd = "sh -c 'export DEBIAN_FRONTEND=noninteractive; apt-get update && apt-get install -y python3'"
install_cmd = "sh -c 'export DEBIAN_FRONTEND=noninteractive; apt-get update && apt-get install -y python3 vim'"
elif distro_id == "fedora":
install_cmd = "dnf install -y python3"
install_cmd = "dnf install -y python3 vim"
else:
print(f"FEHLER: Nicht unterstützte Distribution: {
distro_id}", file=sys.stderr)
@@ -146,7 +283,7 @@ def main():
run_command(f"lxc file push setup_container.py {
vm_name}/root/", f"Kopiere Setup-Skript nach {vm_name}")
run_command(f"lxc exec {vm_name} -- python3 /root/setup_container.py '{
args.root_password}' '{vm_name}' '{distro_id}'", f"Führe Konfiguration in {vm_name} aus")
args.root_password}' '{vm_name}' '{distro_id}' '{ssh_key_content}'", f"Führe Konfiguration in {vm_name} aus")
ssh_info = ""
if not args.no_port_forward:
@@ -171,7 +308,6 @@ def main():
if clients:
csv_path = "out/clients.csv"
with open(csv_path, "a") as f:
# f.write("name,ip\n")
for client in clients:
f.write(f"{client['name']},{client['ip']}\n")
print(f"\nAlle Container wurden erstellt und in {