Share:|

This is a pretty easy one so I thought I'd do a little more with scripting to make it more fun.  I have a Batch Job and I want to get all the member job keys/names/paths/etc.  I don't see any released blcli commands that will do it so I'll look in the ...Unreleased blcli commands and documentation ...  Digging around in the BatchJob namespace (of course) I don't see any list* or get* commands that would do it, though the getMemberJobCountByJobKey looks interesting for later.  I did find a findAllSubJobHeadersByBatchJobKey which looks promising.  I know about headers from past posts in this series.    That gives me something like this:

BATCH_JOB="/Workspace/BatchJobs/MyBatchJob"
blcli_execute BatchJob getDBKeyByGroupAndName "${BATCH_JOB%/*}" "${BATCH_JOB##*/}"
blcli_storeenv batchJobKey
blcli_execute BatchJob findAllSubJobHeadersByBatchJobKey ${batchJobKey}
blcli_execute SJobHeader getDBKey
blcli_execute Utility setTargetObject
blcli_execute Utility listPrint
blcli_storelocal memberJobKeys

Easy-peasy.  What if one of those members is a Batch Job and I want the member jobs in there ? I can probably script together something like that, but first I should create a test batch job to work this out.  I want something like:

Batch Job1

    -> Member Job1a

    -> Member Job1b

    -> Member Job Batch2

                 -> Member Job2a

                 -> Member Job2b

     -> Member Job1c

I could just see what jobs I already have in my test environment and use the gui to create the above but that's no fun.  Why not script out the creation and then script reading it all back ?  Then I'll have a couple scripts I can take between environments to make sure it works the same across BSA versions and such.

 

I'll make some Update Server Properties Jobs as the members since they don't need a Depot Object just to make this a little shorter.  For that I have UpdateServerPropertyJob.createUpdateServerPropertyJobWithTargetServer that should do nicely.  I need to:

Create my USP jobs

Create the member batch jobs

Add some of the USPs to the member batch jobs

create the parent batch job

add the usp and member batches to that job

 

Then another script based on my snippet above will recurse through what I created and spit out the list of jobs in each batch.

 

Below is the script to create the nested Batch Job I'm going to test my dump script against.  This part is really just an exercise to show how you can quickly mock up up some test data to do actual work on with the blcli instead of doing it by hand in the BSA GUI.  Since this required running the same commands a few times I broke out some of the actions into functions in the script.

#!/bin/nsh
blcli_setjvmoption -Dcom.bladelogic.cli.execute.quietmode.enabled=true
blcli_setoption serviceProfileName defaultProfile
blcli_setoption roleName BLAdmins
jobGroup="/Workspace/BatchJobTest"
jobGroupExists="false"
batchJob="TestBatch"
targetServer="blapp891.local"
# Check if the group is there and make it if not
blcli_execute JobGroup groupExists "${jobGroup}"
blcli_storelocal jobGroupExists
if [[ "${jobGroupExists}" = "false" ]]
        then
        blcli_execute JobGroup createGroupWithParentName "${jobGroup##*/}" "${jobGroup%/*}"
fi
blcli_execute JobGroup groupNameToDBKey "${jobGroup}"
blcli_storelocal jobGroupKey
blcli_execute Utility convertModelType UPDATE_SERVER_PROPERTY_JOB
blcli_storelocal uspJobTypeId
blcli_execute Utility convertModelType BATCH_JOB
blcli_storelocal batchJobTypeId
# Make some USP Jobs
for i in {1..3}
        do
        for j in a b c
                do
                blcli_execute Job jobExistsByTypeGroupAndName ${uspJobTypeId} ${jobGroupKey} "USP-${i}${j}"
                blcli_storelocal jobExists
                if [[ "${jobExists}" = "false" ]]
                        then
                        blcli_execute UpdateServerPropertyJob createUpdateServerPropertyJobWithTargetServer "USP-${i}${j}" "${jobGroup}" "${targetServer}"
                fi
        done
done
createBatchJobWithUSP()
{
   local batchJob="${1}"
   local uspJob="${2}"
   local jobGroupId="${3}"

   blcli_execute UpdateServerPropertyJob getDBKeyByGroupAndName "${uspJob%/*}" "${uspJob##*/}"
   blcli_storelocal uspKey
   blcli_execute Job jobExistsByTypeGroupAndName ${batchJobTypeId} ${jobGroupKey} "${batchJob}"
   blcli_storelocal jobExists
   # delete the batch job if it already exists, then re-create it
   if [[ "${jobExists}" = "true" ]]
        then
        blcli_execute BatchJob deleteJobByGroupAndName "${jobGroup}" "${batchJob}"
   fi
   blcli_execute BatchJob createBatchJob "${batchJob}" ${jobGroupId} ${uspKey} true false false
   blcli_storeenv batchJobKey
}
addMemberJob()
{
   local type="${1}"
   local memberJob="${2}"
   local batchJob="${3}"

   blcli_execute ${type} getDBKeyByGroupAndName "${memberJob%/*}" "${memberJob##*/}"
   blcli_storelocal memberJobKey
   blcli_execute BatchJob getDBKeyByGroupAndName "${batchJob%/*}" "${batchJob##*/}"
   blcli_storelocal batchJobKey
   blcli_execute BatchJob addMemberJobByJobKey ${batchJobKey} ${memberJobKey}
}
blcli_execute JobGroup groupNameToId "${jobGroup}"
blcli_storelocal jobGroupId
# put the 2 and 3 jobs in batch jobs
for i in {2..3}
        do
        createBatchJobWithUSP "${batchJob}-${i}" "${jobGroup}/USP-${i}a" ${jobGroupId}
        for j in b c
                do
                addMemberJob UpdateServerPropertyJob "${jobGroup}/USP-${i}${j}" "${jobGroup}/${batchJob}-${i}"
        done
done
createBatchJobWithUSP "${batchJob}-1" "${jobGroup}/USP-1a" ${jobGroupId}
addMemberJob BatchJob "${jobGroup}/${batchJob}-2" "${jobGroup}/${batchJob}-1"
addMemberJob UpdateServerPropertyJob "${jobGroup}/USP-1b" "${jobGroup}/${batchJob}-1"
addMemberJob BatchJob "${jobGroup}/${batchJob}-2" "${jobGroup}/${batchJob}-1"
addMemberJob UpdateServerPropertyJob "${jobGroup}/USP-1c" "${jobGroup}/${batchJob}-1"

That gives me a Batch Job that looks like:

That seems like a lot of work just to make a job for me to test with.  In this case, yeah, it probably was.  Is the script perfect ? Could I add more error handling ? Could it be more elegant ?  It took me about 15 minutes to write and test it out.  It works.  I could have made the jobs there from scratch in about five minutes by hand in the BSA GUI.  But let's say I need to do this again in another environment, and then another.  Or what I'm testing requires me to have a lot of jobs and then delete them.  That's when doing some automation to setup your test data pays off.

 

Now let's start the real work - listing out the Batch Job and its members.  I'm going to forget I wrote this script and pretend I only know the Batch Job that I care about /Workspace/BatchJobTest/TestBatch-1.

Now I need to:

Get my Batch Job

List all the Jobs in it

See if any of those are in turn batch jobs and if so loop back to the first step

 

That loop part probably means another function.  I already have the bit to list all the member jobs from the snippet at the very beginning. I just need to handle the recursion:

#!/bin/nsh
blcli_setjvmoption -Dcom.bladelogic.cli.execute.quietmode.enabled=true
blcli_setoption serviceProfileName defaultProfile
blcli_setoption roleName BLAdmins
if [[ ${#@} -ne 1 ]]
        then
        echo "You must pass the Batch Job"
        exit 1
fi
batchJob="${1}"
getBatchJobMembers()
{
   local batchJob="${1}"
   local batchJobKey=
   local memberKeys=
   local hasParent="${2}"
   blcli_execute BatchJob getDBKeyByGroupAndName "${batchJob%/*}" "${batchJob##*/}"
   blcli_storelocal batchJobKey
   blcli_execute BatchJob findAllSubJobHeadersByBatchJobKey ${batchJobKey}
   blcli_execute SJobHeader getDBKey
   blcli_execute Utility setTargetObject
   blcli_execute Utility listPrint
   blcli_storelocal memberKeys
   while read memberKey
     do
     blcli_execute Job findByDBKey ${memberKey}
     blcli_execute Job getType
     blcli_storelocal jobTypeId
     blcli_execute Job getName
     blcli_storelocal jobName
     blcli_execute Job getGroupId
     blcli_storelocal jobGroupId
     blcli_execute Group getQualifiedGroupName 5005 ${jobGroupId}
     blcli_storeenv jobGroupPath
     if [[ "${hasParent}" = "true" ]]
         then
         echo "--${jobGroupPath},${jobName},${jobTypeId}"
     else
         echo "${jobGroupPath},${jobName},${jobTypeId}"
     fi
     if [[ ${jobTypeId} = 200 ]]
        then
        getBatchJobMembers "${jobGroupPath}/${jobName}" true
     fi
   done <<< "$(awk 'NF' <<< "${memberKeys}")"
}
getBatchJobMembers "${batchJob}" false

That gives me output like:

/Workspace/BatchJobTest,USP-1a,1017

/Workspace/BatchJobTest,TestBatch-2,200

--/Workspace/BatchJobTest,USP-2a,1017

--/Workspace/BatchJobTest,USP-2b,1017

--/Workspace/BatchJobTest,USP-2c,1017

/Workspace/BatchJobTest,USP-1b,1017

/Workspace/BatchJobTest,TestBatch-2,200

--/Workspace/BatchJobTest,USP-2a,1017

--/Workspace/BatchJobTest,USP-2b,1017

--/Workspace/BatchJobTest,USP-2c,1017

/Workspace/BatchJobTest,USP-1c,1017

Of course, once you have the DBKey of the member job you can do whatever you want there, not just list the group path and name. 

 

That's it - we have all the member jobs along with some information about them from the Batch Job.