Compare commits

..

116 Commits
0.3.5 ... main

Author SHA1 Message Date
Natalia Serrano 9cc67bbf1f Merge pull request 'refs #2316 prevent Configurar.py from messing with the browser' (#71) from configurar-coproc into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #71
2025-06-25 11:22:25 +02:00
Natalia Serrano 78f27b724e refs #2316 prevent Configurar.py from messing with the browser 2025-06-25 11:21:53 +02:00
Natalia Serrano b78fb6f900 Merge pull request 'refs #2314 fix bugs' (#70) from fix-bugs into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #70
2025-06-25 11:18:08 +02:00
Natalia Serrano 0f2cb4aefe refs #2314 fix bugs 2025-06-25 11:17:31 +02:00
Natalia Serrano 5541e39b5f Merge pull request 'refs #2308 do ogExecAndLog also when creating images' (#69) from ogexecandlog-createimage into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #69
2025-06-24 15:25:56 +02:00
Natalia Serrano 4f0543fe79 refs #2308 do ogExecAndLog also when creating images 2025-06-24 15:25:09 +02:00
Natalia Serrano a5eacbe203 Merge pull request '#2301 adds mount route when boot mark is created' (#67) from fix-bootMark-linux into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #67
2025-06-24 15:10:25 +02:00
Luis Gerardo Romero Garcia a34c98eb4c refs #2301 updates changelog 0.19.3 2025-06-24 15:09:21 +02:00
Luis Gerardo Romero Garcia c55a75f5ce #2301 adds mount route when boot mark is created 2025-06-24 15:08:29 +02:00
Natalia Serrano 1bf1283aff Merge pull request 'refs #2305 have ogExecAndLog do subprocess.Popen' (#68) from ogexecandlog into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #68
2025-06-24 15:04:40 +02:00
Natalia Serrano d5279eba42 refs #2305 have ogExecAndLog do subprocess.Popen 2025-06-24 15:03:52 +02:00
Natalia Serrano 87fb51ed2a refs #2304 remove obsolete useless function ogMcastRequest
ogclient/pipeline/head This commit looks good Details
2025-06-24 11:50:16 +02:00
Natalia Serrano c9c9e98359 Merge pull request 'refs #2301 write a mark for ogboot on linux only' (#66) from boot-mark-linux-only into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #66
2025-06-24 11:02:59 +02:00
Natalia Serrano 62ed2e3dde refs #2301 write a mark for ogboot on linux only 2025-06-24 11:01:36 +02:00
Natalia Serrano 7cefe8ff43 Merge pull request 'refs #2287 fix efi path' (#65) from fix-path into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #65
2025-06-23 16:28:48 +02:00
Natalia Serrano 9fc48067e6 refs #2287 fix efi path 2025-06-23 16:28:30 +02:00
Natalia Serrano 13b262d8f7 Merge pull request 'refs #2283 create boot mark file' (#64) from boot-mark-file into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #64
2025-06-23 12:57:56 +02:00
Natalia Serrano e43e8baea1 refs #2283 create boot mark file 2025-06-23 12:57:10 +02:00
Natalia Serrano d619cb005d Merge pull request 'refs #2238 support None as partition type' (#63) from createpartitions-none into main
ogclient/pipeline/tag This commit looks good Details
ogclient/pipeline/head This commit looks good Details
Reviewed-on: #63
2025-06-19 11:40:25 +02:00
Natalia Serrano 6d5dea6657 refs #2238 support None as partition type 2025-06-19 11:39:58 +02:00
Natalia Serrano d5fe20d291 Merge pull request 'refs #2236 look for grub.cfg in two places' (#62) from fix-ogboot into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #62
2025-06-18 09:49:40 +02:00
Natalia Serrano c7081b3921 refs #2236 look for grub.cfg in two places 2025-06-18 09:49:16 +02:00
Natalia Serrano 6c543660f9 Merge pull request 'refs #2227 add oggit scripts and libs' (#61) from add-oggit-scripts-libs into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #61
2025-06-16 15:59:21 +02:00
Natalia Serrano 594314161e refs #2227 add oggit scripts and libs 2025-06-16 15:58:54 +02:00
Natalia Serrano 7c326e7114 Merge pull request 'refs #2215 remove loop0 warning, fix windows efi boot' (#60) from loop0 into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #60
2025-06-16 09:44:59 +02:00
Natalia Serrano 944390806b refs #2215 remove loop0 warning, fix windows efi boot 2025-06-16 09:43:33 +02:00
Natalia Serrano 461c5faed5 Merge pull request 'refs #2206 give some care to the Custom scripts' (#59) from scripts-custom into main
ogclient/pipeline/head This commit looks good Details
Reviewed-on: #59
2025-06-12 15:46:59 +02:00
Natalia Serrano a9a2d19653 refs #2206 give some care to the Custom scripts 2025-06-12 15:46:06 +02:00
Natalia Serrano e80ed538b8 Merge pull request 'refs #2204 create missing directory' (#58) from mkdir-grub into main
Reviewed-on: #58
2025-06-12 10:23:56 +02:00
Natalia Serrano 857ebbd267 refs #2204 create missing directory 2025-06-12 10:23:20 +02:00
Natalia Serrano 03f8203598 Merge pull request 'refs #2202 fix bug when creating partitions' (#57) from ogcreatepartitions into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #57
2025-06-11 15:29:07 +02:00
Natalia Serrano 3fd94ecb8f refs #2202 fix bug when creating partitions 2025-06-11 15:28:41 +02:00
Natalia Serrano d2ef8a98f2 Merge pull request 'refs #2198 #2199 #2200 fix bugs' (#56) from bugs-varios into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #56
2025-06-11 10:20:40 +02:00
Natalia Serrano 8af4627e28 refs #2198 #2199 #2200 fix bugs 2025-06-11 10:20:01 +02:00
Natalia Serrano b64b6d79b3 Merge pull request 'refs #2196 remove OG bash functions from the agent's environment' (#55) from no-bash-functions-in-agent into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #55
2025-06-10 12:25:11 +02:00
Natalia Serrano efc22c1bcd refs #2196 remove OG bash functions from the agent's environment 2025-06-10 12:20:16 +02:00
Natalia Serrano 36bf1539d6 Merge pull request 'rc-pipelines' (#54) from rc-pipelines into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #54
2025-06-09 10:35:21 +02:00
Natalia Serrano f2c4371e1e refs #2189 get rc of bash pipelines 2025-06-09 10:35:02 +02:00
Natalia Serrano 39b947e598 refs #2189 get rc of bash pipelines 2025-06-09 10:31:34 +02:00
Natalia Serrano 0a26ebd946 Merge pull request 'deployimage-rc' (#53) from deployimage-rc into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #53
2025-06-06 13:58:33 +02:00
Natalia Serrano 4061f85704 refs #2187 fix rc management in deployImage.py 2025-06-06 13:58:14 +02:00
Natalia Serrano 928dedfeeb refs #2187 fix rc management in deployImage.py 2025-06-06 13:57:33 +02:00
Natalia Serrano 357c94e9ea Merge pull request 'refs #2184 make stunnel use and/or verify tls' (#52) from stunnel-usetls into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #52
2025-06-06 11:59:02 +02:00
Natalia Serrano df7d8d96cb refs #2184 make stunnel use and/or verify tls 2025-06-06 11:58:26 +02:00
Natalia Serrano 4df8caa203 Merge pull request 'refs #2171 copy grub.cfg' (#51) from cp-grub-cfg into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #51
2025-06-04 14:00:25 +02:00
Natalia Serrano fa8e94e688 refs #2171 copy grub.cfg 2025-06-04 13:59:59 +02:00
Natalia Serrano 65a3b862f7 Merge pull request 'ogexecandlog-returncode' (#50) from ogexecandlog-returncode into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #50
2025-06-03 09:32:06 +02:00
Natalia Serrano 05279ba7c5 refs #2165 review returncodes to the shell 2025-06-03 09:30:47 +02:00
Natalia Serrano 15a238c206 refs #2161 fix call to ogTorrentStart via ogExecAndLog 2025-06-02 15:15:18 +02:00
Natalia Serrano 93e349105a Merge pull request 'refs #2164 correctly parse the mcast session' (#49) from mcast-sess into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #49
2025-06-02 14:57:54 +02:00
Natalia Serrano d733d04b69 refs #2164 correctly parse the mcast session 2025-06-02 14:57:29 +02:00
Natalia Serrano e83e0e6e16 Merge pull request 'refs #2162 fix variable name' (#48) from unicast-direct into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #48
2025-06-02 12:13:59 +02:00
Natalia Serrano 972c2a7c8c refs #2162 fix variable name 2025-06-02 12:13:20 +02:00
Natalia Serrano def329436d Merge pull request 'fix-ucast-mcast' (#47) from fix-ucast-mcast into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #47
2025-05-30 13:33:16 +02:00
Natalia Serrano 29cc09105e refs #2153 fully qualify method call 2025-05-30 13:32:42 +02:00
Natalia Serrano 64c5eeae6e refs #2153 fully qualify method call 2025-05-30 13:31:27 +02:00
Natalia Serrano 1050133d59 refs #2151 explicitly return a true value 2025-05-30 13:30:05 +02:00
Natalia Serrano d76390a7b9 Merge pull request 'refs #2105 show sgdisk error' (#46) from fix-configurar into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #46
2025-05-28 14:32:46 +02:00
Natalia Serrano afe190c47d refs #2105 show sgdisk error 2025-05-28 14:30:39 +02:00
Natalia Serrano 9d1224e0c8 Merge pull request 'refs #2103 unlink() only existing files' (#45) from unlink-existing into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #45
2025-05-28 14:05:51 +02:00
Natalia Serrano 02b6708442 refs #2103 unlink() only existing files 2025-05-28 14:05:18 +02:00
Natalia Serrano d7fa82636a Merge pull request 'urlmenu-local-stunnel' (#44) from urlmenu-local-stunnel into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #44
2025-05-28 13:45:33 +02:00
Natalia Serrano bc89ddd711 refs #2053 point urlMenu back to the localhost stunnel 2025-05-28 13:44:55 +02:00
Natalia Serrano 4e3740287a refs #2053 point urlMenu back to the localhost stunnel 2025-05-21 17:22:12 +02:00
Natalia Serrano ab5544203d Merge pull request 'refs #2060 make dbus envvar available to the agent' (#43) from export-dbus-address into main
ogclient/pipeline/head There was a failure building this commit Details
ogclient/pipeline/tag There was a failure building this commit Details
Reviewed-on: #43
2025-05-21 15:56:14 +02:00
Natalia Serrano 50716302dd refs #2060 make dbus envvar available to the agent 2025-05-21 15:55:55 +02:00
Natalia Serrano 3796221fb0 Merge pull request 'refs #2047 run dbus' (#42) from dbus into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #42
2025-05-19 19:52:26 +02:00
Natalia Serrano 8a3a2b4084 refs #2047 run dbus 2025-05-19 19:51:46 +02:00
Natalia Serrano d80695ccb8 Merge pull request 'refs #2038 no ssl urlmenu' (#41) from no-ssl-urlmenu into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #41
2025-05-19 11:52:26 +02:00
Natalia Serrano 2064b787c4 refs #2038 no ssl urlmenu 2025-05-19 11:48:17 +02:00
Natalia Serrano cf13a6da72 Merge pull request 'stunnel' (#40) from stunnel into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #40
2025-05-18 12:28:36 +02:00
Natalia Serrano 867508d5ee refs #2029 update changelog 2025-05-18 12:26:44 +02:00
Natalia Serrano 4a94875d7e refs #2029 change urlMenu to point to stunnel 2025-05-18 12:26:10 +02:00
Natalia Serrano 3d2f06d577 refs #2028 send stunnel output to a log 2025-05-18 11:19:56 +02:00
Natalia Serrano 6c88096eae refs #2027 #2028 run stunnel during startup 2025-05-16 15:42:13 +02:00
Natalia Serrano ed070bc566 Merge pull request 'refs #2000 run the new browser' (#39) from browser into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #39
2025-05-14 14:53:17 +02:00
Natalia Serrano fd59bdc7fa refs #2000 run the new browser 2025-05-14 14:51:23 +02:00
Natalia Serrano cbb978e514 Merge pull request 'refs #1981 use zstd when creating and restoring images' (#38) from use-zstd into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #38
2025-05-09 13:45:51 +02:00
Natalia Serrano e1b8e5c625 refs #1981 use zstd when creating and restoring images 2025-05-09 13:45:03 +02:00
Natalia Serrano 03827cdc58 Merge pull request 'agentcfg-imgname' (#37) from agentcfg-imgname into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #37
2025-05-09 12:17:27 +02:00
Natalia Serrano 9a48940800 refs #1980 pass imgname to configureOs.py 2025-05-09 12:16:21 +02:00
Natalia Serrano 6958c658e8 refs #1980 pass imgname to configureOs.py 2025-05-09 12:11:34 +02:00
Natalia Serrano 06885b35d7 refs #1979 pass imgname to ogConfigureOgagent() 2025-05-09 12:11:02 +02:00
Natalia Serrano b9a2c58c96 refs #1978 change imgname in ogagent.cfg 2025-05-09 12:09:34 +02:00
Natalia Serrano 24f5461860 Merge pull request 'refs #1970 fix handling of spaces in ogNvramAddEntry' (#36) from fix-ogNvramAddEntry into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #36
2025-05-08 09:50:53 +02:00
Natalia Serrano 0961ec10be refs #1970 fix handling of spaces in ogNvramAddEntry 2025-05-08 09:50:25 +02:00
Natalia Serrano 9514ce6b25 Merge pull request 'refs #1962 ignore tch parameter' (#35) from ignore-tch into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #35
2025-05-07 14:47:54 +02:00
Natalia Serrano eb88929f86 refs #1962 ignore tch parameter 2025-05-07 14:47:10 +02:00
Natalia Serrano 6a18e1a0ba Merge pull request 'fix-ogboot' (#34) from fix-ogboot into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details
Reviewed-on: #34
2025-05-07 11:46:57 +02:00
Natalia Serrano 94ee50eff5 refs #1956 gracefully handle error 2025-05-07 11:46:31 +02:00
Natalia Serrano 41f0efbf5c refs #1956 gracefully handle error 2025-05-07 11:06:43 +02:00
Natalia Serrano 7624964ba1 Merge pull request 'refs #1925 send /stopped on poweroff or restart' (#33) from agent-stopped-on-poweroff into main
ogclone-engine/pipeline/head This commit looks good Details
ogclient/pipeline/head This commit looks good Details
Reviewed-on: #33
2025-04-23 13:59:20 +02:00
Natalia Serrano c3e86b7dc0 refs #1925 send /stopped on poweroff or restart 2025-04-23 13:58:51 +02:00
Natalia Serrano a18e861bea Merge pull request 'refs #1912 fix a couple of rc' (#32) from test-configurar-py into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #32
2025-04-21 12:49:14 +02:00
Natalia Serrano 842dbf48c2 refs #1912 fix a couple of rc 2025-04-21 12:48:47 +02:00
Natalia Serrano d79c677f16 Merge pull request 'refs #1918 fix getConfiguration.py' (#31) from fix-getConfiguration into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #31
2025-04-15 17:56:50 +02:00
Natalia Serrano bd056438a1 refs #1918 fix getConfiguration.py 2025-04-15 17:56:27 +02:00
Natalia Serrano fb665fa4ca Merge pull request 'refs #1908 remove refs to OGLOG' (#30) from remove-OGLOG into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #30
2025-04-15 17:17:18 +02:00
Natalia Serrano c76fd8388a refs #1908 remove refs to OGLOG 2025-04-15 17:16:48 +02:00
Natalia Serrano fac6e142f6 Merge pull request 'refs #1914 fix a couple of bugs' (#29) from fix-restaurar-imagen into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #29
2025-04-15 17:07:07 +02:00
Natalia Serrano e20bd46edb refs #1914 fix a couple of bugs 2025-04-15 17:06:34 +02:00
Natalia Serrano f785143b73 Merge pull request 'refs #1916 move ogGetIpAddress to NetLib' (#28) from move-ogGetIpAddress into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #28
2025-04-15 17:04:00 +02:00
Natalia Serrano bf85cb1fed refs #1916 move ogGetIpAddress to NetLib 2025-04-15 17:03:31 +02:00
Natalia Serrano e885302256 Merge pull request 'oglog' (#27) from oglog into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #27
2025-04-15 16:58:15 +02:00
Natalia Serrano ad3388d36e Merge branch 'main' into oglog 2025-04-15 16:56:51 +02:00
Natalia Serrano 46238456cb refs #1838 log to /var/log instead of the shared /opt/opengnsys/log 2025-04-15 16:55:45 +02:00
Natalia Serrano 0179d106e9 refs #1838 log to /var/log instead of the shared /opt/opengnsys/log 2025-04-15 16:54:06 +02:00
Nicolas Arenas 697c60f812 Publish in nightlys
ogclone-engine/pipeline/head This commit looks good Details
2025-04-10 16:26:15 +02:00
Natalia Serrano 4353c74768 Merge pull request 'refs #1879 negate rc to the shell' (#25) from negate-rc-for-shell into main
ogclone-engine/pipeline/tag This commit looks good Details
ogclone-engine/pipeline/head This commit looks good Details
Reviewed-on: #25
2025-04-10 13:33:26 +02:00
Natalia Serrano 2c18e6981f refs #1879 negate rc to the shell 2025-04-10 13:32:48 +02:00
Natalia Serrano c1f123b489 Merge pull request 'refs #1878 makes writable Samba export in ogclient' (#24) from make_samba_public into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #24
2025-04-10 09:41:27 +02:00
Natalia Serrano 1f92f54994 refs #1878 update changelog 2025-04-10 09:41:08 +02:00
Nicolas Arenas bbaa6578e1 refs #1878 makes writable Samba export in ogclient 2025-04-10 08:11:04 +02:00
Natalia Serrano e1a1be667b Merge pull request 'fix-ogReduceFs' (#23) from fix-ogReduceFs into main
ogclone-engine/pipeline/tag This commit looks good Details
Reviewed-on: #23
2025-04-09 18:36:47 +02:00
Natalia Serrano 44511c79a0 refs #1876 change check and improve debug msg 2025-04-09 18:36:11 +02:00
Natalia Serrano a1493a827e refs #1876 change check and improve debug msg 2025-04-09 17:47:51 +02:00
54 changed files with 3824 additions and 785 deletions

View File

@ -5,6 +5,299 @@ 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.21.0] - 2025-06-25
### Changed
- Prevent Configurar.py from messing with the browser
## [0.20.3] - 2025-06-25
### Fixed
- Fixed bugs when partitioning disks
## [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
- Point urlMenu back to the localhost stunnel
## [0.13.1] - 2025-05-21
### Changed
- Make dbus envvar available to the agent
## [0.13.0] - 2025-05-19
### Added
- Run dbus
## [0.12.0] - 2025-05-18
### Changed
- no tls for the urlmenu either
## [0.11.0] - 2025-05-18
### Added
- Run stunnel and point the browser to it
## [0.10.0] - 2025-05-14
### Changed
- Run the new browser
## [0.9.0] - 2025-05-09
### Added
- Use zstd when creating and restoring images
## [0.8.4] - 2025-05-09
### Added
- When restoring an image, include the image name in the ogagent configuration file
## [0.8.3] - 2025-05-08
### Fixed
- Have ogNvramAddEntry() handle EFI entries with spaces in them
## [0.8.2] - 2025-05-07
### Changed
- Have Configurar.py ignore the tch parameter, take cache size from the definition of the cache partition
## [0.8.1] - 2025-05-07
### Fixed
- Gracefully handle error in ogBoot() when not finding /boot partition in target's fstab
## [0.8.0] - 2025-04-23
### Added
- Have the oglive agent send /stopped on poweroff or restart
## [0.7.2] - 2025-04-21
### Fixed
- Have the partitioning functions return a meaningful rc
## [0.7.1] - 2025-04-15
### Fixed
- getConfiguration.py: don't fail if NTFS filesystems are mounted ro
## [0.7.0] - 2025-04-15
### Removed
- Removed references to ogGlobals.OGLOG in python code
## [0.6.1] - 2025-04-15
### Fixed
- Fixed capturing of partclone output and management of return value
## [0.6.0] - 2025-04-15
### Changed
- ogGetIpAddress() is no longer required in ogGlobals--move it back into NetLib
## [0.5.0] - 2025-04-15
### Changed
- Log to /var/log/clone-engine.log and clone-engine.json.log
## [0.4.1] - 2025-04-10
### Fixed
- restoreImage.py: return negated rc to the shell
## [0.4.0] - 2025-04-10
### Changed
- Make /opt/opengnsys writable in clients, just like it used to be
## [0.3.6] - 2025-04-09
### Fixed
- Fixed ogReduceFs
## [0.3.5] - 2025-04-09
### Fixed

View File

@ -48,7 +48,18 @@ pipeline {
}
}
}
stage('Generate Changelog (Nightly)'){
when {
branch 'main'
}
steps {
script {
def devName = params.DEV_NAME ? params.DEV_NAME : env.DEFAULT_DEV_NAME
def devEmail = params.DEV_EMAIL ? params.DEV_EMAIL : env.DEFAULT_DEV_EMAIL
generateDebianChangelog(env.BUILD_DIR, devName, devEmail,"nightly")
}
}
}
stage('Build') {
steps {
script {
@ -71,6 +82,19 @@ pipeline {
}
}
}
stage ('Publish to Debian Repository (Nightly)') {
when {
branch 'main'
}
agent { label 'debian-repo' }
steps {
script {
// Construir el patrón de versión esperado en el nombre del paquete
def versionPattern = "-${env.BUILD_NUMBER}~nightly"
publicarEnAptly('/var/tmp/opengnsys/debian-repo/ogclient', 'nightly', versionPattern)
}
}
}
}
post {
always {

View File

@ -1,7 +1,7 @@
[ogclient]
comment = OpenGnsys Client
browseable = no
writeable = no
writeable = yes
locking = no
path = /opt/opengnsys/ogclient
guest ok = no

View File

@ -21,20 +21,26 @@ echo "${MSG_LAUNCHCLIENT:-.}"
if [ -f "/usr/share/OGAgent/opengnsys/linux/OGAgentService.py" -a "$ogstatus" != "offline" ]; then
# Ejecutar servicio cliente.
cd /usr/share/OGAgent
export OGAGENTCFG_OGCORE_IP=$ogcore
export OGAGENTCFG_OGCORE_IP=$ogcore
export OGAGENTCFG_OGLOG_IP=$oglog
export OGAGENTCFG_URLMENU_IP=$ogcore
python3 -m opengnsys.linux.OGAgentService fg
export OGAGENTCFG_URLMENU_SCHEME=http
export OGAGENTCFG_URLMENU_IP=127.0.0.1
export OGAGENTCFG_URLMENU_PORT=81
(
## 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
[ -f $OGCAC/menus/$FILE.html ] && OGMENU="$OGCAC/menus/$FILE.html"
done
echo "exec /usr/bin/OGBrowser $OGMENU" > /home/root/
/usr/bin/OGBrowser -qws $OGMENU
$OPENGNSYS/bin/launch_browser $OGMENU
fi
# Si fallo en cliente y modo "admin", cargar shell; si no, salir.
if [ "$ogactiveadmin" == "true" ]; then
bash
fi
fi

View File

@ -6,7 +6,7 @@ source /opt/opengnsys/etc/preinit/loadenviron.sh
# Scripts de inicio.
for f in fileslinks loadmodules metadevs mountrepo poweroff otherservices; do
$OGETC/preinit/$f.sh
source $OGETC/preinit/$f.sh
done
unset f

View File

@ -13,6 +13,58 @@ ogIsEfiActive && mount -t efivarfs none /sys/firmware/efi/efivars
# Lanzar servicios complementarios del cliente.
echo "${MSG_OTHERSERVICES:-.}"
# 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
mkdir -p /run/dbus
DBUS_SESSION_BUS_ADDRESS=$(dbus-daemon --print-address --system --nosyslog)
export DBUS_SESSION_BUS_ADDRESS
dbus-monitor --system &>/var/log/dbus-monitor.log &
fi
# Iniciar rsyslog, si es necesario.
[ -S /dev/log ] || service rsyslog start

View File

@ -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')

View File

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

View File

@ -35,10 +35,6 @@ prog = os.path.basename(__name__)
# El parámetro $2 es el que aporta toda la información y el $1 se queda obsoleto
# Formato de entrada:
# dis=Número de disco
# *=caracter de separación
# che=Vale 0 o 1
# *=caracter de separación
# $tch=tamaño cache
# != caracter de separación
#
# Y un numero indeterminado de cadenas del tipo siguuenteseparadas por el caracter '$':
@ -47,13 +43,10 @@ prog = os.path.basename(__name__)
#____________________________________________________________________
# Captura de parámetros (se ignora el 1er parámetro y se eliminan espacios y tabuladores).
#param='dis=1*che=0*tch=70000000!par=1*cpt=NTFS*sfi=NTFS*tam=11000000*ope=0%'
#param='dis=1!par=1*cpt=NTFS*sfi=NTFS*tam=11000000*ope=0%'
#param = ''.join(sys.argv[2:]).replace(' ', '').replace('\t', '')
param = sys.argv[2]
# Activa navegador para ver progreso
coproc = subprocess.Popen (['/opt/opengnsys/bin/browser', '-qws', 'http://localhost/cgi-bin/httpd-log.sh'])
# Leer los dos bloques de parámetros, separados por '!'.
tbprm = param.split ('!')
pparam = tbprm[0] # General disk parameters
@ -67,19 +60,15 @@ for item in tbprm:
if '=' not in item: continue
k, v = item.split ('=', 1)
if k not in ['dis', 'tch']:
if k not in ['dis']:
print (f'ignoring unknown disk parameter ({k})')
continue
if 'dis' == k: dis = int (v)
elif 'tch' == k: tch = v
if 'dis' == k: dis = int (v)
# Error si no se define el parámetro de disco (dis).
if dis is None:
coproc.kill()
sys.exit (ogGlobals.OG_ERR_FORMAT)
if tch is None:
tch = '0'
# Toma valores de distribución de particiones, separados por "%".
tbp = [] # Valores de configuración (parámetros para ogCreatePartitions)
@ -114,11 +103,13 @@ for item in tbprm:
if tam is None: missing_params.append ('tam')
if missing_params:
print (f'partition data ({item}) missing required parameters ({' '.join (missing_params)})')
coproc.kill()
sys.exit (1)
# Componer datos de particionado.
if 'CACHE' != cpt: tbp.append (f'{cpt}:{tam}')
if 'CACHE' == cpt:
tch = tam
else:
tbp.append (f'{cpt}:{tam}')
if ope:
# Si se activa operación de formatear, componer datos de formateo.
if cpt not in ['EMPTY', 'EXTENDED', 'LINUX-LVM', 'LVM', 'ZPOOL']:
@ -126,6 +117,9 @@ for item in tbprm:
# Obtener la partición mayor.
if par > maxp: maxp = par
if tch is None:
tch = '0'
#____________________________________________________
#
# Proceso
@ -144,28 +138,26 @@ 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)
# 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', str(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}')
@ -175,12 +167,11 @@ 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])
if retval:
coproc.kill()
retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatFs', str(dis), str(p), tbf[p]])
if not retval:
SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_GENERIC, f'ogFormatFs {dis} {p} {tbf[p]}')
sys.exit (1)
# Registro de fin de ejecución
@ -191,5 +182,4 @@ SystemLib.ogEcho (['session', 'log'], None, f'{ogGlobals.lang.MSG_INTERFACE_END}
# Retorno
#___________________________________________________________________
coproc.kill()
sys.exit (0)

View File

@ -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()

View File

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

View File

@ -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)

View File

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

View File

@ -79,6 +79,9 @@ def ogBoot (disk, par, nvramperm=False, params=''):
break
if dev:
fstab_part = DiskLib.ogDevToDisk (dev)
if not fstab_part:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({dev})')
return None
else:
return None
# Montar S.F. de /boot.
@ -109,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)
@ -123,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.
@ -153,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'])
@ -434,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
@ -446,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
@ -736,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
#/**
@ -831,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

View File

@ -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

View File

@ -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,10 +177,10 @@ 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 True
return not p.returncode
#/**
@ -283,9 +284,10 @@ 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 True
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).

View File

@ -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
#/**

View File

@ -263,7 +263,7 @@ def ogFormatFs (disk, par, fs=None, label=None):
errcode = ogGlobals.OG_ERR_PARTITION
ogUnlock (disk, par)
return errcode
return not errcode ## reverse to indicate success
#/**
@ -692,7 +692,8 @@ def ogReduceFs (disk, par):
break
elif type == 'NTFS':
ogUnmount (disk, par)
nr_lines = subprocess.run (['ntfsresize', '-fi', PART], capture_output=True, text=True).stdout.splitlines()
ntfsresize_out = subprocess.run (['ntfsresize', '-fi', PART], capture_output=True, text=True).stdout
nr_lines = ntfsresize_out.splitlines()
maxsize = None
size = None
for l in nr_lines:
@ -702,12 +703,10 @@ def ogReduceFs (disk, par):
size = l.split()[4]
size = int ((int (size) * 1.1 / 1024 + 1) * 1024)
if not maxsize and not size:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{par}')
if not maxsize or not size:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{par} ({ntfsresize_out})')
return None
import time
extrasize = 0
retval = 1
while retval != 0 and size+extrasize < maxsize:

View File

@ -101,6 +101,8 @@ def ogCreateImageSyntax (dev, imgfile, tool='partclone', level='gzip'):
'gzip': ' | gzip -c > ',
3: ' | bzip -c > ',
'bzip': ' | bzip -c > ',
4: ' | zstd -c > ',
'zstd': ' | zstd -c > ',
}.get (level, ' > ')
#print (f'param1 ({param1}) param2 ({param2}) param3 ({param3}) imgfile ({imgfile})')
@ -150,6 +152,8 @@ def ogRestoreImageSyntax (imgfile, part, tool=None, level=None):
'gzip': ' gzip -dc ',
3: ' bzip -dc ',
'bzip': ' bzip -dc ',
4: ' zstd -dc ',
'zstd': ' zstd -dc ',
}.get (level, '')
#print (f'tool ({tool}) level ({level}) compressor ({compressor})')
if compressor == '':
@ -250,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:
@ -511,8 +515,8 @@ def ogRestoreImage (repo, imgpath, disk, par):
rc = None
try:
p = subprocess.run (program, shell=True, capture_output=True, text=True)
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:
@ -593,14 +597,15 @@ def ogGetImageInfo (imgfile):
imgdetect = False
filehead = f'/tmp/{os.path.basename (imgfile)}.infohead'
compressor = subprocess.run (['file', imgfile], capture_output=True, text=True).stdout.split()[1]
if compressor not in ['gzip', 'lzop']:
if 'Zstandard' == compressor: compressor = 'zstd'
if compressor not in ['gzip', 'lzop', 'zstd']:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}')
return
## 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

View File

@ -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', ' ')

View File

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

View File

@ -7,6 +7,7 @@
#*/
import os
import re
import glob
import subprocess
@ -200,7 +201,7 @@ def ogAddCmd (disk, par, cmdfile, cmd):
#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado.
#@exception OG_ERR_LOCKED Sistema de archivos bloqueado.
#*/ ##
def ogConfigureOgagent (disk, par):
def ogConfigureOgagent (disk, par, imgname=''):
mntdir = FileSystemLib.ogMount (disk, par)
if not mntdir:
return
@ -217,19 +218,22 @@ def ogConfigureOgagent (disk, par):
ogcore_ip = NetLib.ogGetServerIp()
ogcore_port = NetLib.ogGetServerPort()
cfgfile_patched = cfgfile + '.patched'
in_opengnsys_section = False
cur_section = ''
with open (cfgfile, 'r') as fdin:
with open (cfgfile_patched, 'w') as fdout:
while True:
lineout = linein = fdin.readline()
if not linein: break
if in_opengnsys_section:
if 'remote' == linein[0:6]:
lineout = f'remote={ogcore_scheme}://{ogcore_ip}:{ogcore_port}/opengnsys/rest/\n'
if '[' == linein[0:1]:
in_opengnsys_section = False
if '[opengnsys]' == linein[0:11]:
in_opengnsys_section = True
m = re.match (r'\[(.*)] *$', linein)
if m:
cur_section = m.groups()[0]
else:
if 'opengnsys' == cur_section:
if re.match (r'remote *=', linein):
lineout = f'remote={ogcore_scheme}://{ogcore_ip}:{ogcore_port}/opengnsys/rest/\n'
elif re.match ('imgname *=', linein):
lineout = f'imgname={imgname}\n'
fdout.write (lineout)
os.rename (cfgfile_patched, cfgfile)

View File

@ -58,7 +58,7 @@ def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None):
raise TypeError (f'argument "tool" has unsupported value "{tool}"')
if level is None:
raise TypeError ('missing required argument: "level"')
if level.lower() not in ['lzop', 'gzip', '0', '1']:
if level.lower() not in ['lzop', 'gzip', 'zstd']:
raise TypeError (f'argument "level" has unsupported value "{level}"')
elif 'SENDFILE' == op or 'RECEIVERFILE' == op:
if file is None:
@ -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
@ -290,7 +291,7 @@ def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None):
raise TypeError (f'argument "tool" has unsupported value "{tool}"')
if level is None:
raise TypeError ('missing required argument: "level"')
if level.lower() not in ['lzop', 'gzip', '0', '1']:
if level.lower() not in ['lzop', 'gzip', 'zstd']:
raise TypeError (f'argument "level" has unsupported value "{level}"')
elif 'SENDFILE' == op or 'RECEIVERFILE' == op:
if file is None:
@ -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

View File

@ -3,23 +3,18 @@ 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
elif 'command' == t.lower(): return ogGlobals.OGLOGCOMMAND
elif 'session' == t.lower(): return ogGlobals.OGLOGSESSION
else: raise Exception (f'unknown log type ({t})')
@ -35,24 +30,40 @@ def ogEcho (logtypes, loglevel, msg):
logfiles = ['/dev/stdout']
if type (logtypes) is list:
for l in logtypes:
logfiles.append (_logtype2logfile (l))
if 'log' == l:
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (l))
else: ## string
logfiles.append (_logtype2logfile (logtypes))
if 'log' == logtypes:
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (logtypes))
if loglevel is None or 'help' == loglevel:
if ogGlobals.DEBUG.lower() != "no":
logfiles.append (ogGlobals.OGLOGFILE)
logfiles.append (ogGlobals.OGJSONLOGFILE)
for f in logfiles:
with open (f, 'a') as fd:
fd.write (msg + '\n')
if ogGlobals.OGJSONLOGFILE == f:
fd.write (json.dumps ({'message':msg}) + '\n')
else:
fd.write (msg + '\n')
return
if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel:
DATETIME = datetime.datetime.now(ZoneInfo(ogGlobals.TZ)).strftime("%F %T %Z")
DATETIME = datetime.datetime.now (ZoneInfo (ogGlobals.TZ)).strftime ('%F %T %Z')
DATETIME_json = datetime.datetime.now (ZoneInfo (ogGlobals.TZ)).strftime ('%Y-%m-%d %H:%M:%S')
for f in logfiles:
with open (f, 'a') as fd:
fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n")
if ogGlobals.OGJSONLOGFILE == f:
fd.write (json.dumps ({'timestamp':DATETIME_json, 'severity':loglevel, 'message':msg}) + '\n')
else:
fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n")
else:
raise Exception (f'unknown loglevel ({loglevel})')
@ -66,21 +77,29 @@ 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:
logtypes = list (map (lambda x: x.lower(), logtypes))
logfiles.append (_logtype2logfile (l))
if 'log' == l:
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (l))
else: ## string
logtypes = logtypes.lower()
logfiles.append (_logtype2logfile (logtypes))
if 'log' == logtypes:
logfiles.append (_logtype2logfile ('log'))
logfiles.append (_logtype2logfile ('jsonlog'))
else:
logfiles.append (_logtype2logfile (logtypes))
if not fun:
if not script_and_args:
ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'no function provided')
return
@ -103,34 +122,38 @@ def ogExecAndLog (logtypes, fun, *args, **kwargs):
# ## redirect stdout only
# eval $COMMAND | tee -a $FILES
import time
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 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

View File

@ -98,8 +98,10 @@ def ogNvramAddEntry (bootlbl, bootldr, nvram_set=False):
if nvram_set:
efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout
for l in efibootmgr_out.splitlines():
words = l.split (maxsplit=1)
if len(words) < 2: continue
if '\t' not in l: continue
(pre_tab, post_tab) = l.split ('\t', maxsplit=1)
words = pre_tab.split (maxsplit=1)
if len(words) < 2: continue ## shouldn't happen
if words[1] == bootlabel:
numentry = words[0][4:8]
order = ogNvramGetOrder()

View File

@ -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()

View File

@ -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')

View File

@ -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"])

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -6,33 +6,6 @@ import os.path
import locale
import importlib.util
## required for defining OGLOGFILE
def ogGetIpAddress():
if "IPV4ADDR" in os.environ:
ip = os.environ["IPV4ADDR"]
if '/' in ip: ip = ip.split ('/')[0]
return ip
extra_args = []
if "DEVICE" in os.environ:
extra_args = [ "dev", os.environ["DEVICE"] ]
ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'] + extra_args, capture_output=True, text=True).stdout
ipasj = json.loads (ipas)
addresses = []
for e in ipasj:
if 'lo' == e['ifname']: continue
if 'addr_info' not in e: continue
addrs = e['addr_info']
for a in addrs:
if 'inet' != a['family']: continue
addresses.append ({ 'local': a['local'], 'prefixlen': a['prefixlen'] })
if 1 != len (addresses):
raise Exception ('more than one local IP address found')
return addresses[0]
ip = ogGetIpAddress()
def load_lang (name):
global lang
if name in sys.modules:
@ -62,7 +35,7 @@ OGLOGCOMMAND='/tmp/command.log'
ACTIONCACHEFULL='NONE' #Que hacer cuando la cache no tenga espacio libre. [ NONE | FORMAT ] ]
RESTOREPROTOCOLNOTCACHE=None #Que protocolo de restauracion usar en el caso de que no exista cache o no exista espacio sufiente. [NONE | UNICAST | MULTICAST].NONE retorna error
IMGPROG='partclone'
IMGCOMP='lzop'
IMGCOMP='zstd'
IMGEXT='img'
IMGREDUCE=True
#OGWINREDUCE=True #Al enviar particion reducir el sistema de archivos previamente.
@ -88,8 +61,8 @@ OGPYFUNCS = os.path.join (OPENGNSYS, 'functions')
OGSCRIPTS = os.path.join (OPENGNSYS, 'scripts')
OGIMG = os.path.join (OPENGNSYS, 'images')
OGCAC = os.path.join (OPENGNSYS, 'cache')
OGLOG = os.path.join (OPENGNSYS, 'log')
OGLOGFILE = f'{OGLOG}/{ip}.log'
OGLOGFILE = '/var/log/clone-engine.log'
OGJSONLOGFILE = '/var/log/clone-engine.json.log'
DEBUG = 'yes'
_path = os.environ['PATH'] + ':/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin:/opt/oglive/rootfs/opt/drbl/sbin'
os.environ['PATH'] = ':'.join ([OGSCRIPTS, _path, OGAPI, OGBIN])

View File

@ -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"))

View File

@ -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()

View File

@ -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 de disco
@param $2 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')}")

View File

@ -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'])

View File

@ -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

View File

@ -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

View File

@ -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 de disco
@param $2 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()

View File

@ -5,6 +5,7 @@
#@brief Script para realizar la configuracion del sistema operativo restaurado.
#@param 1 disco
#@param 2 particion
#@param 2 nombre imagen
#@return
#@TODO comprobar que el tipo de particion corresponde con el sistema de archivos.
#@exception OG_ERR_FORMAT # 1 formato incorrecto.
@ -30,8 +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]
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)
@ -71,7 +72,7 @@ if 'Windows' == ostype:
BootLib.ogFixBootSector (disk, par) # Configurar el boot sector de la partición Windows.
BootLib.ogWindowsBootParameters (disk, par) # Configurar el gestor de arranque de Windows XP/Vista/7.
BootLib.ogWindowsRegisterPartition (disk, par, 'C', disk, par) # Registrar en Windows que la partición indicada es su nueva unidad C:\
PostConfLib.ogConfigureOgagent (disk, par) # Configurar nuevo agente OGAgent.
PostConfLib.ogConfigureOgagent (disk, par, imgname) # Configurar nuevo agente OGAgent.
path1 = FileLib.ogGetPath (file=f'{mntdir}/windows/ogAdmWinClient.exe')
path2 = FileLib.ogGetPath (file=f'{mntdir}/winnt/ogAdmWinClient.exe')
if path1 or path2: # Eliminar el antiguo cliente de Windows.
@ -79,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()
@ -88,7 +97,7 @@ elif 'Linux' == ostype:
find_out = subprocess.run (['find', f'{mntdir}/usr/sbin', f'{mntdir}/sbin', f'{mntdir}/usr/local/sbin', '-name', 'ogAdmLnxClient', '-print'], capture_output=True, text=True).stdout
if find_out:
PostConfLib.ogUninstallLinuxClient (disk, par) # Eliminar el antiguo cliente de Linux.
PostConfLib.ogConfigureOgagent (disk, par) # Configurar nuevo agente OGAgent.
PostConfLib.ogConfigureOgagent (disk, par, imgname) # Configurar nuevo agente OGAgent.
## Modificar el nombre del equipo
print (f'Asignar nombre Linux "{host}".')
etc = FileLib.ogGetPath (src=f'{disk} {par}', file='/etc')
@ -154,6 +163,6 @@ elif 'MacOS' == ostype:
fd.write ('\trm -f /osxpostconf # Borrar fichero indicador de psotconfiguración\n')
fd.write ('fi\n')
os.chmod (f'{mntdir}/var/root/postconfd.sh', 0o700) # Dar permiso de ejecución.
PostConfLib.ogConfigureOgagent (disk, par) # Configurar nuevo agente OGAgent de sistema operativo.
PostConfLib.ogConfigureOgagent (disk, par, imgname) # Configurar nuevo agente OGAgent de sistema operativo.
sys.exit (0)

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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).

View File

@ -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])

View File

@ -138,9 +138,9 @@ 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
@ -149,7 +149,8 @@ def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''):
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}')
@ -159,12 +160,12 @@ 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])
subprocess.run (['configureOs.py', disk, par, imgname])
time_total = time.time() - time1
SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_SCRIPTS_TIME_TOTAL} {int (time_total/60)}m {int (time_total%60)}s')

View File

@ -5,7 +5,6 @@
import sys
import time
import subprocess
import ogGlobals
import SystemLib

View File

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

View File

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

14
ogclient/scripts/restoreImage.py 100644 → 100755
View File

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

View File

@ -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).

View File

@ -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 de disco
@param $2 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])

16
ogclient/scripts/updateCache.py 100644 → 100755
View File

@ -143,7 +143,7 @@ if sizerequired >= cachesizefree:
SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE')
sys.exit (1)
# Comprobamos que imagen cache igual a la del repo. Si sincronizada no podemos comprobar.
# Comprobamos que imagen cache igual a la del repo. Si sincronizada no podemos comprobar.
rc = ProtocolLib.ogUpdateCacheIsNecesary (repositorio, path, protocolo)
# si rc=True: actualizamos; si rc=False: no actualizamos (exit 0); si rc=None: exit error
if rc == True: pass ## es necesario actualizar
@ -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