diff --git a/Borealis.ps1 b/Borealis.ps1 index c5f37b9..810e9a7 100644 --- a/Borealis.ps1 +++ b/Borealis.ps1 @@ -601,15 +601,67 @@ function Ensure-AnsibleExecutionEnvironment { $metadata['requirements_hash'] = $requirementsHash } + $supportDir = Join-Path $eeRoot 'support' try { - $metadata | ConvertTo-Json -Depth 5 | Set-Content -Path $metadataPath -Encoding UTF8 + New-Item -ItemType Directory -Force -Path $supportDir | Out-Null + } catch {} + + $fcntlStubPath = Join-Path $supportDir 'fcntl.py' + $fcntlStub = @' +"""Compat shim for POSIX-only fcntl module. + +Generated by Borealis to allow Ansible tooling to run on Windows hosts +where the standard library fcntl module is unavailable. The stub provides +symbol constants and no-op function implementations so imports succeed. +""" + +LOCK_SH = 1 +LOCK_EX = 2 +LOCK_UN = 8 +LOCK_NB = 4 + +F_DUPFD = 0 +F_GETFD = 1 +F_SETFD = 2 +F_GETFL = 3 +F_SETFL = 4 + +FD_CLOEXEC = 1 + +def ioctl(*_args, **_kwargs): + return 0 + + +def fcntl(*_args, **_kwargs): + return 0 + + +def flock(*_args, **_kwargs): + return 0 + + +def lockf(*_args, **_kwargs): + return 0 +'@ + + try { + if (-not (Test-Path (Join-Path $supportDir '__init__.py') -PathType Leaf)) { + Set-Content -Path (Join-Path $supportDir '__init__.py') -Value '' -Encoding UTF8NoBOM + } + Set-Content -Path $fcntlStubPath -Value $fcntlStub -Encoding UTF8NoBOM + } catch { + Write-AgentLog -FileName $LogName -Message "[AnsibleEE] Failed to seed Windows fcntl compatibility shim: $($_.Exception.Message)" + } + + try { + $metadata | ConvertTo-Json -Depth 5 | Set-Content -Path $metadataPath -Encoding UTF8NoBOM } catch { Write-AgentLog -FileName $LogName -Message "[AnsibleEE] Failed to persist metadata.json: $($_.Exception.Message)" throw "Unable to persist Ansible execution environment metadata." } try { - Set-Content -Path $versionTxtPath -Value $expectedVersionNorm -Encoding UTF8 + Set-Content -Path $versionTxtPath -Value $expectedVersionNorm -Encoding UTF8NoBOM } catch {} Write-AgentLog -FileName $LogName -Message "[AnsibleEE] Execution environment ready at $eeRoot" diff --git a/Data/Agent/Roles/role_PlaybookExec_SYSTEM.py b/Data/Agent/Roles/role_PlaybookExec_SYSTEM.py index 2238398..62a7fb4 100644 --- a/Data/Agent/Roles/role_PlaybookExec_SYSTEM.py +++ b/Data/Agent/Roles/role_PlaybookExec_SYSTEM.py @@ -178,6 +178,16 @@ def _scripts_bin(): return None +def _ee_support_path(): + root = _ansible_ee_root() + if not root: + return None + support = os.path.join(root, 'support') + if os.path.isdir(support): + return support + return None + + def _ansible_playbook_cmd(): exe = 'ansible-playbook.exe' if os.name == 'nt' else 'ansible-playbook' sdir = _scripts_bin() @@ -341,6 +351,19 @@ class Role: version = _ansible_ee_version() if version: self._ansible_log(f"[bootstrap] using execution environment version {version}") + + support_dir = _ee_support_path() + if support_dir: + existing_pp = os.environ.get('PYTHONPATH') or '' + paths = [seg for seg in existing_pp.split(os.pathsep) if seg] + if support_dir not in paths: + os.environ['PYTHONPATH'] = ( + support_dir + if not existing_pp + else support_dir + os.pathsep + existing_pp + ) + os.environ['BOREALIS_ANSIBLE_EE_SUPPORT'] = support_dir + return True async def _ensure_ansible_ready(self) -> bool: