-- docker-dev cluster seed. Idempotent — safe to re-run on every `docker compose up`. -- -- Populates: -- ServerCluster MAIN, SITE-A, SITE-B -- ClusterNode central-1, central-2 → MAIN -- site-a-1, site-a-2 → SITE-A -- site-b-1, site-b-2 → SITE-B -- -- ServerCluster.NodeCount + RedundancyMode are coupled by CHECK constraint: -- NodeCount=1 ⇒ RedundancyMode='None' -- NodeCount=2 ⇒ RedundancyMode∈('Warm','Hot') -- -- Each ClusterNode.ApplicationUri MUST be globally unique (UX_ClusterNode_ApplicationUri). -- Convention: urn:OtOpcUa:. -- -- Host = Compose service name (resolves inside the otopcua-dev network). -- OpcUaPort stays at the container-internal 4840; the host-side port mapping is in -- docker-compose.yml ports: blocks and is irrelevant to ClusterNode rows. SET NOCOUNT ON; SET XACT_ABORT ON; BEGIN TRANSACTION; ------------------------------------------------------------------------------ -- ServerCluster ------------------------------------------------------------------------------ IF NOT EXISTS (SELECT 1 FROM dbo.ServerCluster WHERE ClusterId = 'MAIN') INSERT INTO dbo.ServerCluster (ClusterId, Name, Enterprise, Site, NodeCount, RedundancyMode, Enabled, Notes, CreatedBy) VALUES ('MAIN', 'Main cluster', 'zb', 'docker-dev', 2, 'Warm', 1, 'docker-dev seed — central-1/central-2 fused admin+driver: UI + deploy singleton + MAIN OPC UA publishers.', 'docker-dev-seed'); IF NOT EXISTS (SELECT 1 FROM dbo.ServerCluster WHERE ClusterId = 'SITE-A') INSERT INTO dbo.ServerCluster (ClusterId, Name, Enterprise, Site, NodeCount, RedundancyMode, Enabled, Notes, CreatedBy) VALUES ('SITE-A', 'Site A', 'zb', 'site-a', 2, 'Warm', 1, 'docker-dev seed — 2-node driver-only, managed by the central cluster over the shared mesh (empty until configured).', 'docker-dev-seed'); IF NOT EXISTS (SELECT 1 FROM dbo.ServerCluster WHERE ClusterId = 'SITE-B') INSERT INTO dbo.ServerCluster (ClusterId, Name, Enterprise, Site, NodeCount, RedundancyMode, Enabled, Notes, CreatedBy) VALUES ('SITE-B', 'Site B', 'zb', 'site-b', 2, 'Warm', 1, 'docker-dev seed — 2-node driver-only, managed by the central cluster over the shared mesh (empty until configured).', 'docker-dev-seed'); ------------------------------------------------------------------------------ -- ClusterNode — central cluster (MAIN UI + deploy singleton + OPC UA publishers) -- -- NodeId is ":4053" so it matches what ClusterRoleInfo + -- ConfigPublishCoordinator derive from Akka.Cluster.Get(system).State.Members -- (member.Address.Host:Port). NodeDeploymentState.NodeId is FK-bound to -- ClusterNode.NodeId; mismatched values cause FK 547 on deploy. ------------------------------------------------------------------------------ IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'central-1:4053') INSERT INTO dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy) VALUES ('central-1:4053', 'MAIN', 'central-1', 4840, 8081, 'urn:OtOpcUa:central-1', 200, 1, 'docker-dev-seed'); IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'central-2:4053') INSERT INTO dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy) VALUES ('central-2:4053', 'MAIN', 'central-2', 4840, 8081, 'urn:OtOpcUa:central-2', 150, 1, 'docker-dev-seed'); ------------------------------------------------------------------------------ -- ClusterNode — site A ------------------------------------------------------------------------------ IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-a-1:4053') INSERT INTO dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy) VALUES ('site-a-1:4053', 'SITE-A', 'site-a-1', 4840, 8081, 'urn:OtOpcUa:site-a-1', 200, 1, 'docker-dev-seed'); IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-a-2:4053') INSERT INTO dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy) VALUES ('site-a-2:4053', 'SITE-A', 'site-a-2', 4840, 8081, 'urn:OtOpcUa:site-a-2', 150, 1, 'docker-dev-seed'); ------------------------------------------------------------------------------ -- ClusterNode — site B ------------------------------------------------------------------------------ IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-b-1:4053') INSERT INTO dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy) VALUES ('site-b-1:4053', 'SITE-B', 'site-b-1', 4840, 8081, 'urn:OtOpcUa:site-b-1', 200, 1, 'docker-dev-seed'); IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-b-2:4053') INSERT INTO dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy) VALUES ('site-b-2:4053', 'SITE-B', 'site-b-2', 4840, 8081, 'urn:OtOpcUa:site-b-2', 150, 1, 'docker-dev-seed'); ------------------------------------------------------------------------------ -- Galaxy MxAccess gateway — INTENTIONALLY NOT SEEDED (retired 2026-06-15) -- -- This block used to seed a Namespace with Kind='SystemPlatform' + a -- 'GalaxyMxGateway' DriverInstance + 3 mirror tags. That is now BROKEN: the -- 'SystemPlatform' NamespaceKind member was removed when Galaxy became a -- standard Equipment-kind driver (migration 20260613022355 -- CleanupSystemPlatformNamespaces). cluster-seed runs AFTER the migrator, so -- re-inserting a 'SystemPlatform' row re-introduced a Kind the current code -- cannot EF-materialize — which 500s the /deployments page AND fails every -- publish (ConfigComposer reads db.Namespaces). See the cleanup migration. -- -- If a Galaxy fixture is needed on a fresh rig, author an EQUIPMENT-kind Galaxy -- driver via the UNS UI (the 'MAIN-galaxy-eq' pattern) — do NOT re-add a -- SystemPlatform namespace here. ------------------------------------------------------------------------------ COMMIT TRANSACTION; ------------------------------------------------------------------------------ -- Summary (logged by sqlcmd output) ------------------------------------------------------------------------------ SELECT ClusterId, Name, NodeCount, RedundancyMode FROM dbo.ServerCluster ORDER BY ClusterId; SELECT NodeId, ClusterId, Host, OpcUaPort, ApplicationUri, ServiceLevelBase FROM dbo.ClusterNode ORDER BY ClusterId, NodeId; SELECT NamespaceId, ClusterId, Kind, NamespaceUri FROM dbo.Namespace ORDER BY ClusterId, NamespaceId; SELECT DriverInstanceId, ClusterId, DriverType, NamespaceId, Name FROM dbo.DriverInstance ORDER BY ClusterId, DriverInstanceId; SELECT TagId, DriverInstanceId, FolderPath, Name, DataType FROM dbo.Tag ORDER BY DriverInstanceId, FolderPath, Name; ------------------------------------------------------------------------------ -- LDAP group -> AdminUI role mappings (shared dev GLAuth, 10.100.0.35) -- System-wide (ClusterId NULL, IsSystemWide 1). Group keys are the BARE RDN -- names the shared ZB.MOM.WW.Auth.Ldap returns (LdapAuthService.ToGroupShortName -- = first-RDN value), e.g. memberOf ou=OtOpcUa-Admins,... -> "OtOpcUa-Admins". -- Role is stored as the AdminRole enum NAME (HasConversion). -- QUOTED_IDENTIFIER ON is required because the table has a filtered unique index. ------------------------------------------------------------------------------ SET QUOTED_IDENTIFIER ON; SET ANSI_NULLS ON; IF NOT EXISTS (SELECT 1 FROM dbo.LdapGroupRoleMapping WHERE LdapGroup = 'OtOpcUa-Admins' AND ClusterId IS NULL) INSERT INTO dbo.LdapGroupRoleMapping (Id, LdapGroup, Role, ClusterId, IsSystemWide, CreatedAtUtc, Notes) VALUES (NEWID(), 'OtOpcUa-Admins', 'Administrator', NULL, 1, SYSUTCDATETIME(), N'shared-glauth dev seed'); IF NOT EXISTS (SELECT 1 FROM dbo.LdapGroupRoleMapping WHERE LdapGroup = 'OtOpcUa-Designers' AND ClusterId IS NULL) INSERT INTO dbo.LdapGroupRoleMapping (Id, LdapGroup, Role, ClusterId, IsSystemWide, CreatedAtUtc, Notes) VALUES (NEWID(), 'OtOpcUa-Designers', 'Designer', NULL, 1, SYSUTCDATETIME(), N'shared-glauth dev seed'); IF NOT EXISTS (SELECT 1 FROM dbo.LdapGroupRoleMapping WHERE LdapGroup = 'OtOpcUa-Viewers' AND ClusterId IS NULL) INSERT INTO dbo.LdapGroupRoleMapping (Id, LdapGroup, Role, ClusterId, IsSystemWide, CreatedAtUtc, Notes) VALUES (NEWID(), 'OtOpcUa-Viewers', 'Viewer', NULL, 1, SYSUTCDATETIME(), N'shared-glauth dev seed'); SELECT LdapGroup, Role, IsSystemWide FROM dbo.LdapGroupRoleMapping ORDER BY LdapGroup;