219 lines
11 KiB
Python
219 lines
11 KiB
Python
#!/usr/bin/python3
|
|
#/**
|
|
# updateCache
|
|
#@brief Actualiza la cache del cliente con imagen o fichero iso.
|
|
#@param 1 REPO Origen del fichero. -accesible por nfs-samba-
|
|
#@param 2 str_fichero nombre del fichero a actualizar.
|
|
#@param 3 str_protoco. TORRENT | MULTICAST | UNICAST.
|
|
#@param 4 str_opcionesprotocolo
|
|
#@param 4 str_opcionesupdatecache
|
|
#@ejemplo: updateCache.py REPO imgname.img UNICAST 8042:42
|
|
#@return
|
|
#@exception OG_ERR_FORMAT formato incorrecto.
|
|
#@exception OG_ERR_NOTCACHE No existe cache -15-
|
|
#@exception $OG_ERR_CACHESIZE Tamaño de la paticion menor al archivo a descargar -16-
|
|
#@exception $OG_ERR_MCASTRECEIVERFILE Error en la recepción Multicast de un fichero -57-
|
|
#@exception $OG_ERR_PROTOCOLJOINMASTER Error en la conexión de una sesión Unicast|Multicast con el Master -60-
|
|
#@note
|
|
#@todo:
|
|
#*/ ##
|
|
|
|
import os.path
|
|
import sys
|
|
import re
|
|
import time
|
|
import subprocess
|
|
import shutil
|
|
import glob
|
|
import random
|
|
|
|
import ogGlobals
|
|
import SystemLib
|
|
import StringLib
|
|
import NetLib
|
|
import CacheLib
|
|
import FileLib
|
|
import ProtocolLib
|
|
import FileSystemLib
|
|
|
|
prog = os.path.basename (sys.argv[0])
|
|
print (f'argv ({sys.argv}) len ({len (sys.argv)})')
|
|
if len (sys.argv) < 3:
|
|
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} str_REPO _str_Relative_Path_OGIMG_with_/ PROTOCOLO OPCIONES_PROTOCOLO OPCIONES_UPDATECACHE')
|
|
sys.exit (1)
|
|
_, repositorio, path, protocolo, *other = sys.argv
|
|
optprotocolo = other[0] if len (other) > 0 else ''
|
|
cacheopts = other[1] if len (other) > 1 else ''
|
|
|
|
if 'RSYNC' == protocolo:
|
|
raise Exception ('synchronised images are no longer supported')
|
|
|
|
#Carga del configurador del engine
|
|
## (ogGlobals se encarga)
|
|
|
|
# Clear temporary file used as log track by httpdlog
|
|
# Limpia los ficheros temporales usados como log de seguimiento para httpdlog
|
|
open (ogGlobals.OGLOGCOMMAND, 'w').close()
|
|
if SystemLib.ogGetCaller() not in ['deployImage', 'restoreBaseImage', 'restoreDiffImage']:
|
|
open (ogGlobals.OGLOGSESSION, 'w').close()
|
|
SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {prog} {sys.argv}')
|
|
|
|
# Si MCASTWAIT menos que tiempo de espera del servidor lo aumento
|
|
MCASTWAIT = ogGlobals.MCASTWAIT
|
|
if ':' in optprotocolo:
|
|
port, wait, *other = optprotocolo.split (':')
|
|
else:
|
|
port, wait = ('', '')
|
|
if protocolo.startswith ('MULTICAST') and re.match (r'^-?\d+$', wait):
|
|
if int (MCASTWAIT or 0) < int (wait):
|
|
MCASTWAIT = int (wait) + 5
|
|
# Unidad organizativa.
|
|
## (no longer supported)
|
|
#print (f'repositorio ({repositorio}) path ({path}) protocolo ({protocolo}) optprotocolo ({optprotocolo}) cacheopts ({cacheopts}) MCASTWAIT ({MCASTWAIT})')
|
|
|
|
# Si es una ip y es distinta a la del recurso samba cambiamos de REPO.
|
|
if StringLib.ogCheckIpAddress (repositorio) or 'REPO' == repositorio:
|
|
if not NetLib.ogChangeRepo (repositorio):
|
|
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repositorio)
|
|
sys.exit (1)
|
|
repositorio = 'REPO'
|
|
repoip = NetLib.ogGetRepoIp()
|
|
SystemLib.ogEcho (['log', 'session'], None, f'{repositorio} {repoip} {protocolo} {optprotocolo}')
|
|
|
|
# Si el repositorio local CACHE no existe error 15.
|
|
if not CacheLib.ogFindCache():
|
|
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTCACHE, 'CACHE')
|
|
sys.exit (1)
|
|
|
|
# comprobar si la imagen existe (.img, .img.diff o directorio)
|
|
repofile = FileLib.ogGetPath ('REPO', f'/{path}')
|
|
if not os.path.exists (repofile):
|
|
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTFOUND, f'REPO /{path}')
|
|
sys.exit (1)
|
|
|
|
SystemLib.ogEcho (['log', 'session'], None, ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_DOUPDATE)
|
|
# Distingo si es monolitica o sincronizable
|
|
f = subprocess.run (['file', repofile], capture_output=True, text=True).stdout.lower()
|
|
if ' btrfs filesystem ' in f or ' ext4 filesystem ' in f or ' directory' in f:
|
|
raise Exception ('synchronised images are no longer supported')
|
|
rc = ProtocolLib.ogUpdateCacheIsNecesary (repositorio, path, protocolo)
|
|
# si rc=True: actualizamos; si rc=False: no actualizamos (exit 0); si rc=None: exit error
|
|
if rc == True: pass ## es necesario actualizar
|
|
elif rc == False: sys.exit (0) ## no es necesario actualizar
|
|
elif rc == None: sys.exit (ogGlobals.OG_ERR_UPDATECACHE) ## hubo errores
|
|
|
|
SystemLib.ogEcho (['log', 'session'], None, ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE)
|
|
cachesize = CacheLib.ogGetCacheSize()
|
|
cache_disk, cache_par = CacheLib.ogFindCache().split()
|
|
cachesizefree = FileSystemLib.ogGetFreeSize (cache_disk, cache_par)
|
|
path_repo = FileLib.ogGetPath ('REPO', path)
|
|
filesize = int (subprocess.run (['ls', '-sk', path_repo], capture_output=True, text=True).stdout.split()[0])
|
|
realfilesize = subprocess.run (['stat', '--format', '%s', repofile], capture_output=True, text=True).stdout
|
|
realfilesize = int (int (realfilesize) / 1024)
|
|
|
|
# La sincronizada, si existe la imagen en cache el espacio necesario
|
|
# es la nueva menos lo que ocupa la que ya hay.
|
|
sizerequired = filesize
|
|
|
|
#ERROR CACHESIZE 16 (tamanyo de la CACHE insuficiente)
|
|
if sizerequired >= cachesize:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_WARNING}: {ogGlobals.lang.MSG_ERR_CACHESIZE}: {path} = {sizerequired} > CACHE = {cachesize}')
|
|
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE')
|
|
sys.exit (1)
|
|
|
|
|
|
#ERROR CACHESIZE 16 (Espacio libre en CACHE insuficiente)
|
|
if sizerequired >= cachesizefree:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO}: ACTIONCACHEFULL={ogGlobals.ACTIONCACHEFULL}')
|
|
if 'NONE' == ogGlobals.ACTIONCACHEFULL:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_WARNING}: {ogGlobals.lang.MSG_ERR_CACHESIZE}: {path} = {sizerequired} > FREE SPACE CACHE = {cachesizefree}')
|
|
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE FULL, NO SPACE FREE')
|
|
sys.exit (1)
|
|
elif 'FORMAT' == ogGlobals.ACTIONCACHEFULL:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'[51] {ogGlobals.lang.MSG_HELP_ogFormatCache}')
|
|
CacheLib.ogUnmountCache()
|
|
CacheLib.ogFormatCache()
|
|
CacheLib.ogMountCache()
|
|
elif 'DELETE' == ogGlobals.ACTIONCACHEFULL:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'[51] {ogGlobals.lang.MSG_HELP_ogDeleteTree} {ogGlobals.OGCAC}{ogGlobals.OGIMG}/*')
|
|
for d in glob.glob (f'{ogGlobals.OGCAC}{ogGlobals.OGIMG}/*'):
|
|
shutil.rmtree (d)
|
|
else:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_WARNING}: {ogGlobals.lang.MSG_ERR_CACHESIZE}: {path} = {filesize} > CACHE = {cachesizefree}')
|
|
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE')
|
|
sys.exit (1)
|
|
|
|
# Comprobamos que imagen cache igual a la del repo. Si sincronizada no podemos comprobar.
|
|
rc = ProtocolLib.ogUpdateCacheIsNecesary (repositorio, path, protocolo)
|
|
# si rc=True: actualizamos; si rc=False: no actualizamos (exit 0); si rc=None: exit error
|
|
if rc == True: pass ## es necesario actualizar
|
|
elif rc == False: sys.exit (0) ## no es necesario actualizar
|
|
elif rc == None: sys.exit (ogGlobals.OG_ERR_UPDATECACHE) ## hubo errores
|
|
|
|
CacheLib.ogMountCache()
|
|
|
|
## Si no existe, crear subdirectorio para el fichero en la cache.
|
|
imgdir = FileLib.ogGetParentPath ('CACHE', f'/{path}')
|
|
if not imgdir:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'[5] {ogGlobals.lang.MSG_HELP_ogMakeDir} "{path} {os.path.dirname (path)}".')
|
|
FileLib.ogMakeDir ('CACHE', os.path.dirname (f'/{path}'))
|
|
imgdir = ogGetParentPath ('CACHE', f'/{path}')
|
|
if not imgdir:
|
|
sys.exit (1)
|
|
|
|
t0 = time.time()
|
|
|
|
if 'TORRENT' == protocolo:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'ogCopyFile {repositorio} {path}.torrent absolute {ogGlobals.OGCAC}/{ogGlobals.OGIMG}')
|
|
mac_digits = NetLib.ogGetMacAddress().split (':')
|
|
timewait = int ('0x' + mac_digits[4] + mac_digits[5], 16) * 120 / 65535
|
|
if not SystemLib.ogExecAndLog ('command', FileLib.ogCopyFile, {'container':repositorio, 'file':f'{path}.torrent'}, {'file':imgdir}):
|
|
sys.exit (1)
|
|
p2pwait = random.randint (1, 121)
|
|
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TASK_SLEEP} : {p2pwait} seconds')
|
|
time.sleep (p2pwait)
|
|
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TASK_START}: ogTorrentStart CACHE {path}.torrent {optprotocolo}')
|
|
SystemLib.ogExecAndLog ('command', ProtocolLib.ogTorrentStart, 'CACHE', f'{path}.torrent', optprotocolo)
|
|
resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '--before-context', '1', 'Download', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout
|
|
resumeupdatecachebf = subprocess.run (['grep', '--max-count', '1', 'Download', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout
|
|
if 'Download complete.' == resumeupdatecachebf:
|
|
os.unlink (imgdir + path + '.torrent.bf')
|
|
elif 'MULTICAST' == protocolo:
|
|
SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION}: {repoip}:{port}')
|
|
time.sleep (random.randint (1, 31))
|
|
|
|
SystemLib.ogEcho (['log', 'session'], None, f'ogMcastRequest {path} {optprotocolo}')
|
|
if not SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastRequest, path, optprotocolo):
|
|
sys.exit (1)
|
|
|
|
SystemLib.ogEcho (['log', 'session'], None, f'ogMcastReceiverFile {port} CACHE {path}')
|
|
if not SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastReceiverFile, sess=port, container='CACHE', file=path):
|
|
sys.exit (1)
|
|
|
|
resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '--before-context', '1', 'Transfer complete', f'{ogGlobals.OGLOGCOMMAND}.tmp'], capture_output=True, text=True).stdout
|
|
|
|
elif 'UNICAST' == protocolo:
|
|
print (f'ogExecAndLog ("command", FileLib.ogCopyFile, {{"container":{repositorio}, "file":{path}}}, {{"file":{imgdir}}})')
|
|
SystemLib.ogExecAndLog ('command', FileLib.ogCopyFile, {'container':repositorio, 'file':path}, {'file':imgdir})
|
|
time.sleep (5)
|
|
resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '100%', f'{ogGlobals.OGLOGCOMMAND}.tmp'], capture_output=True, text=True).stdout
|
|
|
|
elif 'RSYNC' == protocolo:
|
|
raise Exception ('synchronised images are no longer supported')
|
|
|
|
t = time.time() - t0
|
|
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {resumeupdatecache} ')
|
|
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} updateCache {int (t/60)}m {int (t%60)}s')
|
|
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TASK_START} {ogGlobals.lang.MSG_HELP_ogCalculateChecksum} ')
|
|
t0 = time.time()
|
|
# Si es imagen sincronizada siempre da distinto md5. No podemos comprobar
|
|
rc = ProtocolLib.ogUpdateCacheIsNecesary (repositorio, path, protocolo)
|
|
if 'deployImage' != SystemLib.ogGetCaller():
|
|
t = time.time() - t0
|
|
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} {ogGlobals.lang.MSG_HELP_ogCalculateChecksum} {int (t/60)}m {int (t%60)}s')
|
|
|
|
# si rc todavia es True: exit error; si rc=False: todo bien (exit 0); si rc=None: exit error
|
|
if rc == True: sys.exit (ogGlobals.OG_ERR_UPDATECACHE)
|
|
elif rc == False: sys.exit (0)
|
|
elif rc == None: sys.exit (ogGlobals.OG_ERR_UPDATECACHE)
|