refs #1101 add ogGetPath() and dependencies

code-review
Natalia Serrano 2024-11-11 16:28:03 +01:00
parent 961ccb8c66
commit 4342a5c27e
4 changed files with 244 additions and 187 deletions

View File

@ -5,9 +5,11 @@ import shutil
import sys
import platform
import ogGlobals
import SystemLib
import DiskLib
print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<")
import FileSystemLib
import CacheLib
def ogCreateCache(ndisk=1, npart=4, partsize=None):
"""
@ -193,21 +195,21 @@ def ogGetCacheSpace():
return free_space_kb
#/**
# ogMountCache
#@brief Monta la partición Cache y exporta la variable $OGCAC
#@param sin parametros
#@return path_mountpoint - Punto de montaje del sistema de archivos de cache.
#@warning Salidas de errores no determinada
#*/ ##
def ogMountCache():
"""
Monta la partición de caché en el directorio /mnt/sda4.
:raises RuntimeError: Si ocurre un error durante el montaje de la partición de caché.
"""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogMountCache", "help", "ogMountCache")
# Montar la partición de caché en /mnt/sda4.
try:
subprocess.run(["mount", ogFindCache(), "/mnt/sda4"], check=True)
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Error al montar la partición de caché: {e}")
c = CacheLib.ogFindCache().split()
m = FileSystemLib.ogMountFs (c[0], c[1])
if not m:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE)
#return
return m
def ogUnmountCache():
"""

View File

@ -1,6 +1,8 @@
import subprocess
import os
import shutil
import ogGlobals
import SystemLib
import CacheLib
import FileSystemLib
@ -146,66 +148,82 @@ def ogDeleteTree(*args):
except OSError as e:
SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args)
return
def ogGetPath(*args):
# Variables locales.
MNTDIR = None
FILE = None
PREVFILE = None
FILEPATH = None
CURRENTDIR = None
# Si se solicita, mostrar ayuda.
if "help" in args:
SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS/System32", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc/fstab", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS/System32")
return
# Procesar camino según el número de parámetros.
if len(args) == 1:
FILE = args[0]
elif len(args) == 2:
if args[0].upper() == "REPO":
FILE = os.path.join(OGIMG, args[1])
elif args[0].upper() == "CACHE":
MNTDIR = CacheLib.ogMountCache()
if not MNTDIR:
return
FILE = os.path.join(MNTDIR, OGIMG, args[1])
elif args[0].upper() == "CDROM":
MNTDIR = FileSystemLib.ogMountCdrom()
if not MNTDIR:
return
FILE = os.path.join(MNTDIR, args[1])
#/**
# ogGetPath [ str_repo | int_ndisk int_npartition ] path_filepath
#@brief Inicia el proceso de arranque de un sistema de archivos.
#@param path_filepath camino del fichero (independiente de mayúsculas)
#@param str_repo repositorio de ficheros
#@param int_ndisk nº de orden del disco
#@param int_npartition nº de orden de la partición
#@return path_file - camino completo real del fichero.
#@note repo = { REPO, CACHE, CDROM }
#@note Requisitos: \c grep \c sed
#@exception OG_ERR_FORMAT Formato incorrecto.
#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado.
#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar.
#@warning En caso de error, sólo devuelve el código y no da mensajes.
#@todo Terminar de definir parámetros para acceso a repositorios.
#*/ ##
#ogGetPath (file='/mnt/sda1/windows/system32') ==> '/mnt/sda1/WINDOWS/System32'
#ogGetPath (src='REPO', file='/etc/fstab') ==> '/opt/opengnsys/images/etc/fstab'
#ogGetPath (src='1 1', file='/windows/system32') ==> '/mnt/sda1/WINDOWS/System32'
def ogGetPath (src=None, file=None):
if file is None:
raise TypeError ('missing required argument: "file"')
f = file
if src is not None:
if 'REPO' == src:
f = os.path.join (ogGlobals.OGIMG, file.strip('/'))
elif 'CACHE' == src:
mntdir = CacheLib.ogMountCache()
if not mntdir: return None
f = os.path.join (mntdir, ogGlobals.OGIMG.strip('/'), file.strip('/'))
elif 'CDROM' == src:
mntdir = FileSystemLib.ogMountCdrom()
if not mntdir: return None
f = os.path.join (mntdir, file.strip('/'))
else:
SystemLib.ogRaiseError(OG_ERR_FORMAT)
return
elif len(args) == 3:
MNTDIR = FileSystemLib.ogMount(args[0], args[1])
if not MNTDIR:
return
FILE = os.path.join(MNTDIR, args[2])
else:
SystemLib.ogRaiseError(OG_ERR_FORMAT)
return
try:
disk, part = src.split()
except ValueError:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '')
return
mntdir = FileSystemLib.ogMount (disk, part)
if not mntdir: return None
f = os.path.join (mntdir, file.strip('/'))
# Eliminar caracteres \c / duplicados y finales.
FILE = os.path.normpath(FILE)
f = os.path.normpath (f)
# Comprobar si existe el fichero para reducir tiempos.
if os.path.exists(FILE):
FILEPATH = FILE
if os.path.exists (f):
filepath = f
#print (f'f ({f}) existe, filepath=f ({filepath})')
else:
# Buscar el nombre correcto en cada subdirectorio del camino.
FILEPATH = "/"
while FILE != PREVFILE:
FILEPATH = os.path.join(FILEPATH.rstrip("/"), FILE.split("/")[0])
PREVFILE = FILE
FILE = "/".join(FILE.split("/")[1:])
prevfile = ''
filepath = '/'
#print (f'f ({f}) prevfile ({prevfile})')
while f != prevfile:
#print ('\nno son iguales, nueva iteracion...')
f_first_component = f.split ('/')[0] ## take 1st component
ls_path = os.path.join (filepath, f_first_component) ## "ls" makes reference to the original bash version
#print (f'f_first_component ({f_first_component}) ls_path ({ls_path})')
if FILEPATH:
return FILEPATH
else:
return None
## build filepath to return
if os.path.exists (ls_path):
filepath = ls_path
#print (f'ls_path existe, filepath ({filepath})')
else:
filepath = subprocess.run (['find', filepath, '-maxdepth', '1', '-iname', f_first_component, '-print'], capture_output=True, text=True).stdout.strip()
#print (f'ls_path no existe, filepath ({filepath})')
prevfile = f
f = '/'.join (f.split('/')[1:]) ## remove 1st component
#print (f'f ({f}) prevfile ({prevfile})')
return filepath
def ogGetParentPath(*args):
# Variables locales.

View File

@ -1,13 +1,12 @@
import subprocess
import sys
import os.path
import ogGlobals
import SystemLib
import DiskLib
import CacheLib
print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<")
def ogCheckFs(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if int_ndisk == "help":
@ -398,25 +397,24 @@ def ogGetFsType(disk, part):
return TYPE
def ogGetMountPoint(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogGetMountPoint", "ogGetMountPoint int_ndisk int_nfilesys", "ogGetMountPoint 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
#/**
# ogGetMountPoint int_ndisk int_nfilesys
#@brief Devuelve el punto de montaje de un sistema de archivos.
#@param int_ndisk nº de orden del disco
#@param int_nfilesys nº de orden del sistema de archivos
#@return Punto de montaje
#@exception OG_ERR_FORMAT Formato incorrecto.
#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo.
#@note Requisitos: \c mount* \c awk
#*/ ##
# Obtener partición.
PART = ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
def ogGetMountPoint(disk, par):
PART = DiskLib.ogDiskToDev(disk, par)
if not PART: return
return subprocess.run(["findmnt", "-n", "-o", "TARGET", PART], capture_output=True, text=True).stdout.strip()
# Devolver punto de montaje.
result = subprocess.run(["findmnt", "-n", "-o", "TARGET", PART], capture_output=True, text=True)
return result.stdout.strip()
#/**
@ -441,27 +439,31 @@ def ogIsFormated(disk, part):
out = subprocess.run(["zfs", "list", "-Hp", "-o", "canmount", PART], capture_output=True, text=True).stdout.strip()
return out == "on"
def ogIsLocked(int_ndisk, int_nfilesys):
return ogIsPartitionLocked(int_ndisk, int_nfilesys)
def ogIsPartitionLocked(int_ndisk, int_npartition):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogIsPartitionLocked", "ogIsPartitionLocked int_ndisk int_npartition", "ogIsPartitionLocked 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
#/**
# ogIsLocked int_ndisk int_npartition
#@see ogIsPartitionLocked
#*/
# Obtener partición.
PART = ogDiskToDev(int_ndisk, int_npartition)
if not PART:
return
def ogIsLocked(disk, par):
return ogIsPartitionLocked(disk, par)
# Comprobar existencia de fichero de bloqueo de la partición o de su disco.
LOCKDISK = f"/var/lock/lock{ogDiskToDev(int_ndisk).replace('/', '-')}"
#/**
# ogIsPartitionLocked int_ndisk int_npartition
#@brief Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo.
#@param int_ndisk nº de orden del disco
#@param int_npartition nº de orden de la partición
#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error.
#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-".
#*/ ##
def ogIsPartitionLocked(disk, par):
DISK = DiskLib.ogDiskToDev(disk)
PART = DiskLib.ogDiskToDev(disk, par)
if not PART: return
LOCKDISK = f"/var/lock/lock{DISK.replace('/', '-')}"
LOCKPART = f"/var/lock/lock{PART.replace('/', '-')}"
return os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART)
@ -480,23 +482,22 @@ def ogIsMounted(int_ndisk, int_nfilesys):
MNTDIR = ogGetMountPoint(int_ndisk, int_nfilesys)
return bool(MNTDIR)
def ogIsReadonly(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogIsReadonly", "ogIsReadonly int_ndisk int_nfilesys", "ogIsReadonly 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
#/**
# ogIsReadonly int_ndisk int_nfilesys
#@brief Comprueba si un sistema de archivos está montado solo de lectura.
#@param int_ndisk nº de orden del disco
#@param int_nfilesys nº de orden del sistema de archivos
#@return Código de salida: 0 - montado solo de lectura, 1 - con escritura o no montado.
#@version 1.1.0 - Primera versión para OpenGnsys.
#@author Ramon Gomez, ETSII Universidad de Sevilla
#@date 2016-01-20
#*/ ##
# Obtener partición.
PART = ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
def ogIsReadonly(disk, par):
PART = DiskLib.ogDiskToDev(disk, par)
if not PART: return
# Comprobar si la partición está montada en modo de solo lectura.
result = subprocess.run(["findmnt", "-n", "-o", "OPTIONS", PART], capture_output=True, text=True)
options = result.stdout.strip().split(",")
return "ro" in options
@ -545,14 +546,19 @@ def ogLockPartition(int_ndisk, int_npartition):
LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}"
open(LOCKFILE, 'a').close()
def ogMount():
args = sys.argv[2:]
if args == ["CACHE"] or args == ["cache"]:
ogMountCache()
elif args == ["CDROM"] or args == ["cdrom"]:
ogMountCdrom()
else:
ogMountFs(*args)
#/**
# ogMount int_ndisk int_nfilesys
#@see ogMountFs ogMountCache ogMountCdrom
#*/ ##
def ogMount(*args):
if 1 == len (args):
if 'cache' == args[0].lower():
return ogMountCache()
elif 'cdrom' == args[0].lower():
return ogMountCdrom()
elif 2 == len (args):
return ogMountFs(args[0], args[1])
def ogMountFirstFs(int_ndisk):
# Obtener número de particiones del disco.
@ -564,65 +570,87 @@ def ogMountFirstFs(int_ndisk):
ogRaiseError(OG_ERR_NOTFOUND, int_ndisk)
return OG_ERR_NOTFOUND
def ogMountFs(int_ndisk, int_nfilesys):
FUNCNAME = ogExecAndLog.__name__
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp(f"{FUNCNAME}", "{FUNCNAME} int_ndisk int_nfilesys", "{FUNCNAME} 1 1 => /mnt/sda1")
#/**
# ogMountFs int_ndisk int_nfilesys
#@brief Monta un sistema de archivos.
#@param int_ndisk nº de orden del disco
#@param int_nfilesys nº de orden del sistema de archivos
#@return Punto de montaje
#@exception OG_ERR_FORMAT Formato incorrecto.
#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo.
#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar.
#*/ ##
def ogMountFs (disk, par):
dev = DiskLib.ogDiskToDev (disk, par)
if not dev: return
mntdir = ogGetMountPoint (disk, par)
if mntdir: return mntdir
if ogIsLocked (disk, par):
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener partición.
PART = ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
# Comprobar si el sistema de archivos ya está montada.
MNTDIR = ogGetMountPoint(int_ndisk, int_nfilesys)
# Si no, montarlo en un directorio de sistema.
if not MNTDIR:
# Error si la particion esta bloqueada.
if ogIsLocked(int_ndisk, int_nfilesys):
ogRaiseError(OG_ERR_LOCKED, f"{MSG_PARTITION}, {int_ndisk} {int_nfilesys}")
return
# El camino de un dispositivo normal comienza por el carácter "/".
if PART.startswith("/"):
# Crear punto de montaje o enlace simbólico para caché local.
MNTDIR = PART.replace("/dev", "/mnt")
DEBUG = "no"
if f"{int_ndisk} {int_nfilesys}" == ogFindCache() and OGCAC:
os.makedirs(OGCAC, exist_ok=True)
os.symlink(OGCAC, MNTDIR)
else:
os.makedirs(MNTDIR, exist_ok=True)
del DEBUG
# Montar sistema de archivos.
# El camino de un dispositivo normal comienza por el carácter "/".
if dev.startswith ('/'):
# Crear punto de montaje o enlace simbólico para caché local.
mntdir = dev.replace ('/dev', '/mnt')
if f"{disk} {par}" == CacheLib.ogFindCache():
os.makedirs(ogGlobals.OGCAC, exist_ok=True)
try:
subprocess.run(["mount", PART, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
try:
subprocess.run(["mount", PART, MNTDIR, "-o", "force,remove_hiberfile"], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk}, {int_nfilesys}")
return
# Aviso de montaje de solo lectura.
if ogIsReadonly(int_ndisk, int_nfilesys):
ogEcho("warning", f"{FUNCNAME}: {MSG_MOUNTREADONLY}: \"{int_ndisk}, {int_nfilesys}\"")
else:
# Montar sistema de archivos ZFS (un ZPOOL no comienza por "/").
try:
subprocess.run(["zfs", "mount", PART], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
os.symlink(ogGlobals.OGCAC, mntdir)
except FileExistsError:
pass
else:
os.makedirs(mntdir, exist_ok=True)
return MNTDIR
# Montar sistema de archivos.
try:
rc = subprocess.run(['mount', dev, mntdir], check=True).returncode
except subprocess.CalledProcessError:
try:
rc = subprocess.run(['mount', dev, mntdir, '-o', 'force,remove_hiberfile'], check=True).returncode
except subprocess.CalledProcessError:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk}, {par}")
return
if 0 == rc:
pass
elif 14 == rc:
try:
subprocess.run (['ntfsfix', '-d', par], check=True)
except subprocess.CalledProcessError:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk, par}")
#return
else:
try:
subprocess.run (['mount', par, mntdir, '-o', 'ro'], check=True)
except subprocess.CalledProcessError:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk, par}")
#return
# Aviso de montaje de solo lectura.
if ogIsReadonly(disk, par):
SystemLib.ogEcho("warning", f'ogMountFs: {ogGlobals.lang.MSG_MOUNTREADONLY}: "{disk}, {par}"')
else:
# Montar sistema de archivos ZFS (un ZPOOL no comienza por "/").
subprocess.run(['zfs', 'mount', dev])
return mntdir
#/**
# ogMountCdrom
#@brief Monta dispositivo óptico por defecto
#@return Punto de montaje
#@exception OG_ERR_FORMAT Formato incorrecto.
#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar.
#@version
#@author
#@date
#*/ ##
def ogMountCdrom():
DEV = "/dev/cdrom" # Por defecto
MNTDIR = subprocess.run(["mount", "-l", "-t", "iso9660", DEV], capture_output=True, text=True)
@ -633,7 +661,7 @@ def ogMountCdrom():
try:
subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_PARTITION, "cdrom")
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, "cdrom")
return
return MNTDIR

View File

@ -1,8 +1,9 @@
#!/usr/bin/python3
import sys
import os.path
import locale
import importlib
import importlib.util
def load_lang (name):
global lang
@ -27,17 +28,25 @@ TZ='Europe/Madrid'
## engine.cfg
OGLOGSESSION='/tmp/session.log'
OGLOGCOMMAND='/tmp/command.log'
NODEBUGFUNCTIONS='ogCreateImageSyntax ogGetHivePath ogGetOsType ogRestoreImageSyntax ogUnmountAll ogUnmountCache'
## /engine.cfg
#OPENGNSYS='/opt/opengnsys'
OPENGNSYS='/tmp/opengnsys' ## XXX
OGLOG=f'{OPENGNSYS}/log'
OGLOGFILE=f'{OGLOG}/192.168.42.42' ## TODO
OGLOGCOMMAND='/tmp/command.log'
OGLOGSESSION='/tmp/session.log'
DEBUG='yes'
## loadenviron.sh
OPENGNSYS = '/opt/opengnsys'
OGBIN = os.path.join (OPENGNSYS, 'bin')
OGETC = os.path.join (OPENGNSYS, 'etc')
OGLIB = os.path.join (OPENGNSYS, 'lib')
OGAPI = os.path.join (OGLIB, 'engine', 'bin')
OGSCRIPTS = os.path.join (OPENGNSYS, 'scripts')
OGIMG = os.path.join (OPENGNSYS, 'images')
OGCAC = os.path.join (OPENGNSYS, 'cache')
OGLOG = os.path.join (OPENGNSYS, 'log')
OGLOGFILE = f'{OGLOG}/192.168.42.42' ## TODO import NetLib; OGLOGFILE = f'$OGLOG/{NetLib.ogGetIpAddress()}.log'
DEBUG = 'yes'
## /loadenviron.sh
# Declaración de códigos de error.
OG_ERR_FORMAT=1 # Formato de ejecución incorrecto.