Panel/docs/agents/WINDOWS_AGENT.md
2026-06-07 18:01:52 -05:00

219 lines
9.9 KiB
Markdown

# Windows Agent
## Role
`Agent-Windows/OGP64/OGP/ogp_agent.pl` is the Windows/Cygwin execution agent currently tracked in this repository. It mirrors the Linux agent as closely as practical, while using Windows-compatible paths, processes, and wrappers.
## Important Files
- `Agent-Windows/OGP64/OGP/ogp_agent.pl`
- `Agent-Windows/OGP64/OGP/Cfg/Config.pm`
- `Agent-Windows/OGP64/OGP/Cfg/Preferences.pm`
- `Agent-Windows/OGP64/OGP/Cfg/bash_prefs.cfg`
- `Agent-Windows/OGP64/OGP/Cfg/*.default`
- `Agent-Windows/php-query/`
- `Agent-Windows/ArmaBE/`
- `Agent-Windows/Cfg/`
- `Agent-Windows/Install/`
- `Agent-Windows/ServerFiles/`
- `Agent-Windows/Schedule/`
## Cygwin Requirements
The Windows agent assumes a Cygwin-style environment that can provide:
- `screen`
- Perl
- shell utilities such as `ps`, `grep`, `cut`, `awk`, `sed`
- `cygpath`
- a usable `bash`
The goal is to keep the Windows agent behavior close to the Linux agent so the Panel does not need separate semantics for basic lifecycle operations.
## Startup Logic
Relevant functions:
- `universal_start_without_decrypt`
- `create_screen_cmd`
- `create_screen_cmd_loop`
- `replace_OGP_Env_Vars`
The Windows agent also uses `screen` sessions for managed server execution. Depending on the game and binary type, it may wrap commands in `cmd /Q /C start` or run a batch file wrapper.
The session naming scheme also follows the OGP convention:
```text
OGP_HOME_000000123
```
### Windows Startup Launcher
Relevant files:
- `Agent-Windows/Install/agent_start.bat`
- `Agent-Windows/Install/agent_start_cygwin.sh`
- `/OGP/Cfg/bash_prefs.cfg` on an installed node
The batch launcher must not assume that `bash` is in the Windows `PATH`. It explicitly checks:
- `%~dp0bin\bash.exe`
- `%~dp0..\bin\bash.exe`
- `%~dp0..\..\bin\bash.exe`
- `C:\OGP64\bin\bash.exe`
- `C:\cygwin64\bin\bash.exe`
- `C:\cygwin\bin\bash.exe`
This matters because the maintained launcher may be run from `C:\OGP64\agent_start.bat` or from `C:\OGP64\OGP\Install\agent_start.bat`. In the second case the actual Cygwin root is two directories above the launcher, so `C:\OGP64\bin\bash.exe` must be checked.
Manual launches pause on fatal errors so the error remains visible. Service or scheduled-task wrappers can set `GSP_AGENT_NO_PAUSE=1` to return immediately instead of waiting forever at a `pause` prompt.
The launcher now prints the detected script directory, Cygwin root, `bash.exe` path, OGP path, `ogp_agent.pl` path, config path, and startup log path before it launches the shell helper. The goal is to keep the original failure visible in the same console window instead of replacing it with a generic wrapper message.
The Cygwin-side helper performs the shell work:
1. enter `/OGP`
2. normalize CRLF to LF for `.pl`, `.pm`, `.sh`, and `.cfg` files under `/OGP`
3. create missing `Cfg/Config.pm`, `Cfg/Preferences.pm`, and `Cfg/bash_prefs.cfg` from tracked `.default` files
4. strip CRLF and leading whitespace before assignments in `/OGP/Cfg/bash_prefs.cfg`
5. source `/OGP/Cfg/bash_prefs.cfg`
6. set up `gsp_agent_start.log` under `/var/log` by default, or the native `C:\OGP64\var\log\gsp_agent_start.log` path when passed from the batch wrapper
7. tee stdout and stderr to the startup log while still printing live output in the same console
8. optionally update only the Windows agent file from Forgejo when `agent_auto_update=1`
9. backup the current `/OGP/ogp_agent.pl`
10. validate downloaded and installed agent files with content checks plus `perl -c`
11. restore the backup if validation fails
12. refuse to launch if `Cfg/Config.pm` still contains placeholder values
13. launch `/OGP/ogp_agent.pl`
Default optional update source:
- repo: `http://forge.runlevelsystems.com/dev/GSP.git`
- branch: `Panel-unstable`
- source file: `Agent-Windows/OGP64/OGP/ogp_agent.pl` in the current repo layout
- raw URL: `http://forge.runlevelsystems.com/dev/GSP/raw/branch/Panel-unstable/Agent-Windows/OGP64/OGP/ogp_agent.pl`
- target file: `/OGP/ogp_agent.pl`
Auto-update failure is non-fatal. Missing `curl`/`git`, download failure, clone failure, missing source file, HTTP error-page downloads, empty files, or failed validation should warn and continue with the current installed agent.
Restart-time auto-update is allowlisted. It may replace only `/OGP/ogp_agent.pl`. It must never overwrite `Cfg/Config.pm`, `Cfg/Preferences.pm`, `Cfg/bash_prefs.cfg`, service settings, passwords, generated installer config, server homes, logs, or user-created files. Broader agent updates belong to the admin-only Panel `component_update` flow, which also preserves `Cfg/`.
### Startup Log And Troubleshooting
Default startup log:
- `/var/log/gsp_agent_start.log` inside Cygwin
- `C:\OGP64\var\log\gsp_agent_start.log` when launched through the Windows batch wrapper
If startup fails, the batch wrapper prints the last 100 lines of that log in the same console window before pausing. This is the primary place to look for the real cause of a bad config, missing package, or bad downloaded agent file.
Manual troubleshooting flow:
1. Launch `agent_start.bat` directly from the Windows console or Explorer.
2. Read the path summary printed at the top of the window.
3. Check the log tail printed on failure.
4. Inspect `gsp_agent_start.log` for the full startup sequence.
### Auto-Update Allowlist
Restart-time auto-update must not touch production config files. Only the following file is allowed to be replaced automatically:
- `/OGP/ogp_agent.pl`
It must never overwrite:
- `Cfg/Config.pm`
- `Cfg/Preferences.pm`
- `Cfg/bash_prefs.cfg`
- service settings
- generated installer config
- server homes
- logs
- user-created files
- passwords or keys
The Windows agent file does not use `DBI` at startup. If a Windows node reports `Can't locate DBI.pm` at line 48, it is a strong signal that a Linux agent file was copied onto the Windows node.
Required Cygwin Perl packages include `perl`, `perl_vendor`, `perl-HTTP-Daemon`, `perl-Path-Class`, `perl-XML-Parser`, `perl-XML-Simple`, `perl-Archive-Zip`, and `perl-Archive-Extract`. A clean non-Cygwin Linux workstation may fail `perl -c` on these dependencies even though the bundled Windows Cygwin tree contains them.
Default tracked config template files contain placeholders only. Production installs must replace `CHANGE_ME_PANEL_AGENT_KEY`, `web_api_url`, and related values with the values configured in the Panel remote-server record. If startup creates `Config.pm` from `Config.pm.default`, it stops with a clear error until those values are changed.
## Status Logic
Relevant functions:
- `is_screen_running_without_decrypt`
- `get_screen_pid_without_decrypt`
- `server_status_without_decrypt`
- `verify_server_stopped_without_decrypt`
The status model should check:
- screen/session existence
- process/PID information when available
- game port listening
- optional query metadata
The old `SERVER_STOPPED` file should not be the source of truth.
If the game port is listening but the managed screen session is not found, the agent reports `ONLINE` with a warning. This protects customers from false offline/unknown states when a process survives a screen/session mismatch or an older agent cannot report the session correctly.
## Logging
Relevant function:
- `get_log`
Windows/Cygwin logs come from screen logs and/or local copies. Log retrieval should remain compatible with the Panel's AJAX log view.
## Workshop / Server Content
The primary Workshop workflow is owned by the Panel `addonsmanager`, not the legacy `steam_workshop` RPC. For Windows/Cygwin servers the Panel:
1. writes `gsp_server_content/workshop_manifest.json` under the server home
2. stages `generic_steam_workshop_windows_cygwin.sh` under `gsp_server_content/scripts/workshop/`
3. invokes the staged script through the authenticated `exec` RPC
The staged script uses Python and SteamCMD, validates numeric Workshop IDs, keeps writes under the server home, logs to `gsp_server_content/workshop_install_windows.log`, and supports DayZ/Arma-style `@mod` folders plus `.bikey` copying.
The older `steam_workshop` XML-RPC method remains for legacy compatibility only and should not be treated as the primary customer workflow.
## Scheduler
Relevant functions:
- `scheduler_dispatcher`
- `scheduler_server_action`
- `scheduler_log_events`
- `scheduler_add_task`
- `scheduler_del_task`
- `scheduler_edit_task`
- `scheduler_read_tasks`
- `scheduler_stop`
- `scheduler_list_tasks`
The Windows scheduler implementation should remain aligned with the Linux scheduler implementation so the Panel can treat both the same way.
## Remote Git Self-Update
The Windows agent exposes the same admin-only `component_update` XML-RPC method as the Linux agent. In this repository the Windows agent is explicitly Cygwin-based, so the first implementation uses a Cygwin-compatible detached shell updater rather than a separate native PowerShell service wrapper.
Flow:
1. Panel sends an encrypted payload containing repo URL, branch, Windows agent source folder, optional Git path, optional backup path, and optional admin post-update command.
2. Agent validates the request and writes `gsp_component_update_<timestamp>.sh` under the current agent run directory, usually `/OGP`.
3. The updater runs detached in `screen`.
4. The updater clones the configured branch into staging.
5. It copies only the configured Windows agent source folder, usually `Agent-Windows`.
6. It preserves `Cfg/`, `ServerFiles/`, `Schedule/`, logs, screen logs, `steamcmd/`, `startups/`, temporary folders, backups, and PID files.
7. It validates `ogp_agent.pl` with `perl -c`.
8. It restarts the agent using the existing Cygwin/screen fallback.
The immediate response is `queued` with the agent-side log path `gsp_component_update.log`.
## Windows-Specific Notes
- Path conversion between Cygwin and native Windows paths matters during startup.
- Batch wrappers are often needed for Windows executables.
- Process cleanup must avoid killing unrelated processes that happen to share an executable name.
- The agent should continue to use `screen` where it already does so, to stay aligned with Linux behavior.