Matrix-gate satisfied (14 passed / 1 skipped / 0 failed on 2026-04-30 per docs/v2/Galaxy.ParityMatrix.md). Galaxy access flows through the in-process GalaxyDriver → mxaccessgw exclusively. Legacy infrastructure deleted in this commit: Source projects (6): - src/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host (.NET 4.8 x86 + MXAccess COM) - src/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Proxy (in-process pipe client) - src/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Shared (pipe-IPC contracts) - tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests - tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Proxy.Tests - tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Shared.Tests Test projects with no consumer after legacy retired (3): - tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.E2E (drove Galaxy.Host EXE) - tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.ParityTests (drove both backends) - tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.TestSupport (only consumed by Host/Proxy tests) Edits: - ZB.MOM.WW.OtOpcUa.slnx: drop nine project entries - Server.csproj: drop Driver.Galaxy.Proxy ProjectReference - Server/Program.cs: drop GalaxyProxyDriverFactoryExtensions.Register + the parallel-registration comment block; only GalaxyDriverFactoryExtensions registers now under DriverType "GalaxyMxGateway" - Install-Services.ps1: rewrite to drop OtOpcUaGalaxyHost service install + the GalaxySharedSecret/ZbConnection/GalaxyClientName/GalaxyPipeName/ AvevaServiceDependencies/MxAccessInitialConnect* parameters that only applied to the legacy host. Adds a closing note pointing operators at the separate mxaccessgw install - Uninstall-Services.ps1: keep OtOpcUaGalaxyHost in the cleanup loop so pre-7.2 rigs upgrade-uninstall cleanly, plus add OtOpcUaWonderwareHistorian - scripts/e2e/test-galaxy.ps1: deleted (drove the legacy E2E) - scripts/e2e/e2e-config.sample.json: rewrite the galaxy section comment to reflect the GalaxyMxGateway-only path - scripts/e2e/README.md: drop OtOpcUaGalaxyHost references - scripts/compliance/phase-7-compliance.ps1: drop Galaxy.Shared HistorianAlarms* checks (those contracts moved to Driver.Historian.Wonderware.Client in PR 3.4) Live state: OtOpcUaGalaxyHost Windows service stopped + removed via NSSM before this commit. The dev box's Galaxy access is now exclusively through the running mxaccessgw (separate repo). Stays out of scope for PR 7.2 (PR 7.3 territory): - CLAUDE.md Galaxy section rewrite - mxaccess_documentation.md deletion - Memory entries for the now-retired Galaxy.Host service Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
143 lines
6.0 KiB
PowerShell
143 lines
6.0 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Registers the v2 Windows services on a node: OtOpcUa (main server, net10) and
|
|
optionally OtOpcUaWonderwareHistorian (Wonderware historian sidecar).
|
|
|
|
.DESCRIPTION
|
|
PR 7.2 retired the legacy out-of-process OtOpcUaGalaxyHost service alongside the
|
|
GalaxyProxyDriver / GalaxyHost / GalaxyShared projects. Galaxy access now flows
|
|
through the in-process GalaxyDriver talking gRPC to a separately-installed
|
|
mxaccessgw. The mxaccessgw server runs out of its own repo
|
|
(`c:\Users\dohertj2\Desktop\mxaccessgw\`) — see
|
|
`docs/v2/Galaxy.ParityRig.md` for the gw setup recipe.
|
|
|
|
.PARAMETER InstallRoot
|
|
Where the binaries live (typically C:\Program Files\OtOpcUa).
|
|
|
|
.PARAMETER ServiceAccount
|
|
Service account SID or DOMAIN\name. The OtOpcUa service runs under this account.
|
|
|
|
.PARAMETER InstallWonderwareHistorian
|
|
Gate the OtOpcUaWonderwareHistorian sidecar install. Off by default; set when
|
|
the deployment uses the Wonderware historian for history reads + alarm-event
|
|
persistence.
|
|
|
|
.PARAMETER HistorianSharedSecret
|
|
Per-process secret passed to the Historian sidecar via env var. Generated
|
|
freshly per install when not supplied.
|
|
|
|
.EXAMPLE
|
|
.\Install-Services.ps1 -InstallRoot 'C:\Program Files\OtOpcUa' -ServiceAccount 'OTOPCUA\svc-otopcua'
|
|
|
|
.EXAMPLE
|
|
.\Install-Services.ps1 -InstallRoot 'C:\Program Files\OtOpcUa' -ServiceAccount 'OTOPCUA\svc-otopcua' `
|
|
-InstallWonderwareHistorian
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory)] [string]$InstallRoot,
|
|
[Parameter(Mandatory)] [string]$ServiceAccount,
|
|
|
|
# PR 3.W — Wonderware historian sidecar. Optional; gates the
|
|
# OtOpcUaWonderwareHistorian service. Secret + pipe defaults match the server's
|
|
# Historian:Wonderware appsettings block.
|
|
[switch]$InstallWonderwareHistorian,
|
|
[string]$HistorianSharedSecret,
|
|
[string]$HistorianPipeName = 'OtOpcUaWonderwareHistorian',
|
|
[string]$HistorianServer = 'localhost',
|
|
[int]$HistorianPort = 32568,
|
|
[string[]]$AvevaServiceDependencies = @('NmxSvc', 'aaBootstrap', 'aaGR')
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
if (-not (Test-Path "$InstallRoot\OtOpcUa.Server.exe")) {
|
|
Write-Error "OtOpcUa.Server.exe not found at $InstallRoot — copy the publish output first"
|
|
exit 1
|
|
}
|
|
|
|
# Generate fresh shared secrets per install if not supplied.
|
|
function New-SharedSecret {
|
|
$bytes = New-Object byte[] 32
|
|
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
|
|
return [Convert]::ToBase64String($bytes)
|
|
}
|
|
if ($InstallWonderwareHistorian -and -not $HistorianSharedSecret) { $HistorianSharedSecret = New-SharedSecret }
|
|
|
|
if ($InstallWonderwareHistorian -and -not (Test-Path "$InstallRoot\WonderwareHistorian\OtOpcUa.Driver.Historian.Wonderware.exe")) {
|
|
Write-Error "OtOpcUa.Driver.Historian.Wonderware.exe not found at $InstallRoot\WonderwareHistorian — copy the publish output first"
|
|
exit 1
|
|
}
|
|
|
|
# Resolve the SID — the IPC ACL needs the SID, not the down-level name.
|
|
$sid = if ($ServiceAccount.StartsWith('S-1-')) {
|
|
$ServiceAccount
|
|
} else {
|
|
(New-Object System.Security.Principal.NTAccount $ServiceAccount).Translate([System.Security.Principal.SecurityIdentifier]).Value
|
|
}
|
|
|
|
# --- Install OtOpcUaWonderwareHistorian (PR 3.W) — separate sidecar that exposes the
|
|
# Wonderware Historian SDK via a named-pipe protocol consumed by the .NET 10 server.
|
|
# Optional: only installed when -InstallWonderwareHistorian is supplied. Depends on the
|
|
# hard AVEVA services that host the historian SDK runtime path.
|
|
$historianDepend = $null
|
|
if ($InstallWonderwareHistorian) {
|
|
$historianEnv = @(
|
|
"OTOPCUA_HISTORIAN_PIPE=$HistorianPipeName"
|
|
"OTOPCUA_ALLOWED_SID=$sid"
|
|
"OTOPCUA_HISTORIAN_SECRET=$HistorianSharedSecret"
|
|
"OTOPCUA_HISTORIAN_ENABLED=true"
|
|
"OTOPCUA_HISTORIAN_SERVER=$HistorianServer"
|
|
"OTOPCUA_HISTORIAN_PORT=$HistorianPort"
|
|
) -join "`0"
|
|
$historianEnv += "`0`0"
|
|
|
|
Write-Host "Installing OtOpcUaWonderwareHistorian..."
|
|
& sc.exe create OtOpcUaWonderwareHistorian binPath= "`"$InstallRoot\WonderwareHistorian\OtOpcUa.Driver.Historian.Wonderware.exe`"" `
|
|
DisplayName= 'OtOpcUa Wonderware Historian Sidecar (out-of-process aahClient)' `
|
|
start= auto `
|
|
depend= ($AvevaServiceDependencies -join '/') `
|
|
obj= $ServiceAccount | Out-Null
|
|
& sc.exe config OtOpcUaWonderwareHistorian start= delayed-auto | Out-Null
|
|
|
|
$svcKey = "HKLM:\SYSTEM\CurrentControlSet\Services\OtOpcUaWonderwareHistorian"
|
|
$envValue = $historianEnv.Split("`0") | Where-Object { $_ -ne '' }
|
|
Set-ItemProperty -Path $svcKey -Name 'Environment' -Type MultiString -Value $envValue
|
|
|
|
$historianDepend = 'OtOpcUaWonderwareHistorian'
|
|
}
|
|
|
|
# --- Install OtOpcUa. Galaxy access flows through GalaxyDriver → mxaccessgw (gRPC),
|
|
# so OtOpcUa no longer depends on a sibling service for Galaxy connectivity. The
|
|
# mxaccessgw is installed separately. When the Wonderware sidecar is installed,
|
|
# depend on it for startup ordering.
|
|
$otOpcUaDepends = @()
|
|
if ($historianDepend) { $otOpcUaDepends += $historianDepend }
|
|
|
|
Write-Host "Installing OtOpcUa..."
|
|
$createArgs = @(
|
|
'create', 'OtOpcUa',
|
|
'binPath=', "`"$InstallRoot\OtOpcUa.Server.exe`"",
|
|
'DisplayName=', 'OtOpcUa Server',
|
|
'start=', 'auto',
|
|
'obj=', $ServiceAccount
|
|
)
|
|
if ($otOpcUaDepends.Count -gt 0) {
|
|
$createArgs += @('depend=', ($otOpcUaDepends -join '/'))
|
|
}
|
|
& sc.exe @createArgs | Out-Null
|
|
|
|
Write-Host ""
|
|
Write-Host "Installed. Start with:"
|
|
if ($InstallWonderwareHistorian) { Write-Host " sc.exe start OtOpcUaWonderwareHistorian" }
|
|
Write-Host " sc.exe start OtOpcUa"
|
|
if ($InstallWonderwareHistorian) {
|
|
Write-Host ""
|
|
Write-Host "Wonderware historian shared secret (configure into appsettings.json Historian:Wonderware:SharedSecret):"
|
|
Write-Host " $HistorianSharedSecret"
|
|
}
|
|
Write-Host ""
|
|
Write-Host "NOTE: Galaxy access flows through mxaccessgw — install + run that separately"
|
|
Write-Host " per docs/v2/Galaxy.ParityRig.md. OtOpcUa connects via the Galaxy.Gateway"
|
|
Write-Host " section of appsettings.json (default endpoint http://localhost:5120)."
|