#!/usr/bin/python3 import os import glob import stat import shutil import re import subprocess import ogGlobals from InventoryLib import ogIsEfiActive from DiskLib import ogGetEsp from FileSystemLib import ogMount, ogUnmount ## sets envvar and writes to /etc/environment def env_export (k, v): os.environ[k] = str (v) already_present = False with open ('/etc/environment', 'r') as env_fd: for line in env_fd: if re.search (f'^{k}=', line): already_present = True break if not already_present: with open ('/etc/environment', 'a') as env_fd: env_fd.write (f'{k}={v}\n') return v def loadenviron(): # Idioma por defecto. LANG = os.environ.get ('LANG', 'es_ES') env_export ('LANG', 'es_ES') # Directorios del proyecto OpenGnsys. OPENGNSYS = os.environ.get ('OPENGNSYS', '/opt/opengnsys') env_export ('OPENGNSYS', OPENGNSYS) OGBIN = env_export ('OGBIN', f'{OPENGNSYS}/bin') OGETC = env_export ('OGETC', f'{OPENGNSYS}/etc') OGLIB = env_export ('OGLIB', f'{OPENGNSYS}/lib') OGAPI = env_export ('OGAPI', f'{OGLIB}/engine/bin') OGPYFUNCS = env_export ('OGPYFUNCS', f'{OPENGNSYS}/functions') OGSCRIPTS = env_export ('OGSCRIPTS', f'{OPENGNSYS}/scripts') OGIMG = env_export ('OGIMG', f'{OPENGNSYS}/images') OGCAC = env_export ('OGCAC', f'{OPENGNSYS}/cache') OGLOG = env_export ('OGLOG', f'{OPENGNSYS}/log') # Exportar parámetros del kernel. with open ('/proc/cmdline', 'r') as fd: cmdline = fd.read() kvars = cmdline.split() for kvar in kvars: if '=' not in kvar: continue k, v = kvar.split ('=') env_export (k, v) OGSERVERIMAGES = os.environ.get ('OGSERVERIMAGES', '') if 'ROOTREPO' not in os.environ or not os.environ.get ('ROOTREPO'): env_export ('ROOTREPO', OGSERVERIMAGES) # Compatibilidad para usar proxy en clientes ogLive. http_proxy = os.environ.get ('http_proxy', '') ogproxy = os.environ.get ('ogproxy', '') if not http_proxy and ogproxy: env_export ('http_proxy', ogproxy) def write_profile(): ## si estos accesos a os.environ fallan, es porque loadenviron() no se ejecutó OGSCRIPTS = os.environ['OGSCRIPTS'] OGPYFUNCS = os.environ['OGPYFUNCS'] OGBIN = os.environ['OGBIN'] PYTHONPATH = os.environ['PYTHONPATH'] LANG = os.environ['LANG'] PATH = os.environ.get ('PATH', '') L = LANG[0:LANG.index('_')] with open ('/etc/profile.d/ogprofile.sh', 'w') as fd: fd.write (f''' (locale-gen {LANG} &>/dev/null &) export PATH={OGSCRIPTS}:{OGPYFUNCS}:{OGBIN}:{PATH}:/opt/oglive/rootfs/opt/drbl/sbin export PYTHONPATH={PYTHONPATH} sysctl -p &>/dev/null loadkeys {L} >/dev/null if [ ! -f /run/resolvconf/resolv.conf -a -n "$ogdns" ]; then mkdir -p /run/resolvconf echo "nameserver $ogdns" > /run/resolvconf/resolv.conf fi '''.strip() + '\n') def clean_esp(): ## BootLib.bootOs() makes a copy of grub.cfg in /boot/grub within the ESP ## clean it up if ogIsEfiActive(): esp = ogGetEsp() if esp: esp_disk, esp_par = esp.split() mntpt = ogMount (esp_disk, esp_par) os.unlink (f'{mntpt}/boot/grub/grub.cfg') ogUnmount (esp_disk, esp_par) def fileslinks(): print (ogGlobals.lang.MSG_MAKELINKS) # Shell BASH por defecto (para usar "runtest") if os.path.exists ('/bin/sh'): os.unlink ('/bin/sh') os.symlink ('/bin/bash', '/bin/sh') # Crear directorio de bloqueos ## for some reason we need try/catch even when using 'exist_ok=True' try: os.makedirs ('/var/lock', exist_ok=True) except FileExistsError: pass try: os.makedirs ('/run/lock', exist_ok=True) except FileExistsError: pass # Crear ficheros temporales. for f in [ogGlobals.OGLOGCOMMAND, ogGlobals.OGLOGCOMMAND + '.tmp', ogGlobals.OGLOGSESSION, '/tmp/menu.tmp']: open (f, 'w').close() os.chmod (f, 0o777) # Enlaces para Qt Embeded. # son cosas de QT4, ya no aplica # Autenticación con clave pública para SSH if os.path.exists ('/scripts/ssl/authorized_keys'): for f in glob.glob ('/scripts/ssl/*'): shutil.copy2 (f, '/root/.ssh/') def loadmodules(): print (ogGlobals.lang.MSG_LOADMODULES) # Módulo del ratón. subprocess.run (['modprobe', 'psmouse'], stderr=subprocess.DEVNULL) # Cargar módulos específicos del kernel del cliente. uname_r = os.uname()[2] for m in glob.glob (f'{ogGlobals.OGLIB}/modules/{uname_r}/*.ko'): subprocess.run (['insmod', m], capture_output=True) def metadevs(): print (ogGlobals.lang.MSG_DETECTLVMRAID) subprocess.run (['vgchange', '-ay'], capture_output=True) # Detectar metadispositivos LVM. subprocess.run (['dmraid', '-ay'], capture_output=True) # Detectar metadispositivos RAID. def mountrepo(): ## si estos accesos a os.environ fallan, es porque loadenviron() no se ejecutó ROOTREPO = os.environ['ROOTREPO'] ROOTSERVER = os.environ.get ('ROOTSERVER', '') ogactiveadmin = os.environ.get ('ogactiveadmin', '') ogprotocol = os.environ.get ('ogprotocol', '') ogstatus = os.environ.get ('ogstatus', '') SERVER = os.environ.get ('SERVER', '') if not ROOTREPO: ROOTREPO = ROOTSERVER # TODO Revisar proceso de arranque para no montar 2 veces el repositorio. if 'true' == ogactiveadmin: os.environ['boot'] = 'admin' # ATENCIÓN: siempre en modo "admin". subprocess.run (['umount', ogGlobals.OGIMG], stderr=subprocess.DEVNULL) if 'nfs' == ogprotocol: subprocess.run (['mount.nfs', f'{ROOTREPO}:{ogGlobals.OGIMG}', ogGlobals.OGIMG, '-o', 'rw,nolock']) elif 'smb' == ogprotocol: PASS = subprocess.run ('grep "^[ \t]*\\(export \\)\\?OPTIONS=" /scripts/ogfunctions 2>&1 | sed "s/\\(.*\\)pass=\\(\\w*\\)\\(.*\\)/\\2/"', shell=True, capture_output=True, text=True).stdout.strip() if not PASS: PASS = 'og' subprocess.run (['mount.cifs', f'//{ROOTREPO}/ogimages', ogGlobals.OGIMG, '-o', f'rw,serverino,acl,username=opengnsys,password={PASS}']) elif 'local' == ogprotocol: # TODO: hacer funcion dentro de este script que monte smb # Comprobamos que estatus sea online. if 'offline' == ogstatus or '' == SERVER: # Si estatus es offline buscamos un dispositivo con etiqueta repo # y si no existe montamos la cache como repo (si existe). TYPE = subprocess.run ('blkid | grep REPO | awk -F"TYPE=" \'{print $2}\' | tr -d \\"', shell=True, capture_output=True, text=True).stdout.strip() if '' == TYPE: cac_img = f'{ogGlobals.OGCAC}/{ogGlobals.OGIMG}' if os.path.isdir (cac_img): subprocess.run (['mount', '--bind', cac_img, ogGlobals.OGIMG]) else: subprocess.run (['mount', '-t', TYPE, 'LABEL=REPO', ogGlobals.OGIMG]) else: # Comprobamos que existe un servicio de samba. rc = subprocess.run (['smbclient', '-L', SERVER, '-N'], capture_output=True, text=True).returncode if not rc: ## success PASS = subprocess.run ('grep "^[ \t]*\\(export \\)\\?OPTIONS=" /scripts/ogfunctions 2>&1 | sed "s/\\(.*\\)pass=\\(\\w*\\)\\(.*\\)/\\2/"', shell=True, capture_output=True, text=True).stdout.strip() if not PASS: PASS = 'og' subprocess.run (['mount.cifs', f'//{ROOTREPO}/ogimages', ogGlobals.OGIMG, '-o', f'rw,serverino,acl,username=opengnsys,password={PASS}']) def poweroff(): ogntp = os.environ.get ('ogntp', '') status = os.environ.get ('status', '') print (ogGlobals.lang.MSG_POWEROFFCONF) # Sincronización horaria con servidor NTP. if ogntp and 'offline' != status: subprocess.run (['ntpdate', ogntp]) # Crear fichero de configuración por defecto (30 min. de espera). POWEROFFCONF = '/etc/poweroff.conf' with open (POWEROFFCONF, 'w') as fd: fd.write (f''' POWEROFFSLEEP=30 POWEROFFTIME= '''.strip() + '\n') # Incluir zona horaria en el fichero de configuración. awk_out = subprocess.run (['awk', 'BEGIN {RS=" "} /^TZ=/ {print}', '/proc/cmdline'], capture_output=True, text=True).stdout.strip() with open (POWEROFFCONF, 'a') as fd: fd.write (awk_out + '\n') # Lanzar el proceso "cron". subprocess.run (['cron', '-l']) # Definir la "crontab" lanzando el proceso de comprobación cada minuto. crontab_entry = f'* * * * * [ -x {ogGlobals.OGBIN}/poweroffconf ] && {ogGlobals.OGBIN}/poweroffconf\n' subprocess.run (['crontab', '-'], input=crontab_entry, text=True) def filebeat(): oglog = os.environ.get ('oglog', '') F = '/etc/filebeat/filebeat.yml' OPENSEARCH_PORT = '9200' if not os.path.exists (F): return PASS = subprocess.run ('grep "^[ \t]*\\(export \\)\\?OPTIONS=" /scripts/ogfunctions 2>&1 | sed "s/\\(.*\\)pass=\\(\\w*\\)\\(.*\\)/\\2/"', shell=True, capture_output=True, text=True).stdout.strip() ## taken from a sibling script if not PASS: PASS = 'og' ogkdf = subprocess.run (f'echo -n {PASS} |sha256sum |cut -c1-12', shell=True, capture_output=True, text=True).stdout.strip() PASS = 'OG+' + ogkdf os.chmod (F, 0o600) subprocess.run (['sed', '-i', '-e', f's/__OGLOG_IP/{oglog}/g', '-e', f's/__OGLOG_PORT__/{OPENSEARCH_PORT}/g', '-e', f's/__OPENSEARCH_PASSWORD__/{PASS}/g', F ]) os.makedirs ('/var/log/filebeat', exist_ok=True) subprocess.Popen (['/usr/bin/filebeat', '-c', F, '--path.home', '/usr/share/filebeat', '--path.config', '/etc/filebeat', '--path.data', '/var/lib/filebeat', '--path.logs', '/var/log/filebeat']) def stunnel(): ogcore = os.environ.get ('ogcore', '') ogusetls = os.environ.get ('ogusetls', '') ogverifytls = os.environ.get ('ogverifytls', '') with open ('/etc/stunnel/menu.conf', 'w') as fd: fd.write (f''' setuid = stunnel4 setgid = stunnel4 pid = /var/run/stunnel4/menu.pid foreground = yes debug = info [menu] client = yes accept = 127.0.0.1:81 connect = {ogcore}:8443 '''.strip() + '\n') if 'true' == ogusetls: if 'true' == ogverifytls: ## use tls and verify with open ('/etc/stunnel/menu.conf', 'a') as fd: fd.write (f''' cert = /opt/opengnsys/etc/ogagent.crt key = /opt/opengnsys/etc/ogagent.key CAfile = /opt/opengnsys/etc/ca.crt requireCert = yes verifyChain = yes '''.strip() + '\n') else: ## use tls but not verify with open ('/etc/stunnel/menu.conf', 'a') as fd: fd.write (f''' cert = /opt/opengnsys/etc/ogagent.crt key = /opt/opengnsys/etc/ogagent.key CAfile = /opt/opengnsys/etc/ca.crt requireCert = no verifyChain = no '''.strip() + '\n') else: ## don't use tls with open ('/etc/stunnel/menu.conf', 'a') as fd: fd.write (f''' requireCert = no verifyChain = no '''.strip() + '\n') os.makedirs ('/var/run/stunnel4', exist_ok=True) shutil.chown ('/var/run/stunnel4', 'stunnel4', 'stunnel4') with open ('/var/log/stunnel4/menu.log', 'a') as stunnel_log_fd: subprocess.Popen (['stunnel', '/etc/stunnel/menu.conf'], stdout=stunnel_log_fd, stderr=subprocess.STDOUT) def dbus(): if os.path.exists ('/etc/dbus-1/system.d/ogbrowser.conf'): os.makedirs ('/run/dbus', exist_ok=True) dbus_addr = subprocess.run (['dbus-daemon', '--print-address', '--system', '--nosyslog'], capture_output=True, text=True).stdout.strip() env_export ('DBUS_SESSION_BUS_ADDRESS', dbus_addr) with open ('/var/log/dbus-monitor.log', 'w') as dbus_mon_fd: subprocess.Popen (['dbus-monitor', '--system'], stdout=dbus_mon_fd, stderr=subprocess.STDOUT) def otherservices(): DEVICE = os.environ.get ('DEVICE', '') if ogIsEfiActive(): subprocess.run (['mount', '-t', 'efivarfs', 'none', '/sys/firmware/efi/efivars']) print (ogGlobals.lang.MSG_OTHERSERVICES) if os.path.exists ('/dev/log') and not stat.S_ISSOCK (os.stat ('/dev/log').st_mode): subprocess.run (['service', 'rsyslog', 'start']) # root password PASS = subprocess.run ('grep "^[ \t]*\\(export \\)\\?OPTIONS=" /scripts/ogfunctions 2>&1 | sed "s/\\(.*\\)pass=\\(\\w*\\)\\(.*\\)/\\2/"', shell=True, capture_output=True, text=True).stdout.strip() if not PASS: PASS = 'og' subprocess.run (['passwd', 'root'], input=f'{PASS}\n{PASS}\n', stderr=subprocess.DEVNULL, text=True) subprocess.run (['/etc/init.d/ssh', 'start'], capture_output=True, text=True) #setterm -blank 0 -powersave off -powerdown 0 < /dev/console > /dev/console 2>&1 ## apagado de monitor subprocess.run (['ethtool', '-s', DEVICE, 'wol', 'g'], stderr=subprocess.DEVNULL) ## Activado WOL en la interfaz usada en arranque PXE. def runhttplog(): ## si estos accesos a os.environ fallan, es porque loadenviron() no se ejecutó OPENGNSYS = os.environ['OPENGNSYS'] try: shutil.copy2 ('/etc/lighttpd/lighttpd.conf', '/etc/lighttpd/lighttpd.conf.back') shutil.copy2 ('/etc/lighttpd/conf-enabled/10-cgi.conf', '/etc/lighttpd/conf-enabled/10-cgi.conf.back') except FileNotFoundError: pass shutil.copy2 (f'{OPENGNSYS}/lib/httpd/lighttpd.conf', '/etc/lighttpd/') shutil.copy2 (f'{OPENGNSYS}/lib/httpd/10-cgi.conf', '/etc/lighttpd/conf-enabled/') subprocess.run (['/etc/init.d/lighttpd', 'start'], capture_output=True) o = OPENGNSYS while '/' != o: os.chmod (o, 0o755) o = os.path.dirname (o) os.makedirs ('/usr/lib/cgi-bin', exist_ok=True) for filename in os.listdir (f'{OPENGNSYS}/lib/httpd/'): full_file_name = os.path.join (f'{OPENGNSYS}/lib/httpd/', filename) if os.path.isfile (full_file_name): shutil.copy2 (full_file_name, '/usr/lib/cgi-bin') ## dstat fails because /var/lib/pcp/pmns/root does not exist. ## we work around that by starting/stopping pmcd once. When it starts, it creates the missing file. if not os.path.exists ('/var/lib/pcp/pmns/root'): subprocess.run (['/etc/init.d/pmcd', 'start'], capture_output=True) subprocess.run (['/etc/init.d/pmcd', 'stop'], capture_output=True) with open ('/tmp/bandwidth', 'w') as f: subprocess.Popen (['dstat', '-dn', '10'], stdout=f) with open (ogGlobals.OGLOGSESSION, 'a') as fd: fd.write ('WAITING\n')