refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj, namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated. ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated. SQL roles/logins, LDAP domains, CLI command name, and CLI config dir (~/.scadalink → ~/.scadabridge) also renamed. Build green; 5 Host.Tests fail awaiting SQL login rename in next commit. Pre-existing StaleTagMonitor timing flakes unchanged. Rename script committed at tools/rename-to-scadabridge.sh.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# ScadaLink Installation Guide
|
||||
# ScadaBridge Installation Guide
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -11,32 +11,32 @@
|
||||
|
||||
## Single Binary Deployment
|
||||
|
||||
ScadaLink ships as a single executable (`ScadaLink.Host.exe`) that runs in either Central or Site role based on configuration.
|
||||
ScadaBridge ships as a single executable (`ZB.MOM.WW.ScadaBridge.Host.exe`) that runs in either Central or Site role based on configuration.
|
||||
|
||||
### Windows Service Installation
|
||||
|
||||
```powershell
|
||||
# Central Node
|
||||
sc.exe create "ScadaLink-Central" binPath="C:\ScadaLink\ScadaLink.Host.exe" start=auto
|
||||
sc.exe description "ScadaLink-Central" "ScadaLink SCADA Central Hub"
|
||||
sc.exe create "ScadaBridge-Central" binPath="C:\ScadaBridge\ZB.MOM.WW.ScadaBridge.Host.exe" start=auto
|
||||
sc.exe description "ScadaBridge-Central" "ScadaBridge SCADA Central Hub"
|
||||
|
||||
# Site Node
|
||||
sc.exe create "ScadaLink-Site" binPath="C:\ScadaLink\ScadaLink.Host.exe" start=auto
|
||||
sc.exe description "ScadaLink-Site" "ScadaLink SCADA Site Agent"
|
||||
sc.exe create "ScadaBridge-Site" binPath="C:\ScadaBridge\ZB.MOM.WW.ScadaBridge.Host.exe" start=auto
|
||||
sc.exe description "ScadaBridge-Site" "ScadaBridge SCADA Site Agent"
|
||||
```
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
C:\ScadaLink\
|
||||
ScadaLink.Host.exe
|
||||
C:\ScadaBridge\
|
||||
ZB.MOM.WW.ScadaBridge.Host.exe
|
||||
appsettings.json
|
||||
appsettings.Production.json
|
||||
data\ # Site: SQLite databases
|
||||
site.db # Deployed configs, static overrides
|
||||
store-and-forward.db # S&F message buffer
|
||||
logs\ # Rolling log files
|
||||
scadalink-20260316.log
|
||||
scadabridge-20260316.log
|
||||
```
|
||||
|
||||
## Configuration Templates
|
||||
@@ -45,7 +45,7 @@ C:\ScadaLink\
|
||||
|
||||
```json
|
||||
{
|
||||
"ScadaLink": {
|
||||
"ScadaBridge": {
|
||||
"Node": {
|
||||
"Role": "Central",
|
||||
"NodeHostname": "central-01.example.com",
|
||||
@@ -53,13 +53,13 @@ C:\ScadaLink\
|
||||
},
|
||||
"Cluster": {
|
||||
"SeedNodes": [
|
||||
"akka.tcp://scadalink@central-01.example.com:8081",
|
||||
"akka.tcp://scadalink@central-02.example.com:8081"
|
||||
"akka.tcp://scadabridge@central-01.example.com:8081",
|
||||
"akka.tcp://scadabridge@central-02.example.com:8081"
|
||||
]
|
||||
},
|
||||
"Database": {
|
||||
"ConfigurationDb": "Server=sqlserver.example.com;Database=ScadaLink;User Id=scadalink_svc;Password=<CHANGE_ME>;Encrypt=true;TrustServerCertificate=false",
|
||||
"MachineDataDb": "Server=sqlserver.example.com;Database=ScadaLink_MachineData;User Id=scadalink_svc;Password=<CHANGE_ME>;Encrypt=true;TrustServerCertificate=false"
|
||||
"ConfigurationDb": "Server=sqlserver.example.com;Database=ScadaBridge;User Id=scadabridge_svc;Password=<CHANGE_ME>;Encrypt=true;TrustServerCertificate=false",
|
||||
"MachineDataDb": "Server=sqlserver.example.com;Database=ScadaBridge_MachineData;User Id=scadabridge_svc;Password=<CHANGE_ME>;Encrypt=true;TrustServerCertificate=false"
|
||||
},
|
||||
"Security": {
|
||||
"LdapServer": "ldap.example.com",
|
||||
@@ -95,7 +95,7 @@ C:\ScadaLink\
|
||||
|
||||
```json
|
||||
{
|
||||
"ScadaLink": {
|
||||
"ScadaBridge": {
|
||||
"Node": {
|
||||
"Role": "Site",
|
||||
"NodeHostname": "site-01-node-a.example.com",
|
||||
@@ -104,19 +104,19 @@ C:\ScadaLink\
|
||||
},
|
||||
"Cluster": {
|
||||
"SeedNodes": [
|
||||
"akka.tcp://scadalink@site-01-node-a.example.com:8081",
|
||||
"akka.tcp://scadalink@site-01-node-b.example.com:8081"
|
||||
"akka.tcp://scadabridge@site-01-node-a.example.com:8081",
|
||||
"akka.tcp://scadabridge@site-01-node-b.example.com:8081"
|
||||
]
|
||||
},
|
||||
"Database": {
|
||||
"SiteDbPath": "C:\\ScadaLink\\data\\site.db"
|
||||
"SiteDbPath": "C:\\ScadaBridge\\data\\site.db"
|
||||
},
|
||||
"DataConnection": {
|
||||
"ReconnectInterval": "00:00:05",
|
||||
"TagResolutionRetryInterval": "00:00:30"
|
||||
},
|
||||
"StoreAndForward": {
|
||||
"SqliteDbPath": "C:\\ScadaLink\\data\\store-and-forward.db",
|
||||
"SqliteDbPath": "C:\\ScadaBridge\\data\\store-and-forward.db",
|
||||
"DefaultRetryInterval": "00:00:30",
|
||||
"DefaultMaxRetries": 50,
|
||||
"ReplicationEnabled": true
|
||||
@@ -131,7 +131,7 @@ C:\ScadaLink\
|
||||
"PurgeIntervalHours": 24
|
||||
},
|
||||
"Communication": {
|
||||
"CentralSeedNode": "akka.tcp://scadalink@central-01.example.com:8081"
|
||||
"CentralSeedNode": "akka.tcp://scadabridge@central-01.example.com:8081"
|
||||
},
|
||||
"HealthMonitoring": {
|
||||
"ReportInterval": "00:00:30"
|
||||
@@ -149,26 +149,26 @@ C:\ScadaLink\
|
||||
|
||||
1. Create the configuration database:
|
||||
```sql
|
||||
CREATE DATABASE ScadaLink;
|
||||
CREATE LOGIN scadalink_svc WITH PASSWORD = '<STRONG_PASSWORD>';
|
||||
USE ScadaLink;
|
||||
CREATE USER scadalink_svc FOR LOGIN scadalink_svc;
|
||||
ALTER ROLE db_owner ADD MEMBER scadalink_svc;
|
||||
CREATE DATABASE ScadaBridge;
|
||||
CREATE LOGIN scadabridge_svc WITH PASSWORD = '<STRONG_PASSWORD>';
|
||||
USE ScadaBridge;
|
||||
CREATE USER scadabridge_svc FOR LOGIN scadabridge_svc;
|
||||
ALTER ROLE db_owner ADD MEMBER scadabridge_svc;
|
||||
```
|
||||
|
||||
2. Create the machine data database:
|
||||
```sql
|
||||
CREATE DATABASE ScadaLink_MachineData;
|
||||
USE ScadaLink_MachineData;
|
||||
CREATE USER scadalink_svc FOR LOGIN scadalink_svc;
|
||||
ALTER ROLE db_owner ADD MEMBER scadalink_svc;
|
||||
CREATE DATABASE ScadaBridge_MachineData;
|
||||
USE ScadaBridge_MachineData;
|
||||
CREATE USER scadabridge_svc FOR LOGIN scadabridge_svc;
|
||||
ALTER ROLE db_owner ADD MEMBER scadabridge_svc;
|
||||
```
|
||||
|
||||
3. Apply EF Core migrations (development):
|
||||
- Migrations auto-apply on startup in Development environment.
|
||||
|
||||
4. Apply EF Core migrations (production):
|
||||
- Generate SQL script: `dotnet ef migrations script --project src/ScadaLink.ConfigurationDatabase`
|
||||
- Generate SQL script: `dotnet ef migrations script --project src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase`
|
||||
- Review and execute the SQL script against the production database.
|
||||
|
||||
## Network Requirements
|
||||
@@ -189,7 +189,7 @@ Ensure bidirectional TCP connectivity between all Akka.NET cluster peers. The re
|
||||
|
||||
## Post-Installation Verification
|
||||
|
||||
1. Start the service: `sc.exe start ScadaLink-Central`
|
||||
2. Check the log file: `type C:\ScadaLink\logs\scadalink-*.log`
|
||||
1. Start the service: `sc.exe start ScadaBridge-Central`
|
||||
2. Check the log file: `type C:\ScadaBridge\logs\scadabridge-*.log`
|
||||
3. Verify the readiness endpoint: `curl http://localhost:5000/health/ready`
|
||||
4. For Central: verify the UI is accessible at `https://central-01.example.com/`
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
# ScadaLink Production Deployment Checklist
|
||||
# ScadaBridge Production Deployment Checklist
|
||||
|
||||
## Pre-Deployment
|
||||
|
||||
### Configuration Verification
|
||||
|
||||
- [ ] `ScadaLink:Node:Role` is set correctly (`Central` or `Site`)
|
||||
- [ ] `ScadaLink:Node:NodeHostname` matches the machine's resolvable hostname
|
||||
- [ ] `ScadaLink:Cluster:SeedNodes` contains exactly 2 entries for the cluster pair
|
||||
- [ ] `ScadaBridge:Node:Role` is set correctly (`Central` or `Site`)
|
||||
- [ ] `ScadaBridge:Node:NodeHostname` matches the machine's resolvable hostname
|
||||
- [ ] `ScadaBridge:Cluster:SeedNodes` contains exactly 2 entries for the cluster pair
|
||||
- [ ] Seed node addresses use fully qualified hostnames (not `localhost`)
|
||||
- [ ] Remoting port (default 8081) is open bidirectionally between cluster peers
|
||||
|
||||
### Central Node
|
||||
|
||||
- [ ] `ScadaLink:Database:ConfigurationDb` connection string is valid and tested
|
||||
- [ ] `ScadaLink:Database:MachineDataDb` connection string is valid and tested
|
||||
- [ ] `ScadaBridge:Database:ConfigurationDb` connection string is valid and tested
|
||||
- [ ] `ScadaBridge:Database:MachineDataDb` connection string is valid and tested
|
||||
- [ ] SQL Server login has `db_owner` role on both databases
|
||||
- [ ] EF Core migrations have been applied (SQL script reviewed and executed)
|
||||
- [ ] `ScadaLink:Security:JwtSigningKey` is at least 32 characters, randomly generated
|
||||
- [ ] `ScadaBridge:Security:JwtSigningKey` is at least 32 characters, randomly generated
|
||||
- [ ] **Both central nodes use the same JwtSigningKey** (required for JWT failover)
|
||||
- [ ] `ScadaLink:Security:LdapServer` points to the production LDAP/AD server
|
||||
- [ ] `ScadaLink:Security:LdapUseTls` is `true` (LDAPS required in production)
|
||||
- [ ] `ScadaLink:Security:AllowInsecureLdap` is `false`
|
||||
- [ ] `ScadaBridge:Security:LdapServer` points to the production LDAP/AD server
|
||||
- [ ] `ScadaBridge:Security:LdapUseTls` is `true` (LDAPS required in production)
|
||||
- [ ] `ScadaBridge:Security:AllowInsecureLdap` is `false`
|
||||
- [ ] LDAP search base DN is correct for the organization
|
||||
- [ ] LDAP group-to-role mappings are configured
|
||||
- [ ] Load balancer is configured in front of central UI (sticky sessions not required)
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
### Site Node
|
||||
|
||||
- [ ] `ScadaLink:Node:SiteId` is set and unique across all sites
|
||||
- [ ] `ScadaLink:Database:SiteDbPath` points to a writable directory
|
||||
- [ ] `ScadaBridge:Node:SiteId` is set and unique across all sites
|
||||
- [ ] `ScadaBridge:Database:SiteDbPath` points to a writable directory
|
||||
- [ ] SQLite data directory has sufficient disk space (no max buffer size for S&F)
|
||||
- [ ] `ScadaLink:Communication:CentralSeedNode` points to a reachable central node
|
||||
- [ ] `ScadaBridge:Communication:CentralSeedNode` points to a reachable central node
|
||||
- [ ] OPC UA server endpoints are accessible from site nodes
|
||||
- [ ] OPC UA security certificates are configured if required
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ScadaLink Cluster Topology Guide
|
||||
# ScadaBridge Cluster Topology Guide
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
ScadaLink uses a hub-and-spoke architecture:
|
||||
ScadaBridge uses a hub-and-spoke architecture:
|
||||
- **Central Cluster**: Two-node active/standby Akka.NET cluster for management, UI, and coordination.
|
||||
- **Site Clusters**: Two-node active/standby Akka.NET clusters at each remote site for data collection and local processing.
|
||||
|
||||
@@ -34,7 +34,7 @@ Both central nodes must be configured as seed nodes for each other:
|
||||
**Node A** (`central-01.example.com`):
|
||||
```json
|
||||
{
|
||||
"ScadaLink": {
|
||||
"ScadaBridge": {
|
||||
"Node": {
|
||||
"Role": "Central",
|
||||
"NodeHostname": "central-01.example.com",
|
||||
@@ -42,8 +42,8 @@ Both central nodes must be configured as seed nodes for each other:
|
||||
},
|
||||
"Cluster": {
|
||||
"SeedNodes": [
|
||||
"akka.tcp://scadalink@central-01.example.com:8081",
|
||||
"akka.tcp://scadalink@central-02.example.com:8081"
|
||||
"akka.tcp://scadabridge@central-01.example.com:8081",
|
||||
"akka.tcp://scadabridge@central-02.example.com:8081"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ Both central nodes must be configured as seed nodes for each other:
|
||||
**Node B** (`central-02.example.com`):
|
||||
```json
|
||||
{
|
||||
"ScadaLink": {
|
||||
"ScadaBridge": {
|
||||
"Node": {
|
||||
"Role": "Central",
|
||||
"NodeHostname": "central-02.example.com",
|
||||
@@ -61,8 +61,8 @@ Both central nodes must be configured as seed nodes for each other:
|
||||
},
|
||||
"Cluster": {
|
||||
"SeedNodes": [
|
||||
"akka.tcp://scadalink@central-01.example.com:8081",
|
||||
"akka.tcp://scadalink@central-02.example.com:8081"
|
||||
"akka.tcp://scadabridge@central-01.example.com:8081",
|
||||
"akka.tcp://scadabridge@central-02.example.com:8081"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ Each site has its own two-node cluster:
|
||||
**Site Node A** (`site-01-a.example.com`):
|
||||
```json
|
||||
{
|
||||
"ScadaLink": {
|
||||
"ScadaBridge": {
|
||||
"Node": {
|
||||
"Role": "Site",
|
||||
"NodeHostname": "site-01-a.example.com",
|
||||
@@ -110,8 +110,8 @@ Each site has its own two-node cluster:
|
||||
},
|
||||
"Cluster": {
|
||||
"SeedNodes": [
|
||||
"akka.tcp://scadalink@site-01-a.example.com:8081",
|
||||
"akka.tcp://scadalink@site-01-b.example.com:8081"
|
||||
"akka.tcp://scadabridge@site-01-a.example.com:8081",
|
||||
"akka.tcp://scadabridge@site-01-b.example.com:8081"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user