Hello Monitor - An Introduction to Monitor Scripting

Version: Deadline 7.2, 8.0

Overview - Personalized Control

Deadline ships with a number of useful scripts for the Deadline Monitor that allow users to take advantage of various aspects of Deadline. In addition, users can customize these scripts or write their own to add additional functionality.

Through this blog we will go through the creation process of the PriorityOffset.py Job script that is currently being shipped with Deadline. This script is able to modify the priority of multiple jobs by an offset even if the original jobs have different priorities. We chose to highlight this script because it does something you couldn’t do from the Deadline Monitor otherwise.

By using this script as an example, we hope it encourages you to jump in and write some scripts of your own!

Types of Scripts

The Deadline Monitor supports many types of scripts which can be run in the context of specific Jobs, Tasks, Slaves, Limits, Reports, etc. General scripts or Submission scripts are also supported. For this blog, we wish to modify the priority of Jobs, so we will be creating a Job script.

Initial Setup

Before we start working on our script, we first want to be able to see any log or error messages that our script might produce. To do this, we create a new instance of the Console panel by selecting View -> New Panel -> Console.

We also need to create the new script and place it in the Deadline Repository. Navigate to [Repository]/custom/scripts/Jobs and create an empty file called PriorityOffset.py (this will be the file that we will be modifying for the purposes of this blog).

The reason we are placing it in the custom folder is so that we don’t have modify the one that ships with Deadline. This ensures that your script will not be overwritten when you update Deadline in the future. See the Scripting Overview documentation for more information about the custom folder.

Writing the Script

Open the PriorityOffset.py file that you added to your Deadline Repository, and start by defining the main function and set up an import that almost all scripts will use.

from Deadline.Scripting import *

def __main__( *args ):
    pass

Once we have this the next thing we want to do is build up the UI (User Interface) that this script is going to use. In order to do this, we will use the DeadlineScriptDialog class to add 2 Range controls with buttons and labels and an additional close button.

We will add these controls to a grid layout, which will organize their layout for us.

#Imports
from Deadline.Scripting import *
from DeadlineUI.Controls.Scripting.DeadlineScriptDialog import DeadlineScriptDialog

#a global variable to hold the UI.
scriptDialog = None

def __main__():
    global scriptDialog
    #define the max value that the Range controls can go to.
    maximumPriority = RepositoryUtils.GetMaximumPriority()
    
    scriptDialog = DeadlineScriptDialog()
    scriptDialog.SetSize( 350, 100 )
    scriptDialog.AllowResizingDialog( True )
    scriptDialog.SetTitle( "Set/Offset Priority of Selected Jobs" )
    
    scriptDialog.AddGrid()
    scriptDialog.AddControlToGrid( "AbsLabel", "LabelControl", "Absolute Priority:", 0, 0 , "The absolute priority.", False )
    scriptDialog.AddRangeControlToGrid( "AbsBox", "RangeControl", 0, 0, maximumPriority, 0, 1, 0, 1 )
    absButton = scriptDialog.AddControlToGrid( "AbsButton", "ButtonControl", "Apply", 0, 2, expand=False )
    
    scriptDialog.AddControlToGrid( "OffsetLabel", "LabelControl", "Priority Offset:", 1, 0 , "The priority offset.", False )
    scriptDialog.AddRangeControlToGrid( "OffsetBox", "RangeControl", 0, -maximumPriority, maximumPriority, 0, 1, 1, 1 )
    offsetButton = scriptDialog.AddControlToGrid( "OffsetButton", "ButtonControl", "Apply", 1, 2, expand=False )
    
    closeButton = scriptDialog.AddControlToGrid( "CloseButton", "ButtonControl", "Close", 2, 2, expand=False )
    scriptDialog.EndGrid()
    
    scriptDialog.ShowDialog( False )

We are able to see how the UI will look now by running the script. To run the script, select one or more jobs in the Deadline Monitor, then right click and select Scripts -> Priority Offset. If all goes as planned you will see the following UI.

If you start clicking on buttons though, you’ll notice that nothing happens. This is because the controls aren’t configured to do anything yet.

First, we will create a function to handle the setting of absolute priority. To do this, we first need to get the selected jobs, which can be done using MonitorUtils.GetSelectedJobs(). We then need to go through each of the jobs and modify their priority. Note that we also have to save the job using RepositoryUtils.SaveJob(), so that our changes will take effect.

def AbsButtonPressed( *args ):
    global scriptDialog
    
    jobs = MonitorUtils.GetSelectedJobs()
    priority = int( scriptDialog.GetValue( "AbsBox" ) )
    
    for job in jobs:
        job.JobPriority = priority
        print "Changed Priority of Job "+job.JobId+" to " +str(priority)
        RepositoryUtils.SaveJob(job)

We will then need to connect this function to the first apply button. This can be achieved by adding the following code to where we created the button.

absButton.ValueModified.connect(AbsButtonPressed)

Once we have tested this and have it working to our liking, we can then do the same for the offset button. The main difference for this one being that we are adding the new priority to the original priority, and we then have to make sure that the new priority is within the allowed range.

def OffsetButtonPressed( *args ):
    global scriptDialog
    
    jobs = MonitorUtils.GetSelectedJobs()
    maximumPriority = RepositoryUtils.GetMaximumPriority()
    offset = int( scriptDialog.GetValue( "OffsetBox" ) )
    
    for job in jobs:
        priority = job.JobPriority + offset
        if priority > maximumPriority:
            priority = maximumPriority
        elif priority < 0:
            priority = 0
        
        job.JobPriority = priority
        print "Changed Priority of Job "+job.JobId+" to " +str(priority)
        RepositoryUtils.SaveJob(job)

After this we have to just have to connect the final exit button, which will bring us to this final script.

from System.IO import *
from Deadline.Scripting import *

from DeadlineUI.Controls.Scripting.DeadlineScriptDialog import DeadlineScriptDialog

scriptDialog = None

def __main__():
    global scriptDialog
    #define the max value that the Range controls can go to.
    maximumPriority = RepositoryUtils.GetMaximumPriority()
    
    scriptDialog = DeadlineScriptDialog()
    scriptDialog.SetSize( 350, 100 )
    scriptDialog.AllowResizingDialog( True )
    scriptDialog.SetTitle( "Set/Offset Priority of Selected Jobs" )
    
    scriptDialog.AddGrid()
    scriptDialog.AddControlToGrid( "AbsLabel", "LabelControl", "Absolute Priority:", 0, 0 , "The absolute priority.", False )
    scriptDialog.AddRangeControlToGrid( "AbsBox", "RangeControl", 0, 0, maximumPriority, 0, 1, 0, 1 )
    absButton = scriptDialog.AddControlToGrid( "AbsButton", "ButtonControl", "Apply", 0, 2, expand=False )
    
    scriptDialog.AddControlToGrid( "OffsetLabel", "LabelControl", "Priority Offset:", 1, 0 , "The priority offset.", False )
    scriptDialog.AddRangeControlToGrid( "OffsetBox", "RangeControl", 0, -maximumPriority, maximumPriority, 0, 1, 1, 1 )
    offsetButton = scriptDialog.AddControlToGrid( "OffsetButton", "ButtonControl", "Apply", 1, 2, expand=False )
    
    closeButton = scriptDialog.AddControlToGrid( "CloseButton", "ButtonControl", "Close", 2, 2, expand=False )
    scriptDialog.EndGrid()
    
    scriptDialog.ShowDialog( False )

def OffsetButtonPressed( *args ):
    global scriptDialog
    
    jobs = MonitorUtils.GetSelectedJobs()
    maximumPriority = RepositoryUtils.GetMaximumPriority()
    offset = int( scriptDialog.GetValue( "OffsetBox" ) )
    
    for job in jobs:
        priority = job.JobPriority + offset
        if priority > maximumPriority:
            priority = maximumPriority
        elif priority < 0:
            priority = 0
    
        job.JobPriority = priority
        print "Changed Priority of Job "+job.JobId+" to " +str(priority)
        RepositoryUtils.SaveJob(job)

def AbsButtonPressed( *args ):
    global scriptDialog
    
    jobs = MonitorUtils.GetSelectedJobs()
    priority = int( scriptDialog.GetValue( "AbsBox" ) )
    
    for job in jobs:
        job.JobPriority = priority
        print "Changed Priority of Job "+job.JobId+" to " +str(priority)
        RepositoryUtils.SaveJob(job)

def CloseButtonPressed( *args ):
    global scriptDialog
    scriptDialog.CloseDialog()

Once again we are able to run this script from the monitor and we are now able to modify a job and see the results in the console that we opened earlier.

Additional Information

In addition to the information found here, the Deadline User Manual contains useful information on each of the different types of scripts Deadline can run and what is needed for each, and the Deadline Scripting Reference contains documentation for all of the available classes and functions that are exposed to scripts.

There is also an ever growing Github project that contains multiple useful scripts that are not shipped with Deadline.