Compare commits
57 Commits
Author | SHA1 | Date |
---|---|---|
|
5541e39b5f | |
|
4f0543fe79 | |
|
a5eacbe203 | |
|
a34c98eb4c | |
|
c55a75f5ce | |
|
1bf1283aff | |
|
d5279eba42 | |
|
87fb51ed2a | |
|
c9c9e98359 | |
|
62ed2e3dde | |
|
7cefe8ff43 | |
|
9fc48067e6 | |
|
13b262d8f7 | |
|
e43e8baea1 | |
|
d619cb005d | |
|
6d5dea6657 | |
|
d5fe20d291 | |
|
c7081b3921 | |
|
6c543660f9 | |
|
594314161e | |
|
7c326e7114 | |
|
944390806b | |
|
461c5faed5 | |
|
a9a2d19653 | |
|
e80ed538b8 | |
|
857ebbd267 | |
|
03f8203598 | |
|
3fd94ecb8f | |
|
d2ef8a98f2 | |
|
8af4627e28 | |
|
b64b6d79b3 | |
|
efc22c1bcd | |
|
36bf1539d6 | |
|
f2c4371e1e | |
|
39b947e598 | |
|
0a26ebd946 | |
|
4061f85704 | |
|
928dedfeeb | |
|
357c94e9ea | |
|
df7d8d96cb | |
|
4df8caa203 | |
|
fa8e94e688 | |
|
65a3b862f7 | |
|
05279ba7c5 | |
|
15a238c206 | |
|
93e349105a | |
|
d733d04b69 | |
|
e83e0e6e16 | |
|
972c2a7c8c | |
|
def329436d | |
|
29cc09105e | |
|
64c5eeae6e | |
|
1050133d59 | |
|
d76390a7b9 | |
|
afe190c47d | |
|
9d1224e0c8 | |
|
02b6708442 |
155
CHANGELOG.md
155
CHANGELOG.md
|
@ -5,6 +5,161 @@ 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/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.20.2] - 2025-06-24
|
||||
|
||||
### Changed
|
||||
|
||||
- Do a couple of ogExecAndLog()s also when creating images
|
||||
|
||||
## [0.20.1] - 2025-06-24
|
||||
|
||||
### Changed
|
||||
|
||||
- Fix mark for ogboot on linux
|
||||
|
||||
## [0.20.0] - 2025-06-24
|
||||
|
||||
### Changed
|
||||
|
||||
- In order to have /tmp/command.log updated in realtime, ogExecAndLog now spawns a subprocess rather than calling functions directly
|
||||
|
||||
## [0.19.2] - 2025-06-24
|
||||
|
||||
### Changed
|
||||
|
||||
- Write a mark for ogboot on linux only
|
||||
|
||||
## [0.19.1] - 2025-06-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed path of EFI boot entry
|
||||
|
||||
## [0.19.0] - 2025-06-23
|
||||
|
||||
### Changed
|
||||
|
||||
- Write a mark for ogboot
|
||||
|
||||
## [0.18.2] - 2025-06-19
|
||||
|
||||
### Fixed
|
||||
|
||||
- Accept None as partition type
|
||||
|
||||
## [0.18.1] - 2025-06-18
|
||||
|
||||
### Fixed
|
||||
|
||||
- Look for grub.cfg in two places rather than one
|
||||
|
||||
## [0.18.0] - 2025-06-16
|
||||
|
||||
### Added
|
||||
|
||||
- Added scripts and libs for oggit
|
||||
|
||||
## [0.17.0] - 2025-06-16
|
||||
|
||||
### Changed
|
||||
|
||||
- Removed useless warning about /dev/loop0
|
||||
- Fix windows EFI booting, and a typo
|
||||
|
||||
## [0.16.0] - 2025-06-12
|
||||
|
||||
### Changed
|
||||
|
||||
- Gave some care to the "Custom" scripts
|
||||
|
||||
## [0.15.3] - 2025-06-12
|
||||
|
||||
### Fixed
|
||||
|
||||
- Create missing dir
|
||||
|
||||
## [0.15.2] - 2025-06-11
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed a condition check
|
||||
|
||||
## [0.15.1] - 2025-06-11
|
||||
|
||||
### Fixed
|
||||
|
||||
- Add a missing "import"
|
||||
- Fix retrieving windows version from the registry
|
||||
- Fix bug while building the "Part-01-01" string
|
||||
- Removed obsolete unused "bootOS" scripts (with a capital "S")
|
||||
|
||||
## [0.15.0] - 2025-06-10
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove opengnsys bash functions from the agent's environment
|
||||
|
||||
## [0.14.2] - 2025-06-09
|
||||
|
||||
### Fixed
|
||||
|
||||
- Get rc of bash pipelines in ProtocolLib
|
||||
|
||||
## [0.14.1] - 2025-06-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed rc management in deployImage.py
|
||||
|
||||
## [0.14.0] - 2025-06-07
|
||||
|
||||
### Changed
|
||||
|
||||
- Read $ogusetls and $ogverifytls from the environment and configure stunnel accordingly
|
||||
|
||||
## [0.13.9] - 2025-06-04
|
||||
|
||||
### Fixed
|
||||
|
||||
- Copy grub.cfg so that grub finds the config upon boot
|
||||
|
||||
## [0.13.8] - 2025-06-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Paid attention to return codes between python (True for success) and shell (0 for success)
|
||||
|
||||
## [0.13.7] - 2025-06-02
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed management of the "multicast session" parameter
|
||||
|
||||
## [0.13.6] - 2025-06-02
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed variable name in restoreImage.py
|
||||
|
||||
## [0.13.5] - 2025-05-30
|
||||
|
||||
### Fixed
|
||||
|
||||
- Return a true value from the unicast/multicast methods
|
||||
- Fully qualify a method call
|
||||
|
||||
## [0.13.4] - 2025-05-28
|
||||
|
||||
### Changed
|
||||
|
||||
- Show sgdisk output
|
||||
|
||||
## [0.13.3] - 2025-05-28
|
||||
|
||||
### Fixed
|
||||
|
||||
- unlink() only existing files
|
||||
|
||||
## [0.13.2] - 2025-05-28
|
||||
|
||||
### Changed
|
||||
|
|
|
@ -26,7 +26,12 @@ if [ -f "/usr/share/OGAgent/opengnsys/linux/OGAgentService.py" -a "$ogstatus" !=
|
|||
export OGAGENTCFG_URLMENU_SCHEME=http
|
||||
export OGAGENTCFG_URLMENU_IP=127.0.0.1
|
||||
export OGAGENTCFG_URLMENU_PORT=81
|
||||
python3 -m opengnsys.linux.OGAgentService fg
|
||||
(
|
||||
## remove bash functions and some OG vars from the agent's environment
|
||||
unset -f $(declare -F |awk '/og[A-Z]|NT[A-Z]/ { print $3 }')
|
||||
unset $(declare |awk -F= '/^MSG_|^OG_ERR_/ { print $1 }')
|
||||
python3 -m opengnsys.linux.OGAgentService fg
|
||||
)
|
||||
else
|
||||
for FILE in index $OGGROUP $(ogGetIpAddress)
|
||||
do
|
||||
|
|
|
@ -13,12 +13,49 @@ ogIsEfiActive && mount -t efivarfs none /sys/firmware/efi/efivars
|
|||
# Lanzar servicios complementarios del cliente.
|
||||
echo "${MSG_OTHERSERVICES:-.}"
|
||||
|
||||
# Iniciar stunnel
|
||||
if [ -e /etc/stunnel/menu.conf ]; then
|
||||
sed -i -e "s/__OGCORE_IP__/$ogcore/; s/__OGCORE_PORT__/8443/" /etc/stunnel/menu.conf
|
||||
mkdir -p /var/run/stunnel4; chown stunnel4:stunnel4 /var/run/stunnel4
|
||||
stunnel /etc/stunnel/menu.conf &>/var/log/stunnel4/menu.log &
|
||||
# stunnel start
|
||||
cat >/etc/stunnel/menu.conf <<__EOF__
|
||||
setuid = stunnel4
|
||||
setgid = stunnel4
|
||||
pid = /var/run/stunnel4/menu.pid
|
||||
foreground = yes
|
||||
debug = info
|
||||
|
||||
[menu]
|
||||
client = yes
|
||||
accept = 127.0.0.1:81
|
||||
connect = $ogcore:8443
|
||||
__EOF__
|
||||
if [[ true == "$ogusetls" ]]; then
|
||||
if [[ true == "$ogverifytls" ]]; then
|
||||
## use tls and verify
|
||||
cat >>/etc/stunnel/menu.conf <<__EOF__
|
||||
cert = /opt/opengnsys/etc/ogagent.crt
|
||||
key = /opt/opengnsys/etc/ogagent.key
|
||||
CAfile = /opt/opengnsys/etc/ca.crt
|
||||
requireCert = yes
|
||||
verifyChain = yes
|
||||
__EOF__
|
||||
else
|
||||
## use tls but not verify
|
||||
cat >>/etc/stunnel/menu.conf <<__EOF__
|
||||
cert = /opt/opengnsys/etc/ogagent.crt
|
||||
key = /opt/opengnsys/etc/ogagent.key
|
||||
CAfile = /opt/opengnsys/etc/ca.crt
|
||||
requireCert = no
|
||||
verifyChain = no
|
||||
__EOF__
|
||||
fi
|
||||
else
|
||||
## don't use tls
|
||||
cat >>/etc/stunnel/menu.conf <<__EOF__
|
||||
requireCert = no
|
||||
verifyChain = no
|
||||
__EOF__
|
||||
fi
|
||||
mkdir -p /var/run/stunnel4; chown stunnel4:stunnel4 /var/run/stunnel4
|
||||
stunnel /etc/stunnel/menu.conf &>/var/log/stunnel4/menu.log &
|
||||
# stunnel end
|
||||
|
||||
# Iniciar dbus
|
||||
if [ -e /etc/dbus-1/system.d/ogbrowser.conf ]; then
|
||||
|
|
|
@ -19,6 +19,7 @@ if 5 == len (sys.argv):
|
|||
args = parser.parse_args()
|
||||
src = { 'container': args.src_container, 'file': args.src_file }
|
||||
dst = { 'container': args.dst_container, 'file': args.dst_file }
|
||||
|
||||
elif 7 == len (sys.argv):
|
||||
parser.add_argument ('src_disk')
|
||||
parser.add_argument ('src_par')
|
||||
|
@ -29,6 +30,31 @@ elif 7 == len (sys.argv):
|
|||
args = parser.parse_args()
|
||||
src = { 'disk': args.src_disk, 'par': args.src_par, 'file': args.src_file }
|
||||
dst = { 'disk': args.dst_disk, 'par': args.dst_par, 'file': args.dst_file }
|
||||
|
||||
elif 4 == len (sys.argv):
|
||||
## can be either:
|
||||
## - src_container src_file dst_file
|
||||
## - src_file dst_container dst_file
|
||||
if 'REPO' == sys.argv[1] or 'CACHE' == sys.argv[1]:
|
||||
## we are in "src_container src_file dst_file"
|
||||
parser.add_argument ('src_container')
|
||||
parser.add_argument ('src_file')
|
||||
parser.add_argument ('dst_file')
|
||||
args = parser.parse_args()
|
||||
src = { 'container': args.src_container, 'file': args.src_file }
|
||||
dst = { 'file': args.dst_file }
|
||||
elif 'REPO' == sys.argv[2] or 'CACHE' == sys.argv[2]:
|
||||
## we are in "src_file dst_container dst_file"
|
||||
parser.add_argument ('src_file')
|
||||
parser.add_argument ('dst_container')
|
||||
parser.add_argument ('dst_file')
|
||||
args = parser.parse_args()
|
||||
src = { 'file': args.src_file }
|
||||
dst = { 'container': args.dst_container, 'file': args.dst_file }
|
||||
else:
|
||||
ogHelp ('ogCopyFile', 'ogCopyFile [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target', ['ogCopyFile REPO newfile.txt 1 2 /tmp/newfile.txt'])
|
||||
sys.exit (1)
|
||||
|
||||
elif 6 == len (sys.argv):
|
||||
## can be either:
|
||||
## - src_disk src_par src_file dst_container dst_file
|
||||
|
@ -36,7 +62,7 @@ elif 6 == len (sys.argv):
|
|||
|
||||
try:
|
||||
num = int (sys.argv[1]) ## raises ValueError if sys.argv[1] doesn't look like a number
|
||||
## "src_disk src_par src_file dst_container dst_file"
|
||||
## we are in "src_disk src_par src_file dst_container dst_file"
|
||||
parser.add_argument ('src_disk')
|
||||
parser.add_argument ('src_par')
|
||||
parser.add_argument ('src_file')
|
||||
|
@ -46,7 +72,7 @@ elif 6 == len (sys.argv):
|
|||
src = { 'disk': args.src_disk, 'par': args.src_par, 'file': args.src_file }
|
||||
dst = { 'container': args.dst_container, 'file': args.dst_file }
|
||||
except:
|
||||
## "src_container src_file dst_disk dst_par dst_file"
|
||||
## we are in "src_container src_file dst_disk dst_par dst_file"
|
||||
parser.add_argument ('src_container')
|
||||
parser.add_argument ('src_file')
|
||||
parser.add_argument ('dst_disk')
|
||||
|
|
|
@ -143,15 +143,15 @@ cur_ptt = DiskLib.ogGetPartitionTableType (dis)
|
|||
ptt = 'GPT' if InventoryLib.ogIsEfiActive() else 'MSDOS'
|
||||
if not cur_ptt or ptt != cur_ptt:
|
||||
DiskLib.ogDeletePartitionTable (dis)
|
||||
SystemLib.ogExecAndLog ('command', DiskLib.ogUpdatePartitionTable)
|
||||
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable'])
|
||||
DiskLib.ogCreatePartitionTable (dis, ptt)
|
||||
|
||||
# Inicia la cache.
|
||||
if 'CACHE' in sparam:
|
||||
SystemLib.ogEcho (['session', 'log'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogCreateCache}')
|
||||
SystemLib.ogEcho (['session', 'log'], None, f' initCache {tch}')
|
||||
rc = SystemLib.ogExecAndLog ('command', CacheLib.initCache, tch)
|
||||
if rc:
|
||||
rc = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGSCRIPTS}/initCache', tch])
|
||||
if not rc:
|
||||
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'initCache failed')
|
||||
coproc.kill()
|
||||
sys.exit (1)
|
||||
|
@ -159,12 +159,12 @@ if 'CACHE' in sparam:
|
|||
# Definir particionado.
|
||||
SystemLib.ogEcho (['session', 'log'], None, f'[50] {ogGlobals.lang.MSG_HELP_ogCreatePartitions}')
|
||||
SystemLib.ogEcho (['session', 'log'], None, f' ogCreatePartitions {dis} {' '.join (tbp)}')
|
||||
res = SystemLib.ogExecAndLog ('command', DiskLib.ogCreatePartitions, dis, tbp)
|
||||
res = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCreatePartitions', dis] + tbp)
|
||||
if not res:
|
||||
coproc.kill()
|
||||
SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_GENERIC, f'ogCreatePartitions {dis} {' '.join (tbp)}')
|
||||
sys.exit (1)
|
||||
SystemLib.ogExecAndLog ('command', DiskLib.ogUpdatePartitionTable)
|
||||
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable'])
|
||||
|
||||
# Formatear particiones
|
||||
SystemLib.ogEcho (['session', 'log'], None, f'[70] {ogGlobals.lang.MSG_HELP_ogFormat}')
|
||||
|
@ -174,10 +174,10 @@ for p in range (1, maxp+1):
|
|||
if 'CACHE' == tbf[p]:
|
||||
if CACHESIZE == tch: # Si el tamaño es distinto ya se ha formateado.
|
||||
SystemLib.ogEcho (['session', 'log'], None, ' ogFormatCache')
|
||||
retval = SystemLib.ogExecAndLog ('command', CacheLib.ogFormatCache)
|
||||
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatCache'])
|
||||
else:
|
||||
SystemLib.ogEcho (['session', 'log'], None, f' ogFormatFs {dis} {p} {tbf[p]}')
|
||||
retval = SystemLib.ogExecAndLog ('command', FileSystemLib.ogFormatFs, dis, str(p), tbf[p])
|
||||
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatFs', dis, str(p), tbf[p]])
|
||||
if retval:
|
||||
coproc.kill()
|
||||
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_GENERIC, f'ogFormatFs {dis} {p} {tbf[p]}')
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
sys.path.insert(0, "/opt/oglive/rootfs/opt/opengnsys/lib/python3/")
|
||||
sys.path.insert(0, "/opt/opengnsys/interfaceAdm/git/")
|
||||
sys.path.insert(0, "/opt/opengnsys/ogrepository/oggit/lib/")
|
||||
|
||||
import NetLib
|
||||
import ogGlobals
|
||||
import SystemLib
|
||||
|
||||
|
||||
from gitlib import OpengnsysGitLibrary, NTFSImplementation
|
||||
|
||||
|
||||
def create_image(disk_num, partition_num, repo, image_name):
|
||||
|
||||
ntfs_impl = NTFSImplementation.NTFS3G
|
||||
og_git = OpengnsysGitLibrary(ntfs_implementation = ntfs_impl)
|
||||
device = og_git._runBashFunction("ogDiskToDev", [str(disk_num), str(partition_num)])
|
||||
og_git.initRepo(device, image_name)
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 6:
|
||||
sys.exit(SystemLib.ogRaiseError(OG_ERR_FORMAT, "Incorrect number of arguments"))
|
||||
|
||||
disk_num, partition_num, image_name, repo, tag = sys.argv[1:6]
|
||||
|
||||
retval = create_image(disk_num, partition_num, repo, image_name)
|
||||
|
||||
sys.exit(retval)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
sys.path.insert(0, "/opt/oglive/rootfs/opt/opengnsys/lib/python3/")
|
||||
sys.path.insert(0, "/opt/opengnsys/interfaceAdm/git/")
|
||||
sys.path.insert(0, "/opt/opengnsys/ogrepository/oggit/lib/")
|
||||
|
||||
import NetLib
|
||||
import ogGlobals
|
||||
import SystemLib
|
||||
from gitlib import OpengnsysGitLibrary, NTFSImplementation
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 4:
|
||||
print("Usage: python RestaurarImagenGit.py <disk> <partition> <repo> <boot_device>")
|
||||
sys.exit(1)
|
||||
|
||||
disk = sys.argv[1]
|
||||
partition = sys.argv[2]
|
||||
repo = sys.argv[3]
|
||||
boot_device = sys.argv[4]
|
||||
|
||||
ntfs_impl = NTFSImplementation.NTFS3G
|
||||
og_git = OpengnsysGitLibrary(ntfs_implementation = ntfs_impl)
|
||||
|
||||
device = og_git._runBashFunction("ogDiskToDev", [str(disk), str(partition)])
|
||||
|
||||
og_git.cloneRepo(repo, device, boot_device)
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ def ogBoot (disk, par, nvramperm=False, params=''):
|
|||
bootloader = 'shimx64.efi'
|
||||
# Obtener parcición EFI.
|
||||
esp = DiskLib.ogGetEsp()
|
||||
#efidisk, efipart = esp.split()
|
||||
efidisk, efipart = esp.split()
|
||||
# TODO: Comprobamos que existe la BOOTLABEL, si no buscamos por sistema operativo
|
||||
if '' == FileLib.ogGetPath (src=esp, file=f'EFI/{bootlabel}'):
|
||||
osversion = InventoryLib.ogGetOsVersion (disk, par)
|
||||
|
@ -126,6 +126,14 @@ def ogBoot (disk, par, nvramperm=False, params=''):
|
|||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{esp} Boot loader')
|
||||
return None
|
||||
|
||||
esp_dev = DiskLib.ogDiskToDev (efidisk, efipart)
|
||||
esp_mntdir = esp_dev.replace ('dev', 'mnt')
|
||||
os.makedirs (f'{esp_mntdir}/boot/grub', exist_ok=True)
|
||||
grub_cfg_src = f'{esp_mntdir}/EFI/{bootlabel}/Boot/grub.cfg'
|
||||
if not os.path.exists (grub_cfg_src):
|
||||
grub_cfg_src = f'{esp_mntdir}/boot/grubMBR/boot/grub/grub.cfg'
|
||||
shutil.copy2 (grub_cfg_src, f'{esp_mntdir}/boot/grub/grub.cfg')
|
||||
|
||||
# Crear orden de arranque (con unos valores por defecto).
|
||||
UEFILib.ogNvramAddEntry (bootlabel, f'/EFI/{bootlabel}/Boot/{bootloader}', nvramperm)
|
||||
# Marcar próximo arranque y reiniciar.
|
||||
|
@ -156,9 +164,17 @@ def ogBoot (disk, par, nvramperm=False, params=''):
|
|||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({type}, EFI)')
|
||||
return None
|
||||
|
||||
esp_dev = DiskLib.ogDiskToDev (efidisk, efipart)
|
||||
esp_mntdir = esp_dev.replace ('dev', 'mnt')
|
||||
os.makedirs (f'{esp_mntdir}/boot/grub', exist_ok=True)
|
||||
grub_cfg_src = f'{esp_mntdir}/EFI/{bootlabel}/Boot/grub.cfg'
|
||||
if not os.path.exists (grub_cfg_src):
|
||||
grub_cfg_src = f'{esp_mntdir}/boot/grubMBR/boot/grub/grub.cfg'
|
||||
shutil.copy2 (grub_cfg_src, f'{esp_mntdir}/boot/grub/grub.cfg')
|
||||
|
||||
# Crear orden de arranque (con unos valores por defecto).
|
||||
l = re.sub ('^.*EFI(.*)$', r'\1', loader)
|
||||
UEFILib.ogNvramAddEntry (bootlabel, l, nvramperm)
|
||||
UEFILib.ogNvramAddEntry (bootlabel, '/EFI'+l, nvramperm)
|
||||
# Marcar próximo arranque y reiniciar.
|
||||
UEFILib.ogNvramSetNext (bootlabel)
|
||||
subprocess.run (['reboot'])
|
||||
|
@ -437,7 +453,7 @@ def ogWindowsBootParameters (disk, par):
|
|||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'ESP: {bootdisk} {bootpar}')
|
||||
return
|
||||
bootdisk = str (int (bootdisk) - 1)
|
||||
bootlabel = f'Part-{int(bootdisk):02d}-{int(bootpar):02d}'
|
||||
bootlabel = f'Part-{int(disk):02d}-{int(par):02d}'
|
||||
bcdfile = f'boot_BCD_file=/EFI/{bootlabel}/Boot/BCD'
|
||||
else:
|
||||
bootdisk = disk0
|
||||
|
@ -449,9 +465,9 @@ def ogWindowsBootParameters (disk, par):
|
|||
winver = InventoryLib.ogGetOsVersion (disk, par)
|
||||
parts = re.split (':| ', winver)
|
||||
if 'Windows' == parts[0] and 'Server' == parts[2]:
|
||||
winver = parts[1] + parts[2] + parts[3]
|
||||
winver = parts[1] + ' ' + parts[2] + ' ' + parts[3]
|
||||
else:
|
||||
winver = parts[1] + parts[2]
|
||||
winver = parts[1] + ' ' + parts[2]
|
||||
if not winver:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'Windows')
|
||||
return
|
||||
|
@ -739,7 +755,7 @@ def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''):
|
|||
neworder = neworder[0:1] + [grubentry] + neworder[1:] ## la ponemos en segundo lugar
|
||||
UEFILib.ogNvramSetOrder (neworder)
|
||||
|
||||
return eval
|
||||
return not eval ## negate shell success code
|
||||
|
||||
|
||||
#/**
|
||||
|
@ -834,7 +850,7 @@ def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''):
|
|||
# Nombre OpenGnsys para cargador
|
||||
shutil.copy2 (f'{efisecondstage}/EFI/{efisubdir}/Boot/grubx64.efi', f'{efisecondstage}/EFI/{efisubdir}/Boot/ogloader.efi')
|
||||
|
||||
return eval
|
||||
return not eval ## negate shell success code
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0):
|
|||
get_ptt = DiskLib.ogGetPartitionTableType (ndsk)
|
||||
if 'GPT' == get_ptt:
|
||||
# Si la tabla de particiones no es valida, volver a generarla.
|
||||
if subprocess.run (['sgdisk', '-p', DISK], capture_output=True, text=True).returncode:
|
||||
if subprocess.run (['sgdisk', '-p', DISK], capture_output=True, text=True).returncode: ## if True, then sgdisk failed
|
||||
subprocess.run (['gdisk', DISK], input='2\nw\nY\n', capture_output=True, text=True)
|
||||
# Si existe la cache se borra previamente
|
||||
if ogFindCache(): ogDeleteCache()
|
||||
|
@ -96,7 +96,7 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0):
|
|||
subprocess.run (['sgdisk', DISK, f'-n{part}:{START}:{END}', f'-c{part}:CACHE', f'-t{part}:{ID}'])
|
||||
elif 'MSDOS' == get_ptt:
|
||||
# Si la tabla de particiones no es valida, volver a generarla.
|
||||
if subprocess.run (['parted', '-s', DISK, 'print']).returncode:
|
||||
if subprocess.run (['parted', '-s', DISK, 'print']).returncode: ## if True, then parted failed
|
||||
subprocess.run (['fdisk', DISK], input='w\n', text=True)
|
||||
# Definir particiones y notificar al kernel.
|
||||
ID = DiskLib.ogTypeToId ('CACHE', 'MSDOS')
|
||||
|
@ -139,12 +139,12 @@ def ogDeleteCache():
|
|||
ptt = DiskLib.ogGetPartitionTableType (ndisk)
|
||||
if 'GPT' == ptt:
|
||||
# Si la tabla de particiones no es valida, volver a generarla.
|
||||
if subprocess.run (['sgdisk', '-p', disk]).returncode:
|
||||
if subprocess.run (['sgdisk', '-p', disk]).returncode: ## if True, then sgdisk failed
|
||||
subprocess.run (['gdisk', disk], input='2\nw\nY\n', text=True)
|
||||
subprocess.run (['sgdisk', disk, f'-d{npart}'])
|
||||
elif 'MSDOS' == ptt:
|
||||
# Si la tabla de particiones no es valida, volver a generarla.
|
||||
if subprocess.run (['parted', '-s', disk, 'print']).returncode:
|
||||
if subprocess.run (['parted', '-s', disk, 'print']).returncode: ## if True, then parted failed
|
||||
subprocess.run (['fdisk', disk], input='w', text=True)
|
||||
# Eliminar la partición de caché.
|
||||
subprocess.run (['fdisk', disk], input=f'd\n{npart}\nw', text=True)
|
||||
|
@ -357,4 +357,4 @@ def ogUnmountCache():
|
|||
#*/ ##
|
||||
def initCache (*args):
|
||||
p = subprocess.run ([f'{ogGlobals.OGSCRIPTS}/initCache.py'] + list(args))
|
||||
return p.returncode
|
||||
return not p.returncode ## negate shell return code
|
||||
|
|
|
@ -76,7 +76,7 @@ def ogCreatePartitions (disk, parts):
|
|||
CACHEPART = CacheLib.ogFindCache()
|
||||
if CACHEPART:
|
||||
cache_disk, cache_part = CACHEPART.split()
|
||||
if ND == int (cache_disk):
|
||||
if int (ND) == int (cache_disk):
|
||||
CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2
|
||||
# Sector de inicio (la partición 1 empieza en el sector 63).
|
||||
IODISCO = ogDiskToDev (disk)
|
||||
|
@ -112,6 +112,7 @@ def ogCreatePartitions (disk, parts):
|
|||
|
||||
# Leer formato de cada parámetro - Tipo:Tamaño
|
||||
TYPE, SIZE = p.split (':')
|
||||
if TYPE is None or 'None' == TYPE: TYPE='EMPTY'
|
||||
try:
|
||||
SIZE = int (SIZE)
|
||||
except ValueError:
|
||||
|
@ -176,7 +177,7 @@ def ogCreatePartitions (disk, parts):
|
|||
ogCreatePartitionTable (ND)
|
||||
|
||||
# Definir particiones y notificar al kernel.
|
||||
p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True)
|
||||
p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, text=True)
|
||||
subprocess.run (['partprobe', DISK])
|
||||
if CACHESIZE: CacheLib.ogMountCache()
|
||||
return not p.returncode
|
||||
|
@ -283,6 +284,7 @@ def ogCreateGptPartitions (disk, parts):
|
|||
|
||||
# Definir particiones y notificar al kernel.
|
||||
p = subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK], capture_output=True, text=True)
|
||||
print (f'sgdisk rc ({p.returncode}) stdout ({p.stdout}) stderr ({p.stderr})')
|
||||
subprocess.run (['partprobe', DISK])
|
||||
if CACHESIZE: CacheLib.ogMountCache()
|
||||
return not p.returncode
|
||||
|
@ -391,7 +393,8 @@ def ogDevToDisk(arg_dev):
|
|||
DEV = arg_dev
|
||||
|
||||
if not os.path.exists(DEV):
|
||||
SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev)
|
||||
if '/dev/loop' != DEV[0:9]:
|
||||
SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev)
|
||||
return
|
||||
|
||||
# Error si no es fichero de bloques o directorio (para LVM).
|
||||
|
|
|
@ -215,8 +215,8 @@ def ogCopyFile (src, dst):
|
|||
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], capture_output=True, text=True)
|
||||
return result.returncode
|
||||
result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET], text=True) ## they want the output
|
||||
return not result.returncode ## negate shell result
|
||||
|
||||
|
||||
#/**
|
||||
|
|
|
@ -254,7 +254,7 @@ def ogCreateImage (disk, par, container, imgfile, tool='partclone', level='gzip'
|
|||
#trap
|
||||
p = subprocess.run (program, shell=True, check=True)
|
||||
errcode = p.returncode
|
||||
if 0 == errcode:
|
||||
if 0 == errcode: ## success
|
||||
i = ogGetImageInfo (IMGFILE)
|
||||
h = NetLib.ogGetHostname()
|
||||
with open (f'{IMGFILE}.info', 'w') as fd:
|
||||
|
@ -515,10 +515,8 @@ def ogRestoreImage (repo, imgpath, disk, par):
|
|||
|
||||
rc = None
|
||||
try:
|
||||
p = subprocess.run (program, shell=True, capture_output=True, text=True)
|
||||
print (p.stdout)
|
||||
print (p.stderr)
|
||||
rc = p.returncode
|
||||
p = subprocess.run (program, shell=True, text=True)
|
||||
rc = not p.returncode
|
||||
if not rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobalsOG_ERR_IMAGE, f'{imgfile}, {disk}, {par}')
|
||||
except:
|
||||
|
@ -607,7 +605,7 @@ def ogGetImageInfo (imgfile):
|
|||
## original bash idiom is: $($COMPRESSOR -dc $IMGFILE 2>/dev/null | head -n 40 > $FILEHEAD) || ogRaiseError
|
||||
## the purpose of which I can't fully comprehend
|
||||
#print (f'shelling out "{compressor} -dc {imgfile} |head -n 40 > {filehead}"')
|
||||
if subprocess.run (f'{compressor} -dc {imgfile} |head -n 40 > {filehead}', shell=True).returncode:
|
||||
if subprocess.run (f'{compressor} -dc {imgfile} |head -n 40 > {filehead}', shell=True).returncode: ## if True, then the compressor failed
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}')
|
||||
return
|
||||
|
||||
|
|
|
@ -428,7 +428,7 @@ def ogGetOsVersion(disk, part):
|
|||
f'load {file}',
|
||||
r'cd \Microsoft\Windows NT\CurrentVersion',
|
||||
'lsval ProductName',
|
||||
'lsval DisplayVersion',
|
||||
'lsval ReleaseId',
|
||||
])
|
||||
version = subprocess.run (['hivexsh'], input=i, capture_output=True, text=True).stdout
|
||||
version = version.replace ('\n', ' ')
|
||||
|
|
|
@ -129,11 +129,11 @@ def ogUcastSendPartition (disk, par, sess, tool, level):
|
|||
|
||||
cmd = ogUcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=level)
|
||||
if not cmd: return None
|
||||
try:
|
||||
subprocess.run (cmd, shell=True, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDPARTITION, ' ')
|
||||
rc = subprocess.run (cmd, shell=True).returncode
|
||||
if rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDPARTITION, f'pipeline "{cmd}" returned code "{rc}"')
|
||||
return None
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
@ -160,11 +160,11 @@ def ogUcastReceiverPartition (disk, par, sess, tool, level):
|
|||
|
||||
cmd = ogUcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=level)
|
||||
if not cmd: return None
|
||||
try:
|
||||
subprocess.run (cmd, shell=True, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTRECEIVERPARTITION, ' ')
|
||||
rc = subprocess.run (cmd, shell=True).returncode
|
||||
if rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTRECEIVERPARTITION, f'pipeline "{cmd}" returned code "{rc}"')
|
||||
return None
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
@ -224,17 +224,18 @@ def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None):
|
|||
return
|
||||
|
||||
path2 = FileLib.ogGetPath (file=source)
|
||||
print (f'nati path2 ({path2})')
|
||||
if not path2:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found')
|
||||
return
|
||||
|
||||
cmd = ogUcastSyntax ('SENDFILE', sess, file=source)
|
||||
if not cmd: return None
|
||||
try:
|
||||
subprocess.run (cmd, shell=True, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDFILE, ' ')
|
||||
rc = subprocess.run (cmd, shell=True).returncode
|
||||
if rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDFILE, f'pipeline "{cmd}" returned code "{rc}"')
|
||||
return None
|
||||
return True
|
||||
|
||||
def _clientip():
|
||||
ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'], capture_output=True, text=True).stdout
|
||||
|
@ -482,17 +483,18 @@ def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None):
|
|||
return
|
||||
|
||||
path2 = FileLib.ogGetPath (file=source)
|
||||
print (f'nati path2 ({path2})')
|
||||
if not path2:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found')
|
||||
return
|
||||
|
||||
cmd = ogMcastSyntax ('SENDFILE', sess, file=source)
|
||||
if not cmd: return None
|
||||
try:
|
||||
subprocess.run (cmd, shell=True, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDFILE, ' ')
|
||||
rc = subprocess.run (cmd, shell=True).returncode
|
||||
if rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDFILE, f'pipeline "{cmd}" returned code "{rc}"')
|
||||
return None
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
@ -549,11 +551,11 @@ def ogMcastReceiverFile (disk=None, par=None, container=None, file=None, sess=No
|
|||
|
||||
cmd = ogMcastSyntax ('RECEIVERFILE', sess, file=os.path.join (targetdir, targetfile))
|
||||
if not cmd: return None
|
||||
try:
|
||||
subprocess.run (cmd, shell=True, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERFILE, targetfile)
|
||||
rc = subprocess.run (cmd, shell=True).returncode
|
||||
if rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERFILE, f'pipeline "{cmd}" returned code "{rc}"')
|
||||
return None
|
||||
return True
|
||||
|
||||
|
||||
#/**
|
||||
|
@ -581,11 +583,11 @@ def ogMcastSendPartition (disk, par, sess, tool, compressor):
|
|||
FileSystemLib.ogUnmount (disk, par)
|
||||
cmd = ogMcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=compressor)
|
||||
if not cmd: return None
|
||||
try:
|
||||
subprocess.run (cmd, shell=True, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDPARTITION, ' ')
|
||||
rc = subprocess.run (cmd, shell=True).returncode
|
||||
if rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDPARTITION, f'pipeline "{cmd}" returned code "{rc}"')
|
||||
return None
|
||||
return True
|
||||
|
||||
#/**
|
||||
# ogMcastReceiverPartition
|
||||
|
@ -606,22 +608,10 @@ def ogMcastReceiverPartition (disk, par, sess, tool, compressor):
|
|||
FileSystemLib.ogUnmount (disk, par)
|
||||
cmd = ogMcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=compressor)
|
||||
if not cmd: return None
|
||||
try:
|
||||
subprocess.run (cmd, shell=True, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERPARTITION, ' ') ## original code has OG_ERR_MCASTSENDPARTITION
|
||||
rc = subprocess.run (cmd, shell=True).returncode
|
||||
if rc:
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERPARTITION, f'pipeline "{cmd}" returned code "{rc}"') ## original code has OG_ERR_MCASTSENDPARTITION
|
||||
return None
|
||||
|
||||
|
||||
|
||||
#/**
|
||||
# ogMcastRequest
|
||||
#@brief Función temporal para solicitar al ogRepoAux el envio de un fichero por multicast
|
||||
#@param 1 Fichero a enviar ubicado en el REPO. puede ser ruta absoluta o relatica a /opt/opengnsys/images
|
||||
#@param 2 PROTOOPT opciones protocolo multicast
|
||||
#*/ ##
|
||||
## now ogCore takes this responsibility
|
||||
def ogMcastRequest (img, proto):
|
||||
return True
|
||||
|
||||
|
||||
|
@ -681,7 +671,7 @@ def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torre
|
|||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or torrentfile {dev_err} not found')
|
||||
return
|
||||
|
||||
if subprocess.run (['ctorrent', '-x', source]).returncode:
|
||||
if subprocess.run (['ctorrent', '-x', source]).returncode: ## if True, then ctorrent failed
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, '')
|
||||
return None
|
||||
|
||||
|
@ -736,20 +726,22 @@ def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torre
|
|||
# Creamos el fichero de resumen por defecto
|
||||
open (f'{source}.bf', 'w').close()
|
||||
# ctorrent controla otro fichero -b ${SOURCE}.bfog
|
||||
subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog'])
|
||||
ctorrent_cmd = ['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']
|
||||
elif 'leecher' == mode:
|
||||
print ('Donwloading Torrent as leecher')
|
||||
subprocess.run (['ctorrent', '${SOURCE}', '-X', 'sleep 30; kill -2 $(pidof ctorrent)', '-C', '100', '-U', '0'])
|
||||
ctorrent_cmd = ['ctorrent', source, '-X', 'sleep 30; kill -2 $(pidof ctorrent)', '-C', '100', '-U', '0']
|
||||
elif 'seeder' == mode:
|
||||
print ('MODE seeder ctorrent')
|
||||
# Creamos el fichero de resumen por defecto
|
||||
open (f'{source}.bf', 'w').close()
|
||||
# ctorrent controla otro fichero -b ${SOURCE}.bfog
|
||||
subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog'])
|
||||
ctorrent_cmd = ['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']
|
||||
else:
|
||||
print ('this should not happen')
|
||||
return None
|
||||
|
||||
print (f'executing ctorrent: {' '.join(ctorrent_cmd)}')
|
||||
subprocess.run (ctorrent_cmd)
|
||||
os.chdir (cwd)
|
||||
|
||||
|
||||
|
@ -858,9 +850,9 @@ def ogUpdateCacheIsNecesary (repo, file, proto):
|
|||
filetarget = FileLib.ogGetPath (src='CACHE', file=file)
|
||||
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 (container='CACHE', file=f'{file}.torrent.bf')
|
||||
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.sum'): ogDeleteFile (container='CACHE', file=f'{file}.sum')
|
||||
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.full.sum'): ogDeleteFile (container='CACHE', file=f'{file}.full.sum')
|
||||
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.torrent.bf'): FileLib.ogDeleteFile (container='CACHE', file=f'{file}.torrent.bf')
|
||||
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.sum'): FileLib.ogDeleteFile (container='CACHE', file=f'{file}.sum')
|
||||
if FileLib.ogGetPath (src='CACHE', file=f'/{file}.full.sum'): FileLib.ogDeleteFile (container='CACHE', file=f'{file}.full.sum')
|
||||
print ('TRUE(0), es necesario actualizar. Paso 1, la cache no contiene esa imagen ')
|
||||
return True
|
||||
|
||||
|
@ -926,6 +918,7 @@ def ogUpdateCacheIsNecesary (repo, file, proto):
|
|||
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)
|
||||
if os.path.exists (f):
|
||||
os.unlink (f)
|
||||
print ('TRUE (0), Si es necesario actualizar.')
|
||||
return True
|
||||
|
|
|
@ -3,22 +3,15 @@ import datetime
|
|||
from zoneinfo import ZoneInfo
|
||||
import sys
|
||||
import os
|
||||
import select
|
||||
import json
|
||||
import shutil
|
||||
import inspect
|
||||
import glob
|
||||
|
||||
## for ogExecAndLog
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
|
||||
import ogGlobals
|
||||
import StringLib
|
||||
|
||||
#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 _logtype2logfile (t):
|
||||
if 'log' == t.lower(): return ogGlobals.OGLOGFILE
|
||||
if 'jsonlog' == t.lower(): return ogGlobals.OGJSONLOGFILE
|
||||
|
@ -84,11 +77,11 @@ def ogEcho (logtypes, loglevel, msg):
|
|||
#@note str_logfile = { LOG, SESSION, COMMAND }
|
||||
#*/
|
||||
#ogExecAndLog (str_logfile ... str_command ...",
|
||||
#ogExecAndLog ([], ogMyLib.ogSomeMethod, *args, **kwargs)
|
||||
#ogExecAndLog ('command', ogMyLib.ogSomeMethod, *args, **kwargs)
|
||||
#ogExecAndLog (['command'], ogMyLib.ogSomeMethod, *args, **kwargs)
|
||||
#ogExecAndLog (['log', 'command'], ogMyLib.ogSomeMethod, *args, **kwargs)
|
||||
def ogExecAndLog (logtypes, fun, *args, **kwargs):
|
||||
#ogExecAndLog ([], ['/path/to/script', *args])
|
||||
#ogExecAndLog ('command', ['/path/to/script', *args])
|
||||
#ogExecAndLog (['command'], ['/path/to/script', *args])
|
||||
#ogExecAndLog (['log', 'command'], ['/path/to/script', *args])
|
||||
def ogExecAndLog (logtypes, script_and_args):
|
||||
logfiles = ['/dev/stdout']
|
||||
if type (logtypes) is list:
|
||||
for l in logtypes:
|
||||
|
@ -106,7 +99,7 @@ def ogExecAndLog (logtypes, fun, *args, **kwargs):
|
|||
else:
|
||||
logfiles.append (_logtype2logfile (logtypes))
|
||||
|
||||
if not fun:
|
||||
if not script_and_args:
|
||||
ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'no function provided')
|
||||
return
|
||||
|
||||
|
@ -129,38 +122,38 @@ def ogExecAndLog (logtypes, fun, *args, **kwargs):
|
|||
# ## redirect stdout only
|
||||
# eval $COMMAND | tee -a $FILES
|
||||
|
||||
sout = serr = ''
|
||||
capture_stderr = False
|
||||
if 'command' in logtypes:
|
||||
os.unlink (ogGlobals.OGLOGCOMMAND)
|
||||
open (ogGlobals.OGLOGCOMMAND, 'w').close()
|
||||
with redirect_stdout (StringIO()) as r_stdout, redirect_stderr (StringIO()) as r_stderr:
|
||||
rc = fun (*args, **kwargs)
|
||||
sout = r_stdout.getvalue()
|
||||
serr = r_stderr.getvalue()
|
||||
else:
|
||||
with redirect_stdout (StringIO()) as r_stdout:
|
||||
rc = fun (*args, **kwargs)
|
||||
sout = r_stdout.getvalue()
|
||||
capture_stderr = True
|
||||
|
||||
rc_str = str (rc)
|
||||
if sout or serr or ('True' != rc_str and 'False' != rc_str and 'None' != rc_str):
|
||||
for f in logfiles:
|
||||
with open (f, 'a') as fd:
|
||||
if ogGlobals.OGJSONLOGFILE == f:
|
||||
if sout: fd.write (json.dumps ({'message':sout}) + '\n')
|
||||
if serr: fd.write (json.dumps ({'message':serr}) + '\n')
|
||||
if rc_str: fd.write (json.dumps ({'message':rc_str}) + '\n')
|
||||
else:
|
||||
if sout: fd.write (f'{sout}\n')
|
||||
if serr: fd.write (f'{serr}\n')
|
||||
if rc_str: fd.write (f'{rc_str}\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")
|
||||
p = subprocess.Popen (script_and_args, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
while True:
|
||||
ready_to_read, _, _ = select.select ([p.stdout, p.stderr], [], [], 1)
|
||||
|
||||
return rc
|
||||
partial_out = ''
|
||||
if p.stdout in ready_to_read:
|
||||
l = p.stdout.readline()
|
||||
partial_out += l
|
||||
if p.stderr in ready_to_read:
|
||||
l = p.stderr.readline() ## always read from stderr even if we're discarding it, to prevent buffers from filling up
|
||||
if capture_stderr:
|
||||
partial_out += l
|
||||
|
||||
if partial_out:
|
||||
for f in logfiles:
|
||||
with open (f, 'a') as fd:
|
||||
if ogGlobals.OGJSONLOGFILE == f:
|
||||
fd.write (json.dumps ({'message':partial_out}))
|
||||
else:
|
||||
fd.write (partial_out)
|
||||
|
||||
if p.poll() is not None:
|
||||
break
|
||||
|
||||
rc = p.returncode
|
||||
return not rc ## negate shell return code
|
||||
|
||||
#/**
|
||||
# ogGetCaller
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
#!/usr/bin/env python3
|
||||
import hivex
|
||||
import argparse
|
||||
import struct
|
||||
|
||||
from hivex import Hivex
|
||||
from hivex.hive_types import *
|
||||
|
||||
|
||||
# Docs:
|
||||
#
|
||||
# https://www.geoffchappell.com/notes/windows/boot/bcd/objects.htm
|
||||
# https://learn.microsoft.com/en-us/previous-versions/windows/desktop/bcd/bcdbootmgrelementtypes
|
||||
|
||||
#print(f"Root: {root}")
|
||||
|
||||
|
||||
BCD_Enumerations = {
|
||||
"BcdLibraryDevice_ApplicationDevice" : 0x11000001,
|
||||
"BcdLibraryString_ApplicationPath" : 0x12000002,
|
||||
"BcdLibraryString_Description" : 0x12000004,
|
||||
"BcdLibraryString_PreferredLocale" : 0x12000005,
|
||||
"BcdLibraryObjectList_InheritedObjects" : 0x14000006,
|
||||
"BcdLibraryInteger_TruncatePhysicalMemory" : 0x15000007,
|
||||
"BcdLibraryObjectList_RecoverySequence" : 0x14000008,
|
||||
"BcdLibraryBoolean_AutoRecoveryEnabled" : 0x16000009,
|
||||
"BcdLibraryIntegerList_BadMemoryList" : 0x1700000a,
|
||||
"BcdLibraryBoolean_AllowBadMemoryAccess" : 0x1600000b,
|
||||
"BcdLibraryInteger_FirstMegabytePolicy" : 0x1500000c,
|
||||
"BcdLibraryInteger_RelocatePhysicalMemory" : 0x1500000D,
|
||||
"BcdLibraryInteger_AvoidLowPhysicalMemory" : 0x1500000E,
|
||||
"BcdLibraryBoolean_DebuggerEnabled" : 0x16000010,
|
||||
"BcdLibraryInteger_DebuggerType" : 0x15000011,
|
||||
"BcdLibraryInteger_SerialDebuggerPortAddress" : 0x15000012,
|
||||
"BcdLibraryInteger_SerialDebuggerPort" : 0x15000013,
|
||||
"BcdLibraryInteger_SerialDebuggerBaudRate" : 0x15000014,
|
||||
"BcdLibraryInteger_1394DebuggerChannel" : 0x15000015,
|
||||
"BcdLibraryString_UsbDebuggerTargetName" : 0x12000016,
|
||||
"BcdLibraryBoolean_DebuggerIgnoreUsermodeExceptions" : 0x16000017,
|
||||
"BcdLibraryInteger_DebuggerStartPolicy" : 0x15000018,
|
||||
"BcdLibraryString_DebuggerBusParameters" : 0x12000019,
|
||||
"BcdLibraryInteger_DebuggerNetHostIP" : 0x1500001A,
|
||||
"BcdLibraryInteger_DebuggerNetPort" : 0x1500001B,
|
||||
"BcdLibraryBoolean_DebuggerNetDhcp" : 0x1600001C,
|
||||
"BcdLibraryString_DebuggerNetKey" : 0x1200001D,
|
||||
"BcdLibraryBoolean_EmsEnabled" : 0x16000020,
|
||||
"BcdLibraryInteger_EmsPort" : 0x15000022,
|
||||
"BcdLibraryInteger_EmsBaudRate" : 0x15000023,
|
||||
"BcdLibraryString_LoadOptionsString" : 0x12000030,
|
||||
"BcdLibraryBoolean_DisplayAdvancedOptions" : 0x16000040,
|
||||
"BcdLibraryBoolean_DisplayOptionsEdit" : 0x16000041,
|
||||
"BcdLibraryDevice_BsdLogDevice" : 0x11000043,
|
||||
"BcdLibraryString_BsdLogPath" : 0x12000044,
|
||||
"BcdLibraryBoolean_GraphicsModeDisabled" : 0x16000046,
|
||||
"BcdLibraryInteger_ConfigAccessPolicy" : 0x15000047,
|
||||
"BcdLibraryBoolean_DisableIntegrityChecks" : 0x16000048,
|
||||
"BcdLibraryBoolean_AllowPrereleaseSignatures" : 0x16000049,
|
||||
"BcdLibraryString_FontPath" : 0x1200004A,
|
||||
"BcdLibraryInteger_SiPolicy" : 0x1500004B,
|
||||
"BcdLibraryInteger_FveBandId" : 0x1500004C,
|
||||
"BcdLibraryBoolean_ConsoleExtendedInput" : 0x16000050,
|
||||
"BcdLibraryInteger_GraphicsResolution" : 0x15000052,
|
||||
"BcdLibraryBoolean_RestartOnFailure" : 0x16000053,
|
||||
"BcdLibraryBoolean_GraphicsForceHighestMode" : 0x16000054,
|
||||
"BcdLibraryBoolean_IsolatedExecutionContext" : 0x16000060,
|
||||
"BcdLibraryBoolean_BootUxDisable" : 0x1600006C,
|
||||
"BcdLibraryBoolean_BootShutdownDisabled" : 0x16000074,
|
||||
"BcdLibraryIntegerList_AllowedInMemorySettings" : 0x17000077,
|
||||
"BcdLibraryBoolean_ForceFipsCrypto" : 0x16000079,
|
||||
|
||||
|
||||
"BcdBootMgrObjectList_DisplayOrder" : 0x24000001,
|
||||
"BcdBootMgrObjectList_BootSequence" : 0x24000002,
|
||||
"BcdBootMgrObject_DefaultObject" : 0x23000003,
|
||||
"BcdBootMgrInteger_Timeout" : 0x25000004,
|
||||
"BcdBootMgrBoolean_AttemptResume" : 0x26000005,
|
||||
"BcdBootMgrObject_ResumeObject" : 0x23000006,
|
||||
"BcdBootMgrObjectList_ToolsDisplayOrder" : 0x24000010,
|
||||
"BcdBootMgrBoolean_DisplayBootMenu" : 0x26000020,
|
||||
"BcdBootMgrBoolean_NoErrorDisplay" : 0x26000021,
|
||||
"BcdBootMgrDevice_BcdDevice" : 0x21000022,
|
||||
"BcdBootMgrString_BcdFilePath" : 0x22000023,
|
||||
"BcdBootMgrBoolean_ProcessCustomActionsFirst" : 0x26000028,
|
||||
"BcdBootMgrIntegerList_CustomActionsList" : 0x27000030,
|
||||
"BcdBootMgrBoolean_PersistBootSequence" : 0x26000031,
|
||||
|
||||
"BcdDeviceInteger_RamdiskImageOffset" : 0x35000001,
|
||||
"BcdDeviceInteger_TftpClientPort" : 0x35000002,
|
||||
"BcdDeviceInteger_SdiDevice" : 0x31000003,
|
||||
"BcdDeviceInteger_SdiPath" : 0x32000004,
|
||||
"BcdDeviceInteger_RamdiskImageLength" : 0x35000005,
|
||||
"BcdDeviceBoolean_RamdiskExportAsCd" : 0x36000006,
|
||||
"BcdDeviceInteger_RamdiskTftpBlockSize" : 0x36000007,
|
||||
"BcdDeviceInteger_RamdiskTftpWindowSize" : 0x36000008,
|
||||
"BcdDeviceBoolean_RamdiskMulticastEnabled" : 0x36000009,
|
||||
"BcdDeviceBoolean_RamdiskMulticastTftpFallback" : 0x3600000A,
|
||||
"BcdDeviceBoolean_RamdiskTftpVarWindow" : 0x3600000B,
|
||||
|
||||
"BcdMemDiagInteger_PassCount" : 0x25000001,
|
||||
"BcdMemDiagInteger_FailureCount" : 0x25000003,
|
||||
|
||||
"Reserved1" : 0x21000001,
|
||||
"Reserved2" : 0x22000002,
|
||||
"BcdResumeBoolean_UseCustomSettings" : 0x26000003,
|
||||
"BcdResumeDevice_AssociatedOsDevice" : 0x21000005,
|
||||
"BcdResumeBoolean_DebugOptionEnabled" : 0x26000006,
|
||||
"BcdResumeInteger_BootMenuPolicy" : 0x25000008,
|
||||
|
||||
"BcdOSLoaderDevice_OSDevice" : 0x21000001,
|
||||
"BcdOSLoaderString_SystemRoot" : 0x22000002,
|
||||
"BcdOSLoaderObject_AssociatedResumeObject" : 0x23000003,
|
||||
"BcdOSLoaderBoolean_DetectKernelAndHal" : 0x26000010,
|
||||
"BcdOSLoaderString_KernelPath" : 0x22000011,
|
||||
"BcdOSLoaderString_HalPath" : 0x22000012,
|
||||
"BcdOSLoaderString_DbgTransportPath" : 0x22000013,
|
||||
"BcdOSLoaderInteger_NxPolicy" : 0x25000020,
|
||||
"BcdOSLoaderInteger_PAEPolicy" : 0x25000021,
|
||||
"BcdOSLoaderBoolean_WinPEMode" : 0x26000022,
|
||||
"BcdOSLoaderBoolean_DisableCrashAutoReboot" : 0x26000024,
|
||||
"BcdOSLoaderBoolean_UseLastGoodSettings" : 0x26000025,
|
||||
"BcdOSLoaderBoolean_AllowPrereleaseSignatures" : 0x26000027,
|
||||
"BcdOSLoaderBoolean_NoLowMemory" : 0x26000030,
|
||||
"BcdOSLoaderInteger_RemoveMemory" : 0x25000031,
|
||||
"BcdOSLoaderInteger_IncreaseUserVa" : 0x25000032,
|
||||
"BcdOSLoaderBoolean_UseVgaDriver" : 0x26000040,
|
||||
"BcdOSLoaderBoolean_DisableBootDisplay" : 0x26000041,
|
||||
"BcdOSLoaderBoolean_DisableVesaBios" : 0x26000042,
|
||||
"BcdOSLoaderBoolean_DisableVgaMode" : 0x26000043,
|
||||
"BcdOSLoaderInteger_ClusterModeAddressing" : 0x25000050,
|
||||
"BcdOSLoaderBoolean_UsePhysicalDestination" : 0x26000051,
|
||||
"BcdOSLoaderInteger_RestrictApicCluster" : 0x25000052,
|
||||
"BcdOSLoaderBoolean_UseLegacyApicMode" : 0x26000054,
|
||||
"BcdOSLoaderInteger_X2ApicPolicy" : 0x25000055,
|
||||
"BcdOSLoaderBoolean_UseBootProcessorOnly" : 0x26000060,
|
||||
"BcdOSLoaderInteger_NumberOfProcessors" : 0x25000061,
|
||||
"BcdOSLoaderBoolean_ForceMaximumProcessors" : 0x26000062,
|
||||
"BcdOSLoaderBoolean_ProcessorConfigurationFlags" : 0x25000063,
|
||||
"BcdOSLoaderBoolean_MaximizeGroupsCreated" : 0x26000064,
|
||||
"BcdOSLoaderBoolean_ForceGroupAwareness" : 0x26000065,
|
||||
"BcdOSLoaderInteger_GroupSize" : 0x25000066,
|
||||
"BcdOSLoaderInteger_UseFirmwarePciSettings" : 0x26000070,
|
||||
"BcdOSLoaderInteger_MsiPolicy" : 0x25000071,
|
||||
"BcdOSLoaderInteger_SafeBoot" : 0x25000080,
|
||||
"BcdOSLoaderBoolean_SafeBootAlternateShell" : 0x26000081,
|
||||
"BcdOSLoaderBoolean_BootLogInitialization" : 0x26000090,
|
||||
"BcdOSLoaderBoolean_VerboseObjectLoadMode" : 0x26000091,
|
||||
"BcdOSLoaderBoolean_KernelDebuggerEnabled" : 0x260000a0,
|
||||
"BcdOSLoaderBoolean_DebuggerHalBreakpoint" : 0x260000a1,
|
||||
"BcdOSLoaderBoolean_UsePlatformClock" : 0x260000A2,
|
||||
"BcdOSLoaderBoolean_ForceLegacyPlatform" : 0x260000A3,
|
||||
"BcdOSLoaderInteger_TscSyncPolicy" : 0x250000A6,
|
||||
"BcdOSLoaderBoolean_EmsEnabled" : 0x260000b0,
|
||||
"BcdOSLoaderInteger_DriverLoadFailurePolicy" : 0x250000c1,
|
||||
"BcdOSLoaderInteger_BootMenuPolicy" : 0x250000C2,
|
||||
"BcdOSLoaderBoolean_AdvancedOptionsOneTime" : 0x260000C3,
|
||||
"BcdOSLoaderInteger_BootStatusPolicy" : 0x250000E0,
|
||||
"BcdOSLoaderBoolean_DisableElamDrivers" : 0x260000E1,
|
||||
"BcdOSLoaderInteger_HypervisorLaunchType" : 0x250000F0,
|
||||
"BcdOSLoaderBoolean_HypervisorDebuggerEnabled" : 0x260000F2,
|
||||
"BcdOSLoaderInteger_HypervisorDebuggerType" : 0x250000F3,
|
||||
"BcdOSLoaderInteger_HypervisorDebuggerPortNumber" : 0x250000F4,
|
||||
"BcdOSLoaderInteger_HypervisorDebuggerBaudrate" : 0x250000F5,
|
||||
"BcdOSLoaderInteger_HypervisorDebugger1394Channel" : 0x250000F6,
|
||||
"BcdOSLoaderInteger_BootUxPolicy" : 0x250000F7,
|
||||
"BcdOSLoaderString_HypervisorDebuggerBusParams" : 0x220000F9,
|
||||
"BcdOSLoaderInteger_HypervisorNumProc" : 0x250000FA,
|
||||
"BcdOSLoaderInteger_HypervisorRootProcPerNode" : 0x250000FB,
|
||||
"BcdOSLoaderBoolean_HypervisorUseLargeVTlb" : 0x260000FC,
|
||||
"BcdOSLoaderInteger_HypervisorDebuggerNetHostIp" : 0x250000FD,
|
||||
"BcdOSLoaderInteger_HypervisorDebuggerNetHostPort" : 0x250000FE,
|
||||
"BcdOSLoaderInteger_TpmBootEntropyPolicy" : 0x25000100,
|
||||
"BcdOSLoaderString_HypervisorDebuggerNetKey" : 0x22000110,
|
||||
"BcdOSLoaderBoolean_HypervisorDebuggerNetDhcp" : 0x26000114,
|
||||
"BcdOSLoaderInteger_HypervisorIommuPolicy" : 0x25000115,
|
||||
"BcdOSLoaderInteger_XSaveDisable" : 0x2500012b
|
||||
}
|
||||
|
||||
|
||||
def format_value(bcd, bcd_value):
|
||||
|
||||
name = bcd.value_key(bcd_value)
|
||||
(type, length) = bcd.value_type(bcd_value)
|
||||
|
||||
typename = ""
|
||||
str_value = ""
|
||||
if type == REG_SZ:
|
||||
typename = "SZ"
|
||||
str_value = bcd.value_string(bcd_value)
|
||||
elif type == REG_DWORD:
|
||||
typename = "DWORD"
|
||||
dval = bcd.value_dword(bcd_value)
|
||||
|
||||
str_value = hex(dval) + " (" + str(bcd.value_dword(bcd_value)) + ")"
|
||||
elif type == REG_BINARY:
|
||||
typename = "BIN"
|
||||
(length, value) = bcd.value_value(bcd_value)
|
||||
str_value = value.hex()
|
||||
elif type == REG_DWORD_BIG_ENDIAN:
|
||||
typename = "DWORD_BE"
|
||||
elif type == REG_EXPAND_SZ:
|
||||
typename = "EXPAND SZ"
|
||||
elif type == REG_FULL_RESOURCE_DESCRIPTOR:
|
||||
typename = "RES DESC"
|
||||
elif type == REG_LINK:
|
||||
typename = "LINK"
|
||||
elif type == REG_MULTI_SZ:
|
||||
typename = "MULTISZ"
|
||||
(length, str_value) = bcd.value_value(bcd_value)
|
||||
str_value = str_value.decode('utf-16le')
|
||||
str_value = str_value.replace("\0", ";")
|
||||
#value = ";".join("\0".split(value))
|
||||
elif type == REG_NONE:
|
||||
typename = "NONE"
|
||||
elif type == REG_QWORD:
|
||||
typename = "QWORD"
|
||||
elif type == REG_RESOURCE_LIST:
|
||||
typename = "RES LIST"
|
||||
elif type == REG_RESOURCE_REQUIREMENTS_LIST:
|
||||
typename = "REQ LIST"
|
||||
else:
|
||||
typename = str(type)
|
||||
str_value = "???"
|
||||
|
||||
|
||||
return (typename, length, str_value)
|
||||
|
||||
def dump_all(root, depth = 0):
|
||||
|
||||
padding = "\t" * depth
|
||||
|
||||
children = bcd.node_children(root)
|
||||
|
||||
if len(children) > 0:
|
||||
|
||||
for child in children:
|
||||
name = bcd.node_name(child)
|
||||
print(f"{padding}{name}")
|
||||
|
||||
dump_all(child, depth + 1)
|
||||
# print(f"Child: {child}")
|
||||
|
||||
#print(f"Values: {num_vals}")
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
values = bcd.node_values(root)
|
||||
#print(f"Value list: {values}")
|
||||
|
||||
for v in values:
|
||||
(type_name, length, str_value) = format_value(bcd, v)
|
||||
name = bcd.value_key(v)
|
||||
|
||||
print(f"{padding}{name: <16}: [{type_name: <10}]; ({length: < 4}) {str_value}")
|
||||
|
||||
|
||||
class WindowsBCD:
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.bcd = Hivex(filename)
|
||||
|
||||
def dump(self, root=None, depth = 0):
|
||||
padding = "\t" * depth
|
||||
|
||||
if root is None:
|
||||
root = self.bcd.root()
|
||||
|
||||
children = self.bcd.node_children(root)
|
||||
|
||||
if len(children) > 0:
|
||||
for child in children:
|
||||
name = self.bcd.node_name(child)
|
||||
print(f"{padding}{name}")
|
||||
|
||||
self.dump(child, depth + 1)
|
||||
return
|
||||
|
||||
values = self.bcd.node_values(root)
|
||||
|
||||
for v in values:
|
||||
(type_name, length, str_value) = format_value(self.bcd, v)
|
||||
name = self.bcd.value_key(v)
|
||||
|
||||
print(f"{padding}{name: <16}: [{type_name: <10}]; ({length: < 4}) {str_value}")
|
||||
|
||||
def list(self):
|
||||
root = self.bcd.root()
|
||||
objects = self.bcd.node_get_child(root, "Objects")
|
||||
|
||||
for child in self.bcd.node_children(objects):
|
||||
entry_id = self.bcd.node_name(child)
|
||||
|
||||
elements = self.bcd.node_get_child(child, "Elements")
|
||||
description_entry = self.bcd.node_get_child(elements, "12000004")
|
||||
|
||||
if description_entry:
|
||||
values = self.bcd.node_values(description_entry)
|
||||
if values:
|
||||
(type_name, length, str_value) = format_value(self.bcd, values[0])
|
||||
print(f"{entry_id}: {str_value}")
|
||||
else:
|
||||
print(f"{entry_id}: [no description value!?]")
|
||||
|
||||
|
||||
appdevice_entry = self.bcd.node_get_child(elements, "11000001")
|
||||
|
||||
if appdevice_entry:
|
||||
values = self.bcd.node_values(appdevice_entry)
|
||||
(length, data) = self.bcd.value_value(values[0])
|
||||
hex = data.hex()
|
||||
print(f"LEN: {length}, HEX: {hex}, RAW: {data}")
|
||||
if len(data) > 10:
|
||||
etype = struct.unpack_from('<I', data, offset = 16)
|
||||
print(f"Type: {etype}")
|
||||
|
||||
|
||||
|
||||
else:
|
||||
print(f"{entry_id}: [no description entry 12000004]")
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="Windows BCD parser",
|
||||
description="Parses the BCD",
|
||||
)
|
||||
|
||||
parser.add_argument("--db", type=str, metavar='BCD file', help="Database to use")
|
||||
parser.add_argument("--dump", action='store_true', help="Dumps the specified database")
|
||||
parser.add_argument("--list", action='store_true', help="Lists boot entries in the specified database")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
bcdobj = WindowsBCD(args.db)
|
||||
|
||||
if args.dump:
|
||||
# "/home/vadim/opengnsys/winboot/boot-copy/EFI/Microsoft/Boot/BCD"
|
||||
#bcd = Hivex(args.dump)
|
||||
|
||||
#root = bcd.root()
|
||||
#dump_all(root)
|
||||
bcdobj.dump()
|
||||
elif args.list:
|
||||
bcdobj.list()
|
|
@ -0,0 +1,124 @@
|
|||
|
||||
import logging
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
# pylint: disable=locally-disabled, line-too-long, logging-fstring-interpolation, too-many-lines
|
||||
|
||||
|
||||
class DiskLibrary:
|
||||
def __init__(self):
|
||||
self.logger = logging.getLogger("OpengnsysDiskLibrary")
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
def split_device_partition(self, device):
|
||||
"""
|
||||
Parses a device file like /dev/sda3 into the root device (/dev/sda) and partition number (3)
|
||||
|
||||
Args:
|
||||
device (str): Device in /dev
|
||||
|
||||
Returns:
|
||||
[base_device, partno]
|
||||
"""
|
||||
|
||||
r = re.compile("^(.*?)(\\d+)$")
|
||||
m = r.match(device)
|
||||
disk = m.group(1)
|
||||
partno = int(m.group(2))
|
||||
|
||||
self.logger.debug(f"{device} parsed into disk device {disk}, partition {partno}")
|
||||
return (disk, partno)
|
||||
|
||||
def get_disk_json_data(self, device):
|
||||
"""
|
||||
Returns the partition JSON data dump for the entire disk, even if a partition is passed.
|
||||
|
||||
This is specifically in the format used by sfdisk.
|
||||
|
||||
Args:
|
||||
device (str): Block device, eg, /dev/sda3
|
||||
|
||||
Returns:
|
||||
str: JSON dump produced by sfdisk
|
||||
"""
|
||||
(disk, partno) = self.split_device_partition(device)
|
||||
|
||||
result = subprocess.run(["/usr/sbin/sfdisk", "--json", disk], check=True, capture_output=True, encoding='utf-8')
|
||||
return result.stdout.strip()
|
||||
|
||||
def get_disk_uuid(self, device):
|
||||
"""
|
||||
Returns the UUID of the disk itself, if there's a GPT partition table.
|
||||
|
||||
Args:
|
||||
device (str): Block device, eg, /dev/sda3
|
||||
|
||||
Returns:
|
||||
str: UUID
|
||||
"""
|
||||
(disk, partno) = self.split_device_partition(device)
|
||||
|
||||
result = subprocess.run(["/usr/sbin/sfdisk", "--disk-id", disk], check=True, capture_output=True, encoding='utf-8')
|
||||
return result.stdout.strip()
|
||||
|
||||
def set_disk_uuid(self, device, uuid):
|
||||
|
||||
(disk, partno) = self.split_device_partition(device)
|
||||
|
||||
subprocess.run(["/usr/sbin/sfdisk", "--disk-id", disk, uuid], check=True, encoding='utf-8')
|
||||
|
||||
|
||||
def get_partition_uuid(self, device):
|
||||
"""
|
||||
Returns the UUID of the partition, if there's a GPT partition table.
|
||||
|
||||
Args:
|
||||
device (str): Block device, eg, /dev/sda3
|
||||
|
||||
Returns:
|
||||
str: UUID
|
||||
"""
|
||||
|
||||
(disk, partno) = self.split_device_partition(device)
|
||||
|
||||
#result = subprocess.run(["/usr/sbin/sfdisk", "--part-uuid", disk, str(partno)], check=True, capture_output=True, encoding='utf-8')
|
||||
#return result.stdout.strip()
|
||||
guid = None
|
||||
result = subprocess.run(["/usr/sbin/sgdisk", "--info", str(partno), disk], check=True, capture_output=True, encoding='utf-8')
|
||||
for l in result.stdout.splitlines():
|
||||
if 'Partition unique GUID' not in l: continue
|
||||
guid = l.replace ('Partition unique GUID: ', '')
|
||||
if guid is None:
|
||||
self.logger.error (f'failed to get UUID of disk "{disk}" part "{partno}"')
|
||||
return None
|
||||
return guid
|
||||
|
||||
def set_partition_uuid(self, device, uuid):
|
||||
(disk, partno) = self.split_device_partition(device)
|
||||
|
||||
subprocess.run(["/usr/sbin/sfdisk", "--part-uuid", disk, str(partno), uuid], check=True, encoding='utf-8')
|
||||
|
||||
def get_partition_type(self, device):
|
||||
"""
|
||||
Returns the type UUID of the partition, if there's a GPT partition table.
|
||||
|
||||
Args:
|
||||
device (str): Block device, eg, /dev/sda3
|
||||
|
||||
Returns:
|
||||
str: UUID
|
||||
"""
|
||||
|
||||
(disk, partno) = self.split_device_partition(device)
|
||||
|
||||
result = subprocess.run(["/usr/sbin/sfdisk", "--part-type", disk, str(partno)], check=True, capture_output=True, encoding='utf-8')
|
||||
return result.stdout.strip()
|
||||
|
||||
def set_partition_type(self, device, uuid):
|
||||
(disk, partno) = self.split_device_partition(device)
|
||||
|
||||
subprocess.run(["/usr/sbin/sfdisk", "--part-type", disk, str(partno), uuid], check=True, encoding='utf-8')
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,544 @@
|
|||
|
||||
import logging
|
||||
import subprocess
|
||||
import os
|
||||
import json
|
||||
import blkid
|
||||
import time
|
||||
|
||||
from ntfs import *
|
||||
|
||||
|
||||
|
||||
# pylint: disable=locally-disabled, line-too-long, logging-fstring-interpolation, too-many-lines
|
||||
|
||||
|
||||
class FilesystemLibrary:
|
||||
def __init__(self, ntfs_implementation = NTFSImplementation.KERNEL):
|
||||
self.logger = logging.getLogger("OpengnsysFilesystemLibrary")
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
self.mounts = {}
|
||||
self.base_mount_path = "/mnt"
|
||||
self.ntfs_implementation = ntfs_implementation
|
||||
|
||||
self.update_mounts()
|
||||
|
||||
def _rmmod(self, module):
|
||||
self.logger.debug("Trying to unload module {module}...")
|
||||
subprocess.run(["/usr/sbin/rmmod", module], check=False)
|
||||
|
||||
def _modprobe(self, module):
|
||||
self.logger.debug("Trying to load module {module}...")
|
||||
subprocess.run(["/usr/sbin/modprobe", module], check=True)
|
||||
|
||||
|
||||
# _parse_mounts
|
||||
def update_mounts(self):
|
||||
"""
|
||||
Update the current mount points by parsing the /proc/mounts file.
|
||||
|
||||
This method reads the /proc/mounts file to gather information about
|
||||
the currently mounted filesystems. It stores this information in a
|
||||
dictionary where the keys are the mount points and the values are
|
||||
dictionaries containing details about each filesystem.
|
||||
|
||||
The details stored for each filesystem include:
|
||||
- device: The device file associated with the filesystem.
|
||||
- mountpoint: The directory where the filesystem is mounted.
|
||||
- type: The type of the filesystem (e.g., ext4, vfat).
|
||||
- options: Mount options associated with the filesystem.
|
||||
- dump_freq: The dump frequency for the filesystem.
|
||||
- passno: The pass number for filesystem checks.
|
||||
|
||||
The method also adds an entry for each mount point with a trailing
|
||||
slash to ensure consistency in accessing the mount points.
|
||||
|
||||
Attributes:
|
||||
mounts (dict): A dictionary where keys are mount points and values
|
||||
are dictionaries containing filesystem details.
|
||||
"""
|
||||
filesystems = {}
|
||||
|
||||
self.logger.debug("Parsing /proc/mounts")
|
||||
|
||||
with open("/proc/mounts", 'r', encoding='utf-8') as mounts:
|
||||
for line in mounts:
|
||||
parts = line.split()
|
||||
data = {}
|
||||
data['device'] = parts[0]
|
||||
data['mountpoint'] = parts[1]
|
||||
data['type'] = parts[2]
|
||||
data['options'] = parts[3]
|
||||
data['dump_freq'] = parts[4]
|
||||
data['passno'] = parts[5]
|
||||
|
||||
filesystems[data["mountpoint"]] = data
|
||||
filesystems[data["mountpoint"] + "/"] = data
|
||||
|
||||
self.mounts = filesystems
|
||||
|
||||
def find_mountpoint(self, device):
|
||||
"""
|
||||
Find the mount point for a given device.
|
||||
|
||||
This method checks if the specified device is currently mounted and returns
|
||||
the corresponding mount point if it is found.
|
||||
|
||||
Args:
|
||||
device (str): The path to the device to check.
|
||||
|
||||
Returns:
|
||||
str or None: The mount point of the device if it is mounted, otherwise None.
|
||||
"""
|
||||
norm = os.path.normpath(device)
|
||||
|
||||
self.logger.debug(f"Checking if {device} is mounted")
|
||||
for mountpoint, mount in self.mounts.items():
|
||||
#self.logger.debug(f"Item: {mount}")
|
||||
#self.logger.debug(f"Checking: " + mount['device'])
|
||||
if mount['device'] == norm:
|
||||
return mountpoint
|
||||
|
||||
return None
|
||||
|
||||
def find_device(self, mountpoint):
|
||||
"""
|
||||
Find the device corresponding to a given mount point.
|
||||
|
||||
Args:
|
||||
mountpoint (str): The mount point to search for.
|
||||
|
||||
Returns:
|
||||
str or None: The device corresponding to the mount point if found,
|
||||
otherwise None.
|
||||
"""
|
||||
self.update_mounts()
|
||||
self.logger.debug("Finding device corresponding to mount point %s", mountpoint)
|
||||
if mountpoint in self.mounts:
|
||||
return self.mounts[mountpoint]['device']
|
||||
else:
|
||||
self.logger.warning("Failed to find mountpoint %s", mountpoint)
|
||||
return None
|
||||
|
||||
def is_mounted(self, device = None, mountpoint = None):
|
||||
def is_mounted(self, device=None, mountpoint=None):
|
||||
"""
|
||||
Check if a device or mountpoint is currently mounted.
|
||||
|
||||
Either checking by device or mountpoint is valid.
|
||||
|
||||
Args:
|
||||
device (str, optional): The device to check if it is mounted.
|
||||
Defaults to None.
|
||||
mountpoint (str, optional): The mountpoint to check if it is mounted.
|
||||
Defaults to None.
|
||||
|
||||
Returns:
|
||||
bool: True if the device is mounted or the mountpoint is in the list
|
||||
of mounts, False otherwise.
|
||||
"""
|
||||
self.update_mounts()
|
||||
if device:
|
||||
return not self.find_mountpoint(device) is None
|
||||
else:
|
||||
return mountpoint in self.mounts
|
||||
|
||||
def unmount(self, device = None, mountpoint = None):
|
||||
def unmount(self, device=None, mountpoint=None):
|
||||
"""
|
||||
Unmounts a filesystem.
|
||||
|
||||
This method unmounts a filesystem either by the device name or the mountpoint.
|
||||
If a device is provided, it finds the corresponding mountpoint and unmounts it.
|
||||
If a mountpoint is provided directly, it unmounts the filesystem at that mountpoint.
|
||||
|
||||
Args:
|
||||
device (str, optional): The device name to unmount. Defaults to None.
|
||||
mountpoint (str, optional): The mountpoint to unmount. Defaults to None.
|
||||
|
||||
Raises:
|
||||
subprocess.CalledProcessError: If the unmount command fails.
|
||||
|
||||
Logs:
|
||||
Debug information about the unmounting process.
|
||||
"""
|
||||
if device:
|
||||
self.logger.debug("Finding mountpoint of %s", device)
|
||||
mountpoint = self.find_mountpoint(device)
|
||||
|
||||
if not mountpoint is None:
|
||||
self.logger.debug(f"Unmounting {mountpoint}")
|
||||
|
||||
done = False
|
||||
start_time = time.time()
|
||||
timeout = 60
|
||||
|
||||
|
||||
while not done and (time.time() - start_time) < timeout:
|
||||
ret = subprocess.run(["/usr/bin/umount", mountpoint], check=False, capture_output=True, encoding='utf-8')
|
||||
if ret.returncode == 0:
|
||||
done=True
|
||||
else:
|
||||
if "target is busy" in ret.stderr:
|
||||
self.logger.debug("Filesystem busy, waiting. %.1f seconds left", timeout - (time.time() - start_time))
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
raise subprocess.CalledProcessError(ret.returncode, ret.args, output=ret.stdout, stderr=ret.stderr)
|
||||
|
||||
# We've unmounted a new filesystem, update our filesystems list
|
||||
self.update_mounts()
|
||||
else:
|
||||
self.logger.debug(f"{device} is not mounted")
|
||||
|
||||
|
||||
def mount(self, device, mountpoint, filesystem = None):
|
||||
"""
|
||||
Mounts a device to a specified mountpoint.
|
||||
|
||||
Parameters:
|
||||
device (str): The device to be mounted (e.g., '/dev/sda1').
|
||||
mountpoint (str): The directory where the device will be mounted.
|
||||
filesystem (str, optional): The type of filesystem to be used (e.g., 'ext4', 'ntfs'). Defaults to None.
|
||||
|
||||
Raises:
|
||||
subprocess.CalledProcessError: If the mount command fails.
|
||||
|
||||
Logs:
|
||||
Debug information about the mounting process, including the mount command, return code, stdout, and stderr.
|
||||
|
||||
Side Effects:
|
||||
Creates the mountpoint directory if it does not exist.
|
||||
Updates the internal list of mounted filesystems.
|
||||
"""
|
||||
self.logger.debug(f"Mounting {device} at {mountpoint}")
|
||||
|
||||
if not os.path.exists(mountpoint):
|
||||
self.logger.debug(f"Creating directory {mountpoint}")
|
||||
os.mkdir(mountpoint)
|
||||
|
||||
mount_cmd = ["/usr/bin/mount"]
|
||||
|
||||
if not filesystem is None:
|
||||
mount_cmd = mount_cmd + ["-t", filesystem]
|
||||
|
||||
mount_cmd = mount_cmd + [device, mountpoint]
|
||||
|
||||
self.logger.debug(f"Mount command: {mount_cmd}")
|
||||
result = subprocess.run(mount_cmd, check=True, capture_output = True)
|
||||
|
||||
self.logger.debug(f"retorno: {result.returncode}")
|
||||
self.logger.debug(f"stdout: {result.stdout}")
|
||||
self.logger.debug(f"stderr: {result.stderr}")
|
||||
|
||||
# We've mounted a new filesystem, update our filesystems list
|
||||
self.update_mounts()
|
||||
|
||||
def ensure_mounted(self, device):
|
||||
"""
|
||||
Ensure that the given device is mounted.
|
||||
|
||||
This method attempts to mount the specified device to a path derived from
|
||||
the base mount path and the device's basename. If the device is of type NTFS,
|
||||
it uses the NTFSLibrary to handle the mounting process. For other filesystem
|
||||
types, it uses a generic mount method.
|
||||
|
||||
Args:
|
||||
device (str): The path to the device that needs to be mounted.
|
||||
|
||||
Returns:
|
||||
str: The path where the device is mounted.
|
||||
|
||||
Logs:
|
||||
- Info: When starting the mounting process.
|
||||
- Debug: Various debug information including the mount path, filesystem type,
|
||||
and success message.
|
||||
|
||||
Raises:
|
||||
OSError: If there is an error creating the mount directory or mounting the device.
|
||||
"""
|
||||
|
||||
self.logger.info("Mounting %s", device)
|
||||
|
||||
self.unmount(device = device)
|
||||
path = os.path.join(self.base_mount_path, os.path.basename(device))
|
||||
|
||||
self.logger.debug(f"Will mount repo at {path}")
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
|
||||
if self.filesystem_type(device) == "ntfs":
|
||||
self.logger.debug("Handing a NTFS filesystem")
|
||||
|
||||
self._modprobe("ntfs3")
|
||||
self.ntfsfix(device)
|
||||
|
||||
ntfs = NTFSLibrary(self.ntfs_implementation)
|
||||
ntfs.mount_filesystem(device, path)
|
||||
self.update_mounts()
|
||||
|
||||
else:
|
||||
self.logger.debug("Handling a non-NTFS filesystem")
|
||||
self.mount(device, path)
|
||||
|
||||
self.logger.debug("Successfully mounted at %s", path)
|
||||
return path
|
||||
|
||||
|
||||
def filesystem_type(self, device = None, mountpoint = None):
|
||||
"""
|
||||
Determine the filesystem type of a given device or mountpoint.
|
||||
|
||||
Args:
|
||||
device (str, optional): The device to probe. If not provided, the device
|
||||
will be determined based on the mountpoint.
|
||||
mountpoint (str, optional): The mountpoint to find the device for. This
|
||||
is used only if the device is not provided.
|
||||
|
||||
Returns:
|
||||
str: The filesystem type of the device.
|
||||
|
||||
Raises:
|
||||
KeyError: If the filesystem type cannot be determined from the probe.
|
||||
|
||||
Logs:
|
||||
Debug: Logs the process of finding the device, probing the device, and
|
||||
the determined filesystem type.
|
||||
"""
|
||||
|
||||
if device is None:
|
||||
self.logger.debug("Finding device for mountpoint %s", mountpoint)
|
||||
device = self.find_device(mountpoint)
|
||||
|
||||
self.logger.debug(f"Probing {device}")
|
||||
|
||||
pr = blkid.Probe()
|
||||
pr.set_device(device)
|
||||
pr.enable_superblocks(True)
|
||||
pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_UUID | blkid.SUBLKS_UUIDRAW | blkid.SUBLKS_LABELRAW)
|
||||
pr.do_safeprobe()
|
||||
|
||||
fstype = pr["TYPE"].decode('utf-8')
|
||||
self.logger.debug(f"FS type is {fstype}")
|
||||
|
||||
return fstype
|
||||
|
||||
def is_filesystem(self, path):
|
||||
"""
|
||||
Check if the given path is a filesystem root.
|
||||
|
||||
Args:
|
||||
path (str): The path to check.
|
||||
|
||||
Returns:
|
||||
bool: True if the path is a filesystem root, False otherwise.
|
||||
"""
|
||||
|
||||
# This is just an alias for better code readability
|
||||
return self.is_mounted(mountpoint = path)
|
||||
|
||||
def create_filesystem(self, fs_type = None, fs_uuid = None, device = None):
|
||||
"""
|
||||
Create a filesystem on the specified device.
|
||||
|
||||
Parameters:
|
||||
fs_type (str): The type of filesystem to create (e.g., 'ntfs', 'ext4', 'xfs', 'btrfs').
|
||||
fs_uuid (str): The UUID to assign to the filesystem.
|
||||
device (str): The device on which to create the filesystem (e.g., '/dev/sda1').
|
||||
|
||||
Raises:
|
||||
RuntimeError: If the filesystem type is not recognized or if the filesystem creation command fails.
|
||||
|
||||
"""
|
||||
|
||||
self.logger.info(f"Creating filesystem {fs_type} with UUID {fs_uuid} in {device}")
|
||||
|
||||
if fs_type == "ntfs" or fs_type == "ntfs3":
|
||||
self.logger.debug("Creating NTFS filesystem")
|
||||
ntfs = NTFSLibrary(self.ntfs_implementation)
|
||||
ntfs.create_filesystem(device, "NTFS")
|
||||
ntfs.modify_uuid(device, fs_uuid)
|
||||
|
||||
else:
|
||||
command = [f"/usr/sbin/mkfs.{fs_type}"]
|
||||
command_args = []
|
||||
|
||||
if fs_type == "ext4" or fs_type == "ext3":
|
||||
command_args = ["-U", fs_uuid, "-F", device]
|
||||
elif fs_type == "xfs":
|
||||
command_args = ["-m", f"uuid={fs_uuid}", "-f", device]
|
||||
elif fs_type == "btrfs":
|
||||
command_args = ["-U", fs_uuid, "-f", device]
|
||||
else:
|
||||
raise RuntimeError(f"Don't know how to create filesystem of type {fs_type}")
|
||||
|
||||
command = command + command_args
|
||||
|
||||
self.logger.debug(f"Creating Linux filesystem of type {fs_type} on {device}, command {command}")
|
||||
result = subprocess.run(command, check = True, capture_output=True)
|
||||
|
||||
self.logger.debug(f"retorno: {result.returncode}")
|
||||
self.logger.debug(f"stdout: {result.stdout}")
|
||||
self.logger.debug(f"stderr: {result.stderr}")
|
||||
|
||||
|
||||
|
||||
def mklostandfound(self, path):
|
||||
"""
|
||||
Recreate the lost+found if necessary.
|
||||
|
||||
When cloning at the root of a filesystem, cleaning the contents
|
||||
removes the lost+found directory. This is a special directory that requires the use of
|
||||
a tool to recreate it.
|
||||
|
||||
It may fail if the filesystem does not need it. We consider this harmless and ignore it.
|
||||
|
||||
The command is entirely skipped on NTFS, as mklost+found may malfunction if run on it,
|
||||
and has no useful purpose.
|
||||
"""
|
||||
if self.is_filesystem(path):
|
||||
if self.filesystem_type(mountpoint=path) == "ntfs":
|
||||
self.logger.debug("Not running mklost+found on NTFS")
|
||||
return
|
||||
|
||||
|
||||
curdir = os.getcwd()
|
||||
result = None
|
||||
|
||||
try:
|
||||
self.logger.debug(f"Re-creating lost+found in {path}")
|
||||
os.chdir(path)
|
||||
result = subprocess.run(["/usr/sbin/mklost+found"], check=True, capture_output=True)
|
||||
except subprocess.SubprocessError as e:
|
||||
self.logger.warning(f"Error running mklost+found: {e}")
|
||||
|
||||
if result:
|
||||
self.logger.debug(f"retorno: {result.returncode}")
|
||||
self.logger.debug(f"stdout: {result.stdout}")
|
||||
self.logger.debug(f"stderr: {result.stderr}")
|
||||
|
||||
os.chdir(curdir)
|
||||
|
||||
def ntfsfix(self, device):
|
||||
"""
|
||||
Run the ntfsfix command on the specified device.
|
||||
|
||||
This method uses the ntfsfix utility to fix common NTFS problems on the given device.
|
||||
|
||||
This allows mounting an unclean NTFS filesystem.
|
||||
|
||||
Args:
|
||||
device (str): The path to the device to be fixed.
|
||||
|
||||
Raises:
|
||||
subprocess.CalledProcessError: If the ntfsfix command fails.
|
||||
"""
|
||||
self.logger.debug(f"Running ntfsfix on {device}")
|
||||
subprocess.run(["/usr/bin/ntfsfix", "-d", device], check=True)
|
||||
|
||||
|
||||
def unload_ntfs(self):
|
||||
"""
|
||||
Unloads the NTFS filesystem module.
|
||||
|
||||
This is a function added as a result of NTFS kernel module troubleshooting,
|
||||
to try to ensure that NTFS code is only active as long as necessary.
|
||||
|
||||
The module is internally loaded as needed, so there's no load_ntfs function.
|
||||
|
||||
It may be removed in the future.
|
||||
|
||||
Raises:
|
||||
RuntimeError: If the module cannot be removed.
|
||||
"""
|
||||
self._rmmod("ntfs3")
|
||||
|
||||
def find_boot_device(self):
|
||||
"""
|
||||
Searches for the EFI boot partition on the system.
|
||||
|
||||
This method scans the system's partitions to locate the EFI boot partition,
|
||||
which is identified by the GUID "C12A7328-F81F-11D2-BA4B-00A0C93EC93B".
|
||||
|
||||
Returns:
|
||||
str: The device node of the EFI partition if found, otherwise None.
|
||||
|
||||
Logs:
|
||||
- Debug messages indicating the progress of the search.
|
||||
- A warning message if the EFI partition is not found.
|
||||
"""
|
||||
disks = []
|
||||
|
||||
self.logger.debug("Looking for EFI partition")
|
||||
with open("/proc/partitions", "r", encoding='utf-8') as partitions_file:
|
||||
line_num=0
|
||||
for line in partitions_file:
|
||||
if line_num >=2:
|
||||
data = line.split()
|
||||
disk = data[3]
|
||||
disks.append(disk)
|
||||
self.logger.debug(f"Disk: {disk}")
|
||||
|
||||
line_num = line_num + 1
|
||||
|
||||
for disk in disks:
|
||||
self.logger.debug("Loading partitions for disk %s", disk)
|
||||
#disk_json_data = subprocess.run(["/usr/sbin/sfdisk", "-J", f"/dev/{disk}"], check=False, capture_output=True)
|
||||
sfdisk_out = subprocess.run(["/usr/sbin/sfdisk", "-J", f"/dev/{disk}"], check=False, capture_output=True)
|
||||
|
||||
if sfdisk_out.returncode == 0:
|
||||
disk_json_data = sfdisk_out.stdout
|
||||
disk_data = json.loads(disk_json_data)
|
||||
|
||||
for part in disk_data["partitiontable"]["partitions"]:
|
||||
self.logger.debug("Checking partition %s", part)
|
||||
if part["type"] == "C12A7328-F81F-11D2-BA4B-00A0C93EC93B":
|
||||
self.logger.debug("EFI partition found at %s", part["node"])
|
||||
return part["node"]
|
||||
else:
|
||||
self.logger.debug("sfdisk returned with code %i, error %s", sfdisk_out.returncode, sfdisk_out.stderr)
|
||||
|
||||
|
||||
self.logger.warning("Failed to find EFI partition!")
|
||||
|
||||
def temp_unmount(self, mountpoint):
|
||||
"""
|
||||
Temporarily unmounts the filesystem at the given mountpoint.
|
||||
|
||||
This method finds the device associated with the specified mountpoint,
|
||||
and returns the information to remount it with temp_remount.
|
||||
|
||||
The purpose of this function is to temporarily unmount a filesystem for
|
||||
actions like fsck, and to mount it back afterwards.
|
||||
|
||||
Args:
|
||||
mountpoint (str): The mountpoint of the filesystem to unmount.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing the information needed to remount the filesystem.
|
||||
"""
|
||||
device = self.find_device(mountpoint)
|
||||
fs = self.filesystem_type(mountpoint = mountpoint)
|
||||
|
||||
data = {"mountpoint" : mountpoint, "device" :device, "filesystem" : fs}
|
||||
|
||||
self.logger.debug("Temporarily unmounting device %s, mounted on %s, fs type %s", mountpoint, device, fs)
|
||||
|
||||
self.unmount(mountpoint = mountpoint)
|
||||
return data
|
||||
|
||||
def temp_remount(self, unmount_data):
|
||||
"""
|
||||
Remounts a filesystem unmounted with temp_unmount
|
||||
|
||||
This method remounts a filesystem using the data provided by temp_unmount
|
||||
|
||||
Args:
|
||||
unmount_data (dict): A dictionary containing the data needed to remount the filesystem.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
|
||||
self.logger.debug("Remounting temporarily unmounted device %s on %s, fs type %s", unmount_data["device"], unmount_data["mountpoint"], unmount_data["filesystem"])
|
||||
self.mount(device = unmount_data["device"], mountpoint=unmount_data["mountpoint"], filesystem=unmount_data["filesystem"])
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env python3
|
||||
import unittest
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
import tarfile
|
||||
import subprocess
|
||||
from shutil import rmtree
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
parent_dir = str(Path(__file__).parent.parent.absolute())
|
||||
sys.path.append(parent_dir)
|
||||
sys.path.append("/opengnsys/installer")
|
||||
print(parent_dir)
|
||||
|
||||
from gitlib import OpengnsysGitLibrary
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class GitTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.logger = logging.getLogger("OpengnsysTest")
|
||||
self.oggit = OpengnsysGitLibrary()
|
||||
|
||||
self.logger.info("setUp()")
|
||||
if not hasattr(self, 'init_complete'):
|
||||
self.init_complete = True
|
||||
def test_init(self):
|
||||
self.assertIsNotNone(self.oggit)
|
||||
def test_acls(self):
|
||||
self.oggit.ogCreateAcl()
|
||||
|
||||
def test_sync_local(self):
|
||||
# self.oggit.ogSyncLocalGitImage()
|
||||
None
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)20s - [%(levelname)5s] - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.info("Inicio del programa")
|
||||
|
||||
unittest.main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,22 @@
|
|||
|
||||
|
||||
def parse_kernel_cmdline():
|
||||
"""Parse the kernel arguments to obtain configuration parameters in Oglive
|
||||
|
||||
OpenGnsys passes data in the kernel arguments, for example:
|
||||
[...] group=Aula_virtual ogrepo=192.168.2.1 oglive=192.168.2.1 [...]
|
||||
|
||||
Returns:
|
||||
dict: Dict of configuration parameters and their values.
|
||||
"""
|
||||
params = {}
|
||||
|
||||
with open("/proc/cmdline", encoding='utf-8') as cmdline:
|
||||
line = cmdline.readline()
|
||||
parts = line.split()
|
||||
for part in parts:
|
||||
if "=" in part:
|
||||
key, value = part.split("=")
|
||||
params[key] = value
|
||||
|
||||
return params
|
|
@ -0,0 +1,111 @@
|
|||
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class NTFSImplementation(Enum):
|
||||
KERNEL = 1
|
||||
NTFS3G = 2
|
||||
|
||||
|
||||
class NTFSLibrary:
|
||||
"""
|
||||
A library for managing NTFS filesystems.
|
||||
|
||||
Attributes:
|
||||
logger (logging.Logger): Logger for the class.
|
||||
implementation (NTFSImplementation): The implementation to use for mounting NTFS filesystems.
|
||||
"""
|
||||
|
||||
def __init__(self, implementation):
|
||||
"""
|
||||
Initializes the instance with the given implementation.
|
||||
|
||||
Args:
|
||||
implementation: The implementation to be used by the instance.
|
||||
|
||||
Attributes:
|
||||
logger (logging.Logger): Logger instance for the class, set to debug level.
|
||||
implementation: The implementation provided during initialization.
|
||||
"""
|
||||
self.logger = logging.getLogger("NTFSLibrary")
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
self.implementation = implementation
|
||||
|
||||
self.logger.debug("Initializing")
|
||||
|
||||
def create_filesystem(self, device, label):
|
||||
"""
|
||||
Creates an NTFS filesystem on the specified device with the given label.
|
||||
|
||||
Args:
|
||||
device (str): The device path where the NTFS filesystem will be created.
|
||||
label (str): The label to assign to the NTFS filesystem.
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
Logs:
|
||||
Logs the creation process with the device and label information.
|
||||
"""
|
||||
self.logger.info(f"Creating NTFS in {device} with label {label}")
|
||||
|
||||
subprocess.run(["/usr/sbin/mkntfs", device, "-Q", "-L", label], check=True)
|
||||
|
||||
|
||||
def mount_filesystem(self, device, mountpoint):
|
||||
"""
|
||||
Mounts a filesystem on the specified mountpoint using the specified NTFS implementation.
|
||||
|
||||
Args:
|
||||
device (str): The device path to be mounted (e.g., '/dev/sda1').
|
||||
mountpoint (str): The directory where the device will be mounted.
|
||||
|
||||
Raises:
|
||||
ValueError: If the NTFS implementation is unknown.
|
||||
|
||||
"""
|
||||
self.logger.info(f"Mounting {device} in {mountpoint} using implementation {self.implementation}")
|
||||
if self.implementation == NTFSImplementation.KERNEL:
|
||||
subprocess.run(["/usr/bin/mount", "-t", "ntfs3", device, mountpoint], check = True)
|
||||
elif self.implementation == NTFSImplementation.NTFS3G:
|
||||
subprocess.run(["/usr/bin/ntfs-3g", device, mountpoint], check = True)
|
||||
else:
|
||||
raise ValueError("Unknown NTFS implementation: {self.implementation}")
|
||||
|
||||
def modify_uuid(self, device, uuid):
|
||||
"""
|
||||
Modify the UUID of an NTFS device.
|
||||
|
||||
This function changes the UUID of the specified NTFS device to the given UUID.
|
||||
It reads the current UUID from the device, logs the change, and writes the new UUID.
|
||||
|
||||
Args:
|
||||
device (str): The path to the NTFS device file.
|
||||
uuid (str): The new UUID to be set, in hexadecimal string format.
|
||||
|
||||
Raises:
|
||||
IOError: If there is an error opening or writing to the device file.
|
||||
"""
|
||||
|
||||
ntfs_uuid_offset = 0x48
|
||||
ntfs_uuid_length = 8
|
||||
|
||||
binary_uuid = bytearray.fromhex(uuid)
|
||||
binary_uuid.reverse()
|
||||
|
||||
self.logger.info(f"Changing UUID on {device} to {uuid}")
|
||||
with open(device, 'r+b') as ntfs_dev:
|
||||
self.logger.debug("Reading %i bytes from offset %i", ntfs_uuid_length, ntfs_uuid_offset)
|
||||
|
||||
ntfs_dev.seek(ntfs_uuid_offset)
|
||||
prev_uuid = bytearray(ntfs_dev.read(ntfs_uuid_length))
|
||||
prev_uuid.reverse()
|
||||
prev_uuid_hex = bytearray.hex(prev_uuid)
|
||||
self.logger.debug(f"Previous UUID: {prev_uuid_hex}")
|
||||
|
||||
self.logger.debug("Writing...")
|
||||
ntfs_dev.seek(ntfs_uuid_offset)
|
||||
ntfs_dev.write(binary_uuid)
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
def _hex_to_bin( hex_str):
|
||||
|
||||
while len(hex_str) != 16:
|
||||
hex_str = "0" + hex_str
|
||||
|
||||
hex_int = int(hex_str, 16)
|
||||
binary = bin(hex_int)[2:].zfill(64)
|
||||
|
||||
return binary
|
||||
|
||||
|
||||
print( _hex_to_bin("0ACA"))
|
|
@ -1,62 +0,0 @@
|
|||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import SystemLib
|
||||
import FileSystemLib
|
||||
import DiskLib
|
||||
import Boot
|
||||
|
||||
#!/usr/bin/env python3
|
||||
# Script de ejemplo para arrancar un sistema operativo instalado.
|
||||
# Nota: se usa como base para el programa de arranque de OpenGnsys Admin.
|
||||
|
||||
def main():
|
||||
prog = os.path.basename(__file__)
|
||||
if len(sys.argv) < 3 or len(sys.argv) > 6:
|
||||
SystemLib.ogRaiseError(1, f"Formato: {prog} ndisco nfilesys [str_kernel str_initrd str_kernelparams]")
|
||||
|
||||
disk = sys.argv[1]
|
||||
filesystem = sys.argv[2]
|
||||
|
||||
try:
|
||||
part = DiskLib.ogDiskToDev(disk, filesystem)
|
||||
except Exception as e:
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
mntdir = FileSystemLib.ogMount(disk, filesystem)
|
||||
except Exception as e:
|
||||
sys.exit(1)
|
||||
|
||||
print("[0] Inicio del proceso de arranque.")
|
||||
|
||||
mount_output = subprocess.getoutput(f"mount | grep -q '{mntdir}.*(rw'")
|
||||
if mount_output:
|
||||
SystemLib.ogEcho("log", "session", "MSG_WARNING: MSG_MOUNTREADONLY")
|
||||
FileSystemLib.ogUnmount(disk, filesystem)
|
||||
FileSystemLib.ogCheckFs(disk, filesystem)
|
||||
|
||||
part = DiskLib.ogDiskToDev(disk, filesystem)
|
||||
os.makedirs(mntdir, exist_ok=True)
|
||||
subprocess.run(["ntfs-3g", "-o", "remove_hiberfile", part, mntdir])
|
||||
SystemLib.ogEcho("log", "session", "Particion desbloqueada")
|
||||
|
||||
FileSystemLib.ogUnmount(disk, filesystem)
|
||||
FileSystemLib.ogMount(disk, filesystem)
|
||||
|
||||
if subprocess.call("which bootOsCustom", shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0:
|
||||
print("[10] Configuración personalizada del inicio.")
|
||||
subprocess.run(["bootOsCustom"] + sys.argv[1:])
|
||||
|
||||
print("[70] Desmontar todos los sistemas de archivos.")
|
||||
subprocess.run(["sync"])
|
||||
for i in range(1, len(DiskLib.ogDiskToDev(disk, filesystem).split())):
|
||||
FileSystemLib.ogUnmountAll(i)
|
||||
|
||||
print("[80] Desmontar cache local.")
|
||||
FileSystemLib.ogUnmount_cache()
|
||||
print("[90] Arrancar sistema operativo.")
|
||||
BootLib.ogBoot(sys.argv[1:])
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,105 +0,0 @@
|
|||
import sys
|
||||
import os
|
||||
import SystemLib
|
||||
import DiskLib
|
||||
import FileSystemLib
|
||||
import NetLib
|
||||
import FileLib
|
||||
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
bootOsCustom
|
||||
@brief Plantilla para script de configuración personalizada de sistema operativo restaurado.
|
||||
@param $1 nº de disco
|
||||
@param $2 nº de partición
|
||||
@warning Renombrar este fichero como "bootOsCustom" para personalizar el script estándar "bootOs".
|
||||
@note La partición a inicializar debe estar montada
|
||||
@version 1.1.1 Soporta varios discos
|
||||
"""
|
||||
|
||||
# CONFIGURAR: Partición de datos de Windows que no queremos ocultar (valor por defecto '0' no oculta nada)
|
||||
DISKDATA = 0
|
||||
PARTDATA = 0
|
||||
|
||||
PROG = os.path.basename(__file__)
|
||||
|
||||
# Control de errores
|
||||
if len(sys.argv) < 3:
|
||||
SystemLib.ogRaiseError(OG_ERR_FORMAT, f"Formato: {PROG} ndisco nparticion")
|
||||
sys.exit(1)
|
||||
|
||||
# Parámetros obligatorios.
|
||||
DISK = sys.argv[1] # Nº de disco.
|
||||
PART = sys.argv[2] # Nº de partición.
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
DEVICE = DiskLib.ogDiskToDev(DISK, PART)
|
||||
if not DEVICE:
|
||||
sys.exit(1)
|
||||
|
||||
# Paso 1: Adaptar el código de ejemplo para arranque personalizado.
|
||||
# Nota: el script "bootOs" llama al script "bootOsCustom" después de realizar la operaciones de inicio estándar y antes de desmontar las particiones e iniciar el sistema operativo.
|
||||
|
||||
MNTDIR = FileSystemLib.ogMount(DISK, PART)
|
||||
if not MNTDIR:
|
||||
sys.exit(1)
|
||||
|
||||
NAME = NetLib.ogGetHostname()
|
||||
NAME = NAME if NAME else "pc"
|
||||
OSTYPE = Inventory.ogGetOsType(DISK, PART)
|
||||
|
||||
if OSTYPE == "Windows":
|
||||
# Mostrar las particiones NTFS de sistema (dos opciones)
|
||||
# Opción 1: SIN ocultar las demás.
|
||||
# SystemLib.ogEcho log session "[40] Mostrar y activar particion de Windows {PART}."
|
||||
# if DiskLib.ogGetPartitionType(DISK, PART) in ["HNTFS", "WIN-RESERV"]:
|
||||
# DiskLib.ogUnhidePartition(DISK, PART)
|
||||
|
||||
# Recorremos los distintos discos
|
||||
# for DEVICE in DiskLib.ogDiskToDev():
|
||||
# d = DiskLib.ogDevToDisk(DEVICE)
|
||||
|
||||
# # Mostrar las particiones NTFS de sistema (dos opciones)
|
||||
# # Opción 2: Ocultamos las demás.
|
||||
# SystemLib.ogEcho log session "[40] Activar particion de Windows {PART} y ocultar las demás."
|
||||
# for i in range(1, DiskLib.ogGetPartitionsNumber(d) + 1):
|
||||
# if (d == DISK and i == PART) or (d == DISKDATA and i == PARTDATA):
|
||||
# if DiskLib.ogGetPartitionType(d, i) in ["HNTFS", "WIN-RESERV"]:
|
||||
# DiskLib.ogUnhidePartition(d, i)
|
||||
# else:
|
||||
# if DiskLib.ogGetPartitionType(d, i) in ["NTFS", "WINDOWS"]:
|
||||
# DiskLib.ogHidePartition(d, i)
|
||||
|
||||
# # Borrar marcas de arrranque de todos los Windows instalados en el disco.
|
||||
# SystemLib.ogEcho log session "[30] Borrar marcas de arrranque de todos los Windows instalados en el disco."
|
||||
# for i in range(1, DiskLib.ogGetPartitionsNumber(d) + 1):
|
||||
# if Inventory.ogGetOsType(d, i) == "Windows":
|
||||
# FileSystemLib.ogMount(d, i)
|
||||
# os.system("rm -f /mnt/*/ogboot.*")
|
||||
|
||||
elif OSTYPE == "Linux":
|
||||
# Modificar el nombre del equipo
|
||||
# SystemLib.ogEcho log session "[30] Asignar nombre Linux \"{NAME}\"."
|
||||
# ETC = FileLib.ogGetPath(DISK, PART, "/etc")
|
||||
# if os.path.isdir(ETC):
|
||||
# with open(os.path.join(ETC, "hostname"), "w") as f:
|
||||
# f.write(NAME)
|
||||
|
||||
# Sustituir UUID o LABEL por su dispositivo en definición de sistema de archivo raíz.
|
||||
# if os.path.isfile(os.path.join(ETC, "fstab")):
|
||||
# SystemLib.ogEcho log session "[40] Actualizar fstab con particion raíz \"{PART}\"."
|
||||
# with open(os.path.join(ETC, "fstab"), "r") as f:
|
||||
# lines = f.readlines()
|
||||
# with open("/tmp/fstab", "w") as f:
|
||||
# for line in lines:
|
||||
# if line.split()[1] == "/" and not line.startswith("#"):
|
||||
# line = line.replace(line.split()[0], PART)
|
||||
# f.write(line)
|
||||
# os.replace("/tmp/fstab", os.path.join(ETC, "fstab"))
|
||||
|
||||
# Cambiar claves usuarios, copiando fichero /etc/passwd
|
||||
# En el servidor el nuevo fichero debe situarse en el directorio del grupo:
|
||||
# /opt/opengnsys/images/groups/nombre_aula
|
||||
# if os.path.isfile(os.path.join(ogGetGroupDir(), "passwd")):
|
||||
# SystemLib.ogEcho log session "[65] Cambiar claves de usuarios."
|
||||
# os.system(f"cp {os.path.join(ogGetGroupDir(), 'passwd')} {os.path.join(MNTDIR, 'etc')}")
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import subprocess
|
||||
import shutil
|
||||
|
||||
|
@ -46,7 +47,7 @@ if not mount_out or not re.search (rf'{mntdir}.*\(rw', mount_out):
|
|||
|
||||
if shutil.which ('bootOsCustom.py'):
|
||||
print ('[10] Configuración personalizada del inicio.')
|
||||
subprocess.run ([f'{ogGlobals.OGSCRIPTS}/bootOsCustom.py'])
|
||||
subprocess.run ([f'{ogGlobals.OGSCRIPTS}/bootOsCustom.py', disk, par])
|
||||
|
||||
print ('[70] Desmontar todos los sistemas de archivos.')
|
||||
subprocess.run (['sync'])
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
#!/bin/bash
|
||||
#/**
|
||||
# bootOsCustom
|
||||
#@brief Plantilla para script de configuración personalizada de sistema operativo restaurado.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@warning Renombrar este fichero como "bootOsCustom" para personalizar el script estándar "bootOs".
|
||||
#@note La partición a inicializar debe estar montada
|
||||
#@version 1.1.1 Soporta varios discos
|
||||
#@date 2019/08/26
|
||||
#**/
|
||||
# CONFIGURAR: Partición de datos de Windows que no queremos ocultar (valor por defecto '0' no oculta nada)
|
||||
DISKDATA=0
|
||||
PARTDATA=0
|
||||
|
||||
PROG="$(basename $0)"
|
||||
# Control de errores
|
||||
if [ $# -lt 2 ]; then
|
||||
ogRaiseError $OG_ERR_FORMAT "Formato: $PROG ndisco nparticion"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Parámetros obligatorios.
|
||||
DISK="$1" # Nº de disco.
|
||||
PART="$2" # Nº de partición.
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
DEVICE=$(ogDiskToDev "$DISK" "$PART") || exit $?
|
||||
|
||||
# Paso 1: Adaptar el código de ejemplo para arranque personalizado.
|
||||
# Nota: el script "bootOs" llama al script "bootOsCustom" después de realizar la operaciones de inicio estándar y antes de desmontar las particiones e iniciar el sistema operativo.
|
||||
|
||||
|
||||
MNTDIR=$(ogMount $DISK $PART) || exit $?
|
||||
NAME="$(ogGetHostname)"
|
||||
NAME=${NAME:-"pc"}
|
||||
OSTYPE=$(ogGetOsType $DISK $PART)
|
||||
|
||||
case "$OSTYPE" in
|
||||
Windows)
|
||||
## Mostrar las particiones NTFS de sistema (dos opciones)
|
||||
## Opción 1: SIN ocultar las demás.
|
||||
#ogEcho log session "[40] Mostrar y activar particion de Windows $PART."
|
||||
#[ $(ogGetPartitionType $DISK $PART) == "HNTFS" -o $(ogGetPartitionType $DISK $PART) == "WIN-RESERV" ] && ogUnhidePartition $DISK $PART
|
||||
|
||||
## Recorremos los distintos discos
|
||||
#for DEVICE in $(ogDiskToDev); do
|
||||
# d=$(ogDevToDisk $DEVICE)
|
||||
|
||||
# ## Mostrar las particiones NTFS de sistema (dos opciones)
|
||||
# ## Opción 2: Ocultamos las demás.
|
||||
# ogEcho log session "[40] Activar particion de Windows $PART y ocultar las demás."
|
||||
# for (( i=1; i<=$(ogGetPartitionsNumber $d); i++ )); do
|
||||
# if [ $d == $DISK -a $i == $PART ] || [ $d == $DISKDATA -a $i == $PARTDATA ]; then
|
||||
# [ $(ogGetPartitionType $d $i) == "HNTFS" -o $(ogGetPartitionType $d $i) == "WIN-RESERV" ] && ogUnhidePartition $d $i
|
||||
# else
|
||||
# [ "$(ogGetPartitionType $d $i)" == NTFS -o "$(ogGetPartitionType $d $i)" == "WINDOWS" ] && ogHidePartition $d $i
|
||||
# fi
|
||||
# done
|
||||
|
||||
# ## Borrar marcas de arrranque de todos los Windows instalados en el disco.
|
||||
# ogEcho log session "[30] Borrar marcas de arrranque de todos los Windows instalados en el disco."
|
||||
# for (( i=1; i<=$(ogGetPartitionsNumber $d); i++ )); do
|
||||
# [ "$(ogGetOsType $d $i)" == "Windows" ] && ogMount $d $i &>/dev/null
|
||||
# done
|
||||
# rm -f /mnt/*/ogboot.*
|
||||
|
||||
#done
|
||||
;;
|
||||
Linux)
|
||||
## Modificar el nombre del equipo
|
||||
#ogEcho log session "[30] Asignar nombre Linux \"$NAME\"."
|
||||
#ETC=$(ogGetPath $DISK $PART /etc)
|
||||
#[ -d "$ETC" ] && echo "$NAME" >$ETC/hostname 2>/dev/null
|
||||
|
||||
## Sustituir UUID o LABEL por su dispositivo en definición de sistema de archivo raíz.
|
||||
#if [ -f "$ETC/fstab" ]; then
|
||||
# ogEcho log session "[40] Actualizar fstab con particion raíz \"$PART\"."
|
||||
# awk -v P="$PART " '{ if ($2=="/" && $1!~/^#/) {sub(/^.*$/, P, $1)}
|
||||
# print }' $ETC/fstab >/tmp/fstab
|
||||
# mv /tmp/fstab $ETC/fstab
|
||||
#fi
|
||||
|
||||
## Cambiar claves usuarios, copiando fichero /etc/passwd
|
||||
## En el servidor el nuevo fichero debe situarse en el directorio del grupo:
|
||||
## /opt/opengnsys/images/groups/nombre_aula
|
||||
#if [ -r $(ogGetGroupDir)/passwd ]; then
|
||||
# ogEcho log session "[65] Cambiar claves de usuarios."
|
||||
# cp $(ogGetGroupDir)/passwd $MNTDIR/etc
|
||||
#fi
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
#/**
|
||||
# bootOsCustomTemplate.py
|
||||
#@brief Plantilla para script de configuración personalizada de sistema operativo restaurado.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@warning Renombrar este fichero como "bootOsCustom.py" para personalizar el script estándar "bootOs.py".
|
||||
#@note La partición a inicializar debe estar montada
|
||||
#**/
|
||||
|
||||
import sys
|
||||
|
||||
import ogGlobals
|
||||
from SystemLib import ogRaiseError, ogEcho
|
||||
from DiskLib import ogDiskToDev
|
||||
from FileSystemLib import ogMount
|
||||
from NetLib import ogGetHostname
|
||||
from InventoryLib import ogGetOsType
|
||||
|
||||
prog = sys.argv[0]
|
||||
|
||||
# Control de errores
|
||||
if len (sys.argv) < 3:
|
||||
ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Formato: {prog} ndisco nfilesys')
|
||||
sys.exit (1)
|
||||
disk, par = sys.argv[1:]
|
||||
|
||||
device = ogDiskToDev (disk, par)
|
||||
if not device: sys.exit (1)
|
||||
|
||||
# Nota: el script "bootOs.py" llama al script "bootOsCustom.py" después de realizar la operaciones de inicio estándar y antes de desmontar las particiones e iniciar el sistema operativo.
|
||||
|
||||
mntdir = ogMount (disk, par)
|
||||
if not mntdir: sys.exit (1)
|
||||
name = ogGetHostname()
|
||||
if not name: name = 'pc'
|
||||
ostype = ogGetOsType (disk, par)
|
||||
|
||||
if 'Windows' == ostype:
|
||||
pass
|
||||
elif 'Linux' == ostype:
|
||||
pass
|
|
@ -1,78 +0,0 @@
|
|||
import sys
|
||||
import subprocess
|
||||
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
configureOsCustom
|
||||
@brief Plantilla para script de configuración personalizada de sistema operativo restaurado.
|
||||
@param $1 nº de disco
|
||||
@param $2 nº de partición
|
||||
@param $3 Repositorio: CACHE, REPO o dirección IP (opcional)
|
||||
@param $4 Nombre canónico de la imagen sin extensión (opcional)
|
||||
@warning Renombrar este fichero como "configureOsCustom" para sustituir al script estándar "configureOs".
|
||||
@note Los parámetros disco y partición son obligatorios y opcionalmente puede recibir también el repositorio y la imagen usada para en el despliegue.
|
||||
"""
|
||||
|
||||
def main():
|
||||
if len(sys.argv) not in [3, 5]:
|
||||
og_raise_error("OG_ERR_FORMAT", "Usage: configureOsCustom int_ndisc int_npart [str_repo str_imgname]")
|
||||
|
||||
disk = sys.argv[1]
|
||||
part = sys.argv[2]
|
||||
repo = sys.argv[3].upper() if len(sys.argv) > 3 else None
|
||||
imgname = sys.argv[4] if len(sys.argv) > 4 else None
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
|
||||
# Paso 1: Adaptar el código de ejemplo para postconfiguración personalizada.
|
||||
configure_os(disk, part)
|
||||
|
||||
ostype = og_get_os_type(disk, part)
|
||||
if ostype == "Windows":
|
||||
# Postconfiguración de Windows.
|
||||
pass
|
||||
# Descomentar la siguiente línea para cambiar usuario de inicio.
|
||||
# subprocess.run(["ogSetWinlogonUser", disk, part, " "], check=True)
|
||||
# OPCIONAL: desactivar el chkdisk de windows tras la restauracion. Requiere configuracion previa en el engine.cfg
|
||||
# subprocess.run(["ogLoadHiveWindows", disk, part], check=True)
|
||||
# subprocess.run(["ogSetWindowsChkdisk", "OGWINCHKDISK"], check=True)
|
||||
# subprocess.run(["ogUpdateHiveWindows"], check=True)
|
||||
elif ostype == "Linux":
|
||||
# Postconfiguración de GNU/Linux.
|
||||
pass
|
||||
# OPCIONAL Para UEFI: cambia el UUID de la partición (para tener dos linux en un equipo)
|
||||
# subprocess.run(["ogUuidChange", disk, part], check=True)
|
||||
# OPCIONAL Limpiar dispositivos reconocidos previamente
|
||||
# subprocess.run(["ogCleanLinuxDevices", disk, part], check=True)
|
||||
# Instala (no configura) el codigo de arranque del Grub en la partición (no lo configura, se mantiene el original de la imagen)
|
||||
# subprocess.run(["ogGrubInstallPartition", disk, part], check=True)
|
||||
# OPCIONAL: instala y configura el codigo de arranque del Grub en el MBR (no lo configura, se mantiene el original de la imagen)
|
||||
# subprocess.run(["ogGrubInstallMbr", disk, part], check=True)
|
||||
# OPCIONAL: Instala y configura el Grub en el MBR y lo autoconfigura, entradas para los sistemas operativos, además al linux restaurado le añade los parámetros indicados.
|
||||
# subprocess.run(["ogGrubInstallMbr", disk, part, "TRUE", "irqpoll pci=noacpi noresume quiet splash"], check=True)
|
||||
elif ostype == "MacOS":
|
||||
# Postconfiguración de Mac OS X.
|
||||
with open(f"/mnt/{disk}/{part}/var/root/postconfd.sh", "a") as f:
|
||||
f.write("""
|
||||
### NOTA: descomentar las opciones deseadas.
|
||||
# Activar Journaling en HFS+ (no usar si el cliente continua en OpenGnsys).
|
||||
#diskutil enableJournal disk$[$1-1]s$2
|
||||
# Pedir usuario y clave en pantalla de conexión.
|
||||
#defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME -bool yes
|
||||
# No mostrar botón de cambio rápido de usuario.
|
||||
#defaults write /Library/Preferences/.GlobalPreferences MultipleSessionEnabled -bool NO
|
||||
# Bloquear escritorio, fondo, dock, etc del usuario "usuario".
|
||||
#chflags uchange /Users/usuario/Library/Preferences/com.apple.desktop.plist
|
||||
#chflags uchange /Users/usuario/Library/Preferences/com.apple.dock.plist
|
||||
#chflags uchange /Users/usuario/Desktop
|
||||
# Añadir usuario "usuario" a la lista de desarrolladores de Xcode.
|
||||
#DevToolsSecurity --enable
|
||||
#dscl . -append /Groups/_developer GroupMembership usuario
|
||||
# Bajar volumen (valor entre 0 y 7).
|
||||
#osascript -e 'set volume 1'
|
||||
""")
|
||||
|
||||
# Paso 2: Incluir código genérico de postconfiguración.
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -31,9 +31,8 @@ import FileLib
|
|||
## [ -f $DEVICECFG ] && source $DEVICECFG
|
||||
## pero luego no utiliza ninguna de las variables definidas en el archivo...
|
||||
|
||||
disk = sys.argv[1]
|
||||
par = sys.argv[2]
|
||||
imgname = sys.argv[3]
|
||||
disk, par, *other = sys.argv[1:]
|
||||
imgname = other[0] if len (other) > 0 else ''
|
||||
|
||||
# Si el sistema de archivos no esta extendido, ampliarlo al tamaño de su partición.
|
||||
partsize = DiskLib.ogGetPartitionSize (disk, par)
|
||||
|
@ -81,6 +80,14 @@ if 'Windows' == ostype:
|
|||
PostConfLib.ogUninstallWindowsClient (disk, par, 'postconf.cmd')
|
||||
|
||||
elif 'Linux' == ostype:
|
||||
# Marca para arranque.
|
||||
boot_mark_file = f'{mntdir}/Part-{int(disk):02d}-{int(par):02d}'
|
||||
try:
|
||||
open (boot_mark_file, 'w').close()
|
||||
except Exception as e:
|
||||
print (f'Failed to create boot mark: {e}')
|
||||
sys.exit (1)
|
||||
|
||||
BootLib.ogConfigureFstab (disk, par) # Configuro fstab: particion de Swap y si es UEFI además la partición EFI.
|
||||
if InventoryLib.ogIsEfiActive(): # Si es UEFI instalo Grub en la partición EFI
|
||||
esp = DiskLib.ogGetEsp()
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
#!/bin/bash
|
||||
#/**
|
||||
# configureOsCustom
|
||||
#@brief Plantilla para scirpt de configuracion personalizada de sistema operativo restaurado.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@param $3 Repositorio: CACHE, REPO o dirección IP (opcional)
|
||||
#@param $4 Nombre canónico de la imagen sin extensión (opcional)
|
||||
#@warning Renombrar este fichero como "configureOsCustom" para sustituir al script estándar "configureOs".
|
||||
#@note Los parámetros disco y partición son obligatorios y opcionalmente puede recibir también el repositorio y la imagen usada para en el despliegue.
|
||||
#**/
|
||||
|
||||
|
||||
# Control de parámetros.
|
||||
[ $# -eq 2 -o $# -eq 4 ] || ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: configureOsCustom int_ndisc int_npart [str_repo str_imgname]" || exit $?
|
||||
|
||||
# Parámetros obligatorios.
|
||||
DISK="$1" # Nº de disco.
|
||||
PART="$2" # Nº de partición.
|
||||
# Parámetros opcionales.
|
||||
REPO="${3^^}" # Repositorio (en mayúsculas).
|
||||
IMGNAME="$4" # Nombre canónico de imagen (sin extensión).
|
||||
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
|
||||
# Paso 1: Adaptar el código de ejemplo para postconfiguración personalizada.
|
||||
# Nota: incluye llamada al script "configureOs" para realizar previamente una configuración estándar.
|
||||
|
||||
# Configurarción típica.
|
||||
configureOs "$1" "$2"
|
||||
# Postconfiguración personalizada para cada tipo de sistema operativo.
|
||||
OSTYPE="$(ogGetOsType $1 $2)"
|
||||
case "$OSTYPE" in
|
||||
Windows) # Postconfiguración de Windows.
|
||||
# Descomentar la siguiente línea para cambiar usuario de inicio.
|
||||
#ogSetWinlogonUser $1 $2 " "
|
||||
# OPCIONAL: desactivar el chkdisk de windows tras la restauracion. Requiere configuracion previa en el engine.cfg
|
||||
#ogLoadHiveWindows $1 $2; ogSetWindowsChkdisk $OGWINCHKDISK; ogUpdateHiveWindows
|
||||
;;
|
||||
Linux) # Postconfiguración de GNU/Linux.
|
||||
##OPCIONAL Para UEFI: cambia el UUID de la partición (para tener dos linux en un equipo)
|
||||
#ogUuidChange $DISK $PART
|
||||
##OPCIONAL Limpiar dispositivos reconocidos previamente
|
||||
#ogCleanLinuxDevices $1 $2
|
||||
## Instala (no configura) el codigo de arranque del Grub en la partición (no lo configura, se mantiene el original de la imagen)
|
||||
#ogGrubInstallPartition $1 $2
|
||||
## OPCIONAL: instala y configura el codigo de arranque del Grub en el MBR (no lo configura, se mantiene el original de la imagen)
|
||||
#ogGrubInstallMbr $1 $2
|
||||
## OPCIONAL: Instala y configura el Grub en el MBR y lo autoconfigura, entradas para los sitemas operativos, ademas al linux restaurado le añade los parmetros indicados.
|
||||
#ogGrubInstallMbr $1 $2 TRUE "irqpoll pci=noacpi noresume quiet splash"
|
||||
;;
|
||||
MacOS) # Postconfiguración de Mac OS X.
|
||||
# Programa de inicio que será ejecutado en el arranque de Mac OS X.
|
||||
# NOTA: no modificar la línea siguiente.
|
||||
cat << EOT | sed -n -e '/rm -f /r /dev/stdin' -e 1x -e '2,${x;p}' -e '${x;p}' $MNTDIR/var/root/postconfd.sh
|
||||
|
||||
### NOTA: descomentar las opciones deseadas.
|
||||
# Activar Journaling en HFS+ (no usar si el cliente continua en OpenGnsys).
|
||||
#diskutil enableJournal disk$[$1-1]s$2
|
||||
# Pedir usuario y clave en pantalla de conexión.
|
||||
#defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME -bool yes
|
||||
# No mostrar botón de cambio rápido de usuario.
|
||||
#defaults write /Library/Preferences/.GlobalPreferences MultipleSessionEnabled -bool NO
|
||||
# Bloquear escritorio, fondo, dock, etc del usuario "usuario".
|
||||
#chflags uchange /Users/usuario/Library/Preferences/com.apple.desktop.plist
|
||||
#chflags uchange /Users/usuario/Library/Preferences/com.apple.dock.plist
|
||||
#chflags uchange /Users/usuario/Desktop
|
||||
# Añadir usuario "usuario" a la lista de desarrolladores de Xcode.
|
||||
#DevToolsSecurity --enable
|
||||
#dscl . -append /Groups/_developer GroupMembership usuario
|
||||
# Bajar volumen (valor entre 0 y 7).
|
||||
#osascript -e 'set volume 1'
|
||||
|
||||
EOT
|
||||
# NOTA: no modificar la línea anterior.
|
||||
;;
|
||||
esac
|
||||
|
||||
# Paso 2: Incluir código genérico de postconfiguración.
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/python3
|
||||
#/**
|
||||
# configureOsCustom
|
||||
#@brief Plantilla para scirpt de configuracion personalizada de sistema operativo restaurado.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@param $3 Repositorio: CACHE, REPO o dirección IP (opcional)
|
||||
#@param $4 Nombre canónico de la imagen sin extensión (opcional)
|
||||
#@warning Renombrar este fichero como "configureOsCustom" para sustituir al script estándar "configureOs".
|
||||
#@note Los parámetros disco y partición son obligatorios y opcionalmente puede recibir también el repositorio y la imagen usada para en el despliegue.
|
||||
#**/
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
import ogGlobals
|
||||
from SystemLib import ogRaiseError, ogEcho
|
||||
from InventoryLib import ogGetOsType
|
||||
|
||||
prog = sys.argv[0]
|
||||
|
||||
if len (sys.argv) not in [3, 5]:
|
||||
ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT} configureOsCustom int_ndisc int_npart [str_repo str_imgname]')
|
||||
sys.exit (1)
|
||||
disk, par, *other = sys.argv[1:]
|
||||
repo = other[0].upper() if len (other) > 0 else ''
|
||||
imgname = other[1] if len (other) > 1 else ''
|
||||
|
||||
# Nota: incluye llamada al script "configureOs" para realizar previamente una configuración estándar.
|
||||
subprocess.run ([f'configureOs.py', disk, par, imgname])
|
||||
|
||||
ostype = ogGetOsType (disk, par)
|
||||
if 'Windows' == ostype:
|
||||
pass
|
||||
elif 'Linux' == ostype:
|
||||
pass
|
||||
elif 'MacOS' == ostype:
|
||||
pass
|
|
@ -63,7 +63,7 @@ def main (disk, par, repo, imgname):
|
|||
# Clear temporary file used as log track by httpdlog
|
||||
# Limpia los ficheros temporales usados como log de seguimiento para httpdlog
|
||||
# salvo si es llamado desde createImageCustom
|
||||
if 'createImageCustom' != SystemLib.ogGetCaller():
|
||||
if 'createImageCustom.py' != SystemLib.ogGetCaller():
|
||||
with open (ogGlobals.OGLOGSESSION, 'w') as fd: fd.write ('')
|
||||
with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('')
|
||||
with open (f'{ogGlobals.OGLOGCOMMAND}.tmp', 'w') as fd: fd.write ('')
|
||||
|
@ -140,7 +140,7 @@ def main (disk, par, repo, imgname):
|
|||
# Evaluar variable de engine.cfg para reducir el sistema de archivos en la creacion
|
||||
if ogGlobals.IMGREDUCE:
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogReduceFs}')
|
||||
FileSystemLib.ogReduceFs (disk, par)
|
||||
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogReduceFs}', disk, par])
|
||||
newsizefs = FileSystemLib.ogGetFsSize (disk, par)
|
||||
timeaux = time.time() - time1
|
||||
SystemLib.ogEcho (['log', 'session'], None, f' {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} ( {newsizefs} KB ) : {int (timeaux/60)}m {int (timeaux%60)}s')
|
||||
|
@ -157,7 +157,7 @@ def main (disk, par, repo, imgname):
|
|||
with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('')
|
||||
time2 = time.time()
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[40] {ogGlobals.lang.MSG_HELP_ogCreateImage} : ogCreateImage {disk} {par} {repo} {imgname} {ogGlobals.IMGPROG} {ogGlobals.IMGCOMP}')
|
||||
if not ImageLib.ogCreateImage (disk, par, repo, f'/{imgname}', ogGlobals.IMGPROG, ogGlobals.IMGCOMP):
|
||||
if not SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCreateImage}', disk, par, repo, f'/{imgname}', ogGlobals.IMGPROG, ogGlobals.IMGCOMP]):
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, 'ogCreateImage')
|
||||
sys.exit (1)
|
||||
resumecreateimage = subprocess.run (['grep', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#!/bin/bash
|
||||
#/**
|
||||
# createImageCustom
|
||||
#@brief Plantilla para scirpt de creación personalizada de imagen.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@param $3 Repositorio: CACHE, REPO o dirección IP
|
||||
#@param $4 Nombre canónico de la imagen sin extensión
|
||||
#@warning Renombrar este fichero como "createImageCustom" para sustituir al script estándar "createImage".
|
||||
#**/
|
||||
|
||||
|
||||
# Control de parámetros.
|
||||
[ $# -eq 4 ] || ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: createImageCustom int_ndisc int_npart str_repo str_imgname" || exit $?
|
||||
|
||||
# Toma de parámetros.
|
||||
DISK="$1" # Nº de disco.
|
||||
PART="$2" # Nº de partición.
|
||||
REPO="${3^^}" # Repositorio (en mayúsculas).
|
||||
IMGNAME="$4" # Nombre canónico de imagen (sin extensión).
|
||||
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
|
||||
|
||||
# Paso 1: Añadir aquí el código para el proceso previo antes de la creación de la imagen en el equipo modelo (opcional).
|
||||
|
||||
|
||||
# Paso 2: Sustituir, si se desea, la llamada al proceso estándar de creación de imagen por código personalizado.
|
||||
createImage "$@"
|
||||
|
||||
|
||||
# Paso 3: Añadir aquí el código para el proceso posterior tras la creación de la imagen (opcional).
|
||||
|
||||
|
|
@ -1,27 +1,25 @@
|
|||
#!/usr/bin/python3
|
||||
#/**
|
||||
# createImageCustom
|
||||
#@brief Plantilla para scirpt de creación personalizada de imagen.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@param $3 Repositorio: CACHE, REPO o dirección IP
|
||||
#@param $4 Nombre canónico de la imagen sin extensión
|
||||
#@warning Renombrar este fichero como "createImageCustom" para sustituir al script estándar "createImage".
|
||||
#**/
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
#!/usr/bin/env python3
|
||||
import ogGlobals
|
||||
from SystemLib import ogRaiseError
|
||||
|
||||
def main():
|
||||
# Control de parámetros.
|
||||
if len(sys.argv) != 5:
|
||||
ogRaiseError(os.getenv('OG_ERR_FORMAT', 1), "createImageCustom int_ndisc int_npart str_repo str_imgname")
|
||||
|
||||
# Toma de parámetros.
|
||||
DISK = sys.argv[1] # Nº de disco.
|
||||
PART = sys.argv[2] # Nº de partición.
|
||||
REPO = sys.argv[3].upper() # Repositorio (en mayúsculas).
|
||||
IMGNAME = sys.argv[4] # Nombre canónico de imagen (sin extensión).
|
||||
# Control de parámetros.
|
||||
if len (sys.argv) != 5:
|
||||
ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT} createImageCustom int_ndisc int_npart str_repo str_imgname')
|
||||
sys.exit (1)
|
||||
disk, par, repo, imgname = sys.argv[1:]
|
||||
repo = repo.upper()
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
|
||||
# Paso 1: Añadir aquí el código para el proceso previo antes de la creación de la imagen en el equipo modelo (opcional).
|
||||
|
||||
# Paso 2: Sustituir, si se desea, la llamada al proceso estándar de creación de imagen por código personalizado.
|
||||
createImage(DISK, PART, REPO, IMGNAME)
|
||||
|
||||
# Paso 3: Añadir aquí el código para el proceso posterior tras la creación de la imagen (opcional).
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
subprocess.run (['createImage.py', disk, par, repo, imgname])
|
||||
|
|
|
@ -138,22 +138,19 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''):
|
|||
params = [repo, imgname, disk, par, proto, protoopt]
|
||||
|
||||
# Si existe, ejecuta script personalizado "restoreImageCustom"; si no, llama al genérico "restoreImage".
|
||||
if shutil.which ('restoreImageCustom'):
|
||||
if shutil.which ('restoreImageCustom.py'):
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImageCustom {params}')
|
||||
retval = subprocess.run (['restoreImageCustom'] + params).returncode
|
||||
retval = subprocess.run (['restoreImageCustom.py'] + params).returncode
|
||||
else:
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImage {params}')
|
||||
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.
|
||||
resumerestoreimage = subprocess.run (['grep', '--max-count', '1', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout
|
||||
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {resumerestoreimage} ')
|
||||
# Si la transferencia ha dado error me salgo.
|
||||
if retval:
|
||||
if retval: ## subprocess.run failed
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[60] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: error: returncode not 0 but "{retval}"')
|
||||
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_IMAGE, f'{repo} {imgname}')
|
||||
if SystemLib.ogGetCaller() != 'EjecutarScript':
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {ogGlobals.OG_ERR_IMAGE}')
|
||||
|
@ -163,9 +160,9 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''):
|
|||
SystemLib.ogEcho (['log', 'session'], None, f' [ ] {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} : {int (time3/60)}m {int (time3%60)}s')
|
||||
|
||||
# Si existe, ejecuta script personalizado de postconfiguración "configureOsCustom"; si no, llama al genérico "configureOs".
|
||||
if shutil.which ('configureOsCustom'):
|
||||
if shutil.which ('configureOsCustom.py'):
|
||||
SystemLib.ogEcho (['log', 'session'], None, '[90] configureOsCustom')
|
||||
subprocess.run (['configureOsCustom', disk, par, repo, imgname])
|
||||
subprocess.run (['configureOsCustom.py', disk, par, repo, imgname])
|
||||
else:
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[90] {ogGlobals.lang.MSG_SCRIPTS_OS_CONFIGURE}')
|
||||
subprocess.run (['configureOs.py', disk, par, imgname])
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
import ogGlobals
|
||||
import SystemLib
|
||||
|
|
|
@ -59,9 +59,9 @@ repo = repo.upper()
|
|||
# Si MCASTWAIT menos que tiempo de espera del servidor lo aumento
|
||||
MCASTWAIT = ogGlobals.MCASTWAIT
|
||||
if ':' in protoopt:
|
||||
port, wait = protoopt.split (':')
|
||||
port, method, mcastip, speed, nclients, wait = protoopt.split (':')
|
||||
else:
|
||||
port, wait = ('', '')
|
||||
port, method, mcastip, speed, nclients, wait = ('', '', '', '', '', '')
|
||||
if proto.startswith ('MULTICAST') and re.match (r'^-?\d+$', wait):
|
||||
if int (MCASTWAIT or 0) < int (wait):
|
||||
MCASTWAIT = int (wait) + 5
|
||||
|
@ -76,7 +76,7 @@ if StringLib.ogCheckIpAddress (repo) or 'REPO' == repo:
|
|||
if not NetLib.ogChangeRepo (repo):
|
||||
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repo)
|
||||
sys.exit (1)
|
||||
REPO = 'REPO'
|
||||
repo = 'REPO'
|
||||
|
||||
# Comprobar que existe la imagen del origen.
|
||||
imgfile = FileLib.ogGetPath (repo, f'{imgname}.{imgtype}')
|
||||
|
@ -90,7 +90,7 @@ if not imgfile or not imgdir:
|
|||
retval = 0
|
||||
if proto in ['UNICAST', 'UNICAST-DIRECT']:
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[40] ogRestoreImage {repo} {imgname} {disk} {par} UNICAST')
|
||||
retval = SystemLib.ogExecAndLog ('command', ImageLib.ogRestoreImage, repo, imgname, disk, par)
|
||||
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogRestoreImage', repo, imgname, disk, par])
|
||||
elif proto in ['MULTICAST', 'MULTICAST-DIRECT']:
|
||||
tool = ImageLib.ogGetImageProgram ('REPO', imgname)
|
||||
if not tool:
|
||||
|
@ -103,9 +103,7 @@ elif proto in ['MULTICAST', 'MULTICAST-DIRECT']:
|
|||
sys.exit (1)
|
||||
|
||||
SystemLib.ogEcho (['log', 'session'], None, f'[40] ogMcastReceiverPartition {disk} {par} {port} {tool} {compress}')
|
||||
if not ProtocolLib.ogMcastRequest (f'{imgname}.img', protoopt):
|
||||
sys.exit (1)
|
||||
retval = SystemLib.ogExecAndLog ('command', ProtocolLib.ogMcastReceiverPartition, disk, par, port, tool, compress)
|
||||
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogMcastReceiverPartition', disk, par, port, tool, compress])
|
||||
else:
|
||||
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} REPO|CACHE imagen ndisco nparticion [ UNICAST|MULTICAST opciones protocolo]')
|
||||
sys.exit (1)
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
#!/bin/bash
|
||||
#/**
|
||||
# restoreImageCustom
|
||||
#@brief Plantilla para scirpt de rastauración personalizada de imagen.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@param $3 Repositorio: CACHE, REPO o dirección IP
|
||||
#@param $4 Nombre canónico de la imagen sin extensión
|
||||
#@warning Renombrar este fichero como "restoreImageCustom" para sustituir al script estándar "restoreImage".
|
||||
#**/
|
||||
|
||||
|
||||
# Control de parámetros.
|
||||
[ $# -ge 4 -a $# -le 6 ] || ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: restoreImageCustom str_repo str_imagen int_ndisco int_npart [ str_proto [\"str_opciones\"] ]" || exit $?
|
||||
|
||||
# Toma de parámetros.
|
||||
REPO="${1^^}" # Repositorio (en mayúsculas).
|
||||
IMGNAME="$2" # Nombre canónico de imagen (sin extensión).
|
||||
DISK="$3" # Nº de disco.
|
||||
PART="$4" # Nº de partición.
|
||||
PROTO="${5^^}" # Protocolo de comunicaciones (por defecto, UNICAST).
|
||||
PROTO=${PROTO:-"UNICAST"}
|
||||
PROTOOPT="$6" # Opciones del protocolo separadas por ":" (opcional).
|
||||
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
|
||||
|
||||
# Paso 1: Añadir aquí el código para el proceso previo antes de la restauración de la imagen en los equipos (opcional).
|
||||
|
||||
|
||||
# Paso 2: Sustituir, si se desea, la llamada al proceso estándar de restauración de imagen por código personalizado.
|
||||
restoreImage "$@"
|
||||
|
||||
|
||||
# Aviso: editar la plantilla "configureOsCustom" para añadir el código personalizado para el proceso de postconfiguración de los clientes (no incluir aquí dicho código).
|
||||
|
|
@ -1,35 +1,28 @@
|
|||
import sys
|
||||
import os
|
||||
import SystemLib
|
||||
#!/usr/bin/python3
|
||||
#/**
|
||||
# restoreImageCustom
|
||||
#@brief Plantilla para scirpt de rastauración personalizada de imagen.
|
||||
#@param $1 nº de disco
|
||||
#@param $2 nº de partición
|
||||
#@param $3 Repositorio: CACHE, REPO o dirección IP
|
||||
#@param $4 Nombre canónico de la imagen sin extensión
|
||||
#@warning Renombrar este fichero como "restoreImageCustom" para sustituir al script estándar "restoreImage".
|
||||
#**/
|
||||
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
restoreImageCustom
|
||||
@brief Plantilla para script de restauración personalizada de imagen.
|
||||
@param $1 nº de disco
|
||||
@param $2 nº de partición
|
||||
@param $3 Repositorio: CACHE, REPO o dirección IP
|
||||
@param $4 Nombre canónico de la imagen sin extensión
|
||||
@warning Renombrar este fichero como "restoreImageCustom" para sustituir al script estándar "restoreImage".
|
||||
"""
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
import ogGlobals
|
||||
from SystemLib import ogRaiseError
|
||||
|
||||
# Control de parámetros.
|
||||
if not (4 <= len(sys.argv) <= 6):
|
||||
SystemLib.ogRaiseError(os.getenv('OG_ERR_FORMAT'), "restoreImageCustom str_repo str_imagen int_ndisco int_npart [ str_proto [\"str_opciones\"] ]")
|
||||
|
||||
if len (sys.argv) < 5 or len (sys.argv) > 7):
|
||||
ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'restoreImageCustom str_repo str_imagen int_ndisco int_npart [ str_proto ["str_opciones"] ]')
|
||||
sys.exit (1)
|
||||
# Toma de parámetros.
|
||||
REPO = sys.argv[1].upper() # Repositorio (en mayúsculas).
|
||||
IMGNAME = sys.argv[2] # Nombre canónico de imagen (sin extensión).
|
||||
DISK = sys.argv[3] # Nº de disco.
|
||||
PART = sys.argv[4] # Nº de partición.
|
||||
PROTO = sys.argv[5].upper() if len(sys.argv) > 5 else "UNICAST" # Protocolo de comunicaciones (por defecto, UNICAST).
|
||||
PROTOOPT = sys.argv[6] if len(sys.argv) > 6 else "" # Opciones del protocolo separadas por ":" (opcional).
|
||||
repo, imgname, disk, par, *other = sys.argv[1:]
|
||||
repo = repo.upper()
|
||||
proto = other[0].upper() if len (other) > 0 else 'UNICAST'
|
||||
protoopt = other[1] if len (other) > 1 else ''
|
||||
|
||||
# Paso 0: Añadir código para realizar control de errores de los parámetros de entrada (recomendado).
|
||||
|
||||
# Paso 1: Añadir aquí el código para el proceso previo antes de la restauración de la imagen en los equipos (opcional).
|
||||
|
||||
# Paso 2: Sustituir, si se desea, la llamada al proceso estándar de restauración de imagen por código personalizado.
|
||||
restoreImage(*sys.argv[1:])
|
||||
|
||||
# Aviso: editar la plantilla "configureOsCustom" para añadir el código personalizado para el proceso de postconfiguración de los clientes (no incluir aquí dicho código).
|
||||
subprocess.run (['restoreImage.py', repo, imgname, disk, par, proto, protoopt])
|
||||
|
|
|
@ -167,13 +167,13 @@ 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}):
|
||||
if not SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCopyFile', repositorio, f'{path}.torrent', 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)
|
||||
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/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:
|
||||
|
@ -182,19 +182,15 @@ 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):
|
||||
if not SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogMcastReceiverFile', port, 'CACHE', 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})
|
||||
print (f'ogExecAndLog ("command", {ogGlobals.OGPYFUNCS}/ogCopyFile {repositorio} {path} {imgdir}')
|
||||
SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCopyFile', repositorio, path, imgdir])
|
||||
time.sleep (5)
|
||||
resumeupdatecache = subprocess.run (['grep', '--max-count', '1', '100%', f'{ogGlobals.OGLOGCOMMAND}.tmp'], capture_output=True, text=True).stdout
|
||||
|
||||
|
|
Loading…
Reference in New Issue