#!/usr/bin/env python3 ################################################################################# ##### ogBoot installer script ######## ##### Autor: Antonio Emmanuel Guerrero Silva ######## ################################################################################# import platform, os, sys, subprocess, datetime, shutil, argparse, time, pwd global UBUNTU_OS_VERSION, OPENGNGYS_VERSION, PYTHON_VERSION_LAST, PYTHON_VERSION, DEPENDENCIES2, INSTALL_OGBOOT_TARGET, WORK_DIR, LOG_FILE, CHECKPKG, INSTALLPKG, PATH, PROGRAM_DIR, OPENGNSYS_SERVER, UPDATEPKGLIST UPDATEPKGLIST = "" UBUNTU_OS_VERSION = "18" OPENGNGYS_VERSION = "1.2.0" PYTHON_VERSION = 3 PYTHON_VERSION_LAST = 0 INSTALL_TARGET="/opt/ogboot" INSTALL_OPENGNSYS_TARGET = "/opt/opengnsys" INSTALL_OGBOOT_TARGET = "/opt/ogboot" WORK_DIR = "/tmp/ogboot_installer" DEPENDENCIES2 = [] INSTALLPKG="" PROGRAM_DIR = os.path.dirname(os.path.realpath(sys.argv[0])) PROGRAM_NAME = os.path.basename(sys.argv[0]) OPENGNSYS_SERVER = "opengnsys.es" CHECKPKG="" DEFAULTDEV = "" DEVICE = [] SERVERIP = [] NETIP = [] NETMASK = [] NETBROAD = [] ROUTERIP = [] WORKDIR="/tmp/ogboot_installer" BRANCH = sys.argv[1] if len(sys.argv) > 1 else "main" TFTPSERV = "tftpd-hpa" # Define the TFTPSERV variable with the appropriate value GIT_REPO="ssh://git@ognproject.evlt.uma.es:21987/opengnsys/ogboot.git" #DOWNLOAD_URL = f"https://{OPENGNSYS_SERVER}/trac/downloads" if os.path.isdir(f"{PROGRAM_DIR}/../installer"): REMOTE = 0 else: REMOTE = 1 #CODE_URL = f"https://codeload.github.com/opengnsys/OpenGnsys/zip/{BRANCH}" #API_URL = "https://api.github.com/repos/opengnsys/OpenGnsys" PATH = os.environ.get("PATH", "") + f":{INSTALL_OGBOOT_TARGET}/bin" OG_LOG_FILE = f"{INSTALL_OGBOOT_TARGET}/log/{PROGRAM_NAME[:-3]}.log" LOG_FILE = f"/tmp/{os.path.basename(OG_LOG_FILE)}" if shutil.which("service"): STARTSERVICE = "service $service restart" STOPSERVICE = "service $service stop" else: STARTSERVICE = "/etc/init.d/$service restart" STOPSERVICE = "/etc/init.d/$service stop" #ENABLESERVICE = "update-rc.d $service defaults" #DISABLESERVICE = "update-rc.d $service disable" ENABLESERVICE = "systemctl enable $service.service" DISABLESERVICE = "systemctl disable $service.service" APACHESERV = "apache2" APACHECFGDIR = "/etc/apache2" APACHESITESDIR = "sites-available" APACHEOGSITE = "ogboot" APACHEUSER = "www-data" APACHEGROUP = "www-data" APACHEENABLEMODS = "a2enmod headers ssl rewrite proxy_fcgi fastcgi actions alias" APACHEENABLESSL = "a2ensite default-ssl" APACHEENABLEOG = f"a2ensite {APACHEOGSITE}" APACHEMAKECERT = "make-ssl-cert generate-default-snakeoil --force-overwrite" SAMBASERV = "smbd" SAMBACFGDIR = "/etc/samba" TFTPCFGDIR = "/var/lib/tftpboot" PHPFPMSERV = "php7.2-fpm" INETDCFGDIR = "/etc/xinetd.d/" INETDSERV = "xinetd" OPENGNSYS_CLIENT_PASSWD="og" OPENGNSYS_CLIENT_USER="opengnsys" required_packages_18 = [ "apache2", "arp-scan", "automake", "build-essential", "btrfs-progs", "composer", "curl", "ctorrent", "debootstrap", "g++-multilib", "gawk", "gettext", "graphviz", "grub-efi-amd64-signed", "isc-dhcp-server", "jq", "libapache2-mod-php", "libdbi-dev", "libdbi1", "libev-dev", "libjansson-dev", "liblz4-tool", "libssl-dev", "moreutils", "netpipes", "php", "php-bcmath", "php-cli", "php-curl", "php-fpm", "php-gd", "php-json", "php-ldap", "php-mbstring", "php-mysql", "php-pdo", "php-pear", "php-xml", "php-zip", "procps", "coreutils", "rsync", "samba", "schroot", "shim-signed", "squashfs-tools", "subversion", "tftp-hpa", "tftpd-hpa", "udpcast", "unzip", "wakeonlan", "wget", "xinetd" ] required_packages_22 = [ "apache2", "arp-scan", "automake", "build-essential", "btrfs-progs", "composer", "curl", "ctorrent", "debootstrap", "g++-multilib", "gawk", "gettext", "graphviz", "grub-efi-amd64-signed", "isc-dhcp-server", "jq", "libapache2-mod-php", "libdbi-dev", "libdbi1", "libev-dev", "libjansson-dev", "liblz4-tool", "libssl-dev", "moreutils", "netpipes", "php", "php-bcmath", "php-cli", "php-curl", "php-fpm", "php-gd", "php-json", "php-ldap", "php-mbstring", "php-mysql", "php-pdo", "php-pear", "php-xml", "php-zip", "procps", "coreutils", "rsync", "samba", "schroot", "shim-signed", "squashfs-tools", "subversion", "tftp-hpa", "tftpd-hpa", "udpcast", "unzip", "wakeonlan", "wget", "xinetd" ] ############################################################################### ###::::::::::::::::::::::::::::::: UTILS :::::::::::::::::::::::::::::::::::### ############################################################################### def echoAndLog(message): datetime_now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") #ssh_client = os.environ.get("SSH_CLIENT") log_file = LOG_FILE print(message) with open(log_file, "a") as file: file.write(f"{datetime_now}\t{message}\n") #file.write(f"{datetime_now}\t{ssh_client}\t{message}\n") def errorAndLog(message): datetime_now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") #client_address = socket.gethostbyname(socket.gethostname()) log_message = f"ERROR: {message}" #log_entry = f"{datetime_now};{client_address};{log_message}" log_entry = f"{datetime_now}\t{log_message}" with open(LOG_FILE, "a") as log_file: log_file.write(log_entry + "\n") print(log_message) def check_python_version(): try: # Obtener la versión de Python instalada python_version = platform.python_version() # Convertir la versión a una tupla para comparar fácilmente python_version_tuple = tuple(map(int, python_version.split('.'))) # Verificar si la versión es al menos PYTHON_VERSION.x if python_version_tuple >= (PYTHON_VERSION, 0): echoAndLog(f"LOG\tVersión de python instalada: {python_version}") PYTHON_VERSION_LAST = platform.python_version() else: echoAndLog(f"ERROR\tVersión de python es inferior a la requerida. Version instalada: {python_version}" + ".") exit() except Exception as e: echoAndLog(f"ERROR\tProblema al verificar la versión de Python: {e}") exit() def check_distribution(): if os.path.exists("/etc/os-release"): with open("/etc/os-release", "r") as file: for line in file: if line.startswith("VERSION"): VERSION = line.split("=")[1].strip().strip('"') break if VERSION.startswith(UBUNTU_OS_VERSION + "."): return print(f"La instalación de OpenGnsys {OPENGNGYS_VERSION} se ha probado con funcionalidad completa sobre Ubuntu {UBUNTU_OS_VERSION}") go_on = input("Desea continuar? [s/N]: ") if go_on.upper() != "S": print("Abandonando la instalación.") exit() def cidr2mask(cidr): # Number of args to shift, 255..255, first non-255 byte, zeroes args = [5 - (cidr // 8), 255, 255, 255, 255, (255 << (8 - (cidr % 8))) & 255, 0, 0, 0] if args[0] > 1: args = args[args[0]:] else: args = args[1:] return f"{args[0]}.{args[1]}.{args[2]}.{args[3]}" def downloadCode(url): if len(url) != 1: errorAndLog("downloadCode(): invalid number of parameters") exit(1) print(f"downloadCode(): downloading code from '{url}'...") subprocess.run(["GIT_SSH_COMMAND=ssh -o StrictHostKeyChecking=accept-new git archive --remote=" + url + " --format zip --output opengnsys.zip --prefix=opengnsys/ " + BRANCH + " && unzip opengnsys.zip"], shell=True) if subprocess.returncode != 0: errorAndLog("downloadCode(): error getting OpenGnsys code from " + url) return 1 subprocess.run(["rm -f opengnsys.zip"], shell=True) print("downloadCode(): code was downloaded") return 0 ############################################################################### ###:::::::::::::::::::::::::::::: INSTALL ::::::::::::::::::::::::::::::::::### ############################################################################### def is_installed(package): try: # Verifica si el paquete está instalado subprocess.run(["dpkg", "-s", package], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) return True except subprocess.CalledProcessError: return False def get_missing_packages(packages): faltantes = [] for package in packages: if not is_installed(package): faltantes.append(package) return faltantes def install_packages(missing, log_file="installed_packages.log"): if not missing: print("Todos los paquetes ya están instalados.") return print("Paquetes a instalar:", ", ".join(missing)) print("Actualizando el sistema...") subprocess.run(["sudo", "apt-get", "update"], check=True) with open(log_file, "a") as log: for package in missing: print(f"Instalando {package}") subprocess.run(["sudo", "apt-get", "install", "--force-yes", "-y", package], check=True) print(f"{package} instalado correctamente.") log.write(package + "\n") print("Todos los paquetes faltantes han sido instalados.") def autoConfigure(): # Detectar sistema operativo del servidor os_info = platform.uname() OSDISTRIB = os_info.system.lower() OSVERSION = os_info.release.split('.')[0] # Configuración según la distribución GNU/Linux if OSDISTRIB in ['linux', 'linux2']: if OSDISTRIB == 'linux': # Obtener información del sistema desde el archivo os-release with open('/etc/os-release', 'r') as f: os_release = dict(line.strip().split('=') for line in f) OSDISTRIB = os_release.get('ID', '').lower() OSVERSION = os_release.get('VERSION_ID', '').split('.')[0] else: # Obtener información del sistema utilizando el comando lsb_release lsb_info = subprocess.check_output(['lsb_release', '-is']).decode().strip() OSDISTRIB = lsb_info.lower() lsb_version = subprocess.check_output(['lsb_release', '-rs']).decode().strip() OSVERSION = lsb_version.split('.')[0] # Convertir distribución a minúsculas y obtener solo el 1er número de versión OSDISTRIB = OSDISTRIB.lower() OSVERSION = OSVERSION.split('.')[0] # Configuración según la distribución GNU/Linux (usar minúsculas) print (f"LOG\tDistribución de OS Linux: {OSDISTRIB}") if OSDISTRIB in ['ubuntu', 'debian', 'linuxmint']: #DEPENDENCIES = ['subversion', 'apache2', 'php', 'php-ldap', 'php-fpm', 'isc-dhcp-server', 'bittorrent', 'tftp-hpa', 'tftpd-hpa', 'xinetd', 'build-essential', 'g++-multilib', 'wget', 'curl', 'graphviz', 'bittornado', 'ctorrent', 'samba', 'rsync', 'unzip', 'netpipes', 'debootstrap', 'schroot', 'squashfs-tools', 'btrfs-tools', 'procps', 'arp-scan', 'realpath', 'php-curl', 'gettext', 'moreutils', 'jq', 'wakeonlan', 'udpcast', 'libev-dev', 'libjansson-dev', 'libssl-dev', 'shim-signed', 'grub-efi-amd64-signed', 'gawk', 'libdbi-dev', 'libdbi1', 'automake', 'liblz4-tool'] #DEPENDENCIESX = ["vi"] DEPENDENCIES2= [] #DEPENDENCIES2.append("htop") #DEPENDENCIES2.append("vi") #print (f"LOG\tDependencias identificadas: {DEPENDENCIES2}") #UPDATEPKGLIST = "apt-get update" # INSTALLPKG = "apt-get -y install --force-yes" # CHECKPKG = "dpkg -s $package 2>/dev/null | grep Status | grep -qw install" # STARTSERVICE = "service $service restart" if subprocess.call(['which', 'service'], stdout=subprocess.DEVNULL) == 0 else "/etc/init.d/$service restart" # STOPSERVICE = "service $service stop" if subprocess.call(['which', 'service'], stdout=subprocess.DEVNULL) == 0 else "/etc/init.d/$service stop" # APACHESERV = "apache2" # APACHECFGDIR = "/etc/apache2" # APACHESITESDIR = "sites-available" # APACHEOGSITE = "ogboot" # APACHEUSER = "www-data" # APACHEGROUP = "www-data" # APACHEENABLEMODS = "a2enmod ssl rewrite proxy_fcgi fastcgi actions alias" # APACHEENABLESSL = "a2ensite default-ssl" # APACHEENABLEOG = "a2ensite $APACHEOGSITE" # APACHEMAKECERT = "make-ssl-cert generate-default-snakeoil --force-overwrite" # DHCPSERV = "isc-dhcp-server" # DHCPCFGDIR = "/etc/dhcp" # INETDSERV = "xinetd" # INETDCFGDIR = "/etc/xinetd.d" # PHPFPMSERV = "php-fpm" # RSYNCSERV = "rsync" # RSYNCCFGDIR = "/etc" # SAMBASERV = "smbd" # SAMBACFGDIR = "/etc/samba" # TFTPCFGDIR = "/var/lib/tftpboot" elif OSDISTRIB in ['fedora', 'centos']: # DEPENDENCIES = ['subversion', 'httpd', 'mod_ssl', 'php-ldap', 'php-fpm', 'dhcp', 'tftp-server', 'tftp', 'xinetd', 'binutils', 'gcc', 'gcc-c++', 'glibc-devel', 'glibc-devel.i686', 'glibc-static', 'glibc-static.i686', 'libstdc++-devel.i686', 'make', 'wget', 'curl', 'doxygen', 'graphviz', 'ctorrent', 'samba', 'samba-client', 'rsync', 'unzip', 'debootstrap', 'schroot', 'squashfs-tools', 'python-crypto', 'arp-scan', 'procps-ng', 'gettext', 'moreutils', 'jq', 'net-tools', 'udpcast', 'libev-devel', 'jansson-devel', 'openssl-devel', 'shim-x64', 'grub2-efi-x64', 'grub2-efi-x64-modules', 'gawk', 'libdbi-devel', 'libdbi', 'http://ftp.altlinux.org/pub/distributions/ALTLinux/5.1/branch/$(arch)/RPMS.classic/netpipes-4.2-alt1.$(arch).rpm'] DEPENDENCIES2 = ['htop'] if OSDISTRIB == 'centos': UPDATEPKGLIST = f"yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-{OSVERSION}.noarch.rpm http://rpms.remirepo.net/enterprise/remi-release-{OSVERSION}.rpm" else: print("ERROR: Distribution not supported by OpenGnsys.") exit(1) else: print("ERROR: Unknown Linux distribution.") exit(1) def generate_config_url(): with open('/etc/os-release', 'r') as file: lines = file.readlines() codename = None version = None for line in lines: if line.startswith('VERSION_CODENAME') or line.startswith('UBUNTU_CODENAME'): codename = line.split('=')[1].strip().strip('"') elif line.startswith('VERSION_ID'): version = line.split('=')[1].strip().strip('"') arch = os.uname().machine return f"https://dl.cloudsmith.io/public/isc/kea-2-0/config.deb.txt?distro=ubuntu&codename={codename}&version={version}&arch={arch}" def create_ogboot_project(path_opengnsys_base): # Verificar si el usuario 'ogboot' ya existe try: pwd.getpwnam('ogboot') print("El usuario 'ogboot' ya existe") except KeyError: subprocess.run(["sudo", "useradd", "-m", "ogboot"]) # Verificar si el directorio ya existe if os.path.exists(path_opengnsys_base): if not os.path.isdir(path_opengnsys_base): raise NotADirectoryError(f"{path_opengnsys_base} existe y no es un directorio.") else: print(f"El directorio {path_opengnsys_base} ya existe.") else: os.makedirs(path_opengnsys_base) # Cambiar el propietario del directorio a 'ogboot' si se creó por primera vez subprocess.run(["sudo", "chown", "-R", "ogboot:ogboot", path_opengnsys_base]) # Verificar si la entrada "opengnsys" existe en /etc/hosts with open('/etc/hosts', 'r') as hosts_file: hosts_content = hosts_file.read() if 'opengnsys' not in hosts_content: # Agregar la entrada "opengnsys" con la IP SERVER_OPENGNSYS with open('/etc/hosts', 'a') as hosts_file: hosts_file.write('172.17.8.82 opengnsys\n') print("Entrada 'opengnsys' agregada a /etc/hosts") # Copiar los archivos .env y composer.json primero shutil.copy(f"{WORKDIR}/ogboot/.env", os.path.join(path_opengnsys_base, ".env")) shutil.copy(f"{WORKDIR}/ogboot/composer.json", os.path.join(path_opengnsys_base, "composer.json")) print(".env y composer.json copiados a", path_opengnsys_base) bin_source = os.path.join(WORKDIR, "ogboot/bin") bin_dest = os.path.join(path_opengnsys_base, "bin") src_source = os.path.join(WORKDIR, "ogboot/src") src_dest = os.path.join(path_opengnsys_base, "src") config_source = os.path.join(WORKDIR, "ogboot/config") config_dest = os.path.join(path_opengnsys_base, "config") if os.path.exists(bin_dest): shutil.rmtree(bin_dest) shutil.copytree(bin_source, bin_dest) if os.path.exists(src_dest): shutil.rmtree(src_dest) shutil.copytree(src_source, src_dest) if os.path.exists(config_dest): shutil.rmtree(config_dest) shutil.copytree(config_source, config_dest) subprocess.run(["sudo", "chmod", "-R", "755", path_opengnsys_base]) subprocess.run(["sudo", "chown", "-R", "ogboot:ogboot", path_opengnsys_base]) # Ejecutar Composer como el usuario 'ogboot' para instalar el proyecto Symfony result = subprocess.run(["sudo", "-u", "ogboot", "composer", "install", "--no-interaction", "--working-dir", path_opengnsys_base]) if result.returncode != 0: print("Error al crear el proyecto Symfony usando Composer") return os.chdir(path_opengnsys_base) # Eliminar composer.lock si existe composer_lock_path = os.path.join(path_opengnsys_base, "composer.lock") if os.path.exists(composer_lock_path): os.remove(composer_lock_path) print("Esqueleto de la aplicación creado y archivo composer.lock eliminado.") def createDirs(INSTALL_TARGET): if not os.path.exists(INSTALL_TARGET): try: os.makedirs(INSTALL_TARGET) os.makedirs(os.path.join(INSTALL_TARGET, "client")) # Create INSTALL_TARGET/client directory except OSError: errorAndLog("Error while creating directory paths!") exit(1) else: echoAndLog(f"Directory {INSTALL_TARGET} already exists.") ############################################################################### ###:::::::::::::::::::::::::::: CONFIGURE ::::::::::::::::::::::::::::::::::### ############################################################################### def install_isc_kea(): url = generate_config_url() print(f"URL generada: {url}") print("Ejecutando curl para obtener el archivo de configuración del repositorio KEA...") subprocess.run(["curl", "-1sLf", url, ">", "/etc/apt/sources.list.d/isc-kea-2-0.list"], check=True) print("El archivo de configuración del repositorio KEA ha sido guardado en /etc/apt/sources.list.d/isc-kea-2-0.list") print("Descargando y agregando la clave GPG del repositorio KEA...") subprocess.run(["curl", "-1sLf", "https://dl.cloudsmith.io/public/isc/kea-2-0/gpg.8029D4AFA58CBB5E.key", "|", "gpg", "--dearmor", ">>", "/usr/share/keyrings/isc-kea-2-0-archive-keyring.gpg"], check=True) print("La clave GPG del repositorio KEA ha sido descargada y agregada correctamente") print("Ejecutando apt-get update...") subprocess.run(["apt-get", "update"], check=True) print("Comprobando disponibilidad de los paquetes...") if subprocess.run(["apt-cache", "show", "isc-kea-common"], capture_output=True).returncode == 0: print("El paquete isc-kea-common está disponible para ser instalado.") print("Descargando e instalando el paquete isc-kea-common...") subprocess.run(["apt-get", "install", "-y", "isc-kea-common"], check=True) print("El paquete isc-kea-common ha sido descargado e instalado correctamente.") else: print("El paquete isc-kea-common no está disponible en los repositorios apt.") if subprocess.run(["apt-cache", "show", "isc-kea-dhcp4-server"], capture_output=True).returncode == 0: print("El paquete isc-kea-dhcp4-server está disponible para ser instalado.") print("Descargando e instalando el paquete isc-kea-dhcp4-server...") subprocess.run(["apt-get", "install", "-y", "isc-kea-dhcp4-server"], check=True) print("El paquete isc-kea-dhcp4-server ha sido descargado e instalado correctamente.") else: print("El paquete isc-kea-dhcp4-server no está disponible en los repositorios apt.") if subprocess.run(["apt-cache", "show", "isc-kea-dhcp6-server"], capture_output=True).returncode == 0: print("El paquete isc-kea-dhcp6-server está disponible para ser instalado.") print("Descargando e instalando el paquete isc-kea-dhcp6-server...") subprocess.run(["apt-get", "install", "-y", "isc-kea-dhcp6-server"], check=True) print("El paquete isc-kea-dhcp6-server ha sido descargado e instalado correctamente.") else: print("El paquete isc-kea-dhcp6-server no está disponible en los repositorios apt.") if subprocess.run(["apt-cache", "show", "isc-kea-dhcp-ddns-server"], capture_output=True).returncode == 0: print("El paquete isc-kea-dhcp-ddns-server está disponible para ser instalado.") print("Descargando e instalando el paquete isc-kea-dhcp-ddns-server...") subprocess.run(["apt-get", "install", "-y", "isc-kea-dhcp-ddns-server"], check=True) print("El paquete isc-kea-dhcp-ddns-server ha sido descargado e instalado correctamente.") else: print("El paquete isc-kea-dhcp-ddns-server no está disponible en los repositorios apt.") if subprocess.run(["apt-cache", "show", "isc-kea-ctrl-agent"], capture_output=True).returncode == 0: print("El paquete isc-kea-ctrl-agent está disponible para ser instalado.") print("Descargando e instalando el paquete isc-kea-ctrl-agent...") subprocess.run(["apt-get", "install", "-y", "isc-kea-ctrl-agent"], check=True) print("El paquete isc-kea-ctrl-agent ha sido descargado e instalado correctamente.") else: print("El paquete isc-kea-ctrl-agent no está disponible en los repositorios apt.") def install_kea(): print(f"{install_kea.__name__}(): Instalación de muestra para el servicio DHCP de Kea.") def backupFile(file): if not os.path.isfile(file): print(f"WARNING: file {file} doesn't exist") return print(f"Making backup of {file}") shutil.copy2(file, f"{file}-LAST") dateymd = datetime.datetime.now().strftime("%Y%m%d") backup_file = f"{file}-{dateymd}" if not os.path.isfile(backup_file): shutil.copy2(file, backup_file) print(f"Backup of {file} successful") def isc_keaDhcpConfigure(): print(f"{isc_keaDhcpConfigure.__name__}(): Configuración de muestra para el servicio DHCP de Kea.") errcode = 0 i = 0 interfaces = "[" #DEVICE = ["eth0", "eth1"] # Define the DEVICE variable with appropriate values #NETMASK = "255.255.255.0" # Replace with the actual value of NETMASK #NETIP = "192.168.0.1" # Replace with the actual value of NETIP #ROUTERIP = "192.168.0.1" # Replace with the actual value of ROUTERIP DNSIP = "192.168.0.1" # Replace with the actual value of DNSIP #SERVERIP = "192.168.0.1" # Replace with the actual value of SERVERIP # Rest of the code... # Define the NETMASK variable # Construir la lista de interfaces print(NETIP) print(NETMASK) #CIDR = mask2cidr(NETMASK) #print(CIDR) # Salida: 24 print(ROUTERIP) print(DNSIP) with open("/etc/kea/kea-dhcp4.conf", "w") as file: file.write( f""" "interfaces": {interfaces}, "SERVERIP": "{SERVERIP}", "NETIP": "{NETIP}", "NETMASK": "{NETMASK}", "ROUTERIP": "{ROUTERIP}", "DNSIP": "{DNSIP}" """ ) # Si hubo errores al configurar, muestra un mensaje de error y sale de la función if errcode != 0: print(f"{isc_keaDhcpConfigure.__name__}(): Error al configurar el servicio DHCP de Kea.") return 1 print(f"{isc_keaDhcpConfigure.__name__}(): Configuración de muestra para el servicio DHCP de Kea configurada en \"/etc/kea/kea-dhcp4.conf\".") return 0 def testPxe(): echoAndLog(f"{testPxe.__name__}(): Checking TFTP service... please wait.") subprocess.run(["echo", "test"], stdout=open(f"{TFTPCFGDIR}/testpxe", "w")) try: subprocess.run(["tftp", "-v", "127.0.0.1", "-c", "get", "testpxe", "/tmp/testpxe"], check=True) echoAndLog("TFTP service is OK.") except subprocess.CalledProcessError: errorAndLog("TFTP service is down.") os.remove(f"{TFTPCFGDIR}/testpxe") def tftpConfigure(): echoAndLog(f"{tftpConfigure.__name__}(): Configurando el servicio TFTP.") # Habilitar TFTP y reiniciar Inetd. if TFTPSERV: echoAndLog(f"TFTPSERV está configurado: {TFTPSERV}") inetd_cfg_path = f"{INETDCFGDIR}/{TFTPSERV}" if os.path.isfile(inetd_cfg_path): echoAndLog(f"El archivo de configuración de inetd existe: {inetd_cfg_path}") with open(inetd_cfg_path, "r+") as file: content = file.read() new_content = content.replace("disable.*", "disable = no") file.seek(0) file.write(new_content) file.truncate() echoAndLog(f"Archivo de configuración de inetd modificado: {inetd_cfg_path}") else: service = TFTPSERV echoAndLog(f"Habilitando y arrancando el servicio {service}.service") subprocess.run(["systemctl", "enable", f"{service}.service"], check=True) subprocess.run(["systemctl", "start", f"{service}.service"], check=True) service = INETDSERV echoAndLog(f"Habilitando y arrancando el servicio {service}.service") subprocess.run(["systemctl", "enable", f"{service}.service"], check=True) subprocess.run(["systemctl", "start", f"{service}.service"], check=True) symlink_target = f"{INSTALL_TARGET}/tftpboot" echoAndLog(f"Creando enlace simbólico de /var/lib/tftpboot a {symlink_target}") if not os.path.exists(symlink_target): os.symlink("/var/lib/tftpboot", symlink_target) else: echoAndLog(f"El enlace simbólico ya existe: {symlink_target}") # Comprobamos el servicio tftp # time.sleep(1) # testPxe() def servicesCompilation(): hayErrores = 0 # Compilar OpenGnsys Client echoAndLog(f"{servicesCompilation.__name__}(): Compiling OpenGnsys Admin Client") process = subprocess.run(["make"], cwd=f"{WORKDIR}/ogboot/sources/clients/ogAdmClient") subprocess.run(["mv", f"{WORKDIR}/ogboot/sources/clients/ogAdmClient/ogAdmClient", f"{WORKDIR}/ogboot/client/shared/bin"]) if process.returncode != 0: echoAndLog(f"{servicesCompilation.__name__}(): error while compiling OpenGnsys Admin Client") hayErrores = 1 return hayErrores # Copiar carpeta de Interface def copyInterfaceAdm(): hayErrores = 0 # Crear carpeta y copiar Interface echoAndLog(f"{copyInterfaceAdm.__name__}(): Copying Administration Interface Folder") cp_process = subprocess.run(["cp", "-ar", f"{WORKDIR}/ogboot/sources/interface", f"{INSTALL_TARGET}/client/interfaceAdm"]) if cp_process.returncode != 0: echoAndLog(f"{copyInterfaceAdm.__name__}(): error while copying Administration Interface Folder") hayErrores = 1 return hayErrores def copyClientFiles(): errstatus = 0 echoAndLog(f"{copyClientFiles.__name__}(): Copying OpenGnsys Client files.") cp_process = subprocess.run(["cp", "-a", f"{WORKDIR}/ogboot/client/shared/*", f"{INSTALL_TARGET}/client"]) if cp_process.returncode != 0: errorAndLog(f"{copyClientFiles.__name__}(): error while copying client structure") errstatus = 1 echoAndLog(f"{copyClientFiles.__name__}(): Copying OpenGnsys Cloning Engine files.") subprocess.run(["mkdir", "-p", f"{INSTALL_TARGET}/client/lib/engine/bin"]) cp_engine_process = subprocess.run(["cp", "-a", f"{WORKDIR}/ogboot/client/engine/*.lib*", f"{INSTALL_TARGET}/client/lib/engine/bin"]) if cp_engine_process.returncode != 0: errorAndLog(f"{copyClientFiles.__name__}(): error while copying engine files") errstatus = 1 if errstatus == 0: echoAndLog(f"{copyClientFiles.__name__}(): client copy files success.") else: errorAndLog(f"{copyClientFiles.__name__}(): client copy files with errors") return errstatus # Configuración básica de servicios de OpenGnsys def cidr2mask(bits): # Number of args to shift, 255..255, first non-255 byte, zeroes args = [5 - (bits // 8), 255, 255, 255, 255, (255 << (8 - (bits % 8))) & 255, 0, 0, 0] if args[0] > 1: args = args[args[0]:] else: args = args[1:] return ".".join(str(arg) for arg in args) def mask2cidr(mask): addr = mask.split(".") cidr = 0 for i in addr: cidr += bin(int(i)).count("1") return cidr # Obtener los parámetros de red de la interfaz por defecto. def getNetworkSettings(): DHCPNET = "127.0.0.1" # Arrays globales definidas: # - DEVICE: nombres de dispositivos de red activos. # - SERVERIP: IPs locales del servidor. # - NETIP: IPs de redes. # - NETMASK: máscaras de red. # - NETBROAD: IPs de difusión de redes. # - ROUTERIP: IPs de routers. # Otras variables globales: # - DEFAULTDEV: dispositivo de red por defecto. # - DNSIP: IP del servidor DNS principal. #DEVICE = [] print("getNetworkSettings(): Detecting network parameters.") output = subprocess.check_output(["ip", "-o", "link", "show", "up"]).decode("utf-8") lines = output.strip().split("\n") for line in lines: dev = line.split(":")[1].split("@")[0].strip() output = subprocess.check_output(["ip", "-o", "addr", "show", "dev", dev]).decode("utf-8") addr_lines = output.strip().split("\n") for addr_line in addr_lines: addr_parts = addr_line.split() cidr_netmask = addr_parts[3].split("/")[1] cidr_netmask = int(cidr_netmask) if cidr_netmask < 0 or cidr_netmask > 32: print("") else: #print("*** Interface:", dev) #print("*** IP Address", addr_parts[3].split("/")[0]) netmask = ".".join([str((0xffffffff << (32 - cidr_netmask) >> i) & 0xff) for i in [24, 16, 8, 0]]) #print("*** Netmask:", netmask) #print("*** Broadcast:", addr_parts[5]) #print("*** Router IP:", subprocess.check_output(["ip", "route", "list", "default"]).decode("utf-8").split()[2]) # Por aquí revisar lógica en caso de que haya una interfaz de red sin IP para que no reviente if addr_parts[2] == "inet": DEVICE.append(dev) SERVERIP.append(addr_parts[3].split("/")[0]) NETMASK.append(netmask) NETBROAD.append(addr_parts[5]) NETIP.append(addr_parts[3].split("/")[0]) ROUTERIP.append(subprocess.check_output(["ip", "route", "list", "default"]).decode("utf-8").split()[2]) #print ("====== SERVERIP_:", SERVERIP[-1]) #print ("====== SERVERIP:", SERVERIP[0]) #print ("====== NETIP:", NETIP[-1]) #print ("====== DHCPNET:", DHCPNET) if DHCPNET == NETIP[-1]: #print("DHCPNET:", NETIP[-1], "if yes") DEFAULTDEV = dev else: #print("DHCPNET:", NETIP[-1], "if no") DEFAULTDEV = DEFAULTDEV if "DEFAULTDEV" in locals() else dev # Habria que añadir logica para el caso en el que no este systemd-resolve para que a continuación busque en /etc/resolv.conf # output = subprocess.check_output(["systemd-resolve", "--status"]).decode("utf-8") # dns_servers = output.split("DNS Servers:")[1].split()[0] # DNSIP = dns_servers if dns_servers else open("/etc/resolv.conf").read().splitlines()[0].split()[1] #print ("NETIP:", NETIP) #print ("NETMASK:", NETMASK) num_elements = len(NETIP) #print("Number of elements in NETIP:", num_elements) if len(NETIP) == 0 or len(NETMASK) == 0: #print ("getNetworkSettings(): [ RETURN 1 ]Error: No network devices detected.") return 1 else: #print("getNetworkSettings(): [ RETURN 0 ]Default network device:", DEFAULTDEV) return 0 # Print variable names and values #print("DEVICE:", DEVICE) #print("SERVERIP:", SERVERIP) #print("NETIP:", NETIP) #print("NETMASK:", NETMASK) #print("NETBROAD:", NETBROAD) #print("ROUTERIP:", ROUTERIP) #print("DEFAULTDEV:", DEFAULTDEV) # print("DNSIP:", DNSIP) def openGnsysConfigure(): #DEVICE = [] #SERVERIP = [] #APACHE_RUN_USER = "" #APACHE_RUN_GROUP = "" #OPENGNSYS_CONSOLEURL = "" i = 0 dev = "" CONSOLEURL = "" # Mientras networkConfigure no funcione, utilizar una variable global que apunte al servidor Opengnsys # Para nuetra demo 172.17.8.82 print(f"{openGnsysConfigure.__name__}(): Creating OpenGnsys config files.") for dev in DEVICE: if dev: if SERVERIP[i]: CONSOLEURL = f"https://{SERVERIP[i]}/opengnsys" with open(f"{WORKDIR}/opengnsys/admin/Sources/Clients/ogAdmClient/ogAdmClient.cfg") as file: content = file.read() content = content.replace("SERVERIP", SERVERIP[i]) content = content.replace("OPENGNSYSURL", CONSOLEURL.replace("/", "\\/")) with open(f"{INSTALL_TARGET}/client/etc/ogAdmClient-{dev}.cfg", "w") as outfile: outfile.write(content) if dev == DEFAULTDEV: OPENGNSYS_CONSOLEURL = CONSOLEURL i += 1 if DEFAULTDEV: os.link(f"{INSTALL_TARGET}/client/etc/ogAdmClient-{DEFAULTDEV}.cfg", f"{INSTALL_TARGET}/client/etc/ogAdmClient.cfg") else: print("Error: No se ha detectado la interfaz de red por defecto.") exit(1) TZ = subprocess.check_output(["timedatectl", "status"]).decode().split("\n")[2].split(":")[1].strip() with open(f"{INSTALL_TARGET}/client/etc/engine.cfg", "a") as file: file.write(f"# OpenGnsys Server timezone.\nTZ=\"{TZ.replace(' ', '')}\"\n") print(f"{openGnsysConfigure.__name__}(): OpenGnsys config files created.") def mount_NFS(): if subprocess.call(["sudo", "mount", "-t", "nfs", "ognartefactos.evlt.uma.es:/", "/mnt"]) == 0: print("Sistema NFS montado correctamente.") else: print("Error: No se pudo montar el sistema NFS.") exit(1) subprocess.call(["ls", "/mnt/"]) subprocess.call(["sudo", "cp", "-r", "/mnt/srv/artefactos/ipxe/", "/tmp"]) os.chdir("/tmp/ipxe/src") if subprocess.call(["sudo", "make", "-j", "4"]) == 0: print("Directorio /tmp/ipxe/src montado correctamente.") else: print("Error: No se pudo montar el directorio /tmp/ipxe/src.") exit(1) if subprocess.call(["sudo", "make", "bin/undionly.kpxe", "EMBED=/opt/opengnsys/tftpboot/ipxe_scripts/dhcp_boot.ipxe"]) == 0: print("Fichero de arranque montado correctamente.") else: print("Error: No se pudo montar el fichero de arranque.") exit(1) subprocess.call(["sudo", "cp", "bin/undionly.kpxe", "/opt/opengnsys/tftpboot"]) if subprocess.call(["sudo", "make", "bin-x86_64-efi/ipxe.efi", "EMBED=/opt/opengnsys/tftpboot/ipxe_scripts/dhcp_boot.ipxe"]) == 0: print("Fichero EFI construido correctamente.") else: print("Error: No se pudo construir el fichero EFI.") exit(1) subprocess.call(["sudo", "cp", "bin-x86_64-efi/ipxe.efi", "/opt/opengnsys/tftpboot"]) def generate_ipxe_script(): print("Generando script IPXE...") ip_address_server = subprocess.check_output(["ifconfig", "eth0"]).decode().split("\n")[1].split()[1] template = os.path.join(WORKDIR, "ogboot/etc/dhcp_boot.ipxe.tmpl") ipxe_output = "/opt/ogboot/tftpboot/ipxe_scripts/dhcp_boot.ipxe" os.makedirs(os.path.dirname(ipxe_output), exist_ok=True) shutil.copy(template, ipxe_output) with open(ipxe_output, "r") as ipxe_file: ipxe_content = ipxe_file.read() ipxe_content = ipxe_content.replace("__SERVERIP__", ip_address_server) with open(ipxe_output, "w") as ipxe_file: ipxe_file.write(ipxe_content) #################33 # Reemplazar SERVERIP con la dirección IP en la plantilla y guardarla en el archivo de salida # with open(template, "r") as tmpl_file: # template_content = tmpl_file.read() # ipxe_content = template_content.replace("SERVERIP", ip_address_server) # with open(ipxe_output, "w") as ipxe_file: # ipxe_file.write(ipxe_content) template_default = "ogboot/tftpboot/ipxe_scripts/default.ipxe" default_output = "/opt/ogboot/tftpboot/ipxe_scripts/default.ipxe" with open(template_default, "r") as default_tmpl_file: default_template_content = default_tmpl_file.read() default_ipxe_content = default_template_content.replace("__SERVERIP__", ip_address_server) with open(default_output, "w") as default_ipxe_file: default_ipxe_file.write(default_ipxe_content) print("Archivos creados correctamente.") def smbConfigure(): echoAndLog(f"{smbConfigure.__name__}(): Configuring Samba service.") backupFile(f"{SAMBACFGDIR}/smb.conf") # Copiar plantilla de recursos para OpenGnsys with open(os.path.join(WORKDIR, 'ogboot/etc/smb-ogboot.conf.tmpl'), 'r') as tmpl_file: template = tmpl_file.read() replaced_template = template.replace('OGBOOTDIR', INSTALL_OPENGNSYS_TARGET) with open(os.path.join(SAMBACFGDIR, 'smb-ogboot.conf'), 'w') as conf_file: conf_file.write(replaced_template) # Configurar y recargar Samba" subprocess.run(["perl", "-pi", "-e", "s/WORKGROUP/OPENGNSYS/; s/server string \=.*/server string \= ogBoot Samba Server/", f"{SAMBACFGDIR}/smb.conf"]) if "smb-ogboot" not in open(f"{SAMBACFGDIR}/smb.conf").read(): with open(f"{SAMBACFGDIR}/smb.conf", "a") as file: file.write(f"include = {SAMBACFGDIR}/smb-ogboot.conf\n") service = SAMBASERV subprocess.run(["systemctl", "enable", f"{service}.service"]) subprocess.run(["systemctl", "start", f"{service}.service"]) # Comprobar si se ha configurado correctamente Samba if subprocess.run(["systemctl", "is-active", f"{service}.service"]).returncode == 0: print(f"{service} service started successfully.") else: errorAndLog(f"Failed to start {service} service.") return 1 # Establecer la contraseña para el usuario opengnsys smbpasswd_command = f"(echo {OPENGNSYS_CLIENT_PASSWD}; echo {OPENGNSYS_CLIENT_PASSWD}) | sudo smbpasswd -s -a {OPENGNSYS_CLIENT_USER}" if "Python 3.7" in {PYTHON_VERSION}: result = subprocess.run(smbpasswd_command, shell=True, capture_output=True, text=True) if result.returncode == 0: print(f"La contraseña para el usuario {OPENGNSYS_CLIENT_USER} se ha establecido correctamente.") else: print(f"Error al establecer la contraseña: {result.stderr}") else: print(f"python_version --({PYTHON_VERSION})--") #process = subprocess.Popen(smbpasswd_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) process = subprocess.Popen(smbpasswd_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode == 0: print(f"La contraseña para el usuario {OPENGNSYS_CLIENT_USER} se ha establecido correctamente.") else: print(f"Error al establecer la contraseña: {stderr}") echoAndLog(f"{smbConfigure.__name__}(): Added Samba configuration.") return 0 ############################################################################### ###:::::::::::::::::::::::::::::::: MAIN :::::::::::::::::::::::::::::::::::### ############################################################################### if os.geteuid() != 0: print("ERROR: este programa debe ejecutarse con privilegios de root.") exit(1) if os.path.exists(os.path.join(INSTALL_OGBOOT_TARGET + "/doc/")): echoAndLog(f"ERROR\togBoot ya esta instalado. Ejecute {INSTALL_OGBOOT_TARGET}/lib/ogboot_devel_update.py\" con privilegios de root para actualizar.") exit(2) check_distribution() check_python_version() autoConfigure() Missing = get_missing_packages (required_packages_18) install_packages(Missing) SERVER_OPENGNSYS = "172.17.8.82" # Verificar si la entrada "opengnsys" existe en /etc/hosts with open('/etc/hosts', 'r') as hosts_file: hosts_content = hosts_file.read() if f'{SERVER_OPENGNSYS} opengnsys' not in hosts_content: with open('/etc/hosts', 'a') as hosts_file: hosts_file.write(f'{SERVER_OPENGNSYS} opengnsys\n') print("Entrada 'opengnsys' agregada a /etc/hosts") else: print(f"La entrada '{SERVER_OPENGNSYS} opengnsys' ya existe en /etc/hosts" ) # Detectar parámetros de red y comprobar si hay conexión. if getNetworkSettings() != 0: errorAndLog("Error reading default network settings.") exit(1) if REMOTE == 1: downloadCode(GIT_REPO) if os.system("echo $?") != 0: errorAndLog("Error while getting code from the repository") exit(1) else: # WAR: Crea un link recursivo en el ogboot if not os.path.exists("ogboot"): os.symlink(os.path.dirname(PROGRAM_DIR), "ogboot") createDirs(INSTALL_TARGET) if os.system("echo $?") != 0: errorAndLog("Error while creating directory paths!") exit(1) create_ogboot_project(INSTALL_TARGET) if os.system("echo $?") != 0: errorAndLog("Error while creating skeleton directory!") exit(1) # Configuración de TFTP. tftpConfigure() # Compilar código fuente de los servicios de OpenGnsys. servicesCompilation() if subprocess.run(["echo", "$?"]).returncode != 0: errorAndLog("Error while compiling OpenGnsys services") exit(1) # Copiar carpeta Interface entre administración y motor de clonación. copyInterfaceAdm() if subprocess.run(["echo", "$?"]).returncode != 0: errorAndLog("Error while copying Administration Interface") exit(1) # Crear la estructura de los accesos al servidor desde el cliente (shared) copyClientFiles() if subprocess.run(["echo", "$?"]).returncode != 0: errorAndLog("Error creating client structure") generate_ipxe_script() openGnsysConfigure() # Montar sistema NFS. mount_NFS() # Configuración de Samba. smbConfigure() if subprocess.run(["echo", "$?"]).returncode != 0: errorAndLog("Error while configuring Samba server!") exit(1) ############################################################################### ###:::::::::::::::::::::::::::::::: DHCP :::::::::::::::::::::::::::::::::::### ############################################################################### # parser = argparse.ArgumentParser(description='Instalación de ogBoot', formatter_class=argparse.RawTextHelpFormatter) # help_text_dhcp = """ # install\t\tInstala la versión de DHCP seleccionada con dhcp-version, # configure\tConfigura dhcp sobre un servicio previamente instalado, # none\t\tNo instala ni configura DHCP # """ # help_text_dhcp_version = """ # isc\t\tInstala la versión de DHCP isc-kea-dhcp, para Ubuntu 18.04 # kea\t\tInstala la versión de DHCP kea-dhcp, para Ubuntu 20.04 # none\t\tNo instala ni configura DHCP # """ # parser.add_argument('--dhcp', choices=['install', 'configure', 'none'], default='none', help=help_text_dhcp) # parser.add_argument('--dhcp-version', choices=['isc', 'kea', 'none'], default='none', help=help_text_dhcp_version) # args = parser.parse_args() # if args.dhcp == 'install': # if args.dhcp_version == 'isc': # print("Instalando isc-kea-dhcp") # install_isc_kea() # isc_keaDhcpConfigure() # pass # elif args.dhcp_version == 'kea': # print("Instalando kea-dhcp") # install_kea() # pass # elif args.dhcp_version == 'none': # print("No se ha seleccionado ninguna versión de DHCP, utilice --dhcp-version para seleccionar una versión") # pass # pass # elif args.dhcp == 'configure': # print("Configurando DHCP") # if args.dhcp_version == 'isc': # isc_keaDhcpConfigure() # pass # elif args.dhcp_version == 'kea': # print("Configurando kea-dhcp") # #keaDhcpConfigure() # pass # elif args.dhcp_version == 'none': # print("No se ha seleccionado ninguna versión de DHCP, utilice --dhcp-version para seleccionar una versión") # pass # pass # elif args.dhcp == 'none': # print("DHCP no será instalado ni configurado") # pass