-
Notifications
You must be signed in to change notification settings - Fork 6
plugin sdk server management
Plugins run as roles that can be assigned to multiple servers for high availability and failover.
Plugin Role
↓
Assigned to Server A (Priority 1)
Assigned to Server B (Priority 2)
Assigned to Server C (Priority 3)
↓
Runs on highest priority available server
↓
Fails over to next server if current fails
Key concepts:
- Plugins are roles that can run on multiple servers
- Priority determines which server runs the plugin
- Automatic failover to next priority server on failure
- Manual server selection supported
- Server rejection allows plugins to control where they run
Servers are assigned to plugin roles in Config Tool:
Path: System > Roles > [Plugin Role] > Properties > Servers
Administrators can:
- Add/remove servers
- Set server priorities
- Enable/disable automatic failover
- Manually select running server
Servers have priority levels (1 = highest):
Priority 1: Primary server (preferred)
Priority 2: Secondary server (backup)
Priority 3: Tertiary server (last resort)
Automatic failover behavior:
- Plugin runs on highest priority available server
- If that server fails, plugin fails over to next priority
- When higher priority server recovers, plugin can failover back (if enabled)
Automatically switches to highest priority server when available:
protected override void OnPluginLoaded()
{
// Enable automatic priority-based failover
SetForceExecutionByPriority(true);
}When enabled:
- Plugin always runs on highest priority available server
- Automatically fails back to higher priority servers when they recover
- Good for active-passive failover scenarios
When disabled:
- Plugin stays on current server until failure
- Manual intervention required to switch servers
- Good for active-active scenarios
Administrator manually controls which server runs the plugin:
// Get current server
Guid currentServer = GetCurrentServer();
// Manually switch to different server
SetCurrentServer(targetServerGuid);Use cases:
- Maintenance operations
- Load balancing
- Testing
- Troubleshooting
Available through Plugin base class:
Returns GUID of server currently running the plugin:
protected override void OnPluginLoaded()
{
Guid serverGuid = GetCurrentServer();
var server = Engine.GetEntity<Server>(serverGuid);
Logger.TraceInformation($"Plugin running on server: {server.Name}");
}Returns:
- Server GUID
Returns information about all assigned servers:
protected override void OnPluginLoaded()
{
Dictionary<Guid, ServerInfos> servers = GetServersInfo();
foreach (var kvp in servers)
{
Guid serverGuid = kvp.Key;
ServerInfos info = kvp.Value;
Logger.TraceInformation($"Server: {serverGuid}, Order: {info.Order}");
}
}ServerInfos properties:
-
Order- Server priority order (lower numbers = higher priority) -
NetworkBinding- Network binding configuration for the server
Programmatically add a server to the role:
private void AddBackupServer(Guid serverGuid)
{
AddServer(serverGuid);
Logger.TraceInformation($"Added server {serverGuid} to plugin role");
}Considerations:
- Server must exist in system
- Duplicate adds are ignored
- Priority assigned automatically (lowest available)
- Config Tool reflects change immediately
Remove a server from the role:
private void RemoveServer(Guid serverGuid)
{
RemoveRoleServer(serverGuid);
Logger.TraceInformation($"Removed server {serverGuid} from plugin role");
}Considerations:
- Cannot remove server if plugin is currently running on it
- Must switch to different server first
- Config Tool reflects change immediately
Manually switch to specific server:
private void FailoverToBackup(Guid backupServerGuid)
{
Logger.TraceInformation($"Failing over to backup server {backupServerGuid}");
SetCurrentServer(backupServerGuid);
}Behavior:
- Stops plugin on current server
- Starts plugin on target server
- May cause brief service interruption
- Target server must be in role's server list
Important
SetCurrentServer throws if ForceExecutionByPriority is enabled. Disable it first with SetForceExecutionByPriority(false) before manually switching servers.
Control automatic priority-based failover:
protected override void OnPluginLoaded()
{
// Enable automatic failover to highest priority server
SetForceExecutionByPriority(true);
}Effect:
-
true- Auto-failover to highest priority available server -
false- Stay on current server until failure
Returns the X509 certificate used by the server hosting the plugin:
protected override void OnPluginLoaded()
{
X509Certificate2 cert = GetServerCertificate();
if (cert != null)
{
Logger.TraceInformation($"Server certificate subject: {cert.Subject}");
Logger.TraceInformation($"Certificate expires: {cert.NotAfter}");
}
}Returns:
-
X509Certificate2- A clone of the server's certificate -
null- If no certificate is available
Usage notes:
- Returns a cloned certificate to prevent disposal of the original
- Use for validating server identity or establishing secure connections
- The certificate belongs to the Security Center server hosting the plugin
Returns network cards available on each server assigned to the role:
protected override void OnPluginLoaded()
{
Dictionary<Guid, List<NetworkCard>> networkCards = GetAvailableNetworkCards();
foreach (var kvp in networkCards)
{
Guid serverGuid = kvp.Key;
List<NetworkCard> cards = kvp.Value;
var server = Engine.GetEntity<Server>(serverGuid);
Logger.TraceInformation($"Server {server.Name} has {cards.Count} network cards:");
foreach (var card in cards)
{
Logger.TraceInformation($" MAC: {card.MacAddress}, IP: {card.IpAddress}");
}
}
}Returns:
-
Dictionary<Guid, List<NetworkCard>>- Server GUID mapped to list of network cards -
null- If the role entity cannot be found
NetworkCard properties:
-
MacAddress- The MAC address of the network card (or "Any" for default binding) -
IpAddress- The IPv4 address of the network card
Usage notes:
- Always includes an "Any" option with empty IP address for default network binding
- Use to allow administrators to select specific network interfaces
- Useful for plugins that need to bind to specific network adapters
Sets the network card binding for a specific server:
private void ConfigureNetworkBinding(Guid serverGuid, NetworkCard selectedCard)
{
bool success = SetNetworkCard(serverGuid, selectedCard);
if (success)
{
Logger.TraceInformation($"Network card set to {selectedCard.MacAddress}");
}
else
{
Logger.TraceError("Failed to set network card");
}
}Parameters:
-
serverId- The GUID of the server to configure -
networkCard- The network card to bind to
Returns:
-
true- Network card was set successfully -
false- Role entity not found
Usage notes:
- Setting MAC address to "Any" clears the network binding (uses default)
- Changes are persisted to the role configuration
- The server must be in the role's server list
- Use with
GetAvailableNetworkCards()to present valid options
Plugins can reject servers that don't meet requirements:
Reject current server and trigger failover:
protected override void OnPluginLoaded()
{
if (!ValidateServerRequirements())
{
Guid currentServer = GetCurrentServer();
RejectServer(currentServer, "Required hardware not available");
Logger.TraceWarning($"Rejected server {currentServer}");
return; // Don't continue initialization
}
// Server meets requirements
AcceptServer(GetCurrentServer());
}When rejected:
- Plugin stops on rejected server
- Security Center attempts to start plugin on next priority server
- Rejection reason logged and visible in Config Tool
- Server remains in role's server list but marked as rejected
Explicitly accept current server:
protected override void OnPluginLoaded()
{
if (ValidateServerRequirements())
{
AcceptServer(GetCurrentServer());
Logger.TraceInformation("Server accepted");
}
}When to use:
- After validating server requirements
- Confirms plugin can run on this server
- Good practice for explicit acceptance
Hardware requirements:
private bool ValidateServerRequirements()
{
// Check for required hardware
if (!IsSerialPortAvailable())
{
Logger.TraceError("Serial port not available");
return false;
}
// Check for required network access
if (!CanReachExternalSystem())
{
Logger.TraceError("Cannot reach external system");
return false;
}
return true;
}Resource requirements:
private bool ValidateServerRequirements()
{
// Check available memory
var availableMemory = GetAvailableMemory();
if (availableMemory < RequiredMemoryMB)
{
Logger.TraceError($"Insufficient memory: {availableMemory}MB < {RequiredMemoryMB}MB");
return false;
}
// Check disk space
var availableDisk = GetAvailableDiskSpace();
if (availableDisk < RequiredDiskSpaceGB)
{
Logger.TraceError($"Insufficient disk space");
return false;
}
return true;
}Software requirements:
private bool ValidateServerRequirements()
{
// Check for required assemblies
if (!IsAssemblyAvailable("ThirdParty.Hardware.dll"))
{
Logger.TraceError("Required assembly not found");
return false;
}
// Check for required services
if (!IsServiceRunning("RequiredService"))
{
Logger.TraceError("Required Windows service not running");
return false;
}
return true;
}Plugin running on Server A
↓
Server A fails or priority changes
↓
1. Dispose() called on Server A
↓
2. Plugin stops on Server A
↓
3. Constructor called on Server B
↓
4. Initialize() called on Server B
↓
5. OnPluginLoaded() called on Server B
↓
6. OnPluginStart() called on Server B
↓
Plugin running on Server B
Important
- Complete lifecycle executes on each server
- No state automatically transferred between servers
- Must persist state externally (database, file share)
- Each instance is independent
Use database:
public class MyPlugin : Plugin, IPluginDatabaseSupport
{
protected override void OnPluginStart()
{
// Load state from database
LoadStateFromDatabase();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Save state to database
SaveStateToDatabase();
}
}
}Use configuration:
protected override void OnPluginLoaded()
{
// Load state from configuration
var config = LoadConfiguration();
RestoreState(config.SavedState);
}
private void OnStateChanged()
{
// Persist state to configuration
var config = LoadConfiguration();
config.SavedState = CaptureState();
UpdateConfiguration(config);
}For plugins that don't require failover (stateless operations):
protected override void OnPluginLoaded()
{
// Disable automatic failover
SetForceExecutionByPriority(false);
// Each instance processes independently
StartProcessingQueue();
}Use cases:
- Stateless query processing
- Parallel data processing
- Distributed workloads
protected override void OnPluginLoaded()
{
Guid currentServer = GetCurrentServer();
var server = Engine.GetEntity<Server>(currentServer);
// Configure based on server name (use a naming convention that encodes location)
if (server.Name.Contains("Europe"))
{
ConfigureForEuropeRegion();
}
else if (server.Name.Contains("Asia"))
{
ConfigureForAsiaRegion();
}
}- Plugin SDK overview: Plugin architecture, lifecycle, and components.
- Plugin SDK lifecycle: Plugin initialization, startup, and disposal phases.
-
Plugin SDK database: SQL Server integration through
IPluginDatabaseSupport. - Plugin SDK state management: Reporting plugin and entity health to Config Tool.
- Overview
- Connecting to Security Center
- SDK certificates
- Referencing SDK assemblies
- SDK compatibility
- Entities
- Entity cache
- Transactions
- Events
- Actions
- Security Desk
- Custom events
- ReportManager
- ReportManager query reference
- DownloadAllRelatedData and StrictResults
- Privileges
- Partitions
- Mobile credentials
- Logging
- Overview
- Certificates
- Lifecycle
- Threading
- State management
- Configuration
- Restricted configuration
- Events
- Queries
- Request manager
- Database
- Entity ownership
- Entity mappings
- Server management
- Custom privileges
- Custom entity types
- Resolving non-SDK assemblies
- Deploying plugins
- .NET 8 support
- Overview
- Certificates
- Creating modules
- Tasks
- Pages
- Components
- Tile extensions
- Services
- Contextual actions
- Options extensions
- Configuration pages
- Monitors
- Shared components
- Commands
- Extending events
- Map extensions
- Timeline providers
- Image extractors
- Credential encoders
- Credential readers
- Cardholder fields extractors
- Badge printers
- Content builders
- Dashboard widgets
- Incidents
- Logon providers
- Pinnable content builders
- Custom report pages
- Overview
- Getting started
- MediaPlayer
- VideoSourceFilter
- MediaExporter
- MediaFile
- G64 converters
- FileCryptingManager
- PlaybackSequenceQuerier
- PlaybackStreamReader
- OverlayFactory
- PtzCoordinatesManager
- AudioTransmitter
- AudioRecorder
- AnalogMonitorController
- Camera blocking
- Overview
- Getting started
- Referencing entities
- Entity operations
- About access control in the Web SDK
- About video in the Web SDK
- Users and user groups
- Partitions
- Custom fields
- Custom card formats
- Actions
- Events and alarms
- Incidents
- Reports
- Tasks
- Macros
- Custom entity types
- System endpoints
- Performance guide
- Reference
- Under the hood
- Troubleshooting