353 lines
14 KiB
Python
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')
|