import curses import json import os from git import Repo CONFIGS_DIR = "/tmp/oginstall" os.makedirs(CONFIGS_DIR, exist_ok=True) REPO_URL = "https://ognproject.evlt.uma.es/gitea/opengnsys/ogcore.git" def get_git_tags(): try: repo_path = os.path.join(CONFIGS_DIR, "opengnsys_repo") if not os.path.exists(repo_path): print("Clonando el repositorio...") Repo.clone_from(REPO_URL, repo_path) else: print("Usando repositorio existente en", repo_path) repo = Repo(repo_path) tags = [tag.name for tag in repo.tags] if tags: print("Tags encontrados:", tags) else: print("No se encontraron tags con el patrón especificado.") return tags except Exception as e: print("Error al obtener los tags:", str(e)) return [] def get_password(stdscr, y, x, prompt, default=""): stdscr.addstr(y, x, prompt, curses.color_pair(1)) password = "" masked_password = "" stdscr.move(y, x + len(prompt)) # Coloca el cursor después del prompt while True: key = stdscr.getch() if key in (curses.KEY_BACKSPACE, 127): # Maneja el retroceso if len(password) > 0: password = password[:-1] masked_password = "*" * len(password) stdscr.move(y, x + len(prompt)) # Mueve el cursor después del prompt stdscr.addstr(y, x + len(prompt), " " * (len(masked_password) + 1)) # Borra la línea stdscr.addstr(y, x + len(prompt), masked_password) # Vuelve a mostrar los asteriscos actualizados elif key == ord("\n"): # Confirmar con Enter if not password and default: # Si el usuario no ingresó nada, usa el valor predeterminado password = default break elif 32 <= key <= 126: # Rango de caracteres imprimibles password += chr(key) masked_password = "*" * len(password) stdscr.addstr(y, x + len(prompt), masked_password) # Muestra asteriscos return password def get_input(stdscr, y, x, prompt, default=""): max_y, max_x = stdscr.getmaxyx() if x + len(prompt) >= max_x: raise ValueError("El prompt es demasiado largo para caber en la pantalla.") stdscr.addstr(y, x, prompt, curses.color_pair(1)) input_text = "" prompt_end_x = x + len(prompt) # Calcula la posición final del prompt stdscr.move(y, prompt_end_x) # Coloca el cursor después del prompt while True: key = stdscr.getch() if key in (curses.KEY_BACKSPACE, 127): # Maneja el retroceso if len(input_text) > 0: input_text = input_text[:-1] stdscr.move(y, prompt_end_x) # Mueve el cursor después del prompt stdscr.clrtoeol() # Limpia la línea desde la posición actual hacia el final stdscr.addstr(y, prompt_end_x, input_text) # Vuelve a mostrar el texto actualizado stdscr.move(y, prompt_end_x + len(input_text)) elif key == ord("\n"): # Confirmar con Enter if not input_text and default: # Usa el valor predeterminado si está vacío input_text = default break elif 32 <= key <= 126: # Rango de caracteres imprimibles if prompt_end_x + len(input_text) < max_x - 1: input_text += chr(key) stdscr.addstr(y, prompt_end_x, input_text) # Muestra el texto actualizado stdscr.move(y, prompt_end_x + len(input_text)) # Mueve el cursor al final del texto return input_text def main(stdscr): # Inicializar colores curses.start_color() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) stdscr.bkgd(' ', curses.color_pair(1)) curses.curs_set(0) stdscr.clear() # Paso 1: Seleccionar componentes components = ["ogCore", "ogGui", "ogDhcp", "ogBoot", "ogRepository"] selected_components = [] current_index = 0 # Mostrar instrucciones y opciones de componentes stdscr.addstr(1, 2, "Selecciona los componentes (usa Flechas para navegar, Espacio para seleccionar, Enter para continuar):", curses.color_pair(1) | curses.A_BOLD) while True: for idx, comp in enumerate(components): if comp in selected_components: stdscr.addstr(idx + 3, 4, f"[X] {comp}", curses.color_pair(1)) else: stdscr.addstr(idx + 3, 4, f"[ ] {comp}", curses.color_pair(1)) stdscr.addstr(current_index + 3, 4, f"> {components[current_index]}", curses.color_pair(1)) key = stdscr.getch() if key == curses.KEY_UP and current_index > 0: current_index -= 1 elif key == curses.KEY_DOWN and current_index < len(components) - 1: current_index += 1 elif key == ord(" "): component = components[current_index] if component in selected_components: selected_components.remove(component) else: selected_components.append(component) elif key == ord("\n"): break stdscr.refresh() # Menu de selección de releases tags = get_git_tags() tag_index = 0 stdscr.clear() while True: for idx, tag in enumerate(tags): if idx == tag_index: stdscr.addstr(idx + 3, 4, f"> {tag}", curses.color_pair(1)) else: stdscr.addstr(idx + 3, 4, f" {tag}", curses.color_pair(1)) key = stdscr.getch() if key == curses.KEY_UP and tag_index > 0: tag_index -= 1 elif key == curses.KEY_DOWN and tag_index < len(tags) - 1: tag_index += 1 elif key == ord("\n"): break stdscr.refresh() # Configuración específica de cada componente seleccionado curses.echo() for component in selected_components: stdscr.clear() stdscr.addstr(1, 2, f"Configuración para {component}:", curses.color_pair(1) | curses.A_BOLD) curses.curs_set(1) config_data = {} if component == "ogCore": user = get_input(stdscr, 3, 0, "Usuario administrador (ogadmin): ", "ogadmin") password = get_password(stdscr, 4, 0, "Contraseña (por defecto '12345678'): ", "12345678") config_data = {"username": user, "password": password, "container_version": tags[tag_index]} elif component == "ogGui": ogcore_ip = get_input(stdscr, 3, 0, "URL Api OgCore (https://127.0.0.1:8443): " , "https://127.0.0.1:8443") config_data = {"ogcore_ip": ogcore_ip, "container_version": tags[tag_index]} elif component == "ogDhcp": ogbootIP = get_input(stdscr, 3, 0, "IP servidor de Boot (127.0.0.1): ", "127.0.0.1") ogdhcpIP = get_input(stdscr, 4, 0, "IP servidor de DHCP (127.0.0.1): ", "127.0.0.1") ogdhcpDir = get_input(stdscr, 5, 0, "Directorio de ogdhcp (/opt/opengnsys/ogdhcp): ", "/opt/opengnsys/ogdhcp") interfaces = get_input(stdscr, 6, 0, "Interfaces Boot (eth0,eth1): ", "eth0,eth1") json_array_interfaces = interfaces.split(",") config_data = {"ogbootIP": ogbootIP, "ogDhcpIP": ogdhcpIP , "ogDhcp_Dir" : ogdhcpDir , "interfaces": json_array_interfaces, "release": tags[tag_index]} elif component == "ogBoot": ogcore_ip = get_input(stdscr, 3, 0, "ogCore Ip Server: ", "") ogboot_server_ip = get_input(stdscr, 4, 0, "ogBoot Server IP: ", "") ogcore_dir = get_input(stdscr, 5, 0, "ogCore Dir (/opt/opengnsys/ogboot): ", "/opt/opengnsys/ogboot") ogLive_default = get_input(stdscr, 6, 0, "ogLive por defecto (ogLive-noble-6.8.0-31-generic-amd64-r20241128.62778c9_20241129): ", "ogLive-noble-6.8.0-31-generic-amd64-r20241128.62778c9_20241129") ogboot_samba_user = get_input(stdscr, 7, 0, "ogBoot Samba User (opengnsys): ", "opengnsys") ogboot_samba_pass = get_password(stdscr, 8, 0, "ogBoot Samba Pass (og): ", "og") config_data = { "ogCore_ServerIP": ogcore_ip, "ogBoot_ServerIP": ogboot_server_ip, "ogBoot_Dir": ogcore_dir, "ogLive_Default": "https://ognproject.evlt.uma.es/oglive/" + ogLive_default + ".iso", "ogBootSambaUser": ogboot_samba_user, "ogBootSambaPass": ogboot_samba_pass, "release": tags[tag_index] } elif component == "ogRepository": ogrepository_ip = get_input(stdscr, 3, 0, "ogRepository IP Server (127.0.0.1): ", "") ogrepository_samba_user = get_input(stdscr, 4, 0, "ogRepository Sambauser (opengnsys): ", "opengnsys") ogrepository_samba_pass = get_password(stdscr, 5, 0, "ogRepository Sambapass (og): ", "og") config_data = { "ogrepository_ip": ogrepository_ip, "ogrepository_samba_user": ogrepository_samba_user, "ogrepository_samba_pass": ogrepository_samba_pass, "release": tags[tag_index] } # Guardar en archivo JSON config_file = os.path.join(CONFIGS_DIR, f"config_{component}.json") with open(config_file, "w") as f: json.dump(config_data, f) stdscr.clear() stdscr.addstr(2, 2, f"Configuración de {component} guardada en {config_file}", curses.color_pair(1)) stdscr.refresh() stdscr.getch() curses.noecho() # Desactivar el eco después de la entrada curses.wrapper(main)