1
0
Fork 0

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 sys
import platform import platform
import ogGlobals
import SystemLib
import DiskLib import DiskLib
import FileSystemLib
print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<") import CacheLib
def ogCreateCache(ndisk=1, npart=4, partsize=None): def ogCreateCache(ndisk=1, npart=4, partsize=None):
""" """
@ -193,21 +195,21 @@ def ogGetCacheSpace():
return free_space_kb 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(): def ogMountCache():
""" c = CacheLib.ogFindCache().split()
Monta la partición de caché en el directorio /mnt/sda4. m = FileSystemLib.ogMountFs (c[0], c[1])
if not m:
:raises RuntimeError: Si ocurre un error durante el montaje de la partición de caché. SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE)
""" #return
# Si se solicita, mostrar ayuda. return m
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}")
def ogUnmountCache(): def ogUnmountCache():
""" """

View File

@ -1,6 +1,8 @@
import subprocess import subprocess
import os import os
import shutil import shutil
import ogGlobals
import SystemLib import SystemLib
import CacheLib import CacheLib
import FileSystemLib import FileSystemLib
@ -146,66 +148,82 @@ def ogDeleteTree(*args):
except OSError as e: except OSError as e:
SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args) SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args)
return 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: # ogGetPath [ str_repo | int_ndisk int_npartition ] path_filepath
FILE = args[0] #@brief Inicia el proceso de arranque de un sistema de archivos.
elif len(args) == 2: #@param path_filepath camino del fichero (independiente de mayúsculas)
if args[0].upper() == "REPO": #@param str_repo repositorio de ficheros
FILE = os.path.join(OGIMG, args[1]) #@param int_ndisk nº de orden del disco
elif args[0].upper() == "CACHE": #@param int_npartition nº de orden de la partición
MNTDIR = CacheLib.ogMountCache() #@return path_file - camino completo real del fichero.
if not MNTDIR: #@note repo = { REPO, CACHE, CDROM }
return #@note Requisitos: \c grep \c sed
FILE = os.path.join(MNTDIR, OGIMG, args[1]) #@exception OG_ERR_FORMAT Formato incorrecto.
elif args[0].upper() == "CDROM": #@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado.
MNTDIR = FileSystemLib.ogMountCdrom() #@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar.
if not MNTDIR: #@warning En caso de error, sólo devuelve el código y no da mensajes.
return #@todo Terminar de definir parámetros para acceso a repositorios.
FILE = os.path.join(MNTDIR, args[1]) #*/ ##
#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: else:
SystemLib.ogRaiseError(OG_ERR_FORMAT) try:
return disk, part = src.split()
elif len(args) == 3: except ValueError:
MNTDIR = FileSystemLib.ogMount(args[0], args[1]) SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '')
if not MNTDIR: return
return mntdir = FileSystemLib.ogMount (disk, part)
FILE = os.path.join(MNTDIR, args[2]) if not mntdir: return None
else: f = os.path.join (mntdir, file.strip('/'))
SystemLib.ogRaiseError(OG_ERR_FORMAT)
return
# Eliminar caracteres \c / duplicados y finales. f = os.path.normpath (f)
FILE = os.path.normpath(FILE)
# Comprobar si existe el fichero para reducir tiempos. if os.path.exists (f):
if os.path.exists(FILE): filepath = f
FILEPATH = FILE #print (f'f ({f}) existe, filepath=f ({filepath})')
else: else:
# Buscar el nombre correcto en cada subdirectorio del camino. # Buscar el nombre correcto en cada subdirectorio del camino.
FILEPATH = "/" prevfile = ''
while FILE != PREVFILE: filepath = '/'
FILEPATH = os.path.join(FILEPATH.rstrip("/"), FILE.split("/")[0]) #print (f'f ({f}) prevfile ({prevfile})')
PREVFILE = FILE while f != prevfile:
FILE = "/".join(FILE.split("/")[1:]) #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: ## build filepath to return
return FILEPATH if os.path.exists (ls_path):
else: filepath = ls_path
return None #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): def ogGetParentPath(*args):
# Variables locales. # Variables locales.

View File

@ -1,13 +1,12 @@
import subprocess import subprocess
import sys import sys
import os.path
import ogGlobals import ogGlobals
import SystemLib import SystemLib
import DiskLib import DiskLib
import CacheLib import CacheLib
print (">>>>>>>>>>>>>>>>>>>> Load ", __name__, " <<<<<<<<<<<<<<<<<<<<<<")
def ogCheckFs(int_ndisk, int_nfilesys): def ogCheckFs(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda. # Si se solicita, mostrar ayuda.
if int_ndisk == "help": if int_ndisk == "help":
@ -398,25 +397,24 @@ def ogGetFsType(disk, part):
return TYPE 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: # ogGetMountPoint int_ndisk int_nfilesys
ogRaiseError(OG_ERR_FORMAT) #@brief Devuelve el punto de montaje de un sistema de archivos.
return #@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. def ogGetMountPoint(disk, par):
PART = ogDiskToDev(int_ndisk, int_nfilesys) PART = DiskLib.ogDiskToDev(disk, par)
if not PART: if not PART: return
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() out = subprocess.run(["zfs", "list", "-Hp", "-o", "canmount", PART], capture_output=True, text=True).stdout.strip()
return out == "on" 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: # ogIsLocked int_ndisk int_npartition
ogRaiseError(OG_ERR_FORMAT) #@see ogIsPartitionLocked
return #*/
# Obtener partición. def ogIsLocked(disk, par):
PART = ogDiskToDev(int_ndisk, int_npartition) return ogIsPartitionLocked(disk, par)
if not PART:
return
# 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('/', '-')}" LOCKPART = f"/var/lock/lock{PART.replace('/', '-')}"
return os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART) 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) MNTDIR = ogGetMountPoint(int_ndisk, int_nfilesys)
return bool(MNTDIR) 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: # ogIsReadonly int_ndisk int_nfilesys
ogRaiseError(OG_ERR_FORMAT) #@brief Comprueba si un sistema de archivos está montado solo de lectura.
return #@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. def ogIsReadonly(disk, par):
PART = ogDiskToDev(int_ndisk, int_nfilesys) PART = DiskLib.ogDiskToDev(disk, par)
if not PART: if not PART: return
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) result = subprocess.run(["findmnt", "-n", "-o", "OPTIONS", PART], capture_output=True, text=True)
options = result.stdout.strip().split(",") options = result.stdout.strip().split(",")
return "ro" in options return "ro" in options
@ -545,14 +546,19 @@ def ogLockPartition(int_ndisk, int_npartition):
LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}"
open(LOCKFILE, 'a').close() open(LOCKFILE, 'a').close()
def ogMount():
args = sys.argv[2:] #/**
if args == ["CACHE"] or args == ["cache"]: # ogMount int_ndisk int_nfilesys
ogMountCache() #@see ogMountFs ogMountCache ogMountCdrom
elif args == ["CDROM"] or args == ["cdrom"]: #*/ ##
ogMountCdrom() def ogMount(*args):
else: if 1 == len (args):
ogMountFs(*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): def ogMountFirstFs(int_ndisk):
# Obtener número de particiones del disco. # Obtener número de particiones del disco.
@ -564,65 +570,87 @@ def ogMountFirstFs(int_ndisk):
ogRaiseError(OG_ERR_NOTFOUND, int_ndisk) ogRaiseError(OG_ERR_NOTFOUND, int_ndisk)
return OG_ERR_NOTFOUND return OG_ERR_NOTFOUND
def ogMountFs(int_ndisk, int_nfilesys): #/**
FUNCNAME = ogExecAndLog.__name__ # ogMountFs int_ndisk int_nfilesys
# Si se solicita, mostrar ayuda. #@brief Monta un sistema de archivos.
if len(sys.argv) == 3 and sys.argv[2] == "help": #@param int_ndisk nº de orden del disco
ogHelp(f"{FUNCNAME}", "{FUNCNAME} int_ndisk int_nfilesys", "{FUNCNAME} 1 1 => /mnt/sda1") #@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 return
# Error si no se reciben 2 parámetros. # El camino de un dispositivo normal comienza por el carácter "/".
if len(sys.argv) != 3: if dev.startswith ('/'):
ogRaiseError(OG_ERR_FORMAT) # Crear punto de montaje o enlace simbólico para caché local.
return mntdir = dev.replace ('/dev', '/mnt')
if f"{disk} {par}" == CacheLib.ogFindCache():
# Obtener partición. os.makedirs(ogGlobals.OGCAC, exist_ok=True)
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.
try: try:
subprocess.run(["mount", PART, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) os.symlink(ogGlobals.OGCAC, mntdir)
except subprocess.CalledProcessError: except FileExistsError:
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:
pass 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(): def ogMountCdrom():
DEV = "/dev/cdrom" # Por defecto DEV = "/dev/cdrom" # Por defecto
MNTDIR = subprocess.run(["mount", "-l", "-t", "iso9660", DEV], capture_output=True, text=True) MNTDIR = subprocess.run(["mount", "-l", "-t", "iso9660", DEV], capture_output=True, text=True)
@ -633,7 +661,7 @@ def ogMountCdrom():
try: try:
subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_PARTITION, "cdrom") SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, "cdrom")
return return
return MNTDIR return MNTDIR

View File

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