8 Replies Latest reply on Aug 30, 2018 8:07 AM by florian1

    Service Management API not creating all service requests

    samurainigel Apprentice

      Hi all,

       

      We have a powershell script that we run to batch-create a bunch of service requests, based on the contents of a csv, using a specific request offering template, that we pass variables to. This script works well, and we can create a lot of service requests quickly this way that have the same or similar parameters.

       

      We've been trying to track it, since we're just implementing the Service Request feature with our setup, and we've noticed that there are spots where our log will show success from the request status, which means that the request was accepted by the server, but the Service Request doesn't get created. For example, I am looking at the log for a batch of 24, and the 18th one says success, but no Service Request was made.

       

      Is there some sort of maximum speed that the API can accept these, or something? Should we be adding a delay to the code, or is something else going wrong?

        • 1. Re: Service Management API not creating all service requests
          ItsmCSL Apprentice

          Hey,

           

          I do not have an answer for your question but I'm realy interested in the script which creates the requests. Is it possible to share it? Did you manage to fill the parameter information of a service request with this script?

          • 2. Re: Service Management API not creating all service requests
            DTurner Expert

            Hi samurainigel

             

            Would you be happy to share the script, or 'pseudo'script equivalent if not?

            May help to advise potential reasons for issues

            • 3. Re: Service Management API not creating all service requests
              samurainigel Apprentice

              Our script is below, obviously with modifications to obfuscate server and login information.

               

              In a nutshell, we have the script sitting on the ISM Production server. There is a bulk upload folder on the E drive with 'log' and 'completed' subfolders. The script is set to run as a scheduled task every hour. It looks to the bulk upload folder, and tries to find any csv files. If it finds one, it reads the labeled columns out of it, dumps them into the array and creates a request for each line in it. When it's done, it creates a log file which it puts into the 'log' subfolder, and then moves the csv file into the 'completed' subfolder, and looks for any additional csv files to do the same process with.

               

              Our problem is that, while the below script works, we're finding that it occasionally seems to randomly skip making a request. The log file shows that it successfully made the request (API returns an "ISM request status: Success") but when we view the Service Requests, it will be missing. No gap in the numbering sequence for RecId, so it's not like it was deleted or something weird happened to it. It just never appears. That's why we're wondering if we're just making the requests too fast for the API, or if there's something else we're missing.

               

              $dirList = "e:\Bulk_Upload\"

              $LogDir = "e:\Bulk_Upload\Logs\"

               

              #check for file

              if (-not (Test-Path "$dirList*" )) {Break}

              $files = Get-childitem $dirList -file

               

              # API Variables

              $path = '/HEAT/ServiceAPI/FRSHEATIntegration.asmx?WSDL'

              $tenant = 'SERVERNAMEHERE'

              $uri = "https://$tenant$path"

              $role = 'Admin'

              $loginId = 'ISMUSERNAME'

              $password = 'ISMPASSWORD'

              $Service = 'NAMEOFREQUESTOFFERING'

              $secpasswd = ConvertTo-SecureString "ADPASSWORD" -AsPlainText -Force

              $ADCredential = New-Object System.Management.Automation.PSCredential ("DOMAIN\USERNAME", $secpasswd)

               

              ForEach ($filename in $files) {

                  #Create log file

                  $LogFileName = $filename.name+'.log'

                  #$LogFile = $LogDir+$LogFlieName

                  $LogFile = New-Item -Force -Path $LogDir -Name $LogFileName

                

                  #Add time stamp to log file

                  $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")

                  Add-Content -path $logfile -Value $Stamp

               

                 #Read the File

                  $Lines = Import-Csv $filename.fullname

                  

                  ForEach ($Line in $Lines) {

                      IF ($line.DPSID) {

                          #Look up Sam Account Name and add to $line object

                          $SamAccountName = Get-ADUser -credential $ADCredential -filter "DPSID -eq $($Line.DPSID)" -Server SUB.DOMAIN.COM | Select-Object SamAccountName

                          $line | Add-Member -MemberType NoteProperty -Name AccountName -Value $SamAccountName.SamAccountName

                          #$Line

                          IF (-not $line.AccountName)

                              {

                                  #AD Lookup failed. Write to log.

                                  $DPSID = $Line.DPSID

                                  $Line = "DPISD: $DPSID `tUsername lookup: Failed"

                                  #$Line

                                  Add-Content -path $logfile  -Value $Line

                              }

                          ELSE

                              {

                              # IAM to Ivanti Service Manger Web API Interface

                              # Date: 6/5/2018

                              #Setup the Connection

                              $heat = New-WebServiceProxy -Uri $uri

                              $namespace = $heat.GetType().namespace

                              $connection = $heat.Connect($loginId, $password, $tenant, $role)

               

                              # if Sucessfull, send Ivanti Service Manager the data

                              if ($connection.connectionStatus -eq 'Success') {

                

                                  #Gather the Parameters

               

                                  $Subject = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Subject.strName = "Subject"

                                  $Subject.strValue = $Line.Subject

               

                                  $Rule = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Rule.strName = "Rule"

                                  $Rule.strValue = $Line.Rule

               

                                  $Security_Change_Type = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Security_Change_Type.strName = "Security_Change_Type"

                                  $Security_Change_Type.strValue = $Line.SecurityChangeType

               

                                  $Assignee = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Assignee.strName = "Assignee"

                                  $Assignee.strValue = $Line.Assignee

               

                                  $Security_Application = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Security_Application.strName = "Security_Application"

                                  $Security_Application.strValue = $Line.SecurityApplication

               

                                  $Description = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Description.strName = "Description"

                                  $Description.strValue = $Line.Description

               

                                  $Primary_Location = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Primary_Location.strName = "Primary_Location"

                                  $Primary_Location.strValue = $Line.PrimaryLocation

               

                                  $Other_Locations = New-Object ($namespace + ".FRSHEATServiceReqParam")

                                  $Other_Locations.strName = "Other_Locations"

                                  $Other_Locations.strValue = $Line.OtherLocations

               

                                  #Build the Array

                                  $array = @($Subject, $Rule, $Assignee, $Other_Locations, $Primary_Location, $Security_Change_Type, $Security_Application, $Description)

                                  #$array

                                  $subscription = $heat.GetSubscriptionId($connection.sessionKey, $tenant, $Service)

                   

                                  #Create a Service Request

                                  $request = $heat.SubmitRequest($connection.sessionKey, $tenant, $subscription.subscriptionId, $array, $Line.AccountName)

                                  #$request

                                  }

                              #write status to log file

                              $LogLine = "DPISD: $($Line.DPSID) `tUsername lookup: $($Line.AccountName) `tISM request status: $($request.status)"

                              #$LogLine

                              Add-Content -path $logfile  -Value $LogLine

                          }

                      }

                 }

              Move-Item -Path "$($filename.Fullname)" -destination "$($filename.Directory.fullname)\Completed" -force

              }

              • 4. Re: Service Management API not creating all service requests
                DTurner Expert

                If you ran a script multiple times on your STG environment for example, would the same issues occur?

                My initial thoughts are that certain fields may be required and it is not populated these when importing to ISM. Or perhaps certain fields in ISM are of a certain field type and when importing, invalid data is passed to it.

                If you run the script manually (not as part of schtasks), are any errors shown?

                • 5. Re: Service Management API not creating all service requests
                  florian1 Expert

                  Hi,

                   

                  I experienced a similar issue when using PowerShell (this doesn't seem to happen when using C#) when I had to create ~1500 Service Requests.

                  It may be related to the workflow engine, which isn't correctly triggered all the time.

                   

                  But simply using

                  Start-Sleep 5
                  

                  did the trick for me.

                   

                   

                  Here's my script; please note that I switched to AuthenticateTenantAPIKey instead of "Connect".

                  - The CSV table just looks like this:

                  Name
                  CI1
                  CI2

                   

                  #region Functions
                  Function Initialize-WebServiceProxy{
                      If ($Script:proxy -eq $null){
                          # generate WS proxy
                          Try{
                              Write-Debug "Generating WS Proxy from $($ISMTenantURL)."
                              $Script:proxy = New-WebServiceProxy -Uri $ISMTenantURL -Class "proxy" -Namespace FRSHEATIntegration -ErrorAction Stop
                          }
                          Catch{
                             Write-Debug "Error while connecting: $_"
                             return $false
                          }
                      }
                  }
                  
                  Function Invoke-AuthenticateTenantAPIKey{
                  
                      Initialize-WebServiceProxy
                  
                      # receive session key
                      Try{
                          Write-Debug "Using method `"AuthenticateTenantAPIKey`" to obtain Session Key."
                          $connectResponse = $proxy.AuthenticateTenantAPIKey($ISMTenantAPIKey,$ISMTenantId)
                          If (![String]::IsNullOrEmpty($connectResponse)){
                          $Global:sessionKey = $connectResponse
                              return $true;
                          }
                      }
                      Catch{
                          Write-Debug "Error: $_"
                          return $false
                      }
                  }
                  
                  Function Invoke-GetSubscriptionId{
                      Param (
                          [Parameter(Mandatory=$true)]
                          [string]$RequestOfferingName
                      )
                  
                      Initialize-WebServiceProxy
                      
                      # obtain session key
                      If ([string]::IsNullOrEmpty($Global:sessionKey)){
                          If (!(Invoke-AuthenticateTenantAPIKey)){
                              return ""
                          }
                      }
                  
                      [string]$subscriptionId = ""
                  
                      #Write-Debug "Searching for Offering `"$RequestOfferingName`"..."
                      Try{
                          $result = $proxy.GetSubscriptionId($Global:sessionKey,$ISMTenantId,$RequestOfferingName)
                      }
                      Catch [System.Web.Services.Protocols.SOAPException]{
                          If ($_.Actor -eq "SessionExpired"){
                              Write-Debug "Session expired. Requesting new Session Key."
                              If (Invoke-AuthenticateTenantAPIKey){
                                  $result = $proxy.GetSubscriptionId($Global:sessionKey,$ISMTenantId,$RequestOfferingName)
                              } Else {return $false}
                          }
                          Else{
                              Write-Debug "$_"
                              return $subscriptionId
                          }
                      }
                      Catch{
                          Write-Debug "Error: $_"
                          return $subscriptionId
                      }
                  
                      If ($result.status -eq "Success")
                      {
                          #Write-Debug "$($result.status): $($result.obj.BusinessObjectName) with RecID $($result.recId) was created or updated."
                          [string]$subscriptionId = $result.subscriptionId
                          return $subscriptionId
                      }
                      Else{
                          Write-Debug "$($result.status): $($result.exceptionReason)."
                          return ""
                      }    
                  }
                  
                  Function Invoke-SubmitRequest{
                      Param (
                          [Parameter(Mandatory=$true)]
                          [string]$ParamListItems,
                  
                          [Parameter(Mandatory=$true)]
                          [string]$SubscriptionId,
                  
                          [Parameter(Mandatory=$true)]
                          [string]$LoginId
                      )
                  
                      Initialize-WebServiceProxy
                      
                      # obtain session key
                      If ([string]::IsNullOrEmpty($sessionKey)){
                          If (!(Invoke-AuthenticateTenantAPIKey)){
                              return ""
                          }
                      }
                  
                      $ParamFields = ConvertFrom-Json $ParamListItems
                      $srparamListItems = New-Object 'System.Collections.Generic.List[FRSHEATIntegration.FRSHEATServiceReqParam]'
                  
                      ForEach ($Field in $ParamFields.Fields){
                          $tempFieldProperties = @{}
                          Foreach ($memberType in ($Field | Get-Member -MemberType NoteProperty).Name) {
                              $tempFieldProperties.Add($memberType,$($Field.$memberType))
                          }
                          $tempFieldClass = New-Object FRSHEATIntegration.FRSHEATServiceReqParam -Property $tempFieldProperties
                          $srparamListItems.Add($tempFieldClass)
                      }
                  
                      Try{
                          $srResponse = $proxy.SubmitRequest($sessionKey,$ISMTenantId,$SubscriptionId,$srparamListItems.ToArray(), $LoginId);
                          return $srResponse
                      }
                      Catch [System.Web.Services.Protocols.SOAPException]{
                          If ($_.Actor -eq "SessionExpired"){
                              Write-Debug "Session expired. Requesting new Session Key."
                              If (Invoke-AuthenticateTenantAPIKey){
                                  $proxy.SubmitRequest($sessionKey,$ISMTenantId,$SubscriptionId,$srparamListItems.ToArray(), $LoginId);
                              } Else {return $null}
                          }
                          Else{
                              Write-Debug "$_"
                              return $null
                          }
                      }
                      Catch{
                          Write-Debug "Error: $_"
                          return $null
                      }
                      
                  }
                  #endregion
                  
                  #region Config
                  $Global:DebugPreference = "Continue"
                  $Global:ISMTenantURL = "http://~myTenantURL~/HEAT/ServiceAPI/FRSHEATIntegration.asmx?wsdl"
                  $Global:ISMTenantId = "~myTenant~"
                  $Global:ISMTenantAPIKey = "~myapiKey~"
                  #endregion
                  
                  #region HEATIntegrationAPI
                  $ServiceReqSubcriptionRecID = Invoke-GetSubscriptionId -RequestOfferingName:"Decommission a Client Device"
                  $RequestorLoginID = "fdeutsch"
                  
                  # Create Service Request for each record
                  $CIs = Import-CSV C:\temp\CIs.csv -Delimiter ";"
                  
                  ForEach ($CI in $CIs){
                  $ServiceReqParams = @"
                  {"Fields":[
                      {"strName":"pl_RequestType","strValue":"Decommissioning"},
                      {"strName":"pl_CIActiveClients","strValue":"$($CI.Name)"}
                      ]}
                  "@    
                      $SubmitResult = Invoke-SubmitRequest -ParamListItems:$ServiceReqParams -LoginId:$RequestorLoginID -SubscriptionId:$ServiceReqSubcriptionRecID
                  
                      # SR RecId
                      If ($SubmitResult.status -eq "Success"){
                          Write-Debug "Created Service Request $($SubmitResult.reqData.strRequestNum) with RecId $($SubmitResult.reqData.strRequestRecId)."
                      }
                      Else{
                          Write-Debug "Error occured while creating a Service Request: $($SubmitResult.status) / $($SubmitResult.exceptionReason)."
                      }
                  
                      # Wait 5 seconds before moving on...
                      Start-Sleep 5
                  }
                  
                  #endregion
                  
                  Write-Debug "--- Script ended. ---" 
                  
                  2 of 2 people found this helpful
                  • 6. Re: Service Management API not creating all service requests
                    samurainigel Apprentice

                    DTurner wrote:

                     

                    If you ran a script multiple times on your STG environment for example, would the same issues occur?

                    My initial thoughts are that certain fields may be required and it is not populated these when importing to ISM. Or perhaps certain fields in ISM are of a certain field type and when importing, invalid data is passed to it.

                    If you run the script manually (not as part of schtasks), are any errors shown?

                    We've definitely tried it manually, as that was one of our first tests to make sure we weren't imagining things. We don't have any of the fields set as required, and the same behavior can occur just passing the CustID and nothing else. The tests we've run have all been on our dev server, but we see the same behavior, which makes me think that rules out database lock ups from being actively used by dozens of analysts, live incidents, etc.

                     

                    I like that your thought process follows where we went over here, but alas, we came up empty on those avenues.

                    • 7. Re: Service Management API not creating all service requests
                      samurainigel Apprentice

                      florian1 wrote:

                       

                      Hi,

                       

                      I experienced a similar issue when using PowerShell (this doesn't seem to happen when using C#) when I had to create ~1500 Service Requests.

                      It may be related to the workflow engine, which isn't correctly triggered all the time.

                       

                      But simply using

                      1. Start-Sleep5

                      did the trick for me.

                       

                      This is what I'm fearing, and where we naturally went after trying some other things: that the trigger isn't happening each time like it should, even if the log is lying to us.

                       

                      I will try dropping a Sleep into the script and report back.

                      • 8. Re: Service Management API not creating all service requests
                        florian1 Expert

                        Some thoughts:

                        - you can reuse the Web Service proxy instance instead of creating a new one for every line.

                        - did you enable read committed snapshot isolation RCSI on your database? You might have some locking issues on database level.

                        - are you using the latest version? They might have made some changes recently.