#!/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. ## nati: esto ya lo hicimos mas arriba... 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)