1 2 Previous Next 28 Replies Latest reply on Nov 16, 2011 1:36 PM by Wenchi Liao

    Is there a blcli to execute a deploy job with "execute against"?

      In the 7.6 GUI there is a nice ability to right click on a job and select execute against.  This allows you to not have to clear out existing targets.

       

      I would like to do the same thing in a script.  This would save me from having to do 3 steps to execute a job.

      1.  Have a step to clear existing targets.  save the return handle

      2.  Add the targets and save the return handle.

      3.  Finally execute the job.

        • 1. Re: Is there a blcli to execute a deploy job with "execute against"?
          Paul Seager-Smith

          To delete the target servers, you need to get the Job dbKey, e.g.

           

               blcli_execute NSHScriptJob getDBKeyByGroupAndName "$ANALYSIS_JOB_GROUP" "$ANALYSIS_ONLY_JOB"

               blcli_storeenv RESPONSE

           

          and then clear the targets:

           

              blcli_execute Job clearTargetServers "$RESPONSE"

           

          You can also use clearTargetGroups to get rid of any target groups

           

          You can then add new targets:

           

           

              blcli_execute Job addTargetServers "$RESPONSE"

           

           

          Again you can also use addTargetGroups to add groups as a target

           

          the blcli help will show you all the options.

           

          Rgds,

           

          Paul

          • 2. Re: Is there a blcli to execute a deploy job with "execute against"?

            I understand what your are outlining completely.  I would like to skip that all togethor like you can in the GUI and just pass the job where I would like it to execute.  I guess that feature is not available in the blcli yet.

            • 3. Re: Is there a blcli to execute a deploy job with "execute against"?
              Stefan Kruth

              It is no tpossible with blcli, not even using unreleased commands ...

              • 4. Re: Is there a blcli to execute a deploy job with "execute against"?
                Paul Seager-Smith

                Understood, that's not possible in blcli - it's a script so you only have to write it once

                blcli is generally granular to be more flexible.

                 

                You could create your own complex command to do these steps though and then all your other scripts would just be able to call this one command.

                 

                Paul

                • 5. Re: Is there a blcli to execute a deploy job with "execute against"?
                  Stefan Kruth

                  Yepp, McGyver and the A team would have fixed the year 2000 issue

                  with some matches and some duct tape in a couple of minutes ;-)

                  You're right, if you make it down to the API command level there might be a way of putting a command togehter, but I'd recommend to consider another way. Similar to what PSS has mentioned earlier, I'd just copy the job (add date/timestamp to the name) and wipe the targets and replace them.

                  Advantage of this approach: can be done with std. command set -> survives any upgrade

                  Disadvantage: One has to look at the right job log/history ;-)

                  • 6. Re: Is there a blcli to execute a deploy job with "execute against"?
                    Bill Robinson

                    I would submit an rfe to have the 'execute against' exposed via the blcli.

                    • 7. Re: Is there a blcli to execute a deploy job with "execute against"?

                      Jython script enables the "execute against" within scripts:

                       

                      There is no blcli to execute a deploy job with "execute against" but it is possible to write a jython script that do exactly this job. (I've already written such a script).

                       

                      % bl-execjob -h

                      usage: cb-execjob [<options>] <jobname> [<server> ... ]
                        -f <host-file>, --input=<host-file>      file containing a list of servers
                        -l, --lazy                               continues with job execution even if some targets are unknown
                        -w, --wait                               wait until job is completed (default: just return the runid)
                        -t <job-type>, --type=<host-file>        job type (usefull if ambiguous in job group)


                      if no servers are specified, the job will be executed by using its default targets


                      possible values for <job-type> are:
                        'SNAPSHOT', 'COMPLIANCE', 'COMPONENT_DISCOVERY', 'DEPLOY', ...
                        default is '*' that will retrieve first job in the group matching the given name


                      example:
                        cb-execjob /Workspace/schessner/my-job  zeus.schessner.de mars.schessner.de

                       

                       

                      Note: The script below is for BladeLogic 8.0.

                      In BladeLogic 7.5 use the API call

                         Service.getScheduleService().scheduleJobNow(jobId, targets)

                      instaed of the

                         Service.getScheduleService().scheduleJobNow(jobId, targets, components)

                       

                      bl-execjob

                      #!/bin/bljython
                      ######################################################################################################
                      #vim:syntax=python
                      #
                      # File:         bl-execjob
                      # Author:     Andreas Schessner <andreas.schessner@computacenter.com>
                      #
                      # Description:  execute job against default or specific targets
                      #
                      # Copyright (C) 2010 Computacenter AG & Co.oHG

                      # Feel free to use or to distribute this script, as soon as you keep this header.
                      #
                      ######################################################################################################
                      import sys, os, os.path, time, getopt, re

                       

                      import java.lang.System
                      import java.lang.Integer
                      import java.util.ArrayList
                      import java.util.HashSet
                      import java.util.List
                      import bladelogic.cli.CLI as blcli
                      import java.lang.Error as Error
                      import java.lang.Throwable
                      import java.lang.Exception

                       

                      import com.bladelogic.model.ModelTypeEnum as BladelogicModelTypeEnum
                      import com.bladelogic.model.job.executor.ProgressStatusEnum as BladelogicProgressStatusEnum
                      import com.bladelogic.model.ServiceService as BladelogicServiceService
                      import com.bladelogic.client.nodes.jobs.JobNodeFactory as BladelogicJobNodeFactory
                      import com.bladelogic.client.nodes.ServerNodeFactory as BladelogicServerNodeFactory

                       

                      #-----------------------------------------------------------------------------------------------------

                       

                      def usage():
                        pgm = os.path.basename(sys.argv[0])
                        print "usage: %s [<options>] <jobname> [<server> ... ]" % pgm
                        print "  -f <host-file>, --input=<host-file>      file containing a list of servers"
                        print "  -l, --lazy                               continues with job execution even if some targets are unknown"
                        print "  -w, --wait                               wait until job is completed (default: just return the runid)"
                        print "  -t <job-type>, --type=<host-file>        job type (usefull if ambiguous in job group)"
                        print
                        print "if no servers are specified, the job will be executed by using its default targets"
                        print
                        print "possible values for <job-type> are:"
                        print "  'SNAPSHOT', 'COMPLIANCE', 'COMPONENT_DISCOVERY', 'DEPLOY', ..."
                        print "  default is '*' that will retrieve first job in the group matching the given name"
                        print
                        print "example:"
                        print "  %s cb-execjob /Workspace/schessner/my-job  zeus.schessner.de mars.schessner.de" % pgm
                        print

                       


                      def splitPath(path):
                        sstr = re.sub(r'\\.','??',path) # transform search string to avoid match of backslashed chars ...
                        idx  = sstr.rfind('/')
                        if idx>=0:
                          group=path[:idx]
                          name =path[idx+1:]
                        else:
                          group=""
                          name =path
                        return (group,name)

                       


                      def readInput(fileName):
                          f = open(fileName)
                          line = f.readline()
                          list = [ ]
                          while line:
                             line=line.strip()
                             if not line.startswith('#'): list.append(line)
                             line=f.readline()

                          return list

                       

                      def processOptions(args):
                          options = { }

                       

                          try:
                              opts, args = getopt.getopt(sys.argv[1:], "hwlt:f:", ["help", "wait", "lazy", "type=", "input="])

                       

                          except getopt.GetoptError, err:
                              # print help information and exit:
                              print str(err)                         # will print something like "option -X not recognized"
                              usage()                                # give a hint to the user ...
                              sys.exit(1)

                       

                          options['wait']=options['lazy']=options['file']=options['job']=options['type']=None
                          options['timeout']=5000
                          options['type']='*'

                       

                          if len(args): options['job']=args.pop(0)

                       

                          for o, arg in opts:
                              if o in ("-h","--help"):
                                  usage()
                                  sys.exit(1)
                              elif o in ("-w", "--wait"):
                                  options['wait']=1
                              elif o in ("-l", "--lazy"):
                                  options['lazy']=1
                              elif o in ("-f", "--input"):
                                  options['input']=arg
                                  args = readInput(options['input']) + args
                              elif o in ("-t", "--type"):
                                  if arg!='*':
                                    arg=arg.upper()
                                    if arg[-4:]!='_JOB': arg+='_JOB'
                                    options['type']=arg
                                  else:
                                    options['type']=arg

                       

                          if options['job']==None:
                              print "ERROR: missing job"
                              usage()
                              sys.exit(1)

                       

                          return (options,args)

                       


                      def getJobRunForJobIdAndScheduleId(jobId, scheduleId):
                          jobRunList = Service.getJobRunService().findByScheduleId(scheduleId)
                          for jobRun in jobRunList:
                              if jobRun.getJobKey().getJobId() == jobId:
                                  return jobRun;
                          return None

                       

                       

                      def getJobRun(jobId,scheduleId,wait=0):
                          jobRun  = None
                          while 1:
                              jobRun = getJobRunForJobIdAndScheduleId(jobId,scheduleId)

                       

                              if jobRun==None:ep(2)
                                  time.sleep(1)
                                  schedule = Service.getScheduleService().getById(scheduleId)
                                  if schedule.isExpired():
                                      print "EXCEPTION: schedule has expired (schedule_id=%s)" % scheduleId
                                      break

                       

                                  lastRunTime = schedule.getLastRunTime()
                                  if lastRunTime:
                                      maxTimeInSchedQ=schedule.getMaxTimeInSchedQ()
                                      elapsed = (java.lang.System.currentTimeMillis() - lastRunTime.getTime()) /60000
                                      if elapsed > maxTimeInSchedQ:
                                           print "EXCEPTION: Job has exceeded has exceeded the maximum queue time  limit of %d minute(s).  It will not be run." % maxTimeInSchedQ
                                          break
                              else:
                                  if not wait:
                                      break
                                  elif jobRun.getIsCompleted():
                                      break
                                  else:
                                      time.sleep(2)

                       

                          return jobRun

                       


                      def getJob(grpName,jobName,jobTypeName='*',recursive=0):
                          job = None
                          try:
                              jobGroup     = Service.getGroupService().getGroupByQualifiedName(5005,grpName)
                              if jobTypeName=='*':
                                  list     = Service.getJobService().findAllByGroupId(jobGroup.getGroupId(),recursive)
                                  for job in list:
                                      if job.getName()==jobName: break
                                      job=None
                              else:
                                  jobType  = BladelogicModelTypeEnum.getModelTypeByName(jobTypeName).getIntValue()
                                  job      = Service.getJobService().findByTypeGroupAndName(jobType,jobGroup.getDBKey(),jobName)

                       

                          except java.lang.Exception, e:
                              job = None

                       

                          return job

                       


                      ######################################################################################################


                      #--- get commandline options ------------------
                      (options,args) = processOptions(sys.argv[1:])

                       

                      #--- required specifiers ----------------------
                      (jobGroupPath,jobName) = splitPath(options['job'])
                      jobTypeName = options['type']

                       

                      #--- initialize bl API ------------------------
                      java.lang.System.setProperty("com.bladelogic.cli.debug.release-only","false")
                      jli = blcli.CLI()
                      jli.connect()

                       

                      #--- initialize service -----------------------
                      Service      = BladelogicServiceService.getInstance()

                       

                      #--- get job ----------------------------------
                      job          = getJob(jobGroupPath,jobName,jobTypeName)
                      if job==None:
                        print "ERROR: unable to find job '%s'" % options['job']
                        print "       (group='%s',name='%s',type=%s)" % (jobGroupPath,jobName,jobTypeName)
                        sys.exit(1)

                       

                      jobTypeName=BladelogicModelTypeEnum.getModelTypeByValue(job.getType()).getName()
                      jobId = job.getJobId()
                      print "# %s: %s [ID:%s]" % (jobTypeName,job.getName(),jobId)

                       

                      #--- build up the target list ------------------
                      if len(args)==0:
                          print "# execute job with defaults"
                          targets    = None
                          components = None
                      else:
                          print "# execute job against:"
                          targets     = java.util.HashSet()
                          components  = java.util.HashSet()
                          invalid  = [ ]
                          for serverName in args:
                              try:
                                  server = Service.getServerService().findByName(serverName)
                                  print "#  ",server.getName()
                                  targets.add(java.lang.Integer.valueOf(server.getDeviceId()))
                              except java.lang.Exception, e:
                                  invalid.append(serverName)
                          if len(invalid):
                              print "# unknown server names:"
                              for serverName in invalid:
                                  print "# ? ",serverName
                              if not options['lazy']:
                                  print "# ABORT EXECUTION: Unknown servers found."
                                  sys.exit(1)
                          if targets.size()==0:
                              print "# IGNORE EXECUTION: No servers found."
                              sys.exit(0)

                       

                      #--- schedule the job ----------------------------
                      scheduleId = Service.getScheduleService().scheduleJobNow(jobId, targets, components)
                      print "# Job was scheduled now (scheduleId=%s)" % scheduleId

                       


                      #--- retrieve JobRun -----------------------------
                      rc = 0
                      jobRun = getJobRun(jobId,scheduleId,options['wait'])
                      if jobRun:
                        #status = BladelogicProgressStatusEnum.getStatusById(jobRun.getProgressStatusId()).getName()
                        status  = "N/A"
                        if jobRun.getIsCompleted():
                          status = "completed"
                          if jobRun.getHadErrors() or jobRun.isCancelled():
                            msg    = "The Job %s has failed" % job.getName()
                            rc     = 16
                          elif jobRun.getHadWarnings():
                            msg = "The Job %s succeeded with warnings." % job.getName()
                            rc  = 32
                          else:
                            msg = "The job %s has succeeded." % job.getName()
                            rc  = 0

                       

                        else:
                          msg = "The job %s is running."  % job.getName()
                          status = "running"
                          if options['wait']: rc=1
                          else: rc=0

                       

                        print msg
                        print "runkey:",jobRun.getDBKey()
                        print "status:",status

                       

                      sys.exit(rc)

                      • 9. Re: Is there a blcli to execute a deploy job with &quot;execute against&quot;?

                        What do you mean with "execution task"?

                        As far as I know (and confirmed by this thread - as it is still unresolved ) there is no command line equvalent to the "execute against" GUI functionality.

                        Some people are suggesting to modify the "default target list" of a job before execution.

                        This is dangerous in concurrent invocations.

                        Therefore others are suggesting to make a copy of the original job, before modifying it default targets an executing the job against the new "default target list".

                        Lets assume we are dealing with a orchestration platform, that is invoking a predefined job for varying sets of targets.

                        In this case you may get a lot of job copies with their own history of job results.

                        I do not want to have such a bunch of job copies because it will be dificult to find the right job results

                        • 10. Re: Is there a blcli to execute a deploy job with &quot;execute against&quot;?
                          Bill Robinson

                          In 8.0 there is a new job object called an ‘execution task’  it creates a symlink to a job and lets you set your own targets.

                          • 11. Re: Is there a blcli to execute a deploy job with &quot;execute against&quot;?

                            Yes - for 8.0 you may use the execution task. For 7.6 the Jython script will still be necessary.

                            But the "ExecutionTask" it is not really the same as an "execute against" as it creates new object instances.

                            On the other hand there are also some advantages in using the "ExecutionTask": you may obtain your job results by the originating job as well as by the ExecutionTask itself.

                            • 12. Re: Is there a blcli to execute a deploy job with "execute against"?
                              R V

                              Just to add my two pence - what the GUI does by "Execute against" is exactly what pseagers said in his first reply: actually you DO have to clear the list of available targets and you DO have to add your wanted target and you DO have to click "Finish" - i.e. call "execute" in the blcli. So there's nothing special or even "more simple" about this "Execute against"-GUI-function.

                               

                              Of course I agree with you that it would be nice to have a

                               

                                   Job executeAgainst $jobId $targetId

                               

                              There is indeed an

                               

                                   Job execute $jobId $deviceIdList

                               

                              The problem is once again the "List". There's "Utility objectToList" which you can use to create a one-element-list from one Id. But whatever I tried - I couldn't get aware of the right value to use for Id.

                               

                              And still you have first to delete all the other devices from the already existing target-list.

                              • 13. Re: Is there a blcli to execute a deploy job with &quot;execute against&quot;?
                                Bill Robinson

                                Execute against doesn’t change the job targets in the job object.

                                • 14. Re: Is there a blcli to execute a deploy job with "execute against"?

                                  That's right - Execute against doesn't change the job targets in the job object.

                                  And the posted script bl-execute (see earlier in this thread) also does not change the targets in the job object.

                                  The script is doing exactly what rvielhaber is claiming about:

                                  It is populating a list of device-IDs (targets) before it executes (schedule now) the job with

                                  Service.getScheduleService().scheduleJobNow(jobId, targets).

                                   

                                  As it seems to be impossible to create the required list by blcli commands, I used Jython and its capability to create native Java objects.

                                  The target list is a java.util.HashSet and a derived class from the required list type.

                                  In Jython the list can easily be filled by the add method.

                                   

                                  So I agree with rvielhaber - Live would be easier if the blcli provides a way to build up a list of objects.

                                  1 2 Previous Next