Compare commits
1 Commits
main
...
lgromero-f
Author | SHA1 | Date |
---|---|---|
|
5476ef0199 |
307
CHANGELOG.md
|
@ -1,307 +0,0 @@
|
||||||
|
|
||||||
# Changelog
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
## [5.1.1] - 2025-05-06
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fixed URL for notifying stop to ogcore
|
|
||||||
|
|
||||||
## [5.1.0] - 2025-05-06
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Added powershell helper script for logging out from windows
|
|
||||||
|
|
||||||
## [5.0.0] - 2025-05-06
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Use TLS
|
|
||||||
|
|
||||||
## [4.0.0] - 2025-04-24
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Authn/authz to the oglive agent
|
|
||||||
|
|
||||||
## [3.3.0] - 2025-04-14
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Log stuff to a new json log
|
|
||||||
|
|
||||||
## [3.2.0] - 2025-04-10
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Operating system: periodically ping ogcore
|
|
||||||
|
|
||||||
## [3.1.0] - 2025-04-07
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Oglive: periodically ping ogcore
|
|
||||||
|
|
||||||
## [3.0.0] - 2025-03-31
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Ignore module provided in the URLs to the API
|
|
||||||
|
|
||||||
## [2.0.0] - 2025-03-26
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- EjecutarScript/ConsolaRemota: expect "scp" parameter encoded in base64
|
|
||||||
|
|
||||||
## [1.7.1] - 2025-03-25
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Make cfg2obj more robust
|
|
||||||
|
|
||||||
## [1.7.0] - 2025-03-21
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- Delete the new "ptt" parameter. It's not needed.
|
|
||||||
|
|
||||||
## [1.6.0] - 2025-03-12
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Don't invoke bash code for some functionalities
|
|
||||||
|
|
||||||
## [1.5.0] - 2025-03-12
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Accept new "ptt" parameter in /ogAdmCli/Configurar
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- No longer recognise the unused "che" parameter in /ogAdmCli/Configurar
|
|
||||||
|
|
||||||
## [1.4.9] - 2025-02-20
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Notify ogcore when agent shuts down within oglive
|
|
||||||
|
|
||||||
## [1.4.8] - 2025-02-18
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Optionally return disk config in /status
|
|
||||||
|
|
||||||
## [1.4.7] - 2025-02-04
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Merge server modules
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Track the progress of children
|
|
||||||
|
|
||||||
## [1.4.6] - 2025-01-14
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Point to the new menu browser
|
|
||||||
|
|
||||||
## [1.4.5] - 2024-11-29
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Kill long running jobs in oglive
|
|
||||||
|
|
||||||
## [1.4.5~pre8] - 2024-11-27
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Add Configurar() to the CloningEngine module
|
|
||||||
|
|
||||||
## [1.4.5~pre7] - 2024-11-20
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Use old browser again
|
|
||||||
|
|
||||||
## [1.4.5~pre6] - 2024-11-20
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Do not use envvars for the operating-system module
|
|
||||||
|
|
||||||
## [1.4.5~pre5] - 2024-11-18
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Avoid some KeyErrors
|
|
||||||
|
|
||||||
## [1.4.5~pre4] - 2024-11-15
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Don't die when ogcore returns HTTP 4xx or 5xx
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Get ogcore IP and port from the environment
|
|
||||||
|
|
||||||
## [1.4.5~pre3] - 2024-11-06
|
|
||||||
- Kill long running jobs in oglive (not-yet-working draft)
|
|
||||||
|
|
||||||
## [1.4.5~pre2] - 2024-11-06
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Remove race condition due to several monitoring threads
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Include job_id in asynchronous responses
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- Remove vim swapfiles from the package contents
|
|
||||||
|
|
||||||
## [1.4.5~pre1] - 2024-11-06
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- CrearImagen: return inventory inline
|
|
||||||
|
|
||||||
## [1.4.4] - 2024-10-17
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Use logger.debug() to prevent the windows agent from dying
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Make status() call synchronous
|
|
||||||
|
|
||||||
## [1.4.3] - 2024-10-17
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Use new OGBrowser
|
|
||||||
|
|
||||||
## [1.4.2] - 2024-10-15
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Have ogAdmClient/status return information about network and disks
|
|
||||||
|
|
||||||
## [1.4.1] - 2024-10-11
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Bugfix: move data structure to the right class
|
|
||||||
|
|
||||||
## [1.4.0] - 2024-10-11
|
|
||||||
- Add more functionality
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Begin using semantic versioning
|
|
||||||
|
|
||||||
## [1.3.8] - 2024-10-01
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Add more functionality to the ogAdmClient module
|
|
||||||
|
|
||||||
## [1.3.7] - 2024-09-27
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- CloningEngine: RESTfully keep a list of long-running jobs
|
|
||||||
|
|
||||||
## [1.3.6] - 2024-09-19
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Add more functionality to the ogAdmClient module
|
|
||||||
- Add CloningEngine module
|
|
||||||
|
|
||||||
## [1.3.5] - 2024-08-29
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Don't unconditionally load modules--dynamically load everything
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- Remove old, unused code
|
|
||||||
|
|
||||||
## [1.3.4] - 2024-07-30
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Implement JobMgr
|
|
||||||
|
|
||||||
## [1.3.1] - 2024-06-26
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Migrate the update script from shell to python
|
|
||||||
- pyinstaller: include the 'img' subdir
|
|
||||||
- take icons from 'img'
|
|
||||||
|
|
||||||
## [1.3.0-2] - 2024-04-25
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Add missing dependency on zenity
|
|
||||||
|
|
||||||
## [1.3.0] - 2024-04-25
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Upgrade to Qt 6
|
|
||||||
|
|
||||||
## [1.2.0] - 2020-05-4
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Python 3 and Qt 5 compatibility
|
|
||||||
|
|
||||||
## [1.1.1b] - 2020-02-7
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Use python-distro to detect the distribution version
|
|
||||||
|
|
||||||
## [1.1.1] - 2019-05-23
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Set connection timeout
|
|
||||||
- Compatibility with "Exam Mode" from the University of Seville
|
|
||||||
|
|
||||||
## [1.1.0a] - 2019-05-22
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix a bug when activating the agent with some network devices
|
|
||||||
|
|
||||||
## [1.1.0] - 2016-10-13
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Functional OpenGnsys Agent interacting with OpenGnsys Server 1.1.0
|
|
||||||
|
|
||||||
## [1.0.0] - 2015-07-18
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Initial release for OpenGnsys Agent
|
|
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 43 KiB |
|
@ -1,47 +0,0 @@
|
||||||
## Crear tarea programada para matar el agente de Windows al cerrar sesión
|
|
||||||
|
|
||||||
1. Abrir el task scheduler y pinchar en Create task:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Rellenar el nombre y luego pinchar en Change user or group:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
3. Pinchar en Advanced:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
4. Pinchar en Find now:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
5. Seleccionar Administrator y luego Ok, y luego Ok:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
6. De vuelta en la pantalla de crear tarea, ir a la pestaña Triggers y pinchar en New:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
7. Seleccionar "On disconnect from user session", seleccionar "Connection from local computer", y luego Ok:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
8. Ir a la pestaña "Actions" y pinchar en New:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
9. Pinchar en Browse, seleccionar C:\Program Files (x86)\OGAgent\stop-agent.ps1, y luego Ok:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
10. Ir a la pestaña Conditions y desmarcar las condiciones relativas a Power:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
11. Pinchar Ok y la tarea programada queda creada.
|
|
||||||
|
|
||||||
En caso de usar remotepc, hay que repetir todos estos pasos, es decir, crear una
|
|
||||||
tarea programada nueva, seleccionando "Connection from remote computer" en lugar
|
|
||||||
de "Connection from local computer".
|
|
|
@ -51,9 +51,13 @@ install-ogagent:
|
||||||
cp scripts/OGAgentTool-startup $(BINDIR)
|
cp scripts/OGAgentTool-startup $(BINDIR)
|
||||||
cp scripts/OGAgentTool $(BINDIR)
|
cp scripts/OGAgentTool $(BINDIR)
|
||||||
|
|
||||||
|
# Copy Filebeat directory
|
||||||
|
cp -r $(SOURCEDIR)/filebeat $(LIBDIR)/filebeat
|
||||||
|
|
||||||
# Fix permissions
|
# Fix permissions
|
||||||
chmod 755 $(BINDIR)/ogagent
|
chmod 755 $(BINDIR)/ogagent
|
||||||
chmod 755 $(BINDIR)/OGAgentTool-startup
|
chmod 755 $(BINDIR)/OGAgentTool-startup
|
||||||
|
chmod 755 $(LIBDIR)/filebeat/install_filebeat.sh
|
||||||
chmod 755 $(LIBDIR)/OGAgentUser.py
|
chmod 755 $(LIBDIR)/OGAgentUser.py
|
||||||
chmod 600 $(LIBDIR)/cfg/ogagent.cfg
|
chmod 600 $(LIBDIR)/cfg/ogagent.cfg
|
||||||
|
|
||||||
|
|
|
@ -1,102 +1,4 @@
|
||||||
ogagent (5.1.1-1) stable; urgency=medium
|
ogagent (1.4.6-1) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
* Fix URL for notifying stop to ogcore
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Tue, 06 May 2025 13:31:48 +0200
|
|
||||||
|
|
||||||
ogagent (5.1.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Include powershell helper script for logging out of windows
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Tue, 06 May 2025 13:30:59 +0200
|
|
||||||
|
|
||||||
ogagent (5.0.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Use TLS
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Fri, 25 Apr 2025 13:09:49 +0200
|
|
||||||
|
|
||||||
ogagent (4.0.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Handle authn/authz in the oglive agent
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Thu, 24 Apr 2025 13:28:57 +0200
|
|
||||||
|
|
||||||
ogagent (3.3.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Create an additional json log file
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Mon, 14 Apr 2025 13:50:32 +0200
|
|
||||||
|
|
||||||
ogagent (3.2.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Operating system: periodically ping ogcore
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Thu, 10 Apr 2025 11:37:35 +0200
|
|
||||||
|
|
||||||
ogagent (3.1.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Oglive: periodically ping ogcore
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Mon, 07 Apr 2025 11:50:05 +0200
|
|
||||||
|
|
||||||
ogagent (3.0.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Ignore module provided in the URLs to the API
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Mon, 31 Mar 2025 10:16:07 +0200
|
|
||||||
|
|
||||||
ogagent (2.0.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* EjecutarScript/ConsolaRemota: expect "scp" parameter encoded in base64
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Wed, 26 Mar 2025 10:40:14 +0100
|
|
||||||
|
|
||||||
ogagent (1.7.1-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Make cfg2obj more robust
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Tue, 25 Mar 2025 13:31:33 +0100
|
|
||||||
|
|
||||||
ogagent (1.7.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Delete the new "ptt" parameter. It's not needed.
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Fri, 21 Mar 2025 14:19:56 +0100
|
|
||||||
|
|
||||||
ogagent (1.6.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Don't invoke bash code for some functionalities
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Wed, 12 Mar 2025 11:59:36 +0100
|
|
||||||
|
|
||||||
ogagent (1.5.0-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Accept new "ptt" parameter in /ogAdmCli/Configurar
|
|
||||||
* No longer recognise the unused "che" parameter in /ogAdmCli/Configurar
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Wed, 12 Mar 2025 11:45:37 +0100
|
|
||||||
|
|
||||||
ogagent (1.4.9-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Notify ogcore when agent shuts down within oglive
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Thu, 20 Feb 2025 11:58:29 +0100
|
|
||||||
|
|
||||||
ogagent (1.4.8-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Optionally return disk config in /status
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Tue, 18 Feb 2025 13:48:54 +0100
|
|
||||||
|
|
||||||
ogagent (1.4.7-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Merge server modules
|
|
||||||
* Track the progress of children
|
|
||||||
|
|
||||||
-- OpenGnsys developers <info@opengnsys.es> Tue, 04 Feb 2025 14:12:19 +0100
|
|
||||||
|
|
||||||
ogagent (1.4.6-1) stable; urgency=medium
|
|
||||||
|
|
||||||
* Point to the new menu browser
|
* Point to the new menu browser
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,6 @@ Priority: optional
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends:
|
Depends:
|
||||||
policykit-1 (>= 0.100), python3 (>=3.4) | python (>= 3.4), python3-pyqt6, python3-requests,
|
policykit-1 (>= 0.100), python3 (>=3.4) | python (>= 3.4), python3-pyqt6, python3-requests,
|
||||||
python3-six, python3-prctl, python3-distro, libxss1, zenity, ${misc:Depends}
|
python3-six, python3-prctl, python3-distro, libxss1, zenity, ${misc:Depends}, ${python3:Depends}, python3
|
||||||
Description: OpenGnsys Agent for Operating Systems
|
Description: OpenGnsys Agent for Operating Systems
|
||||||
This package provides the required components to allow this machine to work on an environment managed by OpenGnsys.
|
This package provides the required components to allow this machine to work on an environment managed by OpenGnsys.
|
||||||
|
|
|
@ -6,6 +6,17 @@ set -e
|
||||||
case "$1" in
|
case "$1" in
|
||||||
configure)
|
configure)
|
||||||
chmod 600 /usr/share/OGAgent/cfg/ogagent.cfg
|
chmod 600 /usr/share/OGAgent/cfg/ogagent.cfg
|
||||||
|
# Instalar filebeat directamente desde el paquete incluido
|
||||||
|
if [ -f /usr/share/OGAgent/filebeat/filebeat-oss-7.12.1-amd64.deb ]; then
|
||||||
|
echo "TRYING INSTALLING FILEBEAT"
|
||||||
|
# Crear un servicio temporal con un retraso de 30 segundos
|
||||||
|
systemd-run --quiet --unit=install-filebeat \
|
||||||
|
--on-active=30s \
|
||||||
|
/usr/share/OGAgent/filebeat/install_filebeat.sh
|
||||||
|
else
|
||||||
|
echo "Advertencia: El paquete filebeat no se encuentra en /usr/share/OGAgent/" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
;;
|
;;
|
||||||
abort-upgrade|abort-remove|abort-deconfigure)
|
abort-upgrade|abort-remove|abort-deconfigure)
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [ "$1" = "purge" ] ; then
|
if [ "$1" = "purge" ] ; then
|
||||||
|
update-rc.d ogagent remove || true
|
||||||
rm -rf /usr/share/OGAgent || true > /dev/null 2>&1
|
rm -rf /usr/share/OGAgent || true > /dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ ogausr_a = Analysis(
|
||||||
# ('cfg', 'cfg'), ## add the entire directory
|
# ('cfg', 'cfg'), ## add the entire directory
|
||||||
('img', 'img'), ## add the entire directory
|
('img', 'img'), ## add the entire directory
|
||||||
],
|
],
|
||||||
hiddenimports=['win32timezone', 'socketserver', 'http.server', 'urllib', 'opengnsys.modules.client.OpenGnSys', 'opengnsys.modules.server.ogAdmClient', 'opengnsys.modules.server.OpenGnSys'],
|
hiddenimports=['win32timezone', 'socketserver', 'http.server', 'urllib', 'opengnsys.modules.client.OpenGnSys', 'opengnsys.modules.server.CloningEngine', 'opengnsys.modules.server.ogAdmClient', 'opengnsys.modules.server.OpenGnSys'],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
|
@ -26,7 +26,7 @@ ogasvc_a = Analysis(
|
||||||
pathex=[],
|
pathex=[],
|
||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[],
|
datas=[],
|
||||||
hiddenimports=['win32timezone', 'socketserver', 'http.server', 'urllib', 'opengnsys.modules.client.OpenGnSys', 'opengnsys.modules.server.ogAdmClient', 'opengnsys.modules.server.OpenGnSys'],
|
hiddenimports=['win32timezone', 'socketserver', 'http.server', 'urllib', 'opengnsys.modules.client.OpenGnSys', 'opengnsys.modules.server.CloningEngine', 'opengnsys.modules.server.ogAdmClient', 'opengnsys.modules.server.OpenGnSys'],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
|
@ -98,5 +98,4 @@ coll = COLLECT(
|
||||||
)
|
)
|
||||||
|
|
||||||
import shutil
|
import shutil
|
||||||
shutil.copytree ('cfg', '{}/{}/cfg'. format(DISTPATH, dist_name))
|
shutil.copytree ('cfg', '{}/{}/cfg'.format(DISTPATH, dist_name))
|
||||||
shutil.copy ('stop-agent.ps1', '{}/{}/stop-agent.ps1'.format(DISTPATH, dist_name))
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
5.1.1
|
1.4.6
|
||||||
|
|
|
@ -17,12 +17,6 @@ level=full
|
||||||
# Log Level, if omitted, will be set to INFO
|
# Log Level, if omitted, will be set to INFO
|
||||||
log=DEBUG
|
log=DEBUG
|
||||||
|
|
||||||
# TLS
|
|
||||||
ca=C:\Program Files (x86)\OGagent\ca.crt
|
|
||||||
crt=C:\Program Files (x86)\OGagent\ogagent.crt
|
|
||||||
key=C:\Program Files (x86)\OGagent\ogagent.key
|
|
||||||
|
|
||||||
|
|
||||||
# Module specific
|
# Module specific
|
||||||
# The sections must match the module name
|
# The sections must match the module name
|
||||||
# This section will be passes on activation to module
|
# This section will be passes on activation to module
|
||||||
|
@ -35,7 +29,9 @@ pathinterface=/opt/opengnsys/interfaceAdm
|
||||||
urlMenu={}://{}/menu-browser
|
urlMenu={}://{}/menu-browser
|
||||||
urlMsg=http://localhost/cgi-bin/httpd-log.sh
|
urlMsg=http://localhost/cgi-bin/httpd-log.sh
|
||||||
|
|
||||||
# TLS
|
[CloningEngine]
|
||||||
ca=/opt/opengnsys/etc/ca.crt
|
remote={}://{}/opengnsys/rest
|
||||||
crt=/opt/opengnsys/etc/ogagent.crt
|
log=DEBUG
|
||||||
key=/opt/opengnsys/etc/ogagent.key
|
pathinterface=/opt/opengnsys/interfaceAdm
|
||||||
|
urlMenu={}://{}/menu-browser
|
||||||
|
urlMsg=http://localhost/cgi-bin/httpd-log.sh
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFCzCCAvMCFFUAATNZqrxFv9E6ni4/Gd7yikIxMA0GCSqGSIb3DQEBCwUAMEIx
|
||||||
|
CzAJBgNVBAYTAkVTMQ8wDQYDVQQIDAZNYWRyaWQxDzANBgNVBAcMBk1hZHJpZDER
|
||||||
|
MA8GA1UEAwwIY2EubXl0bGQwHhcNMjQxMjE4MTUxNDEyWhcNNDQxMjEzMTUxNDEy
|
||||||
|
WjBCMQswCQYDVQQGEwJFUzEPMA0GA1UECAwGTWFkcmlkMQ8wDQYDVQQHDAZNYWRy
|
||||||
|
aWQxETAPBgNVBAMMCGNhLm15dGxkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||||
|
CgKCAgEA0gXrrtQKNHKZ+BZs+x++CqobPy02Q1qPnPdD8Md5IXa9FyVHFdtB67j4
|
||||||
|
b5KbI03BU8pi8OHL4wnZI2nWizsao02zXl7ukNuKaWjh0pqTqgBxPjYIiREh4Nai
|
||||||
|
y5DywT9XESiB9LwRB5PDOa4zJPCMd5czumvXV1JCxJh/9wstys90d9lexGdiHWm6
|
||||||
|
TvLuI1kyiRh4vVS3L4Nr2pypgvI7JJsMCMjjvX6F1VosELgRRIqSFwrmqzCG0qV1
|
||||||
|
+FCtbLWZeto7HoVGdJx8XyyCpEYI4luXeGo+f61KZoXoqQ2+5CrTcik199TAdYUg
|
||||||
|
Oa3OlO4+PWRtLqqyn5gyg1Dhdj/hTvsPP/xXaJERdTn3dPYYzKTaJqja2cdkt8J5
|
||||||
|
YHz/Az+6cFEJbeWTrY+k8jvZX2i7QhylG9hcbXbflEA0woy6cqGmLxIZo5kcj0Hy
|
||||||
|
M1dUjvAMkKJgAyshjeUbhW7wH0XndQ9AQ518mPg0o4ygbjBCkeBSBqvsTQrRCdnb
|
||||||
|
+ogE+XzxWXEsNVXiysC3ZURpr+UHMHSeAYin2h8wjZsIC7fRVisdBOkYSYu9NQhU
|
||||||
|
3eLZtjhCgFSzxHOUJ7mI4SbGcw6awwr+irrQNg/HNL4EoEh7xwbvXMU09jA0JLWA
|
||||||
|
G7mpMs4PpAgNyYej68uignXlwDUruxYmZcSr/fQrvtWlCHtj5MUCAwEAATANBgkq
|
||||||
|
hkiG9w0BAQsFAAOCAgEABDXtALkRebuUQwFLpEd9INcfzVxtBNiheFJ3Ip/vzNFK
|
||||||
|
Wg9p1JYIQBB8nvYyr5OGBK0bvz40GZhXUwOxsPnXxjpZMQ2716wDI3BP7N9MP29c
|
||||||
|
0Zd/8+dgfbiRq0PURRThF0UEjFZeL/pr8wKP6YBl5xBKkRHgX8YG2RPQuf0GaIKB
|
||||||
|
jmHGVKsfROWpOS8xQzmeQQq2BLEVKhSdE/f3MqUl8/ml+dheAwaSrxicl5CcalTg
|
||||||
|
7TI6vdo85uoyI4WvSM1+yh5scNlLHvJlq1Poz/qKipukqY9YiKD0PpkY4BkM1qI8
|
||||||
|
AqYnT/W0rce/UvwQPBYsCXNU8rvQZ0gsxaTKTK2bgNLi9ahlfYkSpKmt+vS/mwBh
|
||||||
|
8PqkcAYqzNbWwmhQWK+QKVAOJHRPoXAwgoG7YFHYDTeNetroLzJsGL9IJojuO0vK
|
||||||
|
Ug7wLTSbh/8Y35WB4gyNfJX+7VdWyiZXL/aPtjWBP6ts7oJuUYrU+s4oaap7suL4
|
||||||
|
b85JN+/zlXP2X3EswCFhHSveuHJtkVnUBOpxa54YRw2N3MqOPSS+Csy0lu1qmfcP
|
||||||
|
/1+S/VtxM9s5P1cyK3zIww0DSSAz5O/WWcI9Zt9lAUCp0V6ubQxk3MVIimvv8mkZ
|
||||||
|
E9gCCqd7VgrZvZTGz1uaNWv60MUD2SHwEg4IOQQo7+szsDx3jQkTJYBwtB4eTaw=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEsTCCApmgAwIBAgICEAcwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCRVMx
|
||||||
|
DzANBgNVBAgMBk1hZHJpZDEPMA0GA1UEBwwGTWFkcmlkMREwDwYDVQQDDAhjYS5t
|
||||||
|
eXRsZDAeFw0yNDEyMTgxNTE0MTRaFw0yNTEyMjgxNTE0MTRaMEoxCzAJBgNVBAYT
|
||||||
|
AkVTMQ8wDQYDVQQIDAZNYWRyaWQxDzANBgNVBAcMBk1hZHJpZDEZMBcGA1UEAwwQ
|
||||||
|
b2dhZ2VudC1mYi5teXRsZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||||
|
AMoywL3S1gPxsTfkLWX/cNGIz0S0+KhtrBtVRrRPKL6Snu67Zo9KjQL7+Slp5ybR
|
||||||
|
0F5ZnK+XDBmMaqbAKTBxNb5jmui+3ACbwpD1c+TGMR96wVj2BOr6z+Ir0a1iE4mS
|
||||||
|
cAXlXPl4UFqcmcS+fRlkrtLuR7b94oxtwkKxqw1hq0irQAmJPKN2X3uL2etM99/E
|
||||||
|
Ll4LR7dZlCd0FBMN8Ku/8TSG5Z/liCSs/AFaY/PYJZ61rCIIeHxiixQXJqvtyhjV
|
||||||
|
8q82ezwrvW4yK3y1gBBNA6Njwpaz/foWaUEEgD+MgIavVIxaRMCnqPFBn+uulZqh
|
||||||
|
TMztgxLX//zfjXxCBWQdRAkCAwEAAaOBqDCBpTAbBgNVHREEFDASghBvZ2FnZW50
|
||||||
|
LWZiLm15dGxkMB0GA1UdDgQWBBQjcSfmTGnC+nzg13aLxBdEKluMfTBnBgNVHSME
|
||||||
|
YDBeoUakRDBCMQswCQYDVQQGEwJFUzEPMA0GA1UECAwGTWFkcmlkMQ8wDQYDVQQH
|
||||||
|
DAZNYWRyaWQxETAPBgNVBAMMCGNhLm15dGxkghRVAAEzWaq8Rb/ROp4uPxne8opC
|
||||||
|
MTANBgkqhkiG9w0BAQsFAAOCAgEAlf5LgmqjJxXD0j8A0uOXibNlhullEtPZAskl
|
||||||
|
HKOpwyHO+wLgTkQVLR7Kx88l0Kqje/YI61AUyXrK+6qvfevHWNgMxyVc0n9bW0Qk
|
||||||
|
qgPOjYA3/l6vJOcODFKYkigeF4GHbicBFmmha8eVCLBmNEsmbZlqyeKjC0WpnyhL
|
||||||
|
OFxGwqjC3vqH59eS4ufW1pWSNw+pSXj5QeyhDcla1kZWgx0hgsBkEODI9RZ32mKk
|
||||||
|
wHGUYhpFBO0Xg3AUiOfMUcMbhCojAC3xZ2hdw+joVkLgFnEoh2nuSEIGwb+bNGiH
|
||||||
|
9Qr23gLuilsGwD1fev4NA09ityaadutNL+XNBOKM811fJsfvnOMD/6d0RnCdg7gw
|
||||||
|
zT+XL6YhQmzSzs2NnMUUCbg85DGG4LVyvELzs6deLuEF4qp7udATYrdJZ9P1nNEs
|
||||||
|
XWs6/4Y1RX5TRO5sWeWEdgMP1Avlu9fkxJGipbABsptUbDsQIJyBvWLfbQ/++yKv
|
||||||
|
d10CJxHosT88qqn/oT8hBhvJC6yrOI0ZUszfaf7taYlGDSJj+azSuTkZ12yaQ4ql
|
||||||
|
YVgyO8w7KI6fpldnWOK3ReAAR6g0GI1d5ZRnx82RVg/NUkMgMoWcuCV386vo6Y5T
|
||||||
|
2CBmg1khtAASJAS2MnCi7qJNJH0WZy/pFCbN0bJzKsDqz3DAa4huA3v9PmFJ8OcK
|
||||||
|
QG0vBDg=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDKMsC90tYD8bE3
|
||||||
|
5C1l/3DRiM9EtPiobawbVUa0Tyi+kp7uu2aPSo0C+/kpaecm0dBeWZyvlwwZjGqm
|
||||||
|
wCkwcTW+Y5rovtwAm8KQ9XPkxjEfesFY9gTq+s/iK9GtYhOJknAF5Vz5eFBanJnE
|
||||||
|
vn0ZZK7S7ke2/eKMbcJCsasNYatIq0AJiTyjdl97i9nrTPffxC5eC0e3WZQndBQT
|
||||||
|
DfCrv/E0huWf5YgkrPwBWmPz2CWetawiCHh8YosUFyar7coY1fKvNns8K71uMit8
|
||||||
|
tYAQTQOjY8KWs/36FmlBBIA/jICGr1SMWkTAp6jxQZ/rrpWaoUzM7YMS1//83418
|
||||||
|
QgVkHUQJAgMBAAECggEABROoJjv8dqXjYrlecHCs9v3d4mY+1g/G4frOpylTpxFM
|
||||||
|
X0ciSJfBGaGU/Ha1wJJFDpFmbzw2KBAP/3bUsewtwsWCdrSQFo3SoUwgaE6Xnig5
|
||||||
|
YY/vyKyaep3KCnXrcqlUGbnMD1F3hwbmj3uO7YvLHe2wrEYMoaUB2yXV2ySoJc9n
|
||||||
|
ghbRU3oaDl1rZWtDFxSSVLuntYkahST8bqiznUCVNd2DfyZJ0yUTzX/MxgKe0MSo
|
||||||
|
qPFsnBnLRgywl3hfG/gR/rtVwDZGxY/KhCX9mHEzk74/iCQasguCatdC862ZFUaK
|
||||||
|
YSRVn6i25Eja+PSTrSNEqkXe65RRNBzunjTroJu9AQKBgQDrrdPXTW3NsnS5tsKi
|
||||||
|
4TLriWRoeLVG5QUvcVhmCrYYunAkU9X3DaJyfn5rMLnpKhSDDj0/zPsGFSXPaax4
|
||||||
|
XP/xwYZBezXlqBALWtUtecZ+lWaLxIPrPto02Le/ARTELolfXF72NBmGovtNlwnG
|
||||||
|
4i8mvx0G/NS/tn8GIryBD02DwQKBgQDboeZ+QpkEN3mkeETdsTiYvSl8qGJ8DJpd
|
||||||
|
VgAs5tyARgOQHBlfPQRSgNIgxlLs+UMMW5Q3l53B2bAh8v64cEalZyRJsWYD+5BW
|
||||||
|
v7T08RoofuL087F1u2/IscgUuEacZKcjrRvvugIvh6TLPhPePqN/MUe0Gd163Czr
|
||||||
|
XQQaiQcySQKBgQDTQRBnqJ8pR7J7mcfj6osTOCeJwdF0R+ua+DWt2iIaDlxhI8ji
|
||||||
|
WBVqHdrByH6M80xJoWTjoKDOdfxbbDTN+0bs9HSck43fWwNuui/mQIbdhpvR4wgA
|
||||||
|
wWkk/7HNA3IS3EgE866ncFIFLmimxyFbZfmv+JVTYyRs6G/6Fv7zjL0FwQKBgB0O
|
||||||
|
OA3wBYo3RJJrjsC9Vz1tmPVy2USL7kf2vqMyD22w1XvVG84rpky72hCX7BSJjUMv
|
||||||
|
QlZwamBgyhpTqTsBL3dmQ7i0DUjtmNTBG9FjrBA7aQ76xjlLCKjGTC/hiQXbkvj3
|
||||||
|
R8DZHLzo9vYkSkCWjM6g2FmNKm28fvzMG2TfR+JxAoGAbycyqTwbUXgv030Mcmtu
|
||||||
|
SnIqVsUW5aZ7UoAsWRo10vo2OpVQ+2FT+jcChnue0G5ffy7344wRN4Q+xixG/hlP
|
||||||
|
QdMwhl94+Cj9DHxwTuPELfahr0289tcjHP+CTw1SlTgDR7bgaa9/PVJeUl8mreuC
|
||||||
|
lolkshxjAE5pFYIG3ozFIoY=
|
||||||
|
-----END PRIVATE KEY-----
|
|
@ -0,0 +1,36 @@
|
||||||
|
logging.level: info
|
||||||
|
logging.to_files: true
|
||||||
|
logging.files:
|
||||||
|
path: /var/log/filebeat
|
||||||
|
name: filebeat
|
||||||
|
keepfiles: 7
|
||||||
|
permissions: 0640
|
||||||
|
|
||||||
|
filebeat.inputs:
|
||||||
|
- type: log
|
||||||
|
enabled: true
|
||||||
|
paths:
|
||||||
|
- /var/log/opengnsys.log
|
||||||
|
|
||||||
|
setup.template.settings:
|
||||||
|
index.number_of_shards: 1
|
||||||
|
|
||||||
|
output.elasticsearch:
|
||||||
|
hosts: ["oglog-os.mytld:9200"]
|
||||||
|
username: "admin"
|
||||||
|
password: "CorrectHorse_BatteryStaple1"
|
||||||
|
protocol: "https"
|
||||||
|
ssl.enabled: true
|
||||||
|
ssl.verification_mode: full
|
||||||
|
ssl.certificate: "/etc/filebeat/ogagent-fb.mytld.crt.pem"
|
||||||
|
ssl.key: "/etc/filebeat/ogagent-fb.mytld.key.pem"
|
||||||
|
|
||||||
|
processors:
|
||||||
|
- add_host_metadata:
|
||||||
|
when.not.contains.tags: forwarded
|
||||||
|
- add_cloud_metadata: ~
|
||||||
|
- add_docker_metadata: ~
|
||||||
|
- add_kubernetes_metadata: ~
|
||||||
|
|
||||||
|
seccomp.enabled: false
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Install Filebeat package
|
||||||
|
echo "INSTALLING FILEBEAT"
|
||||||
|
|
||||||
|
# Función para esperar a que el lock de dpkg esté libre
|
||||||
|
wait_for_dpkg_lock() {
|
||||||
|
while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 ; do
|
||||||
|
echo "Esperando a que el lock de dpkg se libere..."
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Esperar máximo 2 minutos hasta que dpkg esté listo
|
||||||
|
wait_for_dpkg_lock
|
||||||
|
|
||||||
|
|
||||||
|
dpkg -i --force-overwrite /usr/share/OGAgent/filebeat/filebeat-oss-7.12.1-amd64.deb
|
||||||
|
|
||||||
|
# Copy certificates and configuration
|
||||||
|
cp /usr/share/OGAgent/filebeat/CA/ogagent-fb.mytld.crt.pem /etc/filebeat/
|
||||||
|
cp /usr/share/OGAgent/filebeat/CA/ogagent-fb.mytld.key.pem /etc/filebeat/
|
||||||
|
cp /usr/share/OGAgent/filebeat/CA/ca.crt.pem /etc/ssl/certs/
|
||||||
|
cp /usr/share/OGAgent/filebeat/filebeat.yml /etc/filebeat/filebeat.yml
|
||||||
|
|
||||||
|
# Add entry to /etc/hosts
|
||||||
|
oglog_ip="${OGAGENTCFG_OGLOG_IP:-192.168.2.1}"
|
||||||
|
echo "${oglog_ip} oglog-os.mytld" >> /etc/hosts
|
||||||
|
|
||||||
|
# Start Filebeat
|
||||||
|
/usr/bin/filebeat --environment systemd -c /etc/filebeat/filebeat.yml --path.home /usr/share/filebeat --path.config /etc/filebeat --path.data /var/lib/filebeat --path.logs /var/log/filebeat &
|
|
@ -34,7 +34,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
@ -44,6 +43,7 @@ from .log import logger
|
||||||
|
|
||||||
from .utils import exceptionToMessage
|
from .utils import exceptionToMessage
|
||||||
|
|
||||||
|
VERIFY_CERT = False # Do not check server certificate
|
||||||
TIMEOUT = 5 # Connection timout, in seconds
|
TIMEOUT = 5 # Connection timout, in seconds
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,12 +58,8 @@ class ConnectionError(RESTError):
|
||||||
# Disable warnings log messages
|
# Disable warnings log messages
|
||||||
try:
|
try:
|
||||||
import urllib3 # @UnusedImport
|
import urllib3 # @UnusedImport
|
||||||
requests_log = logging.getLogger ('urllib3')
|
|
||||||
requests_log.setLevel (logging.INFO)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
from requests.packages import urllib3 # @Reimport
|
from requests.packages import urllib3 # @Reimport
|
||||||
requests_log = logging.getLogger ('requests.packages.urllib3')
|
|
||||||
requests_log.setLevel (logging.INFO)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
urllib3.disable_warnings() # @UndefinedVariable
|
urllib3.disable_warnings() # @UndefinedVariable
|
||||||
|
@ -88,7 +84,7 @@ class REST(object):
|
||||||
the deserialized JSON result or raises an exception in case of error
|
the deserialized JSON result or raises an exception in case of error
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, url, ca_file=None, crt_file=None, key_file=None):
|
def __init__(self, url):
|
||||||
"""
|
"""
|
||||||
Initializes the REST helper
|
Initializes the REST helper
|
||||||
url is the full url of the REST API Base, as for example "https://example.com/rest/v1".
|
url is the full url of the REST API Base, as for example "https://example.com/rest/v1".
|
||||||
|
@ -105,26 +101,6 @@ class REST(object):
|
||||||
except Exception:
|
except Exception:
|
||||||
self.newerRequestLib = False # I no version, guess this must be an old requests
|
self.newerRequestLib = False # I no version, guess this must be an old requests
|
||||||
|
|
||||||
if not self.newerRequestLib:
|
|
||||||
logger.debug ('TLS not available: python requests library is old')
|
|
||||||
|
|
||||||
self.use_tls = url.startswith ('https')
|
|
||||||
if self.use_tls:
|
|
||||||
if not ca_file or not crt_file or not key_file:
|
|
||||||
raise Exception ('missing TLS parameters in REST constructor')
|
|
||||||
|
|
||||||
errs = 0
|
|
||||||
for f in [ca_file, crt_file, key_file]:
|
|
||||||
if not os.path.exists (f):
|
|
||||||
logger.error (f'{f}: No such file or directory')
|
|
||||||
errs += 1
|
|
||||||
if errs:
|
|
||||||
raise Exception ('TLS files not found')
|
|
||||||
|
|
||||||
self.ca_file = ca_file
|
|
||||||
self.crt_file = crt_file
|
|
||||||
self.key_file = key_file
|
|
||||||
|
|
||||||
# Disable logging requests messages except for errors, ...
|
# Disable logging requests messages except for errors, ...
|
||||||
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
||||||
# Tries to disable all warnings
|
# Tries to disable all warnings
|
||||||
|
@ -155,19 +131,14 @@ class REST(object):
|
||||||
logger.debug('Requesting using GET (no data provided) {}'.format(url))
|
logger.debug('Requesting using GET (no data provided) {}'.format(url))
|
||||||
# Old requests version does not support verify, but it do not checks ssl certificate by default
|
# Old requests version does not support verify, but it do not checks ssl certificate by default
|
||||||
if self.newerRequestLib:
|
if self.newerRequestLib:
|
||||||
if self.use_tls:
|
r = requests.get(url, verify=VERIFY_CERT, timeout=TIMEOUT)
|
||||||
r = requests.get(url, cert=(self.crt_file, self.key_file), verify=self.ca_file, timeout=TIMEOUT)
|
|
||||||
else:
|
|
||||||
r = requests.get(url, timeout=TIMEOUT)
|
|
||||||
else:
|
else:
|
||||||
r = requests.get(url)
|
r = requests.get(url)
|
||||||
else: # POST
|
else: # POST
|
||||||
logger.debug('Requesting using POST {}, data: {}'.format(url, data))
|
logger.debug('Requesting using POST {}, data: {}'.format(url, data))
|
||||||
if self.newerRequestLib:
|
if self.newerRequestLib:
|
||||||
if self.use_tls:
|
r = requests.post(url, data=data, headers={'content-type': 'application/json'},
|
||||||
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, cert=(self.crt_file, self.key_file), verify=self.ca_file, timeout=TIMEOUT)
|
verify=VERIFY_CERT, timeout=TIMEOUT)
|
||||||
else:
|
|
||||||
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, timeout=TIMEOUT)
|
|
||||||
else:
|
else:
|
||||||
r = requests.post(url, data=data, headers={'content-type': 'application/json'})
|
r = requests.post(url, data=data, headers={'content-type': 'application/json'})
|
||||||
|
|
||||||
|
@ -177,9 +148,7 @@ class REST(object):
|
||||||
raise Exception (f'response content-type is not "application/json" but "{ct}"')
|
raise Exception (f'response content-type is not "application/json" but "{ct}"')
|
||||||
r = json.loads(r.content) # Using instead of r.json() to make compatible with old requests lib versions
|
r = json.loads(r.content) # Using instead of r.json() to make compatible with old requests lib versions
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
code = e.response.status_code
|
raise ConnectionError(e)
|
||||||
logger.warning (f'request failed, HTTP code "{code}"')
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ConnectionError(exceptionToMessage(e))
|
raise ConnectionError(exceptionToMessage(e))
|
||||||
|
|
||||||
|
@ -191,13 +160,13 @@ class REST(object):
|
||||||
@param data: if None or omitted, message will be a GET, else it will send a POST
|
@param data: if None or omitted, message will be a GET, else it will send a POST
|
||||||
@param processData: if True, data will be serialized to json before sending, else, data will be sent as "raw"
|
@param processData: if True, data will be serialized to json before sending, else, data will be sent as "raw"
|
||||||
"""
|
"""
|
||||||
#logger.debug('Invoking post message {} with data {}'.format(msg, data))
|
logger.debug('Invoking post message {} with data {}'.format(msg, data))
|
||||||
|
|
||||||
if processData and data is not None:
|
if processData and data is not None:
|
||||||
data = json.dumps(data)
|
data = json.dumps(data)
|
||||||
|
|
||||||
url = self._getUrl(msg)
|
url = self._getUrl(msg)
|
||||||
#logger.debug('Requesting {}'.format(url))
|
logger.debug('Requesting {}'.format(url))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = self._request(url, data)
|
res = self._request(url, data)
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import ssl
|
import ssl
|
||||||
import threading
|
import threading
|
||||||
|
@ -78,11 +77,8 @@ class HTTPServerHandler(BaseHTTPRequestHandler):
|
||||||
except Exception:
|
except Exception:
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
## quick override because universities do not actually want the module to be extracted out of the URL
|
|
||||||
module = 'ogAdmClient' if os.path.exists ('/scripts/oginit') else 'opengnsys'
|
|
||||||
|
|
||||||
for v in self.service.modules:
|
for v in self.service.modules:
|
||||||
if v.name == module: # Case Sensitive!!!!
|
if v.name == path[0]: # Case Sensitive!!!!
|
||||||
return v, path[1:], params
|
return v, path[1:], params
|
||||||
|
|
||||||
return None, path, params
|
return None, path, params
|
||||||
|
|
|
@ -34,8 +34,6 @@ import logging
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from ..log_format import JsonFormatter
|
|
||||||
|
|
||||||
# Logging levels
|
# Logging levels
|
||||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
|
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
|
||||||
|
|
||||||
|
@ -50,25 +48,15 @@ class LocalLogger(object):
|
||||||
|
|
||||||
for logDir in ('/var/log', os.path.expanduser('~'), tempfile.gettempdir()):
|
for logDir in ('/var/log', os.path.expanduser('~'), tempfile.gettempdir()):
|
||||||
try:
|
try:
|
||||||
fname1 = os.path.join (logDir, 'opengnsys.log')
|
fname = os.path.join(logDir, 'opengnsys.log')
|
||||||
fmt1 = logging.Formatter (fmt='%(levelname)s %(asctime)s (%(threadName)s) (%(funcName)s) %(message)s')
|
logging.basicConfig(
|
||||||
fh1 = logging.FileHandler (filename=fname1, mode='a')
|
filename=fname,
|
||||||
fh1.setFormatter (fmt1)
|
filemode='a',
|
||||||
fh1.setLevel (logging.DEBUG)
|
format='%(levelname)s %(asctime)s (%(threadName)s) (%(funcName)s) %(message)s',
|
||||||
|
level=logging.DEBUG
|
||||||
fname2 = os.path.join (logDir, 'opengnsys.json.log')
|
)
|
||||||
fmt2 = JsonFormatter ({"timestamp": "asctime", "severity": "levelname", "threadName": "threadName", "function": "funcName", "message": "message"}, time_format='%Y-%m-%d %H:%M:%S', msec_format='')
|
self.logger = logging.getLogger('opengnsys')
|
||||||
fh2 = logging.FileHandler (filename=fname2, mode='a')
|
os.chmod(fname, 0o0600)
|
||||||
fh2.setFormatter (fmt2)
|
|
||||||
fh2.setLevel (logging.DEBUG)
|
|
||||||
|
|
||||||
self.logger = logging.getLogger ('opengnsys')
|
|
||||||
self.logger.setLevel (logging.DEBUG)
|
|
||||||
self.logger.addHandler (fh1)
|
|
||||||
self.logger.addHandler (fh2)
|
|
||||||
|
|
||||||
os.chmod (fname1, 0o0600)
|
|
||||||
os.chmod (fname2, 0o0600)
|
|
||||||
return
|
return
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
|
|
||||||
class JsonFormatter(logging.Formatter):
|
|
||||||
"""
|
|
||||||
Formatter that outputs JSON strings after parsing the LogRecord.
|
|
||||||
|
|
||||||
@param dict fmt_dict: Key: logging format attribute pairs. Defaults to {"message": "message"}.
|
|
||||||
@param str time_format: time.strftime() format string. Default: "%Y-%m-%dT%H:%M:%S"
|
|
||||||
@param str msec_format: Microsecond formatting. Appended at the end. Default: "%s.%03dZ"
|
|
||||||
"""
|
|
||||||
def __init__(self, fmt_dict: dict = None, time_format: str = "%Y-%m-%dT%H:%M:%S", msec_format: str = "%s.%03dZ"):
|
|
||||||
self.fmt_dict = fmt_dict if fmt_dict is not None else {"message": "message"}
|
|
||||||
self.default_time_format = time_format
|
|
||||||
self.default_msec_format = msec_format
|
|
||||||
self.datefmt = None
|
|
||||||
|
|
||||||
def usesTime(self) -> bool:
|
|
||||||
"""
|
|
||||||
Overwritten to look for the attribute in the format dict values instead of the fmt string.
|
|
||||||
"""
|
|
||||||
return "asctime" in self.fmt_dict.values()
|
|
||||||
|
|
||||||
def formatMessage(self, record) -> dict:
|
|
||||||
"""
|
|
||||||
Overwritten to return a dictionary of the relevant LogRecord attributes instead of a string.
|
|
||||||
KeyError is raised if an unknown attribute is provided in the fmt_dict.
|
|
||||||
"""
|
|
||||||
return {fmt_key: record.__dict__[fmt_val] for fmt_key, fmt_val in self.fmt_dict.items()}
|
|
||||||
|
|
||||||
def format(self, record) -> str:
|
|
||||||
"""
|
|
||||||
Mostly the same as the parent's class method, the difference being that a dict is manipulated and dumped as JSON
|
|
||||||
instead of a string.
|
|
||||||
"""
|
|
||||||
record.message = record.getMessage()
|
|
||||||
|
|
||||||
if self.usesTime():
|
|
||||||
record.asctime = self.formatTime(record, self.datefmt)
|
|
||||||
|
|
||||||
message_dict = self.formatMessage(record)
|
|
||||||
|
|
||||||
if record.exc_info:
|
|
||||||
# Cache the traceback text to avoid converting it multiple times
|
|
||||||
# (it's constant anyway)
|
|
||||||
if not record.exc_text:
|
|
||||||
record.exc_text = self.formatException(record.exc_info)
|
|
||||||
|
|
||||||
if record.exc_text:
|
|
||||||
message_dict["exc_info"] = record.exc_text
|
|
||||||
|
|
||||||
if record.stack_info:
|
|
||||||
message_dict["stack_info"] = self.formatStack(record.stack_info)
|
|
||||||
|
|
||||||
return json.dumps(message_dict, default=str)
|
|
|
@ -0,0 +1,355 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 Qindel Formación y Servicios S.L.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
"""
|
||||||
|
@author: Natalia Serrano, nserrano at qindel dot com
|
||||||
|
"""
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from opengnsys.log import logger
|
||||||
|
from opengnsys.workers import ogLiveWorker
|
||||||
|
|
||||||
|
class CloningEngineWorker (ogLiveWorker):
|
||||||
|
name = 'CloningEngine' # Module name
|
||||||
|
REST = None # REST object
|
||||||
|
|
||||||
|
def onActivation (self):
|
||||||
|
super().onActivation (run_monitoring_thread=False)
|
||||||
|
logger.info ('onActivation ok')
|
||||||
|
|
||||||
|
def onDeactivation (self):
|
||||||
|
logger.debug ('onDeactivation')
|
||||||
|
|
||||||
|
def InventariandoSoftware (self, dsk, par, nfn):
|
||||||
|
sft_src = f'/tmp/CSft-{self.IPlocal}-{par}'
|
||||||
|
try:
|
||||||
|
self.interfaceAdmin (nfn, [dsk, par, sft_src])
|
||||||
|
herror = 0
|
||||||
|
except:
|
||||||
|
herror = 1
|
||||||
|
|
||||||
|
if herror:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
b64 = ''
|
||||||
|
self.muestraMensaje (20)
|
||||||
|
else:
|
||||||
|
if not os.path.exists (sft_src):
|
||||||
|
raise Exception (f'interfaceAdmin({nfn}) returned success but did not create file ({sft_src})')
|
||||||
|
sft_src_contents = Path (sft_src).read_bytes()
|
||||||
|
|
||||||
|
b64 = base64.b64encode (sft_src_contents).decode ('utf-8')
|
||||||
|
self.muestraMensaje (19)
|
||||||
|
|
||||||
|
cmd = {
|
||||||
|
'nfn': 'RESPUESTA_InventarioSoftware',
|
||||||
|
'dsk': dsk, ## not in the original C code, around ogAdmClient.c:1944
|
||||||
|
'par': par,
|
||||||
|
'contents': b64,
|
||||||
|
}
|
||||||
|
return self.respuestaEjecucionComando (cmd, herror, 0)
|
||||||
|
|
||||||
|
def do_CrearImagen (self, post_params):
|
||||||
|
for k in ['dsk', 'par', 'cpt', 'idi', 'nci', 'ipr', 'nfn', 'ids']:
|
||||||
|
if k not in post_params:
|
||||||
|
logger.error (f'required parameter ({k}) not in POST params')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
dsk = post_params['dsk'] ## Disco
|
||||||
|
par = post_params['par'] ## Número de partición
|
||||||
|
cpt = post_params['cpt'] ## Código de la partición
|
||||||
|
idi = post_params['idi'] ## Identificador de la imagen
|
||||||
|
nci = post_params['nci'] ## Nombre canónico de la imagen
|
||||||
|
ipr = post_params['ipr'] ## Ip del repositorio
|
||||||
|
nfn = post_params['nfn']
|
||||||
|
ids = post_params['ids']
|
||||||
|
|
||||||
|
self.muestraMensaje (7)
|
||||||
|
|
||||||
|
try:
|
||||||
|
res = self.InventariandoSoftware (dsk, par, 'InventarioSoftware') ## Crea inventario Software previamente
|
||||||
|
except:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
if res['contents']:
|
||||||
|
self.muestraMensaje (2)
|
||||||
|
inv_sft = res['contents']
|
||||||
|
try:
|
||||||
|
self.interfaceAdmin (nfn, [dsk, par, nci, ipr])
|
||||||
|
self.muestraMensaje (9)
|
||||||
|
herror = 0
|
||||||
|
except:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
self.muestraMensaje (10)
|
||||||
|
herror = 1
|
||||||
|
else:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
inv_sft = ''
|
||||||
|
|
||||||
|
self.muestraMenu()
|
||||||
|
|
||||||
|
cmd = {
|
||||||
|
'nfn': 'RESPUESTA_CrearImagen',
|
||||||
|
'idi': idi, ## Identificador de la imagen
|
||||||
|
'dsk': dsk, ## Número de disco
|
||||||
|
'par': par, ## Número de partición de donde se creó
|
||||||
|
'cpt': cpt, ## Tipo o código de partición
|
||||||
|
'ipr': ipr, ## Ip del repositorio donde se alojó
|
||||||
|
'inv_sft': inv_sft,
|
||||||
|
}
|
||||||
|
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||||
|
|
||||||
|
def do_RestaurarImagen (self, post_params):
|
||||||
|
for k in ['dsk', 'par', 'idi', 'ipr', 'nci', 'ifs', 'ptc', 'nfn', 'ids']:
|
||||||
|
if k not in post_params:
|
||||||
|
logger.error (f'required parameter ({k}) not in POST params')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
dsk = post_params['dsk']
|
||||||
|
par = post_params['par']
|
||||||
|
idi = post_params['idi']
|
||||||
|
ipr = post_params['ipr']
|
||||||
|
nci = post_params['nci']
|
||||||
|
ifs = post_params['ifs']
|
||||||
|
ptc = post_params['ptc'] ## Protocolo de clonación: Unicast, Multicast, Torrent
|
||||||
|
nfn = post_params['nfn']
|
||||||
|
ids = post_params['ids']
|
||||||
|
|
||||||
|
self.muestraMensaje (3)
|
||||||
|
|
||||||
|
try:
|
||||||
|
## the ptc.split() is useless right now, since interfaceAdmin() does ' '.join(params) in order to spawn a shell
|
||||||
|
## however we're going to need it in the future (when everything gets translated into python), plus it's harmless now. So let's do it
|
||||||
|
#self.interfaceAdmin (nfn, [dsk, par, nci, ipr, ptc])
|
||||||
|
self.interfaceAdmin (nfn, [dsk, par, nci, ipr] + ptc.split())
|
||||||
|
self.muestraMensaje (11)
|
||||||
|
herror = 0
|
||||||
|
except:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
self.muestraMensaje (12)
|
||||||
|
herror = 1
|
||||||
|
|
||||||
|
cfg = self.LeeConfiguracion()
|
||||||
|
if not cfg:
|
||||||
|
logger.warning ('No se ha podido recuperar la configuración de las particiones del disco')
|
||||||
|
|
||||||
|
self.muestraMenu()
|
||||||
|
|
||||||
|
cmd = {
|
||||||
|
'nfn': 'RESPUESTA_RestaurarImagen',
|
||||||
|
'idi': idi, ## Identificador de la imagen
|
||||||
|
'dsk': dsk, ## Número de disco
|
||||||
|
'par': par, ## Número de partición
|
||||||
|
'ifs': ifs, ## Identificador del perfil software
|
||||||
|
'cfg': self.cfg2obj(cfg), ## Configuración de discos
|
||||||
|
}
|
||||||
|
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||||
|
|
||||||
|
def process_status (self, path, get_params, post_params, server):
|
||||||
|
thr_status = {}
|
||||||
|
for k in self.thread_list:
|
||||||
|
thr_status[k] = {
|
||||||
|
'running': self.thread_list[k]['running'],
|
||||||
|
'result': self.thread_list[k]['result'],
|
||||||
|
}
|
||||||
|
return thr_status
|
||||||
|
|
||||||
|
def do_Configurar (self, post_params):
|
||||||
|
for k in ['nfn', 'dsk', 'cfg', 'ids']:
|
||||||
|
if k not in post_params:
|
||||||
|
logger.error (f'required parameter ({k}) not in POST params')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
nfn = post_params['nfn']
|
||||||
|
dsk = post_params['dsk']
|
||||||
|
cfg = post_params['cfg']
|
||||||
|
ids = post_params['ids']
|
||||||
|
|
||||||
|
self.muestraMensaje (4)
|
||||||
|
|
||||||
|
params = []
|
||||||
|
disk_info = cfg.pop (0)
|
||||||
|
logger.debug (f'disk_info ({disk_info})')
|
||||||
|
for k in ['dis', 'che', 'tch']:
|
||||||
|
params.append (f'{k}={disk_info[k]}')
|
||||||
|
disk_info_str = '*'.join (params)
|
||||||
|
|
||||||
|
partitions = []
|
||||||
|
for entry in cfg:
|
||||||
|
logger.debug (f'entry ({entry})')
|
||||||
|
params = []
|
||||||
|
for k in ['par', 'cpt', 'sfi', 'tam', 'ope']:
|
||||||
|
params.append (f'{k}={entry[k]}')
|
||||||
|
partitions.append ('*'.join (params))
|
||||||
|
part_info_str = '%'.join (partitions)
|
||||||
|
|
||||||
|
cfg_str = f'{disk_info_str}!{part_info_str}%'
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.interfaceAdmin (nfn, ['ignored', cfg_str])
|
||||||
|
self.muestraMensaje (14)
|
||||||
|
herror = 0
|
||||||
|
except:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
self.muestraMensaje (13)
|
||||||
|
herror = 1
|
||||||
|
|
||||||
|
cfg = self.LeeConfiguracion()
|
||||||
|
if not cfg:
|
||||||
|
logger.warning ('No se ha podido recuperar la configuración de las particiones del disco')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
cmd = {
|
||||||
|
'nfn': 'RESPUESTA_Configurar',
|
||||||
|
'cfg': self.cfg2obj (cfg),
|
||||||
|
}
|
||||||
|
self.muestraMenu()
|
||||||
|
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||||
|
|
||||||
|
def do_InventarioHardware (self, post_params):
|
||||||
|
for k in ['nfn', 'ids']:
|
||||||
|
if k not in post_params:
|
||||||
|
logger.error (f'required parameter ({k}) not in POST params')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
nfn = post_params['nfn']
|
||||||
|
ids = post_params['ids']
|
||||||
|
|
||||||
|
self.muestraMensaje (6)
|
||||||
|
|
||||||
|
hrdsrc = f'/tmp/Chrd-{self.IPlocal}' ## Nombre que tendra el archivo de inventario
|
||||||
|
hrddst = f'/tmp/Shrd-{self.IPlocal}' ## Nombre que tendra el archivo en el Servidor
|
||||||
|
try:
|
||||||
|
self.interfaceAdmin (nfn, [hrdsrc])
|
||||||
|
hrdsrc_contents = Path (hrdsrc).read_bytes()
|
||||||
|
logger.debug (f'hrdsrc_contents 1 ({hrdsrc_contents})')
|
||||||
|
herror = 0
|
||||||
|
except:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
self.muestraMensaje (18)
|
||||||
|
herror = 1
|
||||||
|
|
||||||
|
if herror:
|
||||||
|
hrddst = ''
|
||||||
|
else:
|
||||||
|
logger.debug (f'hrdsrc_contents 2 ({hrdsrc_contents})')
|
||||||
|
## Envía fichero de inventario al servidor
|
||||||
|
res = self.enviaMensajeServidor ('recibeArchivo', { 'nfl': hrddst, 'contents': base64.b64encode (hrdsrc_contents).decode ('utf-8') })
|
||||||
|
logger.debug (res)
|
||||||
|
if not res:
|
||||||
|
logger.error ('Ha ocurrido algún problema al enviar un archivo por la red')
|
||||||
|
herror = 12 ## Error de envío de fichero por la red
|
||||||
|
self.muestraMensaje (17)
|
||||||
|
|
||||||
|
## Envia respuesta de ejecución de la función de interface
|
||||||
|
cmd = {
|
||||||
|
'nfn': 'RESPUESTA_InventarioHardware',
|
||||||
|
'hrd': hrddst,
|
||||||
|
}
|
||||||
|
self.muestraMenu()
|
||||||
|
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||||
|
|
||||||
|
def do_InventarioSoftware (self, post_params):
|
||||||
|
for k in ['nfn', 'dsk', 'par', 'ids']:
|
||||||
|
if k not in post_params:
|
||||||
|
logger.error (f'required parameter ({k}) not in POST params')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
nfn = post_params['nfn']
|
||||||
|
dsk = post_params['dsk']
|
||||||
|
par = post_params['par']
|
||||||
|
ids = post_params['ids']
|
||||||
|
|
||||||
|
self.muestraMensaje (7)
|
||||||
|
|
||||||
|
try:
|
||||||
|
cmd = self.InventariandoSoftware (dsk, par, 'InventarioSoftware')
|
||||||
|
herror = 0
|
||||||
|
except:
|
||||||
|
logger.warning ('Error al ejecutar el comando')
|
||||||
|
cmd = { 'nfn': 'RESPUESTA_InventarioSoftware' }
|
||||||
|
herror = 1
|
||||||
|
|
||||||
|
self.muestraMenu()
|
||||||
|
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||||
|
|
||||||
|
def process_CrearImagen (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_CrearImagen, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
||||||
|
return self._long_running_job ('CrearImagen', self.do_CrearImagen, args=(post_params,))
|
||||||
|
|
||||||
|
def process_CrearImagenBasica (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_CrearImagenBasica, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
logger.warning ('this method has been removed')
|
||||||
|
raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
||||||
|
|
||||||
|
def process_CrearSoftIncremental (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_CrearSoftIncremental, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
logger.warning ('this method has been removed')
|
||||||
|
raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
||||||
|
|
||||||
|
def process_RestaurarImagen (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_RestaurarImagen, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
||||||
|
return self._long_running_job ('RestaurarImagen', self.do_RestaurarImagen, args=(post_params,))
|
||||||
|
|
||||||
|
def process_RestaurarImagenBasica (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_RestaurarImagenBasica, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
logger.warning ('this method has been removed')
|
||||||
|
raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
||||||
|
|
||||||
|
def process_RestaurarSoftIncremental (self, path, get_params, post_params, server):
|
||||||
|
logger.warning ('in process_RestaurarSoftIncremental')
|
||||||
|
logger.debug ('in process_RestaurarSoftIncremental, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
logger.warning ('this method has been removed')
|
||||||
|
raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
||||||
|
|
||||||
|
def process_Configurar (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_Configurar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
return self._long_running_job ('Configurar', self.do_Configurar, args=(post_params,))
|
||||||
|
|
||||||
|
def process_InventarioHardware (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_InventarioHardware, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
return self._long_running_job ('InventarioHardware', self.do_InventarioHardware, args=(post_params,))
|
||||||
|
|
||||||
|
def process_InventarioSoftware (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_InventarioSoftware, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
return self._long_running_job ('InventarioSoftware', self.do_InventarioSoftware, args=(post_params,))
|
||||||
|
|
||||||
|
## curl --insecure -X POST --data '{"job_id":"foo"}' https://192.168.2.199:8000/CloningEngine/KillJob
|
||||||
|
def process_KillJob (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_KillJob, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
jid = post_params['job_id']
|
||||||
|
r = self.killer (jid)
|
||||||
|
logger.debug (f'r bef ({r})')
|
||||||
|
r.update ({ 'nfn':'RESPUESTA_KillJob', 'job':jid })
|
||||||
|
logger.debug (f'r aft ({r})')
|
||||||
|
return r
|
|
@ -30,6 +30,7 @@
|
||||||
@author: Ramón M. Gómez, ramongomez at us dot es
|
@author: Ramón M. Gómez, ramongomez at us dot es
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
@ -101,20 +102,6 @@ class OpenGnSysWorker(ServerWorker):
|
||||||
exec_level = None # Execution level (permitted operations)
|
exec_level = None # Execution level (permitted operations)
|
||||||
jobmgr = JobMgr()
|
jobmgr = JobMgr()
|
||||||
|
|
||||||
## pings ogcore
|
|
||||||
def mon (self):
|
|
||||||
n = 0
|
|
||||||
while True:
|
|
||||||
time.sleep (1)
|
|
||||||
n += 1
|
|
||||||
if not n % 10:
|
|
||||||
body = {
|
|
||||||
"iph": self.interface.ip,
|
|
||||||
"timestamp": int (time.time()),
|
|
||||||
}
|
|
||||||
logger.debug (f'about to send ping ({body})')
|
|
||||||
self.REST.sendMessage ('clients/status/webhook', body)
|
|
||||||
|
|
||||||
def onActivation(self):
|
def onActivation(self):
|
||||||
"""
|
"""
|
||||||
Sends OGAgent activation notification to OpenGnsys server
|
Sends OGAgent activation notification to OpenGnsys server
|
||||||
|
@ -131,13 +118,10 @@ class OpenGnSysWorker(ServerWorker):
|
||||||
# Ensure cfg has required configuration variables or an exception will be thrown
|
# Ensure cfg has required configuration variables or an exception will be thrown
|
||||||
try:
|
try:
|
||||||
url = self.service.config.get(self.name, 'remote')
|
url = self.service.config.get(self.name, 'remote')
|
||||||
ca_file = self.service.config.get(self.name, 'ca')
|
|
||||||
crt_file = self.service.config.get(self.name, 'crt')
|
|
||||||
key_file = self.service.config.get(self.name, 'key')
|
|
||||||
except NoOptionError as e:
|
except NoOptionError as e:
|
||||||
logger.error("Configuration error: {}".format(e))
|
logger.error("Configuration error: {}".format(e))
|
||||||
raise e
|
raise e
|
||||||
self.REST = REST (url, ca_file=ca_file, crt_file=crt_file, key_file=key_file)
|
self.REST = REST(url)
|
||||||
# Execution level ('full' by default)
|
# Execution level ('full' by default)
|
||||||
try:
|
try:
|
||||||
self.exec_level = self.service.config.get(self.name, 'level')
|
self.exec_level = self.service.config.get(self.name, 'level')
|
||||||
|
@ -177,7 +161,7 @@ class OpenGnSysWorker(ServerWorker):
|
||||||
logger.warn (str (e))
|
logger.warn (str (e))
|
||||||
# Trying to initialize on alternative server, if defined
|
# Trying to initialize on alternative server, if defined
|
||||||
# (used in "exam mode" from the University of Seville)
|
# (used in "exam mode" from the University of Seville)
|
||||||
self.REST = REST(self.service.config.get(self.name, 'altremote'), ca_file=ca_file, crt_file=crt_file, key_file=key_file)
|
self.REST = REST(self.service.config.get(self.name, 'altremote'))
|
||||||
self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
||||||
'secret': self.random, 'ostype': operations.os_type,
|
'secret': self.random, 'ostype': operations.os_type,
|
||||||
'osversion': operations.os_version, 'alt_url': True,
|
'osversion': operations.os_version, 'alt_url': True,
|
||||||
|
@ -205,8 +189,6 @@ class OpenGnSysWorker(ServerWorker):
|
||||||
if os.path.isfile(new_hosts_file):
|
if os.path.isfile(new_hosts_file):
|
||||||
shutil.copyfile(new_hosts_file, hosts_file)
|
shutil.copyfile(new_hosts_file, hosts_file)
|
||||||
|
|
||||||
threading.Thread (name='monitoring_thread', target=self.mon, daemon=True).start()
|
|
||||||
|
|
||||||
logger.debug ('onActivation ok')
|
logger.debug ('onActivation ok')
|
||||||
|
|
||||||
def onDeactivation(self):
|
def onDeactivation(self):
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2014 Virtual Cable S.L.
|
# Copyright (c) 2014 Virtual Cable S.L.
|
||||||
# Copyright (c) 2024-2025 Qindel Formación y Servicios S.L.
|
# Copyright (c) 2024 Qindel Formación y Servicios S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
@ -33,15 +33,15 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
#import threading
|
||||||
|
#import time
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
import string
|
|
||||||
import random
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
|
|
||||||
from opengnsys import VERSION
|
#from opengnsys import operations
|
||||||
from opengnsys.log import logger
|
from opengnsys.log import logger
|
||||||
from opengnsys.workers import ogLiveWorker
|
from opengnsys.workers import ogLiveWorker
|
||||||
|
|
||||||
|
@ -51,43 +51,25 @@ def check_secret (fnc):
|
||||||
Decorator to check for received secret key and raise exception if it isn't valid.
|
Decorator to check for received secret key and raise exception if it isn't valid.
|
||||||
"""
|
"""
|
||||||
def wrapper (*args, **kwargs):
|
def wrapper (*args, **kwargs):
|
||||||
try:
|
|
||||||
this, path, get_params, post_params, server = args
|
|
||||||
|
|
||||||
if not server: ## this happens on startup, eg. onActivation->autoexecCliente->ejecutaArchivo->popup->check_secret
|
|
||||||
return fnc (*args, **kwargs)
|
return fnc (*args, **kwargs)
|
||||||
|
#try:
|
||||||
if this.random == server.headers['Authorization']:
|
# this, path, get_params, post_params, server = args
|
||||||
return fnc (*args, **kwargs)
|
# # Accept "status" operation with no arguments or any function with Authorization header
|
||||||
else:
|
# if fnc.__name__ == 'process_status' and not get_params:
|
||||||
raise Exception ('Unauthorized operation')
|
# return fnc (*args, **kwargs)
|
||||||
except Exception as e:
|
# elif this.random == server.headers['Authorization']:
|
||||||
logger.error (str (e))
|
# return fnc (*args, **kwargs)
|
||||||
raise Exception (e)
|
# else:
|
||||||
|
# raise Exception ('Unauthorized operation')
|
||||||
|
#except Exception as e:
|
||||||
|
# logger.error (str (e))
|
||||||
|
# raise Exception (e)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
# Check if operation is permitted
|
|
||||||
def execution_level(level):
|
|
||||||
def check_permitted(fnc):
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
levels = ['status', 'halt', 'full']
|
|
||||||
this = args[0]
|
|
||||||
try:
|
|
||||||
if levels.index(level) <= levels.index(this.exec_level):
|
|
||||||
return fnc(*args, **kwargs)
|
|
||||||
else:
|
|
||||||
raise Exception('Unauthorized operation')
|
|
||||||
except Exception as e:
|
|
||||||
logger.debug (str(e))
|
|
||||||
raise Exception(e)
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
return check_permitted
|
|
||||||
|
|
||||||
class ogAdmClientWorker (ogLiveWorker):
|
class ogAdmClientWorker (ogLiveWorker):
|
||||||
name = 'ogAdmClient' # Module name
|
name = 'ogAdmClient' # Module name
|
||||||
|
#interface = None # Bound interface for OpenGnsys (el otro modulo lo usa para obtener .ip y .mac
|
||||||
REST = None # REST object
|
REST = None # REST object
|
||||||
|
|
||||||
def onDeactivation (self):
|
def onDeactivation (self):
|
||||||
|
@ -95,40 +77,64 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
Sends OGAgent stopping notification to OpenGnsys server
|
Sends OGAgent stopping notification to OpenGnsys server
|
||||||
"""
|
"""
|
||||||
logger.debug ('onDeactivation')
|
logger.debug ('onDeactivation')
|
||||||
self.REST.sendMessage ('ogagent/stopped', {'mac': self.mac, 'ip': self.IPlocal, 'idcentro': self.idcentro, 'idaula': self.idaula,
|
|
||||||
'idordenador': self.idordenador, 'nombreordenador': self.nombreordenador})
|
#def processClientMessage (self, message, data):
|
||||||
|
# logger.debug ('Got OpenGnsys message from client: {}, data {}'.format (message, data))
|
||||||
|
|
||||||
|
#def onLogin (self, data):
|
||||||
|
# logger.warning ('in onLogin, should not happen')
|
||||||
|
|
||||||
|
#def onLogout (self, user):
|
||||||
|
# logger.warning ('in onLogout, should not happen')
|
||||||
|
|
||||||
|
#@check_secret
|
||||||
|
#def process_reboot (self, path, get_params, post_params, server):
|
||||||
|
# """
|
||||||
|
# Launches a system reboot operation
|
||||||
|
# :param path:
|
||||||
|
# :param get_params:
|
||||||
|
# :param post_params:
|
||||||
|
# :param server: authorization header
|
||||||
|
# :return: JSON object {"op": "launched"}
|
||||||
|
# """
|
||||||
|
# logger.debug ('Received reboot operation')
|
||||||
|
|
||||||
|
# # Rebooting thread
|
||||||
|
# def rebt():
|
||||||
|
# operations.reboot()
|
||||||
|
# threading.Thread (target=rebt).start()
|
||||||
|
# return {'op': 'launched'}
|
||||||
|
|
||||||
|
#@check_secret
|
||||||
|
#def process_poweroff (self, path, get_params, post_params, server):
|
||||||
|
# """
|
||||||
|
# Launches a system power off operation
|
||||||
|
# :param path:
|
||||||
|
# :param get_params:
|
||||||
|
# :param post_params:
|
||||||
|
# :param server: authorization header
|
||||||
|
# :return: JSON object {"op": "launched"}
|
||||||
|
# """
|
||||||
|
# logger.debug ('Received poweroff operation')
|
||||||
|
|
||||||
|
# # Powering off thread
|
||||||
|
# def pwoff():
|
||||||
|
# time.sleep (2)
|
||||||
|
# operations.poweroff()
|
||||||
|
# threading.Thread (target=pwoff).start()
|
||||||
|
# return {'op': 'launched'}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def InventariandoSoftware (self, dsk, par, nfn):
|
|
||||||
sft_src = f'/tmp/CSft-{self.IPlocal}-{par}'
|
|
||||||
try:
|
|
||||||
self.interfaceAdmin (nfn, [dsk, par, sft_src])
|
|
||||||
herror = 0
|
|
||||||
except:
|
|
||||||
herror = 1
|
|
||||||
|
|
||||||
if herror:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
b64 = ''
|
|
||||||
self.muestraMensaje (20)
|
|
||||||
else:
|
|
||||||
if not os.path.exists (sft_src):
|
|
||||||
raise Exception (f'interfaceAdmin({nfn}) returned success but did not create file ({sft_src})')
|
|
||||||
sft_src_contents = Path (sft_src).read_bytes()
|
|
||||||
|
|
||||||
b64 = base64.b64encode (sft_src_contents).decode ('utf-8')
|
|
||||||
self.muestraMensaje (19)
|
|
||||||
|
|
||||||
cmd = {
|
|
||||||
'nfn': 'RESPUESTA_InventarioSoftware',
|
|
||||||
'dsk': dsk, ## not in the original C code, around ogAdmClient.c:1944
|
## process_* are invoked from opengnsys/httpserver.py:99 "data = module.processServerMessage (path, get_params, post_params, self)" (via opengnsys/workers/server_worker.py)
|
||||||
'par': par,
|
## process_client_* are invoked from opengnsys/service.py:123 "v.processClientMessage (message, json.loads (data))" (via opengnsys/workers/server_worker.py)
|
||||||
'contents': b64,
|
|
||||||
}
|
|
||||||
return self.respuestaEjecucionComando (cmd, herror, 0)
|
|
||||||
|
|
||||||
def ejecutaArchivo (self,fn):
|
def ejecutaArchivo (self,fn):
|
||||||
logger.debug ('fn ({})'.format (fn))
|
logger.debug ('fn ({})'.format (fn))
|
||||||
|
@ -139,7 +145,7 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
if buffer:
|
if buffer:
|
||||||
for l in buffer.split ('@'):
|
for l in buffer.split ('@'):
|
||||||
if not len (l): continue
|
if not len (l): continue
|
||||||
logger.debug ('line ({})'.format (l.replace ('\r', '\\r'))) ## change \r so as not to mess with the log
|
logger.debug ('line ({})'.format (l))
|
||||||
## at this point, an option would be fire up a curl to localhost, but we can also parse the params and locally call the desired function:
|
## at this point, an option would be fire up a curl to localhost, but we can also parse the params and locally call the desired function:
|
||||||
post_params = {}
|
post_params = {}
|
||||||
for param in l.split ("\r"):
|
for param in l.split ("\r"):
|
||||||
|
@ -168,7 +174,7 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
logger.warning ('Ha ocurrido algún problema en el proceso de inclusión del cliente')
|
logger.warning ('Ha ocurrido algún problema en el proceso de inclusión del cliente')
|
||||||
logger.error ('LeeConfiguracion() failed')
|
logger.error ('LeeConfiguracion() failed')
|
||||||
return False
|
return False
|
||||||
res = self.enviaMensajeServidor ('InclusionCliente', { 'cfg': self.cfg2obj (cfg), 'secret': self.random, 'agent_version': VERSION })
|
res = self.enviaMensajeServidor ('InclusionCliente', { 'cfg': self.cfg2obj (cfg) })
|
||||||
logger.debug ('res ({})'.format (res))
|
logger.debug ('res ({})'.format (res))
|
||||||
|
|
||||||
## RESPUESTA_InclusionCliente
|
## RESPUESTA_InclusionCliente
|
||||||
|
@ -273,10 +279,7 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
#}
|
#}
|
||||||
|
|
||||||
def onActivation (self):
|
def onActivation (self):
|
||||||
super().onActivation()
|
super().onActivation (run_monitoring_thread=True)
|
||||||
self.exec_level = 'full'
|
|
||||||
self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(32))
|
|
||||||
|
|
||||||
logger.info ('Inicio de sesion')
|
logger.info ('Inicio de sesion')
|
||||||
logger.info ('Abriendo sesión en el servidor de Administración')
|
logger.info ('Abriendo sesión en el servidor de Administración')
|
||||||
if (not self.inclusionCliente()):
|
if (not self.inclusionCliente()):
|
||||||
|
@ -303,227 +306,31 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
|
|
||||||
logger.info ('onActivation ok')
|
logger.info ('onActivation ok')
|
||||||
|
|
||||||
|
@check_secret
|
||||||
|
def process_status (self, path, get_params, post_params, server):
|
||||||
|
logger.debug ('in process_status, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
|
||||||
|
|
||||||
def do_CrearImagen (self, post_params):
|
|
||||||
for k in ['dsk', 'par', 'cpt', 'idi', 'nci', 'ipr', 'nfn', 'ids']:
|
|
||||||
if k not in post_params:
|
|
||||||
logger.error (f'required parameter ({k}) not in POST params')
|
|
||||||
return {}
|
|
||||||
|
|
||||||
dsk = post_params['dsk'] ## Disco
|
|
||||||
par = post_params['par'] ## Número de partición
|
|
||||||
cpt = post_params['cpt'] ## Código de la partición
|
|
||||||
idi = post_params['idi'] ## Identificador de la imagen
|
|
||||||
nci = post_params['nci'] ## Nombre canónico de la imagen
|
|
||||||
ipr = post_params['ipr'] ## Ip del repositorio
|
|
||||||
nfn = post_params['nfn']
|
|
||||||
ids = post_params['ids']
|
|
||||||
|
|
||||||
self.muestraMensaje (7)
|
|
||||||
|
|
||||||
try:
|
|
||||||
res = self.InventariandoSoftware (dsk, par, 'InventarioSoftware') ## Crea inventario Software previamente
|
|
||||||
except:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
return {}
|
|
||||||
|
|
||||||
if res['contents']:
|
|
||||||
self.muestraMensaje (2)
|
|
||||||
inv_sft = res['contents']
|
|
||||||
try:
|
|
||||||
self.interfaceAdmin (nfn, [dsk, par, nci, ipr])
|
|
||||||
self.muestraMensaje (9)
|
|
||||||
herror = 0
|
|
||||||
except:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
self.muestraMensaje (10)
|
|
||||||
herror = 1
|
|
||||||
else:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
herror = 1
|
|
||||||
inv_sft = ''
|
|
||||||
|
|
||||||
self.muestraMenu()
|
|
||||||
|
|
||||||
cmd = {
|
|
||||||
'nfn': 'RESPUESTA_CrearImagen',
|
|
||||||
'idi': idi, ## Identificador de la imagen
|
|
||||||
'dsk': dsk, ## Número de disco
|
|
||||||
'par': par, ## Número de partición de donde se creó
|
|
||||||
'cpt': cpt, ## Tipo o código de partición
|
|
||||||
'ipr': ipr, ## Ip del repositorio donde se alojó
|
|
||||||
'inv_sft': inv_sft,
|
|
||||||
}
|
|
||||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
|
||||||
|
|
||||||
def do_RestaurarImagen (self, post_params):
|
|
||||||
for k in ['dsk', 'par', 'idi', 'ipr', 'nci', 'ifs', 'ptc', 'nfn', 'ids']:
|
|
||||||
if k not in post_params:
|
|
||||||
logger.error (f'required parameter ({k}) not in POST params')
|
|
||||||
return {}
|
|
||||||
|
|
||||||
dsk = post_params['dsk']
|
|
||||||
par = post_params['par']
|
|
||||||
idi = post_params['idi']
|
|
||||||
ipr = post_params['ipr']
|
|
||||||
nci = post_params['nci']
|
|
||||||
ifs = post_params['ifs']
|
|
||||||
ptc = post_params['ptc'] ## Protocolo de clonación: Unicast, Multicast, Torrent
|
|
||||||
nfn = post_params['nfn']
|
|
||||||
ids = post_params['ids']
|
|
||||||
|
|
||||||
self.muestraMensaje (3)
|
|
||||||
|
|
||||||
try:
|
|
||||||
## the ptc.split() is useless right now, since interfaceAdmin() does ' '.join(params) in order to spawn a shell
|
|
||||||
## however we're going to need it in the future (when everything gets translated into python), plus it's harmless now. So let's do it
|
|
||||||
#self.interfaceAdmin (nfn, [dsk, par, nci, ipr, ptc])
|
|
||||||
self.interfaceAdmin (nfn, [dsk, par, nci, ipr] + ptc.split())
|
|
||||||
self.muestraMensaje (11)
|
|
||||||
herror = 0
|
|
||||||
except:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
self.muestraMensaje (12)
|
|
||||||
herror = 1
|
|
||||||
|
|
||||||
cfg = self.LeeConfiguracion()
|
cfg = self.LeeConfiguracion()
|
||||||
if not cfg:
|
thr_status = {}
|
||||||
logger.warning ('No se ha podido recuperar la configuración de las particiones del disco')
|
for k in self.thread_list:
|
||||||
|
thr_status[k] = {
|
||||||
self.muestraMenu()
|
'running': self.thread_list[k]['running'],
|
||||||
|
'result': self.thread_list[k]['result'],
|
||||||
cmd = {
|
|
||||||
'nfn': 'RESPUESTA_RestaurarImagen',
|
|
||||||
'idi': idi, ## Identificador de la imagen
|
|
||||||
'dsk': dsk, ## Número de disco
|
|
||||||
'par': par, ## Número de partición
|
|
||||||
'ifs': ifs, ## Identificador del perfil software
|
|
||||||
'cfg': self.cfg2obj(cfg), ## Configuración de discos
|
|
||||||
}
|
}
|
||||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
return {
|
||||||
|
'nfn': 'RESPUESTA_status',
|
||||||
def do_Configurar (self, post_params):
|
'mac': self.mac,
|
||||||
for k in ['nfn', 'dsk', 'cfg', 'ids']:
|
'ip': self.IPlocal,
|
||||||
if k not in post_params:
|
|
||||||
logger.error (f'required parameter ({k}) not in POST params')
|
|
||||||
return {}
|
|
||||||
|
|
||||||
nfn = post_params['nfn']
|
|
||||||
dsk = post_params['dsk']
|
|
||||||
cfg = post_params['cfg']
|
|
||||||
ids = post_params['ids']
|
|
||||||
|
|
||||||
self.muestraMensaje (4)
|
|
||||||
|
|
||||||
params = []
|
|
||||||
disk_info = cfg.pop (0)
|
|
||||||
logger.debug (f'disk_info ({disk_info})')
|
|
||||||
for k in ['dis', 'tch']:
|
|
||||||
params.append (f'{k}={disk_info[k]}')
|
|
||||||
disk_info_str = '*'.join (params)
|
|
||||||
|
|
||||||
partitions = []
|
|
||||||
for entry in cfg:
|
|
||||||
logger.debug (f'entry ({entry})')
|
|
||||||
params = []
|
|
||||||
for k in ['par', 'cpt', 'sfi', 'tam', 'ope']:
|
|
||||||
params.append (f'{k}={entry[k]}')
|
|
||||||
partitions.append ('*'.join (params))
|
|
||||||
part_info_str = '%'.join (partitions)
|
|
||||||
|
|
||||||
cfg_str = f'{disk_info_str}!{part_info_str}%'
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.interfaceAdmin (nfn, ['ignored', cfg_str])
|
|
||||||
self.muestraMensaje (14)
|
|
||||||
herror = 0
|
|
||||||
except:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
self.muestraMensaje (13)
|
|
||||||
herror = 1
|
|
||||||
|
|
||||||
cfg = self.LeeConfiguracion()
|
|
||||||
if not cfg:
|
|
||||||
logger.warning ('No se ha podido recuperar la configuración de las particiones del disco')
|
|
||||||
return {}
|
|
||||||
|
|
||||||
cmd = {
|
|
||||||
'nfn': 'RESPUESTA_Configurar',
|
|
||||||
'cfg': self.cfg2obj (cfg),
|
'cfg': self.cfg2obj (cfg),
|
||||||
|
'threads': thr_status,
|
||||||
}
|
}
|
||||||
self.muestraMenu()
|
|
||||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
|
||||||
|
|
||||||
def do_InventarioHardware (self, post_params):
|
@check_secret
|
||||||
for k in ['nfn', 'ids']:
|
def process_popup (self, path, get_params, post_params, server):
|
||||||
if k not in post_params:
|
logger.debug ('in process_popup, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
logger.error (f'required parameter ({k}) not in POST params')
|
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
||||||
return {}
|
## in process_popup, should not happen, path "[]" get_params "{}" post_params "{'title': 'mi titulo', 'message': 'mi mensaje'}" server "<opengnsys.httpserver.HTTPServerHandler object at 0x7fa788cb8fa0>"
|
||||||
|
## type(post_params) "<class 'dict'>"
|
||||||
nfn = post_params['nfn']
|
return {'debug':'test'}
|
||||||
ids = post_params['ids']
|
|
||||||
|
|
||||||
self.muestraMensaje (6)
|
|
||||||
|
|
||||||
hrdsrc = f'/tmp/Chrd-{self.IPlocal}' ## Nombre que tendra el archivo de inventario
|
|
||||||
hrddst = f'/tmp/Shrd-{self.IPlocal}' ## Nombre que tendra el archivo en el Servidor
|
|
||||||
try:
|
|
||||||
self.interfaceAdmin (nfn, [hrdsrc])
|
|
||||||
hrdsrc_contents = Path (hrdsrc).read_bytes()
|
|
||||||
logger.debug (f'hrdsrc_contents 1 ({hrdsrc_contents})')
|
|
||||||
herror = 0
|
|
||||||
except:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
self.muestraMensaje (18)
|
|
||||||
herror = 1
|
|
||||||
|
|
||||||
if herror:
|
|
||||||
hrddst = ''
|
|
||||||
else:
|
|
||||||
logger.debug (f'hrdsrc_contents 2 ({hrdsrc_contents})')
|
|
||||||
## Envía fichero de inventario al servidor
|
|
||||||
res = self.enviaMensajeServidor ('recibeArchivo', { 'nfl': hrddst, 'contents': base64.b64encode (hrdsrc_contents).decode ('utf-8') })
|
|
||||||
logger.debug (res)
|
|
||||||
if not res:
|
|
||||||
logger.error ('Ha ocurrido algún problema al enviar un archivo por la red')
|
|
||||||
herror = 12 ## Error de envío de fichero por la red
|
|
||||||
self.muestraMensaje (17)
|
|
||||||
|
|
||||||
## Envia respuesta de ejecución de la función de interface
|
|
||||||
cmd = {
|
|
||||||
'nfn': 'RESPUESTA_InventarioHardware',
|
|
||||||
'hrd': hrddst,
|
|
||||||
}
|
|
||||||
self.muestraMenu()
|
|
||||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
|
||||||
|
|
||||||
def do_InventarioSoftware (self, post_params):
|
|
||||||
for k in ['nfn', 'dsk', 'par', 'ids']:
|
|
||||||
if k not in post_params:
|
|
||||||
logger.error (f'required parameter ({k}) not in POST params')
|
|
||||||
return {}
|
|
||||||
|
|
||||||
nfn = post_params['nfn']
|
|
||||||
dsk = post_params['dsk']
|
|
||||||
par = post_params['par']
|
|
||||||
ids = post_params['ids']
|
|
||||||
|
|
||||||
self.muestraMensaje (7)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cmd = self.InventariandoSoftware (dsk, par, 'InventarioSoftware')
|
|
||||||
herror = 0
|
|
||||||
except:
|
|
||||||
logger.warning ('Error al ejecutar el comando')
|
|
||||||
cmd = { 'nfn': 'RESPUESTA_InventarioSoftware' }
|
|
||||||
herror = 1
|
|
||||||
|
|
||||||
self.muestraMenu()
|
|
||||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
|
||||||
|
|
||||||
def do_Actualizar (self, post_params):
|
def do_Actualizar (self, post_params):
|
||||||
self.muestraMensaje (1)
|
self.muestraMensaje (1)
|
||||||
|
@ -569,7 +376,7 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
nfn = post_params['nfn']
|
nfn = post_params['nfn']
|
||||||
scp = base64.b64decode (unquote (post_params['scp'])).decode ('utf-8')
|
scp = unquote (post_params['scp'])
|
||||||
filescript = f'/tmp/_script_{self.IPlocal}'
|
filescript = f'/tmp/_script_{self.IPlocal}'
|
||||||
ecosrc = f'/tmp/_econsola_{self.IPlocal}'
|
ecosrc = f'/tmp/_econsola_{self.IPlocal}'
|
||||||
ecodst = f'/tmp/_Seconsola_{self.IPlocal}' ## Nombre que tendra el archivo en el Servidor
|
ecodst = f'/tmp/_Seconsola_{self.IPlocal}' ## Nombre que tendra el archivo en el Servidor
|
||||||
|
@ -664,7 +471,7 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
nfn = post_params['nfn']
|
nfn = post_params['nfn']
|
||||||
scp = base64.b64decode (unquote (post_params['scp'])).decode ('utf-8')
|
scp = unquote (post_params['scp'])
|
||||||
ids = post_params['ids']
|
ids = post_params['ids']
|
||||||
|
|
||||||
self.muestraMensaje (8)
|
self.muestraMensaje (8)
|
||||||
|
@ -697,56 +504,16 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
self.muestraMenu()
|
self.muestraMenu()
|
||||||
return self.respuestaEjecucionComando (cmd, herror, ids)
|
return self.respuestaEjecucionComando (cmd, herror, ids)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@execution_level('status')
|
|
||||||
def process_status (self, path, get_params, post_params, server):
|
|
||||||
logger.debug ('in process_status, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
full_config = 'full-config' in post_params and post_params['full-config']
|
|
||||||
thr_status = {}
|
|
||||||
for k in self.thread_list:
|
|
||||||
thr_status[k] = {
|
|
||||||
'running': self.thread_list[k]['running'],
|
|
||||||
'result': self.thread_list[k]['result'],
|
|
||||||
}
|
|
||||||
ret = {
|
|
||||||
'nfn': 'RESPUESTA_status',
|
|
||||||
'mac': self.mac,
|
|
||||||
'st': 'OGL',
|
|
||||||
'ip': self.IPlocal,
|
|
||||||
'threads': thr_status,
|
|
||||||
}
|
|
||||||
if full_config:
|
|
||||||
cfg = self.LeeConfiguracion()
|
|
||||||
ret['cfg'] = self.cfg2obj (cfg)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
@check_secret
|
|
||||||
def process_popup (self, path, get_params, post_params, server):
|
|
||||||
logger.debug ('in process_popup, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
|
||||||
## in process_popup, should not happen, path "[]" get_params "{}" post_params "{'title': 'mi titulo', 'message': 'mi mensaje'}" server "<opengnsys.httpserver.HTTPServerHandler object at 0x7fa788cb8fa0>"
|
|
||||||
## type(post_params) "<class 'dict'>"
|
|
||||||
return {'debug':'test'}
|
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_Actualizar (self, path, get_params, post_params, server):
|
def process_Actualizar (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_Actualizar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_Actualizar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return self._long_running_job ('Actualizar', self.do_Actualizar, args=(post_params,))
|
return self._long_running_job ('Actualizar', self.do_Actualizar, args=(post_params,))
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_Purgar (self, path, get_params, post_params, server):
|
def process_Purgar (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_Purgar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_Purgar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
os.kill (os.getpid(), signal.SIGTERM)
|
os.kill (os.getpid(), signal.SIGTERM)
|
||||||
return {}
|
return {}
|
||||||
#exit (0) ## ogAdmClient.c:905
|
#exit (0) ## ogAdmClient.c:905
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_Comando (self, path, get_params, post_params, server):
|
def process_Comando (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_Comando, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_Comando, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return self._long_running_job ('Comando', self.do_Comando, args=(post_params,))
|
return self._long_running_job ('Comando', self.do_Comando, args=(post_params,))
|
||||||
|
@ -755,14 +522,10 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
logger.debug ('in process_Sondeo, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_Sondeo, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return {} ## ogAdmClient.c:920
|
return {} ## ogAdmClient.c:920
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_ConsolaRemota (self, path, get_params, post_params, server):
|
def process_ConsolaRemota (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_ConsolaRemota, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_ConsolaRemota, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return self._long_running_job ('ConsolaRemota', self.do_ConsolaRemota, args=(post_params,))
|
return self._long_running_job ('ConsolaRemota', self.do_ConsolaRemota, args=(post_params,))
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_Arrancar (self, path, get_params, post_params, server):
|
def process_Arrancar (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_Arrancar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_Arrancar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
|
|
||||||
|
@ -779,92 +542,27 @@ class ogAdmClientWorker (ogLiveWorker):
|
||||||
}
|
}
|
||||||
return self.respuestaEjecucionComando (cmd, 0, ids)
|
return self.respuestaEjecucionComando (cmd, 0, ids)
|
||||||
|
|
||||||
@execution_level('halt')
|
|
||||||
@check_secret
|
|
||||||
def process_Apagar (self, path, get_params, post_params, server):
|
def process_Apagar (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_Apagar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_Apagar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return self._long_running_job ('Apagar', self.do_Apagar, args=(post_params,))
|
return self._long_running_job ('Apagar', self.do_Apagar, args=(post_params,))
|
||||||
|
|
||||||
@execution_level('halt')
|
|
||||||
@check_secret
|
|
||||||
def process_Reiniciar (self, path, get_params, post_params, server):
|
def process_Reiniciar (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_Reiniciar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_Reiniciar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return self._long_running_job ('Reiniciar', self.do_Reiniciar, args=(post_params,))
|
return self._long_running_job ('Reiniciar', self.do_Reiniciar, args=(post_params,))
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_IniciarSesion (self, path, get_params, post_params, server):
|
def process_IniciarSesion (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_IniciarSesion, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_IniciarSesion, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return self._long_running_job ('IniciarSesion', self.do_IniciarSesion, args=(post_params,))
|
return self._long_running_job ('IniciarSesion', self.do_IniciarSesion, args=(post_params,))
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_EjecutarScript (self, path, get_params, post_params, server):
|
def process_EjecutarScript (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_EjecutarScript, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_EjecutarScript, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return self._long_running_job ('EjecutarScript', self.do_EjecutarScript, args=(post_params,))
|
return self._long_running_job ('EjecutarScript', self.do_EjecutarScript, args=(post_params,))
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_EjecutaComandosPendientes (self, path, get_params, post_params, server):
|
def process_EjecutaComandosPendientes (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_EjecutaComandosPendientes, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_EjecutaComandosPendientes, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
return {'true':'true'} ## ogAdmClient.c:2138
|
return {'true':'true'} ## ogAdmClient.c:2138
|
||||||
|
|
||||||
@execution_level('full')
|
## curl --insecure -X POST --data '{"job_id":"foo"}' https://192.168.2.199:8000/ogAdmClient/KillJob
|
||||||
@check_secret
|
|
||||||
def process_CrearImagen (self, path, get_params, post_params, server):
|
|
||||||
logger.debug ('in process_CrearImagen, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
|
||||||
return self._long_running_job ('CrearImagen', self.do_CrearImagen, args=(post_params,))
|
|
||||||
|
|
||||||
#def process_CrearImagenBasica (self, path, get_params, post_params, server):
|
|
||||||
# logger.debug ('in process_CrearImagenBasica, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
# logger.warning ('this method has been removed')
|
|
||||||
# raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
|
||||||
|
|
||||||
#def process_CrearSoftIncremental (self, path, get_params, post_params, server):
|
|
||||||
# logger.debug ('in process_CrearSoftIncremental, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
# logger.warning ('this method has been removed')
|
|
||||||
# raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_RestaurarImagen (self, path, get_params, post_params, server):
|
|
||||||
logger.debug ('in process_RestaurarImagen, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
logger.debug ('type(post_params) "{}"'.format (type (post_params)))
|
|
||||||
return self._long_running_job ('RestaurarImagen', self.do_RestaurarImagen, args=(post_params,))
|
|
||||||
|
|
||||||
#def process_RestaurarImagenBasica (self, path, get_params, post_params, server):
|
|
||||||
# logger.debug ('in process_RestaurarImagenBasica, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
# logger.warning ('this method has been removed')
|
|
||||||
# raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
|
||||||
|
|
||||||
#def process_RestaurarSoftIncremental (self, path, get_params, post_params, server):
|
|
||||||
# logger.warning ('in process_RestaurarSoftIncremental')
|
|
||||||
# logger.debug ('in process_RestaurarSoftIncremental, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
# logger.warning ('this method has been removed')
|
|
||||||
# raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' })
|
|
||||||
|
|
||||||
## una partición + cache en disco de 30 Gb:
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_Configurar (self, path, get_params, post_params, server):
|
|
||||||
logger.debug ('in process_Configurar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
return self._long_running_job ('Configurar', self.do_Configurar, args=(post_params,))
|
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_InventarioHardware (self, path, get_params, post_params, server):
|
|
||||||
logger.debug ('in process_InventarioHardware, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
return self._long_running_job ('InventarioHardware', self.do_InventarioHardware, args=(post_params,))
|
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_InventarioSoftware (self, path, get_params, post_params, server):
|
|
||||||
logger.debug ('in process_InventarioSoftware, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
|
||||||
return self._long_running_job ('InventarioSoftware', self.do_InventarioSoftware, args=(post_params,))
|
|
||||||
|
|
||||||
@execution_level('full')
|
|
||||||
@check_secret
|
|
||||||
def process_KillJob (self, path, get_params, post_params, server):
|
def process_KillJob (self, path, get_params, post_params, server):
|
||||||
logger.debug ('in process_KillJob, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
logger.debug ('in process_KillJob, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server))
|
||||||
jid = post_params['job_id']
|
jid = post_params['job_id']
|
||||||
|
|
|
@ -31,13 +31,15 @@
|
||||||
'''
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
try:
|
||||||
|
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||||
|
except ImportError:
|
||||||
|
servicemanager = None # Definir como None para evitar errores posteriores
|
||||||
|
print("Warning: 'servicemanager' module not found. Continuing execution without it.")
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from ..log_format import JsonFormatter
|
|
||||||
|
|
||||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
|
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
|
||||||
|
|
||||||
|
@ -46,24 +48,13 @@ class LocalLogger(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# tempdir is different for "user application" and "service"
|
# tempdir is different for "user application" and "service"
|
||||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\appdata\local\temp
|
# service wil get c:\windows\temp, while user will get c:\users\XXX\appdata\local\temp
|
||||||
|
logging.basicConfig(
|
||||||
fname1 = os.path.join (tempfile.gettempdir(), 'opengnsys.log')
|
filename=os.path.join(tempfile.gettempdir(), 'opengnsys.log'),
|
||||||
fmt1 = logging.Formatter (fmt='%(levelname)s %(asctime)s (%(threadName)s) (%(funcName)s) %(message)s')
|
filemode='a',
|
||||||
fh1 = logging.FileHandler (filename=fname1, mode='a')
|
format='%(levelname)s %(asctime)s (%(threadName)s) (%(funcName)s) %(message)s',
|
||||||
fh1.setFormatter (fmt1)
|
level=logging.DEBUG
|
||||||
fh1.setLevel (logging.DEBUG)
|
)
|
||||||
|
|
||||||
fname2 = os.path.join (tempfile.gettempdir(), 'opengnsys.json.log')
|
|
||||||
fmt2 = JsonFormatter ({"timestamp": "asctime", "severity": "levelname", "threadName": "threadName", "function": "funcName", "message": "message"}, time_format='%Y-%m-%d %H:%M:%S', msec_format='')
|
|
||||||
fh2 = logging.FileHandler (filename=fname2, mode='a')
|
|
||||||
fh2.setFormatter (fmt2)
|
|
||||||
fh2.setLevel (logging.DEBUG)
|
|
||||||
|
|
||||||
self.logger = logging.getLogger('opengnsys')
|
self.logger = logging.getLogger('opengnsys')
|
||||||
self.logger.setLevel (logging.DEBUG)
|
|
||||||
self.logger.addHandler (fh1)
|
|
||||||
self.logger.addHandler (fh2)
|
|
||||||
|
|
||||||
self.serviceLogger = False
|
self.serviceLogger = False
|
||||||
|
|
||||||
def log(self, level, message):
|
def log(self, level, message):
|
||||||
|
@ -77,11 +68,22 @@ class LocalLogger(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
if level < WARN: # Info
|
if level < WARN: # Info
|
||||||
|
try:
|
||||||
servicemanager.LogInfoMsg(message)
|
servicemanager.LogInfoMsg(message)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Warning: Failed to log info message: {message}. Error: {e}")
|
||||||
|
|
||||||
elif level < ERROR: # WARN
|
elif level < ERROR: # WARN
|
||||||
|
try:
|
||||||
servicemanager.LogWarningMsg(message)
|
servicemanager.LogWarningMsg(message)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Warning: Failed to log warning message: {message}. Error: {e}")
|
||||||
|
|
||||||
else: # Error & Fatal
|
else: # Error & Fatal
|
||||||
|
try:
|
||||||
servicemanager.LogErrorMsg(message)
|
servicemanager.LogErrorMsg(message)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Warning: Failed to log error message: {message}. Error: {e}")
|
||||||
|
|
||||||
def isWindows(self):
|
def isWindows(self):
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
# pylint: disable=unused-wildcard-import,wildcard-import
|
# pylint: disable=unused-wildcard-import,wildcard-import
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -50,16 +49,15 @@ class ThreadWithResult (threading.Thread):
|
||||||
self.result = None
|
self.result = None
|
||||||
if self._target is not None:
|
if self._target is not None:
|
||||||
## the first arg in self._args is the queue
|
## the first arg in self._args is the queue
|
||||||
self.pid_q = self._args[0]
|
self.q = self._args[0]
|
||||||
self.stdout_q = self._args[1]
|
self._args = self._args[1:]
|
||||||
self._args = self._args[2:]
|
|
||||||
try:
|
try:
|
||||||
self.result = self._target (*self._args, **self._kwargs)
|
self.result = self._target (*self._args, **self._kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.result = { 'res': 2, 'der': f'got exception: ({e})' } ## res=2 as defined in ogAdmClient.c:2048
|
self.result = { 'res': 2, 'der': f'got exception: ({e})' } ## res=2 as defined in ogAdmClient.c:2048
|
||||||
finally:
|
finally:
|
||||||
# Avoid a refcycle if the thread is running a function with an argument that has a member that points to the thread.
|
# Avoid a refcycle if the thread is running a function with an argument that has a member that points to the thread.
|
||||||
del self._target, self._args, self._kwargs, self.pid_q, self.stdout_q
|
del self._target, self._args, self._kwargs, self.q
|
||||||
|
|
||||||
class ogLiveWorker(ServerWorker):
|
class ogLiveWorker(ServerWorker):
|
||||||
thread_list = {}
|
thread_list = {}
|
||||||
|
@ -145,6 +143,7 @@ class ogLiveWorker(ServerWorker):
|
||||||
]
|
]
|
||||||
|
|
||||||
def notifier (self, job_id, result):
|
def notifier (self, job_id, result):
|
||||||
|
logger.debug (f'notifier() called, job_id ({job_id}) result ({result})')
|
||||||
result['job_id'] = job_id
|
result['job_id'] = job_id
|
||||||
self.REST.sendMessage ('clients/status/webhook', result)
|
self.REST.sendMessage ('clients/status/webhook', result)
|
||||||
|
|
||||||
|
@ -194,40 +193,20 @@ class ogLiveWorker(ServerWorker):
|
||||||
|
|
||||||
return { 'res':success, 'der':msg }
|
return { 'res':success, 'der':msg }
|
||||||
|
|
||||||
def _extract_progress (self, job_id, ary=[]):
|
|
||||||
progress = None
|
|
||||||
for i in ary:
|
|
||||||
if m := re.search (r'^\[([0-9]+)\]', i): ## look for strings like '[10]', '[60]'
|
|
||||||
#logger.debug (f"matched regex, m.groups ({m.groups()})")
|
|
||||||
progress = float (m.groups()[0]) / 100
|
|
||||||
return progress
|
|
||||||
|
|
||||||
## monitors child threads, waits for them to finish
|
|
||||||
## pings ogcore
|
|
||||||
def mon (self):
|
def mon (self):
|
||||||
n = 0
|
|
||||||
while True:
|
while True:
|
||||||
with self.thread_lock:
|
with self.thread_lock:
|
||||||
for k in self.thread_list:
|
for k in self.thread_list:
|
||||||
elem = self.thread_list[k]
|
elem = self.thread_list[k]
|
||||||
if 'thread' not in elem: continue
|
if 'thread' not in elem: continue
|
||||||
#logger.debug (f'considering thread ({k})')
|
logger.debug (f'considering thread ({k})')
|
||||||
|
|
||||||
if self.pid_q:
|
if self.q:
|
||||||
if not self.pid_q.empty():
|
if not self.q.empty():
|
||||||
elem['child_pid'] = self.pid_q.get()
|
elem['child_pid'] = self.q.get()
|
||||||
logger.debug (f'queue not empty, got pid ({elem["child_pid"]})')
|
logger.debug (f'queue not empty, got pid ({elem["child_pid"]})')
|
||||||
|
else:
|
||||||
if self.stdout_q:
|
logger.debug (f'queue empty')
|
||||||
partial = ''
|
|
||||||
while not self.stdout_q.empty():
|
|
||||||
partial += self.stdout_q.get()
|
|
||||||
lines = partial.splitlines()
|
|
||||||
if len (lines):
|
|
||||||
p = self._extract_progress (k, lines)
|
|
||||||
if p:
|
|
||||||
m = { "job_id": k, "progress": p }
|
|
||||||
self.REST.sendMessage ('clients/status/webhook', { "job_id": k, "progress": p })
|
|
||||||
|
|
||||||
elem['thread'].join (0.05)
|
elem['thread'].join (0.05)
|
||||||
if not elem['thread'].is_alive():
|
if not elem['thread'].is_alive():
|
||||||
|
@ -238,39 +217,12 @@ class ogLiveWorker(ServerWorker):
|
||||||
self.notifier (k, elem['result'])
|
self.notifier (k, elem['result'])
|
||||||
|
|
||||||
time.sleep (1)
|
time.sleep (1)
|
||||||
n += 1
|
|
||||||
if not n % 10:
|
|
||||||
alive_threads = []
|
|
||||||
for k in self.thread_list:
|
|
||||||
elem = self.thread_list[k]
|
|
||||||
if 'thread' not in elem: continue
|
|
||||||
alive_threads.append (k)
|
|
||||||
if alive_threads:
|
|
||||||
s = ','.join (alive_threads)
|
|
||||||
logger.debug (f'alive threads: {s}')
|
|
||||||
|
|
||||||
body = {
|
|
||||||
'iph': self.IPlocal,
|
|
||||||
'timestamp': int (time.time()),
|
|
||||||
}
|
|
||||||
#logger.debug (f'about to send ping ({body})')
|
|
||||||
self.REST.sendMessage ('clients/status/webhook', body)
|
|
||||||
|
|
||||||
def interfaceAdmin (self, method, parametros=[]):
|
def interfaceAdmin (self, method, parametros=[]):
|
||||||
if method in ['Apagar', 'CambiarAcceso', 'Configurar', 'CrearImagen', 'EjecutarScript', 'getConfiguration', 'getIpAddress', 'IniciarSesion', 'InventarioHardware', 'InventarioSoftware', 'Reiniciar', 'RestaurarImagen']:
|
|
||||||
## python
|
|
||||||
logger.debug (f'({method}) is a python method')
|
|
||||||
exe = '{}/{}.py'.format (self.pathinterface, method)
|
|
||||||
proc = [exe]+parametros
|
|
||||||
else: ## ConsolaRemota procesaCache
|
|
||||||
## bash
|
|
||||||
logger.debug (f'({method}) is a bash method')
|
|
||||||
exe = '{}/{}'.format (self.pathinterface, method)
|
exe = '{}/{}'.format (self.pathinterface, method)
|
||||||
|
## for development only. Will be removed when the referenced bash code (/opt/opengnsys/lib/engine/bin/*.lib) is translated into python
|
||||||
LANG = os.environ.get ('LANG', 'en_GB.UTF-8').replace ('UTF_8', 'UTF-8')
|
devel_bash_prefix = '''
|
||||||
devel_bash_prefix = f'''
|
|
||||||
PATH=/opt/opengnsys/scripts/:$PATH;
|
PATH=/opt/opengnsys/scripts/:$PATH;
|
||||||
source /opt/opengnsys/etc/lang.{LANG}.conf;
|
|
||||||
for I in /opt/opengnsys/lib/engine/bin/*.lib; do source $I; done;
|
for I in /opt/opengnsys/lib/engine/bin/*.lib; do source $I; done;
|
||||||
for i in $(declare -F |cut -f3 -d" "); do export -f $i; done;
|
for i in $(declare -F |cut -f3 -d" "); do export -f $i; done;
|
||||||
'''
|
'''
|
||||||
|
@ -279,36 +231,29 @@ class ogLiveWorker(ServerWorker):
|
||||||
proc = ['bash', '-c', '{} {} {}'.format (devel_bash_prefix, exe, ' '.join (parametros))]
|
proc = ['bash', '-c', '{} {} {}'.format (devel_bash_prefix, exe, ' '.join (parametros))]
|
||||||
else:
|
else:
|
||||||
proc = ['bash', '-c', '{} {}'.format (devel_bash_prefix, exe)]
|
proc = ['bash', '-c', '{} {}'.format (devel_bash_prefix, exe)]
|
||||||
|
logger.debug ('subprocess.run ("{}", capture_output=True)'.format (proc))
|
||||||
|
|
||||||
logger.debug ('subprocess.run ("{}")'.format (' '.join (proc)))
|
|
||||||
p = subprocess.Popen (proc, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
p = subprocess.Popen (proc, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
if self.pid_q:
|
if self.q:
|
||||||
self.pid_q.put (p.pid)
|
self.q.put (p.pid)
|
||||||
else:
|
else:
|
||||||
## esto sucede por ejemplo cuando arranca el agente, que estamos en interfaceAdmin() en el mismo hilo, sin _long_running_job ni hilo separado
|
## esto sucede por ejemplo cuando arranca el agente, que estamos en interfaceAdmin() en el mismo hilo, sin _long_running_job ni hilo separado
|
||||||
#logger.debug ('no queue--not writing any PID to it')
|
logger.debug ('no queue--not writing any PID to it')
|
||||||
pass
|
|
||||||
|
|
||||||
sout = serr = ''
|
sout = serr = ''
|
||||||
while p.poll() is None:
|
while p.poll() is None:
|
||||||
for l in iter (p.stdout.readline, b''):
|
for l in iter (p.stdout.readline, b''): sout += l.decode ('utf-8', 'ignore')
|
||||||
partial = l.decode ('utf-8', 'ignore')
|
for l in iter (p.stderr.readline, b''): serr += l.decode ('utf-8', 'ignore')
|
||||||
if self.stdout_q: self.stdout_q.put (partial)
|
|
||||||
sout += partial
|
|
||||||
for l in iter (p.stderr.readline, b''):
|
|
||||||
partial = l.decode ('utf-8', 'ignore')
|
|
||||||
serr += partial
|
|
||||||
time.sleep (1)
|
time.sleep (1)
|
||||||
sout = sout.strip()
|
sout = sout.strip()
|
||||||
serr = serr.strip()
|
serr = serr.strip()
|
||||||
|
|
||||||
## DEBUG
|
## DEBUG
|
||||||
logger.debug (f'stdout follows:')
|
logger.info (f'stdout follows:')
|
||||||
for l in sout.splitlines():
|
for l in sout.splitlines():
|
||||||
logger.debug (f' {l}')
|
logger.info (f' {l}')
|
||||||
#logger.debug (f'stderr follows:')
|
logger.info (f'stderr follows:')
|
||||||
#for l in serr.splitlines():
|
for l in serr.splitlines():
|
||||||
# logger.debug (f' {l}')
|
logger.info (f' {l}')
|
||||||
## /DEBUG
|
## /DEBUG
|
||||||
if 0 != p.returncode:
|
if 0 != p.returncode:
|
||||||
cmd_txt = ' '.join (proc)
|
cmd_txt = ' '.join (proc)
|
||||||
|
@ -347,7 +292,9 @@ class ogLiveWorker(ServerWorker):
|
||||||
res = self.REST.sendMessage ('/'.join ([self.name, path]), obj)
|
res = self.REST.sendMessage ('/'.join ([self.name, path]), obj)
|
||||||
|
|
||||||
if (type (res) is not dict):
|
if (type (res) is not dict):
|
||||||
logger.error (f'response is not a dict ({res})')
|
#logger.error ('No se ha podido establecer conexión con el Servidor de Administración') ## Error de conexión con el servidor
|
||||||
|
logger.debug (f'res ({res})')
|
||||||
|
logger.error ('Error al enviar trama ***send() fallo')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
@ -374,7 +321,9 @@ class ogLiveWorker(ServerWorker):
|
||||||
p = subprocess.Popen (['/usr/bin/browser', '-qws', url])
|
p = subprocess.Popen (['/usr/bin/browser', '-qws', url])
|
||||||
try:
|
try:
|
||||||
p.wait (2) ## if the process dies before 2 seconds...
|
p.wait (2) ## if the process dies before 2 seconds...
|
||||||
logger.error ('Error al ejecutar browser, return code "{}"'.format (p.returncode))
|
logger.error ('Error al ejecutar la llamada a la interface de administración')
|
||||||
|
logger.error ('Error en la creación del proceso hijo')
|
||||||
|
logger.error ('return code "{}"'.format (p.returncode))
|
||||||
return False
|
return False
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
pass
|
pass
|
||||||
|
@ -394,7 +343,7 @@ class ogLiveWorker(ServerWorker):
|
||||||
logger.error (e)
|
logger.error (e)
|
||||||
logger.error ('No se ha podido recuperar la dirección IP del cliente')
|
logger.error ('No se ha podido recuperar la dirección IP del cliente')
|
||||||
return None
|
return None
|
||||||
#logger.debug ('parametroscfg ({})'.format (parametroscfg))
|
logger.debug ('parametroscfg ({})'.format (parametroscfg))
|
||||||
return parametroscfg
|
return parametroscfg
|
||||||
|
|
||||||
def cfg2obj (self, cfg):
|
def cfg2obj (self, cfg):
|
||||||
|
@ -405,17 +354,14 @@ class ogLiveWorker(ServerWorker):
|
||||||
ptrCfg = line.split ('\t')
|
ptrCfg = line.split ('\t')
|
||||||
|
|
||||||
for item in ptrCfg:
|
for item in ptrCfg:
|
||||||
if '=' not in item:
|
k, v = item.split ('=')
|
||||||
logger.warning (f'invalid item ({item})')
|
|
||||||
continue
|
|
||||||
k, v = item.split ('=', maxsplit=1)
|
|
||||||
elem[k] = v
|
elem[k] = v
|
||||||
|
|
||||||
obj.append (elem)
|
obj.append (elem)
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def onActivation (self):
|
def onActivation (self, run_monitoring_thread):
|
||||||
if not os.path.exists ('/scripts/oginit'):
|
if not os.path.exists ('/scripts/oginit'):
|
||||||
## no estamos en oglive, este modulo no debe cargarse
|
## no estamos en oglive, este modulo no debe cargarse
|
||||||
## esta lógica la saco de src/opengnsys/linux/operations.py, donde hay un if similar
|
## esta lógica la saco de src/opengnsys/linux/operations.py, donde hay un if similar
|
||||||
|
@ -430,9 +376,7 @@ class ogLiveWorker(ServerWorker):
|
||||||
self.idproautoexec = None
|
self.idproautoexec = None
|
||||||
self.idcentro = None ## Identificador del centro
|
self.idcentro = None ## Identificador del centro
|
||||||
self.idaula = None ## Identificador del aula
|
self.idaula = None ## Identificador del aula
|
||||||
self.pid_q = None ## for passing PIDs around
|
self.q = None ## for passing PIDs around
|
||||||
self.stdout_q = None ## for passing stdout
|
|
||||||
self.progress_jobs = {}
|
|
||||||
|
|
||||||
ogcore_scheme = os.environ.get ('OGAGENTCFG_OGCORE_SCHEME', 'https')
|
ogcore_scheme = os.environ.get ('OGAGENTCFG_OGCORE_SCHEME', 'https')
|
||||||
ogcore_ip = os.environ.get ('OGAGENTCFG_OGCORE_IP', '192.168.2.1')
|
ogcore_ip = os.environ.get ('OGAGENTCFG_OGCORE_IP', '192.168.2.1')
|
||||||
|
@ -449,16 +393,13 @@ class ogLiveWorker(ServerWorker):
|
||||||
self.urlMenu = self.service.config.get (self.name, 'urlMenu')
|
self.urlMenu = self.service.config.get (self.name, 'urlMenu')
|
||||||
self.urlMsg = self.service.config.get (self.name, 'urlMsg')
|
self.urlMsg = self.service.config.get (self.name, 'urlMsg')
|
||||||
|
|
||||||
ca_file = self.service.config.get (self.name, 'ca')
|
|
||||||
crt_file = self.service.config.get (self.name, 'crt')
|
|
||||||
key_file = self.service.config.get (self.name, 'key')
|
|
||||||
url = url.format (ogcore_scheme, ogcore_ip_port)
|
url = url.format (ogcore_scheme, ogcore_ip_port)
|
||||||
self.urlMenu = self.urlMenu.format (urlmenu_scheme, urlmenu_ip_port)
|
self.urlMenu = self.urlMenu.format (urlmenu_scheme, urlmenu_ip_port)
|
||||||
except NoOptionError as e:
|
except NoOptionError as e:
|
||||||
logger.error ("Configuration error: {}".format (e))
|
logger.error ("Configuration error: {}".format (e))
|
||||||
raise e
|
raise e
|
||||||
logger.setLevel (loglevel)
|
logger.setLevel (loglevel)
|
||||||
self.REST = REST (url, ca_file=ca_file, crt_file=crt_file, key_file=key_file)
|
self.REST = REST (url)
|
||||||
|
|
||||||
if not self.tomaIPlocal():
|
if not self.tomaIPlocal():
|
||||||
raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo')
|
raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo')
|
||||||
|
@ -466,6 +407,7 @@ class ogLiveWorker(ServerWorker):
|
||||||
if not self.tomaMAClocal():
|
if not self.tomaMAClocal():
|
||||||
raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo')
|
raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo')
|
||||||
|
|
||||||
|
if run_monitoring_thread: ## should be true for exactly one ogLiveWorker
|
||||||
threading.Thread (name='monitoring_thread', target=self.mon, daemon=True).start()
|
threading.Thread (name='monitoring_thread', target=self.mon, daemon=True).start()
|
||||||
|
|
||||||
def _long_running_job (self, name, f, args):
|
def _long_running_job (self, name, f, args):
|
||||||
|
@ -480,10 +422,9 @@ class ogLiveWorker(ServerWorker):
|
||||||
|
|
||||||
job_id = '{}-{}'.format (name, ''.join (random.choice ('0123456789abcdef') for _ in range (8)))
|
job_id = '{}-{}'.format (name, ''.join (random.choice ('0123456789abcdef') for _ in range (8)))
|
||||||
import queue
|
import queue
|
||||||
self.pid_q = queue.Queue() ## a single queue works for us because we never have more than one long_running_job at the same time
|
self.q = queue.Queue() ## a single queue works for us because we never have more than one long_running_job at the same time
|
||||||
self.stdout_q = queue.Queue()
|
|
||||||
self.thread_list[job_id] = {
|
self.thread_list[job_id] = {
|
||||||
'thread': ThreadWithResult (target=f, args=(self.pid_q, self.stdout_q) + args),
|
'thread': ThreadWithResult (target=f, args=(self.q,) + args),
|
||||||
'starttime': time.time(),
|
'starttime': time.time(),
|
||||||
'child_pid': None,
|
'child_pid': None,
|
||||||
'running': True,
|
'running': True,
|
||||||
|
@ -493,10 +434,10 @@ class ogLiveWorker(ServerWorker):
|
||||||
return { 'job_id': job_id }
|
return { 'job_id': job_id }
|
||||||
|
|
||||||
## para matar threads tengo lo siguiente:
|
## para matar threads tengo lo siguiente:
|
||||||
## - aqui en _long_running_job meto una cola en self.pid_q
|
## - aqui en _long_running_job meto una cola en self.q
|
||||||
## - (self.pid_q fue inicializado a None al instanciar el objeto, para evitar error "objeto no tiene 'pid_q'")
|
## - (self.q fue inicializado a None al instanciar el objeto, para evitar error "objeto no tiene 'q'")
|
||||||
## - en el thread_list también tengo un child_pid para almacenar el pid de los procesos hijos
|
## - en el thread_list también tengo un child_pid para almacenar el pid de los procesos hijos
|
||||||
## - al crear el ThreadWithResult le paso la cola, y luego en run() la recojo y la meto en el self.pid_q del thread
|
## - al crear el ThreadWithResult le paso la cola, y luego en run() la recojo y la meto en el self.q del thread
|
||||||
## - en interfaceAdmin() al hacer subprocess.Popen(), recojo el pid y lo escribo en la queue
|
## - en interfaceAdmin() al hacer subprocess.Popen(), recojo el pid y lo escribo en la queue
|
||||||
## - en mon() recojo pids de la queue y los meto en thread_list 'child_pid'
|
## - en mon() recojo pids de la queue y los meto en thread_list 'child_pid'
|
||||||
## - algunas funciones llaman a interfaceAdmin más de una vez, y escriben más de un pid en la cola, y en mon() voy recogiendo y actualizando
|
## - algunas funciones llaman a interfaceAdmin más de una vez, y escriben más de un pid en la cola, y en mon() voy recogiendo y actualizando
|
||||||
|
@ -507,11 +448,6 @@ class ogLiveWorker(ServerWorker):
|
||||||
##
|
##
|
||||||
## $ curl --insecure -X POST --data '{"nfn":"EjecutarScript","scp":"cd /usr; sleep 30; pwd; ls","ids":"0"}' https://192.168.2.199:8000/ogAdmClient/EjecutarScript
|
## $ curl --insecure -X POST --data '{"nfn":"EjecutarScript","scp":"cd /usr; sleep 30; pwd; ls","ids":"0"}' https://192.168.2.199:8000/ogAdmClient/EjecutarScript
|
||||||
## {"job_id": "EjecutarScript-333feb3f"}
|
## {"job_id": "EjecutarScript-333feb3f"}
|
||||||
## $ curl --insecure -X POST --data '{"job_id":"EjecutarScript-333feb3f"}' https://192.168.2.199:8000/ogAdmClient/KillJob
|
## $ curl --insecure -X POST --data '{"job_id":"EjecutarScript-333feb3f"}' https://192.168.2.199:8000/CloningEngine/KillJob
|
||||||
##
|
##
|
||||||
## funciona bien, excepto que el PID no muere xD, ni siquiera haciendo subprocess.run('kill')
|
## funciona bien, excepto que el PID no muere xD, ni siquiera haciendo subprocess.run('kill')
|
||||||
|
|
||||||
## para mostrar el progreso de los jobs reutilizo la misma infra
|
|
||||||
## una cola self.stdout_q
|
|
||||||
## en interfaceAdmin escribo la stdout parcial que ya venia recogiendo
|
|
||||||
## mon() lo recoge y le hace un POST a ogcore
|
|
||||||
|
|