Anpassungen hinzufügen von ssh-key und anpassung der out.csv
This commit is contained in:
@@ -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`)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -133,6 +134,17 @@ def main():
|
||||
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
|
||||
|
||||
162
setup_host.py
162
setup_host.py
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user