1
0
Fork 0

Compare commits

..

1 Commits

Author SHA1 Message Date
Nicolas Arenas 3c2a3b3846 Publish in nightlys 2025-04-10 16:21:59 +02:00
13 changed files with 52 additions and 138 deletions

View File

@ -5,54 +5,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.8.0] - 2025-04-23
### Added
- Have the oglive agent send /stopped on poweroff or restart
## [0.7.2] - 2025-04-21
### Fixed
- Have the partitioning functions return a meaningful rc
## [0.7.1] - 2025-04-15
### Fixed
- getConfiguration.py: don't fail if NTFS filesystems are mounted ro
## [0.7.0] - 2025-04-15
### Removed
- Removed references to ogGlobals.OGLOG in python code
## [0.6.1] - 2025-04-15
### Fixed
- Fixed capturing of partclone output and management of return value
## [0.6.0] - 2025-04-15
### Changed
- ogGetIpAddress() is no longer required in ogGlobals--move it back into NetLib
## [0.5.0] - 2025-04-15
### Changed
- Log to /var/log/clone-engine.log and clone-engine.json.log
## [0.4.1] - 2025-04-10
### Fixed
- restoreImage.py: return negated rc to the shell
## [0.4.0] - 2025-04-10 ## [0.4.0] - 2025-04-10
### Changed ### Changed

View File

@ -2,9 +2,6 @@
import os import os
import sys import sys
import time
os.system ('pkill -f OGAgent')
time.sleep (3)
os.system ('poweroff') os.system ('poweroff')
sys.exit (0) sys.exit (0)

View File

@ -2,9 +2,6 @@
import os import os
import sys import sys
import time
os.system ('pkill -f OGAgent')
time.sleep (3)
os.system ('reboot') os.system ('reboot')
sys.exit (0) sys.exit (0)

View File

@ -74,5 +74,4 @@ else:
# Borramos marcas de arranque de Windows # Borramos marcas de arranque de Windows
for f in glob.glob ('/mnt/*/ogboot.*') + glob.glob ('/mnt/*/*/ogboot.*'): for f in glob.glob ('/mnt/*/ogboot.*') + glob.glob ('/mnt/*/*/ogboot.*'):
try: os.unlink (f) os.unlink (f)
except: pass

View File

@ -179,7 +179,7 @@ def ogCreatePartitions (disk, parts):
p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True)
subprocess.run (['partprobe', DISK]) subprocess.run (['partprobe', DISK])
if CACHESIZE: CacheLib.ogMountCache() if CACHESIZE: CacheLib.ogMountCache()
return not p.returncode return True
#/** #/**
@ -285,7 +285,7 @@ def ogCreateGptPartitions (disk, parts):
p = subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK], capture_output=True, text=True) p = subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK], capture_output=True, text=True)
subprocess.run (['partprobe', DISK]) subprocess.run (['partprobe', DISK])
if CACHESIZE: CacheLib.ogMountCache() if CACHESIZE: CacheLib.ogMountCache()
return not p.returncode return True
#/** #/**

View File

@ -512,8 +512,6 @@ def ogRestoreImage (repo, imgpath, disk, par):
rc = None rc = None
try: try:
p = subprocess.run (program, shell=True, capture_output=True, text=True) p = subprocess.run (program, shell=True, capture_output=True, text=True)
print (p.stdout)
print (p.stderr)
rc = p.returncode rc = p.returncode
if not rc: if not rc:
SystemLib.ogRaiseError ([], ogGlobalsOG_ERR_IMAGE, f'{imgfile}, {disk}, {par}') SystemLib.ogRaiseError ([], ogGlobalsOG_ERR_IMAGE, f'{imgfile}, {disk}, {par}')

View File

@ -142,29 +142,7 @@ def ogGetHostname():
#@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf #@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf
#*/ ## #*/ ##
def ogGetIpAddress(): def ogGetIpAddress():
if "IPV4ADDR" in os.environ: return ogGlobals.ogGetIpAddress()
ip = os.environ["IPV4ADDR"]
if '/' in ip: ip = ip.split ('/')[0]
return ip
extra_args = []
if "DEVICE" in os.environ:
extra_args = [ "dev", os.environ["DEVICE"] ]
ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'] + extra_args, capture_output=True, text=True).stdout
ipasj = json.loads (ipas)
addresses = []
for e in ipasj:
if 'lo' == e['ifname']: continue
if 'addr_info' not in e: continue
addrs = e['addr_info']
for a in addrs:
if 'inet' != a['family']: continue
addresses.append ({ 'local': a['local'], 'prefixlen': a['prefixlen'] })
if 1 != len (addresses):
raise Exception ('more than one local IP address found')
return addresses[0]
#/** #/**

View File

@ -3,7 +3,6 @@ import datetime
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
import sys import sys
import os import os
import json
import shutil import shutil
import inspect import inspect
import glob import glob
@ -21,7 +20,6 @@ import StringLib
def _logtype2logfile (t): def _logtype2logfile (t):
if 'log' == t.lower(): return ogGlobals.OGLOGFILE if 'log' == t.lower(): return ogGlobals.OGLOGFILE
if 'jsonlog' == t.lower(): return ogGlobals.OGJSONLOGFILE
elif 'command' == t.lower(): return ogGlobals.OGLOGCOMMAND elif 'command' == t.lower(): return ogGlobals.OGLOGCOMMAND
elif 'session' == t.lower(): return ogGlobals.OGLOGSESSION elif 'session' == t.lower(): return ogGlobals.OGLOGSESSION
else: raise Exception (f'unknown log type ({t})') else: raise Exception (f'unknown log type ({t})')
@ -37,40 +35,24 @@ def ogEcho (logtypes, loglevel, msg):
logfiles = ['/dev/stdout'] logfiles = ['/dev/stdout']
if type (logtypes) is list: if type (logtypes) is list:
for l in logtypes: for l in logtypes:
if 'log' == l: logfiles.append (_logtype2logfile (l))
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (l))
else: ## string else: ## string
if 'log' == logtypes: logfiles.append (_logtype2logfile (logtypes))
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (logtypes))
if loglevel is None or 'help' == loglevel: if loglevel is None or 'help' == loglevel:
if ogGlobals.DEBUG.lower() != "no": if ogGlobals.DEBUG.lower() != "no":
logfiles.append (ogGlobals.OGLOGFILE) logfiles.append (ogGlobals.OGLOGFILE)
logfiles.append (ogGlobals.OGJSONLOGFILE)
for f in logfiles: for f in logfiles:
with open (f, 'a') as fd: with open (f, 'a') as fd:
if ogGlobals.OGJSONLOGFILE == f: fd.write (msg + '\n')
fd.write (json.dumps ({'message':msg}) + '\n')
else:
fd.write (msg + '\n')
return return
if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel: if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel:
DATETIME = datetime.datetime.now (ZoneInfo (ogGlobals.TZ)).strftime ('%F %T %Z') DATETIME = datetime.datetime.now(ZoneInfo(ogGlobals.TZ)).strftime("%F %T %Z")
DATETIME_json = datetime.datetime.now (ZoneInfo (ogGlobals.TZ)).strftime ('%Y-%m-%d %H:%M:%S')
for f in logfiles: for f in logfiles:
with open (f, 'a') as fd: with open (f, 'a') as fd:
if ogGlobals.OGJSONLOGFILE == f: fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n")
fd.write (json.dumps ({'timestamp':DATETIME_json, 'severity':loglevel, 'message':msg}) + '\n')
else:
fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n")
else: else:
raise Exception (f'unknown loglevel ({loglevel})') raise Exception (f'unknown loglevel ({loglevel})')
@ -93,18 +75,10 @@ def ogExecAndLog (logtypes, fun, *args, **kwargs):
if type (logtypes) is list: if type (logtypes) is list:
for l in logtypes: for l in logtypes:
logtypes = list (map (lambda x: x.lower(), logtypes)) logtypes = list (map (lambda x: x.lower(), logtypes))
if 'log' == l: logfiles.append (_logtype2logfile (l))
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (l))
else: ## string else: ## string
logtypes = logtypes.lower() logtypes = logtypes.lower()
if 'log' == logtypes: logfiles.append (_logtype2logfile (logtypes))
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (logtypes))
if not fun: if not fun:
ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'no function provided') ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'no function provided')
@ -129,6 +103,7 @@ def ogExecAndLog (logtypes, fun, *args, **kwargs):
# ## redirect stdout only # ## redirect stdout only
# eval $COMMAND | tee -a $FILES # eval $COMMAND | tee -a $FILES
import time
sout = serr = '' sout = serr = ''
if 'command' in logtypes: if 'command' in logtypes:
os.unlink (ogGlobals.OGLOGCOMMAND) os.unlink (ogGlobals.OGLOGCOMMAND)
@ -146,19 +121,14 @@ def ogExecAndLog (logtypes, fun, *args, **kwargs):
if sout or serr or ('True' != rc_str and 'False' != rc_str and 'None' != rc_str): if sout or serr or ('True' != rc_str and 'False' != rc_str and 'None' != rc_str):
for f in logfiles: for f in logfiles:
with open (f, 'a') as fd: with open (f, 'a') as fd:
if ogGlobals.OGJSONLOGFILE == f: if sout: fd.write (f'{sout}\n')
if sout: fd.write (json.dumps ({'message':sout}) + '\n') if serr: fd.write (f'{serr}\n')
if serr: fd.write (json.dumps ({'message':serr}) + '\n') if rc_str: fd.write (f'{rc_str}\n')
if rc_str: fd.write (json.dumps ({'message':rc_str}) + '\n') #fd.write (f"ogExecAndLog: {fun.__name__} rc:\n{rc_str}\n")
else: #if sout: fd.write (f"ogExecAndLog: {fun.__name__} stdout:\n{sout}\n")
if sout: fd.write (f'{sout}\n') #else: fd.write (f"ogExecAndLog: {fun.__name__} stdout: (none)\n")
if serr: fd.write (f'{serr}\n') #if serr: fd.write (f"ogExecAndLog: {fun.__name__} stderr:\n{serr}\n")
if rc_str: fd.write (f'{rc_str}\n') #else: fd.write (f"ogExecAndLog: {fun.__name__} stderr: (none)\n")
#fd.write (f"ogExecAndLog: {fun.__name__} rc:\n{rc_str}\n")
#if sout: fd.write (f"ogExecAndLog: {fun.__name__} stdout:\n{sout}\n")
#else: fd.write (f"ogExecAndLog: {fun.__name__} stdout: (none)\n")
#if serr: fd.write (f"ogExecAndLog: {fun.__name__} stderr:\n{serr}\n")
#else: fd.write (f"ogExecAndLog: {fun.__name__} stderr: (none)\n")
return rc return rc

View File

@ -6,6 +6,33 @@ import os.path
import locale import locale
import importlib.util import importlib.util
## required for defining OGLOGFILE
def ogGetIpAddress():
if "IPV4ADDR" in os.environ:
ip = os.environ["IPV4ADDR"]
if '/' in ip: ip = ip.split ('/')[0]
return ip
extra_args = []
if "DEVICE" in os.environ:
extra_args = [ "dev", os.environ["DEVICE"] ]
ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'] + extra_args, capture_output=True, text=True).stdout
ipasj = json.loads (ipas)
addresses = []
for e in ipasj:
if 'lo' == e['ifname']: continue
if 'addr_info' not in e: continue
addrs = e['addr_info']
for a in addrs:
if 'inet' != a['family']: continue
addresses.append ({ 'local': a['local'], 'prefixlen': a['prefixlen'] })
if 1 != len (addresses):
raise Exception ('more than one local IP address found')
return addresses[0]
ip = ogGetIpAddress()
def load_lang (name): def load_lang (name):
global lang global lang
if name in sys.modules: if name in sys.modules:
@ -61,8 +88,8 @@ OGPYFUNCS = os.path.join (OPENGNSYS, 'functions')
OGSCRIPTS = os.path.join (OPENGNSYS, 'scripts') OGSCRIPTS = os.path.join (OPENGNSYS, 'scripts')
OGIMG = os.path.join (OPENGNSYS, 'images') OGIMG = os.path.join (OPENGNSYS, 'images')
OGCAC = os.path.join (OPENGNSYS, 'cache') OGCAC = os.path.join (OPENGNSYS, 'cache')
OGLOGFILE = '/var/log/clone-engine.log' OGLOG = os.path.join (OPENGNSYS, 'log')
OGJSONLOGFILE = '/var/log/clone-engine.json.log' OGLOGFILE = f'{OGLOG}/{ip}.log'
DEBUG = 'yes' DEBUG = 'yes'
_path = os.environ['PATH'] + ':/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin:/opt/oglive/rootfs/opt/drbl/sbin' _path = os.environ['PATH'] + ':/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin:/opt/oglive/rootfs/opt/drbl/sbin'
os.environ['PATH'] = ':'.join ([OGSCRIPTS, _path, OGAPI, OGBIN]) os.environ['PATH'] = ':'.join ([OGSCRIPTS, _path, OGAPI, OGBIN])

View File

@ -145,10 +145,6 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''):
SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImage {params}') SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImage {params}')
retval = subprocess.run (['restoreImage.py'] + params).returncode retval = subprocess.run (['restoreImage.py'] + params).returncode
## turn shell's success into python success (without ending up with True or False)
if retval: retval = 0
else: retval = 1
# Mostrar resultados. # Mostrar resultados.
resumerestoreimage = subprocess.run (['grep', '--max-count', '1', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout resumerestoreimage = subprocess.run (['grep', '--max-count', '1', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {resumerestoreimage} ') SystemLib.ogEcho (['log', 'session'], None, f' [ ] {resumerestoreimage} ')

View File

@ -21,7 +21,7 @@ if len (sys.argv) > 1:
#SERVERLOGDIR = unused #SERVERLOGDIR = unused
# Fichero de listado: hard-IP # Fichero de listado: hard-IP
HARDFILE = f'/tmp/hard-{ogGetIpAddress()}' HARDFILE = f'{ogGlobals.OGLOG}/hard-{ogGetIpAddress()}'
out = ogListHardwareInfo() out = ogListHardwareInfo()
with open (HARDFILE, 'w') as fd: with open (HARDFILE, 'w') as fd:
fd.write (out) fd.write (out)

View File

@ -18,7 +18,7 @@ prog = os.path.basename (sys.argv[0])
def main (disk, par, reduced): def main (disk, par, reduced):
ip = NetLib.ogGetIpAddress() ip = NetLib.ogGetIpAddress()
softfile = f'/tmp/soft-{ip}-{disk}-{par}' softfile = f'{ogGlobals.OGLOG}/soft-{ip}-{disk}-{par}'
software_list = InventoryLib.ogListSoftware (disk, par) software_list = InventoryLib.ogListSoftware (disk, par)
if reduced: if reduced:

View File

@ -114,5 +114,5 @@ t = time.time() - t0
SystemLib.ogEcho (['log', 'session'], None, f'[100] Duracion de la operacion {int (t/60)}m {int (t%60)}s') SystemLib.ogEcho (['log', 'session'], None, f'[100] Duracion de la operacion {int (t/60)}m {int (t%60)}s')
# Código de salida del comando prinicpal de restauración. # Código de salida del comando prinicpal de restauración.
sys.exit (not retval) ## negated for the shell sys.exit (retval)