Updted installer

select_mono_multi
Nicolas Arenas 2025-05-14 07:00:27 +02:00
parent 561232ee9f
commit 6983bba294
1 changed files with 66 additions and 55 deletions

View File

@ -95,6 +95,7 @@ def get_available_versions():
def get_default_ip():
"""Obtiene la IP asociada a la interfaz por defecto del servidor."""
logging.debug("Obteniendo la IP por defecto del servidor.")
try:
# Obtener la interfaz asociada a la ruta por defecto
result = subprocess.run(
@ -106,7 +107,9 @@ def get_default_ip():
# Extraer la interfaz de la salida
interface = next((line.split()[-1] for line in result.stdout.splitlines() if "dev" in line), None)
if not interface:
logging.error("No se pudo determinar la interfaz por defecto.")
raise ValueError("No se pudo determinar la interfaz por defecto.")
logging.debug(f"Interfaz por defecto: {interface}")
# Obtener la IP de la interfaz
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
@ -114,7 +117,7 @@ def get_default_ip():
ip_address = s.getsockname()[0]
return ip_address
except Exception as e:
print(f"Error al obtener la IP por defecto: {e}")
logging.error(f"Error al obtener la IP por defecto: {e}")
return "192.168.2.2" # Valor por defecto
def get_oglive_list():
@ -123,6 +126,7 @@ def get_oglive_list():
# Realizar la solicitud HTTP
response = requests.get("https://ognproject.evlt.uma.es/oglive/", timeout=10)
response.raise_for_status() # Lanza una excepción si la respuesta no es 200 OK
# Registrar el contenido de la respuesta para depuración
# Extraer los enlaces del contenido HTML
from bs4 import BeautifulSoup
@ -133,7 +137,7 @@ def get_oglive_list():
sorted_links = sorted(links, key=lambda x: x.split("_")[1] if "_" in x else x, reverse=True)
return sorted_links
except Exception as e:
print(f"Error al obtener la lista de oglives: {e}")
logging.error(f"Error al obtener la lista de oglives: {e}")
return [] # Devolver una lista vacía en caso de error
# Variable global para la IP por defecto
@ -151,17 +155,20 @@ class InstallationTypeForm(npyscreen.ActionForm):
def on_ok(self):
"""Guardar la selección y pasar al formulario correspondiente."""
logging.debug(f"Entrando en InstallationTypeForm")
if self.installation_type.value is None:
npyscreen.notify_confirm("Debes seleccionar un tipo de instalación.", title="Error")
return
if self.installation_type.value == [0]: # Mononodo
logging.debug("Instalación mononodo seleccionada.")
self.parentApp.installation_type = "mononodo"
self.parentApp.setNextForm("MONONODO_CONFIG")
elif self.installation_type.value == [1]: # Multinodo
logging.debug("Instalación multinodo seleccionada.")
self.parentApp.installation_type = "multinodo"
self.parentApp.setNextForm("MULTINODO_CONFIG")
def on_cancel(self):
"""Salir de la aplicación."""
if npyscreen.notify_yes_no("¿Estás seguro de que deseas salir?", title="Confirmación"):
@ -179,6 +186,7 @@ class MononodoConfigForm(npyscreen.ActionForm):
def on_ok(self):
"""Guardar la configuración y pasar al siguiente formulario."""
logging.debug(f"Entrando en MononodoConfigForm")
self.parentApp.server_ip = self.server_ip.value
self.parentApp.setNextForm("MAIN")
@ -707,22 +715,24 @@ class OgRepositoryForm(ComponentForm):
)
}
class InstallationProgressForm(npyscreen.FormBaseNew):
class InstallationProgressForm(npyscreen.Form):
"""Formulario para mostrar el progreso de instalación y el log en tiempo real."""
# Crear la parte superior para el progreso de instalación
def create(self):
# Usa tamaños fijos razonables que funcionen incluso en terminales pequeños
# Ajustar alturas para evitar problemas de espacio
self.progress_box = self.add(
npyscreen.BoxTitle,
name="Progreso de instalación",
max_height=10,
max_height=6,
rely=1,
relx=2,
scroll_exit=True
)
self.log_box = self.add(
npyscreen.BoxTitle,
name="Log de instalación",
max_height=10,
max_height=8,
rely=8,
relx=2,
scroll_exit=True
)
@ -748,67 +758,54 @@ class InstallationProgressForm(npyscreen.FormBaseNew):
def install_components_with_ui(form, components, selected_tag):
"""Instala los componentes seleccionados mostrando el progreso y el log en tiempo real."""
log_file_path = os.path.join(LOGS_DIR, "installation.log")
installed_packages = [] # Lista de paquetes instalados correctamente
failed_packages = [] # Lista de paquetes que fallaron
# Registrar el tiempo de inicio
installed_packages = []
failed_packages = []
start_time = time.time()
try:
# Abrir el archivo de log en modo sin buffer
with open(log_file_path, "w", buffering=1) as log_file: # Line-buffered mode
with open(log_file_path, "w", buffering=1) as log_file:
total_packages = len(components)
# Hilo para leer el log en tiempo real
def tail_log():
with open(log_file_path, "r") as log_reader:
log_reader.seek(0, os.SEEK_END) # Ir al final del archivo
while True:
line = log_reader.readline() # Leer una nueva línea
if line:
form.update_log(line) # Actualizar el log en la interfaz
#time.sleep(0.1) # Pequeña pausa para evitar uso excesivo de CPU
try:
with open(log_file_path, "r") as log_reader:
log_reader.seek(0, os.SEEK_END)
while True:
line = log_reader.readline()
if line:
form.update_log(line)
except Exception as e:
# Mostrar error en log si ocurre
try:
form.update_log(f"[ERROR] {e}")
except Exception:
pass
log_thread = threading.Thread(target=tail_log, daemon=True)
log_thread.start()
for index, package in enumerate(components, start=1):
# Actualizar el progreso en la parte superior con barra de progreso
form.update_progress(f"Instalando paquete {index}/{total_packages}: {package}", current=index, total=total_packages)
# Crear una barra de progreso para el paquete
install_command = f"DEBIAN_FRONTEND=noninteractive apt-get install -y {package}"
process = subprocess.Popen(
install_command, shell=True, text=True, stdout=log_file, stderr=log_file, bufsize=1 # Line-buffered
install_command, shell=True, text=True, stdout=log_file, stderr=log_file, bufsize=1
)
# Esperar a que el proceso de instalación termine
process.wait()
# Forzar el vaciado del buffer del archivo de log
log_file.flush()
# Registrar errores en el archivo de registro
if process.returncode != 0:
error_message = f"Error al instalar el paquete {package}. Consulta el archivo de registro: {log_file_path}"
form.update_progress(error_message)
failed_packages.append(package) # Agregar a la lista de fallos
failed_packages.append(package)
else:
form.update_progress(f"Paquete {package} instalado correctamente.")
installed_packages.append(package) # Agregar a la lista de éxitos
# Instalar ogclient si se está instalando ogboot
installed_packages.append(package)
if package == "ogboot":
form.update_progress("Instalando paquete adicional: ogclient")
install_command = "DEBIAN_FRONTEND=noninteractive apt-get install -y ogclient"
process = subprocess.Popen(
install_command, shell=True, text=True, stdout=log_file, stderr=log_file, bufsize=1 # Line-buffered
install_command, shell=True, text=True, stdout=log_file, stderr=log_file, bufsize=1
)
process.wait()
# Forzar el vaciado del buffer del archivo de log
log_file.flush()
if process.returncode != 0:
error_message = f"Error al instalar el paquete ogclient. Consulta el archivo de registro: {log_file_path}"
form.update_progress(error_message)
@ -817,14 +814,14 @@ def install_components_with_ui(form, components, selected_tag):
form.update_progress("Paquete ogclient instalado correctamente.")
installed_packages.append("ogclient")
except Exception as e:
form.update_progress(f"Error durante la instalación: {e}")
try:
form.update_progress(f"Error durante la instalación: {e}")
except Exception:
print(f"[ERROR] {e}")
failed_packages.append("Error general durante la instalación")
# Registrar el tiempo de finalización
end_time = time.time()
duration = end_time - start_time # Calcular la duración en segundos
# Generar el resumen
duration = end_time - start_time
summary = "\n--- Resumen de la instalación ---\n"
summary += f"Tiempo total de instalación: {duration:.2f} segundos\n"
summary += f"Paquetes instalados correctamente: {len(installed_packages)}\n"
@ -838,11 +835,16 @@ def install_components_with_ui(form, components, selected_tag):
summary += "\nTodos los paquetes se instalaron correctamente.\n"
summary += f"\nConsulta el archivo de registro para más detalles: {log_file_path}"
# Mostrar el resumen en una ventana emergente
npyscreen.notify_confirm(summary, title="Resumen de la instalación", wide=True)
# Mostrar el resumen y salir del formulario
try:
npyscreen.notify_confirm(summary, title="Resumen de la instalación", wide=True)
except Exception as e:
print(summary)
print(f"[ERROR] {e}")
# Mostrar el resumen en la parte superior (opcional, si quieres mantenerlo en el formulario)
form.update_progress(summary)
# Forzar la salida de la aplicación después del resumen
import sys
sys.exit(0)
class MyApp(npyscreen.NPSAppManaged):
def onStart(self):
@ -852,7 +854,7 @@ class MyApp(npyscreen.NPSAppManaged):
self.repo_ip = None # IP del servidor Repository
self.dhcp_ip = None # IP del servidor DHCP
self.core_ip = None # IP del servidor Core
self.boot_ip = None # IP del servidor Boot
self.boot_ip = None # IP del servidor Bootdpkg
self.selected_components = [] # Componentes seleccionados
self.selected_tag = None # Versión seleccionada
self.configurations = {} # Configuraciones de los componentes
@ -874,6 +876,7 @@ class MyApp(npyscreen.NPSAppManaged):
def generate_debconf(self):
# Comprobar si la clave pública ya existe
logging.debug("Entrando en generate_debconf")
key_path = "/etc/apt/trusted.gpg.d/opengnsys.gpg"
if os.path.exists(key_path):
# Silenciar este mensaje
@ -881,16 +884,19 @@ class MyApp(npyscreen.NPSAppManaged):
else:
# Añadir la clave pública
try:
logging.debug("Añadiendo la clave pública")
subprocess.run(
'curl -k -L https://ognproject.evlt.uma.es/debian-opengnsys/public.key | gpg --dearmour -o /etc/apt/trusted.gpg.d/opengnsys.gpg',
shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True
)
except subprocess.CalledProcessError:
# Silenciar errores
logging.error("Error al añadir la clave pública")
return
# Añadir el repositorio
try:
logging.debug("Añadiendo el repositorio")
selected_tag = self.selected_tag # Obtener el tag seleccionado
# Determinar el valor de repo_line según el argumento recibido
if len(sys.argv) > 1 and sys.argv[1].lower() == "devel":
@ -902,11 +908,13 @@ class MyApp(npyscreen.NPSAppManaged):
with open('/etc/apt/sources.list.d/opengnsys.list', 'w') as repo_file:
repo_file.write(repo_line + '\n')
except Exception:
# Silenciar errores
logging.error("Error al añadir el repositorio")
print("Error al añadir el repositorio")
return
# Crear el archivo de versión instalada
try:
logging.debug("Creando el archivo de versión instalada")
os.makedirs("/opt/opengnsys", exist_ok=True)
with open("/opt/opengnsys/release", "w") as release_file:
release_file.write(f"Versión instalada: {selected_tag}\n")
@ -915,6 +923,7 @@ class MyApp(npyscreen.NPSAppManaged):
# Actualizar los repositorios
try:
logging.debug("Actualizando los repositorios")
subprocess.run('apt-get update', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
except subprocess.CalledProcessError:
# Silenciar errores
@ -935,9 +944,11 @@ class MyApp(npyscreen.NPSAppManaged):
subprocess.run(
line, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
logging.debug(f"Configuraciones guardadas en: {output_file}")
except Exception:
# Silenciar errores
pass
logging.error(f"Error al guardar configuraciones en {output_file}")
print(f"Error al guardar configuraciones en {output_file}")
# Silenciar el mensaje de configuraciones guardadas
# print(f"\nConfiguraciones guardadas en: {output_file}")