Skip to content

plugin sdk server management

Andre Lafleur edited this page May 10, 2026 · 8 revisions

About plugin server management

Plugins run as roles that can be assigned to multiple servers for high availability and failover.

Server assignment model

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

Server Assignment

Adding Servers

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

Server Priority

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)

High availability strategies

Force execution by priority

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

Manual server selection

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

Server management methods

Available through Plugin base class:

GetCurrentServer()

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

GetServersInfo()

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

AddServer()

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

RemoveRoleServer()

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

SetCurrentServer()

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.

SetForceExecutionByPriority()

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

GetServerCertificate()

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

GetAvailableNetworkCards()

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

SetNetworkCard()

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

Server Rejection

Plugins can reject servers that don't meet requirements:

RejectServer()

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

AcceptServer()

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

Server requirements validation

Common validation scenarios

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;
}

Server lifecycle events

Plugin moving between servers

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

Persisting state across failover

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);
}

Load Balancing

For plugins that don't require failover (stateless operations):

Active-Active Pattern

protected override void OnPluginLoaded()
{
    // Disable automatic failover
    SetForceExecutionByPriority(false);
    
    // Each instance processes independently
    StartProcessingQueue();
}

Use cases:

  • Stateless query processing
  • Parallel data processing
  • Distributed workloads

Geographic Distribution

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();
    }
}

See also

Platform SDK

Plugin SDK

Workspace SDK

Media SDK

Macro SDK

Web SDK

Media Gateway

Genetec Web Player

Clone this wiki locally