ogclone-engine/ogclient/lib/python3/InitLib.py

353 lines
14 KiB
Python

#!/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')