Phase 1 + Phase 2 A/B/C feature-complete #1
Reference in New Issue
Block a user
Delete Branch "phase-1-configuration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
PR 1 — Phase 1 + Phase 2 A/B/C → v2
Source:
phase-1-configuration(commits980ea51..7403b92, 11 commits)Target:
v2URL: https://gitea.dohertylan.com/dohertj2/lmxopcua/pulls/new/phase-1-configuration
Summary
(InitialSchema + 8 stored procs + AuthorizationGrants), Core + Server + full Admin UI
(Blazor Server with cluster CRUD, draft → diff → publish → rollback, equipment with
OPC 40010, UNS, namespaces, drivers, ACLs, reservations, audit), LDAP via GLAuth
(
localhost:3893), SignalR real-time fleet status + alerts.(Galaxy.Shared, netstandard2.0, MessagePack), Galaxy.Host with real Win32 STA pump,
ACL + caller-SID + per-process-secret IPC, Galaxy-specific MemoryWatchdog +
RecyclePolicy + PostMortemMmf + MxAccessHandle, three
IGalaxyBackendimplementations (Stub / DbBacked / MxAccess — real ArchestrA.MxAccess.dll
reference, x86, smoke-tested live against
LMXProxyServer), Galaxy.Proxy with all9 capability interfaces (
IDriver/ITagDiscovery/IReadable/IWritable/ISubscribable/IAlarmSource/IHistoryProvider/IRediscoverable/IHostConnectivityProbe) + supervisor (Backoff + CircuitBreaker +HeartbeatMonitor).
migration script, two-service Windows installer scripts, process-spawn cross-FX
parity test, Stream D removal procedure doc with both Option A (rewrite 494 v1
tests) and Option B (archive + new v2 E2E suite) spelled out step-by-step.
What's NOT in this PR
OtOpcUa.Hostdeletion (Stream D.1) — reserved for a follow-up PR afterOption B's E2E suite is green. The 494 v1 tests still pass against the unchanged
legacy Host.
removal-procedure doc describes.
Tests
964 pass / 1 pre-existing Phase 0 baseline failure, across 14 test projects:
Test plan for reviewers
dotnet build ZB.MOM.WW.OtOpcUa.slnxsucceeds with no warnings beyond theknown NuGetAuditSuppress + xUnit1051 warnings
dotnet test ZB.MOM.WW.OtOpcUa.slnxshows the same 964/1 resultGet-Service aaGR, aaBootstrapreports Running on the merger's boxdocker ps --filter name=otopcua-mssqlshows the SQL container Updotnet run --project src/ZB.MOM.WW.OtOpcUa.Admin); home pagerenders at http://localhost:5123/; LDAP sign-in with GLAuth
readonly/readonly123succeedspowershell -File scripts/migration/Migrate-AppSettings-To-DriverConfig.ps1 -DryRunproducesa well-formed DriverConfig JSON
are explicitly documented (
549cd36,a7126ba,7403b92are the mostrecent and most detailed)
Follow-up tracking
PR 2 (next session) will execute Stream D Option B — archive
OtOpcUa.TestsasOtOpcUa.Tests.v1Archive, build the newOtOpcUa.Driver.Galaxy.E2Etest project,delete legacy
OtOpcUa.Host, and run the parity-validation cycle. Seedocs/v2/implementation/stream-d-removal-procedure.md.otopcua-mssql-data:/var/opt/mssqlon the SQL Server container so DB files survive container restart anddocker rm; sqlcmd verification command using the newmssql-tools18path that the 2022 image ships with; EF Core CLI install for use starting in Phase 1 Stream B; bumped step count from 8 → 10. Also adds a Troubleshooting subsection covering the seven most common Windows install snags (WSL distro not auto-installed needs-d Ubuntu; Docker PATH not refreshed needs new shell or sign-in; docker-users group membership needs sign-out/in; WSL 2 kernel update needs manual install on legacy systems; SA password complexity rules; Linux vs Windows containers mode mismatch; Hyper-V coexistence with Docker requires WSL 2 backend not Hyper-V backend per decision #134). Step 1 acceptance criteria gain "docker ps shows otopcua-mssql Up" and explicit note that steps 4a/4b need admin elevation (no silent admin-free path exists on Windows). bf6741ba7fotopcua-mssqlat localhost:1433 with sa/OtOpcUaDev_2026! credentials and Docker named volumeotopcua-mssql-datamounted at /var/opt/mssql, dev Galaxy, GLAuth at C:\publish\glauth\ on ports 3893/3894, plus rows for not-yet-standing services like OPC Foundation reference server / FOCAS stub / Modbus simulator / ab_server / Snap7 / TwinCAT XAR VM with target ports to stand up later); Connection strings for appsettings.Development.json (copy-paste-ready, flagged never-commit); Container management quick reference (start/stop/logs/shell/query/nuclear-reset); Credential rotation note. fc0ce36308requiredmodifier — net48 lacks RequiredMemberAttribute and we'd need a polyfill shim like the existing IsExternalInit one; default-string init is simpler). System.Data.SqlClient 4.9.0 added (the same package the v1 Host uses; net48-compatible). Backend/DbBackedGalaxyBackend wraps the repository: DiscoverAsync builds a real DiscoverHierarchyResponse (groups attributes by gobject, resolves parent-by-tagname, maps category_id → human-readable template-category name mirroring v1 AlarmObjectFilter); ReadValuesAsync/WriteValuesAsync/HistoryReadAsync still surface "MXAccess code lift pending (Phase 2 Task B.1)" because runtime data values genuinely need the COM client; OpenSession/CloseSession/Subscribe/Unsubscribe/AlarmSubscribe/AlarmAck/Recycle return success without backend work (subscription ID is a synthetic counter for now). Live smoke tests (GalaxyRepositoryLiveSmokeTests) skip when localhost ZB is unreachable; when present they verify (1) TestConnection returns true, (2) GetHierarchy returns at least one deployed gobject with a non-empty TagName, (3) GetAttributes returns rows with FullTagReference matching the "tag.attribute" shape, (4) GetLastDeployTime returns a value, (5) DbBackedBackend.DiscoverAsync returns at least one gobject with attributes and a populated TemplateCategory. All 5 pass against the local Galaxy. Full solution 957 pass / 1 pre-existing Phase 0 baseline; the 494 v1 IntegrationTests + 6 v1 IntegrationTests-net48 tests still pass — legacy OtOpcUa.Host untouched. Remaining for the Phase 2 exit gate is the MXAccess COM client port itself (the v1 MxAccessClient partials + IMxProxy abstraction + StaPump-based Connect/Subscribe/Read/Write semantics) — Discover is now solved in DB-backed form, so the lift can focus exclusively on the runtime data-plane. 549cd36662git rm -r src/ZB.MOM.WW.OtOpcUa.Hostis destructive enough to need explicit operator authorization on a real PR review. scripts/migration/Migrate-AppSettings-To-DriverConfig.ps1 takes a v1 appsettings.json and emits the v2 DriverInstance.DriverConfig JSON blob (MxAccess/Database/Historian sections) ready to upsert into the central Configuration DB; null-leaf stripping; -DryRun mode; smoke-tested against the dev appsettings.json and produces the expected three-section ordered-dictionary output. scripts/install/Install-Services.ps1 registers the two v2 services with sc.exe — OtOpcUaGalaxyHost first (net48 x86 EXE with OTOPCUA_GALAXY_PIPE/OTOPCUA_ALLOWED_SID/OTOPCUA_GALAXY_SECRET/OTOPCUA_GALAXY_BACKEND/OTOPCUA_GALAXY_ZB_CONN/OTOPCUA_GALAXY_CLIENT_NAME env vars set via HKLM:\SYSTEM\CurrentControlSet\Services\OtOpcUaGalaxyHost\Environment registry), then OtOpcUa with depend=OtOpcUaGalaxyHost; resolves down-level account names to SID for the IPC ACL; generates a fresh 32-byte base64 shared secret per install if not supplied (kept out of registry — operators record offline for service rebinding scenarios); echoes start commands. scripts/install/Uninstall-Services.ps1 stops + removes both services. tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Proxy.Tests/HostSubprocessParityTests.cs is the production-shape parity test — Proxy (.NET 10) spawns the actual OtOpcUa.Driver.Galaxy.Host.exe (net48 x86) as a subprocess via Process.Start with backend=db env vars, connects via real named pipe, calls Discover, asserts at least one Galaxy gobject comes back. Skipped when running as Administrator (PipeAcl denies admins, same guard as other IPC integration tests), when the Host EXE hasn't been built, or when the ZB SQL endpoint is unreachable. This is the cross-FX integration that the parity suite genuinely needs — the previous IPC tests all ran in-process; this one validates the production deployment topology where Proxy and Host are separate processes communicating only over the named pipe. docs/v2/implementation/stream-d-removal-procedure.md is the next-session playbook: Option A (rewrite 494 v1 tests via a ProxyMxAccessClientAdapter that implements v1's IMxAccessClient by forwarding to GalaxyProxyDriver — Vtq↔DataValueSnapshot, Quality↔StatusCode, OnTagValueChanged↔OnDataChange mapping; 3-5 days, full coverage), Option B (rename OtOpcUa.Tests → OtOpcUa.Tests.v1Archive with [Trait("Category", "v1Archive")] for opt-in CI runs; new OtOpcUa.Driver.Galaxy.E2E test project with 10-20 representative tests via the HostSubprocessParityTests pattern; 1-2 days, accreted coverage); deletion checklist with eight pre-conditions, ten ordered steps, and a rollback path (git revert restores the legacy Host alongside the v2 stack — both topologies remain installable until the downstream consumer cutover). Full solution 964 pass / 1 pre-existing Phase 0 baseline; the 494 v1 IntegrationTests + 6 v1 IntegrationTests-net48 still pass because legacy OtOpcUa.Host stays untouched until an interactive session executes the procedure doc. 7403b92b72Closing � commits from this PR are already ancestors of v2 via PR #3 (pr4-findings was a linear superset). The code is merged; this PR is now redundant.
Pull request closed