Compare commits

...

9 Commits

32 changed files with 11265 additions and 5 deletions

2438
client/engine/BootLib.py Normal file

File diff suppressed because it is too large Load Diff

210
client/engine/CacheLib.py Normal file
View File

@ -0,0 +1,210 @@
import os
import re
import subprocess
import shutil
import sys
import platform
from engine.FileSystemLib import *
from engine.SystemLib import *
from engine.DiskLib import *
def ogCreateCache(ndisk=1, npart=4, partsize=None):
"""
Define la caché local, por defecto en partición 4 del disco 1.
:param ndisk: número de disco donde crear la caché, por defecto es 1.
:param npart: número de partición (opcional, 4 por defecto).
:param partsize: tamaño de la partición en KB.
:raises ValueError: Si el formato de los parámetros es incorrecto.
:raises RuntimeError: Si ocurre un error durante la creación de la caché.
"""
if partsize is None:
raise ValueError("El tamaño de la partición debe especificarse.")
# Verifica si las herramientas necesarias están instaladas
required_tools = ["sfdisk", "parted", "awk", "sed"]
for tool in required_tools:
if not shutil.which(tool):
raise RuntimeError(f"La herramienta {tool} no está instalada.")
# Preparar los comandos para crear la caché
disk = f"/dev/sd{chr(96 + ndisk)}"
size_in_sectors = partsize * 2 # Asumiendo 512B por sector
try:
# Lógica simplificada para crear la caché en la partición
subprocess.run(["parted", disk, "mkpart", "primary", str(npart), str(partsize)], check=True)
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Error al crear la caché: {e}")
def ogDeleteCache():
"""
Borra la partición utilizada para caché.
:raises RuntimeError: Si ocurre un error durante la eliminación de la partición de caché.
"""
cachepart = ogFindCache()
if cachepart is None:
raise RuntimeError("No se encontró la partición de caché.")
disk = f"/dev/sd{chr(96 + int(cachepart))}"
try:
subprocess.run(["parted", disk, "rm", cachepart], check=True)
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Error al borrar la partición de caché: {e}")
def ogFindCache():
"""
Encuentra la partición que se usa como caché.
:return: El nombre de la partición de caché si se encuentra, de lo contrario None.
"""
try:
for disk in [f"/dev/sd{chr(97 + i)}" for i in range(26)]: # /dev/sda to /dev/sdz
result = subprocess.run(["sfdisk", "-d", disk], capture_output=True, text=True, check=True)
if "CA00" in result.stdout:
cachepart = [line.split()[0] for line in result.stdout.splitlines() if "CA00" in line][0]
return cachepart
except subprocess.CalledProcessError:
return None
return None
def ogFormatCache():
"""
Formatea la partición de caché.
:raises RuntimeError: Si ocurre un error durante el formateo de la partición.
"""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogFormatCache", "ogFormatCache")
return
# Error si no hay definida partición de caché.
cachepart = ogFindCache()
if cachepart is None:
ogRaiseError(OG_ERR_PARTITION, MSG_NOCACHE)
return
disk = ogDiskToDev(cachepart)
# Formatear sistema de ficheros.
ogUnmountCache()
options = "extent,large_file"
if re.match("^5", platform.release()):
options += ",uninit_bg,^metadata_csum,^64bit"
try:
subprocess.run(["mkfs.ext4", "-q", "-F", disk, "-L", "CACHE", "-O", options], check=True)
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Error al formatear la partición de caché: {e}")
# Crear estructura básica.
mntdir = ogMountCache()
os.makedirs(os.path.join(mntdir, OGIMG), exist_ok=True)
# Incluir kernel e Initrd del ogLive
updateBootCache()
def ogGetCacheSize():
"""
Obtiene el tamaño de la partición de caché.
:return: Tamaño de la partición de caché en kilobytes.
:raises RuntimeError: Si ocurre un error al obtener el tamaño de la partición de caché.
"""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogGetCacheSize", "help", "ogGetCacheSize")
# Error si no se encuentra partición de caché.
cachepart = ogFindCache()
if cachepart is None:
raise RuntimeError(MSG_NOCACHE)
# Devuelve tamaño de la partición de caché.
return ogGetPartitionSize(cachepart)
def ogGetCacheSpace():
"""
Obtiene el espacio libre en la partición de caché en kilobytes.
:return: Espacio libre en kilobytes.
:raises RuntimeError: Si ocurre un error al obtener el espacio libre.
"""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogGetCacheSpace", "help", "ogGetCacheSpace")
# Error si no se encuentra partición de caché.
cachepart = ogFindCache()
if cachepart is None:
raise RuntimeError(MSG_NOCACHE)
# Obtener el tamaño del disco y el número de sectores.
disk = ogDiskToDev(cachepart)
try:
result = subprocess.run(["sfdisk", "-g", disk], capture_output=True, text=True, check=True)
output = result.stdout
sectors_per_cylinder = int(output.splitlines()[1].split()[1])
total_sectors = int(output.splitlines()[1].split()[0]) * sectors_per_cylinder - 1
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Error al obtener el espacio libre: {e}")
# Obtener el último sector de la partición 3.
try:
result = subprocess.run(["sfdisk", "-uS", "-l", disk], capture_output=True, text=True, check=True)
output = result.stdout
end_sector_part3 = int([line.split()[2] for line in output.splitlines() if cachepart + "3" in line][0])
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Error al obtener el espacio libre: {e}")
# Calcular el espacio libre en kilobytes.
if end_sector_part3 > total_sectors // 2:
free_space_kb = (total_sectors - end_sector_part3) // 2
else:
free_space_kb = total_sectors // 4
return free_space_kb
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}")
def ogUnmountCache():
"""
Desmonta la partición de caché.
:raises RuntimeError: Si ocurre un error durante el desmontaje de la partición de caché.
"""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogUnmountCache", "help", "ogUnmountCache")
# Obtener la partición de caché.
cachepart = ogFindCache()
if cachepart is None:
raise RuntimeError("No se encontró la partición de caché.")
# Desmontar la partición de caché.
try:
subprocess.run(["umount", cachepart], check=True)
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Error al desmontar la partición de caché: {e}")
# Eliminar el enlace simbólico de /mnt/ParticiónCache.
os.remove(f"/mnt/{cachepart}")

View File

@ -0,0 +1,95 @@
import json
import sys
from CacheLib import (
ogCreateCache, ogDeleteCache, ogFindCache, ogFormatCache,
ogGetCacheSize, ogGetCacheSpace, ogMountCache, ogUnmountCache,
ogRaiseError
)
def load_test_data(file_path):
with open(file_path, 'r') as file:
return json.load(file)
def test_ogCreateCache(test_cases):
for case in test_cases:
try:
ogCreateCache(**case)
print(f"ogCreateCache({case}) pasó la prueba")
except Exception as e:
print(f"ogCreateCache({case}) falló la prueba: {e}")
def test_ogDeleteCache(test_cases):
for case in test_cases:
try:
ogDeleteCache()
print(f"ogDeleteCache() pasó la prueba")
except Exception as e:
print(f"ogDeleteCache() falló la prueba: {e}")
def test_ogFindCache(test_cases):
for case in test_cases:
try:
result = ogFindCache()
print(f"ogFindCache() pasó la prueba, resultado: {result}")
except Exception as e:
print(f"ogFindCache() falló la prueba: {e}")
def test_ogFormatCache(test_cases):
for case in test_cases:
try:
ogFormatCache()
print(f"ogFormatCache() pasó la prueba")
except Exception as e:
print(f"ogFormatCache() falló la prueba: {e}")
def test_ogGetCacheSize(test_cases):
for case in test_cases:
try:
result = ogGetCacheSize()
print(f"ogGetCacheSize() pasó la prueba, tamaño: {result} KB")
except Exception as e:
print(f"ogGetCacheSize() falló la prueba: {e}")
def test_ogGetCacheSpace(test_cases):
for case in test_cases:
try:
result = ogGetCacheSpace()
print(f"ogGetCacheSpace() pasó la prueba, espacio libre: {result} KB")
except Exception as e:
print(f"ogGetCacheSpace() falló la prueba: {e}")
def test_ogMountCache(test_cases):
for case in test_cases:
try:
ogMountCache(**case)
print(f"ogMountCache({case}) pasó la prueba")
except Exception as e:
print(f"ogMountCache({case}) falló la prueba: {e}")
def test_ogUnmountCache(test_cases):
for case in test_cases:
try:
ogUnmountCache()
print(f"ogUnmountCache() pasó la prueba")
except Exception as e:
print(f"ogUnmountCache() falló la prueba: {e}")
def run_tests(test_data):
test_ogCreateCache(test_data.get("ogCreateCache", []))
test_ogDeleteCache(test_data.get("ogDeleteCache", []))
test_ogFindCache(test_data.get("ogFindCache", []))
test_ogFormatCache(test_data.get("ogFormatCache", []))
test_ogGetCacheSize(test_data.get("ogGetCacheSize", []))
test_ogGetCacheSpace(test_data.get("ogGetCacheSpace", []))
test_ogMountCache(test_data.get("ogMountCache", []))
test_ogUnmountCache(test_data.get("ogUnmountCache", []))
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Uso: python3 test_CacheLib.py <ruta_al_archivo_json>")
sys.exit(1)
test_data_file = sys.argv[1]
test_data = load_test_data(test_data_file)
run_tests(test_data)

1367
client/engine/DiskLib.py Normal file

File diff suppressed because it is too large Load Diff

284
client/engine/FileLib.py Normal file
View File

@ -0,0 +1,284 @@
import subprocess
import os
import shutil
def ogCalculateChecksum(*args):
# Check if help is requested
if "help" in args:
print("ogCalculateChecksum [ str_repo | int_ndisk int_npartition ] path_filepath")
print("ogCalculateChecksum REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf")
return
# Get the file path
file_path = ogGetPath(*args)
if not file_path:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
# Calculate the checksum
result = subprocess.run(["tail", "-c1M", file_path], capture_output=True)
checksum = result.stdout.decode().split()[0]
return checksum
def ogCompareChecksumFiles(*args):
# Variables locales.
ARGS = args
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ...; fi")
return
ARGS = args
if args[0].startswith("/"):
# Camino completo. */ (Comentario Doxygen)
SOURCE = ogGetPath(*args[:1])
args = args[1:]
elif args[0].isdigit():
# ndisco npartición.
SOURCE = ogGetPath(*args[:3])
args = args[3:]
else:
# Otros: repo, cache, cdrom (no se permiten caminos relativos).
SOURCE = ogGetPath(*args[:2])
args = args[2:]
TARGET = ogGetPath(*args)
# Comparar los ficheros de checksum.
return "$(cat "$SOURCE.sum" 2>/dev/null)" == "$(cat "$TARGET.sum" 2>/dev/null)"
def ogCalculateFullChecksum(*args):
# Variables locales.
FILE = None
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf")
return
# Comprobar que existe el fichero y devolver sus datos.
FILE = ogGetPath(*args)
if not FILE:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
# Calculate the checksum
result = subprocess.run(["md5sum", FILE, "-b"], capture_output=True)
checksum = result.stdout.decode().split()[0]
return checksum
def ogCopyFile(*args):
# Variables locales.
ARGS = args
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "$FUNCNAME REPO newfile.txt 1 2 /tmp/newfile.txt")
return
ARGS = args
if args[0].startswith("/"):
# Camino completo. */ (Comentrio Doxygen)
SOURCE = ogGetPath(*args[:1])
args = args[1:]
elif args[0].isdigit():
# ndisco npartición.
SOURCE = ogGetPath(*args[:3])
args = args[3:]
else:
# Otros: repo, cache, cdrom (no se permiten caminos relativos).
SOURCE = ogGetPath(*args[:2])
args = args[2:]
TARGET = ogGetPath(*args)
# Comprobar fichero origen y directorio destino.
if not SOURCE:
ogRaiseError(OG_ERR_NOTFOUND, *args[:-1])
return
if not TARGET:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
# Copiar fichero (para evitar problemas de comunicaciones las copias se hacen con rsync en vez de cp).
result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET])
return result.returncode
def ogDeleteFile(*args):
# Variables locales.
FILE = None
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_file", "$FUNCNAME 1 2 /tmp/newfile.txt")
return
# Comprobar que existe el fichero y borrarlo.
FILE = ogGetPath(*args)
if not FILE:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
try:
os.remove(FILE)
except OSError as e:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
def ogDeleteTree(*args):
# Variables locales.
DIR = None
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir")
return
# Comprobar que existe el directorio y borrarlo con su contenido.
DIR = ogGetPath(*args)
if not DIR:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
try:
shutil.rmtree(DIR)
except OSError as e:
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:
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 = ogMountCache()
if not MNTDIR:
return
FILE = os.path.join(MNTDIR, OGIMG, args[1])
elif args[0].upper() == "CDROM":
MNTDIR = ogMountCdrom()
if not MNTDIR:
return
FILE = os.path.join(MNTDIR, args[1])
else:
ogRaiseError(OG_ERR_FORMAT)
return
elif len(args) == 3:
MNTDIR = ogMount(args[0], args[1])
if not MNTDIR:
return
FILE = os.path.join(MNTDIR, args[2])
else:
ogRaiseError(OG_ERR_FORMAT)
return
# Eliminar caracteres \c / duplicados y finales.
FILE = os.path.normpath(FILE)
# Comprobar si existe el fichero para reducir tiempos.
if os.path.exists(FILE):
FILEPATH = FILE
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:])
if FILEPATH:
return FILEPATH
else:
return None
def ogGetParentPath(*args):
# Variables locales.
PARENT = None
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS", "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc", "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS")
return
# Procesar camino según el número de parámetros.
if len(args) == 1:
PARENT = os.path.dirname(args[0])
elif len(args) == 2:
PARENT = f"{args[0]} {os.path.dirname(f'/{args[1]}')}"
elif len(args) == 3:
PARENT = f"{args[0]} {args[1]} {os.path.dirname(f'/{args[2]}')}"
else:
ogRaiseError(OG_ERR_FORMAT)
return
return ogGetPath(PARENT)
def ogIsNewerFile(*args):
# Variables locales.
ARGS = args
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ... fi")
return
ARGS = args
if args[0].startswith("/"):
# Camino completo. */ (Comentrio Doxygen)
SOURCE = ogGetPath(*args[:1])
args = args[1:]
elif args[0].isdigit():
# ndisco npartición.
SOURCE = ogGetPath(*args[:3])
args = args[3:]
else:
# Otros: repo, cache, cdrom (no se permiten caminos relativos).
SOURCE = ogGetPath(*args[:2])
args = args[2:]
TARGET = ogGetPath(*args)
# Comprobar que existen los ficheros origen y destino.
if not SOURCE:
ogRaiseError(OG_ERR_NOTFOUND, *args[:-1])
return
if not TARGET:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
# Devolver si el primer fichero se ha modificado después que el segundo.
return os.path.getmtime(SOURCE) > os.path.getmtime(TARGET)
def ogMakeChecksumFile(*args):
# Variables locales.
FILE = None
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img")
return
# Comprobar que existe el fichero y guardar su checksum.
FILE = ogGetPath(*args)
if not FILE:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
checksum = ogCalculateChecksum(FILE)
with open(f"{FILE}.sum", "w") as f:
f.write(checksum)
def ogMakeDir(*args):
# Variables locales.
PARENT = None
DIR = None
if "help" in args:
ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir", "$FUNCNAME 1 2 /tmp/newdir")
return
PARENT = ogGetParentPath(*args)
if not PARENT:
ogRaiseError(OG_ERR_NOTFOUND, *args)
return
DIR = os.path.basename(args[-1])
os.makedirs(os.path.join(PARENT, DIR), exist_ok=True)

View File

@ -0,0 +1,829 @@
import subprocess
import sys
from engine.SystemLib import *
from engine.DiskLib import *
from engine.CacheLib import *
def ogCheckFs(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if int_ndisk == "help":
ogHelp("ogCheckFs", "ogCheckFs int_ndisk int_nfilesys", "ogCheckFs 1 1")
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
TYPE = ogGetFsType(int_ndisk, int_nfilesys)
if TYPE == "EXT[234]" or TYPE == "CACHE":
PROG = "e2fsck"
PARAMS = "-y"
CODES = [1, 2]
elif TYPE == "BTRFS":
PROG = "btrfsck"
CODES = [1]
elif TYPE == "REISERFS":
PROG = "fsck.reiserfs"
PARAMS = "<<<\"Yes\""
CODES = [1, 2]
elif TYPE == "REISER4":
PROG = "fsck.reiser4"
PARAMS = "-ay"
elif TYPE == "JFS":
PROG = "fsck.jfs"
CODES = [1, 2]
elif TYPE == "XFS":
PROG = "xfs_repair"
elif TYPE == "F2FS":
PROG = "fsck.f2fs"
elif TYPE == "NTFS":
PROG = "ntfsfix"
elif TYPE == "EXFAT":
PROG = "fsck.exfat"
elif TYPE == "FAT32":
PROG = "dosfsck"
PARAMS = "-a"
CODES = [1]
elif TYPE == "FAT16":
PROG = "dosfsck"
PARAMS = "-a"
CODES = [1]
elif TYPE == "FAT12":
PROG = "dosfsck"
PARAMS = "-a"
CODES = [1]
elif TYPE == "HFS":
PROG = "fsck.hfs"
PARAMS = "-f"
elif TYPE == "HFSPLUS":
PROG = "fsck.hfs"
PARAMS = "-f"
elif TYPE == "UFS":
PROG = "fsck.ufs"
elif TYPE == "ZFS":
PROG = "fsck.zfs"
else:
ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk}, {int_nfilesys}")
return
# Error si el sistema de archivos esta montado o bloqueado.
ogUnmount(int_ndisk, int_nfilesys)
if ogIsMounted(int_ndisk, int_nfilesys):
ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys}")
return
if ogIsLocked(int_ndisk, int_nfilesys):
ogRaiseError(OG_ERR_LOCKED, f"{int_ndisk} {int_nfilesys}")
return
# Comprobar en modo uso exclusivo.
ogLock(int_ndisk, int_nfilesys)
try:
result = subprocess.run([PROG, PARAMS, PART], capture_output=True)
ERRCODE = result.returncode
except FileNotFoundError:
ogRaiseError(OG_ERR_NOTEXEC, PROG)
ERRCODE = OG_ERR_NOTEXEC
except:
ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys}")
ERRCODE = OG_ERR_PARTITION
ogUnlock(int_ndisk, int_nfilesys)
return ERRCODE
def ogExtendFs():
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 2 and sys.argv[1] == "help":
ogHelp("ogExtendFs", "ogExtendFs int_ndisk int_nfilesys", "ogExtendFs 1 1")
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(sys.argv[1]), int(sys.argv[2]))
if not PART:
return
# Redimensionar al tamaño máximo según el tipo de partición.
TYPE = ogGetFsType(int(sys.argv[1]), int(sys.argv[2]))
if TYPE == "EXT[234]":
PROG = "resize2fs"
PARAMS = "-f"
elif TYPE == "BTRFS":
PROG = "btrfs"
PARAMS = "filesystem resize max"
DOMOUNT = True # Debe estar montado.
elif TYPE == "REISERFS" or TYPE == "REISER4":
PROG = "resize_reiserfs"
PARAMS = "-f"
elif TYPE == "F2FS" or TYPE == "JFS" or TYPE == "NILFS2" or TYPE == "XFS" or TYPE == "EXFAT" or TYPE == "FAT32" or TYPE == "FAT16" or TYPE == "HFS" or TYPE == "HFSPLUS" or TYPE == "UFS":
return # No se reduce (por el momento).
elif TYPE == "NTFS":
PROG = "ntfsresize"
PARAMS = "<<<\"y\" -f"
else:
ogRaiseError(OG_ERR_PARTITION, f"{int(sys.argv[1])} {int(sys.argv[2])} {TYPE}")
return
# Salida normal si no se va a aplicar la operación.
if not PROG:
return
# Error si el sistema de archivos no se queda en el estado de montaje adecuado.
if DOMOUNT:
PART = ogMount(int(sys.argv[1]), int(sys.argv[2]))
if not PART:
return
else:
ogUnmount(int(sys.argv[1]), int(sys.argv[2]))
if ogIsMounted(int(sys.argv[1]), int(sys.argv[2])):
ogRaiseError(OG_ERR_PARTITION, f"{int(sys.argv[1])} {int(sys.argv[2])}")
return
# Error si el sistema de archivos está bloqueado.
if ogIsLocked(int(sys.argv[1]), int(sys.argv[2])):
ogRaiseError(OG_ERR_LOCKED, f"{int(sys.argv[1])} {int(sys.argv[2])}")
return
# Redimensionar en modo uso exclusivo.
ogLock(int(sys.argv[1]), int(sys.argv[2]))
try:
subprocess.run([PROG, PARAMS, PART], capture_output=True)
ERRCODE = 0
except FileNotFoundError:
ogRaiseError(OG_ERR_NOTEXEC, PROG)
ERRCODE = OG_ERR_NOTEXEC
except:
ogRaiseError(OG_ERR_PARTITION, f"{int(sys.argv[1])} {int(sys.argv[2])}")
ERRCODE = OG_ERR_PARTITION
ogUnlock(int(sys.argv[1]), int(sys.argv[2]))
return ERRCODE
def ogFormat(int_ndisk, int_nfilesys):
if int_nfilesys.lower() == "cache":
ogFormatCache()
else:
ogFormatFs(int_ndisk, int_nfilesys)
def ogFormatFs(int_ndisk, int_nfilesys, str_label=None):
# Si se solicita, mostrar ayuda.
if str_label == "help":
ogHelp("ogFormatFs", "ogFormatFs int_ndisk int_nfilesys [str_label]", "ogFormatFs 1 1", "ogFormatFs 1 1 EXT4", "ogFormatFs 1 1 \"DATA\"", "ogFormatFs 1 1 EXT4 \"DATA\"")
return
# Error si no se reciben entre 2 y 4 parámetros.
if not (2 <= len(sys.argv) <= 4):
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener fichero de dispositivo.
PART = ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
# Error si la partición está montada o bloqueada.
if ogIsMounted(int_ndisk, int_nfilesys):
ogRaiseError(OG_ERR_DONTFORMAT, f"{MSG_MOUNT}: {int_ndisk} {int_nfilesys}")
return
if ogIsLocked(int_ndisk, int_nfilesys):
ogRaiseError(OG_ERR_LOCKED, f"{int_ndisk} {int_nfilesys}")
return
# Si no se indica el tipo de sistema de archivos, intentar obtenerlo.
TYPE = ogGetFsType(int_ndisk, int_nfilesys)
if not TYPE:
TYPE = sys.argv[3]
# Error, si no especifica el tipo de sistema de archivos a formatear.
if not TYPE:
ogRaiseError(OG_ERR_FORMAT, f"{int_ndisk} {int_nfilesys} ...")
return
# Elegir tipo de formato.
if TYPE == "EXT2":
PROG = "mkfs.ext2"
PARAMS = "-F"
elif TYPE == "EXT3":
PROG = "mkfs.ext3"
PARAMS = "-F"
elif TYPE == "EXT4":
PROG = "mkfs.ext4"
PARAMS = "-F"
elif TYPE == "BTRFS":
PROG = "mkfs.btrfs"
PARAMS = "-f"
elif TYPE == "REISERFS":
PROG = "mkfs.reiserfs"
PARAMS = "-f"
LABELPARAM = "-l"
elif TYPE == "REISER4":
PROG = "mkfs.reiser4"
PARAMS = "-f <<<\"y\""
elif TYPE == "XFS":
PROG = "mkfs.xfs"
PARAMS = "-f"
elif TYPE == "JFS":
PROG = "mkfs.jfs"
PARAMS = "<<<\"y\""
elif TYPE == "F2FS":
PROG = "mkfs.f2fs"
LABELPARAM = "-l"
elif TYPE == "NILFS2":
PROG = "mkfs.nilfs2"
PARAMS = "-f"
elif TYPE == "LINUX-SWAP":
PROG = "mkswap"
elif TYPE == "NTFS":
PROG = "mkntfs"
PARAMS = "-f"
elif TYPE == "EXFAT":
PROG = "mkfs.exfat"
LABELPARAM = "-n"
elif TYPE == "FAT32":
PROG = "mkdosfs"
PARAMS = "-F 32"
LABELPARAM = "-n"
elif TYPE == "FAT16":
PROG = "mkdosfs"
PARAMS = "-F 16"
LABELPARAM = "-n"
elif TYPE == "FAT12":
PROG = "mkdosfs"
PARAMS = "-F 12"
LABELPARAM = "-n"
elif TYPE == "HFS":
PROG = "mkfs.hfs"
elif TYPE == "HFSPLUS":
PROG = "mkfs.hfsplus"
LABELPARAM = "-v"
elif TYPE == "UFS":
PROG = "mkfs.ufs"
PARAMS = "-O 2"
else:
ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys} {TYPE}")
return
# Etiquetas de particion.
if not str_label:
if sys.argv[4] == "CACHE":
ogRaiseError(OG_ERR_FORMAT, f"{MSG_RESERVEDVALUE}: CACHE")
return
if len(sys.argv) >= 4:
PARAMS = f"{PARAMS} {LABELPARAM or '-L'} {sys.argv[4]}"
else:
PARAMS = f"{PARAMS} {LABELPARAM or '-L'} {str_label}"
# Formatear en modo uso exclusivo (desmontar siempre).
ogLock(int_ndisk, int_nfilesys)
try:
subprocess.run([PROG, PARAMS, PART], capture_output=True)
ERRCODE = 0
except FileNotFoundError:
ogRaiseError(OG_ERR_NOTEXEC, PROG)
ERRCODE = OG_ERR_NOTEXEC
except:
ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk} {int_nfilesys}")
ERRCODE = OG_ERR_PARTITION
ogUnlock(int_ndisk, int_nfilesys)
return ERRCODE
def ogGetFsSize(int_ndisk, int_npartition, str_unit=None):
# Si se solicita, mostrar ayuda.
if str_unit == "help":
ogHelp("ogGetFsSize", "ogGetFsSize int_ndisk int_npartition [str_unit]", "ogGetFsSize 1 1", "ogGetFsSize 1 1 KB")
return
# Error si no se reciben 2 o 3 parámetros.
if not (2 <= len(sys.argv) <= 3):
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener unidad y factor de medida.
UNIT = str_unit or "KB"
FACTOR = 1
if UNIT.upper() == "MB":
FACTOR = 1024
elif UNIT.upper() == "GB":
FACTOR = 1024 * 1024
elif UNIT.upper() == "TB":
FACTOR = 1024 * 1024 * 1024
elif UNIT.upper() != "KB":
ogRaiseError(OG_ERR_FORMAT, f"{UNIT} != {{ KB, MB, GB, TB }}")
return
# Obtener el tamaño del sistema de archivo (si no está formateado; tamaño = 0).
MNTDIR = ogMount(int_ndisk, int_npartition)
if MNTDIR:
result = subprocess.run(["df", "-BK", MNTDIR], capture_output=True, text=True)
VALUE = result.stdout.split("\n")[1].split()[1]
SIZE = float(VALUE) / FACTOR
else:
SIZE = 0
# Devolver el tamaño (quitar decimales si son 0).
return int(SIZE) if SIZE.is_integer() else SIZE
def ogGetFsType(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogGetFsType", "ogGetFsType int_ndisk int_nfilesys", "ogGetFsType 1 1")
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
# Detectar tipo de sistema de archivo (independientemente del tipo de partición).
if PART.startswith("/"):
result = subprocess.run(["blkid", "-o", "export", PART], capture_output=True, text=True)
TYPE = ""
for line in result.stdout.split("\n"):
if line.startswith("TYPE="):
TYPE = line.split("=")[1].upper()
break
else:
subprocess.run(["zfs", "mount", PART], stderr=subprocess.DEVNULL)
result = subprocess.run(["mount"], capture_output=True, text=True)
TYPE = ""
for line in result.stdout.split("\n"):
if line.startswith(PART):
TYPE = line.split()[4].upper()
break
# Componer valores correctos.
if TYPE == "EXT4":
if f"{int_ndisk} {int_nfilesys}" == ogFindCache():
if ogIsFormated(int_ndisk, int_nfilesys):
TYPE = "CACHE"
elif TYPE == "VFAT":
result = subprocess.run(["blkid", "-po", "export", PART], capture_output=True, text=True)
for line in result.stdout.split("\n"):
if line.startswith("VERSION="):
TYPE = line.split("=")[1].upper()
break
elif TYPE == "SWAP":
TYPE = "LINUX-SWAP"
elif TYPE.startswith("LVM"):
TYPE = "LINUX-LVM"
elif "RAID" in TYPE:
TYPE = "LINUX-RAID"
elif TYPE == "ZFS_MEMBER":
TYPE = "ZVOL"
elif "_MEMBER" in TYPE:
TYPE = TYPE.replace("_MEMBER", "")
if 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:
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener partición.
PART = ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
# Devolver punto de montaje.
result = subprocess.run(["findmnt", "-n", "-o", "TARGET", PART], capture_output=True, text=True)
return result.stdout.strip()
def ogIsFormated(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogIsFormated", "ogIsFormated int_ndisk int_nfilesys", "ogIsFormated 1 1")
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
# Revisar tipo de sistema de archivos.
if PART.startswith("/"):
result = subprocess.run(["blkid", "-s", "TYPE", PART], capture_output=True, text=True)
return bool(result.stdout.strip())
else:
result = subprocess.run(["zfs", "list", "-Hp", "-o", "canmount", PART], capture_output=True, text=True)
return result.stdout.strip() == "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
# Obtener partición.
PART = ogDiskToDev(int_ndisk, int_npartition)
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('/', '-')}"
LOCKPART = f"/var/lock/lock{PART.replace('/', '-')}"
return os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART)
def ogIsMounted(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogIsMounted", "ogIsMounted int_ndisk int_nfilesys", "ogIsMounted 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener punto de montaje.
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
# Obtener partición.
PART = ogDiskToDev(int_ndisk, int_nfilesys)
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
def ogIsWritable(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogIsWritable", "ogIsWritable int_ndisk int_nfilesys", "ogIsWritable 1 1")
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 la partición está montada en modo de escritura.
result = subprocess.run(["findmnt", "-n", "-o", "OPTIONS", PART], capture_output=True, text=True)
options = result.stdout.strip().split(",")
return "rw" in options
def ogLock(int_ndisk, int_nfilesys):
ogLockPartition(int_ndisk, int_nfilesys)
def ogLockPartition(int_ndisk, int_npartition):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogLockPartition", "ogLockPartition int_ndisk int_npartition", "ogLockPartition 1 1")
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_npartition)
if not PART:
return
# Crear archivo de bloqueo exclusivo.
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)
def ogMountFirstFs(int_ndisk):
# Obtener número de particiones del disco.
NPARTS = ogGetPartitionsNumber(int_ndisk)
for PART in range(1, NPARTS + 1):
MNTDIR = ogMount(int_ndisk, PART)
if MNTDIR:
return MNTDIR
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")
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.
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:
pass
return MNTDIR
def ogMountCdrom():
DEV = "/dev/cdrom" # Por defecto
MNTDIR = subprocess.run(["mount", "-l", "-t", "iso9660", DEV], capture_output=True, text=True)
MNTDIR = MNTDIR.stdout.strip().split(" ")[2]
if not MNTDIR:
MNTDIR = DEV.replace("/dev", "/mnt")
os.makedirs(MNTDIR, exist_ok=True)
try:
subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_PARTITION, "cdrom")
return
return MNTDIR
def ogReduceFs(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogReduceFs", "ogReduceFs int_ndisk int_nfilesys", "ogReduceFs 1 1")
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
# Redimensionar según el tipo de partición.
TYPE = ogGetFsType(int_ndisk, int_nfilesys)
if TYPE == "EXT4":
ogUnmount(int_ndisk, int_nfilesys)
subprocess.run(["resize2fs", "-fpM", PART], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE == "BTRFS":
MNTDIR = ogMount(int_ndisk, int_nfilesys)
SIZE = subprocess.run(["btrfs", "filesystem", "show", MNTDIR], capture_output=True, text=True)
SIZE = SIZE.stdout.strip().split(" ")[6]
SIZE = int(float(SIZE) * 1.1 + 1)
subprocess.run(["btrfs", "filesystem", "resize", str(SIZE), MNTDIR], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE in ["REISERFS", "REISER4"]:
MNTDIR = ogMount(int_ndisk, int_nfilesys)
SIZE = int(subprocess.run(["df", "-k", MNTDIR], capture_output=True, text=True).stdout.strip().split("\n")[1].split()[2])
SIZE = SIZE * 110 // 100
ogUnmount(int_ndisk, int_nfilesys)
subprocess.run(["resize_reiserfs", "-s" + str(SIZE) + "K", PART], input="y\n", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE == "NTFS":
ogUnmount(int_ndisk, int_nfilesys)
MAXSIZE, SIZE = subprocess.run(["ntfsresize", "-fi", PART], capture_output=True, text=True)
MAXSIZE = MAXSIZE.strip().split(" ")[3]
SIZE = SIZE.strip().split(" ")[4]
SIZE = int(float(SIZE) * 1.1 / 1024 + 1) * 1024
RETVAL = 1
while RETVAL != 0 and SIZE + EXTRASIZE < MAXSIZE:
EXTRASIZE = subprocess.run(["ntfsresize", "-fns", str(SIZE), PART], capture_output=True, text=True)
EXTRASIZE = int(EXTRASIZE.stdout.strip()) if EXTRASIZE.stdout.strip() else 0
RETVAL = EXTRASIZE != 0
SIZE += EXTRASIZE
if SIZE < MAXSIZE:
subprocess.run(["ntfsresize", "-fs", str(SIZE), PART], input="y\n", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE in ["FAT32", "FAT16"]:
# No se reduce (por el momento).
pass
elif TYPE == "HFS" or TYPE == "HFSPLUS":
# No se reduce (por el momento).
pass
elif TYPE == "UFS":
# No se reduce (por el momento).
pass
else:
ogRaiseError(OG_ERR_PARTITION, f"{int_ndisk}, {int_nfilesys}")
# Devuelve tamaño del sistema de ficheros.
return ogGetFsSize(int_ndisk, int_nfilesys)
def ogUnlock(int_ndisk, int_npartition):
ogUnlockPartition(int_ndisk, int_npartition)
def ogUnlockPartition(int_ndisk, int_npartition):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogUnlockPartition", "ogUnlockPartition int_ndisk int_npartition", "ogUnlockPartition 1 1")
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_npartition)
if not PART:
return
# Borrar archivo de bloqueo exclusivo.
LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}"
os.remove(LOCKFILE)
def ogUnmount():
ogUnmountFs(*sys.argv[2:])
def ogUnmountFs(int_ndisk, int_npartition):
FUNCNAME = ogUnmountFs.__name__
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogUnmountFs", "ogUnmountFs int_ndisk int_npartition", "ogUnmountFs 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener partición y punto de montaje.
PART = ogDiskToDev(int_ndisk, int_npartition)
MNTDIR = ogGetMountPoint(int_ndisk, int_npartition)
# Si está montada, desmontarla.
if MNTDIR:
# Error si la particion está bloqueada.
if ogIsPartitionLocked(int_ndisk, int_npartition):
ogRaiseError(OG_ERR_LOCKED, f"{MSG_PARTITION}, {int_ndisk} {int_npartition}")
return
# Desmontar y borrar punto de montaje.
try:
subprocess.run(["umount", PART], check=True, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
ogEcho("warning", f"{FUNCNAME}: {MSG_DONTUNMOUNT}: \"{int_ndisk}, {int_npartition}\"")
try:
os.rmdir(MNTDIR)
except OSError:
os.remove(MNTDIR)
else:
ogEcho("warning", f"{MSG_DONTMOUNT}: \"{int_ndisk},{int_npartition}\"")
ogUnmountFs(int_ndisk, int_npartition)
def ogUnmountAll(int_ndisk):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogUnmountAll", "ogUnmountAll int_ndisk", "ogUnmountAll 1")
return
# Error si no se recibe 1 parámetro.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener partición y punto de montaje.
DISK = ogDiskToDev(int_ndisk)
for PART in range(1, ogGetPartitionsNumber(int_ndisk) + 1):
if ogGetFsType(int_ndisk, PART) != "CACHE":
ogUnmount(int_ndisk, PART)
def ogUnsetDirtyBit(int_ndisk, int_nfilesys):
# Si se solicita, mostrar ayuda.
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogUnsetDirtyBit", "ogUnsetDirtyBit int_ndisk int_nfilesys", "ogUnsetDirtyBit 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener partición y punto de montaje.
PART = ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
# Realizar acciones específicas según el tipo de sistema de archivos.
TYPE = ogGetFsType(int_ndisk, int_nfilesys)
if TYPE == "NTFS":
ogUnmount(int_ndisk, int_nfilesys)
subprocess.run(["ntfsfix", "-d", PART], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
else:
pass # Add more specific actions for other file systems if needed.
def ogGetFreeSize(int_ndisk, int_npartition, str_SizeOutput):
if len(sys.argv) == 3 and sys.argv[2] == "help":
ogHelp("ogGetFreeSize", "ogGetFreeSize int_ndisk int_npartition str_SizeOutput", "ogGetFreeSize 1 1 GB")
return
if len(sys.argv) < 3:
ogRaiseError(OG_ERR_FORMAT)
return
PART = ogDiskToDev(int_ndisk, int_npartition)
if not PART:
return
unit = str_SizeOutput
if not unit:
unit = "GB"
factor = 1.024 / 1000000
if unit == "kB":
factor = 1.024
elif unit == "MB":
factor = 1.024 / 1000
result = subprocess.run(["df", PART], capture_output=True, text=True)
output = result.stdout.strip().split("\n")[1].split()
size = float(output[1]) * factor
used = float(output[2]) * factor
free = float(output[3]) * factor
return free

989
client/engine/ImageLib.py Normal file
View File

@ -0,0 +1,989 @@
import subprocess
from engine.DiskLib import *
from engine.FileLib import *
from engine.NetLib import *
def ogCreateImageSyntax(*args):
FUNCNAME=ogCreateImageSyntax.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} path_device path_imagefile [str_tool] [str_compressionlevel]",
f"{FUNCNAME} /dev/sda1 /opt/opengnsys/images/prueba.img partclone lzop",
f"{FUNCNAME} /dev/sda1 /opt/opengnsys/images/prueba.img")
return
# Error si no se reciben entre 2 y 4 parámetros.
if not (2 <= len(args) <= 4):
ogRaiseError(OG_ERR_FORMAT, " ".join(args))
return
# Asignación de parámetros.
DEV = args[0]
IMGFILE = args[1]
if len(args) == 2:
# Sintaxis por defecto OG DEV IMGFILE
TOOL = "partclone"
LEVEL = "gzip"
elif len(args) == 4:
# Sintaxis condicionada.
TOOL = args[2].lower()
LEVEL = args[3].lower()
if TOOL == "ntfsclone":
PARAM1 = f"ntfsclone --force --save-image -O - {DEV}"
elif TOOL in ["partimage", "default"]:
PARAM1 = f"partimage -M -f3 -o -d -B gui=no -c -z0 --volume=0 save {DEV} stdout"
elif TOOL == "partclone":
FS = ogGetFsType(ogDevToDisk(DEV))
if FS == "EXT[234]":
PARAM1 = "partclone.extfs"
elif FS == "BTRFS":
PARAM1 = "partclone.btrfs"
elif FS == "REISERFS":
PARAM1 = "partclone.reiserfs"
elif FS == "REISER4":
PARAM1 = "partclone.reiser4"
elif FS == "JFS":
PARAM1 = "partclone.jfs"
elif FS == "XFS":
PARAM1 = "partclone.xfs"
elif FS == "F2FS":
PARAM1 = "partclone.f2fs"
elif FS == "NILFS2":
PARAM1 = "partclone.nilfs2"
elif FS == "NTFS":
PARAM1 = "partclone.ntfs"
elif FS == "EXFAT":
PARAM1 = "partclone.exfat"
elif FS in ["FAT16", "FAT32"]:
PARAM1 = "partclone.fat"
elif FS in ["HFS", "HFSPLUS"]:
PARAM1 = "partclone.hfsp"
elif FS == "UFS":
PARAM1 = "partclone.ufs"
elif FS == "VMFS":
PARAM1 = "partclone.vmfs"
else:
PARAM1 = "partclone.imager"
# Por compatibilidad, si no existe el ejecutable usar por defecto "parclone.dd".
if not subprocess.run(["which", PARAM1], capture_output=True).returncode:
PARAM1 = "partclone.dd"
PARAM1 = f"{PARAM1} -d0 -F -c -s {DEV}"
# Algunas versiones de partclone.dd no tienen opción "-c".
if "-c" not in subprocess.run([PARAM1.split()[0], "--help"], capture_output=True).stdout.decode():
PARAM1 = PARAM1.replace(" -c ", " ")
# Comprobar que existe mbuffer.
if not subprocess.run(["which", "mbuffer"], capture_output=True).returncode:
PARAM2 = "| mbuffer -q -m 40M "
else:
PARAM2 = " "
# Nivel de compresion.
if LEVEL in ["0", "none"]:
PARAM3 = " > "
elif LEVEL in ["1", "lzop"]:
PARAM3 = " | lzop > "
elif LEVEL in ["2", "gzip"]:
PARAM3 = " | gzip -c > "
elif LEVEL in ["3", "bzip"]:
PARAM3 = " | bzip -c > "
# Sintaxis final.
if PARAM1:
return f"{PARAM1} {PARAM2} {PARAM3} {IMGFILE}"
return ogCreateImageSyntax
def ogRestoreImageSyntax(*args):
FUNCNAME=ogRestoreImageSyntax.__name__
TOOL = ""
COMPRESSOR = ""
LEVEL = ""
PART = ""
IMGFILE = ""
FILEHEAD = ""
INFOIMG = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} filename partition [tool] [levelcompresor]",
f"{FUNCNAME} /opt/opengnsys/images/prueba.img /dev/sda1 [partclone] [lzop]")
return
# Error si no se reciben entre 2 y 4 parámetros.
if not (2 <= len(args) <= 4):
ogRaiseError(OG_ERR_FORMAT, " ".join(args))
return
# controlamos que el parametro 1 (imagen) es tipo file.
if not os.path.isfile(args[0]):
ogRaiseError(OG_ERR_NOTFOUND, args[0])
return
# Si 2 parametros (file-origen-, device-destino-) = ogGetImageFull($1)
if len(args) == 2:
IMGFILE = args[0]
PART = args[1]
INFOIMG = ogGetImageInfo(IMGFILE)
if INFOIMG:
TOOL = INFOIMG.split(":")[0]
COMPRESSOR = INFOIMG.split(":")[1]
return ogRestoreImageSyntax(IMGFILE, PART, TOOL, COMPRESSOR)
# Si cuatro parametros genera sintaxis
if len(args) == 4:
IMGFILE = args[0]
PART = args[1]
# comprobamos parametro herramienta compresion.
TOOL = args[2].lower()
# comprobar parámetro compresor.
LEVEL = args[3].lower()
if LEVEL in ["0", "none"]:
COMPRESSOR = " "
elif LEVEL in ["1", "lzop"]:
COMPRESSOR = " lzop -dc "
elif LEVEL in ["2", "gzip"]:
COMPRESSOR = " gzip -dc "
elif LEVEL in ["3", "bzip"]:
COMPRESSOR = " bzip -dc "
else:
ogRaiseError(OG_ERR_NOTFOUND, f"Compressor no valid {TOOL}")
return
# comprobar mbuffer
if shutil.which("mbuffer"):
MBUFFER = "| mbuffer -q -m 40M "
else:
MBUFFER = " "
if TOOL == "ntfsclone":
TOOL = f"| ntfsclone --restore-image --overwrite {PART} -"
elif TOOL == "partimage":
TOOL = f"| partimage -f3 -B gui=no restore {PART} stdin"
elif TOOL.startswith("partclone"):
TOOL = f"| partclone.restore -d0 -C -I -o {PART}"
elif TOOL == "dd":
TOOL = f"| pv | dd conv=sync,noerror bs=1M of={PART}"
else:
ogRaiseError(OG_ERR_NOTFOUND, f"Tools imaging no valid {TOOL}")
return
return f"{COMPRESSOR} {IMGFILE} {MBUFFER} {TOOL}"
def ogCreateDiskImage(*args):
FUNCNAME = ogCreateDiskImage.__name__
# Variables locales
DISK = ""
PROGRAM = ""
IMGDIR = ""
IMGFILE = ""
IMGTYPE = ""
ERRCODE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk str_repo path_image",
f"{FUNCNAME} 1 REPO /disk1")
return
# Error si no se reciben entre 3 y 5 parámetros.
if not (3 <= len(args) <= 5):
ogRaiseError(OG_ERR_FORMAT, " ".join(args))
return
# Comprobar que no está bloqueada ni la partición, ni la imagen.
DISK = ogDiskToDev(args[0])
if ogIsDiskLocked(args[0]):
ogRaiseError(OG_ERR_LOCKED, f"{MSG_LOCKED} {args[0]}")
return
IMGTYPE = "dsk" # Extensión genérica de imágenes de disco.
IMGDIR = ogGetParentPath(args[1], args[2])
if not IMGDIR:
ogRaiseError(OG_ERR_NOTFOUND, f"{args[1]} {os.path.dirname(args[2])}")
return
IMGFILE = f"{IMGDIR}/{os.path.basename(args[2])}.{IMGTYPE}"
if ogIsImageLocked(IMGFILE):
ogRaiseError(OG_ERR_LOCKED, f"{MSG_IMAGE} {args[2]}, {args[3]}")
return
# No guardar imagen en el propio disco (disco no incluido en el camino del repositorio).
if ogGetPath(args[1], "/").startswith(DISK):
ogRaiseError(OG_ERR_IMAGE, f"{args[1]} = {DISK}")
return
# Generar la instruccion a ejecutar antes de aplicar los bloqueos.
PROGRAM = ogCreateImageSyntax(DISK, IMGFILE)
# Desmontar todos los sistemas de archivos del disco, bloquear disco e imagen.
ogUnmountAll(args[0])
ogLockDisk(args[0])
ogLockImage(args[1], f"{args[2]}.{IMGTYPE}")
# Crear Imagen.
try:
with open(IMGFILE + ".info", "w") as info_file:
subprocess.run(PROGRAM, shell=True, check=True)
info_file.write(f"{ogGetImageInfo(IMGFILE)}:{ogGetHostname()}")
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {args[1]} {IMGFILE}")
os.remove(IMGFILE)
return ERRCODE
# Desbloquear disco e imagen.
ogUnlockDisk(args[0])
ogUnlockImage(args[1], f"{args[2]}.{IMGTYPE}")
return ERRCODE
def ogCreateImage(*args):
FUNCNAME = ogCreateImage.__name__
# Variables locales
PART = ""
PROGRAM = ""
IMGDIR = ""
IMGFILE = ""
IMGTYPE = ""
ERRCODE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_npart str_repo path_image",
f"{FUNCNAME} 1 1 REPO /aula1/win7")
return
# Error si no se reciben entre 4 y 6 parámetros.
if not (4 <= len(args) <= 6):
ogRaiseError(OG_ERR_FORMAT, " ".join(args))
return
# Comprobar que no está bloqueada ni la partición, ni la imagen.
PART = ogDiskToDev(args[0], args[1])
if ogIsLocked(args[0], args[1]):
ogRaiseError(OG_ERR_LOCKED, f"{MSG_LOCKED} {args[0]}, {args[1]}")
return
IMGTYPE = "img" # Extensión genérica de imágenes.
IMGDIR = ogGetParentPath(args[2], args[3])
if not IMGDIR:
ogRaiseError(OG_ERR_NOTFOUND, f"{args[2]} {os.path.dirname(args[3])}")
return
IMGFILE = f"{IMGDIR}/{os.path.basename(args[3])}.{IMGTYPE}"
if ogIsImageLocked(IMGFILE):
ogRaiseError(OG_ERR_LOCKED, f"{MSG_IMAGE} {args[2]}, {args[3]}")
return
# Generar la instruccion a ejecutar antes de aplicar los bloqueos.
PROGRAM = ogCreateImageSyntax(PART, IMGFILE, *args[4:])
# Desmontar partición, bloquear partición e imagen.
ogUnmount(args[0], args[1])
ogLock(args[0], args[1])
# Crear Imagen.
try:
with open(f"{IMGFILE}.info", "w") as info_file:
subprocess.run(PROGRAM, shell=True, check=True)
info_file.write(f"{ogGetImageInfo(IMGFILE)}:{ogGetHostname()}")
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {args[1]} {IMGFILE}")
os.remove(IMGFILE)
return ERRCODE
# Desbloquear partición e imagen.
ogUnlock(args[0], args[1])
ogUnlockImage(args[2], f"{args[3]}.{IMGTYPE}")
return ERRCODE
def ogCreateMbrImage(*args):
FUNCNAME = ogCreateMbrImage.__name__
# Variables locales
DISK = ""
IMGDIR = ""
IMGFILE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk str_repo path_image",
f"{FUNCNAME} 1 REPO /aula1/mbr")
return
# Error si no se reciben 3 parámetros.
if len(args) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
DISK = ogDiskToDev(args[0])
if not DISK:
ogRaiseError(OG_ERR_NOTFOUND, args[0])
return
IMGDIR = ogGetParentPath(args[1], args[2])
if not IMGDIR:
ogRaiseError(OG_ERR_NOTFOUND, f"{args[1]} {os.path.dirname(args[2])}")
return
IMGFILE = f"{IMGDIR}/{os.path.basename(args[2])}.mbr"
# Crear imagen del MBR.
try:
subprocess.run(["dd", f"if={DISK}", f"of={IMGFILE}", "bs=512", "count=1"], check=True)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {IMGFILE}")
return
return
def ogCreateBootLoaderImage(*args):
FUNCNAME = ogCreateBootLoaderImage.__name__
# Variables locales
DISK = ""
IMGDIR = ""
IMGFILE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk str_repo path_image",
f"{FUNCNAME} 1 REPO /aula1/mbr")
return
# Error si no se reciben 3 parámetros.
if len(args) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
DISK = ogDiskToDev(args[0])
if not DISK:
ogRaiseError(OG_ERR_NOTFOUND, args[0])
return
IMGDIR = ogGetParentPath(args[1], args[2])
if not IMGDIR:
ogRaiseError(OG_ERR_NOTFOUND, f"{args[1]} {os.path.dirname(args[2])}")
return
IMGFILE = f"{IMGDIR}/{os.path.basename(args[2])}.mbr"
# Crear imagen del Boot Loader dentro del MBR.
try:
subprocess.run(["dd", f"if={DISK}", f"of={IMGFILE}", "bs=446", "count=1"], check=True)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {IMGFILE}")
return
return
def ogGetSizeParameters(*args):
FUNCNAME = ogGetSizeParameters.__name__
# Variables locales
REPO = ""
MNTDIR = ""
SIZEDATA = ""
KERNELVERSION = ""
SIZEREQUIRED = ""
FACTORGZIP = ""
FACTORLZOP = ""
FACTORSYNC = ""
SIZEFREE = ""
IMGTYPE = ""
IMGDIR = ""
IMGFILE = ""
IMGEXT = ""
IMGSIZE = ""
ISENOUGHSPACE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part str_repo path_imgname [monolit|sync|diff]",
f"if {FUNCNAME} 1 2 REPO Windows10 sync ; then ...; fi",
f"if {FUNCNAME} 1 6 Ubuntu16 CACHE ; then ...; fi")
return
# Error si no se reciben 1 o 2 parámetros.
if len(args) < 4:
return ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: {PROG} ndisco nparticion REPO|CACHE imgname [monolit|sync|diff]")
# Recogemos parametros
REPO = args[2].upper()
IMGTYPE = f"_{args[4].upper()}_"
MNTDIR = ogMount(args[0], args[1])
if not MNTDIR:
return ogRaiseError(OG_ERR_PARTITION, f"{args[0]} {args[1]}")
# Datos contenidos en la particion o en la lista de archivos de contiene la diferencial.
if IMGTYPE == "_DIFF_":
if not os.path.isfile("/tmp/ogimg.info"):
return ogRaiseError(OG_ERR_NOTFOUND, "/tmp/ogimg.info")
os.chdir(MNTDIR)
with open("/tmp/ogimg.info", "r") as info_file:
lines = info_file.readlines()
lines = [line.strip() for line in lines if line.strip() != "/"]
SIZEDATA = sum([os.path.getsize(line) for line in lines])
os.chdir("/")
else:
df_output = subprocess.run(["df", "-k"], capture_output=True, text=True).stdout
df_lines = df_output.split("\n")
for line in df_lines:
if line.endswith(MNTDIR):
SIZEDATA = line.split()[2]
break
# Aplicar factor de compresion
if IMGTYPE == "_SYNC_" or IMGTYPE == "_DIFF_":
# Sistema de fichero de la imagen según kernel, menor que 3.7 EXT4. comparamos revision
KERNELVERSION = os.uname().release
KERNELVERSION = float(KERNELVERSION.split("-")[0])
IMGFS = "EXT4" if KERNELVERSION < 3.07 else "BTRFS"
FACTORSYNC = 130
# Si IMGFS="BTRFS" la compresion es mayor.
if IMGFS == "BTRFS":
FACTORSYNC -= 20
SIZEREQUIRED = SIZEDATA * FACTORSYNC // 100
# El tamaño mínimo del sistema de ficheros btrfs es 250M, ponemos 300
if SIZEREQUIRED < 300000:
SIZEREQUIRED = 300000
else:
FACTORGZIP = 55 / 100
FACTORLZOP = 65 / 100
SIZEREQUIRED = SIZEDATA * FACTORLZOP
# Comprobar espacio libre en el contenedor.
if REPO == "CACHE":
SIZEFREE = ogGetFreeSize(ogFindCache())
elif REPO == "REPO":
df_output = subprocess.run(["df", "-k"], capture_output=True, text=True).stdout
df_lines = df_output.split("\n")
for line in df_lines:
if line.endswith(OGIMG):
SIZEFREE = line.split()[3]
break
# Comprobamos si existe una imagen con el mismo nombre en $REPO
# En sincronizadas restamos tamaño de la imagen y en monoloticas de la .ant
if IMGTYPE == "_DIFF_":
IMGEXT = "img.diff"
elif IMGTYPE == "_SYNC_":
IMGEXT = "img"
else:
IMGEXT = "img.ant"
IMGDIR = ogGetParentPath(REPO, f"/{args[3]}")
IMGFILE = ogGetPath(f"{IMGDIR}/{os.path.basename(f'/{args[3]}')}.{IMGEXT}")
if IMGFILE == "":
IMGSIZE = 0
else:
IMGSIZE = os.path.getsize(IMGFILE)
SIZEFREE += IMGSIZE
ISENOUGHSPACE = "TRUE" if SIZEREQUIRED < SIZEFREE else "FALSE"
return f"{SIZEDATA} {SIZEREQUIRED} {SIZEFREE} {ISENOUGHSPACE}"
def ogIsImageLocked(*args):
FUNCNAME = ogIsImageLocked.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} [str_repo] path_image",
f"if {FUNCNAME} /opt/opengnsys/images/aula1/win7.img; then ...; fi",
f"if {FUNCNAME} REPO /aula1/win7.img; then ...; fi")
return
# Error si no se reciben 1 o 2 parámetros.
if len(args) < 1 or len(args) > 2:
return 1
# Comprobar si existe el fichero de bloqueo.
if ogGetPath(*args) + ".lock":
return True
else:
return False
def ogLockImage(*args):
FUNCNAME = ogLockImage.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} [str_repo] path_image",
f"if {FUNCNAME} /opt/opengnsys/images/aula1/win7.img; then ...; fi",
f"if {FUNCNAME} REPO /aula1/win7.img; then ...; fi")
return
# Error si no se reciben 1 o 2 parámetros.
if len(args) < 1 or len(args) > 2:
return 1
# Comprobar que existe directorio de imagen
IMGDIR = ogGetParentPath(*args)
if not IMGDIR:
return
# Crear fichero de bloqueo.
try:
with open(f"{IMGDIR}/{os.path.basename(args[-1])}.lock", "w") as lock_file:
pass
except IOError:
ogRaiseError(OG_ERR_NOTWRITE, " ".join(args))
return
return
def ogRestoreDiskImage(*args):
FUNCNAME = ogRestoreDiskImage.__name__
# Variables locales
DISK = ""
DISKSIZE = ""
IMGFILE = ""
IMGTYPE = ""
IMGSIZE = ""
PROGRAM = ""
ERRCODE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image int_ndisk",
f"{FUNCNAME} REPO /aula1/win7 1")
return
# Error si no se reciben 3 parámetros.
if len(args) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Procesar parámetros.
DISK = ogDiskToDev(args[2])
if not DISK:
return ogRaiseError(OG_ERR_NOTFOUND, f" {args[2]} {args[3]}")
IMGTYPE = "dsk"
IMGFILE = ogGetPath(args[0], f"{args[1]}.{IMGTYPE}")
if not os.path.isfile(IMGFILE):
return ogRaiseError(OG_ERR_NOTFOUND, f" {args[2]} {args[3]}")
# comprobamos consistencia de la imagen
if not ogGetImageInfo(IMGFILE):
return ogRaiseError(OG_ERR_IMAGE, f" {args[0]} {args[1]}")
#/* (Comienzo comentario Doxygen)
# Error si la imagen no cabe en la particion.
#IMGSIZE=$(ogGetImageSize "$1" "$2") || return $(ogRaiseError $OG_ERR_IMAGE " $1 $2"; echo $?)
#DISKSIZE=$(ogGetDiskSize $3)
#if [ $IMGSIZE -gt $DISKSIZE ]; then
# ogRaiseError $OG_ERR_IMGSIZEPARTITION "$DISKSIZE < $IMGSIZE"
# return $?
#fi
#*/ (Fin comentario Doxygen)
# Comprobar el bloqueo de la imagen y de la partición.
if ogIsImageLocked(IMGFILE):
return ogRaiseError(OG_ERR_LOCKED, f"{MSG_IMAGE} {args[0]}, {args[1]}.{IMGTYPE}")
if ogIsDiskLocked(args[2]):
return ogRaiseError(OG_ERR_LOCKED, f"{MSG_DISK} {args[2]}")
# Solicitamos la generación de la instruccion a ejecutar
PROGRAM = ogRestoreImageSyntax(IMGFILE, DISK)
# Bloquear el disco
ogLockDisk(args[2])
try:
# Ejecutar restauración según el tipo de imagen.
subprocess.run(PROGRAM, shell=True, check=True)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{IMGFILE}, {args[2]}, {args[3]}")
ERRCODE = 1
ogUnlockDisk(args[2], args[3])
return ERRCODE
def ogRestoreImage(*args):
FUNCNAME = ogRestoreImage.__name
# Variables locales
PART = ""
PARTSIZE = ""
IMGFILE = ""
IMGTYPE = ""
IMGSIZE = ""
PROGRAM = ""
ERRCODE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image int_ndisk int_npart",
f"{FUNCNAME} REPO /aula1/win7 1 1")
return
# Error si no se reciben 4 parámetros.
if len(args) != 4:
ogRaiseError(OG_ERR_FORMAT)
return
# Procesar parámetros.
PART = ogDiskToDev(args[2], args[3])
if not PART:
return ogRaiseError(OG_ERR_NOTFOUND, f" {args[2]} {args[3]}")
IMGTYPE = "img"
IMGFILE = ogGetPath(args[0], f"{args[1]}.{IMGTYPE}")
if not os.path.isfile(IMGFILE):
return ogRaiseError(OG_ERR_NOTFOUND, f" {args[2]} {args[3]}")
# comprobamos consistencia de la imagen
if not ogGetImageInfo(IMGFILE):
return ogRaiseError(OG_ERR_IMAGE, f" {args[0]} {args[1]}")
# Error si la imagen no cabe en la particion.
IMGSIZE = ogGetImageSize(args[0], args[1])
PARTSIZE = ogGetPartitionSize(args[2], args[3])
if IMGSIZE > PARTSIZE:
ogRaiseError(OG_ERR_IMGSIZEPARTITION, f" {PARTSIZE} < {IMGSIZE}")
return
# Comprobar el bloqueo de la imagen y de la partición.
if ogIsImageLocked(IMGFILE):
return ogRaiseError(OG_ERR_LOCKED, f"{MSG_IMAGE} {args[0]}, {args[1]}.{IMGTYPE}")
if ogIsLocked(args[2], args[3]):
return ogRaiseError(OG_ERR_LOCKED, f"{MSG_PARTITION} {args[2]}, {args[3]}")
# Solicitamos la generación de la instruccion a ejecutar
PROGRAM = ogRestoreImageSyntax(IMGFILE, PART)
# Desmontar y bloquear partición.
ogUnmount(args[2], args[3])
ogLock(args[2], args[3])
try:
# Ejecutar restauración según el tipo de imagen.
subprocess.run(PROGRAM, shell=True, check=True)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{IMGFILE}, {args[2]}, {args[3]}")
ERRCODE = 1
ogUnlock(args[2], args[3])
return ERRCODE
def ogRestoreMbrImage(*args):
FUNCNAME = ogRestoreMbrImage.__name__
# Variables locales
DISK = ""
IMGFILE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image int_ndisk",
f"{FUNCNAME} REPO /aula1/mbr 1")
return
# Error si no se reciben 3 parámetros.
if len(args) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Procesar parámetros.
DISK = ogDiskToDev(args[2])
if not DISK:
return ogRaiseError(OG_ERR_NOTFOUND, args[2])
IMGFILE = ogGetPath(args[0], f"{args[1]}.mbr")
if not os.path.isfile(IMGFILE):
return ogRaiseError(OG_ERR_NOTFOUND, IMGFILE)
# Restaurar imagen del MBR.
try:
subprocess.run(["dd", f"if={IMGFILE}", f"of={DISK}", "bs=512", "count=1"], check=True)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {IMGFILE}")
return
return
def ogRestoreBootLoaderImage(*args):
FUNCNAME = ogRestoreBootLoaderImage.__name__
# Variables locales
DISK = ""
IMGFILE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image int_ndisk",
f"{FUNCNAME} REPO /aula1/mbr 1")
return
# Error si no se reciben 3 parámetros.
if len(args) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Procesar parámetros.
DISK = ogDiskToDev(args[2])
if not DISK:
return ogRaiseError(OG_ERR_NOTFOUND, args[2])
IMGFILE = ogGetPath(args[0], f"{args[1]}.mbr")
if not os.path.isfile(IMGFILE):
return ogRaiseError(OG_ERR_NOTFOUND, IMGFILE)
# Restaurar imagen del MBR.
try:
subprocess.run(["dd", f"if={IMGFILE}", f"of={DISK}", "bs=446", "count=1"], check=True)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {IMGFILE}")
return
return
def ogUnlockImage(*args):
FUNCNAME = ogUnlockImage.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} [str_repo] path_image",
f"if {FUNCNAME} /opt/opengnsys/images/aula1/win7.img; then ...; fi",
f"if {FUNCNAME} REPO /aula1/win7.img; then ...; fi")
return
# Error si no se reciben 1 o 2 parámetros.
if len(args) < 1 or len(args) > 2:
return 1
# Borrar fichero de bloqueo para la imagen.
lock_file = f"{ogGetPath(*args)}.lock"
os.remove(lock_file)
return
def ogGetImageInfo(*args):
FUNCNAME = ogGetImageInfo.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} path_filename",
f"{FUNCNAME} /opt/opengnsys/images/prueba.img ==> PARTCLONE:LZOP:NTFS:5642158")
return
# Error si no se recibe 1 parámetro.
if len(args) != 1:
ogRaiseError(OG_ERR_FORMAT)
return
# Comprobando que el parámetro uno es un archivo.
if not os.path.isfile(args[0]):
ogRaiseError(OG_ERR_NOTFOUND, args[0])
return
IMGDETECT = "FALSE"
IMGFILE = args[0]
FILEHEAD = f"/tmp/{os.path.basename(IMGFILE)}.infohead"
COMPRESSOR = subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.split()[1]
if not ogCheckStringInGroup(COMPRESSOR, "gzip lzop"):
ogRaiseError(OG_ERR_IMAGE, f"Image format is not valid {IMGFILE}")
return
try:
with open(FILEHEAD, "w") as filehead:
subprocess.run([COMPRESSOR, "-dc", IMGFILE], stdout=filehead, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
ogRaiseError(OG_ERR_IMAGE, f"Image format is not valid {IMGFILE}")
return
# Buscando Primera opción.
if IMGDETECT == "FALSE":
PARTCLONEINFO = subprocess.run(["partclone.info", FILEHEAD], capture_output=True, text=True).stdout
if "size" in PARTCLONEINFO:
TOOLS = "PARTCLONE"
FS = PARTCLONEINFO.split(": ")[7].upper()
if FS in ["HFS", "HFSPLUS", "FAT32"]:
FSPLUS = PARTCLONEINFO.split(": ")[8].upper()
SIZEFACTOR = 1000000 if "GB" in PARTCLONEINFO else 1024
if FSPLUS == "PLUS":
FS = FS + FSPLUS
SIZE = int(PARTCLONEINFO.split(": ")[16]) * SIZEFACTOR
else:
SIZE = int(PARTCLONEINFO.split(": ")[15]) * SIZEFACTOR
else:
SIZEFACTOR = 1000000 if "GB" in PARTCLONEINFO else 1024
SIZE = int(PARTCLONEINFO.split(": ")[10]) * SIZEFACTOR
IMGDETECT = "TRUE"
# Buscando segunda opción.
if IMGDETECT == "FALSE" and not os.path.exists("/dev/loop2"):
if "ntfsclone-image" in open(FILEHEAD).read():
NTFSCLONEINFO = subprocess.run(["ntfsclone", "--restore", "--overwrite", "/dev/loop2", "-"], input=open(FILEHEAD).read(), capture_output=True, text=True).stdout
if "ntfsclone" in NTFSCLONEINFO:
TOOLS = "NTFSCLONE"
SIZE = int(NTFSCLONEINFO.split("(")[1].split(".")[0]) // 1000
FS = "NTFS"
IMGDETECT = "TRUE"
# Buscando Tercer opción.
if IMGDETECT == "FALSE":
PARTIMAGEINFO = subprocess.run(["partimage", "-B", "gui=no", "imginfo", FILEHEAD], capture_output=True, text=True).stdout
if "Partition" in PARTIMAGEINFO:
TOOLS = "PARTIMAGE"
FS = PARTIMAGEINFO.split()[16].upper()
SIZE = int(PARTIMAGEINFO.split()[35]) * 1024 * 1024
IMGDETECT = "TRUE"
if "boot sector" in subprocess.run(["file", FILEHEAD], capture_output=True, text=True).stdout:
TOOLS = "partclone.dd"
FS = ""
SIZE = ""
IMGDETECT = "TRUE"
# Comprobamos valores
if not TOOLS or not COMPRESSOR or IMGDETECT == "FALSE":
ogRaiseError(OG_ERR_IMAGE, f"Image format is not valid {IMGFILE}")
return
else:
COMPRESSOR = COMPRESSOR.upper()
return f"{TOOLS}:{COMPRESSOR}:{FS}:{SIZE}"
def ogGetImageProgram(*args):
FUNCNAME = ogGetImageProgram.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
return ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image",
f"{FUNCNAME} REPO prueba ==> PARTCLONE")
# Error si no se reciben 2 parámetros.
if len(args) != 2:
return ogRaiseError(OG_ERR_FORMAT)
IMGFILE = ogGetPath(args[0], f"{args[1]}.img")
if not os.path.isfile(IMGFILE):
return ogRaiseError(OG_ERR_NOTFOUND, IMGFILE)
return ogGetImageInfo(IMGFILE).split(":")[0]
def ogGetImageCompressor(*args):
FUNCNAME = ogGetImageCompressor.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image",
f"{FUNCNAME} REPO prueba ==> LZOP")
return
# Error si no se reciben 2 parámetros.
if len(args) != 2:
ogRaiseError(OG_ERR_FORMAT)
return
IMGFILE = ogGetPath(args[0], f"{args[1]}.img")
if not os.path.isfile(IMGFILE):
ogRaiseError(OG_ERR_NOTFOUND, IMGFILE)
return
return ogGetImageInfo(IMGFILE).split(":")[1]
def ogGetImageType(*args):
FUNCNAME = ogGetImageType.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image",
f"{FUNCNAME} REPO prueba ==> NTFS")
return
# Error si no se reciben 2 parámetros.
if len(args) != 2:
ogRaiseError(OG_ERR_FORMAT)
return
IMGFILE = ogGetPath(args[0], f"{args[1]}.img")
if not os.path.isfile(IMGFILE):
ogRaiseError(OG_ERR_NOTFOUND, IMGFILE)
return
return ogGetImageInfo(IMGFILE).split(":")[2]
def ogGetImageSize(*args):
FUNCNAME = ogGetImageSize.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} str_repo path_image",
f"{FUNCNAME} REPO prueba ==> 5642158")
return
# Error si no se reciben 2 parámetros.
if len(args) != 2:
ogRaiseError(OG_ERR_FORMAT)
return
IMGFILE = ogGetPath(args[0], f"{args[1]}.img")
if not os.path.isfile(IMGFILE):
ogRaiseError(OG_ERR_NOTFOUND, IMGFILE)
return
return ogGetImageInfo(IMGFILE).split(":")[3]
def ogCreateGptImage(*args):
FUNCNAME = ogCreateGptImage.__name__
# Variables locales
DISK = ""
IMGDIR = ""
IMGFILE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk path_dir str_image",
f"{FUNCNAME} 1 REPO /aula1/gpt")
return
# Error si no se reciben 3 parámetros.
if len(args) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
DISK = ogDiskToDev(args[0])
if not DISK:
return ogRaiseError(OG_ERR_NOTFOUND, args[0])
IMGDIR = ogGetParentPath(args[1], args[2])
if not IMGDIR:
return ogRaiseError(OG_ERR_NOTFOUND, f"{args[1]} {os.path.dirname(args[2])}")
IMGFILE = f"{IMGDIR}/{os.path.basename(args[2])}.gpt"
# Crear imagen de la tabla GPT.
try:
subprocess.run(["sgdisk", f"-b={IMGFILE}", DISK], check=True)
except subprocess.CalledProcessError:
return ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {IMGFILE}")
return
def ogRestoreGptImage(*args):
FUNCNAME = ogRestoreGptImage.__name__
# Variables locales
DISK = ""
IMGFILE = ""
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} path_dir str_image int_ndisk",
f"{FUNCNAME} REPO /aula1/gpt 1")
return
# Error si no se reciben 3 parámetros.
if len(args) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
DISK = ogDiskToDev(args[2])
if not DISK:
return ogRaiseError(OG_ERR_NOTFOUND, args[2])
IMGFILE = ogGetPath(args[0], f"{args[1]}.gpt")
if not os.path.isfile(IMGFILE):
return ogRaiseError(OG_ERR_NOTFOUND, IMGFILE)
# Restaurar tabla GPT del disco.
try:
subprocess.run(["sgdisk", f"-l={IMGFILE}", DISK], check=True)
except subprocess.CalledProcessError:
return ogRaiseError(OG_ERR_IMAGE, f"{args[0]} {IMGFILE}")
return

View File

@ -0,0 +1,445 @@
import glob
import platform
import sys
import os
import subprocess
import tempfile
from engine.FileLib import *
from engine.RegistryLib import *
from engine.SystemLib import *
from engine.FileSystemLib import *
def ogGetArch():
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64")
return
if platform.machine().endswith("64"):
print("x86_64")
else:
print("i386")
def ogGetOsType():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_npartition", sys.argv[0] + " 1 2 => Linux")
return
ogGetOsVersion(sys.argv[1:]).split(':')[0]
def ogGetOsUuid():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => 540e47c6-8e78-4178-aa46-042e4803fb16")
return
# Error si no se reciben 2 parametros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Montar la particion, si no lo estaba previamente.
MNTDIR = ogMount(sys.argv[1], sys.argv[2])
if not MNTDIR:
return
# Obtener UUID según el tipo de sistema operativo.
os_type = ogGetOsType(sys.argv[1], sys.argv[2])
if os_type == "Linux":
# Leer el UUID del sistema de ficheros raíz o el fichero de identificador.
uuid = subprocess.check_output(["findmnt", "-no", "UUID", MNTDIR], stderr=subprocess.DEVNULL).decode().strip() or open(os.path.join(MNTDIR, "etc", "machine-id")).read().strip()
print(uuid)
elif os_type == "Windows":
# Leer identificador en clave de registro.
uuid = ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid")
print(uuid)
def ogGetSerialNumber():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => 123456")
return
# Obtener nº de serie (ignorar los no especificados).
SERIALNO = subprocess.check_output(["dmidecode", "-s", "system-serial-number"]).decode().strip()
SERIALNO = re.sub(r"(not specified|to be filled|invalid entry|default string)", "", SERIALNO, flags=re.IGNORECASE)
SERIALNO = SERIALNO.replace(" ", "")
SERIALNO = SERIALNO[:25] if len(SERIALNO) > 25 else SERIALNO
if SERIALNO:
print(SERIALNO)
return 0
def ogIsEfiActive():
return os.path.isdir("/sys/firmware/efi")
def ogListHardwareInfo():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(sys.argv[0], sys.argv[0])
return
# Recopilación de dispositivos procesando la salida de \c lshw
ogEcho("info", MSG_HARDWAREINVENTORY)
output = subprocess.check_output('echo "cha=$(dmidecode -s chassis-type)" | grep -v "Other"', shell=True).decode().strip()
print(output)
if os.path.isdir("/sys/firmware/efi"):
print("boo=UEFI")
else:
print("boo=BIOS")
subprocess.call(["lshw", "|", "awk", "'BEGIN {type=\"mod\";}",
"/product:/ {sub(/ *product: */,\"\", prod=$0);}",
"/vendor:/ {sub(/ *vendor: */,\"\", vend=$0);}",
"/version:/ {sub(/ *version: */,\"v.\", vers=$0);}",
"/size:/ {size=$2;}",
"/clock:/ {clock=$2;}",
"/slot:/ {sub(/ *slot: */,\"\", slot=$0);}",
"/\\*-/ {if (type==\"mem\"){",
"if (size!=\"\"){",
"numbank++;",
"print type\"=\"vend,prod,size,clock\" (\"slot\")\";}",
"}else{",
"if (type==\"totalmem\"){",
"if (size!=\"\"){",
"totalmemory=\"mem=\"size;}",
"}else{",
"if (type!=\"\" && prod!=\"\"){",
"if (prod==\"v.\"vers)",
"vers=\"\";",
"print type\"=\"vend,prod,size,vers;}}}",
"type=prod=vend=vers=size=clock=slot=\"\";}",
"$1~/-core/ {type=\"boa\";}",
"$1~/-firmware/ {type=\"bio\";}",
"$1~/-cpu/ {type=\"cpu\";}",
"$1~/-bank/ {type=\"mem\";}",
"$1~/-memory/ {type=\"totalmem\";}",
"$1~/-ide/ {type=\"ide\";}",
"$1~/-storage/ {type=\"sto\";}",
"$1~/-disk/ {type=\"dis\";}",
"$1~/-cdrom/ {type=\"cdr\";}",
"$1~/-display/ {type=\"vga\";}",
"$1~/-network/ {type=\"net\";}",
"$1~/-multimedia/ {type=\"mul\";}",
"$1~/-usb/ {type=\"usb\";}",
"$1~/-firewire/ {type=\"fir\";}",
"$1~/-serial/ {type=\"bus\";}",
"END {if (type!=\"\" && prod!=\"\")",
"print type\"=\"vend,prod,size,vers;",
"if (length(numbank)==0 && length(totalmemory)>=4)",
"print totalmemory; }'",
])
# */ (comentario para Doxygen)
def ogListSoftware():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(sys.argv[0], sys.argv[0] + " 1 1")
return
# Error si no se reciben 2 parametros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Obtener tipo de sistema de archivos y montarlo.
MNTDIR = ogMount(sys.argv[1], sys.argv[2])
if not MNTDIR:
return
TYPE = ogGetOsType(sys.argv[1], sys.argv[2])
if not TYPE:
return
# Ficheros temporales.
APPS = tempfile.mktemp()
TMPFILE = tempfile.mktemp()
try:
with open(APPS, "w") as apps_file:
if TYPE == "Linux":
# Procesar paquetes dpkg.
PKGDIR = os.path.join(MNTDIR, "var", "lib", "dpkg")
if os.path.exists(PKGDIR):
# Proceso de fichero en sistemas de 64 bits.
subprocess.call(["awk", "/Package:/ {if (pack!=\"\") print pack,vers;\
sub(/-dev$/,\"\",$2);\
pack=$2}\
/Version:/ {sub(/^.*:/,\"\",$2); sub(/-.*$/,\"\",$2);\
vers=$2}\
/Status:/ {if ($2!=\"install\") pack=vers=\"\"}\
END {if (pack!=\"\") print pack,vers}", os.path.join(PKGDIR, "status")], stdout=apps_file)
# Procesar paquetes RPM.
PKGDIR = os.path.join(MNTDIR, "var", "lib", "rpm")
if os.path.exists(PKGDIR):
# Listar si está instalado el paquete "rpm" en el cliente.
if shutil.which("rpm"):
subprocess.call(["rm", "-f", os.path.join(PKGDIR, "__db.*")])
subprocess.call(["rpm", "--dbpath", PKGDIR, "-qa", "--qf", "%{NAME} %{VERSION}\n"], stdout=apps_file, stderr=subprocess.DEVNULL)
subprocess.call(["rm", "-f", os.path.join(PKGDIR, "__db.*")])
else:
# Obtener el nombre de cada paquete en la BD de RPM.
subprocess.call(["python", "-c", f"import re; import bsddb; db=bsddb.hashopen('{os.path.join(PKGDIR, 'Name')}','r');\
for k in db.keys():\
print(re.sub('-devel$','',k));"], stdout=apps_file)
# Procesar paquetes pacman.
PKGDIR = os.path.join(MNTDIR, "var", "lib", "pacman", "local")
if os.path.exists(PKGDIR):
subprocess.call(["ls", PKGDIR], stdout=subprocess.PIPE)
subprocess.call(["awk", "-F-", "/-/ {print gensub(/-/, \" \", NF-2);}", os.path.join(PKGDIR, "*")], stdout=apps_file)
# Procesar aplicaciones Snappy.
PKGDIR = os.path.join(MNTDIR, "snap")
subprocess.call(["find", PKGDIR, "-name", "snap.yaml", "-exec", "awk", "/name:/ {pack=$2}\
/version:/ {vers=$2}\
END {if (pack!=\"\") print pack,\"(snap)\",vers}", "{}", "+", "2>/dev/null"], stdout=apps_file)
# Procesar aplicaciones Flatpak.
PKGDIR = os.path.join(MNTDIR, "var", "lib", "flatpak")
subprocess.call(["ls", "-1", os.path.join(PKGDIR, "app", "*", "current", "active", "deploy")], stderr=subprocess.DEVNULL)
subprocess.call(["python", "-c", "import sys; for f in sys.stdin:\
p = open(f.strip()).read().split('\0');\
try:\
if(p[0] != 'flathub'):\
raise ValueError;\
print('{} (flatpak) {}'.format(p[p.index('appdata-name') + 4], p[p.index('appdata-version') + 1]));\
except ValueError:\
pass;"], stdout=apps_file)
elif TYPE == "Windows":
# Comprobar tipo de proceso del registro de Windows.
if shutil.which("hivexregedit"):
# Nuevo proceso más rápido basado en "hivexregedit".
HIVE = ogGetHivePath(MNTDIR, "software")
if HIVE:
# Claves de registro para programas instalados.
subprocess.call(["hivexregedit", "--unsafe-printable-strings", "--export", HIVE, "\\Microsoft\\Windows\\CurrentVersion\\Uninstall"], stdout=TMPFILE, stderr=subprocess.DEVNULL)
subprocess.call(["hivexregedit", "--unsafe-printable-strings", "--export", HIVE, "\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"], stdout=TMPFILE, stderr=subprocess.DEVNULL)
# Mostrar los valores "DisplayName" y "DisplayVersion" para cada clave.
subprocess.call(["awk", "-F\"", "$1~/^\\[/ {n=\"\"}\
$2~/DisplayName/ {n=$4}\
$2~/DisplayVersion/ {print n,$4}", TMPFILE], stdout=apps_file)
else:
# Compatibilidad con clientes ogLive antiguos.
# Claves de registro para programas instalados: formato "{clave}".
KEYS = ogListRegistryKeys(MNTDIR, "software", "\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
KEYS32 = ogListRegistryKeys(MNTDIR, "software", "\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
# Mostrar los valores "DisplayName" y "DisplayVersion" para cada clave.
for k in KEYS:
PROG = ogGetRegistryValue(MNTDIR, "software", f"\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayName")
if PROG:
VERS = ogGetRegistryValue(MNTDIR, "software", f"\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayVersion")
apps_file.write(f"{PROG} {VERS}\n")
for k in KEYS32:
PROG = ogGetRegistryValue(MNTDIR, "software", f"\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayName")
if PROG:
VERS = ogGetRegistryValue(MNTDIR, "software", f"\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayVersion")
apps_file.write(f"{PROG} {VERS}\n")
elif TYPE == "MacOS":
# Listar directorios de aplicaciones e intentar obtener la versión del fichero .plist (tanto original como descomprimido).
for root, dirs, files in os.walk(os.path.join(MNTDIR, "Applications")):
for dir in dirs:
if dir.endswith(".app"):
file = os.path.join(root, dir, "Contents", "version.plist")
if not os.path.exists(file):
file = os.path.join(root, dir, "Contents", "version.plist.uncompress")
if os.path.exists(file):
with open(file, "r") as plist_file:
plist_data = plist_file.read()
version = re.search("<key>ShortVersionString</key>\s*<string>(.*?)</string>", plist_data)
if version:
apps_file.write(f"{os.path.basename(dir)}.app {version.group(1)}\n")
elif TYPE == "BSD":
subprocess.call(["sqlite3", os.path.join(MNTDIR, "var", "db", "pkg", "local.sqlite")], input="SELECT name FROM pkg_search;", stdout=apps_file, stderr=subprocess.DEVNULL)
# Mostrar sistema Operativo y aplicaciones.
ogGetOsVersion(sys.argv[1], sys.argv[2]).split(":")[1].strip()
with open(APPS, "r") as apps_file:
apps = apps_file.readlines()
apps = sorted(set(apps))
for app in apps:
print(app.strip())
finally:
os.remove(APPS)
os.remove(TMPFILE)
def ogGetOsVersion(ndisk, nfilesys):
# Variables locales.
MNTDIR = ogMount(ndisk, nfilesys)
TYPE = ""
VERSION = ""
IS64BIT = ""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => Linux:Ubuntu precise (12.04 LTS) 64 bits")
return
# Error si no se reciben 2 parametros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
# Montar la particion, si no lo estaba previamente.
MNTDIR = ogMount(sys.argv[1], sys.argv[2])
if not MNTDIR:
return
# Buscar tipo de sistema operativo.
# Para GNU/Linux: leer descripción.
TYPE = "Linux"
FILE = os.path.join(MNTDIR, "etc", "os-release")
if os.path.exists(FILE):
with open(FILE, "r") as f:
for line in f:
if line.startswith("PRETTY_NAME"):
VERSION = line.split("=")[1].strip().strip('"')
break
# Si no se puede obtener, buscar en ficheros del sistema.
if not VERSION:
FILE = os.path.join(MNTDIR, "etc", "lsb-release")
if os.path.exists(FILE):
with open(FILE, "r") as f:
for line in f:
if line.startswith("DESCRIPTION"):
VERSION = line.split("=")[1].strip().strip('"')
break
for DISTRIB in ["redhat", "SuSE", "mandrake", "gentoo"]:
FILE = os.path.join(MNTDIR, "etc", f"{DISTRIB}-release")
if os.path.exists(FILE):
with open(FILE, "r") as f:
VERSION = f.readline().strip()
break
FILE = os.path.join(MNTDIR, "etc", "arch-release")
if os.path.exists(FILE):
VERSION = "Arch Linux"
FILE = os.path.join(MNTDIR, "etc", "slackware-version")
if os.path.exists(FILE):
with open(FILE, "r") as f:
VERSION = f.read().strip()
# Si no se encuentra, intentar ejecutar "lsb_release".
if not VERSION:
try:
output = subprocess.check_output(["chroot", MNTDIR, "lsb_release", "-d"], stderr=subprocess.DEVNULL).decode().strip()
VERSION = output.split(":")[1].strip()
except subprocess.CalledProcessError:
pass
# Comprobar Linux de 64 bits.
if VERSION and os.path.exists(os.path.join(MNTDIR, "lib64")):
IS64BIT = "64 bits"
# Para Android, leer fichero de propiedades.
if not VERSION:
TYPE = "Android"
FILE = os.path.join(MNTDIR, "android*", "system", "build.prop")
if glob.glob(FILE):
with open(glob.glob(FILE)[0], "r") as f:
lines = f.readlines()
brand = ""
release = ""
for line in lines:
if line.startswith("product.brand"):
brand = line.split("=")[1].strip()
elif line.startswith("build.version.release"):
release = line.split("=")[1].strip()
VERSION = f"Android {brand} {release}"
if os.path.exists(os.path.join(MNTDIR, "lib64")):
IS64BIT = "64 bits"
# Para GNU/Hurd, comprobar fichero de inicio (basado en os-prober).
if not VERSION:
TYPE = "Hurd"
FILE = os.path.join(MNTDIR, "hurd", "init")
if os.path.exists(FILE):
VERSION = "GNU/Hurd"
# Para Windows: leer la version del registro.
if not VERSION:
TYPE = "Windows"
FILE = ogGetHivePath(MNTDIR, "SOFTWARE")
if FILE:
try:
output = subprocess.check_output(["hivexsh", "load", FILE, "cd", "\\Microsoft\\Windows NT\\CurrentVersion", "lsval", "ProductName", "lsval", "DisplayVersion"], stderr=subprocess.DEVNULL).decode().strip()
lines = output.split("\n")
if len(lines) == 2:
VERSION = lines[1].strip()
if ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\ProgramW6432Dir"):
IS64BIT = "64 bits"
except subprocess.CalledProcessError:
pass
# Para cargador Windows: buscar versión en fichero BCD (basado en os-prober).
if not VERSION:
TYPE = "WinLoader"
FILE = ogGetPath(MNTDIR, "boot", "bcd")
if not FILE:
FILE = ogGetPath(MNTDIR, "EFI", "Microsoft", "boot", "bcd")
if FILE:
for DISTRIB in ["Windows Recovery", "Windows Boot"]:
with open(FILE, "rb") as f:
if re.search(DISTRIB.encode(), f.read()):
VERSION = f"{DISTRIB} loader"
break
# Para macOS: detectar kernel y completar con fichero plist de información del sistema.
if not VERSION:
TYPE = "MacOS"
FILE = os.path.join(MNTDIR, "mach_kernel")
if os.path.exists(FILE) and not subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("text"):
if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O"):
VERSION = "macOS"
if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O 64-bit"):
IS64BIT = "64 bits"
FILE = os.path.join(MNTDIR, "System", "Library", "CoreServices", "SystemVersion.plist")
if os.path.exists(FILE):
with open(FILE, "r") as f:
plist_data = f.read()
product_name = re.search("<key>ProductName</key>\s*<string>(.*?)</string>", plist_data)
product_version = re.search("<key>ProductVersion</key>\s*<string>(.*?)</string>", plist_data)
if product_name and product_version:
VERSION = f"{product_name.group(1)} {product_version.group(1)}"
FILE = os.path.join(MNTDIR, "com.apple.recovery.boot")
if os.path.exists(FILE) and VERSION:
VERSION = f"{VERSION} recovery"
# Para FreeBSD: obtener datos del Kernel.
if not VERSION:
TYPE = "BSD"
FILE = os.path.join(MNTDIR, "boot", "kernel", "kernel")
if os.path.exists(FILE):
output = subprocess.check_output(["strings", FILE]).decode().strip()
match = re.search(r"@.*RELEASE", output)
if match:
VERSION = match.group().split("@")[0].strip()
if subprocess.check_output(["file", "-b", FILE]).decode().strip().endswith("x86-64"):
IS64BIT = "64 bits"
# Para Solaris: leer el fichero de versión.
if not VERSION:
TYPE = "Solaris"
FILE = os.path.join(MNTDIR, "etc", "release")
if os.path.exists(FILE):
with open(FILE, "r") as f:
VERSION = f.readline().strip()
# Para cargador GRUB, comprobar fichero de configuración.
if not VERSION:
TYPE = "GrubLoader"
for FILE in [os.path.join(MNTDIR, "grub", "menu.lst"), os.path.join(MNTDIR, "boot", "grub", "menu.lst")]:
if os.path.exists(FILE):
VERSION = "GRUB Loader"
break
for FILE in glob.glob(os.path.join(MNTDIR, "{,boot/}{grub{,2},EFI/*}/grub.cfg")):
if os.path.exists(FILE):
VERSION = "GRUB2 Loader"
break
# Mostrar resultado y salir sin errores.
if VERSION:
print(f"{TYPE}:{VERSION} {IS64BIT}")
return 0

254
client/engine/NetLib.py Normal file
View File

@ -0,0 +1,254 @@
import subprocess
import sys
import os
from engine.FileLib import *
from engine.SystemLib import *
def ogChangeRepo():
SRCIMG = ""
NEWREPO = ""
REPO = ""
OGUNIT = ""
if len(sys.argv) < 2:
print("Usage: ogChangeRepo IPREPO [ OgUnit ]")
print("Example: ogChangeRepo 10.1.120.3")
print("Example: ogChangeRepo 10.1.120.3 cdc")
return
if sys.argv[1] == "help":
print("Usage: ogChangeRepo IPREPO [ OgUnit ]")
print("Example: ogChangeRepo 10.1.120.3")
print("Example: ogChangeRepo 10.1.120.3 cdc")
return
if len(sys.argv) >= 2:
NEWREPO = sys.argv[1]
# Opciones de montaje: lectura o escritura
subprocess.run(["mount", "|", "grep", "ogimages.*rw,"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
RW = ",rw" if subprocess.returncode == 0 else ",ro"
# Si REPO tomamos el repositorio y la unidad organizativa actual
REPO = ogGetRepoIp()
OGUNIT = subprocess.run(["df", "|", "awk", "-F", " ", "'/ogimages/ {sub(\"//.*/ogimages\",\"\",$1); sub(\"/\",\"\",$1); print $1}'"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().strip()
# Parametros de entrada. Si $1 = "REPO" dejo el repositorio actual
if sys.argv[1].upper() == "REPO":
NEWREPO = REPO
# Si $1 y $2 son el repositorio y la OU actual me salgo
if NEWREPO == REPO and sys.argv[2] == OGUNIT:
return 0
subprocess.run(["source", "/scripts/functions"], shell=True)
subprocess.run(["source", "/scripts/ogfunctions"], shell=True)
subprocess.run(["umount", OGIMG])
if sys.argv[2] == "":
SRCIMG = "ogimages"
else:
SRCIMG = "ogimages/" + sys.argv[2]
subprocess.run(["eval", "$(grep \"OPTIONS=\" /scripts/ogfunctions)"])
ogEcho("session", "log", MSG_HELP_ogChangeRepo + " " + NEWREPO + " " + sys.argv[2].rstrip())
ogConnect(NEWREPO, ogprotocol, SRCIMG, OGIMG, RW)
# Si da error volvemos a montar el inicial
if subprocess.returncode != 0:
ogConnect(REPO, ogprotocol, SRCIMG, OGIMG, RW)
ogRaiseError("session", OG_ERR_REPO, NEWREPO)
return subprocess.returncode
def ogGetGroupDir():
REPO = ""
DIR = ""
GROUP = ""
if len(sys.argv) < 2:
ogHelp("ogGetGroupDir", "ogGetGroupDir str_repo", "ogGetGroupDir REPO ==> /opt/opengnsys/images/groups/Grupo1")
return
if len(sys.argv) == 1:
REPO = "REPO"
else:
REPO = sys.argv[1]
GROUP = ogGetGroupName()
if GROUP:
DIR = ogGetPath(REPO, "/groups/" + GROUP, stderr=subprocess.DEVNULL)
if os.path.isdir(DIR):
print(DIR)
return 0
def ogGetGroupName():
if len(sys.argv) >= 2 and sys.argv[1] == "help":
ogHelp("ogGetGroupName", "ogGetGroupName", "ogGetGroupName => Grupo1")
return
if "group" in globals() and group:
print(group)
return 0
def ogGetHostname():
HOST = ""
if len(sys.argv) >= 2 and sys.argv[1] == "help":
ogHelp("ogGetHostname", "ogGetHostname", "ogGetHostname => pc1")
return
# Tomar nombre de la variable HOSTNAME
HOST = os.getenv("HOSTNAME")
# Si no, tomar del DHCP, opción host-name
if not HOST:
with open("/var/lib/dhcp3/dhclient.leases", "r") as f:
for line in f:
if "option host-name" in line:
HOST = line.split('"')[1]
break
# Si no, leer el parámetro del kernel hostname
if not HOST:
with open("/proc/cmdline", "r") as f:
cmdline = f.read()
HOST = re.search(r"hostname=([^ ]+)", cmdline)
if HOST:
HOST = HOST.group(1)
if HOSTNAME != HOST:
os.environ["HOSTNAME"] = HOST
if HOST:
print(HOST)
def ogGetIpAddress():
IP = ""
if len(sys.argv) >= 2 and sys.argv[1] == "help":
ogHelp("ogGetIpAddress", "ogGetIpAddress", "ogGetIpAddress => 192.168.0.10")
return
if "IPV4ADDR" in os.environ:
IP = os.environ["IPV4ADDR"]
else:
# Obtener direcciones IP.
if "DEVICE" in os.environ:
IP = subprocess.run(["ip", "-o", "address", "show", "up", "dev", os.environ["DEVICE"]], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split()
else:
IP = subprocess.run(["ip", "-o", "address", "show", "up"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split()
IP = [addr.split("/")[0] for addr in IP if "inet" in addr]
# Mostrar solo la primera.
if IP:
print(IP[0])
return 0
def ogGetMacAddress():
MAC = ""
if len(sys.argv) >= 2 and sys.argv[1] == "help":
ogHelp("ogGetMacAddress", "ogGetMacAddress", "ogGetMacAddress => 00:11:22:33:44:55")
return
# Obtener direcciones Ethernet.
if "DEVICE" in os.environ:
MAC = subprocess.run(["ip", "-o", "link", "show", "up", "dev", os.environ["DEVICE"]], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split()
MAC = [addr.upper() for addr in MAC if "ether" in addr]
else:
MAC = subprocess.run(["ip", "-o", "link", "show", "up"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().split()
MAC = [addr.upper() for addr in MAC if "ether" in addr and "lo" not in addr]
# Mostrar solo la primera.
if MAC:
print(MAC[0])
return 0
def ogGetNetInterface():
if len(sys.argv) >= 2 and sys.argv[1] == "help":
ogHelp("ogGetNetInterface", "ogGetNetInterface", "ogGetNetInterface => eth0")
return
if "DEVICE" in os.environ:
print(os.environ["DEVICE"])
return 0
def ogGetRepoIp():
# Variables locales.
SOURCE = ""
FSTYPE = ""
# Mostrar ayuda.
if len(sys.argv) >= 2 and sys.argv[1] == "help":
ogHelp("ogGetRepoIp", "ogGetRepoIp", "ogGetRepoIp => 192.168.0.2")
return
# Obtener direcciones IP, según el tipo de montaje.
output = subprocess.run(["findmnt", "-P", "-o", "SOURCE,FSTYPE", OGIMG], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().strip()
lines = output.split("\n")
for line in lines:
fields = line.split()
if len(fields) == 2:
if fields[1] == "nfs":
SOURCE = fields[0].split(":")[0]
elif fields[1] == "cifs":
SOURCE = fields[0].split("/")[2]
if SOURCE:
print(SOURCE)
return 0
def ogGetServerIp():
# Variables locales.
SOURCE = ""
FSTYPE = ""
# Mostrar ayuda.
if len(sys.argv) >= 2 and sys.argv[1] == "help":
ogHelp("ogGetServerIp", "ogGetServerIp", "ogGetServerIp => 192.168.0.2")
return
# Obtener direcciones IP, según el tipo de montaje.
output = subprocess.run(["findmnt", "-P", "-o", "SOURCE,FSTYPE", OGIMG], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode().strip()
lines = output.split("\n")
for line in lines:
fields = line.split()
if len(fields) == 2:
if fields[1] == "nfs":
SOURCE = fields[0].split(":")[0]
elif fields[1] == "cifs":
SOURCE = fields[0].split("/")[2]
if SOURCE:
print(SOURCE)
return 0
def ogMakeGroupDir():
REPO = ""
DIR = ""
GROUP = ""
if len(sys.argv) < 2:
ogHelp("ogMakeGroupDir", "ogMakeGroupDir str_repo", "ogMakeGroupDir", "ogMakeGroupDir REPO")
return
if len(sys.argv) == 1:
REPO = "REPO"
else:
REPO = sys.argv[1]
DIR = ogGetPath(REPO, "/groups/" + ogGetGroupName(), stderr=subprocess.DEVNULL)
if DIR:
subprocess.run(["mkdir", "-p", DIR], stderr=subprocess.DEVNULL)
return 0

View File

@ -0,0 +1,533 @@
from engine.SystemLib import *
def ogLoadHiveWindows():
FUNCNAME = ogLoadHiveWindows.__name__
# Variables locales.
PART = None
DISK = None
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_partition", f"{FUNCNAME} 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
return ogRaiseError(OG_ERR_FORMAT)
DISK = int(sys.argv[1])
PART = int(sys.argv[2])
# Comprobaciones redundantes: borrar"
# ogDiskToDev(DISK, PART) or return ogRaiseError(OG_ERR_PARTITION, "particion de windows no detectada")
# ogGetOsType(DISK, PART).startswith("Windows") or return ogRaiseError(OG_ERR_NOTOS, "no es windows")
# VERSION = ogGetOsVersion(DISK, PART)
# Fin Comprobaciones redundantes: borrar"
# primera fase, carga de los hive del sistema
if ogGetPath(DISK, PART, "WINDOWS"):
SYSTEMROOT = "Windows"
elif ogGetPath(DISK, PART, "WINNT"):
SYSTEMROOT = "winnt"
else:
return ogRaiseError(OG_ERR_NOTOS, "version windows no detectada")
hiveSAM = ogGetPath(DISK, PART, f"/{SYSTEMROOT}/system32/config/SAM")
if hiveSAM:
os.environ["hiveSAM"] = hiveSAM
else:
return ogRaiseError(OG_ERR_NOTOS, "hive SAM no detectada")
hiveSYSTEM = ogGetPath(DISK, PART, f"/{SYSTEMROOT}/system32/config/system")
if hiveSYSTEM:
os.environ["hiveSYSTEM"] = hiveSYSTEM
else:
return ogRaiseError(OG_ERR_NOTOS, "hive SYSTEM no detectada")
hiveSOFTWARE = ogGetPath(DISK, PART, f"/{SYSTEMROOT}/system32/config/software")
if hiveSOFTWARE:
os.environ["hiveSOFTWARE"] = hiveSOFTWARE
else:
return ogRaiseError(OG_ERR_NOTOS, "hive SOFTWARE no detectada")
os.environ["TEMPhive"] = "/tmp/tmpregistry"
# segunda fase, carga de los hive de usuarios windows.
COUNT = 3
# TODO WINDOWS XP WINDOWS7
BASEHOMEDIR = ogGetPath(DISK, PART, "/Documents and Settings")
TMPUSERFILE = "/tmp/WuserRegAndDAT.tmp"
with open(TMPUSERFILE, "w") as f:
f.write("\n".join(glob.glob(f"{BASEHOMEDIR}/**/NTUSER.DAT", recursive=True)))
LISTUSERS = subprocess.check_output(["drbl-chntpw", "-l", hiveSAM]).decode().splitlines()
LISTUSERS = [user.split("<")[1].split(">")[0] for user in LISTUSERS if "RID" in user]
for user in LISTUSERS:
# Comprobamos que el usuario registrado tiene .DAT
if HOMEDIR := next((line for line in open(TMPUSERFILE) if user in line), None):
os.environ[user] = f"hiveUSER{COUNT}"
os.environ[f"hiveUSER{COUNT}"] = HOMEDIR.strip()
COUNT += 1
COUNT = 0
def ogUpdateHiveWindows():
FUNCNAME = ogUpdateHiveWindows.__name__
# Variables locales.
PART = None
DISK = None
FILE = None
# TODO detectar llamada a ogLoadHiveWindows
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(FUNCNAME, f"{FUNCNAME} ", f"{FUNCNAME} ")
return
subprocess.call(["drbl-chntpw", "-f", os.environ["TEMPhive"], os.environ["hiveSAM"], os.environ["hiveSYSTEM"], os.environ["hiveSOFTWARE"], os.environ["hiveUSER3"], os.environ["hiveUSER4"], os.environ["hiveUSER5"], os.environ["hiveUSER6"], os.environ["hiveUSER7"], os.environ["hiveUSER8"], os.environ["hiveUSER9"]])
os.remove(os.environ["TEMPhive"])
del os.environ["hiveSAM"]
del os.environ["hiveSYSTEM"]
del os.environ["hiveSOFTWARE"]
del os.environ["TEMPhive"]
del os.environ["hiveUSER3"]
del os.environ["hiveUSER4"]
del os.environ["hiveUSER5"]
del os.environ["hiveUSER6"]
del os.environ["hiveUSER7"]
del os.environ["hiveUSER8"]
del os.environ["hiveUSER9"]
def ogHiveNTRunMachine():
FUNCNAME = ogHiveNTRunMachine.__name__
# Variables locales.
PART = None
DISK = None
FILE = None
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(FUNCNAME, f"{FUNCNAME} PathScripts|command keyName",
f"{FUNCNAME} c:\\\\Windows\\\\crearusuarios.cmd scripts_crearUsuarios",
f"{FUNCNAME} \"cmd /c del c:\ogboot.*\" ogcleanboot",
f"{FUNCNAME} Requiere la previa ejecución de ogLoadHive int_disk int_part",
f"{FUNCNAME} Despues requiere el ogUpdateHive")
return
# Error si no se reciben al menos 1 parámetros.
if len(sys.argv) != 3:
return ogRaiseError(OG_ERR_FORMAT)
with open(os.environ["TEMPhive"], "a") as f:
f.write(f"h 2\ncd \\Microsoft\\Windows\\CurrentVersion\\Run\nnv 1 {sys.argv[2]}\ned {sys.argv[2]}\n{sys.argv[1]}\n")
def ogNTPolUserOn():
FUNCNAME = ogNTPolUserOn.__name__
# Variables locales.
PART = None
DISK = None
FILE = None
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(FUNCNAME, f"{FUNCNAME} id_hive_user", f"{FUNCNAME} NombreUsuario", f"{FUNCNAME}")
return
# TODO: error si no se ha llamado previamente a ogLoadHiveWindows
if "hiveSAM" not in os.environ:
return ogRaiseError(OG_ERR_FORMAT, "se debe utilizar primero la utilidad ogLoadHiveWindows")
# TODO: error si el usuario no tiene cuenta en windows.
if subprocess.call(["drbl-chntpw", "-l", os.environ["hiveSAM"]], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode().count(f"RID: {sys.argv[1]}") == 0:
return ogRaiseError(OG_ERR_FORMAT, f"el usuario {sys.argv[1]} no tiene cuenta en este windows: Compruebe mayusculas o minusculas")
# TODO: error si no el usario no no tiene HIVE asociado.
if sys.argv[1] not in os.environ:
return ogRaiseError(OG_ERR_FORMAT, "el usuario no tiene hive creado")
HIVEID = os.environ[sys.argv[1]].replace("hiveUSER", "")
# echo "IMPORTANTE: la variable HiveUser3=/mnt/windows/Document/\ and/\ Seeting\alumnmos\NTUSER.dat"
print(HIVEID)
# cp /var/EAC/admin/utilswin/Fondo.BMP ${particion}/WINDOWS/
with open(os.environ["TEMPhive"], "a") as f:
f.write(f"h {HIVEID}\n")
f.write("cd \\Control Panel\\Desktop\n")
f.write("ed Wallpaper\n")
f.write("C:\\WINDOWS\\fondo.bmp\n")
f.write("\n")
f.write("cd \\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\n")
f.write("nk Explorer\n")
f.write("cd Explorer\n")
f.write("\n")
f.write("nv 4 NoDesktop\n")
f.write("ed NoDesktop\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoSimpleStartMenu\n")
f.write("ed NoSimpleStartMenu\n")
f.write("1\n")
f.write("nv 4 NoWindowsUpdate\n")
f.write("ed NoWindowsUpdate\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoSMConfigurePrograms\n")
f.write("ed NoSMConfigurePrograms\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoChangeStartMenu\n")
f.write("ed NoChangeStartMenu\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 Intellimenus\n")
f.write("ed Intellimenus\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoRun\n")
f.write("ed NoRun\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoRecentDocsHistory\n")
f.write("ed NoRecentDocsHistory\n")
f.write("1\n")
def NTChangeName():
if len(sys.argv) == 1:
print("sintaxis: NTChangeName str_$var")
print("ejemplos: NTChangeName adi${IPcuatro}-xp")
return
with open(os.environ["TEMPhive"], "a") as f:
f.write("h 1\n")
f.write("ed ControlSet001\\Control\\ComputerName\\ComputerName\\ComputerName\n")
f.write(sys.argv[1] + "\n")
f.write("ed ControlSet001\\Services\\Tcpip\\Parameters\\Hostname\n")
f.write(sys.argv[1] + "\n")
f.write("ed ControlSet001\\Services\\Tcpip\\Parameters\\NV Hostname\n")
f.write(sys.argv[1] + "\n")
f.write("h 2\n")
f.write("cd \\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\n")
f.write("ed DefaultDomainName\n")
f.write(sys.argv[1] + "\n")
def NTSetGroupName(group_name):
if len(sys.argv) == 1:
print("sintaxis: NTSetGroupName str_$var")
print("ejemplos: NTSetGroupName adi")
return
with open(os.environ["TEMPhive"], "a") as f:
f.write("h 2\n")
f.write("ed \\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultDomainName\n")
f.write(group_name + "\n")
def NTSetOwner(owner, organization):
if len(sys.argv) == 1:
print("sintaxis: NtSetOwner str_propietario str_organizacion")
print("ejemplos: NTSetOwner eu\\ politecnica universidad\\ de\\ malaga")
return
with open(os.environ["TEMPhive"], "a") as f:
f.write("h 2\n")
f.write("ed \\Microsoft\\Windows NT\\CurrentVersion\\RegisteredOwner\n")
f.write(owner + "\n")
f.write("ed \\Microsoft\\Windows NT\\CurrentVersion\\RegisteredOrganization\n")
f.write(organization + "\n")
def NTAutoLogon():
if len(sys.argv) == 1:
print("sintaxis: NTAutoLogon int_Activar int_nves str_usuario str_passwd str_equipo")
print("ejemplos: NTAutoLogon 1 2 administrador 3451 $equipo")
print("IMPORTANTE: cuando AutoLogonCount llegue a 0, activa el AutoAdminLogon a 0. Pero no borra los valores de DefaultPassword")
return 2
with open(os.environ["TEMPhive"], "a") as f:
f.write("hive 2\n")
f.write("cd \\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\n")
f.write(f"nv 1 AutoAdminLogon\n")
f.write(f"ed AutoAdminLogon\n")
f.write(f"{sys.argv[1]}\n")
f.write(f"nv 1 AutoLogonCount\n")
f.write(f"ed AutoLogonCount\n")
f.write(f"{sys.argv[2]}\n")
f.write(f"nv 1 DefaultUserName\n")
f.write(f"ed DefaultUserName\n")
f.write(f"{sys.argv[3]}\n")
f.write(f"nv 1 DefaultDomainName\n")
f.write(f"ed DefaultDomainName\n")
f.write(f"{sys.argv[5]}\n")
if sys.argv[4] == "none":
f.write("dv DefaultPassword\n")
else:
f.write(f"nv 1 DefaultPassword\n")
f.write(f"ed DefaultPassword\n")
f.write(f"{sys.argv[4]}\n")
def NTStatusRatonTeclado():
if len(sys.argv) == 1:
print("sintaxis: NTStatusRatonTeclado int_StatusRaton int_StatusTeclado")
print("ejemplos: NTStatusRatonTeclado 1 4")
return 2
with open(os.environ["TEMPhive"], "a") as f:
f.write("hive 1\n")
f.write("cd \\ControlSet001\\Services\\Mouclass\n")
f.write("ed Start\n")
f.write(sys.argv[1] + "\n")
f.write("cd \\ControlSet001\\Services\\Kbdclass\n")
f.write("ed Start\n")
f.write(sys.argv[2] + "\n")
def NTRunOnceMachine():
if len(sys.argv) == 1:
print("sintaxis: NTRunOnceMachine PathScripts idScripts")
print("ejemplo: NTRunOnceMachine c:\\\\WINDOWS\\\\crearusuarios.bat scripts1")
print("IMPORTANTE: el path debe llevar dos barras \\, pero como se deben 'escapar' debes poner cuatro \\\\")
return 2
with open(os.environ["TEMPhive"], "a") as f:
f.write("h 2\n")
f.write("cd \\Microsoft\\Windows\\CurrentVersion\\RunOnce\n")
f.write(f"nv 1 {sys.argv[2]}\n")
f.write(f"ed {sys.argv[2]}\n")
f.write(f"{sys.argv[1]}\n")
def NTRunMachine():
if len(sys.argv) == 1:
print("sintaxis: NTRunMachine PathScripts idScripts")
print("ejemplo: NTRunMachine c:\\\\WINDOWS\\\\crearusuarios.bat scripts1")
print("IMPORTANTE: el path debe llevar dos barras \\, pero como se deben 'escapar' debes poner cuatro \\\\")
return 2
with open(os.environ["TEMPhive"], "a") as f:
f.write("h 2\n")
f.write("cd \\Microsoft\\Windows\\CurrentVersion\\Run\n")
f.write(f"nv 1 {sys.argv[2]}\n")
f.write(f"ed {sys.argv[2]}\n")
f.write(f"{sys.argv[1]}\n")
def NTRunUser():
if len(sys.argv) == 1:
print("sintaxis: str_PathWINScripts str_idScripts Int_hive||$usuario")
print("ejemplo: c:\\\\WINDOWS\\\\crearusuarios.bat scripts1 3")
print("IMPORTANTE: el pathWIN debe llevar dos barras \\, pero como se deben 'escapar' debes poner cuatro \\\\")
print("IMPORTANTE: el pathLinux si lleva espacios debe escaparse con una barra \\")
print("IMPORTANTE Int_hive: 3 para el primer usuario, 4 para el segundo usuario")
print("requiere export un HiveUser3=/mnt/windows/Document\\ and\\ Seeting\\alumnmos\\NTUSER.dat")
return 2
with open(os.environ["TEMPhive"], "a") as f:
f.write(f"h {sys.argv[3]}\n")
f.write("cd \\Software\\Microsoft\\Windows\\CurrentVersion\\Run\n")
f.write(f"nv 1 {sys.argv[2]}\n")
f.write(f"ed {sys.argv[2]}\n")
f.write(f"{sys.argv[1]}\n")
def NTPolUserOn():
if len(sys.argv) == 1:
print("sintaxis: NTPolUserOn Int_hive")
print("ejemplo: NTPolUserOn 3")
print("IMPORTANTE: la variable HiveUser3=/mnt/windows/Document/ and/ Seeting/alumnmos/NTUSER.dat")
return 2
with open(os.environ["TEMPhive"], "a") as f:
f.write(f"h {sys.argv[1]}\n")
f.write("cd \\Control Panel\\Desktop\n")
f.write("ed Wallpaper\n")
f.write("C:\\WINDOWS\\fondo.bmp\n")
f.write("\n")
f.write("cd \\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\n")
f.write("nk Explorer\n")
f.write("cd Explorer\n")
f.write("\n")
f.write("nv 4 NoDesktop\n")
f.write("ed NoDesktop\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoSimpleStartMenu\n")
f.write("ed NoSimpleStartMenu\n")
f.write("1\n")
f.write("nv 4 NoWindowsUpdate\n")
f.write("ed NoWindowsUpdate\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoSMConfigurePrograms\n")
f.write("ed NoSMConfigurePrograms\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoChangeStartMenu\n")
f.write("ed NoChangeStartMenu\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 Intellimenus\n")
f.write("ed Intellimenus\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoRun\n")
f.write("ed NoRun\n")
f.write("1\n")
f.write("\n")
f.write("nv 4 NoRecentDocsHistory\n")
f.write("ed NoRecentDocsHistory\n")
f.write("1\n")
def NTPolUserOFF(hive):
if len(sys.argv) == 1:
print("sintaxis: NTPolUserOFF Int_hive")
print("ejemplo: NTPolUserOFF 3")
print("IMPORTANTE: la variable HiveUser3=/mnt/windows/Document/ and/ Seeting/alumnmos/NTUSER.dat")
return 2
with open(os.environ["TEMPhive"], "a") as f:
f.write(f"h {hive}\n")
f.write("cd \\Control Panel\\Desktop\n")
f.write("ed Wallpaper\n")
f.write("C:\\WINDOWS\\web\\wallpaper\\Felicidad.bmp\n")
f.write("\n")
f.write("cd \\Software\\Microsoft\\Windows\\CurrentVersion\\\n")
f.write("rdel Policies\n")
f.write("nk Policies\n")
f.write("1\n")
def ogSetWindowsChkdisk():
if len(sys.argv) == 1:
print("sintaxis: true|TRUE|0 false|false|1")
print("ejemplos: int=0 desactivado int=1 activado")
return 2
valor = ""
if sys.argv[1] in ["0", "true", "TRUE"]:
valor = "autocheck autochk *"
elif sys.argv[1] in ["1", "false", "FALSE"]:
valor = "none"
else:
return 0
with open(os.environ["TEMPhive"], "a") as f:
f.write("hive 1\n")
f.write("cd \\ControlSet001\\Control\\Session Manager\n")
f.write("ed BootExecute\n")
f.write(valor + "\n")
f.write("--n\n")
def NTStartRecovery():
if len(sys.argv) == 1:
print("sintaxis: Int-Status")
print("ejemplos: int=0 desactivado int=1 activado")
return 2
valor = ""
if sys.argv[1] == "0":
valor = "none"
elif sys.argv[1] == "1":
valor = "00000000"
else:
return 0
with open(os.environ["TEMPhive"], "a") as f:
f.write("hive 2\n")
f.write("#cd \\Policies\\Microsoft\\Windows\\WinRE\n")
f.write("#ed DisableSetup\n")
f.write("cd \\Policies\\Microsoft\\Windows\n")
f.write("nk WinRE\n")
f.write("nv 4 DisableSetup\n")
f.write("ed DisableSetup\n")
f.write(valor + "\n")
f.write("--n\n")
def ogSchrootLinux():
FUNCNAME = ogSchrootLinux.__name
# Variables locales.
PART = None
DISK = None
DIRCONF = "/etc/schroot"
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_partition", f"{FUNCNAME} 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
return ogRaiseError(OG_ERR_FORMAT)
DISK = int(sys.argv[1])
PART = int(sys.argv[2])
VERSION = ogGetOsVersion(DISK, PART)
if "Linux" not in VERSION:
return ogRaiseError(OG_ERR_NOTOS, "no es linux")
ogUnmount(DISK, PART) or return ogRaiseError(OG_ERR_NOTOS, "no es linux")
SCHROOTDEVICE = ogDiskToDev(DISK, PART)
os.remove(f"{DIRCONF}/mount-defaults")
os.remove(f"{DIRCONF}/schroot.conf")
with open(f"{DIRCONF}/mount-defaults", "w") as f:
f.write("# <file system> <mount point> <type> <options> <dump> <pass>\n")
f.write("proc /proc proc defaults 0 0\n")
f.write("/dev /dev none rw,bind 0 0\n")
f.write("/dev/pts /dev/pts none rw,bind 0 0\n")
f.write("/dev/shm /dev/shm none rw,bind 0 0\n")
with open(f"{DIRCONF}/schroot.conf", "w") as f:
f.write("[linux]\n")
f.write(f"description={VERSION}\n")
f.write("type=block-device\n")
f.write(f"device={SCHROOTDEVICE}\n")
subprocess.call(["schroot", "-c", "linux"])
subprocess.call(["schroot", "-end-sessiona", "--all-sessions"])
def ogDiskToRelativeDev(int_disk, int_partition=None):
FUNCNAME = ogDiskToRelativeDev.__name__
if int_partition is None:
# Sintaxis1: IdPartition int_disk
# Ejemplo1: IdPartition 1 -> sda
return ogDiskToDev(int_disk)
else:
# Sintaxis2: IdPartition int_disk int_partition
# Ejemplo2: IdPartition 1 2 -> sda2
return ogDiskToDev(int_disk) + str(int_partition)
def ogDeletePartitionsLabels():
FUNCNAME = ogDeletePartitionsLabels.__name__
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(FUNCNAME, f"{FUNCNAME}", f"{FUNCNAME}")
return
subprocess.call(["rm", "/dev/disk/by-label/*"])
def ogInfoCache():
info = subprocess.check_output(["df", "-h"]).decode()
info = info.split("\n")
for line in info:
if "$OGCAC" in line:
infoFilesystem = line.split()[0]
infoSize = line.split()[1]
infoUsed = line.split()[2]
infoAvail = line.split()[3]
infoUsedPorcet = line.split()[4]
infoMountedOn = line.split()[5]
break
else:
return
if os.path.exists(f"{OGCAC}{OGIMG}"):
os.chdir(f"{OGCAC}{OPENGNSYS}")
content = subprocess.check_output(["find", "images/", "-type", "f"]).decode()
os.chdir("/")
print(info)
print(content)
print(" ")
else:
print(info)

View File

@ -0,0 +1,372 @@
import os
import sys
from engine.FileLib import *
from engine.InventoryLib import *
from engine.NetLib import *
from engine.RegistryLib import *
from engine.SystemLib import *
def ogCleanOs():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogCleanOs", "ogCleanOs int_ndisk int_nfilesys", "ogCleanOs 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT, "ogCleanOs int_ndisk int_nfilesys")
return
os_type = ogGetOsType(sys.argv[1], sys.argv[2])
if os_type == "Linux":
# Borramos los ficheros de dispositivos y los temporales.
ogCleanLinuxDevices(sys.argv[1], sys.argv[2])
os.system("rm -rf " + ogMount(sys.argv[1], sys.argv[2]) + "/tmp/*")
elif os_type == "Windows":
# Borrar ficheros de hibernación y paginación de Windows.
if ogGetPath(sys.argv[1], sys.argv[2], "pagefile.sys"):
ogDeleteFile(sys.argv[1], sys.argv[2], "pagefile.sys")
if ogGetPath(sys.argv[1], sys.argv[2], "hiberfil.sys"):
ogDeleteFile(sys.argv[1], sys.argv[2], "hiberfil.sys")
if ogGetPath(sys.argv[1], sys.argv[2], "swapfile.sys"):
ogDeleteFile(sys.argv[1], sys.argv[2], "swapfile.sys")
def ogInstallMiniSetup():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogInstallMiniSetup", "ogInstallFirstBoot ogInstallRunonce")
return
if len(sys.argv) == 4:
# Ejecución en el primer arranque de la máquina.
ogInstallFirstBoot(sys.argv[1], sys.argv[2], sys.argv[3])
elif len(sys.argv) == 7 or len(sys.argv) == 9:
# Ejecución en el "runonce".
ogInstallRunonce(*sys.argv[1:])
else:
ogRaiseError(OG_ERR_FORMAT)
def ogInstallFirstBoot():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogInstallFirstBoot", "ogInstallFirstBoot int_ndisk int_npartition str_filename", "ogInstallFirstBoot 1 1 filename.cmd")
return
# Error si no se reciben 3 parámetros.
if len(sys.argv) != 4:
ogRaiseError(OG_ERR_FORMAT)
return
MNTDIR = ogMount(sys.argv[1], sys.argv[2])
if not MNTDIR:
return
for i in ["winnt", "windows"]:
DIR = ogGetPath(os.path.join(MNTDIR, i, "system32"))
if DIR:
CMDDIR = DIR
break
else:
ogRaiseError(OG_ERR_NOTFOUND, os.path.join(MNTDIR, "windows", "system32"))
return
CMDFILE = os.path.join(CMDDIR, sys.argv[3])
# Creamos el archivo cmd y creamos un par de comandos para que una vez acabe la
# postconfiguracion resetee el mini setup, sino lo haria en cada arranque.
with open(CMDFILE, "w") as f:
f.write("""REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f
REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f""")
# Crear los valores de registro necesarios para que se haga la ejecución del .cmd al aranque.
ogSetRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\SystemSetupInProgress", 1)
ogSetRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\SetupType", 4)
#ogDeleteRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\CmdLine")
ogAddRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\CmdLine")
ogSetRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\CmdLine", "cmd.exe /c " + os.path.basename(CMDFILE))
def ogInstallRunonce():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogInstallRunonce", "ogInstallRunonce int_ndisk int_npartition str_filename str_adm_user str_adm_password bool_autologin [str_auto_user str_auto_password]", "ogInstallRunonce 1 1 filename.cmd administrator passadmin 1 userauto passuserauto", "ogInstallRunonce 1 1 filename.cmd administrator passadmin 0")
return
# Error si no se reciben 6 u 8 parámetros.
if len(sys.argv) != 6 and len(sys.argv) != 8:
ogRaiseError(OG_ERR_FORMAT)
return
MOUNTPOINT = ogGetPath(sys.argv[1], sys.argv[2], "/")
CMDDIR = None
# Comprobar que existe el directorio del fichero de comandos.
for i in ["winnt", "windows"]:
DIR = ogGetPath(os.path.join(MOUNTPOINT, i, "system32"))
if DIR:
CMDDIR = DIR
break
if not CMDDIR:
ogRaiseError(OG_ERR_NOTFOUND, os.path.join(MOUNTPOINT, "Windows", "System32"))
return
CMDFILE = os.path.join(CMDDIR, sys.argv[3])
if sys.argv[6] == "0":
# Si no queremos hacer autologin despues de la postconfiguracion lo indicamos en las claves de registro
with open(CMDFILE, "w") as f:
f.write("""DEL C:\ogboot.*
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "" /f
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /f""")
else:
# Si queremos hacer autologin despues de la postconfiguracion introducimos la informacion en las claves de registro
with open(CMDFILE, "w") as f:
f.write(f"""DEL C:\ogboot.*
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 1 /f
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "{sys.argv[7]}" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "{sys.argv[8]}" /f""")
# Creamos las claves de registro necesarias para que meter el cmd en el runonce del usuario y este haga autologin
ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\PostConfiguracion")
ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\PostConfiguracion", f"C:\\windows\\system32\\{sys.argv[3]}")
ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoAdminLogon")
ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoAdminLogon", "1")
ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultUserName")
ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultUserName", sys.argv[4])
ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultDomainName")
ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultDomainName", ".\\")
ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultPassword")
ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultPassword", sys.argv[5])
ogDeleteRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\ForceAutoLockOnLogon")
ogDeleteRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoLogonCount")
def ogAddCmd():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogAddCmd", "ogAddCmd int_ndisk int_npartition str_filename str_commands", "ogAddCmd 1 1 filename.cmd command")
return
# Error si no se reciben 4 parámetros.
if len(sys.argv) != 5:
ogRaiseError(OG_ERR_FORMAT)
return
MOUNTPOINT = ogMount(sys.argv[1], sys.argv[2])
if not MOUNTPOINT:
return
# Crear fichero de comandos, si no existe.
CMDFILE = ogGetPath(os.path.join(MOUNTPOINT, "windows", "system32"), sys.argv[3])
if not CMDFILE:
ogInstallMiniSetup(sys.argv[1], sys.argv[2], sys.argv[3])
CMDFILE = ogGetPath(os.path.join(MOUNTPOINT, "windows", "system32"), sys.argv[3])
if not CMDFILE:
ogRaiseError(OG_ERR_NOTFOUND, os.path.join(MOUNTPOINT, "windows", "system32", sys.argv[3]))
return
# Concatenamos el comando en el fichero de comandos
with open(CMDFILE, "a") as f:
f.write(sys.argv[4])
def ogDomainScript():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogDomainScript", "ogDomainScript int_ndisk int_npartition str_filename str_domain str_user str_password", "ogDomainScript 1 1 filename.cmd domain user password_user")
return
# Error si no se reciben 6 parámetros.
if len(sys.argv) != 7:
ogRaiseError(OG_ERR_FORMAT)
return
MOUNTPOINT = ogMount(sys.argv[1], sys.argv[2])
if not MOUNTPOINT:
return
# Comprobar que existe el directorio de comandos.
CMDDIR = ogGetPath(os.path.join(MOUNTPOINT, "windows", "system32"))
if not CMDDIR:
ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], "windows", "system32"))
return
# Añadimos en el cmd que se ejecutara al arranque, el comando de ejecutar el script que añade al dominio.
ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], "CSCRIPT joindomain.vbs")
# Eliminamos el script porque tiene el usuario de administrador de dominio en claro
ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], "DEL /Q C:\\Windows\\System32\\joindomain.vbs")
# Metemos unas claves de registro para que el dominio salga seleccionado por defecto
ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], f"REG ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultDomainName /t REG_SZ /d \"{sys.argv[4]}\" /f")
# Creamos el archivo joindomain.vbs que nos introduce la maquina en el dominio
with open(os.path.join(CMDDIR, "joindomain.vbs"), "w") as f:
f.write(f"""Const JOIN_DOMAIN = 1
Const ACCT_CREATE = 2
Const ACCT_DELETE = 4
Const WIN9X_UPGRADE = 16
Const DOMAIN_JOIN_IF_JOINED = 32
Const JOIN_UNSECURE = 64
Const MACHINE_PASSWORD_PASSED = 128
Const DEFERRED_SPN_SET = 256
Const INSTALL_INVOCATION = 262144
strDomain = "{sys.argv[4]}"
strUser = "{sys.argv[5]}"
strPassword = "{sys.argv[6]}"
Set objNetwork = CreateObject("WScript.Network")
strComputer = objNetwork.ComputerName
Set objComputer = GetObject("winmgmts:{{impersonationLevel=Impersonate}}!\\\\\" & _
strComputer & "\\root\\cimv2:Win32_ComputerSystem.Name='" & strComputer & "'")
ReturnValue = objComputer.JoinDomainOrWorkGroup(strDomain, strPassword, _
strDomain & "\\" & strUser, NULL, JOIN_DOMAIN + ACCT_CREATE)""")
def ogConfigureOgagent():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogConfigureOgagent", "ogConfigureOgagent int_ndisk int_nfilesys", "ogConfigureOgagent 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT, "ogConfigureOgagent int_ndisk int_nfilesys")
return
MNTDIR = ogMount(sys.argv[1], sys.argv[2])
if not MNTDIR:
return
# Comprobar si existe el fichero de configuración de OGAgent.
for AGENTDIR in ["usr/share/OGAgent", "Program Files/OGAgent", "Program Files (x86)/OGAgent", "Applications/OGAgent.app"]:
CFGFILE = ogGetPath(os.path.join(MNTDIR, AGENTDIR, "cfg", "ogagent.cfg"))
if CFGFILE:
break
else:
ogRaiseError(OG_ERR_NOTFOUND, "ogagent.cfg")
return
# Parchear dirección del servidor OpenGnsys en el fichero de configuración de OGAgent.
with open(CFGFILE, "r") as f:
lines = f.readlines()
with open(CFGFILE, "w") as f:
for line in lines:
if line.startswith("remote="):
line = "remote=https://" + ogGetServerIp() + "/opengnsys/rest/\n"
f.write(line)
def ogInstallLaunchDaemon():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogInstallLaunchDaemon", "ogInstallLaunchDaemon int_ndisk int_nfilesys str_scriptname", "ogInstallLaunchDaemon 1 2 postconf")
return
# Error si no se reciben 3 parámetros.
if len(sys.argv) != 4:
ogRaiseError(OG_ERR_FORMAT)
return
LAUNCHDIR = ogGetPath(sys.argv[1], sys.argv[2], "/Library/LaunchDaemons")
if not LAUNCHDIR:
ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], sys.argv[2], "/Library/LaunchDaemons"))
return
SCRIPTDIR = ogGetPath(sys.argv[1], sys.argv[2], "/usr/share")
if not SCRIPTDIR:
ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], sys.argv[2], "/usr/share"))
return
# Crear fichero de configuración del servicio de arranque.
with open(os.path.join(LAUNCHDIR, f"es.opengnsys.{sys.argv[3]}.plist"), "w") as f:
f.write("""<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>es.opengnsys.{}</string>
<key>ProgramArguments</key>
<array>
<string>{}/{}.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/{}.log</string>
<key>StandardErrorPath</key>
<string>/var/log/{}.err</string>
<true/>
</dict>
</plist>""".format(sys.argv[3], SCRIPTDIR, sys.argv[3], sys.argv[3], sys.argv[3]))
# Crear un fichero de script vacío.
with open(os.path.join(SCRIPTDIR, f"{sys.argv[3]}.sh"), "w") as f:
f.write("")
os.chmod(os.path.join(SCRIPTDIR, f"{sys.argv[3]}.sh"), 0o755)
def ogAddToLaunchDaemon():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogAddToLaunchDaemon", "ogAddToLaunchDaemon int_ndisk int_nfilesys str_scriptname str_command", "ogAddToLaunchDaemon 1 2 postconf \"diskutil enableJournal disk0s2\"")
return
# Error si no se reciben 4 parámetros.
if len(sys.argv) != 5:
ogRaiseError(OG_ERR_FORMAT)
return
SCRIPTDIR = ogGetPath(sys.argv[1], sys.argv[2], "/usr/share")
if not SCRIPTDIR:
ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], sys.argv[2], "/usr/share"))
return
# Comprobar que existe el fichero de comandos.
SCRIPTFILE = os.path.join(SCRIPTDIR, sys.argv[3] + ".sh")
if not os.path.exists(SCRIPTFILE):
ogRaiseError(OG_ERR_NOTFOUND, SCRIPTFILE)
return
# Concatenamos el comando en el fichero de comandos
with open(SCRIPTFILE, "a") as f:
f.write(sys.argv[4] + "\n")
def ogUninstallLinuxClient():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogUninstallLinuxClient", "ogUninstallLinuxClient int_ndisk int_filesys", "ogUninstallLinuxClient 1 1")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
MNTDIR = ogMount(sys.argv[1], sys.argv[2])
if not MNTDIR:
return
# Borrar ficheros y quitar llamada al cliente durante el proceso de inicio.
os.system(f"rm -f {MNTDIR}/{{usr/sbin,sbin,usr/local/sbin}}/ogAdmLnxClient")
os.system(f"rm -f {MNTDIR}/{{etc,usr/local/etc}}/ogAdmLnxClient.cfg")
os.system(f"sed -i -e '/ogAdmLnxClient/ d' {MNTDIR}/{{etc,usr/local/etc}}/{{rc.local,rc.d/rc.local}} 2>/dev/null")
def ogUninstallWindowsClient():
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp("ogUninstallWindowsClient", "ogUninstallWindowsClient int_ndisk int_filesys str_filename", "ogUninstallWindowsClient 1 1 filename.cmd")
return
# Error si no se reciben 3 parámetros.
if len(sys.argv) != 4:
ogRaiseError(OG_ERR_FORMAT)
return
MNTDIR = ogMount(sys.argv[1], sys.argv[2])
if not MNTDIR:
return
# Crear órdenes para desinstalar servicio y borrar ejecutable del cliente.
if ogGetPath(MNTDIR, "windows", "ogAdmWinClient.exe") or ogGetPath(MNTDIR, "winnt", "ogAdmWinClient.exe"):
ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], 'ogAdmWinClient -remove')
ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], 'DEL C:\\Windows\\ogAdmWinClient.exe')
ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], 'DEL C:\\Winnt\\ogAdmWinClient.exe')

View File

@ -0,0 +1,838 @@
import sys
import os
from engine.FileSystemLib import *
from engine.SystemLib import *
from engine.FileLib import *
from engine.NetLib import *
def ogUcastSyntax():
FUNCNAME = ogUcastSyntax.__name__
PARM = SESSION = SESSIONPARM = MODE = PORTBASE = PERROR = ADDRESS = TOOL = LEVEL = DEVICE = MBUFFER = SYNTAXSERVER = SYNTAXCLIENT = ""
# Si se solicita, mostrar ayuda.
if "help" in sys.argv or len(sys.argv) > 2 and sys.argv[2] == "help":
ogHelp(f"{FUNCNAME} SENDPARTITION str_sessionSERVER str_device str_tools str_level",
f"{FUNCNAME} RECEIVERPARTITION str_sessionCLIENT str_device str_tools str_level",
f"{FUNCNAME} SENDFILE str_sessionSERVER str_file",
f"{FUNCNAME} RECEIVERFILE str_sessionCLIENT str_file",
"sessionServer syntax: portbase:ipCLIENT-1:ipCLIENT-2:ipCLIENT-N",
"sessionServer example: 8000:172.17.36.11:172.17.36.12",
"sessionClient syntax: portbase:ipMASTER",
"sessionClient example: 8000:172.17.36.249")
return
PERROR = 0
# Error si no se reciben $PARM parámetros.
if "PARTITION" in sys.argv[1]:
PARM = 5
else:
PARM = 3
if len(sys.argv) != PARM:
ogRaiseError(OG_ERR_FORMAT, "sin parametros")
return
# 1er param check
if sys.argv[1] not in ["SENDPARTITION", "sendpartition", "RECEIVERPARTITION", "receiverpartition", "SENDFILE", "sendfile", "RECEIVERFILE", "receiverfile"]:
ogRaiseError(OG_ERR_FORMAT, f"1st param: {sys.argv[1]}")
PERROR = 1
# 2º param check
if "SEND" in sys.argv[1]:
MODE = "server"
else:
MODE = "client"
######### No controlamos el numero de elementos de la session unicast porque en el master es variable en numero
# TODO: diferenciamos los paramatros especificos de la sessión unicast
# SI: controlamos todos los parametros de la sessión unicast.
# [ $MODE == "client" ] && SESSIONPARM=2 || SESSIONPARM=6
OIFS = IFS
IFS = ':'
SESSION = sys.argv[2].split(':')
IFS = OIFS
# [[ ${#SESSION[*]} == $SESSIONPARM ]] || ogRaiseError $OG_ERR_FORMAT "parametros session multicast no completa" || PERROR=2# return $?
# controlamos el PORTBASE de la sesion. Comun.-
PORTBASE = SESSION[0]
if PORTBASE not in ["8000", "8001", "8002", "8003", "8004", "8005"]:
ogRaiseError(OG_ERR_FORMAT, f"McastSession portbase {SESSION[0]}")
PERROR = 3
if MODE == "server":
SIZEARRAY = len(SESSION)
for i in range(1, SIZEARRAY):
ADDRESS += f" -O {SESSION[i]}:{PORTBASE}"
# echo " -O ${SESSION[$i]}:$PORTBASE"
else:
ADDRESS = f"{SESSION[1]}:{PORTBASE}"
# 3er param check - que puede ser un dispositvo o un fichero.
# [ -n "$(ogGetPath "$3")" ] || ogRaiseError $OG_ERR_NOTFOUND " device or file $3" || PERROR=9 #return $?
DEVICE = sys.argv[3]
# 4 y 5 param check . solo si es sobre particiones.
if PARM == 5:
# 4 param check
if sys.argv[4] not in ["partclone", "PARTCLONE", "partimage", "PARTIMAGE", "ntfsclone", "NTFSCLONE"]:
ogRaiseError(OG_ERR_NOTFOUND, f" herramienta {sys.argv[4]} no soportada")
PERROR = 10
TOOL = sys.argv[4]
if sys.argv[5] not in ["lzop", "gzip", "LZOP", "GZIP", "0", "1"]:
ogRaiseError(OG_ERR_NOTFOUND, f" compresor {sys.argv[5]} no valido")
PERROR = 11
if PERROR != 0:
ogRaiseError(OG_ERR_UCASTSYNTAXT, f" {PERROR}")
return
# Generamos la instrucción base de unicast -Envio,Recepcion-
SYNTAXSERVER = f"mbuffer {ADDRESS}"
SYNTAXCLIENT = f"mbuffer -I {ADDRESS}"
if sys.argv[1] == "SENDPARTITION":
PROG1 = ogCreateImageSyntax(DEVICE, " ", TOOL, LEVEL).split("|")[0].split("|")[2].replace(">", "")
print(f"{PROG1} | {SYNTAXSERVER}")
elif sys.argv[1] == "RECEIVERPARTITION":
COMPRESSOR = ogRestoreImageSyntax(" ", DEVICE, TOOL, LEVEL).split("|")[0]
TOOLS = ogRestoreImageSyntax(" ", DEVICE, TOOL, LEVEL).split("|")[-1]
print(f"{SYNTAXCLIENT} | {COMPRESSOR} | {TOOLS}")
elif sys.argv[1] == "SENDFILE":
print(f"{SYNTAXSERVER} -i {sys.argv[3]}")
elif sys.argv[1] == "RECEIVERFILE":
print(f"{SYNTAXCLIENT} -i {sys.argv[3]}")
#
def ogUcastSendPartition():
FUNCNAME = ogUcastSendPartition.__name__
# Variables locales
PART = COMMAND = RETVAL = ""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} int_ndisk int_npart SessionUNICAST-SERVER tools compresor",
f"{FUNCNAME} 1 1 8000:172.17.36.11:172.17.36.12 partclone lzop")
return
# Error si no se reciben 5 parámetros.
if len(sys.argv) != 6:
ogRaiseError(OG_ERR_FORMAT)
return
# chequeamos la particion.
PART = ogDiskToDev(sys.argv[2], sys.argv[3])
if not PART:
return
ogUnmount(sys.argv[2], sys.argv[3])
# generamos la instrucción a ejecutar.
COMMAND = ogUcastSyntax("SENDPARTITION", sys.argv[4], PART, sys.argv[5], sys.argv[6])
RETVAL = 0
if RETVAL > 0:
return RETVAL
else:
print(COMMAND)
eval(COMMAND)
if RETVAL > 0:
ogRaiseError(OG_ERR_UCASTSENDPARTITION)
return RETVAL
#
def ogUcastReceiverPartition():
FUNCNAME = ogUcastReceiverPartition.__name__
# Variables locales
PART = COMMAND = RETVAL = ""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} int_ndisk int_npart SessionMulticastCLIENT tools compresor",
f"{FUNCNAME} 1 1 8000:ipMASTER partclone lzop")
return
# Error si no se reciben 5 parámetros.
if len(sys.argv) != 6:
ogRaiseError(OG_ERR_FORMAT)
return
# chequeamos la particion.
PART = ogDiskToDev(sys.argv[2], sys.argv[3])
if not PART:
return
ogUnmount(sys.argv[2], sys.argv[3])
# generamos la instrucción a ejecutar.
COMMAND = ogUcastSyntax("RECEIVERPARTITION", sys.argv[4], PART, sys.argv[5], sys.argv[6])
RETVAL = 0
if RETVAL > 0:
return RETVAL
else:
print(COMMAND)
eval(COMMAND)
if RETVAL > 0:
ogRaiseError(OG_ERR_UCASTRECEIVERPARTITION)
return RETVAL
#
def ogUcastSendFile():
FUNCNAME = ogUcastSendFile.__name__
# Variables locales
ARG = ARGS = SOURCE = TARGET = COMMAND = DEVICE = RETVAL = LOGFILE
# ARGS usado para controlar ubicación de la sesion multicast
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast(puerto:ip:ip:ip)",
f"{FUNCNAME} 1 1 /aula1/winxp.img 8000:172.17.36.11:172.17.36.12",
f"{FUNCNAME} REPO /aula1/ubuntu.iso sesionUcast",
f"{FUNCNAME} CACHE /aula1/winxp.img sesionUcast",
f"{FUNCNAME} /opt/opengnsys/images/aula1/hd500.vmx sesionUcast")
return
ARGS = sys.argv[1:]
if ARGS[0].startswith("/"):
SOURCE = ogGetPath(ARGS[0])
ARG = 2
DEVICE = ARGS[0]
elif ARGS[0].isdigit():
SOURCE = ogGetPath(ARGS[0], ARGS[1], ARGS[2])
ARG = 4
DEVICE = f"{ARGS[0]} {ARGS[1]} {ARGS[2]}"
else:
SOURCE = ogGetPath(ARGS[0], ARGS[1])
ARG = 3
DEVICE = f"{ARGS[0]} {ARGS[1]}"
# Error si no se reciben los argumentos ARG necesarios según la opcion.
if len(sys.argv) != ARG:
ogRaiseError(OG_ERR_FORMAT)
return
# Comprobar fichero origen
if not ogGetPath(SOURCE):
ogRaiseError(OG_ERR_NOTFOUND, f" device or file {DEVICE} not found")
return
SESSION = sys.argv[ARG]
# generamos la instrucción a ejecutar.
COMMAND = ogUcastSyntax("SENDFILE", SESSION, SOURCE)
RETVAL = 0
if RETVAL > 0:
return RETVAL
else:
print(COMMAND)
eval(COMMAND)
if RETVAL > 0:
ogRaiseError(OG_ERR_UCASTSENDFILE)
return RETVAL
#
def ogMcastSyntax():
FUNCNAME = ogMcastSyntax.__name__
PERROR = 0
# Si se solicita, mostrar ayuda.
if "help" in sys.argv or len(sys.argv) > 2 and sys.argv[2] == "help":
ogHelp(f"{FUNCNAME} SENDPARTITION str_sessionSERVER str_device str_tools str_level",
f"{FUNCNAME} RECEIVERPARTITION str_sessionCLIENT str_device str_tools str_level",
f"{FUNCNAME} SENDFILE str_sessionSERVER str_file",
f"{FUNCNAME} RECEIVERFILE str_sessionCLIENT str_file",
"sessionServer syntax: portbase:method:mcastaddress:speed:nclients:ntimeWaitingUntilNclients",
"sessionServer example: 9000:full-duplex|half-duplex|broadcast:239.194.17.36:80M:50:60",
"sessionClient syntax: portbase",
"sessionClient example: 9000",
"sessionClient syntax: portbase:serverIP:TimeOut_session:TimeOut_transmision",
"sessionClient example: 9000:172.17.88.161:40:120")
return
# BEGIN NUMBERS PARAMETERS CHECK AND SESSION OPTIONS IF CLIENT OR SERVER
if "PARTITION" in sys.argv[1]:
PARM = 5
else:
PARM = 3
if len(sys.argv) != PARM:
ogRaiseError(OG_ERR_FORMAT, "sin parametros")
return
ogCheckStringInGroup(sys.argv[1], "SENDPARTITION sendpartition RECEIVERPARTITION receiverpartition SENDFILE sendfile RECEIVERFILE receiverfile") or ogRaiseError(OG_ERR_FORMAT, f"1st param: {sys.argv[1]}") or PERROR = 1
if "SEND" in sys.argv[1]:
MODE = "server"
else:
MODE = "client"
SESSION = sys.argv[2].split(':')
if MODE == "client":
SESSIONPARM = 1
else:
SESSIONPARM = 6
if len(SESSION) != SESSIONPARM:
ogRaiseError(OG_ERR_FORMAT, "parametros session de cliente multicast no completa") or PERROR = 2
if MODE == "server":
ogCheckStringInGroup(SESSION[1], "full-duplex FULL-DUPLEX half-duplex HALF-DUPLEX broadcast BROADCAST") or ogRaiseError(OG_ERR_FORMAT, f"McastSession method {SESSION[1]}") or PERROR = 4
ogCheckIpAddress(SESSION[2]) or ogRaiseError(OG_ERR_FORMAT, f"McastSession address {SESSION[2]}") or PERROR = 5
ogCheckStringInReg(SESSION[3], "^[0-9]{1,3}\M$") or ogRaiseError(OG_ERR_FORMAT, f"McastSession bitrate {SESSION[3]}") or PERROR = 6
ogCheckStringInReg(SESSION[4], "^[0-9]{1,10}$") or ogRaiseError(OG_ERR_FORMAT, f"McastSession nclients {SESSION[4]}") or PERROR = 7
ogCheckStringInReg(SESSION[5], "^[0-9]{1,10}$") or ogRaiseError(OG_ERR_FORMAT, f"McastSession maxtime {SESSION[5]}") or PERROR = 8
if PERROR != 0:
ogRaiseError(OG_ERR_MCASTSYNTAXT, f" {PERROR}")
return
# END NUMBERS PARAMETERS CHECK
# BEGIN SERVER SESSION
if MODE == "server":
PORTBASE = SESSION[0]
METHOD = SESSION[1]
ADDRESS = SESSION[2]
BITRATE = SESSION[3]
NCLIENTS = SESSION[4]
MAXTIME = SESSION[5]
CERROR = "8x8/128"
if "mbuffer" in sys.modules:
MBUFFER = " --pipe 'mbuffer -q -m 20M' "
else:
MBUFFER = ""
SYNTAXSERVER = f"udp-sender {MBUFFER} --nokbd --portbase {PORTBASE} --{METHOD} --mcast-data-address {ADDRESS} --fec {CERROR} --max-bitrate {BITRATE} --ttl 16 --min-clients {NCLIENTS} --max-wait {MAXTIME} --autostart {MAXTIME} --log /tmp/mcast.log"
# END SERVER SESSION
# BEGIN CLIENT SESSION
if MODE == "client":
PORTBASE = SESSION[0]
if ogCheckIpAddress(SESSION[1]):
SERVERADDRESS = f" --mcast-rdv-address {SESSION[1]}"
else:
REPOIP = ogGetRepoIp()
CLIENTIP = " ".join([addr.split("/")[0] for addr in subprocess.check_output(["ip", "-o", "address", "show", "up"]).decode().splitlines() if "lo" not in addr])
MASCARA = CLIENTIP.split("/")[1]
CLIENTIP = CLIENTIP.split("/")[0]
RIPBT = ""
IPBT = ""
for i in range(1, 5):
RIP = str(int(REPOIP.split(".")[i-1]) + 256)
RIPB = ""
while RIP > 0:
COCIENTE = RIP // 2
RESTO = RIP % 2
RIPB = str(RESTO) + RIPB
RIP = COCIENTE
RIPB = RIPB[1:]
RIPBT += RIPB
IP = str(int(CLIENTIP.split(".")[i-1]) + 256)
IPB = ""
while IP > 0:
COCIENTE = IP // 2
RESTO = IP % 2
IPB = str(RESTO) + IPB
IP = COCIENTE
IPB = IPB[1:]
IPBT += IPB
REPOSUBRED = RIPBT[:MASCARA]
CLIENTSUBRED = IPBT[:MASCARA]
if REPOSUBRED == CLIENTSUBRED:
SERVERADDRESS = ""
else:
SERVERADDRESS = f" --mcast-rdv-address {REPOIP}"
if ogCheckStringInReg(SESSION[2], "^[0-9]{1,10}$"):
if SESSION[2] == "0":
STARTTIMEOUT = ""
else:
STARTTIMEOUT = f" --start-timeout {SESSION[2]}"
else:
STARTTIMEOUT = ""
if ogCheckStringInReg(SESSION[3], "^[0-9]{1,10}$"):
if SESSION[3] == "0":
RECEIVERTIMEOUT = ""
else:
RECEIVERTIMEOUT = f" --receive-timeout {SESSION[3]}"
else:
RECEIVERTIMEOUT = ""
if "udp-receiver" not in ISUDPCAST:
STARTTIMEOUT = ""
RECEIVERTIMEOUT = ""
SYNTAXCLIENT = f"udp-receiver {MBUFFER} --portbase {PORTBASE}{SERVERADDRESS}{STARTTIMEOUT}{RECEIVERTIMEOUT} --log /tmp/mcast.log"
# END CLIENT SESSION
# BEGIN MAIN PROGRAM
if sys.argv[1] == "SENDPARTITION":
PROG1 = ogCreateImageSyntax(DEVICE, " ", TOOL, LEVEL).split("|")[0].split("|")[2].replace(">", "")
print(f"{PROG1} | {SYNTAXSERVER}")
elif sys.argv[1] == "RECEIVERPARTITION":
COMPRESSOR = ogRestoreImageSyntax(" ", DEVICE, TOOL, LEVEL).split("|")[0]
TOOLS = ogRestoreImageSyntax(" ", DEVICE, TOOL, LEVEL).split("|")[-1]
print(f"{SYNTAXCLIENT} | {COMPRESSOR} | {TOOLS}")
elif sys.argv[1] == "SENDFILE":
print(f"{SYNTAXSERVER} --file {sys.argv[3]}")
elif sys.argv[1] == "RECEIVERFILE":
print(f"{SYNTAXCLIENT} --file {sys.argv[3]}")
# END MAIN PROGRAM
#
def ogMcastSendFile():
FUNCNAME = ogMcastSendFile.__name__
# Variables locales
ARGS = ARG = SOURCE = TARGET = COMMAND = DEVICE = RETVAL = LOGFILE
# LOGFILE = "/tmp/mcast.log"
# ARGS usado para controlar ubicación de la sesion multicast
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast",
f"{FUNCNAME} 1 1 /aula1/winxp.img sesionMcast",
f"{FUNCNAME} REPO /aula1/ubuntu.iso sesionMcast",
f"{FUNCNAME} CACHE /aula1/winxp.img sesionMcast",
f"{FUNCNAME} /opt/opengnsys/images/aula1/hd500.vmx sesionMcast")
return
ARGS = sys.argv[1:]
if ARGS[0].startswith("/"):
SOURCE = ogGetPath(ARGS[0])
ARG = 2
DEVICE = ARGS[0]
elif ARGS[0].isdigit():
SOURCE = ogGetPath(ARGS[0], ARGS[1], ARGS[2])
ARG = 4
DEVICE = f"{ARGS[0]} {ARGS[1]} {ARGS[2]}"
else:
SOURCE = ogGetPath(ARGS[0], ARGS[1])
ARG = 3
DEVICE = f"{ARGS[0]} {ARGS[1]}"
# Error si no se reciben los argumentos ARG necesarios según la opcion.
if len(sys.argv) != ARG:
ogRaiseError(OG_ERR_FORMAT)
return
# Comprobar fichero origen
if not ogGetPath(SOURCE):
ogRaiseError(OG_ERR_NOTFOUND, f" device or file {DEVICE} not found")
return
SESSION = sys.argv[ARG]
# generamos la instrucción a ejecutar.
COMMAND = ogMcastSyntax("SENDFILE", SESSION, SOURCE)
RETVAL = 0
if RETVAL > 0:
return RETVAL
else:
print(COMMAND)
eval(COMMAND)
if RETVAL > 0:
ogRaiseError(OG_ERR_MCASTSENDFILE)
return RETVAL
#
def ogMcastReceiverFile():
# Variables locales
FUNCNAME = ogMcastReceiverFile.__name__
ARGS = ARG = TARGETDIR = TARGETFILE = COMMAND = ""
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} [str_portMcast] [[Relative_path_file] | [str_REPOSITORY path_file] | [int_ndisk int_npart path_file]]",
f"{FUNCNAME} 9000 /PS1_PH1.img",
f"{FUNCNAME} 9000 CACHE /aula1/PS2_PH4.img",
f"{FUNCNAME} 9000 1 1 /isos/linux.iso")
return
ARGS = sys.argv[1:]
if ARGS[1].startswith("/"):
TARGETDIR = ogGetParentPath(ARGS[1])
ARG = 2
elif ARGS[1].isdigit():
TARGETDIR = ogGetParentPath(ARGS[1], ARGS[2], ARGS[3])
ARG = 4
else:
TARGETDIR = ogGetParentPath(ARGS[1], ARGS[2])
ARG = 3
# Error si no se reciben los argumentos ARG necesarios según la opcion.
if len(sys.argv) != ARG:
ogRaiseError(OG_ERR_FORMAT, "Parametros no admitidos")
return
# obtenemos el nombre del fichero a descargar.
TARGETFILE = os.path.basename(ARGS[ARG])
# generamos la instrucción a ejecutar.
COMMAND = ogMcastSyntax("RECEIVERFILE", sys.argv[1], f"{TARGETDIR}/{TARGETFILE}")
RETVAL = 0
if RETVAL > 0:
return RETVAL
else:
print(COMMAND)
eval(COMMAND)
if RETVAL > 0:
ogRaiseError(OG_ERR_MCASTRECEIVERFILE, TARGETFILE)
return RETVAL
#[ -s "$LOGFILE" ] || return 21
#
def ogMcastSendPartition():
FUNCNAME = ogMcastSendPartition.__name__
# Variables locales
PART = ""
COMMAND = ""
RETVAL = 0
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} int_ndisk int_npart SessionMulticastSERVER tools compresor",
f"{FUNCNAME} 1 1 9000:full-duplex:239.194.37.31:50M:20:2 partclone lzop")
return
# Error si no se reciben 5 parámetros.
if len(sys.argv) != 6:
ogRaiseError(OG_ERR_FORMAT)
return
# chequeamos la particion.
PART = ogDiskToDev(sys.argv[2], sys.argv[3])
if not PART:
return
ogUnmount(sys.argv[2], sys.argv[3])
# generamos la instrucción a ejecutar.
COMMAND = ogMcastSyntax("SENDPARTITION", sys.argv[4], PART, sys.argv[5], sys.argv[6])
RETVAL = 0
if RETVAL > 0:
return RETVAL
else:
print(COMMAND)
eval(COMMAND)
if RETVAL > 0:
ogRaiseError(OG_ERR_MCASTSENDPARTITION)
return RETVAL
#
def ogMcastReceiverPartition():
FUNCNAME = ogMcastReceiverPartition.__name__
# Variables locales
PART = ""
COMMAND = ""
RETVAL = 0
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} int_ndisk int_npart SessionMulticastCLIENT tools compresor",
f"{FUNCNAME} 1 1 9000 partclone lzop")
return
# Error si no se reciben 5 parámetros.
if len(sys.argv) != 6:
ogRaiseError(OG_ERR_FORMAT)
return
# chequeamos la particion.
PART = ogDiskToDev(sys.argv[2], sys.argv[3])
if not PART:
return
ogUnmount(sys.argv[2], sys.argv[3])
# generamos la instrucción a ejecutar.
COMMAND = ogMcastSyntax("RECEIVERPARTITION", sys.argv[4], PART, sys.argv[5], sys.argv[6])
RETVAL = 0
if RETVAL > 0:
return RETVAL
else:
print(COMMAND)
eval(COMMAND)
if RETVAL > 0:
ogRaiseError(OG_ERR_MCASTSENDPARTITION)
return RETVAL
#
def ogMcastRequest():
# Variables locales
FILE = ""
PROTOOPT = ""
PORT = ""
PORTAUX = ""
REPOIP = ""
REPOPORTAUX = ""
REPEAT = 0
OGUNIT = "$(df|awk '/ogimages/ {print $1}'|cut -d/ -f5)/"
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} path_filename str_mcastoptions")
return
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
ogRaiseError(OG_ERR_FORMAT)
return
FILE = f"{OGUNIT}{sys.argv[1]}"
PROTOOPT = sys.argv[2]
# TODO: CONTROL PARAMETROS
PORT = PROTOOPT.split(":")[0]
PORTAUX = str(int(PORT) + 1)
REPOIP = ogGetRepoIp()
REPOPORTAUX = 2009
REPEAT = 0
while not nmap -n -sU -p $PORTAUX $REPOIP | grep open:
REPEAT += 1
if REPEAT >= 6:
ogRaiseError("session log", OG_ERR_PROTOCOLJOINMASTER, f"MULTICAST {FILE} {PROTOOPT} {FILELIST}")
return
print(f"{MSG_SCRIPTS_TASK_START}: hose {REPOIP} {REPOPORTAUX} --out sh -c 'echo -ne START_MULTICAST {FILE} {PROTOOPT}'")
# update-cache:
hose(REPOIP, REPOPORTAUX, "--out sh -c 'echo -ne START_MULTICAST {FILE} {PROTOOPT}'")
# multicas-direct: hose {REPOIP} 2009 --out sh -c 'echo -ne START_MULTICAST /{IMAGE}.img {OPTPROTOCOLO}'
time.sleep(10)
#
def ogTorrentStart():
FUNCNAME = ogTorrentStart.__name__
ERROR = 0
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} [str_repo] [[Relative_path_fileTORRENT] | [str_REPOSITORY path_fileTORRENT] | [int_ndisk int_npart path_fileTORRENT]] SessionTorrent",
f"{FUNCNAME} CACHE /PS1_PH1.img.torrent seeder:10000",
f"{FUNCNAME} /opt/opengnsys/cache/linux.iso peer:60",
f"{FUNCNAME} 1 1 /linux.iso.torrent leecher:60")
return
ARGS = sys.argv[1:]
if ARGS[0].startswith("/"):
SOURCE = ogGetPath(ARGS[0])
ARG = 2
elif ARGS[0].isdigit():
SOURCE = ogGetPath(ARGS[0], ARGS[1], ARGS[2])
ARG = 4
else:
SOURCE = ogGetPath(ARGS[0], ARGS[1])
ARG = 3
# Error si no se reciben los argumentos ARG necesarios según la opcion.
if len(sys.argv) != ARG:
ogRaiseError(OG_ERR_FORMAT, "Parametros no admitidos")
return
# Controlar source, que no se haga al repo.
if ARG == 3:
if not ogCheckStringInGroup(ARGS[0], "CACHE cache"):
ogRaiseError(OG_ERR_FORMAT, "La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación")
return
if ARG == 2:
if ogCheckStringInReg(ARGS[0], "^/opt/opengnsys/images"):
ogRaiseError(OG_ERR_FORMAT, "La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación")
return
# Controlar el source, para que sea un torrent.
if subprocess.call(['ctorrent', '-x', SOURCE], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) != 0:
ogRaiseError(OG_ERR_NOTFOUND, f"{ARGS[0]}")
return
TARGET = SOURCE.rsplit('.torrent', 1)[0]
DIRSOURCE = ogGetParentPath(SOURCE)
os.chdir(DIRSOURCE)
SESSION = ARGS[ARG - 1]
SESSION = SESSION.split(':')
if len(SESSION) != 2:
ogRaiseError(OG_ERR_FORMAT, "parametros session Torrent no completa: modo:tiempo")
ERROR = 1
# Controlamos el modo de operación del cliente.
if not ogCheckStringInGroup(SESSION[0], "seeder SEEDER peer PEER leecher LEECHER"):
ogRaiseError(OG_ERR_FORMAT, f"valor modo Torrent no valido {SESSION[0]}")
ERROR = 1
MODE = SESSION[0]
# Controlamos el tiempo para el seeder o una vez descargada la imagen como peer o leecher.
if not ogCheckStringInReg(SESSION[1], "^[0-9]{1,10}$"):
ogRaiseError(OG_ERR_FORMAT, f"valor tiempo no valido {SESSION[1]}")
ERROR = 1
TIME = SESSION[1]
# Si ha habido error en el control de parametros error.
if ERROR == 1:
return 1
# Si No fichero .bf, y Si fichero destino imagen ya descargada y su chequeo fue comprobado en su descarga inicial.
if not os.path.isfile(f"{SOURCE}.bf") and os.path.isfile(TARGET):
print("imagen ya descargada")
if MODE.lower() == "seeder":
print("MODE seeder ctorrent")
subprocess.Popen(['sleep', TIME, '&&', 'kill', '-2', str(subprocess.check_output(['pidof', 'ctorrent']).strip())], shell=True)
subprocess.call(['ctorrent', '-f', SOURCE])
return 0
# Si no existe bf ni fichero destino descarga inicial.
if not os.path.isfile(f"{SOURCE}.bf") and not os.path.isfile(TARGET):
OPTION = "DOWNLOAD"
print("descarga inicial")
# Si fichero bf descarga anterior no completada.
if os.path.isfile(f"{SOURCE}.bf") and os.path.isfile(TARGET):
print("Continuar con Descargar inicial no terminada.")
OPTION = "DOWNLOAD"
if OPTION == "DOWNLOAD":
if MODE.lower() == "peer":
print("Downloading Torrent as peer")
open(f"{SOURCE}.bf", 'a').close()
subprocess.call(['ctorrent', '-f', '-c', '-X', f"sleep {TIME}; kill -2 $(pidof ctorrent)", '-C', '100', SOURCE, '-s', TARGET, '-b', f"{SOURCE}.bfog"])
elif MODE.lower() == "leecher":
print("Downloading Torrent as leecher")
subprocess.call(['ctorrent', SOURCE, '-X', f"sleep 30; kill -2 $(pidof ctorrent)", '-C', '100', '-U', '0'])
elif MODE.lower() == "seeder":
print("MODE seeder ctorrent")
open(f"{SOURCE}.bf", 'a').close()
subprocess.call(['ctorrent', '-f', '-c', '-X', f"sleep {TIME}; kill -2 $(pidof ctorrent)", '-C', '100', SOURCE, '-s', TARGET, '-b', f"{SOURCE}.bfog"])
os.chdir('/tmp')
def ogCreateTorrent():
FUNCNAME = ogCreateTorrent.__name__
ERROR = 0
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME} [str_REPOSITORY] [int_ndisk int_npart] Relative_path_file IpBttrack",
f"{FUNCNAME} 1 1 /aula1/winxp 10.1.15.23",
f"{FUNCNAME} REPO /aula1/winxp 10.1.15.45")
return
ARGS = sys.argv[1:]
if ARGS[0].startswith("/"):
SOURCE = ogGetPath(f"{ARGS[0]}.img")
ARG = 2
elif ARGS[0].isdigit():
SOURCE = ogGetPath(ARGS[0], ARGS[1], f"{ARGS[2]}.img")
ARG = 4
else:
EXT = ogGetImageType(ARGS[0], ARGS[1])
SOURCE = ogGetPath(ARGS[0], f"{ARGS[1]}.{EXT}")
ARG = 3
# Error si no se reciben los argumentos ARG necesarios según la opcion.
if len(sys.argv) != ARG + 1:
ogRaiseError(OG_ERR_FORMAT)
return
# Error si no existe la imagen
if not SOURCE:
ogRaiseError(OG_ERR_NOTFOUND)
return
if os.path.isfile(f"{SOURCE}.torrent"):
os.rename(f"{SOURCE}.torrent", f"{SOURCE}.torrent.ant")
print("Esperamos que se refresque el servidor")
time.sleep(20)
IPTORRENT = sys.argv[ARG]
# Si ponemos el path completo cuando creamos el fichero torrent da error
os.chdir(os.path.dirname(SOURCE))
print(f"ctorrent -t {os.path.basename(SOURCE)} -u http://{IPTORRENT}:6969/announce -s {SOURCE}.torrent")
subprocess.call(['ctorrent', '-t', os.path.basename(SOURCE), '-u', f"http://{IPTORRENT}:6969/announce", '-s', f"{SOURCE}.torrent"])
def ogUpdateCacheIsNecesary(repo, relative_path_image, protocol=""):
ERROR = 0
# Si se solicita, mostrar ayuda.
if repo == "help":
ogHelp("ogUpdateCacheIsNecesary", "ogUpdateCacheIsNecesary str_repo relative_path_image [protocol|FULL]",
"ogUpdateCacheIsNecesary REPO /PS1_PH1.img UNICAST",
"ogUpdateCacheIsNecesary REPO /ogclient.sqfs FULL")
return
# Control de la cache
if not ogFindCache():
ogRaiseError(OG_ERR_NOTCACHE)
return 1
# Control de parametros: ahora admite tres.
if not repo or not relative_path_image:
ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: ogUpdateCacheIsNecesary str_repo relative_path_image [protocol|FULL]")
return 1
if repo not in ["REPO", "repo"]:
ogRaiseError(OG_ERR_NOTFOUND, f"{repo} {relative_path_image}")
return 1
FILESOURCE = ogGetPath(repo, relative_path_image)
if not FILESOURCE:
ogRaiseError(OG_ERR_NOTFOUND, f"{repo} {relative_path_image}")
return 1
FILETARGET = ogGetPath("CACHE", relative_path_image)
if not FILETARGET:
# Borramos el fichero bf del torrent, en el caso de que se hubiese quedado de algun proceso fallido
if ogGetPath("CACHE", f"/{relative_path_image}.torrent.bf"):
ogDeleteFile("CACHE", f"/{relative_path_image}.torrent.bf")
if ogGetPath("CACHE", f"/{relative_path_image}.sum"):
ogDeleteFile("CACHE", f"/{relative_path_image}.sum")
if ogGetPath("CACHE", f"/{relative_path_image}.full.sum"):
ogDeleteFile("CACHE", f"/{relative_path_image}.full.sum")
print("TRUE(0), es necesario actualizar. Paso 1, la cache no contiene esa imagen")
return 0
if ogGetPath(f"{FILETARGET}.torrent.bf"):
print("TRUE(0), es necesario actualizar. Paso 2, la imagen esta en un estado de descarga torrent interrumpido")
return 0
protocol = protocol.upper()
if protocol in ["FULL", "TORRENT"]:
if os.path.isfile(f"{FILESOURCE}.full.sum"):
with open(f"{FILESOURCE}.full.sum") as f:
MD5SOURCE = f.read().strip()
else:
MD5SOURCE = ogCalculateFullChecksum(FILESOURCE)
if not os.path.isfile(f"{FILETARGET}.full.sum"):
with open(f"{FILETARGET}.full.sum", "w") as f:
f.write(ogCalculateFullChecksum(FILETARGET))
with open(f"{FILETARGET}.full.sum") as f:
MD5TARGET = f.read().strip()
if not os.path.isfile(f"{FILETARGET}.sum"):
with open(f"{FILETARGET}.sum", "w") as f:
f.write(ogCalculateChecksum(FILETARGET))
else:
if os.path.isfile(f"{FILESOURCE}.sum"):
with open(f"{FILESOURCE}.sum") as f:
MD5SOURCE = f.read().strip()
else:
MD5SOURCE = ogCalculateChecksum(FILESOURCE)
if not os.path.isfile(f"{FILETARGET}.sum"):
with open(f"{FILETARGET}.sum", "w") as f:
f.write(ogCalculateChecksum(FILETARGET))
with open(f"{FILETARGET}.sum") as f:
MD5TARGET = f.read().strip()
if not os.path.isfile(f"{FILETARGET}.full.sum") and os.path.isfile(f"{FILETARGET}.sum"):
if os.path.isfile(f"{FILESOURCE}.full.sum"):
shutil.copy(f"{FILESOURCE}.full.sum", f"{FILETARGET}.full.sum")
else:
with open(f"{FILETARGET}.full.sum", "w") as f:
f.write(ogCalculateFullChecksum(FILETARGET))
if MD5SOURCE == MD5TARGET:
print("FALSE (1), No es neceario actualizar. Paso5.A la imagen esta en cache")
return 1
else:
print("imagen en cache distinta, borramos la imagen anterior")
os.remove(FILETARGET)
os.remove(f"{FILETARGET}.sum")
os.remove(f"{FILETARGET}.torrent")
os.remove(f"{FILETARGET}.full.sum")
print("TRUE (0), Si es necesario actualizar.")
return 0

View File

@ -0,0 +1,179 @@
import subprocess
import os
import re
from engine.FileLib import *
from engine.SystemLib import *
def chntpw(*args):
chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip()
if not chntpw_path:
chntpw_path = subprocess.check_output(['which', 'chntpw']).decode().strip()
subprocess.run([chntpw_path, '-e'] + list(args), timeout=5)
def ogAddRegistryKey(path_mountpoint, str_hive, str_key):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Añadir nueva clave.
chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0])
chntpw(FILE, 'nk', str_key.rsplit('\\', 1)[-1])
chntpw(FILE, 'q')
chntpw(FILE, 'y')
def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Determine the value type.
if str_valuetype.upper() == 'STRING' or str_valuetype == '':
TYPE = 1
elif str_valuetype.upper() == 'BINARY':
TYPE = 3
elif str_valuetype.upper() == 'DWORD':
TYPE = 4
else:
ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype)
return
# Add the registry value.
chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0])
chntpw(FILE, 'nv', str_valuename.rsplit('\\', 1)[-1], TYPE)
chntpw(FILE, 'q')
chntpw(FILE, 'y')
def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Delete the registry key.
subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5)
def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Delete the registry value.
chntpw(FILE, 'cd', str_valuename.rsplit('\\', 1)[0])
chntpw(FILE, 'dv', str_valuename.rsplit('\\', 1)[-1])
chntpw(FILE, 'q')
chntpw(FILE, 'y')
def ogGetHivePath(path_mountpoint, str_hive):
# Variables locales.
FILE = None
# Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad).
FILE = ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}")
if not FILE:
FILE = ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT")
if not FILE:
FILE = ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}")
if not FILE:
FILE = ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT")
if FILE and os.path.isfile(FILE):
return FILE
else:
ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}")
return None
def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Devolver el dato del valor de registro.
chntpw_cmd = f'''
chntpw "{FILE}" << EOT 2> /dev/null | awk '/> Value/ {{
if (index($0, "REG_BINARY") > 0) {{
data=""
}} else {{
getline
data=$0
}}
}}
/^:[0-9A-F]+ / {{
data=data""substr($0, 9, 48)
}}
END {{
print data
}}'
cd {str_valuename.rsplit('\\', 1)[0]}
cat {str_valuename.rsplit('\\', 1)[-1]}
q
EOT
'''
subprocess.run(chntpw_cmd, shell=True, timeout=5)
def ogListRegistryKeys(path_mountpoint, str_hive, str_key):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Devolver la lista de claves de registro.
chntpw_cmd = f'''
chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/^ $/ {{print $2}}'
ls {str_key}
q
EOT
'''
subprocess.run(chntpw_cmd, shell=True, timeout=5)
def ogListRegistryValues(path_mountpoint, str_hive, str_key):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Devolver la lista de valores de registro.
chntpw_cmd = f'''
chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/REG_/ {{print $2}}'
ls {str_key}
q
EOT
'''
subprocess.run(chntpw_cmd, shell=True, timeout=5)
def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data):
# Variables locales.
FILE = ogGetHivePath(path_mountpoint, str_hive)
if not FILE:
return
# Fichero temporal para componer la entrada al comando "chntpw".
tmpfile = "/tmp/chntpw$$"
try:
# Comprobar tipo de datos del valor del registro.
with open(tmpfile, 'w') as f:
f.write(f"ls {str_valuename.rsplit('\\', 1)[0]}\nq\n")
output = subprocess.check_output(['chntpw', FILE], input=open(tmpfile, 'rb'), stderr=subprocess.DEVNULL).decode()
if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output:
# Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales).
if not re.match(r'^([0-9A-F]{2} )*$', str_data):
ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"')
return
n = len(str_data) + 1
with open(tmpfile, 'w') as f:
f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{int(n/3)}\n")
for i in range(0, n, 48):
f.write(f":{i//3:05x} {str_data[i:i+48]}\n")
f.write("s\nq\ny\n")
else:
# Cambiar el dato del valor de registro para cadenas y bytes.
with open(tmpfile, 'w') as f:
f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{str_data}\nq\ny\n")
# Aplicar cambios.
subprocess.run(['chntpw', FILE], input=open(tmpfile, 'rb'), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
finally:
os.remove(tmpfile)

631
client/engine/RsyncLib.py Normal file
View File

@ -0,0 +1,631 @@
import subprocess
import sys
import os
import shutil
import time
from engine.DiskLib import *
from engine.FileSystemLib import *
from engine.FileLib import *
from engine.NetLib import *
# Example usage:
#rsync("-a", "-v", "source/", "destination/")
def rsync(*args):
RSYNC = subprocess.check_output(["which", "rsync"]).decode().strip()
if sys.platform == "linux" and sys.maxsize <= 2**32 and RSYNC == "":
RSYNC = "/opt/opengnsys/bin/rsync"
subprocess.run([RSYNC] + list(args))
def ogCreateFileImage():
SIZEREQUIRED = int(sys.argv[4])
if SIZEREQUIRED < 300000:
SIZEREQUIRED = 300000
KERNELVERSION = ".".join([str(int(num)) for num in platform.release().split(".")])
if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
IMGDIR = ogGetParentPath(sys.argv[1], "/" + sys.argv[2])
if sys.argv[3] == "img":
IMGEXT = "img"
else:
IMGEXT = "img.diff"
IMGFILE = f"{IMGDIR}/{os.path.basename('/' + sys.argv[2])}.{IMGEXT}"
if not os.path.exists(IMGDIR):
ogEcho("log session", f" {MSG_HELP_ogMakeDir} \"{sys.argv[1]} {os.path.dirname('/' + sys.argv[2])}.\"")
ogMakeDir(sys.argv[1], os.path.dirname('/' + sys.argv[2]))
IMGDIR = ogGetParentPath(sys.argv[1], "/" + sys.argv[2])
DIRMOUNT = f"/tmp/{ogGetMountImageDir(sys.argv[2], sys.argv[3])}"
os.makedirs(DIRMOUNT, exist_ok=True)
LOOPDEVICE = subprocess.run(["losetup", "-f"], capture_output=True, text=True).stdout.strip()
if os.path.isfile(IMGFILE):
if os.path.isfile(f"{IMGFILE}.ant"):
if BACKUP == "true" or BACKUP == "TRUE":
ogEcho("log session", f" {MSG_SCRIPTS_FILE_RENAME} \"{IMGFILE}\" -> \"{IMGFILE}.ant\".")
shutil.copy2(IMGFILE, f"{IMGFILE}.ant")
os.rename(f"{IMGFILE}.torrent", f"{IMGFILE}.torrent.ant")
os.remove(f"{IMGFILE}.sum")
IMGSIZE = os.path.getsize(IMGFILE)
if IMGSIZE < SIZEREQUIRED:
ogEcho("log session", f" {MSG_SYNC_RESIZE}")
print(f" truncate --size=>{SIZEREQUIRED}k {IMGFILE}")
subprocess.run(["truncate", f"--size={SIZEREQUIRED}k", IMGFILE], capture_output=True, text=True)
if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
subprocess.run(["losetup", LOOPDEVICE, IMGFILE])
print(f" resize2fs -f {LOOPDEVICE}")
subprocess.run(["resize2fs", "-f", LOOPDEVICE], capture_output=True, text=True)
else:
print(f" ogMountImage {sys.argv[1]} {sys.argv[2]} {sys.argv[3]}")
ogMountImage(sys.argv[1], sys.argv[2], sys.argv[3])
print(f" btrfs filesystem resize max {DIRMOUNT}")
subprocess.run(["btrfs", "filesystem", "resize", "max", DIRMOUNT], capture_output=True, text=True)
else:
open(IMGFILE, "w").close()
print(f" truncate --size=>{SIZEREQUIRED}k {IMGFILE}")
subprocess.run(["truncate", f"--size={SIZEREQUIRED}k", IMGFILE], capture_output=True, text=True)
subprocess.run(["losetup", LOOPDEVICE, IMGFILE])
if KERNELVERSION < "3.07":
IMGFS = "EXT4"
else:
IMGFS = os.environ.get("IMGFS", "BTRFS")
if IMGFS == "EXT4":
print(f" mkfs.ext4 -i 4096 -b 4096 -L {os.path.basename(sys.argv[2])} {LOOPDEVICE}")
subprocess.run(["mkfs.ext4", "-i", "4096", "-b", "4096", "-L", os.path.basename(sys.argv[2]), LOOPDEVICE], capture_output=True, text=True)
else:
print(f" mkfs.btrfs -L {os.path.basename(sys.argv[2])} {LOOPDEVICE}")
subprocess.run(["mkfs.btrfs", "-L", os.path.basename(sys.argv[2]), LOOPDEVICE], capture_output=True, text=True)
ogMountImage(sys.argv[1], sys.argv[2], sys.argv[3])
if not os.path.exists(IMGFILE + ".lock"):
open(IMGFILE + ".lock", "w").write("mounted")
if LOOPDEVICE:
subprocess.run(["losetup", "-d", LOOPDEVICE], capture_output=True, text=True)
else:
REPOIP = ogGetRepoIp()
print(f" hose {REPOIP} 2009 --out sh -c \"echo -ne CREATE_IMAGE {sys.argv[2]} {sys.argv[3]} {SIZEREQUIRED} \"")
subprocess.run(["hose", REPOIP, "2009", "--out", "sh", "-c", f"echo -ne CREATE_IMAGE \"{sys.argv[2]}\" {sys.argv[3]} {SIZEREQUIRED}\""], capture_output=True, text=True)
def ogCreateInfoImage():
FUNCNAME = ogCreateInfoImage.__name__
IMGTYPE = None
IMGDIRAUX = None
DIRMOUNT = None
DESTRSYNC = None
PASSWORD = None
USERRSYNC = None
ORIG = None
FSTYPE = None
PART = None
DIREMPTY = None
IMGLIST = None
IMGINFO = None
IMGACL = None
KERNELVERSION = None
if len(sys.argv) < 5 or (len(sys.argv) < 6 and sys.argv[3] != "img"):
ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part [ REPO|CACHE ] [ base_image_name ] extension", f"base image -> {FUNCNAME} 1 2 img", f"diff image -> {FUNCNAME} 1 1 CACHE Windows7 diff")
return
if len(sys.argv) < 3:
ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: {FUNCNAME} num_disk num_part [ REPO|CACHE ] [ base_image_name] extension")
return
PART = ogDiskToDev(sys.argv[1], sys.argv[2])
if not PART:
return
ORIG = ogMount(sys.argv[1], sys.argv[2])
if not ORIG:
return
if sys.argv[3] == "img":
IMGTYPE = "img"
else:
if not ogCheckStringInGroup(sys.argv[5], "img diff"):
ogRaiseError(OG_ERR_FORMAT, MSG_SYNC_EXTENSION)
return
IMGTYPE = sys.argv[5]
if IMGTYPE == "diff":
IMGDIRAUX = ogGetMountImageDir(sys.argv[4], "img")
if sys.argv[3] == "CACHE" or sys.argv[3] == "cache":
DIRMOUNT = f"/tmp/{IMGDIRAUX}"
DESTRSYNC = DIRMOUNT
else:
if not REPOIP:
REPOIP = ogGetRepoIp()
DIRMOUNT = f"{OGIMG}/{IMGDIRAUX}"
USERRSYNC = "opengnsys"
PASSWORD = "--password-file=/scripts/passrsync"
DESTRSYNC = f"{USERRSYNC}@{REPOIP}::ogimages/{IMGDIRAUX}"
FSTYPE = ogGetFsType(sys.argv[1], sys.argv[2])
DIREMPTY = "/tmp/empty$$"
IMGLIST = "/tmp/ogimg.list"
IMGINFO = "/tmp/ogimg.info"
IMGACL = "/tmp/ogimg.acl"
os.system(f"rm -f /tmp/ogimg.* 2>/dev/null")
os.system(f"rm -f {ORIG}/ogimg.* 2>/dev/null")
SIZEDATA = os.environ.get("SIZEDATA", "SIZEDATA")
KERNELVERSION = ".".join([str(int(num)) for num in platform.release().split(".")])
if KERNELVERSION < "3.07":
IMGFS = "EXT4"
else:
IMGFS = os.environ.get("IMGFS", "BTRFS")
with open(IMGINFO, "w") as f:
f.write(f"#{IMGFS}:NO:{FSTYPE}:{SIZEDATA}\n")
if IMGTYPE == "img":
print(f" rsync -aHAXWvn --delete {ORIG}/ {DIREMPTY} >> {IMGINFO}")
subprocess.run(["rsync", "-aHAXWvn", "--delete", f"{ORIG}/", DIREMPTY], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
os.system(f"sed -i -e s/\"^sent.*.bytes\\/sec\"//g -e s/^total.*.speedup.*.$//g -e s/\"sending.*.list\"//g {IMGINFO}")
os.system(f"sed -i '/^\\.\\//d' {IMGINFO}")
else:
print(f" rsync -aHAXWvn --delete {ORIG}/ {DESTRSYNC} a {IMGLIST}")
subprocess.run(["rsync", "-aHAXWvn", "--delete", f"{ORIG}/", DESTRSYNC], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
os.system(f"sed -i -e s/\"^sent.*.bytes\\/sec\"//g -e s/^total.*.speedup.*.$//g -e s/\"sending.*.list\"//g {IMGLIST}")
os.system(f"sed -i '/^\\.\\//d' {IMGLIST}")
with open(IMGINFO, "a") as f:
subprocess.run(["grep", "-e", "\\->", "-e", "\\=>", IMGLIST], stdout=f)
subprocess.run(["grep", "-e", "^deleting", IMGLIST], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode().replace("deleting ", "").split("\n")
subprocess.run(["grep", "-v", "-e", "\\->", "-e", "\\=>", "-e", "^deleting", "-e", "^created", IMGLIST], stdout=f)
os.system(f"rm -f {IMGLIST}")
if subprocess.run(["grep", "-v", "-e", "^$", "-e", "^#", IMGINFO, "/tmp/ogimg.ln", "/tmp/ogimg.rm"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode().count("\n") == 0:
ogRaiseError(OG_ERR_NOTDIFFERENT, " ".join(sys.argv[1:]))
return
if FSTYPE == "NTFS":
print(f" ntfs-3g.secaudit -b {PART} /")
subprocess.run(["ntfs-3g.secaudit", "-b", PART, "/"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def ogAclFilter():
FUNCNAME = ogAclFilter.__name__
IMGACL = "/tmp/ogimg.acl"
IMGINFO = "/tmp/ogimg.info"
FILES = "/tmp/files$$"
ACLTMP = "/tmp/acl$$.tmp"
ACLFILES = "/tmp/aclfiles$$"
# Ayuda
if len(sys.argv) == 2 and sys.argv[1] == "help":
ogHelp(FUNCNAME, FUNCNAME)
return
# comprobamos que existan los archivos de origen. Si no salimos sin error.
if not (os.path.isfile(IMGACL) and os.path.isfile(IMGINFO)):
return
with open(ACLTMP, "w") as f:
with open(IMGINFO, "r") as info_file:
for line in info_file:
line = line.strip()
if line.startswith("#") or line == "":
continue
line_number = line.split(":")[0]
acl_lines = []
with open(ACLFILES, "r") as acl_file:
acl_lines = acl_file.readlines()
end_line, start_line = None, None
for i, acl_line in enumerate(acl_lines):
acl_line = acl_line.strip()
if acl_line == "File" or acl_line == "Directory":
if acl_lines[i-1].startswith(line_number):
start_line = i
if acl_lines[i+1].startswith(line_number):
end_line = i
break
if start_line is not None and end_line is not None:
acl_lines = acl_lines[start_line+1:end_line]
f.writelines(acl_lines)
ogEcho("aclfilter", line)
shutil.copy2(ACLTMP, IMGACL)
os.remove(FILES)
os.remove(ACLTMP)
os.remove(ACLFILES)
def ogRestoreInfoImage():
FUNCNAME = ogRestoreInfoImage.__name__
DEST = None
PART = None
IMGACL = "ogimg.acl"
IMGLN = "ogimg.ln"
IMGINFO = "ogimg.info"
# Ayuda o menos de 5 parametros y la imagen no es basica
if len(sys.argv) < 3 or (len(sys.argv) < 4 and sys.argv[3] != "img"):
ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part", f"base image -> {FUNCNAME} 1 2", f"diff image -> {FUNCNAME} 1 1")
return
PART = ogDiskToDev(sys.argv[1], sys.argv[2])
if not PART:
return
DEST = ogMount(sys.argv[1], sys.argv[2])
if not DEST:
return
# Copiamos informacion de la imagen a /tmp (para basicas)
if os.path.isfile(f"{DEST}/{IMGINFO}"):
shutil.copy2(f"{DEST}/ogimg.*", "/tmp")
# Creamos o modificamos los enlaces.
# La imagen diferencial tiene ogimg.ln
# para la completa lo generamos con los enlaces que contengan /mnt/
if not os.path.isfile(f"/tmp/{IMGLN}"):
with open(f"/tmp/{IMGINFO}", "r") as info_file:
for line in info_file:
line = line.strip()
if "->" in line or "=>" in line:
if "/mnt/" in line:
with open(f"/tmp/{IMGLN}", "a") as ln_file:
ln_file.write(line.split(">")[0] + "\n")
if os.path.isfile(f"/tmp/{IMGLN}"):
with open(f"/tmp/{IMGLN}", "r") as ln_file:
for line in ln_file:
line = line.strip()
ORIGLN = line.split("> ")[1]
if "/mnt/" in ORIGLN:
ORIGLN = f"{DEST}/{ORIGLN.replace('/mnt/*/', '')}"
TYPELN = line.split(" ")[-1]
DESTLN = line.split(" ")[0]
if TYPELN == "-":
OPTLN = "-s"
else:
OPTLN = ""
os.chdir(f"{DEST}/{os.path.dirname(DESTLN)}")
os.remove(os.path.basename(DESTLN))
os.symlink(ORIGLN, os.path.basename(DESTLN))
print(".", end="")
print("")
os.chdir("/")
def ogRestoreAclImage():
PART = None
IMGACL = "ogimg.acl"
if len(sys.argv) < 3 or (len(sys.argv) < 4 and sys.argv[3] != "img"):
ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part", f"base image -> {FUNCNAME} 1 2", f"diff image -> {FUNCNAME} 1 1")
return
PART = ogDiskToDev(sys.argv[1], sys.argv[2])
if not PART:
return
# Restauramos acl
if ogGetFsType(sys.argv[1], sys.argv[2]) == "NTFS" and os.path.isfile(f"/tmp/{IMGACL}"):
os.chdir("/")
ogUnmount(sys.argv[1], sys.argv[2])
print(f" ntfs-3g.secaudit -se {PART} /tmp/{IMGACL}")
subprocess.run(["ntfs-3g.secaudit", "-se", PART, f"/tmp/{IMGACL}"], capture_output=True, text=True)
# Para evitar que de falso error
print("")
def ogSyncCreate():
ORIG = ogMount(sys.argv[1], sys.argv[2])
DIRAUX = ogGetMountImageDir(sys.argv[4], sys.argv[5])
DIRMOUNT = f"/tmp/{DIRAUX}"
DESTRSYNC = None
USERRSYNC = None
PASSWORD = None
OPTRSYNC = None
RETVAL = None
if sys.argv[3] == "CACHE" or sys.argv[3] == "cache":
DESTRSYNC = DIRMOUNT
else:
if not REPOIP:
REPOIP = ogGetRepoIp()
PASSWORD = "--password-file=/scripts/passrsync"
if ogrsyncz == "true":
OPTRSYNC = "z "
if ogrsyncw == "true":
OPTRSYNC = f"W{OPTRSYNC}"
USERRSYNC = "opengnsys"
DESTRSYNC = f"{USERRSYNC}@{REPOIP}::ogimages/{DIRMOUNT}"
print(f" rsync -aHAX{OPTRSYNC} --progress --inplace --delete {ORIG}/ {DESTRSYNC}")
subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--progress", "--inplace", "--delete", f"{ORIG}/", DESTRSYNC], stderr=subprocess.PIPE, shell=True)
print(f" rsync -aHAX{OPTRSYNC} --inplace /tmp/ogimg* {DESTRSYNC}")
subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--inplace", "/tmp/ogimg*", DESTRSYNC], stderr=subprocess.PIPE, shell=True)
return RETVAL
def ogSyncRestore():
DIRMOUNT = ogGetMountImageDir(sys.argv[2], sys.argv[3])
DESTRSYNC = ogGetMountPoint(sys.argv[4], sys.argv[5])
# Borramos ficheros de informacion de restauraciones antiguas
os.system(f"rm -rf {DESTRSYNC}/ogimg.*")
os.system("rm -rf /tmp/ogimg.*")
# Origen y destino de la sincronizacion y en REPO opciones rsync
if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
ORIG = f"/tmp/{DIRMOUNT}"
else:
REPOIP = ogGetRepoIp()
PASSWORD = "--password-file=/scripts/passrsync"
OPTRSYNC = ""
if ogrsyncz == "true":
OPTRSYNC += "z "
if ogrsyncw == "true":
OPTRSYNC += "W" + OPTRSYNC
USERRSYNC = "opengnsys"
ORIG = f"{USERRSYNC}@{REPOIP}::ogimages/{DIRMOUNT}"
# Opciones rsync en cache y repo
# Para la imagen basica, opcion de borrar archivos de la particion que no existen en la imagen
if sys.argv[3] == "img" and ogrsyncdel != "false":
OPTRSYNC += "--delete"
# Nos traemos listado ficheros y bajamos la imagen
ogEcho("log session", f" {MSG_SYNC_RESTORE}")
# Si la imagen es diferencial nos traemos los archivos de informacion de la imagen.
if sys.argv[3] == "diff":
# Lista de archivos a copiar:
IMGINFO = "ogimg.info"
FILESFROM = f"--files-from=/tmp/{IMGINFO}"
print(f" rsync -aHAX{OPTRSYNC} --progress {ORIG}/ogimg* /tmp")
subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--progress", f"{ORIG}/ogimg*", "/tmp"])
# Borramos linea de información de la imagen, sino busca un fichero con ese nombre
os.system("sed -i '/^#/d' /tmp/{IMGINFO}")
os.chdir(DESTRSYNC)
# Diferencial: Borramos archivos sobrantes.
ogEcho("log session", f" {MSG_SYNC_DELETE}")
os.system(f"sed -e s/^/\"/g -e s/$/\"/g \"/tmp/ogimg.rm\" 2>/dev/null | xargs rm -rf")
print(f" rsync -aHAX{OPTRSYNC} --progress {FILESFROM} {ORIG}/ {DESTRSYNC}")
subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--progress", FILESROM, f"{ORIG}/", DESTRSYNC], stderr=subprocess.PIPE, shell=True)
RETVAL = subprocess.PIPESTATUS[0]
os.chdir("/")
def ogMountImage(repo_cache, image_name, extension=None):
FUNCNAME = ogMountImage.__name__
if repo_cache == "help":
ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
return
if len(sys.argv) < 2:
ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: {FUNCNAME} [ REPO|CACHE ] image_name [ extension ]")
return
if not extension or extension == "img":
IMGEXT = "img"
else:
IMGEXT = "img.diff"
DIRMOUNT = ogGetMountImageDir(image_name, IMGEXT.split(".")[1])
if repo_cache == "REPO" or repo_cache == "repo":
REPOIP = ogGetRepoIp()
print(f" hose {REPOIP} 2009 --out sh -c \"echo -ne MOUNT_IMAGE {image_name} {IMGEXT.split('.')[1]}\"")
return f"{OGIMG}/{DIRMOUNT}"
else:
# Check if already mounted
if subprocess.run(["df"], capture_output=True, text=True).stdout.count(f"{DIRMOUNT}\n") > 0:
return f"/tmp/{DIRMOUNT}"
IMGFILE = ogGetPath(repo_cache, f"/{image_name}.{IMGEXT}")
if not IMGFILE:
ogRaiseError(OG_ERR_NOTFOUND, f"{repo_cache} {image_name}.{IMGEXT}")
return
os.makedirs(f"/tmp/{DIRMOUNT}", exist_ok=True)
if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
print(f" mount -t ext4 -o loop {IMGFILE} /tmp/{DIRMOUNT}")
subprocess.run(["mount", "-t", "ext4", "-o", "loop", IMGFILE, f"/tmp/{DIRMOUNT}"], capture_output=True, text=True)
else:
print(f" mount -o compress=lzo {IMGFILE} /tmp/{DIRMOUNT}")
subprocess.run(["mount", "-o", "compress=lzo", IMGFILE, f"/tmp/{DIRMOUNT}"], capture_output=True, text=True)
if subprocess.run(["mount"], capture_output=True, text=True).stdout.count(f"/tmp/{DIRMOUNT}\n") == 0:
ogRaiseError(OG_ERR_DONTMOUNT_IMAGE, f"{repo_cache} {image_name} {extension}")
return
return f"/tmp/{DIRMOUNT}"
def ogUnmountImage():
FUNCNAME = ogUnmountImage.__name__
IMGTYPE = None
DIRMOUNT = None
if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[2] != "img"):
ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
return
if not sys.argv[3] or sys.argv[3] == "img":
IMGTYPE = "img"
else:
IMGTYPE = sys.argv[3]
if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
DIRMOUNT = f"/tmp/{ogGetMountImageDir(sys.argv[2], IMGTYPE)}"
subprocess.run(["umount", DIRMOUNT], capture_output=True, text=True)
subprocess.run(["rmdir", DIRMOUNT], capture_output=True, text=True)
if os.path.exists(f"{IMGFILE}.lock"):
os.system(f"sed -i s/\"mounted\"//g {IMGFILE}.lock")
else:
if not REPOIP:
REPOIP = ogGetRepoIp()
print(f" hose {REPOIP} 2009 --out sh -c \"echo -ne UMOUNT_IMAGE {sys.argv[2]} {IMGTYPE}\"")
subprocess.run(["hose", REPOIP, "2009", "--out", "sh", "-c", f"echo -ne UMOUNT_IMAGE \"{sys.argv[2]}\" {IMGTYPE}\""], capture_output=True, text=True)
def ogGetMountImageDir(image_name, extension=None):
FUNCNAME = ogGetMountImageDir.__name__
if image_name == "help":
ogHelp(FUNCNAME, f"{FUNCNAME} image_name [ extension ]", f"{FUNCNAME} Ubuntu12", f"{FUNCNAME} Windows7 diff")
return
if len(sys.argv) < 2:
ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: {FUNCNAME} image_name [ extension ]")
return
DIRMOUNT = f"mount/{image_name}"
if extension == "diff":
DIRMOUNT = f"{DIRMOUNT}.diff"
return DIRMOUNT
def ogWaitSyncImage():
SIZE = int(sys.argv[5]) if len(sys.argv) >= 6 else 300000
STATE = sys.argv[4]
ogCheckStringInGroup(STATE, "mounted reduced") or return ogRaiseError(OG_ERR_FORMAT, "STATE = [ mounted | reduced ]")
IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
IMGEXT = "img" if sys.argv[3] == "img" else "img.diff"
LOCKFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}.lock"
if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
DIRMOUNT = f"/tmp/{ogGetMountImageDir(sys.argv[2], sys.argv[3])}"
else:
DIRMOUNT = f"{OGIMG}/{ogGetMountImageDir(sys.argv[2], sys.argv[3])}"
print(f" {MSG_SYNC_SLEEP}: {DIRMOUNT}")
print(" #")
TIMEOUT = SIZE // CREATESPEED
if TIMEOUT < 60:
TIMEOUT = 60
while True:
if STATE == "mounted" and os.path.isfile(f"{DIRMOUNT}/ogimg.info"):
ogEcho("log session", "")
return 0
TIMEAUX = SECONDS - TIME
if TIMEAUX >= TIMEOUT:
return ogRaiseError(OG_ERR_DONTMOUNT_IMAGE, f"{sys.argv[3]} {sys.argv[4]} {IMGEXT}: time_out.")
print("#")
time.sleep(5)
print("")
def ogReduceImage():
FUNCNAME = ogReduceImage.__name__
IMGEXT = None
DIRMOUNT = None
AVAILABLE = None
USED = None
IMGDIR = None
IMGFILE = None
ENDSIZE = None
LOOPDEVICE = None
if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[3] != "img"):
ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
return
if not sys.argv[3] or sys.argv[3] == "img":
IMGEXT = "img"
else:
IMGEXT = sys.argv[3]
IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
IMGFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}"
if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
DIRMOUNT = ogMountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
AVAILABLE = int(subprocess.run(["df", "-k"], capture_output=True, text=True).stdout.split(f"{DIRMOUNT}\n")[1].split()[3])
if AVAILABLE < 200000:
ogUnmountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
os.system(f"echo \"reduced\" > \"{IMGFILE}.lock\"")
return 0
EXTSIZE = int(subprocess.run(["ls", "-l", "--block-size=1024", IMGFILE], capture_output=True, text=True).stdout.split()[4])
INTSIZE = int(subprocess.run(["df", "-k"], capture_output=True, text=True).stdout.split(f"{DIRMOUNT}\n")[1].split()[1])
EDGESIZE = EXTSIZE - INTSIZE
ogUnmountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
LOOPDEVICE = subprocess.run(["losetup", "-f"], capture_output=True, text=True).stdout.strip()
os.system(f"losetup {LOOPDEVICE} \"{IMGFILE}\"")
os.system(f"resize2fs -fpM {LOOPDEVICE}")
ogMountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
INTSIZE = int(subprocess.run(["df", "-k"], capture_output=True, text=True).stdout.split(f"{DIRMOUNT}\n")[1].split()[1])
EXTSIZE = INTSIZE + EDGESIZE
os.system(f"umount \"{DIRMOUNT}\"")
if LOOPDEVICE:
os.system(f"losetup -d {LOOPDEVICE}")
os.system(f"truncate --size=\"{EXTSIZE}\"k \"{IMGFILE}\"")
else:
os.system(f"umount \"{DIRMOUNT}\"")
os.system(f"echo \"reduced\" > \"{IMGFILE}.lock\"")
os.system(f"rmdir \"{DIRMOUNT}\"")
def ogIsSyncImage():
FUNCNAME = ogIsSyncImage.__name__
IMGEXT = None
IMGDIR = None
IMGFILE = None
if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[3] != "img"):
ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
return
if not sys.argv[3] or sys.argv[3] == "img":
IMGEXT = "img"
else:
IMGEXT = sys.argv[3]
IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
IMGFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}"
if "BTRFS Filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower() or "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
return 0
else:
return OG_ERR_DONTSYNC_IMAGE
def ogCheckSyncImage():
FUNCNAME = ogCheckSyncImage.__name__
IMGEXT = None
IMGDIR = None
IMGFILE = None
DIRMOUNT = None
ISMOUNT = None
RETVAL = None
if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[3] != "img"):
ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
return
if not sys.argv[3] or sys.argv[3] == "img":
IMGEXT = "img"
else:
IMGEXT = sys.argv[3]
IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
IMGFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}"
if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
DIRMOUNT = f"/tmp/ogCheckImage$$"
os.makedirs(DIRMOUNT, exist_ok=True)
subprocess.run(["mount", "-t", "ext4", "-o", "loop", IMGFILE, DIRMOUNT], capture_output=True, text=True)
RETVAL = subprocess.PIPESTATUS[0]
else:
DIRMOUNT = f"/tmp/ogCheckImage$$"
os.makedirs(DIRMOUNT, exist_ok=True)
subprocess.run(["mount", "-o", "compress=lzo", IMGFILE, DIRMOUNT], capture_output=True, text=True)
RETVAL = subprocess.PIPESTATUS[0]
print("\n".join(os.listdir(DIRMOUNT)))
subprocess.run(["umount", DIRMOUNT], capture_output=True, text=True)
os.rmdir(DIRMOUNT)
return RETVAL

45
client/engine/StringLib.py Executable file
View File

@ -0,0 +1,45 @@
import re
def ogCheckStringInGroup(element, group):
"""
Función para determinar si el elemento pertenece a un conjunto.
:param element: elemento a comprobar
:param group: grupo de elementos para comprobar tipo "valor1 valor2 valor3"
:return: True si pertenece al grupo, False si NO pertenece al grupo
"""
if not isinstance(element, str) or not isinstance(group, str):
raise ValueError("Formato incorrecto, ambos parámetros deben ser cadenas.")
return element in group.split()
def ogCheckStringInReg(element, regex):
"""
Función para determinar si el elemento contiene una "expresión regular".
:param element: elemento a comprobar
:param regex: expresión regular
:return: True si coincide con la expresión, False si NO coincide con la expresión
"""
if not isinstance(element, str) or not isinstance(regex, str):
raise ValueError("Formato incorrecto, ambos parámetros deben ser cadenas.")
return re.match(regex, element) is not None
def ogCheckIpAddress(ip):
"""
Función para determinar si una cadena es una dirección ipv4 válida.
:param ip: string de la ip a comprobar
:return: True si es una dirección válida, False si NO es una dirección válida
"""
if not isinstance(ip, str):
raise ValueError("Formato incorrecto, el parámetro debe ser una cadena.")
regex = r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
if re.match(regex, ip):
parts = ip.split('.')
if all(0 <= int(part) <= 255 for part in parts):
return True
return False

27
client/engine/StringLib.test.py Executable file
View File

@ -0,0 +1,27 @@
from StringLib import ogCheckStringInGroup, ogCheckStringInReg, ogCheckIpAddress
def test_functions():
# Prueba de ogCheckStringInGroup
print("Prueba de ogCheckStringInGroup")
element = "full-duplex"
group = "full-duplex half-duplex broadcast"
print(f"Elemento: {element}, Grupo: {group}")
print("Pertenece al grupo:", ogCheckStringInGroup(element, group))
# Prueba de ogCheckStringInReg
print("\nPrueba de ogCheckStringInReg")
element = "50M"
regex = r"^[0-9]{1,2}M$"
print(f"Elemento: {element}, Expresión regular: {regex}")
print("Coincide con la expresión regular:", ogCheckStringInReg(element, regex))
# Prueba de ogCheckIpAddress
print("\nPrueba de ogCheckIpAddress")
ip = "192.18.35.3"
print(f"IP: {ip}")
print("Es una dirección IP válida:", ogCheckIpAddress(ip))
if __name__ == "__main__":
test_functions()

View File

@ -298,11 +298,7 @@ test -n "$FILES"
function ogCheckProgram ()
{
# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
ogHelp "$FUNCNAME \"str_program ...\"" \
"$FUNCNAME \"partimage partclone mbuffer\""
return
fi
# Error si no se recibe 1 parámetro.
[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $?

299
client/engine/SystemLib.py Normal file
View File

@ -0,0 +1,299 @@
import subprocess
import datetime
import sys
import os
import shutil
from engine.DiskLib import *
from engine.CacheLib import *
from engine.StringLib import *
#NODEBUGFUNCTIONS, OGIMG, OG_ERR_CACHESIZE, OG_ERR_NOTCACHE, OG_ERR_NOTWRITE, OG_ERR_FILESYS
#OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE
#OGLOGSESSION, OGLOGCOMMAND, OGLOGFILE, OG_ERR_LOCKED, OG_ERR_PARTITION, OG_ERR_FORMAT, OG_ERR_NOTEXEC, OG_ERR_NOTFOUND
def ogEcho(*args):
# Variables locales
CONT = 1
LOGS = ""
LOGLEVEL = ""
DATETIME = ""
# Selección de ficheros de registro de incidencias.
while CONT:
arg = args.pop(0).lower()
if arg == "log":
LOGS += " " + OGLOGFILE
elif arg == "command":
LOGS += " " + OGLOGCOMMAND
elif arg == "session":
LOGS += " " + OGLOGSESSION
else:
CONT = 0
# Selección del nivel de registro (opcional).
arg = args.pop(0).lower()
if arg == "help":
pass
elif arg == "info" or arg == "warning" or arg == "error":
LOGLEVEL = arg
if LOGLEVEL:
DATETIME = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Registrar mensajes en fichero de log si la depuración no está desactivada.
if DEBUG.lower() != "no":
LOGS += " " + OGLOGFILE
subprocess.call(f"logger -t OpenGnsys {LOGLEVEL} {DATETIME} {' '.join(args)}", shell=True)
else:
print(' '.join(args))
def ogExecAndLog(*args):
# Variables locales
ISCOMMAND = False
ISLOG = False
ISSESSION = False
COMMAND = ""
CONTINUE = 1
FILES = ""
REDIREC = ""
FUNCNAME = ogExecAndLog.__name__
# Si se solicita, mostrar ayuda.
if len(args) > 0 and args[0] == "help":
ogHelp(f"{FUNCNAME} str_logfile ... str_command ...",
f"{FUNCNAME} COMMAND ls -al /")
return
# Procesar parámetros.
while CONTINUE:
arg = args.pop(0).lower()
if arg == "command":
ISCOMMAND = True
continue
elif arg == "log":
ISLOG = True
continue
elif arg == "session":
ISSESSION = True
continue
else:
COMMAND = " ".join(args)
CONTINUE = 0
# Error si no se recibe un comando que ejecutar.
if not COMMAND:
ogRaiseError(OG_ERR_FORMAT)
return
# Componer lista de ficheros de registro.
if ISCOMMAND:
FILES = OGLOGCOMMAND
open(FILES, "w").close()
REDIREC = "2>&1"
if ISLOG:
FILES += " " + OGLOGFILE
if ISSESSION:
FILES += " " + OGLOGSESSION
# Ejecutar comando.
subprocess.call(f"{COMMAND} {REDIREC} | tee -a {FILES}", shell=True)
# Salida de error del comando ejecutado.
return subprocess.PIPESTATUS[0]
def ogGetCaller():
# Obtener el nombre del programa o del script que ha llamado al proceso actual.
output = subprocess.check_output(["ps", "hp", str(os.getppid()), "-o", "args"]).decode("utf-8")
lines = output.split("\n")
caller = ""
for line in lines:
if "bash" in line and line.split()[1] != "":
caller = line.split()[1]
else:
caller = line.split()[0].lstrip("-")
return os.path.basename(caller)
def ogHelp(*args):
# Variables locales
FUNC = ""
MSG = ""
FUNCNAME = ogHelp.__name__
# Mostrar función, descripción y formato.
FUNC = args[0] if len(args) > 0 else FUNCNAME[-1]
MSG = f"MSG_HELP_{FUNC}"
ogEcho("help", f"{MSG_FUNCTION} {FUNC}: {globals()[MSG]}")
if len(args) > 1:
ogEcho("help", f" {MSG_FORMAT}: {args[1]}")
# Mostrar ejemplos (si existen).
for example in args[2:]:
ogEcho("help", f" {MSG_EXAMPLE}: {example}")
def ogRaiseError(*args):
# Variables locales
CONT = 1
LOGS = ""
MSG = ""
CODE = ""
FUNCS = ""
FUNCNAME = ogRaiseError.__name__
# Si se solicita, mostrar ayuda.
if len(args) > 0 and args[0] == "help":
ogHelp(f"{FUNCNAME}", f"{FUNCNAME} [str_logfile ...] int_errorcode str_errormessage")
return
# Selección de registros de incidencias.
while CONT:
arg = args.pop(0).lower()
if arg == "log" or arg == "command" or arg == "session":
LOGS += " " + arg
else:
CONT = 0
# Obtener código y mensaje de error.
CODE = args.pop(0)
if CODE == OG_ERR_FORMAT:
MSG = f"{MSG_ERR_FORMAT} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTFOUND:
MSG = f"{MSG_ERR_NOTFOUND} \"{args.pop(0)}\""
elif CODE == OG_ERR_OUTOFLIMIT:
MSG = f"{MSG_ERR_OUTOFLIMIT} \"{args.pop(0)}\""
elif CODE == OG_ERR_PARTITION:
MSG = f"{MSG_ERR_PARTITION} \"{args.pop(0)}\""
elif CODE == OG_ERR_LOCKED:
MSG = f"{MSG_ERR_LOCKED} \"{args.pop(0)}\""
elif CODE == OG_ERR_CACHE:
MSG = f"{MSG_ERR_CACHE} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOGPT:
MSG = f"{MSG_ERR_NOGPT} \"{args.pop(0)}\""
elif CODE == OG_ERR_REPO:
MSG = f"{MSG_ERR_REPO} \"{args.pop(0)}\""
elif CODE == OG_ERR_FILESYS:
MSG = f"{MSG_ERR_FILESYS} \"{args.pop(0)}\""
elif CODE == OG_ERR_IMAGE:
MSG = f"{MSG_ERR_IMAGE} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTOS:
MSG = f"{MSG_ERR_NOTOS} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTEXEC:
MSG = f"{MSG_ERR_NOTEXEC} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTWRITE:
MSG = f"{MSG_ERR_NOTWRITE} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTCACHE:
MSG = f"{MSG_ERR_NOTCACHE} \"{args.pop(0)}\""
elif CODE == OG_ERR_CACHESIZE:
MSG = f"{MSG_ERR_CACHESIZE} \"{args.pop(0)}\""
elif CODE == OG_ERR_REDUCEFS:
MSG = f"{MSG_ERR_REDUCEFS} \"{args.pop(0)}\""
elif CODE == OG_ERR_EXTENDFS:
MSG = f"{MSG_ERR_EXTENDFS} \"{args.pop(0)}\""
elif CODE == OG_ERR_IMGSIZEPARTITION:
MSG = f"{MSG_ERR_IMGSIZEPARTITION} \"{args.pop(0)}\""
elif CODE == OG_ERR_UPDATECACHE:
MSG = f"{MSG_ERR_UPDATECACHE} \"{args.pop(0)}\""
elif CODE == OG_ERR_DONTFORMAT:
MSG = f"{MSG_ERR_DONTFORMAT} \"{args.pop(0)}\""
elif CODE == OG_ERR_IMAGEFILE:
MSG = f"{MSG_ERR_IMAGEFILE} \"{args.pop(0)}\""
elif CODE == OG_ERR_UCASTSYNTAXT:
MSG = f"{MSG_ERR_UCASTSYNTAXT} \"{args.pop(0)}\""
elif CODE == OG_ERR_UCASTSENDPARTITION:
MSG = f"{MSG_ERR_UCASTSENDPARTITION} \"{args.pop(0)}\""
elif CODE == OG_ERR_UCASTSENDFILE:
MSG = f"{MSG_ERR_UCASTSENDFILE} \"{args.pop(0)}\""
elif CODE == OG_ERR_UCASTRECEIVERPARTITION:
MSG = f"{MSG_ERR_UCASTRECEIVERPARTITION} \"{args.pop(0)}\""
elif CODE == OG_ERR_UCASTRECEIVERFILE:
MSG = f"{MSG_ERR_UCASTRECEIVERFILE} \"{args.pop(0)}\""
elif CODE == OG_ERR_MCASTSYNTAXT:
MSG = f"{MSG_ERR_MCASTSYNTAXT} \"{args.pop(0)}\""
elif CODE == OG_ERR_MCASTSENDFILE:
MSG = f"{MSG_ERR_MCASTSENDFILE} \"{args.pop(0)}\""
elif CODE == OG_ERR_MCASTRECEIVERFILE:
MSG = f"{MSG_ERR_MCASTRECEIVERFILE} \"{args.pop(0)}\""
elif CODE == OG_ERR_MCASTSENDPARTITION:
MSG = f"{MSG_ERR_MCASTSENDPARTITION} \"{args.pop(0)}\""
elif CODE == OG_ERR_MCASTRECEIVERPARTITION:
MSG = f"{MSG_ERR_MCASTRECEIVERPARTITION} \"{args.pop(0)}\""
elif CODE == OG_ERR_PROTOCOLJOINMASTER:
MSG = f"{MSG_ERR_PROTOCOLJOINMASTER} \"{args.pop(0)}\""
elif CODE == OG_ERR_DONTMOUNT_IMAGE:
MSG = f"{MSG_ERR_DONTMOUNT_IMAGE} \"{args.pop(0)}\""
elif CODE == OG_ERR_DONTUNMOUNT_IMAGE:
MSG = f"{MSG_ERR_DONTUNMOUNT_IMAGE} \"{args.pop(0)}\""
elif CODE == OG_ERR_DONTSYNC_IMAGE:
MSG = f"{MSG_ERR_DONTSYNC_IMAGE} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTDIFFERENT:
MSG = f"{MSG_ERR_NOTDIFFERENT} \"{args.pop(0)}\""
elif CODE == OG_ERR_SYNCHRONIZING:
MSG = f"{MSG_ERR_SYNCHRONIZING} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTUEFI:
MSG = f"{MSG_ERR_NOTUEFI} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOMSDOS:
MSG = f"{MSG_ERR_NOMSDOS} \"{args.pop(0)}\""
elif CODE == OG_ERR_NOTBIOS:
MSG = f"{MSG_ERR_NOTBIOS} \"{args.pop(0)}\""
else:
MSG = MSG_ERR_GENERIC
CODE = OG_ERR_GENERIC
# Obtener lista de funciones afectadas, incluyendo el script que las llama.
FUNCS = " ".join(FUNCNAME[1:])
FUNCS = FUNCS.replace("main", os.path.basename(sys.argv[0]))
# Mostrar mensaje de error si es función depurable y salir con el código indicado.
if CODE == OG_ERR_FORMAT or ogCheckStringInGroup(FUNCS, NODEBUGFUNCTIONS) or not ogCheckStringInGroup(FUNCS.split()[0], NODEBUGFUNCTIONS):
ogEcho(LOGS, "error", f"{FUNCS.replace(' ', '<-')}: {MSG}", file=sys.stderr)
return CODE
def ogIsRepoLocked():
# Variables locales
FILES = ""
FUNCNAME = ogIsRepoLocked.__name__
# Si se solicita, mostrar ayuda.
if len(sys.argv) > 1 and sys.argv[1] == "help":
ogHelp(f"{FUNCNAME}", f"{FUNCNAME}", f"if {FUNCNAME}(): ...")
# No hacer nada, si no está definido el punto de montaje del repositorio.
if not OGIMG:
return 1
# Comprobar si alguno de los ficheros abiertos por los procesos activos está en el
# punto de montaje del repositorio de imágenes.
FILES = subprocess.check_output(["find", "/proc", "-maxdepth", "2", "-type", "f", "-lname", f"{OGIMG}/*"]).decode("utf-8")
return bool(FILES)
def ogCheckProgram(*args):
FUNCNAME = ogCheckProgram.__name__
# Si se solicita, mostrar ayuda.
if len(args) > 0 and args[0] == "help":
ogHelp(f"{FUNCNAME} \"str_program ...\"",
f"{FUNCNAME} \"partimage partclone mbuffer\"")
return
# Error si no se recibe 1 parámetro.
if len(args) != 1:
ogRaiseError(OG_ERR_FORMAT)
return
PERROR = 0
PLOG = " "
for i in args[0].split():
if not shutil.which(i):
PERROR = 1
PLOG += f" {i}"
if PERROR == 1:
ogRaiseError(OG_ERR_NOTEXEC, PLOG)
return
else:
return 0
def ogIsVirtualMachine():
output = subprocess.check_output(["dmidecode", "-s", "system-product-name"]).decode("utf-8")
if "KVM" in output or "VirtualBox" in output:
return 1
else:
return 0

View File

@ -0,0 +1,94 @@
import os
import subprocess
def install(url):
if not url:
print("Please provide the URL of the tar.gz file")
return
os.chdir("/tmp")
subprocess.run(["wget", "-O", "download.tgz", url])
os.mkdir("download")
subprocess.run(["tar", "xzvf", "download.tgz", "-C", "download"])
for i in os.listdir("download"):
os.chdir(f"download/{i}")
if os.path.exists("configure"):
subprocess.run(["./configure"])
subprocess.run(["make"])
subprocess.run(["make", "install"])
os.chdir("-")
subprocess.run(["rm", "-fr", "download*"])
def mbuffer():
if os.path.exists("/opt/git/opengnsys/client/engine/ToolsGNUc.py"):
subprocess.run(["python", "/opt/git/opengnsys/client/engine/ToolsGNUc.py"])
else:
return
def ms_sys():
if os.path.exists("/opt/git/opengnsys/client/engine/ToolsGNUc.py"):
subprocess.run(["python", "/opt/git/opengnsys/client/engine/ToolsGNUc.py"])
else:
return
def ctorrent():
if os.path.exists("/opt/git/opengnsys/client/engine/ToolsGNUc.py"):
subprocess.run(["python", "/opt/git/opengnsys/client/engine/ToolsGNUc.py", "install"])
else:
return
def udpcast():
if len(sys.argv) > 1 and sys.argv[1] == "install":
install("http://udpcast.linux.lu/download/udpcast-20100130.tar.gz")
else:
return
def ntfs_3g():
if len(sys.argv) > 1 and sys.argv[1] == "install":
install("http://tuxera.com/opensource/ntfs-3g-2011.1.15.tgz")
else:
return
def partitionsaving():
return
def awk():
return
def chntpw():
return
def fdisk():
return
def fsck():
return
def kexec():
return
def lshw():
return
def mkfs():
return
def mount():
return
def parted():
return
def partimage():
return
def partprobe():
return
def sfdisk():
return
def umount():
return

645
client/engine/UEFILib.py Normal file
View File

@ -0,0 +1,645 @@
from engine.SystemLib import *
import subprocess
import os
import shutil
def ogNvramActiveEntry(*args):
FUNCNAME = ogNvramActiveEntry.__name__
NUMENTRY = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} [ Num_order_entry | Label_entry ]", f"{FUNCNAME} 2", f'{FUNCNAME} "Windows Boot Manager"')
return
# Error si no se recibe 1 parámetro.
if len(args) != 1:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} [ Num_order_entry | Label_entry ]")
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
# Distingo si es número de orden o etiqueta
if args[0].isdigit():
NUMENTRY = subprocess.check_output(['efibootmgr', '-v']).decode().split()[0][4:8]
else:
NUMENTRY = subprocess.check_output(['efibootmgr', '-v']).decode().split()[0][4:8]
if NUMENTRY == "":
ogRaiseError(OG_ERR_NOTFOUND, f"NVRAM entry '{args[0]}'")
return
subprocess.run(['efibootmgr', '-a', '-b', NUMENTRY], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def ogNvramAddEntry(*args):
FUNCNAME = ogNvramAddEntry.__name__
EFIDISK = None
EFIPART = None
BOOTLABEL = None
BOOTLOADER = None
ADDORDER = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} Str_label_entry Str_boot_loader [ Bool_add_bootorder ]", f"{FUNCNAME} 1 2 TRUE", f'{FUNCNAME} grub /EFI/grub/grubx64.efi TRUE', f'{FUNCNAME} Windows /EFI/Microsoft/Boot/bootmgfw.efi')
return
# Error si no se recibe 2 o 3 parámetros.
if len(args) < 2 or len(args) > 3:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} Str_label_entry Str_boot_loader")
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
EFIDISK, EFIPART = ogGetEsp().split()
if EFIPART == "":
ogRaiseError(OG_ERR_NOTFOUND, "ESP")
return
# Recogemos parámetros
# Distinguimos si es disco/partición o etiqueta/cargador
if args[0].isdigit() and args[1].isdigit():
BOOTLABEL = f"Part-{int(args[0]):02d}-{int(args[1]):02d}"
BOOTLOADER = f"/EFI/{BOOTLABEL}/Boot/ogloader.efi"
else:
BOOTLABEL = args[0]
BOOTLOADER = args[1]
# Si existe entrada con la misma etiqueta la borramos
ogNvramDeleteEntry(BOOTLABEL)
subprocess.run(['efibootmgr', '-C', '-d', ogDiskToDev(EFIDISK), '-p', EFIPART, '-L', BOOTLABEL, '-l', BOOTLOADER], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Incluimos la entrada en el orden de arranque (opcional)
if len(args) == 3 and args[2].upper() == "TRUE":
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith(BOOTLABEL):
NUMENTRY = entry[4:8]
break
ogNvramSetOrder(*ogNvramGetOrder().split(','), NUMENTRY)
def ogCopyEfiBootLoader():
FUNCNAME = ogCopyEfiBootLoader.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_part", f"{FUNCNAME} 1 2")
return
# Error si no se reciben 2 parámetros.
if len(args) != 2:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} int_ndisk int_part")
return
# Comprobamos que exista partición de sistema y la ESP
MNTDIR = ogMount(args[0], args[1])
if MNTDIR is None:
ogRaiseError(OG_ERR_PARTITION, f"{DISK} {PART}")
return
EFIDIR = ogMount(ogGetEsp())
if EFIDIR is None:
ogRaiseError(OG_ERR_PARTITION, "ESP")
return
# Comprobamos que exista el cargador
BOOTLABEL = f"Part-{int(args[0]):02d}-{int(args[1]):02d}"
OSVERSION = ogGetOsVersion(args[0], args[1])
LOADER = None
for f in [f"{EFIDIR}/EFI/Microsoft/Boot/bootmgfw.efi", f"{EFIDIR}/EFI/{BOOTLABEL}/Boot/bootmgfw.efi"]:
if os.path.isfile(f):
LOADER = f
break
if LOADER is None:
ogRaiseError(OG_ERR_NOTOS, f"{args[0]} {args[1]} ({OSVERSION}, EFI)")
return
# Si existe el directorio Boot lo borramos
if os.path.isdir(f"{MNTDIR}/ogBoot"):
shutil.rmtree(f"{MNTDIR}/ogBoot")
DIRLOADER = os.path.realpath(os.path.join(os.path.dirname(LOADER), ".."))
shutil.copytree(f"{DIRLOADER}/Boot", f"{MNTDIR}/ogBoot")
def ogNvramDeleteEntry(*args):
FUNCNAME = ogNvramDeleteEntry.__name__
NUMENTRY = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} [ Num_order_entry | Label_entry ]", f"{FUNCNAME} 2", f'{FUNCNAME} "Windows Boot Manager"')
return
# Error si no se recibe 1 parámetro.
if len(args) != 1:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} [ Num_order_entry | Label_entry ]")
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
# Distingo si es número de orden o etiqueta
if args[0].isdigit():
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith(args[0]):
NUMENTRY = entry[4:8]
break
else:
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith(args[0]):
NUMENTRY = entry[4:8]
break
if NUMENTRY == "":
ogRaiseError(OG_ERR_NOTFOUND, f"NVRAM entry '{args[0]}'")
return
for n in NUMENTRY:
subprocess.run(['efibootmgr', '-B', '-b', n], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def ogNvramGetCurrent():
FUNCNAME = ogNvramGetCurrent.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, FUNCNAME, FUNCNAME)
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
output = subprocess.check_output(['efibootmgr']).decode().split('\n')
bootentry = 99999
for line in output:
if "BootCurrent" in line:
bootentry = line.split()[1]
if bootentry in line:
num_entry = line[4:8]
label_entry = line[line.index(bootentry):]
print(f"{num_entry} {label_entry}")
def ogNvramGetNext():
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, FUNCNAME, FUNCNAME)
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
output = subprocess.check_output(['efibootmgr']).decode().split('\n')
for line in output:
if "BootNext" in line:
bootnext = line.split()[1]
return bootnext
return None
def ogNvramGetOrder():
FUNCNAME = ogNvramGetOrder.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, FUNCNAME, FUNCNAME)
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
output = subprocess.check_output(['efibootmgr']).decode().split('\n')
for line in output:
if "BootOrder" in line:
bootorder = line.split(':')[1].strip()
return bootorder
return None
def ogNvramGetTimeout():
FUNCNAME = ogNvramGetTimeout.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, FUNCNAME, FUNCNAME)
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
output = subprocess.check_output(['efibootmgr']).decode().split('\n')
for line in output:
if "Timeout" in line:
timeout = line.split(':')[1].strip()
return timeout
return None
def ogGrubUefiConf(*args):
FUNCNAME = ogGrubUefiConf.__name__
EFIDIR = None
BOOTLABEL = None
GRUBEFI = None
UUID = None
DEVICE = None
PREFIXSECONDSTAGE = None
EFIGRUBDIR = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_part [ str_dir_grub ]", f"{FUNCNAME} 1 2", f"{FUNCNAME} 1 3 /boot/grubPARTITION")
return
# Error si no se reciben al menos 2 parámetros.
if len(args) < 2:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} int_ndisk int_part [ str_dir_grub ]")
return
EFIDIR = ogMount(ogGetEsp())
if EFIDIR is None:
ogRaiseError(OG_ERR_PARTITION, "ESP")
return
BOOTLABEL = f"Part-{int(args[0]):02d}-{int(args[1]):02d}"
EFIGRUBDIR = f"{EFIDIR}/EFI/{BOOTLABEL}/boot/grub"
# Comprobamos que existe directorio
if not os.path.isdir(EFIGRUBDIR):
os.makedirs(EFIGRUBDIR)
# Parcheamos uuid y particion en grub.cfg
UUID = subprocess.check_output(['blkid', '-o', 'value', '-s', 'UUID', ogDiskToDev(args[0], args[1])]).decode().strip()
DEVICE = f"hd{int(args[0]) - 1},gpt{int(args[1])}"
with open(f"{EFIGRUBDIR}/grub.cfg", "w") as f:
f.write(f"set root='{DEVICE}'\n")
f.write(f"set prefix=($root)'{args[2]}/boot/grub'\n")
f.write(f"configfile $prefix/grub.cfg\n")
# Provisional: confirmar si el segundo archivo se utiliza
shutil.copy(f"{EFIGRUBDIR}/grub.cfg", f"{EFIDIR}/EFI/{BOOTLABEL}/grub.cfg")
def ogNvramInactiveEntry(*args):
FUNCNAME = ogNvramInactiveEntry.__name__
NUMENTRY = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} [ Num_order_entry | Label_entry ]", f"{FUNCNAME} 2", f'{FUNCNAME} "Windows Boot Manager"')
return
# Error si no se recibe 1 parámetro.
if len(args) != 1:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} [ Num_order_entry | Label_entry ]")
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
# Distingo si es número de orden o etiqueta
if args[0].isdigit():
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith(args[0]):
NUMENTRY = entry[4:8]
break
else:
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith(args[0]):
NUMENTRY = entry[4:8]
break
if NUMENTRY == "":
ogRaiseError(OG_ERR_NOTFOUND, f"NVRAM entry '{args[0]}'")
return
subprocess.run(['efibootmgr', '-A', '-b', NUMENTRY], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def ogNvramList():
FUNCNAME = ogNvramList.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, FUNCNAME, FUNCNAME)
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
output = subprocess.check_output(['efibootmgr']).decode().split('\n')
for line in output:
if line.startswith("Boot"):
num_entry = line[4:8]
label_entry = line[line.index(num_entry):]
active = "*" if line.startswith("*") else ""
print(f"{num_entry} {label_entry} {active}")
def ogNvramPxeFirstEntry():
FUNCNAME = ogNvramPxeFirstEntry.__name__
NUMENTRY = None
ORDER = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, FUNCNAME, FUNCNAME)
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith("IPv4"):
NUMENTRY = entry[4:8]
break
# Si la entrada es la primera nos salimos.
if NUMENTRY in ogNvramGetOrder().split(','):
return
# Si la entrada ya existe la borramos.
ORDER = ogNvramGetOrder().split(',')
if NUMENTRY in ORDER:
ORDER.remove(NUMENTRY)
ogNvramSetOrder(','.join([NUMENTRY] + ORDER))
def ogRestoreEfiBootLoader(*args):
FUNCNAME = ogRestoreEfiBootLoader.__name__
MNTDIR = None
EFIDIR = None
BOOTLABEL = None
OSVERSION = None
LOADER = None
UUID = None
DEVICE = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_part", f"{FUNCNAME} 1 2")
return
# Error si no se reciben 2 parámetros.
if len(args) != 2:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} int_ndisk int_part")
return
# Comprobamos que exista partición de sistema y la ESP
MNTDIR = ogMount(args[0], args[1])
if MNTDIR is None:
ogRaiseError(OG_ERR_PARTITION, f"{DISK} {PART}")
return
EFIDIR = ogMount(ogGetEsp())
if EFIDIR is None:
ogFormat(ogGetEsp(), "FAT32")
EFIDIR = ogMount(ogGetEsp())
if EFIDIR is None:
ogRaiseError(OG_ERR_PARTITION, "ESP")
return
# Comprobamos que exista el cargador
BOOTLABEL = f"Part-{int(args[0]):02d}-{int(args[1]):02d}"
OSVERSION = ogGetOsVersion(args[0], args[1])
if "Windows" in OSVERSION:
LOADER = ogGetPath(f"{MNTDIR}/ogBoot/bootmgfw.efi")
if LOADER is None:
ogRaiseError(OG_ERR_NOTOS, f"{args[0]} {args[1]} ({OSVERSION}, EFI)")
return
if os.path.isdir(f"{EFIDIR}/EFI/{BOOTLABEL}"):
shutil.rmtree(f"{EFIDIR}/EFI/{BOOTLABEL}")
os.makedirs(f"{EFIDIR}/EFI/{BOOTLABEL}")
shutil.copytree(f"{LOADER.rstrip('/bootmgfw.efi')}", f"{EFIDIR}/EFI/{BOOTLABEL}/Boot")
shutil.copy(LOADER, f"{EFIDIR}/EFI/{BOOTLABEL}/Boot/ogloader.efi")
if os.path.isdir(f"{EFIDIR}/EFI/Microsoft"):
os.rename(f"{EFIDIR}/EFI/Microsoft", f"{EFIDIR}/EFI/Microsoft.backup.og")
def ogRestoreUuidPartitions():
FUNCNAME = ogRestoreUuidPartitions.__name__
DISK = None
PART = None
IMGNAME = None
INFOFILE = None
DEVICE = None
DATA = None
GUID = None
UUID = None
IMGGUID = None
EFIDEVICE = None
EFIDATA = None
EFIGUID = None
EFIUUID = None
IMGEFIGUID = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} REPO|CACHE str_imgname int_ndisk int_npart", f"{FUNCNAME} REPO Windows 1 2")
return
# Error si no se reciben 4 parámetros.
if len(args) != 4:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} REPO|CACHE str_imgname int_ndisk int_npart")
return
# Sólo se ejecuta si es UEFI
if not ogIsEfiActive():
return
# Parámetros de entrada
IMGNAME = args[1]
INFOFILE = f"{OGIMG}/.{IMGNAME}.img.json"
if args[0].upper() == "CACHE":
INFOFILE = f"{OGCAC}{INFOFILE}"
# TODO: que la función getPath soporte archivos ocultos
if not os.path.exists(INFOFILE):
ogRaiseError(OG_ERR_NOTFOUND, INFOFILE)
return
DISK = args[2]
PART = args[3]
DEVICE = ogDiskToDev(DISK)
EFIDISK, EFIPART = ogGetEsp().split()
# Datos de la imagen
IMGGUID = subprocess.check_output(['jq', '.guid', INFOFILE]).decode().strip().strip('"')
IMGEFIGUID = subprocess.check_output(['jq', '.espguid', INFOFILE]).decode().strip().strip('"')
# Datos actuales
DATA = subprocess.check_output(['sfdisk', '-J', DEVICE]).decode()
GUID = subprocess.check_output(['echo', DATA, '|', 'jq', '".partitiontable|.id"', '|', 'tr', '-d', '"']).decode().strip()
if IMGGUID != GUID:
subprocess.run(['sgdisk', '-U', IMGGUID, DEVICE])
subprocess.run(['partprobe'])
if DISK == EFIDISK:
EFIDATA = DATA
EFIDEVICE = DEVICE
else:
EFIDEVICE = ogDiskToDev(EFIDISK)
EFIDATA = subprocess.check_output(['sfdisk', '-J', EFIDEVICE]).decode()
EFIGUID = subprocess.check_output(['echo', EFIDATA, '|', 'jq', '".partitiontable|.id"', '|', 'tr', '-d', '"']).decode().strip()
if IMGEFIGUID != EFIGUID:
subprocess.run(['sgdisk', '-U', IMGEFIGUID, EFIDEVICE])
subprocess.run(['partprobe'])
def ogNvramSetNext(*args):
FUNCNAME = ogNvramSetNext.__name__
NUMENTRY = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} [ Num_order_entry | Label_entry ]", f"{FUNCNAME} 2", f'{FUNCNAME} "Windows Boot Manager"')
return
# Error si no se recibe 1 parámetro.
if len(args) != 1:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} [ Num_order_entry | Label_entry ]")
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
# Distingo si es número de orden o etiqueta
if args[0].isdigit():
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith(args[0]):
NUMENTRY = entry[4:8]
break
else:
NUMENTRY = subprocess.check_output(['efibootmgr']).decode().split('\n')
for entry in NUMENTRY:
if entry.startswith(args[0]):
NUMENTRY = entry[4:8]
break
if NUMENTRY == "":
ogRaiseError(OG_ERR_NOTFOUND, f"NVRAM entry '{args[0]}'")
return
subprocess.run(['efibootmgr', '-n', NUMENTRY], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def ogNvramSetOrder(*args):
FUNCNAME = ogNvramSetOrder.__name
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} Num_order1 [ Num_order2 ] ...", f"{FUNCNAME} 1 3")
return
# Error si no se recibe al menos 1 parámetro.
if len(args) < 1:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} Num_order1 [ Num_order2 ] ...")
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
# Comprobamos que sean números
for arg in args:
if not arg.isdigit():
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} Num_order1 [ Num_order2 ] ...")
return
# Entradas de la NVRAM actuales
NUMENTRYS = subprocess.check_output(['efibootmgr']).decode().split('\n')
NUMENTRYS = [entry[4:8] for entry in NUMENTRYS if entry.startswith("Boot")]
ORDER = ""
for arg in args:
# Si no existe la entrada me salgo
if arg not in NUMENTRYS:
ogRaiseError(OG_ERR_NOTFOUND, f"NVRAM entry order '{arg}'")
return
ORDER += f",{arg}"
# Cambiamos el orden
subprocess.run(['efibootmgr', '-o', ORDER[1:]], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def ogNvramSetTimeout(*args):
FUNCNAME = ogNvramSetTimeout.__name__
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_Timeout (seg)", f"{FUNCNAME} 2")
return
# Si no es equipo UEFI salir con error
if not ogIsEfiActive():
ogRaiseError(OG_ERR_NOTUEFI)
return
# Error si no se recibe 1 parámetro.
if len(args) != 1:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} int_Timeout (seg)")
return
# Comprobamos que sea un número
if not args[0].isdigit():
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} int_Timeout (seg)")
return
# Cambiamos el timeout
subprocess.run(['efibootmgr', '-t', args[0]], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def ogUuidChange(*args):
FUNCNAME = ogUuidChange.__name__
MNTDIR = None
DEVICE = None
UUID = None
NEWUUID = None
# Si se solicita, mostrar ayuda.
if "help" in args:
ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_part", f"{FUNCNAME} 1 2")
return
# Error si no se reciben al menos 2 parámetros.
if len(args) < 2:
ogRaiseError(OG_ERR_FORMAT, f"{FUNCNAME} int_ndisk int_part")
return
# Comprobamos que exista la partición
MNTDIR = ogMount(args[0], args[1])
if MNTDIR is None:
ogRaiseError(OG_ERR_NOTFOUND, f"Device {args[0]} {args[1]}")
return
DEVICE = ogDiskToDev(args[0], args[1])
UUID = subprocess.check_output(['blkid', '-o', 'value', '-s', 'UUID', DEVICE]).decode().strip()
NEWUUID = subprocess.check_output(['cat', '/proc/sys/kernel/random/uuid']).decode().strip()
# Cambiamos UUID a la partición
ogUnmount(args[0], args[1])
subprocess.run(['tune2fs', DEVICE, '-U', NEWUUID], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Cambiamos UUID en la configuración (fstab y grub)
ogMount(args[0], args[1])
for f in [f"{MNTDIR}/etc/fstab", f"{MNTDIR}/{{,boot/}}{{grubMBR,grubPARTITION}}/boot/{{,grub{,2},{,efi/}EFI/*/}}/{{menu.lst,grub.cfg}}"]:
if os.path.isfile(f):
subprocess.run(['sed', '-i', f's/{UUID}/{NEWUUID}/g', f], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

View File

@ -0,0 +1,91 @@
#!/usr/bin/env python3
import os
import sys
import re
import time
from datetime import datetime, timedelta
"""
@file poweroffconf
@brief Control de parada tras tiempo de inactividad para ahorro de energía.
@param int_minutos Minutos de inactividad (opcional); "no" para deshabilitar.
@note La comprobación periódica debe ejecutarse en el "cron" del sistema.
@note Fichero de configuración: /etc/poweroff.conf
@version 1.0.5: incluir opción para deshabilitar ahorro de energía.
@version 1.1.1: Corregir problema al cambiar de día
"""
OPENGNSYS = os.getenv('OPENGNSYS', '/opt/opengnsys')
OGETC = os.getenv('OGETC', f'{OPENGNSYS}/etc')
POWEROFFCONF = '/etc/poweroff.conf'
def ogRaiseError(error_code, message):
print(f"Error {error_code}: {message}", file=sys.stderr)
sys.exit(1)
if not os.path.isfile(POWEROFFCONF):
ogRaiseError('OG_ERR_NOTFOUND', POWEROFFCONF)
config = {}
with open(POWEROFFCONF) as f:
for line in f:
name, var = line.partition("=")[::2]
config[name.strip()] = str(var).strip()
POWEROFFSLEEP = config.get('POWEROFFSLEEP')
POWEROFFTIME = config.get('POWEROFFTIME')
if len(sys.argv) == 1:
if not POWEROFFSLEEP:
ogRaiseError('OG_ERR_FORMAT', "Sin tiempo de espera.")
elif len(sys.argv) == 2:
POWEROFFSLEEP = sys.argv[1]
if POWEROFFSLEEP == "no":
POWEROFFSLEEP = ""
elif not re.match(r'^\d*$', POWEROFFSLEEP):
ogRaiseError('OG_ERR_FORMAT', 'Parámetro debe ser núm. minutos o "no" para deshabilitar.')
with open(POWEROFFCONF, 'r') as file:
data = file.read()
data = re.sub(r'POWEROFFSLEEP=.*', f'POWEROFFSLEEP={POWEROFFSLEEP}', data)
with open(POWEROFFCONF, 'w') as file:
file.write(data)
if POWEROFFSLEEP:
POWEROFFTIME = int((datetime.now() + timedelta(minutes=int(POWEROFFSLEEP))).timestamp())
with open(POWEROFFCONF, 'r') as file:
data = file.read()
data = re.sub(r'POWEROFFTIME=.*', f'POWEROFFTIME={POWEROFFTIME}', data)
with open(POWEROFFCONF, 'w') as file:
file.write(data)
sys.exit(0)
else:
ogRaiseError('OG_ERR_FORMAT', f"Formato: {sys.argv[0]} [int_minutos | no]")
pgrep_output = os.popen('pgrep -fa 2>&1').read()
if 'invalid' in pgrep_output:
PGREP = 'pgrep -fl'
else:
PGREP = 'pgrep -fa'
pgrep_result = os.popen(f'{PGREP} {OPENGNSYS}').read()
if re.search(f'{OGETC}|{sys.argv[0]}', pgrep_result) is None:
with open(POWEROFFCONF, 'r') as file:
data = file.read()
data = re.sub(r'POWEROFFTIME=.*', 'POWEROFFTIME=', data)
with open(POWEROFFCONF, 'w') as file:
file.write(data)
else:
NOW = int(time.time())
if not POWEROFFTIME:
POWEROFFTIME = int((datetime.now() + timedelta(minutes=int(POWEROFFSLEEP))).timestamp())
with open(POWEROFFCONF, 'r') as file:
data = file.read()
data = re.sub(r'POWEROFFTIME=.*', f'POWEROFFTIME={POWEROFFTIME}', data)
with open(POWEROFFCONF, 'w') as file:
file.write(data)
else:
if NOW >= int(POWEROFFTIME):
os.system(f'{OPENGNSYS}/scripts/poweroff')

View File

@ -0,0 +1,50 @@
import os
import subprocess
import socket
#!/usr/bin/env python3
def get_ip_address():
return socket.gethostbyname(socket.gethostname())
# Fichero de registro de incidencias (en el servidor; si no, en local).
OPENGNSYS = os.getenv('OPENGNSYS', '/opt/opengnsys')
OGLOGFILE = os.getenv('OGLOGFILE', f'{OPENGNSYS}/log/{get_ip_address()}.log')
try:
with open(OGLOGFILE, 'a'):
pass
except IOError:
OGLOGFILE = '/var/log/opengnsys.log'
LOGLEVEL = 5
# Matando plymount para iniciar browser o shell
subprocess.run(['pkill', '-9', 'plymouthd'])
# Arranque de OpenGnsys Client daemon (socket).
print(os.getenv('MSG_LAUNCHCLIENT', '.'))
# Indicar fichero de teclado de Qt para el idioma especificado (tipo "es.qmap").
lang = os.getenv('LANG', '')
if os.path.isfile(f'/usr/local/etc/{lang.split("_")[0]}.qmap'):
os.environ['QWS_KEYBOARD'] = f'TTY:keymap=/usr/local/etc/{lang.split("_")[0]}.qmap'
ogstatus = os.getenv('ogstatus', '')
if os.path.isfile(f'{OPENGNSYS}/bin/ogAdmClient') and ogstatus != 'offline':
# Ejecutar servicio cliente.
subprocess.run([f'{OPENGNSYS}/bin/ogAdmClient', '-f', f'{OPENGNSYS}/etc/ogAdmClient.cfg', '-l', OGLOGFILE, '-d', str(LOGLEVEL)])
else:
OGMENU = None
for FILE in ['index', os.getenv('OGGROUP', ''), get_ip_address()]:
if os.path.isfile(f'{OPENGNSYS}/menus/{FILE}.html'):
OGMENU = f'{OPENGNSYS}/menus/{FILE}.html'
break
if OGMENU:
subprocess.run([f'{OPENGNSYS}/bin/browser', '-qws', OGMENU])
# Si fallo en cliente y modo "admin", cargar shell; si no, salir.
if os.getenv('ogactiveadmin') == 'true':
subprocess.run(['bash'])

View File

@ -0,0 +1,47 @@
import os
import subprocess
print("==============================================")
print("OpenGnsys Clonning Engine Start...")
# Cargar entorno de OpenGnsys
#os.environ['OGETC'] = '/opt/opengnsys/etc' #Entorno opengnsys
os.environ['OGETC'] = 'shared/etc' #Pruebas locales
print (f"OGETC: {os.environ['OGETC']}")
os.environ['PYTHONUNBUFFERED'] = '1'
print (f"PYTHONUNBUFFERED: {os.environ['PYTHONUNBUFFERED']}")
#loadenviron_path = os.path.join(os.environ['OGETC'], 'preinit', 'loadenviron.sh')
loadenviron_path = os.path.join(os.environ['OGETC'], 'preinit', 'loadenviron.py')
print (f"loadenviron_path: {loadenviron_path}")
exec(open(loadenviron_path).read())
print ("set environment:")
subprocess.run(['bash', '-c', f'set -a && source {loadenviron_path} && set +a'], shell=True)
print("==============================================")
# Scripts de inicio
scripts = ['fileslinks', 'loadmodules', 'metadevs', 'mountrepo', 'poweroff', 'otherservices']
for script in scripts:
script_path = os.path.join(os.environ['OGETC'], 'preinit', f'{script}.sh')
print (f"script_path: {script_path}")
subprocess.run(['bash', script_path])
# Check and run the appropriate init script
init_scripts = [
os.path.join(os.environ['OGETC'], 'init', f'{os.environ.get("IPV4ADDR", "")}.sh'),
os.path.join(os.environ['OGETC'], 'init', f'{os.environ.get("OGGROUP", "")}.sh'),
os.path.join(os.environ['OGETC'], 'init', 'default.sh')
]
for script in init_scripts:
if os.path.isfile(script):
subprocess.run(['bash', script])
break
else:
print("No se ha encontrado script de inicio")
subprocess.run(['halt'])
print("OpenGnsys Clonning Engine End.")
print("==============================================")

View File

@ -4,6 +4,15 @@
set -a
source /opt/opengnsys/etc/preinit/loadenviron.sh
echo "OGBIN: $OGBIN"
echo "OGETC: $OGETC"
echo "OGLIB: $OGLIB"
echo "OGAPI: $OGAPI"
echo "OGSCRIPTS: $OGSCRIPTS"
echo "OGIMG: $OGIMG"
echo "OGCAC: $OGCAC"
echo "OGLOG: $OGLOG"
# Scripts de inicio.
for f in fileslinks loadmodules metadevs mountrepo poweroff otherservices; do
$OGETC/preinit/$f.sh

View File

@ -0,0 +1,73 @@
import os
import shutil
import stat
# Si está configurado OpenGnsys ...
if os.getenv("OPENGNSYS"):
print(os.getenv("MSG_MAKELINKS", "."))
# Shell BASH por defecto (para usar "runtest")
try:
os.symlink('/bin/bash', '/bin/sh')
except FileExistsError:
pass
# Crear directorio de bloqueos
os.makedirs('/var/lock', exist_ok=True)
if not os.path.exists('/var/lock'):
os.makedirs('/run/lock', exist_ok=True)
# Crear ficheros temporales.
oglogcommand = os.getenv("OGLOGCOMMAND")
oglogsession = os.getenv("OGLOGSESSION")
temp_files = [oglogcommand, f"{oglogcommand}.tmp", oglogsession, "/tmp/menu.tmp"]
for temp_file in temp_files:
with open(temp_file, 'a'):
os.utime(temp_file, None)
os.chmod(temp_file, 0o777)
# Enlaces para Qt Embeded.
qtdir = "/usr/local"
os.makedirs(os.path.join(qtdir, 'etc'), exist_ok=True)
os.makedirs(os.path.join(qtdir, 'lib'), exist_ok=True)
os.makedirs(os.path.join(qtdir, 'plugins'), exist_ok=True)
oglib = os.getenv("OGLIB")
for i in os.listdir(os.path.join(oglib, 'qtlib')) + [os.path.join(oglib, 'fonts')]:
src = os.path.join(oglib, 'qtlib', i)
dst = os.path.join(qtdir, 'lib', i)
if not os.path.exists(dst):
try:
os.symlink(src, dst)
except FileExistsError:
pass
for i in os.listdir(os.path.join(oglib, 'qtplugins')):
src = os.path.join(oglib, 'qtplugins', i)
dst = os.path.join(qtdir, 'plugins', i)
if not os.path.exists(dst):
try:
os.symlink(src, dst)
except FileExistsError:
pass
ogetc = os.getenv("OGETC")
for i in os.listdir(ogetc):
if i.endswith('.qmap'):
src = os.path.join(ogetc, i)
dst = os.path.join(qtdir, 'etc', i)
if not os.path.exists(dst):
try:
os.symlink(src, dst)
except FileExistsError:
pass
# Autenticación con clave pública para SSH
if os.path.isfile('/scripts/ssl/authorized_keys'):
for file in os.listdir('/scripts/ssl'):
shutil.copy(os.path.join('/scripts/ssl', file), '/root/.ssh')
else:
# FIXME Error: entorno de OpenGnsys no configurado.
print("Error: OpenGnsys environment is not configured.") # FIXME: definir mensaje.
exit(1)

View File

@ -0,0 +1,202 @@
import os
import subprocess
#!/usr/bin/env python3
print("=============== START LOAD ENVIRONMENT =================")
# Idioma por defecto.
os.environ["LANG"] = os.getenv("LANG", "es_ES")
print("-- step 2")
os.environ["LC_ALL"] = os.getenv("LC_ALL", os.environ["LANG"])
print("-- step 3")
result = subprocess.run(["locale-gen", os.environ["LANG"]], capture_output=True, text=True)
if result.returncode != 0:
print(f"Error generating locale: {result.stderr}")
print("-- step 4")
opengnsys_path = os.environ['OPENGNSYS']
print(f"OPENGNSYS Directory: {opengnsys_path}")
print("-- step 5")
# Directorios del proyecto OpenGnsys.
os.environ["OPENGNSYS"] = os.getenv("OPENGNSYS", "/opt/opengnsys")
print("-- step 6")
print (f"OPENGNSYS: {os.environ['OPENGNSYS']}")
if os.path.isdir(os.environ["OPENGNSYS"]):
print("OPENGNSYS directory found")
os.environ["OGBIN"] = os.path.join(os.environ["OPENGNSYS"], "bin")
os.environ["OGETC"] = os.path.join(os.environ["OPENGNSYS"], "etc")
os.environ["OGLIB"] = os.path.join(os.environ["OPENGNSYS"], "lib")
os.environ["OGAPI"] = os.path.join(os.environ["OGLIB"], "engine", "bin")
os.environ["OGSCRIPTS"] = os.path.join(os.environ["OPENGNSYS"], "scripts")
os.environ["OGIMG"] = os.path.join(os.environ["OPENGNSYS"], "images")
os.environ["OGCAC"] = os.path.join(os.environ["OPENGNSYS"], "cache")
os.environ["OGLOG"] = os.path.join(os.environ["OPENGNSYS"], "log")
os.environ["PATH"] = os.pathsep.join([
os.environ["PATH"],
"/sbin",
"/usr/sbin",
"/usr/local/sbin",
"/bin",
"/usr/bin",
"/usr/local/bin",
"/opt/oglive/rootfs/opt/drbl/sbin",
os.environ["OGSCRIPTS"],
os.environ["OGAPI"],
os.environ["OGBIN"]
])
print("-- step 7")
# Exportar parámetros del kernel.
with open("/proc/cmdline") as f:
for i in f.read().split():
if "=" in i:
key, value = i.split("=", 1)
os.environ[key] = value
print("-- step 8")
# Cargar fichero de idioma.
lang_file = os.path.join(os.environ["OGETC"], f"lang.{os.environ['LANG'].split('@')[0]}.conf")
if os.path.isfile(lang_file):
with open(lang_file) as f:
for line in f:
if "=" in line:
key, value = line.strip().split("=", 1)
os.environ[key] = value
print("-- step 9")
# Mensaje de carga del entorno.
print(os.getenv("MSG_LOADAPI", "."))
print("-- step 10")
# Cargar mapa de teclado.
subprocess.run(["loadkeys", os.environ["LANG"].split("_")[0]], stdout=subprocess.DEVNULL)
print("-- step 10.1")
# Imprimir todas las variables de entorno declaradas hasta el momento.
for key, value in os.environ.items():
print(f"{key}: {value}")
print("-- step 11")
# Cargar API de funciones.
def execute_lib_file(filepath):
with open(filepath) as f:
code = compile(f.read(), filepath, 'exec')
exec(code, globals())
for lib_file in os.listdir(os.environ["OGAPI"]):
if lib_file.endswith(".lib"):
execute_lib_file(os.path.join(os.environ["OGAPI"], lib_file))
# for lib_file in os.listdir(os.environ["OGAPI"]):
# if lib_file.endswith(".lib"):
# exec(open(os.path.join(os.environ["OGAPI"], lib_file)).read())
print("-- step 12")
# Cargar configuración del engine.
engine_cfg = os.path.join(os.environ["OGETC"], "engine.cfg")
if os.path.isfile(engine_cfg):
exec(open(engine_cfg).read())
os.environ["OGLOGCOMMAND"] = os.getenv("OGLOGCOMMAND", "/tmp/command.log")
os.environ["OGLOGSESSION"] = os.getenv("OGLOGSESSION", "/tmp/session.log")
print("-- step 13")
# Cargar las APIs según engine.
ogengine = os.getenv("ogengine")
if ogengine:
for api_file in os.listdir(os.environ["OGAPI"]):
if api_file.endswith(f".{ogengine}"):
exec(open(os.path.join(os.environ["OGAPI"], api_file)).read())
print("-- step 14")
# Configuración de la red (modo offline).
initrd_cfg = "/tmp/initrd.cfg"
if os.path.isfile(initrd_cfg):
with open(initrd_cfg) as f:
for line in f:
if line.startswith("DEVICECFG="):
device_cfg = line.strip().split("=", 1)[1]
os.environ["DEVICECFG"] = device_cfg
if os.path.isfile(device_cfg):
exec(open(device_cfg).read())
print("-- step 15")
# FIXME Pruebas para grupos de ordenadores
os.environ["OGGROUP"] = os.getenv("group", "")
root_repo = os.getenv("ROOTREPO", os.getenv("OGSERVERIMAGES"))
# Fichero de registros.
og_log_file = os.path.join(os.environ["OGLOG"], f"{ogGetIpAddress()}.log")
os.environ["OGLOGFILE"] = og_log_file
else:
print("ERROR: OPENGNSYS directory not found")
# Compatibilidad para usar proxy en clientes ogLive.
if not os.getenv("http_proxy") and os.getenv("ogproxy"):
os.environ["http_proxy"] = os.getenv("ogproxy")
# Compatibilidad para usar servidor DNS en clientes ogLive.
if not os.path.isfile("/run/resolvconf/resolv.conf") and os.getenv("ogdns"):
os.makedirs("/run/resolvconf", exist_ok=True)
with open("/run/resolvconf/resolv.conf", "w") as f:
f.write(f"nameserver {os.getenv('ogdns')}\n")
# Declaración de códigos de error.
error_codes = {
"OG_ERR_FORMAT": 1,
"OG_ERR_NOTFOUND": 2,
"OG_ERR_PARTITION": 3,
"OG_ERR_LOCKED": 4,
"OG_ERR_IMAGE": 5,
"OG_ERR_NOTOS": 6,
"OG_ERR_NOTEXEC": 7,
"OG_ERR_NOTWRITE": 14,
"OG_ERR_NOTCACHE": 15,
"OG_ERR_CACHESIZE": 16,
"OG_ERR_REDUCEFS": 17,
"OG_ERR_EXTENDFS": 18,
"OG_ERR_OUTOFLIMIT": 19,
"OG_ERR_FILESYS": 20,
"OG_ERR_CACHE": 21,
"OG_ERR_NOGPT": 22,
"OG_ERR_REPO": 23,
"OG_ERR_NOMSDOS": 24,
"OG_ERR_IMGSIZEPARTITION": 30,
"OG_ERR_UPDATECACHE": 31,
"OG_ERR_DONTFORMAT": 32,
"OG_ERR_IMAGEFILE": 33,
"OG_ERR_GENERIC": 40,
"OG_ERR_UCASTSYNTAXT": 50,
"OG_ERR_UCASTSENDPARTITION": 51,
"OG_ERR_UCASTSENDFILE": 52,
"OG_ERR_UCASTRECEIVERPARTITION": 53,
"OG_ERR_UCASTRECEIVERFILE": 54,
"OG_ERR_MCASTSYNTAXT": 55,
"OG_ERR_MCASTSENDFILE": 56,
"OG_ERR_MCASTRECEIVERFILE": 57,
"OG_ERR_MCASTSENDPARTITION": 58,
"OG_ERR_MCASTRECEIVERPARTITION": 59,
"OG_ERR_PROTOCOLJOINMASTER": 60,
"OG_ERR_DONTMOUNT_IMAGE": 70,
"OG_ERR_DONTSYNC_IMAGE": 71,
"OG_ERR_DONTUNMOUNT_IMAGE": 72,
"OG_ERR_NOTDIFFERENT": 73,
"OG_ERR_SYNCHRONIZING": 74,
"OG_ERR_NOTUEFI": 80,
"OG_ERR_NOTBIOS": 81
}
for key, value in error_codes.items():
os.environ[key] = str(value)

View File

@ -18,6 +18,8 @@
export LANG="${LANG:-es_ES}"
locale-gen $LANG
echo "Cargando entorno de OpenGnsys (load environment)..."
# Directorios del proyecto OpenGnsys.
export OPENGNSYS="${OPENGNSYS:-/opt/opengnsys}"
if [ -d $OPENGNSYS ]; then

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python3
import os
import subprocess
import glob
"""
@file loadmodules.py
@brief Script de inicio para cargar módulos complementarios del kernel.
@version 1.0.5 - Cargar módulos específicos para el cliente.
"""
def main():
msg_loadmodules = os.getenv('MSG_LOADMODULES', '.')
print(msg_loadmodules)
# Módulo del ratón.
subprocess.run(['modprobe', 'psmouse'], stderr=subprocess.DEVNULL)
# Cargar módulos específicos del kernel del cliente.
kernel_version = os.uname().release
module_path = os.path.join(os.getenv('OGLIB', ''), 'modules', kernel_version, '*.ko')
for module in glob.glob(module_path):
if os.access(module, os.R_OK):
subprocess.run(['insmod', module], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,29 @@
import os
import subprocess
import sys
#!/usr/bin/env python3
"""
@file metadevs.py
@brief Script de inicio para detectar metadispositivos LVM y RAID.
@note Desglose del script "loadenviron.sh".
@warning License: GNU GPLv3+
"""
def main():
opengnsys = os.getenv('OPENGNSYS')
msg_detectlvmraid = os.getenv('MSG_DETECTLVMRAID', '')
if opengnsys:
print(msg_detectlvmraid)
# Detectar metadispositivos LVM.
subprocess.run(['vgchange', '-ay'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Detectar metadispositivos RAID.
subprocess.run(['dmraid', '-ay'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
else:
# FIXME Error: entorno de OpenGnsys no configurado.
print("Error: OpenGnsys environment is not configured.") # FIXME: definir mensaje.
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,62 @@
#!/usr/bin/env python3
import os
import subprocess
#/**
# @file mountrepo.py
# @brief Script para montar el repositorio de datos remoto.
#*/
OGIMG = os.getenv('OGIMG', '/opt/opengnsys/images')
ROOTREPO = os.getenv('ROOTREPO', os.getenv('ROOTSERVER'))
ogactiveadmin = os.getenv('ogactiveadmin')
ogprotocol = os.getenv('ogprotocol', 'smb')
ogunit = os.getenv('ogunit', '')
ogstatus = os.getenv('ogstatus')
SERVER = os.getenv('SERVER')
OGCAC = os.getenv('OGCAC')
MSG_MOUNTREPO = "Mounting repository using protocol: {} in mode: {}"
def mount_repo():
if ogactiveadmin == "true":
os.environ['boot'] = 'admin' # ATENCIÓN: siempre en modo "admin".
subprocess.run(['umount', OGIMG], stderr=subprocess.DEVNULL)
protocol = ogprotocol
OGUNIT = f"/{ogunit}" if ogunit else ""
print(MSG_MOUNTREPO.format(protocol, 'admin'))
if protocol == 'nfs':
subprocess.run(['mount.nfs', f'{ROOTREPO}:{OGIMG}{OGUNIT}', OGIMG, '-o', 'rw,nolock'])
elif protocol == 'smb':
PASS = get_password()
subprocess.run(['mount.cifs', f'//{ROOTREPO}/ogimages{OGUNIT}', OGIMG, '-o', f'rw,serverino,acl,username=opengnsys,password={PASS}'])
elif protocol == 'local':
handle_local_mount()
def get_password():
try:
with open('/scripts/ogfunctions') as f:
for line in f:
if 'OPTIONS=' in line:
return line.split('pass=')[1].split()[0]
except Exception:
pass
return 'og'
def handle_local_mount():
if ogstatus == "offline" or not SERVER:
TYPE = subprocess.getoutput("blkid | grep REPO | awk -F'TYPE=' '{print $2}' | tr -d '\"'")
if not TYPE:
if os.path.isdir(f'{OGCAC}/{OGIMG}'):
subprocess.run(['mount', '--bind', f'{OGCAC}/{OGIMG}', OGIMG])
else:
subprocess.run(['mount', '-t', TYPE, 'LABEL=REPO', OGIMG], stderr=subprocess.DEVNULL)
else:
if subprocess.run(['smbclient', '-L', SERVER, '-N'], stderr=subprocess.DEVNULL).returncode == 0:
PASS = get_password()
subprocess.run(['mount.cifs', f'//{ROOTREPO}/ogimages', OGIMG, '-o', f'rw,serverino,acl,username=opengnsys,password={PASS}'])
if __name__ == "__main__":
mount_repo()

View File

@ -0,0 +1,44 @@
#!/usr/bin/env python3
import os
import subprocess
"""
@file otherservices.py
@brief Script de inicio para cargar otros servicios complementarios.
"""
# Lanzar servicios complementarios del cliente.
print(os.getenv('MSG_OTHERSERVICES', '.'))
# Iniciar rsyslog, si es necesario.
if not os.path.exists('/dev/log'):
subprocess.run(['service', 'rsyslog', 'start'])
# Adpatar la clave de "root" para acceso SSH.
with open('/scripts/ogfunctions', 'r') as file:
for line in file:
if 'OPTIONS=' in line:
pass_option = line.split('pass=')[1].split()[0]
break
else:
pass_option = 'og'
passwd = pass_option or 'og'
subprocess.run(['passwd', 'root'], input=f'{passwd}\n{passwd}\n', text=True)
# Cargar el entorno OpenGnsys en conexión SSH.
subprocess.run(['cp', '-a', f'{os.getenv("OPENGNSYS")}/etc/preinit/loadenviron.sh', '/etc/profile.d/'])
# Arrancar SSH.
subprocess.run(['/etc/init.d/ssh', 'start'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Desactivado apagado de monitor.
# subprocess.run(['setterm', '-blank', '0', '-powersave', 'off', '-powerdown', '0'], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Activado WOL en la interfaz usada en arranque PXE.
subprocess.run(['ethtool', '-s', os.getenv('DEVICE'), 'wol', 'g'], stderr=subprocess.DEVNULL)
# TODO Localizar correctamente el script de arranque.
if os.path.isfile('/opt/opengnsys/scripts/runhttplog.sh'):
subprocess.run(['/opt/opengnsys/scripts/runhttplog.sh'], stderr=subprocess.DEVNULL)

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
import os
import subprocess
import sys
"""
@file poweroff.py
@brief Script de inicio para cargar el proceso comprobación de clientes inactivos.
@note Arranca y configura el proceso "cron".
"""
def main():
opengnsys = os.getenv('OPENGNSYS')
if opengnsys:
msg_poweroffconf = os.getenv('MSG_POWEROFFCONF', '.')
print(msg_poweroffconf)
ogntp = os.getenv('ogntp')
status = os.getenv('status')
# Sincronización horaria con servidor NTP.
if ogntp and status != "offline":
subprocess.run(['ntpdate', ogntp])
# Crear fichero de configuración por defecto (30 min. de espera).
poweroff_conf = '/etc/poweroff.conf'
with open(poweroff_conf, 'w') as f:
f.write("POWEROFFSLEEP=30\nPOWEROFFTIME=\n")
# Incluir zona horaria en el fichero de configuración.
with open('/proc/cmdline') as f:
cmdline = f.read()
tz = ' '.join([x for x in cmdline.split() if x.startswith('TZ=')])
with open(poweroff_conf, 'a') as f:
f.write(tz + '\n')
# Lanzar el proceso "cron".
subprocess.run(['cron', '-l'])
# Definir la "crontab" lanzando el proceso de comprobación cada minuto.
ogbin = os.getenv('OGBIN')
crontab_line = f"* * * * * [ -x {ogbin}/poweroffconf ] && {ogbin}/poweroffconf\n"
subprocess.run(['crontab', '-'], input=crontab_line, text=True)
else:
# FIXME Error: entorno de OpenGnsys no configurado.
print("Error: OpenGnsys environment is not configured.") # FIXME: definir mensaje.
sys.exit(1)
if __name__ == "__main__":
main()