refs #1101 add ogUpdateCacheIsNecesary() and dependencies
parent
bc3d68e8fb
commit
646d1da734
|
@ -1,31 +1,81 @@
|
||||||
|
#/**
|
||||||
|
#@file FileLib.py
|
||||||
|
#@brief Librería o clase File
|
||||||
|
#@class File
|
||||||
|
#@brief Funciones para gestión de archivos y directorios.
|
||||||
|
#@warning License: GNU GPLv3+
|
||||||
|
#*/
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import hashlib
|
||||||
|
|
||||||
import ogGlobals
|
import ogGlobals
|
||||||
import SystemLib
|
import SystemLib
|
||||||
import CacheLib
|
import CacheLib
|
||||||
import FileSystemLib
|
import FileSystemLib
|
||||||
|
|
||||||
def ogCalculateChecksum(*args):
|
#/**
|
||||||
# Check if help is requested
|
# ogCalculateChecksum [ str_repo | int_ndisk int_npart ] path_filepath
|
||||||
if "help" in args:
|
#@brief Devuelve la suma de comprobación (checksum) de un fichero.
|
||||||
print("ogCalculateChecksum [ str_repo | int_ndisk int_npartition ] path_filepath")
|
#@param path_filepath camino del fichero (independiente de mayúsculas)
|
||||||
print("ogCalculateChecksum REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf")
|
#@param str_repo repositorio de ficheros
|
||||||
|
#@param int_ndisk nº de orden del disco
|
||||||
|
#@param int_npartition nº de orden de la partición
|
||||||
|
#@return hex_checksum Checksum del fichero
|
||||||
|
#*/ ##
|
||||||
|
#ogCalculateChecksum ([ str_repo | int_ndisk int_npartition ] path_filepath")
|
||||||
|
#ogCalculateChecksum (container='REPO', file='ubuntu.img') ==> ef899299caf8b517ce36f1157a93d8bf
|
||||||
|
#ogCalculateChecksum (disk=1, par=1, file='ubuntu.img') ==> ef899299caf8b517ce36f1157a93d8bf
|
||||||
|
def ogCalculateChecksum (disk=None, par=None, container=None, file=None):
|
||||||
|
if file is None:
|
||||||
|
raise TypeError ('missing required argument: "file"')
|
||||||
|
|
||||||
|
if container is not None:
|
||||||
|
if disk is None and par is None:
|
||||||
|
## we were given container=
|
||||||
|
f = ogGetPath (src=container, file=file)
|
||||||
|
dev_err = f'{container} {file}'
|
||||||
|
print (f'ogGetPath (src=({container}), file=({file})) = f ({f})')
|
||||||
|
else:
|
||||||
|
raise TypeError ('argument "container" can be specified along neither "disk" nor "par"')
|
||||||
|
|
||||||
|
else:
|
||||||
|
if disk is not None and par is not None:
|
||||||
|
## we were given disk= par=
|
||||||
|
f = ogGetPath (src=f'{disk} {par}', file=file)
|
||||||
|
dev_err = f'{disk} {par} {file}'
|
||||||
|
print (f'ogGetPath (src=({disk} {par}), file=({file})) = f ({f})')
|
||||||
|
elif disk is None and par is None:
|
||||||
|
## we were given nothing
|
||||||
|
f = ogGetPath (file=file)
|
||||||
|
dev_err = file
|
||||||
|
print (f'ogGetPath (file=({file})) = f ({f})')
|
||||||
|
else:
|
||||||
|
raise TypeError ('if one of "disk" and "par" are specified, then both must be')
|
||||||
|
|
||||||
|
if not f:
|
||||||
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, dev_err)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get the file path
|
last_n_bytes = 1024*1024
|
||||||
file_path = ogGetPath(*args)
|
if last_n_bytes >= os.stat ('/bin/ls').st_size:
|
||||||
if not file_path:
|
return ogCalculateFullChecksum (disk, par, container, file)
|
||||||
SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args)
|
with open (f, 'rb') as fd:
|
||||||
return
|
fd.seek (-last_n_bytes, os.SEEK_END)
|
||||||
|
data = file.read()
|
||||||
|
md5 = hashlib.md5(data).hexdigest()
|
||||||
|
|
||||||
# Calculate the checksum
|
return md5
|
||||||
result = subprocess.run(["tail", "-c1M", file_path], capture_output=True)
|
|
||||||
checksum = result.stdout.decode().split()[0]
|
|
||||||
|
|
||||||
return checksum
|
|
||||||
|
|
||||||
|
#/**
|
||||||
|
# ogCompareChecksumFiles [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target
|
||||||
|
#@brief Metafunción que compara las sumas de comprobación almacenadas de 2 ficheros.
|
||||||
|
#@return bool_compare Valor de comparación.
|
||||||
|
#@warning No es necesario especificar la extensión ".sum".
|
||||||
|
#*/ ##
|
||||||
def ogCompareChecksumFiles(*args):
|
def ogCompareChecksumFiles(*args):
|
||||||
# Variables locales.
|
# Variables locales.
|
||||||
ARGS = args
|
ARGS = args
|
||||||
|
@ -59,24 +109,63 @@ def ogCompareChecksumFiles(*args):
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def ogCalculateFullChecksum(*args):
|
|
||||||
# Variables locales.
|
#/**
|
||||||
FILE = None
|
# ogCalculateFullChecksum [ str_repo | int_ndisk int_npart ] path_filepath
|
||||||
if "help" in args:
|
#@brief Devuelve la suma COMPLETA de comprobación (checksum) de un fichero.
|
||||||
SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf")
|
#@param path_filepath camino del fichero (independiente de mayúsculas)
|
||||||
|
#@param str_repo repositorio de ficheros
|
||||||
|
#@param int_ndisk nº de orden del disco
|
||||||
|
#@param int_npartition nº de orden de la partición
|
||||||
|
#@return hex_checksum Checksum del fichero
|
||||||
|
#*/ ##
|
||||||
|
def ogCalculateFullChecksum (disk=None, par=None, container=None, file=None):
|
||||||
|
if file is None:
|
||||||
|
raise TypeError ('missing required argument: "file"')
|
||||||
|
|
||||||
|
if container is not None:
|
||||||
|
if disk is None and par is None:
|
||||||
|
## we were given container=
|
||||||
|
f = ogGetPath (src=container, file=file)
|
||||||
|
dev_err = f'{container} {file}'
|
||||||
|
print (f'ogGetPath (src=({container}), file=({file})) = f ({f})')
|
||||||
|
else:
|
||||||
|
raise TypeError ('argument "container" can be specified along neither "disk" nor "par"')
|
||||||
|
|
||||||
|
else:
|
||||||
|
if disk is not None and par is not None:
|
||||||
|
## we were given disk= par=
|
||||||
|
f = ogGetPath (src=f'{disk} {par}', file=file)
|
||||||
|
dev_err = f'{disk} {par} {file}'
|
||||||
|
print (f'ogGetPath (src=({disk} {par}), file=({file})) = f ({f})')
|
||||||
|
elif disk is None and par is None:
|
||||||
|
## we were given nothing
|
||||||
|
f = ogGetPath (file=file)
|
||||||
|
dev_err = file
|
||||||
|
print (f'ogGetPath (file=({file})) = f ({f})')
|
||||||
|
else:
|
||||||
|
raise TypeError ('if one of "disk" and "par" are specified, then both must be')
|
||||||
|
|
||||||
|
if not f:
|
||||||
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, dev_err)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Comprobar que existe el fichero y devolver sus datos.
|
md5 = hashlib.md5()
|
||||||
FILE = ogGetPath(*args)
|
with open (f, 'rb') as fd:
|
||||||
if not FILE:
|
for chunk in iter (lambda: fd.read (64*1024), b''):
|
||||||
SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args)
|
md5.update (chunk)
|
||||||
return
|
return md5.hexdigest()
|
||||||
|
|
||||||
# Calculate the checksum
|
|
||||||
result = subprocess.run(["md5sum", FILE, "-b"], capture_output=True)
|
|
||||||
checksum = result.stdout.decode().split()[0]
|
|
||||||
|
|
||||||
return checksum
|
|
||||||
|
|
||||||
|
#/**
|
||||||
|
# ogCopyFile [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target
|
||||||
|
#@brief Metafunción para copiar un fichero de sistema OpenGnSys a un directorio.
|
||||||
|
#@see ogGetPath
|
||||||
|
#@return Progreso de la copia.
|
||||||
|
#@warning Deben existir tanto el fichero origen como el directorio destino.
|
||||||
|
#*/ ##
|
||||||
|
|
||||||
def ogCopyFile(*args):
|
def ogCopyFile(*args):
|
||||||
# Variables locales.
|
# Variables locales.
|
||||||
|
@ -113,22 +202,45 @@ def ogCopyFile(*args):
|
||||||
result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET])
|
result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET])
|
||||||
return result.returncode
|
return result.returncode
|
||||||
|
|
||||||
def ogDeleteFile(*args):
|
|
||||||
# Variables locales.
|
#/**
|
||||||
FILE = None
|
# ogDeleteFile [ str_repo | int_ndisk int_npartition ] path_filepath
|
||||||
if "help" in args:
|
#@brief Metafunción que borra un fichero de un dispositivo.
|
||||||
SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_file", "$FUNCNAME 1 2 /tmp/newfile.txt")
|
#@see ogGetPath
|
||||||
|
#@version 0.9 - Pruebas con OpenGnSys.
|
||||||
|
#@author Ramon Gomez, ETSII Universidad de Sevilla
|
||||||
|
#@date 2009-09-29
|
||||||
|
#*/ ##
|
||||||
|
#ogDeleteFile ([ str_repo | int_ndisk int_npartition ] path_file)
|
||||||
|
#ogDeleteFile (container='REPO', file='/tmp/newfile.txt')
|
||||||
|
#ogDeleteFile (disk=1, par=2, file='/tmp/newfile.txt')
|
||||||
|
def ogDeleteFile (disk=None, par=None, container=None, file=None):
|
||||||
|
if file is None:
|
||||||
|
raise TypeError ('missing required argument: "file"')
|
||||||
|
|
||||||
|
if container is not None:
|
||||||
|
if disk is None and par is None:
|
||||||
|
## we were given container=
|
||||||
|
src = container
|
||||||
|
else:
|
||||||
|
raise TypeError ('argument "container" can be specified along neither "disk" nor "par"')
|
||||||
|
else:
|
||||||
|
if disk is not None and par is not None:
|
||||||
|
## we were given disk= par=
|
||||||
|
src = f'{disk} {par}'
|
||||||
|
else:
|
||||||
|
## we were given nothing
|
||||||
|
raise TypeError ('either "container" or both "disk" and "par" must be specified')
|
||||||
|
|
||||||
|
f = ogGetPath (src=src, file=file)
|
||||||
|
if not f:
|
||||||
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{src} {file}')
|
||||||
return
|
return
|
||||||
|
|
||||||
# Comprobar que existe el fichero y borrarlo.
|
|
||||||
FILE = ogGetPath(*args)
|
|
||||||
if not FILE:
|
|
||||||
SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args)
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
os.remove(FILE)
|
os.remove (f)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
SystemLib.ogRaiseError(OG_ERR_NOTFOUND, *args)
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, str (e))
|
||||||
return
|
return
|
||||||
|
|
||||||
def ogDeleteTree(*args):
|
def ogDeleteTree(*args):
|
||||||
|
|
|
@ -4,6 +4,7 @@ import subprocess
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
import os.path
|
import os.path
|
||||||
|
import shutil
|
||||||
|
|
||||||
import ogGlobals
|
import ogGlobals
|
||||||
import SystemLib
|
import SystemLib
|
||||||
|
@ -852,10 +853,104 @@ def ogCreateTorrent (disk=None, par=None, container=None, file=None, ip_bttrack=
|
||||||
#@param 1 str_REPO
|
#@param 1 str_REPO
|
||||||
#@param 2 str_Relative_path_file_OGIMG_with_/
|
#@param 2 str_Relative_path_file_OGIMG_with_/
|
||||||
#@param 3 md5 to check: use full to check download image torrent
|
#@param 3 md5 to check: use full to check download image torrent
|
||||||
#@return 0 (true) cache sin imagen, SI es necesario actualizar el fichero.
|
#@return True cache sin imagen, SI es necesario actualizar el fichero.
|
||||||
#@return 1 (false) imagen en la cache, NO es necesario actualizar el fichero
|
#@return False imagen en la cache, NO es necesario actualizar el fichero
|
||||||
#@return >1 (false) error de sintaxis (TODO)
|
#@return None error de sintaxis (TODO)
|
||||||
#@note
|
#@note
|
||||||
#@todo: Proceso en el caso de que el fichero tenga el mismo nombre, pero su contenido sea distinto.
|
#@todo: Proceso en el caso de que el fichero tenga el mismo nombre, pero su contenido sea distinto.
|
||||||
#@todo: Se dejan mensajes mientras se confirma su funcionamiento.
|
#@todo: Se dejan mensajes mientras se confirma su funcionamiento.
|
||||||
#*/ ##
|
#*/ ##
|
||||||
|
#ogUpdateCacheIsNecesary ('REPO', '/PS1_PH1.img', 'UNICAST')
|
||||||
|
#ogUpdateCacheIsNecesary ('REPO', '/ogclient.sqfs', 'FULL')
|
||||||
|
#ogUpdateCacheIsNecesary ('REPO', '/ogclient.sqfs', 'TORRENT')
|
||||||
|
def ogUpdateCacheIsNecesary (repo, file, proto):
|
||||||
|
if not CacheLib.ogFindCache():
|
||||||
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, '')
|
||||||
|
return None
|
||||||
|
|
||||||
|
if repo.lower() != 'repo':
|
||||||
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {repo} {file}')
|
||||||
|
return None
|
||||||
|
|
||||||
|
filesource = FileLib.ogGetPath (src=repo, file=file)
|
||||||
|
print (f'filesource ({filesource})')
|
||||||
|
if not filesource:
|
||||||
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {repo} {file}')
|
||||||
|
return None
|
||||||
|
|
||||||
|
# paso 1. si no existe la imagen, confirmar que es necesario actualizar la cache.
|
||||||
|
filetarget = FileLib.ogGetPath (src='CACHE', file=file)
|
||||||
|
print (f'filetarget ({filetarget})')
|
||||||
|
if not filetarget:
|
||||||
|
# borramos el fichero bf del torrent, en el caso de que se hubiese quedado de algun proceso fallido
|
||||||
|
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.torrent.bf'): ogDeleteFile ('CACHE', f'{file}.torrent.bf')
|
||||||
|
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.sum'): ogDeleteFile ('CACHE', f'{file}.sum')
|
||||||
|
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.full.sum'): ogDeleteFile ('CACHE', f'{file}.full.sum')
|
||||||
|
print ('TRUE(0), es necesario actualizar. Paso 1, la cache no contiene esa imagen ')
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Paso 2. Comprobamos que la imagen no estuviese en un proceso previo torrent
|
||||||
|
if FileLib.ogGetPath (file=f'{filetarget}.torrent.bf'):
|
||||||
|
#TODO: comprobar los md5 del fichero .torrent para asegurarnos que la imagen a descarga es la misma.
|
||||||
|
print ('TRUE(0), es necesario actualizar. Paso 2, la imagen esta en un estado de descarga torrent interrumpido')
|
||||||
|
return True
|
||||||
|
|
||||||
|
## En este punto la imagen en el repo y en la cache se llaman igual,
|
||||||
|
# paso 4. Obtener los md5 del fichero imagen en la cacha segun PROTOCOLO $3
|
||||||
|
if proto.lower() in ['full', 'torrent']:
|
||||||
|
#Buscamos MD5 en el REPO SOURCE
|
||||||
|
if os.path.exists (f'{filesource}.full.sum'):
|
||||||
|
with open (f'{filesource}.full.sum', 'r') as fd:
|
||||||
|
md5source = fd.read().strip()
|
||||||
|
else:
|
||||||
|
md5source = FileLib.ogCalculateFullChecksum (file=filesource)
|
||||||
|
|
||||||
|
# Generamos el MD5 (full) en la CACHE
|
||||||
|
if not os.path.exists (f'{filetarget}.full.sum'):
|
||||||
|
fullck = FileLib.ogCalculateFullChecksum (file=filetarget)
|
||||||
|
with open (f'{filetarget}.full.sum', 'w') as fd:
|
||||||
|
fd.write (fullck + '\n')
|
||||||
|
with open (f'{filetarget}.full.sum', 'r') as fd:
|
||||||
|
md5target = fd.read().strip()
|
||||||
|
# Generamos el MD5 (little) en la CACHE para posteriores usos del protocolo MULTICAST
|
||||||
|
if not os.path.exists (f'{filetarget}.sum'):
|
||||||
|
ck = FileLib.ogCalculateChecksum (file=filetarget)
|
||||||
|
with open (f'{filetarget}.sum', 'w') as fd:
|
||||||
|
fd.write (ck + '\n')
|
||||||
|
else:
|
||||||
|
#Buscamos MD5 en el REPO SOURCE
|
||||||
|
if os.path.exists (f'{filesource}.sum'):
|
||||||
|
with open (f'{filesource}.sum', 'r') as fd:
|
||||||
|
md5source = fd.read().strip()
|
||||||
|
else:
|
||||||
|
md5source = FileLib.ogCalculateChecksum (file=filesource)
|
||||||
|
|
||||||
|
# Generamos el MD5 (little) en la CACHE
|
||||||
|
if not os.path.exists (f'{filetarget}.sum'):
|
||||||
|
ck = FileLib.ogCalculateChecksum (file=filetarget)
|
||||||
|
with open (f'{filetarget}.sum', 'w') as fd:
|
||||||
|
fd.write (ck + '\n')
|
||||||
|
with open (f'{filetarget}.sum', 'r') as fd:
|
||||||
|
md5target = fd.read().strip()
|
||||||
|
#Generamos o copiamos MD5 (full) en la CACHE para posteriores usos con Torrent
|
||||||
|
# Si no existe el full.sum y si existe el .sum es porque el upateCACHE multicast o unicast ha sido correcto.
|
||||||
|
if not os.path.exists (f'{filetarget}.full.sum') and os.path.exists (f'{filetarget}.sum'):
|
||||||
|
if os.path.exists (f'{filesource}.full.sum'):
|
||||||
|
#Existe el .full.sum en REPO realizamos COPIA
|
||||||
|
shutil.copy2 (f'{filesource}.full.sum', f'{filetarget}.full.sum')
|
||||||
|
else:
|
||||||
|
#No existe .full.sum no en REPO LO GENERAMOS en la cache: situacion dificil que ocurra
|
||||||
|
fullck = FileLib.ogCalculateFullChecksum (file=filetarget)
|
||||||
|
with open (f'{filetarget}.full.sum', 'w') as fd:
|
||||||
|
fd.write (fullck + '\n')
|
||||||
|
|
||||||
|
# Paso 5. comparar los md5
|
||||||
|
if md5source == md5target:
|
||||||
|
print ('FALSE (1), No es neceario actualizar. Paso5.A la imagen esta en cache')
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print ('imagen en cache distinta, borramos la imagen anterior')
|
||||||
|
for f in [f'{filetarget}', f'{filetarget}.sum', f'{filetarget}.torrent', f'{filetarget}.full.sum']:
|
||||||
|
os.unlink (f)
|
||||||
|
print ('TRUE (0), Si es necesario actualizar.')
|
||||||
|
return True
|
||||||
|
|
Loading…
Reference in New Issue