In DPM, Jobs are objects that encapsulate the notion of a (typically) long running operation. Unfortunately though DPM v2 does not have cmdlets to directly monitor jobs, still a large number of cmdlets output jobs and it is useful to be able to interact with them.

 

The most commonly desired interaction is to be able to track the progress of a triggered job. If you see the anatomy of a Job object, it has properties that can be monitored to view the status of a job.

 

Let's start a relatively short running job and analyze the object.

>$j = Start-DPMLibraryRescan mydpmserver

>$j | gm -MemberType property

 

The ones we are interested in are 'HasCompleted' which is a boolean and 'Status' which is an enum. As the name says 'HasCompleted' tells whether the job has run to completion or not whereas the current state of a job is given by the 'Status' property.

 

The possible values of Status are -

·         Scheduled - the job is scheduled to run but is not currently running, either because it is set to run at a later time or is waiting for availability of required resources.

·         InProgress - The job is currently running.

·         Cancelling - The job is being cancelled either because the user manually cancelled the execution or DPM decided so. NOTE: You can manually cancel a running job by calling the Cancel() method on it.

·         Failed - The job has completed and was unsuccessful due to some error (or cancellation).

·         Warning - The job has completed and one or more (but not all) sub-operations in the job failed.

·         Succeeded - The job has completed successfully.

 

'HasCompleted' will be true when the Status is either 'Failed', 'Warning' or 'Succeeded'. So, typically the pattern to track the progress of a job is -

 

### Begin code

$job = <Some DPM cmdlet that returns a job>

while (!$job.HasCompleted)

{

    Write-Host "Job status: $($job.Status)"

    sleep 5

}

 

Write-Host "Job has completed. Final status: $($job.Status)"

### End code

 

There are 2 variations of monitoring when multiple jobs are triggered through a script. Either the jobs are to be run sequentially or they need to be all triggered without waiting for the others to finish and then all of them need to be tracked together.

 

The first intent is easy to achieve using the above mentioned steps. Trigger jobs in a loop and have the while loop inside to monitor the triggered job. Then a new job will not be triggered until the previous finishes. For the second one, triggering several jobs in parallel is easy, keep calling cmdlet(s) that trigger jobs without waiting for the completion of others. For tracking all of the triggered jobs, you can use the following -

 

It is easier to explain using a real example, so consider the problem of running consistency check on all datasources that are being actively protected.

 

### begin code

$jobList = @() # Create an empty array to store information about all the triggered jobs.

foreach ($datasource in @(Get-Datasource -DPMServerName $DPMServerName | ? {$_.Protected -and $_.State -eq "Invalid"}))  # Find all the actively protected datasources which are not valid.

{

    # Create a hash table that has a key named Job which contains the triggered consistency check job and a key named Datasource which contains the name of the datasource on which the consistency check job is triggered. Then add this hash table as an element of the array.

    $jobList += @{Job = Start-DatasourceConsistencyCheck -Datasource $datasource; Datasource = $($datasource.LogicalPath)}

}

 

At this point we have an array of hashtables with each hash table having the triggered job and the name of the datasource.

 

Now we can track all the jobs and print out useful progress messages (this is the reason we stored useful information (name of the datasource) about the job). The following block prints the progress of all the jobs every 5 seconds and stops when all the jobs have run to completion.

 

$completedJobsCount = 0

while ($completedJobsCount -ne $jobList.Length)

{

    $completedJobsCount = 0

    Write-Host ""

 

    foreach ($jobHT in $jobList)

    {

        if ($jobHT.Job.HasCompleted)

        {

            Write-Host "Consistency check on $($jobHT.Datasource) completed. Status: $(($jobHT.Job).Status)"

            $completedJobsCount += 1

        }

        else

        {

            Write-Host "Runnning consistency check on $($jobHT.Datasource)..."

        }

    }

 

    sleep 5

}

 

- Mohit Chakraborty