Compare commits

...

26 Commits
ogkdf ... main

Author SHA1 Message Date
Natalia Serrano c33c9ec1af Merge pull request 'refs #2468 add python init scripts' (#91) from pyinit into main
Reviewed-on: #91
2025-07-16 13:26:06 +02:00
Natalia Serrano 6617bace74 refs #2468 add python init scripts 2025-07-16 13:23:12 +02:00
Natalia Serrano a560380b81 Merge pull request 'refs #2464 change sort order' (#90) from getalldisks-sort into main
Reviewed-on: #90
2025-07-14 17:13:39 +02:00
Natalia Serrano acaf67f486 refs #2464 change sort order 2025-07-14 17:13:17 +02:00
Natalia Serrano 5cf92d6367 Merge pull request 'particionador' (#89) from particionador into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #89
2025-07-14 13:24:59 +02:00
Natalia Serrano c2d04ca39f refs #2432 remove unused function and debug stmts 2025-07-14 13:23:03 +02:00
Natalia Serrano 4432b60326 refs #2450 support two disks 2025-07-14 13:18:40 +02:00
Natalia Serrano 87b566532c refs #2415 check that 1st partition is the ESP in EFI systems 2025-07-14 13:18:40 +02:00
Natalia Serrano c5db321d93 refs #2461 remove dangling symlinks 2025-07-14 13:18:40 +02:00
Natalia Serrano 3d692f54a5 refs #2414 add a missing partition type 2025-07-14 13:18:40 +02:00
Natalia Serrano e529768257 refs #2414 add some more checks 2025-07-14 13:18:40 +02:00
Natalia Serrano 8029d469a7 refs #2414 improve some error messages, create a windows logical partition rather than an empty one 2025-07-14 13:18:40 +02:00
Natalia Serrano 73721d70f7 refs #2414 make initCache.py output more silent 2025-07-14 13:18:40 +02:00
Natalia Serrano 83c1c7763a refs #2414 do not fail when only the cache partition is requested 2025-07-14 13:18:40 +02:00
Natalia Serrano 9e7fda8944 refs #2414 fail early when requested some wrong scenarios 2025-07-14 13:18:40 +02:00
Natalia Serrano df36d74d7c refs #2441 remove "sgdisk" call in ogCreateCache 2025-07-14 13:18:40 +02:00
Natalia Serrano 38be98d9f1 refs #2436 add new function to obtain disk I/O size 2025-07-14 13:18:40 +02:00
Natalia Serrano 36a8277aab refs #2412 merge ogCreatePartitions and ogCreateGptPartitions into a single function 2025-07-14 13:18:40 +02:00
Natalia Serrano cf5ec4c214 refs #2412 fix two more bugs with extended/logical partitions 2025-07-14 13:18:40 +02:00
Natalia Serrano 0d28787318 refs #2412 fix bug with extended/logical partitions, remove useless variable, add some comments 2025-07-14 13:18:40 +02:00
Natalia Serrano 9cad17e4f4 refs #2412 check partition sizes before touching the disk 2025-07-14 13:18:40 +02:00
Natalia Serrano a7f4d767f5 refs #2412 add and improve error messages 2025-07-14 13:18:40 +02:00
Natalia Serrano 588ed96098 refs #2412 rename variables, add a couple of log messages, move a check 2025-07-14 13:18:38 +02:00
Natalia Serrano 87adfeda1c Merge pull request 'refs #2456 fix invocation of script' (#88) from fix-initCache into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #88
2025-07-14 11:15:05 +02:00
Natalia Serrano 6e806424cc refs #2456 fix invocation of script 2025-07-14 11:13:41 +02:00
Natalia Serrano 334f961e4c Merge pull request 'refs #2448 derive a strong password from the default opengnsys weak one' (#87) from ogkdf into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #87
2025-07-11 14:07:39 +02:00
20 changed files with 886 additions and 360 deletions

View File

@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.27.0] - 2025-07-16
### Added
- Add python init scripts
## [0.26.1] - 2025-07-14
### Changed
- Change sort order in `_getAllDisks()`
## [0.26.0] - 2025-07-14
### Fixed
- Overhaul partitioning
## [0.25.2] - 2025-07-14
### Fixed
- Run initCache.py rather than just initCache
## [0.25.1] - 2025-07-11
### Changed

View File

@ -0,0 +1,49 @@
#!/usr/bin/python3
# Proceso general de arranque de OpenGnsys Client.
import os
import re
import subprocess
import ogGlobals
from NetLib import ogGetIpAddress
ogstatus = os.environ.get ('ogstatus', '')
ogcore = os.environ.get ('ogcore', '')
oglog = os.environ.get ('oglog', '')
oggroup = os.environ.get ('OGGROUP', '')
ogactiveadmin = os.environ.get ('ogactiveadmin', '')
LANG = os.environ.get ('LANG', 'es_ES')
LANG = LANG[0:LANG.index('_')]
LOGLEVEL=5
# Matando plymount para inicir browser o shell
subprocess.run (['pkill', '-9', 'plymouthd'])
# Arranque de OpenGnsys Client daemon (socket).
print (ogGlobals.lang.MSG_LAUNCHCLIENT)
# Indicar fichero de teclado de Qt para el idioma especificado (tipo "es.qmap").
if os.path.exists (f'/usr/local/etc/{LANG}.qmap'):
os.environ['QWS_KEYBOARD'] = f'TTY:keymap=/usr/local/etc/{LANG}.qmap'
if os.path.exists ('/usr/share/OGAgent/opengnsys/linux/OGAgentService.py') and ogstatus != 'offline':
os.chdir ('/usr/share/OGAgent')
os.environ['OGAGENTCFG_OGCORE_IP'] = ogcore
os.environ['OGAGENTCFG_OGLOG_IP'] = oglog
os.environ['OGAGENTCFG_URLMENU_SCHEME'] = 'http'
os.environ['OGAGENTCFG_URLMENU_IP'] = '127.0.0.1'
os.environ['OGAGENTCFG_URLMENU_PORT'] = '81'
subprocess.run (['python3', '-m', 'opengnsys.linux.OGAgentService', 'fg'])
else:
ip = ogGetIpAddress()
OGMENU = ''
for FILE in [index, oggroup, ip]:
if not FILE: continue
m = f'{ogGlobals.OGCAC}/menus/{FILE}.html'
if os.path.exists (m): OGMENU = m
subprocess.run ([f'{ogGlobals.OPENGNSYS}/bin/launch_browser', m])
# Si fallo en cliente y modo "admin", cargar shell; si no, salir.
if ogactiveadmin == 'true':
subprocess.run (['bash'])

View File

@ -0,0 +1,43 @@
#!/usr/bin/python3
## early init
import os
import sys
OPENGNSYS = os.environ.get ('OPENGNSYS', '/opt/opengnsys')
os.environ['PYTHONPATH'] = f'{OPENGNSYS}/lib/python3'
sys.path.insert (0, os.environ['PYTHONPATH'])
## end
import subprocess
import ogGlobals
from InitLib import loadenviron, write_profile, clean_esp, fileslinks, loadmodules, metadevs, mountrepo, poweroff, filebeat, stunnel, dbus, otherservices, runhttplog
IPV4ADDR = os.environ.get ('IPV4ADDR', '')
OG_IP = os.environ.get ('OG_IP', '')
loadenviron()
write_profile()
# Funciones de inicio.
clean_esp()
fileslinks()
loadmodules()
metadevs()
mountrepo()
poweroff()
filebeat()
stunnel()
dbus()
otherservices()
runhttplog()
if IPV4ADDR and os.path.exists (f'{ogGlobals.OGETC}/init/{IPV4ADDR}.sh'):
if OG_IP: subprocess.run ([f'{ogGlobals.OGETC}/init/{OG_IP}.sh'])
elif os.path.exists (f'{ogGlobals.OGETC}/init.py'):
subprocess.run ([f'{ogGlobals.OGETC}/init.py'])
else:
print ('No se ha encontrado script de inicio')
subprocess.run (['halt'])

View File

@ -1,5 +1,12 @@
#!/bin/bash
if grep -q pyinit=true /proc/cmdline; then
echo "python init"
exec /opt/opengnsys/etc/preinit/default.py
else
echo "shell init"
fi
# Cargar entorno de OpenGnsys
set -a
source /opt/opengnsys/etc/preinit/loadenviron.sh

View File

@ -2,7 +2,6 @@
import os
import sys
import subprocess
import ogGlobals
import SystemLib
@ -34,12 +33,12 @@ prog = os.path.basename(__name__)
#
# El parámetro $2 es el que aporta toda la información y el $1 se queda obsoleto
# Formato de entrada:
# dis=Número de disco
# != caracter de separación
# dis=Número de disco
# != caracter de separación
#
# Y un numero indeterminado de cadenas del tipo siguuenteseparadas por el caracter '$':
# par=Número de particion*cod=Código de partición*sfi=Sistema de ficheros*tam=Tamaño de la partición*ope=Operación
# @= caracter de separación
# par=Número de particion*cod=Código de partición*sfi=Sistema de ficheros*tam=Tamaño de la partición*ope=Operación
# @= caracter de separación
#____________________________________________________________________
# Captura de parámetros (se ignora el 1er parámetro y se eliminan espacios y tabuladores).
@ -51,12 +50,13 @@ param = sys.argv[2]
tbprm = param.split ('!')
pparam = tbprm[0] # General disk parameters
sparam = tbprm[1] # Partitioning and formatting parameters
is_there_cache = 'CACHE' in sparam
# Toma valores de disco y caché, separados por "*".
# Los valores están en las variables $dis: disco, $che: existe cache (1, 0), $tch: Tamaño de la cache.
tbprm = pparam.split ('*')
pparams = pparam.split ('*')
dis = tch = None
for item in tbprm:
for item in pparams:
if '=' not in item: continue
k, v = item.split ('=', 1)
@ -74,10 +74,13 @@ if dis is None:
tbp = [] # Valores de configuración (parámetros para ogCreatePartitions)
tbf = {} # Tabla de formateo
tbprm = sparam.split('%')
sparams = sparam.split('%')
maxp=0
for item in tbprm:
sum_tam = 0
do_sum_tam = True
cache_seen = extended_seen = efi_seen = False
for item in sparams:
if not item: continue ## por si nos pasan un '%' al final de todo
# Leer datos de la partición, separados por "*".
par = cpt = sfi = tam = None
@ -93,7 +96,7 @@ for item in tbprm:
if 'par' == k: par = int (v)
elif 'cpt' == k: cpt = v
elif 'sfi' == k: sfi = v
elif 'tam' == k: tam = v
elif 'tam' == k: tam = int (v)
elif 'ope' == k: ope = int (v)
missing_params = []
@ -106,10 +109,29 @@ for item in tbprm:
sys.exit (1)
# Componer datos de particionado.
if 'EFI' == cpt:
if efi_seen:
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición de ESP')
sys.exit (1)
efi_seen = True
if 'CACHE' == cpt:
if cache_seen:
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición de cache')
sys.exit (1)
cache_seen = True
tch = tam
else:
tbp.append (f'{cpt}:{tam}')
if do_sum_tam:
sum_tam += tam
if 'EXTENDED' == cpt:
if extended_seen:
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición extendida')
sys.exit (1)
extended_seen = True
extended_is_at = par
do_sum_tam = False ## don't sum sizes anymore
if ope:
# Si se activa operación de formatear, componer datos de formateo.
if cpt not in ['EMPTY', 'EXTENDED', 'LINUX-LVM', 'LVM', 'ZPOOL']:
@ -118,7 +140,88 @@ for item in tbprm:
if par > maxp: maxp = par
if tch is None:
tch = '0'
tch = 0
cur_ptt = DiskLib.ogGetPartitionTableType (dis)
ptt = 'GPT' if InventoryLib.ogIsEfiActive() else 'MSDOS'
if not cache_seen and not tbp:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'No se ha solicitado ninguna partición')
sys.exit (1)
if 'GPT' == ptt and extended_seen:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'En GPT no se pueden usar particiones extendidas')
sys.exit (1)
## error si nos piden más de 4 y ninguna es extendida
if 'MSDOS' == ptt and not extended_seen:
requested_partitions = len (tbp)
if cache_seen: requested_partitions += 1
if requested_partitions > 4:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'Se han solicitado más de 4 particiones y ninguna es extendida')
sys.exit (1)
if efi_seen:
if 'EFI' != tbp[0].split (':')[0]:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'la partición ESP debe estar declarada en primera posición')
sys.exit (1)
else:
if 'GPT' == ptt and 1 == dis:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'En GPT debe haber una partición ESP')
sys.exit (1)
## si no nos definen partición de cache y el disco tiene una, hay que borrarla
if not cache_seen:
c = CacheLib.ogFindCache()
if c:
cache_disk, cache_part = c.split()
if int (cache_disk) == int (dis):
CacheLib.ogUnmountCache()
CacheLib.ogDeleteCache()
## la extendida solo puede estar en la (si hay cache) o en la 4 (si no lo hay)
if extended_seen:
extended_should_be_at = 3 if cache_seen else 4
if extended_is_at != extended_should_be_at:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'La partición extendida no puede ser la "{extended_is_at}" sino que debe ser la "{extended_should_be_at}"')
sys.exit (1)
recreate_partition_table = False
if not cur_ptt:
SystemLib.ogEcho (['session', 'log'], None, f'No partition table--will create a "{ptt}" one')
recreate_partition_table = True
if cur_ptt and ptt != cur_ptt:
SystemLib.ogEcho (['session', 'log'], None, f'Current partition table type "{cur_ptt}" is wrong for this system--will replace it for a "{ptt}" one')
recreate_partition_table = True
## size check: check that cache fits in the space left by the previously existing partitions
if not recreate_partition_table and not CacheLib.ogCheckNewCacheSize (dis, tch):
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'nueva partición de caché no cabe en el hueco actual')
## BUG el "hueco actual" me podría dar igual, si luego resulta que también estoy definiendo otras particiones y ya sí hay sitio para todo
sys.exit (1)
## size check: check that the newly defined partitions fit in the disk
disk_sectors = DiskLib.ogGetLastSector (dis)
IOSIZE = DiskLib.ogGetIoSize (dis)
if not IOSIZE:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size')
sys.exit (1)
if 512 == IOSIZE:
sum_tam_sectors = sum_tam*2
cache_sectors = tch*2
else:
sum_tam_sectors = (sum_tam+3)//4 ## sumamos 3 para que la división entera "redondee al alza"
cache_sectors = (tch+3)//4
## esta comprobacion puede dejar pasar situaciones que más tarde dan error
## la ventana es bastante estrecha, y sumando aquí simplemente un 1 por 1000, ya la cerramos del todo
sum_tam_sectors = int (sum_tam_sectors * 1.001)
space_left_by_cache = disk_sectors - cache_sectors
if sum_tam_sectors > space_left_by_cache:
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'las particiones no caben en el disco')
sys.exit (1)
#____________________________________________________
#
@ -133,53 +236,46 @@ SystemLib.ogEcho (['session', 'log'], None, f'[10] {ogGlobals.lang.MSG_HELP_ogUn
FileSystemLib.ogUnmountAll (dis)
CacheLib.ogUnmountCache()
# Elimina la tabla de particiones
cur_ptt = DiskLib.ogGetPartitionTableType (dis)
ptt = 'GPT' if InventoryLib.ogIsEfiActive() else 'MSDOS'
if not cur_ptt or ptt != cur_ptt:
if recreate_partition_table:
DiskLib.ogDeletePartitionTable (dis)
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable'])
DiskLib.ogCreatePartitionTable (dis, ptt)
# Inicia la cache.
if 'CACHE' in sparam:
if is_there_cache:
SystemLib.ogEcho (['session', 'log'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogCreateCache}')
SystemLib.ogEcho (['session', 'log'], None, f' initCache {tch}')
rc = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGSCRIPTS}/initCache', tch])
SystemLib.ogEcho (['session', 'log'], None, f' initCache.py {dis} {tch}')
rc = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGSCRIPTS}/initCache.py', str (dis), str (tch)])
if not rc:
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'initCache failed')
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'initCache.py failed')
sys.exit (1)
# Definir particionado.
SystemLib.ogEcho (['session', 'log'], None, f'[50] {ogGlobals.lang.MSG_HELP_ogCreatePartitions}')
SystemLib.ogEcho (['session', 'log'], None, f' ogCreatePartitions {dis} {' '.join (tbp)}')
res = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCreatePartitions', str(dis)] + tbp)
if not res:
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_GENERIC, f'ogCreatePartitions {dis} {' '.join (tbp)}')
sys.exit (1)
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable'])
if tbp:
SystemLib.ogEcho (['session', 'log'], None, f'[50] {ogGlobals.lang.MSG_HELP_ogCreatePartitions}')
SystemLib.ogEcho (['session', 'log'], None, f' ogCreatePartitions {dis} {' '.join (tbp)}')
res = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCreatePartitions', str(dis)] + tbp)
if not res:
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'ogCreatePartitions {dis} {' '.join (tbp)}')
sys.exit (1)
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable'])
# Formatear particiones
SystemLib.ogEcho (['session', 'log'], None, f'[70] {ogGlobals.lang.MSG_HELP_ogFormat}')
retval = 0
for p in range (1, maxp+1):
if p not in tbf: continue
if 'CACHE' == tbf[p]:
if CACHESIZE == tch: # Si el tamaño es distinto ya se ha formateado.
SystemLib.ogEcho (['session', 'log'], None, ' ogFormatCache')
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatCache'])
else:
SystemLib.ogEcho (['session', 'log'], None, f' ogFormatFs {dis} {p} {tbf[p]}')
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatFs', str(dis), str(p), tbf[p]])
if not retval:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_GENERIC, f'ogFormatFs {dis} {p} {tbf[p]}')
sys.exit (1)
# Registro de fin de ejecución
if tbf:
# Formatear particiones
SystemLib.ogEcho (['session', 'log'], None, f'[70] {ogGlobals.lang.MSG_HELP_ogFormat}')
for p in range (1, maxp+1):
if p not in tbf: continue
if 'CACHE' == tbf[p]:
if CACHESIZE == tch: # Si el tamaño es distinto ya se ha formateado.
SystemLib.ogEcho (['session', 'log'], None, ' ogFormatCache')
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatCache'])
else:
SystemLib.ogEcho (['session', 'log'], None, f' ogFormatFs {dis} {p} {tbf[p]}')
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatFs', str(dis), str(p), tbf[p]])
if not retval:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_GENERIC, f'ogFormatFs {dis} {p} {tbf[p]}')
sys.exit (1)
SystemLib.ogEcho (['session', 'log'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {retval}')
#___________________________________________________________________
#
# Retorno
#___________________________________________________________________
sys.exit (0)

View File

@ -195,7 +195,7 @@ def ogBoot (disk, par, nvramperm=False, params=''):
winboot = os.environ.get ('winboot', '')
if 'kexec' == winboot:
# Modo de arranque en caliente (con kexec).
cp_cmd = f'cp {ogGlobals.OGLIB}/grub4dos/* {mntdir}'
cp_cmd = f'cp {ogGlobals.OGLIB}/grub4dos/* {mntdir}' ## shutil sucks a bit for copying both files and dirs
subprocess.run (cp_cmd, shell=True)
disk0 = int(disk)-1
par0 = int(par)-1

View File

@ -37,16 +37,15 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0):
NVME_PREFIX = 'p'
END = DiskLib.ogGetLastSector (ndsk)
if not END:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'Failed to get last sector of disk')
return None
SIZE = 2 * sizecache
# Inicio partición cache según el disco tenga sectores de 4k o menores
IOSIZE = 0
fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout
for l in fdisk_out.splitlines():
items = l.split()
if len(items) < 4: continue
if 'I/O' == items[0]:
IOSIZE = int (items[3])
break
IOSIZE = DiskLib.ogGetIoSize (ndsk)
if not IOSIZE:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size')
return None
START = 0
if 4096 == IOSIZE:
END -= 8192
@ -70,7 +69,7 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0):
MINSIZE = 25000
MAXSIZE = END
if SIZE < MINSIZE or SIZE > MAXSIZE or START < ENDPREVPART:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'size ({SIZE}) < minsize ({MINSIZE}) or size > maxsize ({MAXSIZE}) or start ({START}) < endprevpart ({ENDPREVPART})')
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'size ({SIZE}) < minsize ({MINSIZE}) or size ({SIZE}) > maxsize ({MAXSIZE}) or start ({START}) < endprevpart ({ENDPREVPART})')
return None
# Desmontar todos los sistemas de archivos del disco.
@ -90,27 +89,32 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0):
subprocess.run (['gdisk', DISK], input='2\nw\nY\n', capture_output=True, text=True)
# Si existe la cache se borra previamente
if ogFindCache(): ogDeleteCache()
# Capturamos el codigo de particion GPT para cache
# PATCH - Cuando es GPT, la particion con codigo CACHE (CA00) no existe y no puede crearse, se cambia por LINUX (8300)
ID = DiskLib.ogTypeToId ('LINUX', 'GPT')
subprocess.run (['sgdisk', DISK, f'-n{part}:{START}:{END}', f'-c{part}:CACHE', f'-t{part}:{ID}'])
ID = DiskLib.ogTypeToId ('LINUX', 'GPT_GUID')
sfdisk_line = f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, type={ID}, name=CACHE'
elif 'MSDOS' == get_ptt:
# Si la tabla de particiones no es valida, volver a generarla.
if subprocess.run (['parted', '-s', DISK, 'print']).returncode: ## if True, then parted failed
subprocess.run (['fdisk', DISK], input='w\n', text=True)
# Definir particiones y notificar al kernel.
if subprocess.run (['parted', '-s', DISK, 'print'], capture_output=True).returncode: ## if True, then parted failed
subprocess.run (['fdisk', DISK], input='w\n', text=True, capture_output=True)
ID = DiskLib.ogTypeToId ('CACHE', 'MSDOS')
# Salvamos la configuración de las particiones e incluimos la cache.
tmp = subprocess.run (['sfdisk', '--dump', DISK], capture_output=True, text=True).stdout.splitlines()
tmp = [ x for x in tmp if f'{DISK}{part}' not in x ]
tmp.append (f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, Id={ID}')
# Ordenamos las líneas de los dispositivos
UNIT = [ x for x in tmp if 'unit' in x ][0]
tmp = sorted ([ x for x in tmp if re.match ('^/dev', x) ])
tmp = [UNIT, ''] + tmp
# Guardamos nueva configuración en el disco.
i = '\n'.join(tmp)
subprocess.run (['sfdisk', '--no-reread', DISK], input=i, text=True)
sfdisk_line = f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, Id={ID}'
else:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'No hay tabla de particiones en el disco')
return False
# Salvamos la configuración de las particiones e incluimos la cache.
tmp = subprocess.run (['sfdisk', '--dump', DISK], capture_output=True, text=True).stdout.splitlines()
tmp = [ x for x in tmp if f'{DISK}{part}' not in x ] ## grep -v la_de_cache
tmp.append (sfdisk_line)
# Ordenamos las líneas de los dispositivos
UNIT = [ x for x in tmp if 'unit' in x ][0]
tmp = sorted ([ x for x in tmp if re.match ('^/dev', x) ])
tmp = [UNIT, ''] + tmp
# Guardamos nueva configuración en el disco.
i = '\n'.join(tmp)
subprocess.run (['sfdisk', '--no-reread', DISK], input=i, text=True)
# Actualiza la tabla de particiones en el kernel.
DiskLib.ogUpdatePartitionTable()
return True
@ -139,15 +143,15 @@ def ogDeleteCache():
ptt = DiskLib.ogGetPartitionTableType (ndisk)
if 'GPT' == ptt:
# Si la tabla de particiones no es valida, volver a generarla.
if subprocess.run (['sgdisk', '-p', disk]).returncode: ## if True, then sgdisk failed
subprocess.run (['gdisk', disk], input='2\nw\nY\n', text=True)
if subprocess.run (['sgdisk', '-p', disk], capture_output=True).returncode: ## if True, then sgdisk failed
subprocess.run (['gdisk', disk], input='2\nw\nY\n', text=True, capture_output=True)
subprocess.run (['sgdisk', disk, f'-d{npart}'])
elif 'MSDOS' == ptt:
# Si la tabla de particiones no es valida, volver a generarla.
if subprocess.run (['parted', '-s', disk, 'print']).returncode: ## if True, then parted failed
subprocess.run (['fdisk', disk], input='w', text=True)
if subprocess.run (['parted', '-s', disk, 'print'], capture_output=True).returncode: ## if True, then parted failed
subprocess.run (['fdisk', disk], input='w', text=True, capture_output=True)
# Eliminar la partición de caché.
subprocess.run (['fdisk', disk], input=f'd\n{npart}\nw', text=True)
subprocess.run (['fdisk', disk], input=f'd\n{npart}\nw', text=True, capture_output=True)
# Borrar etiqueta de la caché.
if os.path.exists ('/dev/disk/by-label/CACHE'):
os.unlink ('/dev/disk/by-label/CACHE')
@ -358,3 +362,46 @@ def ogUnmountCache():
def initCache (*args):
p = subprocess.run ([f'{ogGlobals.OGSCRIPTS}/initCache.py'] + list(args))
return not p.returncode ## negate shell return code
#/**
# ogCheckNewCacheSize
#@brief Comprueba si un cache de X tamaño cabe en el hueco que dejan las demás particiones
#@param Tamaño de la nueva hipotética cache
#@return Boolean, True si la nueva cache cabría, False si no
#*/ ##
def ogCheckNewCacheSize (disk, kB):
DISK = DiskLib.ogDiskToDev (disk)
if not DISK: return None
IOSIZE = DiskLib.ogGetIoSize (disk)
if not IOSIZE:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size')
return None
last_sector = DiskLib.ogGetLastSector (disk)
end_of_last_partition = 0
cachepart = ogFindCache()
if cachepart:
cache_disk, cache_part = cachepart.split()
cache_dev = DiskLib.ogDiskToDev (cache_disk, cache_part)
else:
cache_dev = None
fdisk_l_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout
for l in fdisk_l_out.splitlines():
if not re.match ('^/dev', l): ## no empieza por /dev, nos la saltamos
continue
if cache_dev and re.match (f'^{cache_dev}', l): ## es la de cache, nos la saltamos
continue
last_sector_of_partition = int (l.split()[2])
if last_sector_of_partition > end_of_last_partition:
end_of_last_partition = last_sector_of_partition
if 512 == IOSIZE:
cache_sectors = kB*2
else: ## 4096
cache_sectors = (kB+3)//4 ## sumamos 3 para que la división entera "redondee al alza"
if end_of_last_partition + cache_sectors > last_sector:
SystemLib.ogEcho (['session', 'log'], None, f'end_of_last_partition ({end_of_last_partition}) + cache_sectors ({cache_sectors}) > last_sector ({last_sector}), check failed')
return False
return True

View File

@ -38,6 +38,32 @@ def parted(*args):
return "Error: 'parted' command not found"
#/**
# ogGetIoSize int_ndisk
#@brief Devuelve el tamaño de sector de un disco
#@param int_ndisk nº de orden del disco
#@return Tamaño de sector
#*/ ##
def ogGetIoSize (disk):
DISK = ogDiskToDev (disk)
if not DISK: return None
IOSIZE = None
fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout
for l in fdisk_out.splitlines():
if 'I/O' not in l: continue
items = l.split()
if len(items) < 4: continue
IOSIZE = items[3]
break
if IOSIZE is None:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Could not extract disk sector size from fdisk output')
return None
return int (IOSIZE)
#/**
# ogCreatePartitions int_ndisk str_parttype:int_partsize ...
#@brief Define el conjunto de particiones de un disco.
@ -61,12 +87,11 @@ def ogCreatePartitions (disk, parts):
PTTYPE = ogGetPartitionTableType (disk)
if not PTTYPE: PTTYPE = 'MSDOS' # Por defecto para discos vacíos.
if 'GPT' == PTTYPE:
return ogCreateGptPartitions (disk, parts)
elif 'MSDOS' != PTTYPE:
if PTTYPE not in ['MSDOS', 'GPT']:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, PTTYPE)
return None
if 'MSDOS' == PTTYPE: CACHE_ID = ogTypeToId ('CACHE', 'MSDOS')
else: CACHE_ID = ogTypeToId ('CACHE', 'GPT_GUID')
# Se calcula el ultimo sector del disco (total de sectores usables)
SECTORS = ogGetLastSector (disk)
@ -78,24 +103,21 @@ def ogCreatePartitions (disk, parts):
cache_disk, cache_part = CACHEPART.split()
if int (ND) == int (cache_disk):
CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2
# Sector de inicio (la partición 1 empieza en el sector 63).
IODISCO = ogDiskToDev (disk)
IOSIZE = 0
fdisk_out = subprocess.run (['fdisk', '-l', IODISCO], capture_output=True, text=True).stdout
for l in fdisk_out.splitlines():
if 'I/O' not in l: continue
items = l.split()
if len(items) < 4: continue
IOSIZE = items[3]
break
if '4096' == IOSIZE:
# Sector de inicio (la partición 1 empieza en el sector 63).
IOSIZE = ogGetIoSize (ND)
if not IOSIZE:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size')
return None
if 4096 == IOSIZE:
START = 4096
SECTORS -= 8192
if CACHESIZE:
SECTORS = SECTORS - CACHESIZE + 2048 - (SECTORS - CACHESIZE) % 2048 - 1
else:
START = 63
else: ## 512
if 'MSDOS' == PTTYPE: START = 63
else: START = 2048
if CACHESIZE:
SECTORS -= CACHESIZE
@ -103,71 +125,108 @@ def ogCreatePartitions (disk, parts):
sfdisk_input = 'unit: sectors\n\n'
NVME_PREFIX = 'p' if 'nvme' in DISK else ''
EXTSTART = EXTSIZE = 0
for p in parts:
# Conservar los datos de la partición de caché.
if f'{ND} {PART}' == CACHEPART and CACHESIZE:
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n'
PART += 1
continue
# Leer formato de cada parámetro - Tipo:Tamaño
TYPE, SIZE = p.split (':')
if TYPE is None or 'None' == TYPE: TYPE='EMPTY'
# Obtener identificador de tipo de partición válido.
if 'GPT' == PTTYPE:
ID = ogTypeToId (TYPE, 'GPT_GUID')
else:
ID = ogTypeToId (TYPE, PTTYPE)
# Conservar los datos de la partición de caché.
if f'{ND} {PART}' == CACHEPART and CACHESIZE:
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, type={CACHE_ID}\n'
PART += 1
try:
SIZE = int (SIZE)
except ValueError:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE)
return None
# Obtener identificador de tipo de partición válido.
ID = ogTypeToId (TYPE, 'MSDOS')
if 'CACHE' == TYPE or not ID:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE)
return None
# Comprobar tamaño numérico y convertir en sectores de 512 B.
SIZE *= 2
# Comprobar tamaño numérico y convertir en sectores
ORIG_SIZE = SIZE ## para reportar en un error
if 512 == IOSIZE: SIZE *= 2
else: SIZE = (SIZE+3)//4 ## sumamos 3 para que la división entera "redondee al alza"
# Comprobar si la partición es extendida.
EXTSTART = EXTSIZE = 0
if 5 == ID:
if PART > 4:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '')
if '5' == ID:
if 'GPT' == PTTYPE:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'EXTENDED')
return None
## la extendida debe ser:
## - si no estamos creando cache: /dev/sda4
## - si sí estamos creando cache: /dev/sda3
## de lo contrario, crea eg. esto:
## Device Boot Start End Sectors Size Id Type
## /dev/sda1 63 222444728 222444666 106,1G 82 Linux swap / Solaris
## /dev/sda2 222444729 244889394 22444666 10,7G 5 Extended <---------
## /dev/sda3 244889395 251334060 6444666 3,1G 83 Linux <---------
## /dev/sda4 314103633 314572766 469134 229,1M ca unknown
## /dev/sda5 222446777 224891442 2444666 1,2G 83 Linux
## /dev/sda6 224891443 229558330 4666888 2,2G 83 Linux
## la sda2 es extendida, y las lógicas deberían ser sda5, sda6, sda7
## pero esto mete una sda3 como lógica, y luego va el cache que es primaria... WTF
error_in_extended = False
if CACHEPART and PART != 3: error_in_extended = True
if not CACHEPART and PART != 4: error_in_extended = True
if PART > 4: error_in_extended = True
if error_in_extended:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'No se puede definir la partición extendida en la partición "{PART}"')
return None
# El inicio de la primera partición logica es el de la extendida más 4x512
EXTSTART = START+2048
EXTSIZE = SIZE-2048
# Incluir particiones lógicas dentro de la partición extendida.
if 5 == PART:
if not EXTSTART:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '')
return None
START = EXTSTART
SECTORS = EXTSTART+EXTSIZE
if 'GPT' == PTTYPE:
pass ## sin problema, la partición 5 es simplemente una más
else:
if not EXTSTART:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'la partición 5 es lógica pero no hay ninguna EXTENDED definida antes')
return None
START = EXTSTART
SECTORS = EXTSTART+EXTSIZE
# Generar datos para la partición.
# En el caso de que la partición sea EMPTY no se crea nada
if 'EMPTY' != TYPE:
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n'
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, type={ID}\n'
START += SIZE
# Error si se supera el nº total de sectores.
if '4096' == IOSIZE and PART > 4:
if 'MSDOS' == PTTYPE and 4096 == IOSIZE and PART > 4:
START += 2048
# Error si se supera el nº total de sectores.
if START > SECTORS:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}')
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'partición "{TYPE}:{ORIG_SIZE}" no cabe')
return None
PART += 1
# Si no se indican las 4 particiones primarias, definirlas como vacías, conservando la partición de caché.
while PART <= 4:
if f'{ND} {PART}' == CACHEPART and CACHESIZE:
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n'
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, type={CACHE_ID}\n'
else:
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, Id=0\n'
sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, type=0\n'
PART += 1
# Si se define partición extendida sin lógicas, crear particion 5 vacía.
if 5 == PART and EXTSTART:
sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, Id=0\n'
ID = ogTypeToId ('WINDOWS', PTTYPE)
sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, type={ID}\n'
# Desmontar los sistemas de archivos del disco antes de realizar las operaciones.
FileSystemLib.ogUnmountAll (ND)
@ -183,113 +242,6 @@ def ogCreatePartitions (disk, parts):
return not p.returncode
#/**
# ogCreateGptPartitions int_ndisk str_parttype:int_partsize ...
#@brief Define el conjunto de particiones de un disco GPT
#@param int_ndisk nº de orden del disco
#@param str_parttype mnemónico del tipo de partición
#@param int_partsize tamaño de la partición (en KB)
#@return (nada, por determinar)
#@exception OG_ERR_FORMAT formato incorrecto.
#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo).
#@exception OG_ERR_PARTITION error en partición o en tabla de particiones.
#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize
#@attention Pueden definirse particiones vacías de tipo \c EMPTY
#@attention No puede definirse partición de caché y no se modifica si existe.
#@note Requisitos: sfdisk, parted, partprobe, awk
#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc.
#*/ ##
def ogCreateGptPartitions (disk, parts):
ND = disk
DISK = ogDiskToDev (ND)
if not DISK: return None
# Se calcula el ultimo sector del disco (total de sectores usables)
SECTORS = ogGetLastSector (disk)
# Se recalcula el nº de sectores del disco si existe partición de caché.
CACHESIZE = 0
CACHEPART = CacheLib.ogFindCache()
if CACHEPART:
cache_disk, cache_part = CACHEPART.split()
if ND == cache_disk:
CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2
if CACHESIZE:
SECTORS -= CACHESIZE
# Si el disco es GPT empieza en el sector 2048 por defecto, pero podria cambiarse
ALIGN = int (subprocess.run (['sgdisk', '-D', DISK], capture_output=True, text=True).stdout)
START = ALIGN
PART = 1
print (f'START ({START}) SECTORS ({SECTORS}) PART ({PART})')
# Leer parámetros con definición de particionado.
DELOPTIONS = []
OPTIONS = []
for p in parts:
# Conservar los datos de la partición de caché.
if f'{ND} {PART}' == CACHEPART and CACHESIZE:
PART += 1
# Leer formato de cada parámetro - Tipo:Tamaño
TYPE, SIZE = p.split (':')
try:
SIZE = int (SIZE)
except ValueError:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE)
return None
# Error si la partición es extendida (no válida en discos GPT).
if 'EXTENDED' == TYPE:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'EXTENDED')
return None
# Comprobar si existe la particion actual, capturamos su tamaño para ver si cambio o no
PARTSIZE = ogGetPartitionSize (ND, PART)
# En sgdisk no se pueden redimensionar las particiones, es necesario borrarlas y volver a crealas
if PARTSIZE:
DELOPTIONS.append (f'-d{PART}')
# Creamos la particion
# Obtener identificador de tipo de partición válido.
ID = ogTypeToId (TYPE, 'GPT')
if 'CACHE' == TYPE or not ID:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE)
return None
# Comprobar tamaño numérico y convertir en sectores de 512 B.
SIZE *= 2
# SIZE debe ser múltiplo de ALIGN, si no gdisk lo mueve automáticamente.
SIZE = (SIZE // ALIGN) * ALIGN
# Generar datos para la partición.
# En el caso de que la partición sea EMPTY no se crea nada
if 'EMPTY' != TYPE:
OPTIONS += [f'-n{PART}:{START}:+{SIZE}', f'-t{PART}:{ID}']
START += SIZE
# Error si se supera el nº total de sectores.
if START > SECTORS:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}')
return None
PART += 1
# Desmontar los sistemas de archivos del disco antes de realizar las operaciones.
FileSystemLib.ogUnmountAll (ND)
if CACHESIZE: CacheLib.ogUnmountCache()
# Si la tabla de particiones no es valida, volver a generarla.
ogCreatePartitionTable (ND, 'GPT')
# Definir particiones y notificar al kernel.
p = subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK], capture_output=True, text=True)
print (f'sgdisk rc ({p.returncode}) stdout ({p.stdout}) stderr ({p.stderr})')
subprocess.run (['partprobe', DISK])
if CACHESIZE: CacheLib.ogMountCache()
return not p.returncode
#/**
# ogCreatePartitionTable int_ndisk [str_tabletype]
#@brief Genera una tabla de particiones en caso de que no sea valida, si es valida no hace nada.
@ -431,7 +383,7 @@ def ogDevToDisk(arg_dev):
def _getAllDisks():
ret = []
all_disks = subprocess.run("lsblk -n -e 1,2 -x MAJ:MIN 2>/dev/null || lsblk -n -e 1,2", shell=True, capture_output=True, text=True).stdout.splitlines()
all_disks = subprocess.run("lsblk -n -e 1,2 -x NAME 2>/dev/null || lsblk -n -e 1,2", shell=True, capture_output=True, text=True).stdout.splitlines()
for line in all_disks:
parts = line.split()
if parts[5] == "disk":
@ -785,9 +737,9 @@ def ogGetPartitionActive (disk):
break
if lang is None:
del os.environ['LANG']
if 'LANG' in os.environ: del os.environ['LANG']
else:
os.environ['LAMG'] = lang
os.environ['LANG'] = lang
return ret
@ -858,7 +810,7 @@ def ogGetPartitionSize (disk, par):
#@return Devuelve el numero paritiones del disco duro indicado
#@warning Salidas de errores no determinada
#@attention Requisitos: parted
#@note Notas sin especificar
#@note Notas sin especificar
#*/ ##
def ogGetPartitionsNumber (disk):
DISK = ogDiskToDev (disk)
@ -1277,6 +1229,23 @@ def ogSetPartitionType (disk, par, t):
#ogTypeToId ('LINUX', 'MSDOS') => "83"
def ogTypeToId (type, pttype='MSDOS'):
data = {
'GPT_GUID': {
## https://en.wikipedia.org/wiki/GUID_Partition_Table?useskin=vector
'EMPTY': '0',
'WINDOWS': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7',
'NTFS': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7',
'FAT32': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7',
'FAT16': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7',
'FAT12': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7',
'WIN-RESERV': 'E3C9E316-0B5C-4DB8-817D-F92DF00215AE',
'LINUX-SWAP': '0657FD6D-A4AB-43C4-84E5-0933C84B4F4F',
'LINUX': '0FC63DAF-8483-4772-8E79-3D69D8477DE4',
'EXT2': '0FC63DAF-8483-4772-8E79-3D69D8477DE4',
'EXT3': '0FC63DAF-8483-4772-8E79-3D69D8477DE4',
'EXT4': '0FC63DAF-8483-4772-8E79-3D69D8477DE4',
'CACHE': '0FC63DAF-8483-4772-8E79-3D69D8477DE4',
'EFI': 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B',
},
'GPT': {
'EMPTY': '0',
'WINDOWS': '0700',

View File

@ -635,7 +635,7 @@ def ogGetImageInfo (imgfile):
if lc_all is not None:
os.environ["LC_ALL"] = lc_all
else:
del os.environ["LC_ALL"]
if "LC_ALL" in os.environ: del os.environ["LC_ALL"]
if 'size' in partclone_info:
tools = 'PARTCLONE'

View File

@ -0,0 +1,352 @@
#!/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')

View File

@ -255,7 +255,7 @@ def ogGetRepoIp():
#@note Comprobacion segun protocolo de conexion al Repo
#*/ ##
def ogGetServerIp():
return os.environ['ogcore']
return os.environ.get ('ogcore', '')
#/**
# ogGetServerPort
@ -263,10 +263,7 @@ def ogGetServerIp():
#@return str_port - Puerto
#*/ ##
def ogGetServerPort():
if 'ogcore_port' in os.environ:
return os.environ['ogcore_port']
else:
return '8443'
return os.environ.get ('ogcore_port', '8443')
#/**

View File

@ -224,7 +224,6 @@ def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None):
return
path2 = FileLib.ogGetPath (file=source)
print (f'nati path2 ({path2})')
if not path2:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found')
return
@ -483,7 +482,6 @@ def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None):
return
path2 = FileLib.ogGetPath (file=source)
print (f'nati path2 ({path2})')
if not path2:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found')
return

View File

@ -178,7 +178,7 @@ def ogGetCaller():
caller = words[0].lstrip("-")
if cols is None:
del (os.environ['COLUMNS'])
if 'COLUMNS' in os.environ: del os.environ['COLUMNS']
else:
os.environ['COLUMNS'] = cols

View File

@ -45,7 +45,7 @@ MCASTWAIT=30 # timeout (segundos) para abortar la la tran
#FACTORSYNC=120 # Factor de compresion para las imagenes (windos en ext4).
#BACKUP=False # Realizar copia de seguridad antes de crear la imagen.
#IMGFS='EXT4' # Sistema de archivo de la imagenes sincronizadas. EXT4 o BTRFS
#OGSLEEP=20 # Tiempo de sleep antes de realizar el reboot
OGSLEEP=4 # Tiempo de sleep antes de realizar el reboot
NODEBUGFUNCTIONS=['ogCreateImageSyntax', 'ogGetHivePath', 'ogGetOsType', 'ogRestoreImageSyntax', 'ogUnmountAll', 'ogUnmountCache'] # Funciones que no deben mostrar salida de avisos si son llamadas por otras funciones.
#DEFAULTSPEED=''
## /engine.cfg

View File

@ -1 +0,0 @@
bootOs

View File

@ -1 +0,0 @@
bootOs

View File

@ -50,6 +50,8 @@ def main (NDISK, NPART, SIZE, MOUNT):
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_CACHE, 'failed to create cache')
return False
DiskLib.ogUpdatePartitionTable()
else:
print("[10] Partición de caché solicitada es del mismo tamaño que la existente, ignorar.")
# Si caché no montada y no formateada o cambia el tamaño: formatear.
cache = CacheLib.ogFindCache()

View File

@ -1,39 +1,74 @@
#!/bin/bash
# Scirpt de ejemplo para apagar un ordenador
# Nota: se usa como base para el programa de apagado de OpenGnsys Admin.
#!/usr/bin/python3
import os
import sys
import shutil
import time
import subprocess
# Registrar ejecución manual de script.
case "$(ogGetCaller)" in
browser|bash) ogEcho log info "Script: $0" ;;
esac
import ogGlobals
from SystemLib import ogGetCaller, ogEcho
from DiskLib import ogDiskToDev
from FileSystemLib import ogUnmountAll
from CacheLib import ogUnmountCache
DEVICE = os.environ.get ('DEVICE', '')
ogstatus = os.environ.get ('ogstatus', '')
PROG = os.path.basename (sys.argv[0])
is_reboot = 'reboot'==PROG
TIME = None
try:
TIME = int (sys.argv[1])
except:
pass
# Registrar ejecución manual de script.
c = ogGetCaller()
if c in ['browser', 'OGBrowser', 'bash']:
ogEcho ('log', 'info', f'Script: {PROG}')
# Cargamos el valor por defecto del tiempo de sleep
if TIME:
print (f'[5] Se ha introducido un retardo de {TIME} segundos para reiniciar')
else:
TIME = ogGlobals.OGSLEEP
print (f'[5] No se ha introducido un retardo, {TIME} segundos para reiniciar')
# No registrar errores.
export DEBUG="no"
#DEBUG=no
# Desmontar los sistemas de archivos y la caché local.
echo "[10] Desmontar todos los sistemas de archivos."
sync
for (( i=1; i <= $(ogDiskToDev | wc -w); i++ )); do
ogUnmountAll $i &>/dev/null
done
echo "[50] Desmontar cache local."
ogUnmountCache &>/dev/null
print ('[10] Desmontar todos los sistemas de archivos.')
subprocess.run (['sync'])
ndisks = len (ogDiskToDev())
for d in range (1, ndisks+1):
ogUnmountAll (d)
print ('[50] Desmontar cache local.')
ogUnmountCache()
# Volver a registrar errores.
unset DEBUG
#DEBUG=yes
echo "[70] Apagando el equipo."
if is_reboot:
print ('[90] Reiniciar el equipo.')
else:
print ('[70] Apagando el equipo.')
# Estado correcto de Wake-On-Lan antes de apagar.
ethtool -s $DEVICE wol g 2>/dev/null
subprocess.run (['ethtool', '-s', DEVICE, 'wol', 'g'], stderr=subprocess.DEVNULL)
# Detectar Busybox.
BUSYBOX=$(which busyboxOLD)
BUSYBOX=${BUSYBOX:-"busybox"}
BUSYBOX = shutil.which ('busyboxOLD')
if not BUSYBOX: BUSYBOX = shutil.which ('busybox')
# Retardo para dar lugar al registro en cola de acciones.
sleep 5
time.sleep (TIME)
# Parar Browser para evitar "cuelgues".
[ "$ogstatus" == "offline" ] || pkill browser
if 'offline' != ogstatus:
subprocess.run (['killall', 'QtWebEngineProcess', 'OGBrowser', 'i3', 'sway', 'Xorg', 'startx'], stderr=subprocess.DEVNULL)
# Apagar.
$BUSYBOX poweroff
if is_reboot:
subprocess.run ([BUSYBOX, 'reboot'])
else:
subprocess.run ([BUSYBOX, 'poweroff'])

View File

@ -1,54 +0,0 @@
#!/bin/bash
# Script de ejemplo para reiniciar un ordenador
# Nota: se usa como base para el programa de reinicio de OpenGnsys Admin.
# Registrar ejecución manual de script.
case "$(ogGetCaller)" in
browser|bash) ogEcho log info "Script: $0" ;;
esac
# Cargamos el valor por defecto del tiempo de sleep
[ -z $OGSLEEP ] && source /opt/opengnsys/etc/engine.cfg
# Si se recibe un parametro sera el tiempo de sleep antes de realizar el reboot
if [ $# == 1 ] && [ "${1//[^0-9]/}" == "$1" ]
then
TIME=$1
echo "[5] Se ha introducido un retardo de $TIME segundos para reiniciar"
else
# Sin parámetros, o el parámetro introducido no es un número
TIME=${OGSLEEP:-5}
echo "[5] No se ha introducido un retardo, $TIME segundos para reiniciar"
fi
# No registrar errores.
export DEBUG="no"
# Desmontar los sistemas de archivos y la caché local.
echo "[10] Desmontar todos los sistemas de archivos."
sync
for (( i=1; i <= $(ogDiskToDev | wc -w); i++ )); do
ogUnmountAll $i &>/dev/null
done
echo "[50] Desmontar cache local."
ogUnmountCache &>/dev/null
# Volver a registrar errores.
unset DEBUG
echo "[90] Reiniciar el equipo."
# Estado correcto de Wake-On-Lan antes de reiniciar.
ethtool -s $DEVICE wol g 2>/dev/null
# Detectar Busybox.
BUSYBOX=$(which busyboxOLD)
BUSYBOX=${BUSYBOX:-"busybox"}
# Retardo para dar lugar al registro en cola de acciones.
sleep $TIME
# Parar Browser para evitar "cuelgues".
[ "$ogstatus" == "offline" ] || pkill browser
# Reiniciar.
$BUSYBOX reboot

View File

@ -0,0 +1 @@
poweroff

View File

@ -1,38 +0,0 @@
import shutil
import os
import subprocess
def main():
# Copy lighttpd.conf
shutil.copy('/etc/lighttpd/lighttpd.conf', '/etc/lighttpd/lighttpd.conf.back')
shutil.copy('/opt/opengnsys/lib/httpd/lighttpd.conf', '/etc/lighttpd/')
# Copy 10-cgi.conf
shutil.copy('/etc/lighttpd/conf-enabled/10-cgi.conf', '/etc/lighttpd/conf-enabled/10-cgi.conf.back')
shutil.copy('/opt/opengnsys/lib/httpd/10-cgi.conf', '/etc/lighttpd/conf-enabled/')
# Start lighttpd service
subprocess.run(['/etc/init.d/lighttpd', 'start'])
# Change permissions and create directories
os.chmod('/opt', 0o755)
os.makedirs('/usr/lib/cgi-bin', exist_ok=True)
# Copy files to /usr/lib/cgi-bin
for filename in os.listdir('/opt/opengnsys/lib/httpd/'):
full_file_name = os.path.join('/opt/opengnsys/lib/httpd/', filename)
if os.path.isfile(full_file_name):
shutil.copy(full_file_name, '/usr/lib/cgi-bin')
# Run dstat command
with open('/tmp/bandwidth', 'w') as f:
subprocess.Popen(['dstat', '-dn', '10'], stdout=f)
# Append "WAITING" to OGLOGSESSION
oglogsession = os.getenv('OGLOGSESSION')
if oglogsession:
with open(oglogsession, 'a') as f:
f.write("WAITING\n")
if __name__ == "__main__":
main()