ogboot/installer/ogboot_installer.py

1015 lines
42 KiB
Python

#!/usr/bin/env python3
#################################################################################
##### ogBoot installer script ########
##### Autor: Antonio Emmanuel Guerrero Silva <aguerrero@qindel.com> ########
#################################################################################
import platform, os, sys, subprocess, datetime, shutil, argparse, time, pwd, glob
import subprocess
import os
import shutil
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 downloadComposer():
echoAndLog("Downloading composer.phar...")
os.makedirs(os.path.join(WORKDIR, "ogboot", "bin"), exist_ok=True)
# Download composer.phar to the destination directory
subprocess.run(["curl", "-sS", "-o", os.path.join(WORKDIR, "ogboot", "bin", "composer.phar"), "https://getcomposer.org/installer"], check=True)
# Check if the download was successful
if not os.path.isfile(os.path.join(WORKDIR, "ogboot", "bin", "composer.phar")):
errorAndLog("Failed to download composer.phar")
return 1
echoAndLog("composer.phar downloaded to /opt/ogboot/bin")
return 0
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")
downloadComposer() # Descargar composer.phar
# 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.")
source_files = glob.glob(f"{WORKDIR}/ogboot/client/shared/*")
# Copy each file individually
for file in source_files:
cp_process = subprocess.run(["cp", "-a", file, f"{INSTALL_TARGET}/client"])
if cp_process.returncode != 0:
errorAndLog(f"{copyClientFiles.__name__}(): error while copying client structure: {file}")
errstatus = 1
echoAndLog(f"{copyClientFiles.__name__}(): Copying OpenGnsys Cloning Engine files.")
os.makedirs(f"{INSTALL_TARGET}/client/lib/engine/bin", exist_ok=True)
engine_files = glob.glob(f"{WORKDIR}/ogboot/client/engine/*.lib*")
# Copiar cada archivo individualmente
for file in engine_files:
cp_engine_process = subprocess.run(["cp", "-a", file, f"{INSTALL_TARGET}/client/lib/engine/bin"])
if cp_engine_process.returncode != 0:
errorAndLog(f"{copyClientFiles.__name__}(): error while copying engine files: {file}")
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.")
CONSOLEURL = f"https://{SERVER_OPENGNSYS}/opengnsys"
with open(f"{WORKDIR}/ogboot/etc/ogAdmClient.cfg") as file:
content = file.read()
content = content.replace("SERVERIP", SERVER_OPENGNSYS)
content = content.replace("OPENGNSYSURL", CONSOLEURL)
with open(f"{INSTALL_TARGET}/client/etc/ogAdmClient-eth0.cfg", "w") as outfile:
outfile.write(content)
os.link(f"{INSTALL_TARGET}/client/etc/ogAdmClient-eth0.cfg", f"{INSTALL_TARGET}/client/etc/ogAdmClient.cfg")
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