Balancer Plugins

Overview

Balancer plugins can be created to customize the algorithm logic for the Balancer application. Balancer plugins are written in Python, which means that they can easily be created and customized. You can also refer to the default plugin in the Repository’s Balancer folder for a full example of how it works. See the Scripting Overview documentation for more information, and links to the Deadline Scripting reference.

Creating a Balancer Plugin

To create a custom Balancer plugin, you start by creating a folder in the Repository’s custom\balancer folder and give it the name of your Balancer plugin. See the Scripting Overview documentation for more information on the ‘custom’ folder in the Repository and how it’s used.

For the sake of this document, we will call our new Balancer plugin MyBalancerAlgorithm. All relative script and configuration files for this Balancer plugin are to be placed in this folder.

.py File

Required

The first required file is MyBalancerAlgorithm.py, which is the main Balancer plugin script. It defines the BalancerPluginWrapper class that contains all the necessary callbacks that will be used during a Balancer cycle. The template for this script file might look like this:

from Deadline.Balancer import *

###########################################################################
## This is the function that Deadline calls to get an instance of the
## main BalancerPluginWrapper class.
###########################################################################
def GetBalancerPluginWrapper():
    return MyBalancerPlugin()

###########################################################################
## This is the main DeadlineBalancerListener class for MyBalancerAlgorithm.
###########################################################################
class MyBalancerAlgorithm (BalancerPluginWrapper):
    def __init__( self ):
        self.BalancerAlgorithmCallback += self.BalancerAlgorithm

    def BalancerAlgorithm(self, stateStruct):
        #TODO: Return a target struct to the Balancer.
        pass

    def Cleanup(self):
        del self.BalancerAlgorithmCallback

The GetBalancerPluginWrapper() function is important, as it allows Deadline to get an instance of our MyBalancerAlgorithm class (which is extending the abstract BalancerPluginWrapper class). If this function isn’t defined, Deadline will report an error when it tries to load the Balancer plugin. Notice that we’re importing the Deadline.Balancer namespace so that we can access the BalancerPluginWrapper class.

The MyBalancerAlgorithm class will need to implement the BalancerAlgorithm callback so that Deadline can know how to balance your farm, and these callbacks must be hooked up in the MyBalancerAlgorithm constructor.

Here’s what a BalancerTargetStruct looks like:

/// <summary>
/// The BalancerTargetStruct indicates the ideal number of VM instances that should
/// be running in each enabled Group of each CloudRegion.  The BalancerTargetStruct
/// is populated by a Balancer Logic Plug-in.
/// </summary>
public class BalancerTargetStruct
{
    public BalancerTargetStruct() { }

    // Logic plugin can set this to true to indicate that an error occurred.
    public bool ErrorEncountered;

    // Logic plugin can convey an error message here
    // (ErrorEncountered should be set to true).
    public string ErrorMessage;

    // Logic plugin can convey a non-error message here.
    public string Message;

    // An array of cloud region targets.
    public CloudRegionTargetStruct[] CloudRegionTargets;

    // The time the structure was filled.
    public DateTime Time;
}

public class CloudRegionTargetStruct
{
    public CloudRegionTargetStruct() { }

    // The unique ID of the region.
    public string RegionID;

    // An array of Group targets
    public GroupTargetStruct[] GroupTargets;
}

public class GroupTargetStruct
{
    public GroupTargetStruct() { }

    public GroupTargetStruct(string Name, int Count)
    {
        this.Name = Name;
        this.Count = Count;
    }

    // The name of the group.
    public string Name;

    // The target number of VM instances for the group.
    public int Count;
}

.param File

Required

The MyBalancerAlgorithm.param file is a required file that is used in the Balancer Settings panel of the Repository Options dialog in the Monitor. It declares properties that the Monitor uses to generate a user interface for modifying settings for this algorithm, which are then stored in the database. After you’ve created this file, open the Monitor and enter Super User mode. Then select Tools -> Repository Options -> Balancer Settings and click the dropdown to MyBalancerAlgorithm to see your settings.

Each control is identified in the MyBalancerAlgorithm.param file by a unique name between square brackets, and a set of key=value pairs that determine its default value and how it appears in Deadline’s user interface. For example, a typical Balancer plugin might control whether logging is verbose and how conservative or aggressive pre-job tasks are evaluated.

[Verbose]
Type=boolean
Category=Options
CategoryOrder=0
Index=0
Label=Verbose Logging
Default=true
Description=Whether or not Verbose logging is enabled.

[PreJobTaskMode]
Type=enum
Values=Conservative;Ignore;Normal;
Category=Options
CategoryOrder=0
Index=1
Label=Pre Job Task Mode
Default=Conservative
Description=How the Balancer handles Pre Job Tasks.

For possible user interface types, please see the .param section of Application Plugins.

Note that in previous versions of Deadline, Balancer Plugin settings were stored in *.dlinit files, which have been removed as of Deadline 8.0. All data that was previously stored in the *.dlinit file is now stored in the database. In order to declare custom settings for a plugin you must do so in the *.param file.

Optional

IsServerData=True

When an item is marked as server data, it is stored differently than other data. The purpose of this is to reduce data transfer in cases where a lot of data needs to be stored as configuration data, but needs to be accessed less frequently than the rest of the config. In this case the data can be retrieved as follows: 1) Call var myServerData = RepositoryUtils.GetServerData("balancer.plugin.mypluginname") 2) Call myServerData["sectionname"]