"""CAU service: Cluster-Aware Updating via PowerShell remoting (WinRM).""" from collections.abc import AsyncIterator from app.core.exceptions import CAUError from app.core.logging import get_logger from app.services.winrm import WinRMCredentials, WinRMService logger = get_logger(__name__) class CAUService: """Orchestrates Invoke-CauRun against a Windows failover cluster.""" def __init__( self, cluster_name: str, access_node: str, port: int = 5985, credentials: WinRMCredentials | None = None, ) -> None: self.cluster_name = cluster_name self.winrm = WinRMService(access_node, port=port, credentials=credentials) async def get_cluster_nodes(self) -> list[dict[str, str]]: """List cluster nodes and their state.""" script = f""" Import-Module FailoverClusters Get-ClusterNode -Cluster {self.cluster_name} | Select-Object Name, State | ForEach-Object {{ "$($_.Name)|$($_.State)" }} """ output = await self.winrm.run_powershell(script) nodes = [] for line in output.splitlines(): if "|" in line: name, state = line.split("|", 1) nodes.append({"name": name.strip(), "state": state.strip()}) return nodes async def get_cau_status(self) -> str: """Return the last CAU run summary.""" script = f""" Import-Module ClusterAwareUpdating Get-CauRun -ClusterName {self.cluster_name} | Select-Object -First 1 | Format-List | Out-String """ return await self.winrm.run_powershell(script) async def test_cluster(self) -> tuple[bool, str]: """Verify the cluster is reachable and CAU module present.""" try: nodes = await self.get_cluster_nodes() if not nodes: return False, "Keine Cluster-Knoten gefunden" return True, f"Cluster OK — {len(nodes)} Knoten" except Exception as exc: # noqa: BLE001 return False, str(exc) async def invoke_cau_run(self) -> AsyncIterator[str]: """Start a CAU run and stream per-node progress lines. Scaffold implementation: starts Invoke-CauRun and polls Get-CauReport. TODO: true live streaming of per-node phases via event log polling. """ script = f""" Import-Module ClusterAwareUpdating Invoke-CauRun -ClusterName {self.cluster_name} ` -Force -Confirm:$false -WaitForCompletion | Out-String """ try: async for line in self.winrm.stream_powershell(script): yield line except Exception as exc: # noqa: BLE001 raise CAUError(f"CAU-Lauf fehlgeschlagen: {exc}") from exc