Automation of the Recompose/Push Image Process for Clone Pools and update in code. (Consolidation of previous posts)

This is script is the culmination of many hours of work at night and on the weekends. This has been a personal goal of mine was to automate as much of the daily job that I can. And this is where I chose to start. This will allow me to start becoming Proactive instead of reactive.

So here I go! I give you the ability to do full monthly or weekly or daily update cycles of your clone pools from start to finish 100% scripted. Yes, you are reading that right. With this you are able to do software installs based on SCCM and/or Windows updates, Do 3rd Party patching, shut down the VM take a snapshot, clean out the old snaps, power it back on and prepare for the process to start next month all while updating ServiceNow Incident and Change. Yes, that sounds like a ton of stuff and it really is.

Currently, this has been tested and is running on production systems Windows 7, 8, and 10 64bit systems only. I have also tested the code on Horizon 7.4,7.5,7.6, and 7.7. Also tested with vSphere 6.5 and 6.7. Anything outside of this has not been tested.

Time to get down to the features. What is does this script do? Well, here you go:

  1. Captures Service accounts and passwords for Horizon, and Service Now
  2. Connects to the Horizon Connection server and pulls an inventory of pools and get the info for the Master Images, Pool Names, vCenter Info.
  3. Create a ServiceNow Incident and a ServiceNow Change.
  4. Builds out Installation and Shutdown script on a Share location that distributes the scripts to the VDI Master images.
  5. Runs the Install Updates function.
    • Runs a report of what the current installed 3rd party software is before updating
    • Install updates from SCCM
    • Install 3rd Party from SCCM (Requires Automatic install of Software)
    • Install Windows updates (If not managed by SCCM)
    • Install 3rd Party updates (If not managed by SCCM, and requires you to find appropriate scripts to install updates. There are many things on GitHub for the installs.)
    • Run a report of what the current installed 3rd party software is after updating.
    • Run a report of what the installed updates are since the last recompose
    • Create or Update a custom registry key to store the Corporate Build Date.
    • Create or Update a custom registry key to store the Last Recompose Date
    • Create or Update a custom registry key to store the Last Update Date.
    • Create or Update a custom registry key to store the Pool Assignment Type.
    • Create or Update a custom registry key to store the Pool Name.
    • Create or Update a custom registry key to store the Pool Provision Type
    • Create or Update a custom registry key to store the Pool Type.
    • Create or Update a custom registry key to store the Pool Name.
    • Create or Update a custom registry key to store the Windows Build Version.
    • Create or Update a custom registry key to store the Windows Revision.
    • Create or Update a custom registry key to store the Windows Version.
  6. Reboot the master image, it will run the cleanup script. This will clean up the master and make it ready to be cloned.
    • Checks the version of windows. (This is used for the optimizer at the end.)
    • Create or Update a custom registry key to store the current Windows Core Build Version.
    • Runs Disk Cleanup
    • Runs Defragment
    • Pre-Compile .NET Framework
    • Runs SEP update, Scan, Forced Check-in, and Clone Prep.
    • Runs VMware Optimizer based on what OS version you are on and what templates you have defined. (Beings its ran via CMD there are no rolling back changes, it’s a bug/Feature in the Optimizer)
    • Disables or Stops Services like Windows Updates, SCCM, Adaptiva. AppVolumes
    • Clean out Downloads Cache folder
    • Clean out Windows Prefetch
    • Clear the event logs
    • Releases IP Addresses
    • Clears DNS
    • Shutdown the VM
  7. Connect to each of the vCenters.
  8. Create a snapshot of each of the Masters in there Powered Off State.
  9. Update the VM Notes in vCenter to show Last Recomposed date, Last Update Date, Windows Core Build Version, Pool Type. and Pool Name based off the custom Registry Keys
  10. Will remove the old snapshots past X number of days old.
  11. Will Power the Master VMs back on.
  12. Start the SCCM and Windows Update services.
  13. Copy’s the log files from each VDI Master back to the central share.
  14. It will connect to the Horizon View Connection servers.
  15. Recompose or do image Push to the Pools, Varying the times based on if they are Production or Test.SNDev

During this entire process, we will update notes in ServiceNow. All logs generated by this task will be updated in the change.

 

There a few requirements for this script. 

  • Must be running Powershell v5.1 or newer on the Scripting Server and the Master VMs
  • The account you are running the script as has to have admin rights to the Master Images, Rights to do recompose or image push in Horizon, and appropriate rights in vCenter to take Snapshot, delete snapshots, and write notes.
  • Must have a folder share setup with the Read and Write rights to the user you will run the script as. I set up the following directories like this.
    • \\ShareLocation\VDI_Tools
      • Logs (This is where all the log files will be saved)
      • Scripts (Save this script and run it from this location)
      • CloneTools (Place your VMware Optimizer and templates in that location.
  • The VMware Modules must be installed on the Scripting Server. (Out of laziness I just enable them all.)
  • Must install the HV-Helper module on the Scripting Server. The code can be found HERE.
      1. Click the green Clone or download button and then click Download ZIP.
      2. Extract the zip file and copy the advanced functions Hv.Helper folder to a modules directory.
      3. Check your PowerShell $env: PSModulePath variable to see which directories are in use:
        • User-specific:  %UserProfile%\Documents\WindowsPowerShell\Modules
        • Systemwide: C:\Program Files\WindowsPowerShell\Modules
      4. Unblock the advanced functions to allow them to be executed.
        • In a PowerShell prompt (as Administrator), run the following command, tailoring the path to where you copied the VMware.Hv.Helper folder:
      dir ‘C:\Program Files\WindowsPowerShell\Modules\VMware.HvHelper\’ | Unblock-File
  • This only works on Horizon 7.0.2 and newer deployments! So if you are not there yet get to updating.
  • If you want to run VMware OS Optimization Tool Fling you must have it downloaded and installed in the “CloneTools” share directory, with your custom Templates. For example, this is my configuration. OptimizeFolder
  • All VDI Master Images must be domain joined. It uses domain authentication to do the remote PowerShell.
  • Enable-PSRemoting must be enabled on All the VDI Master Images.

User Editable Variables for Primary portion of Script:

$HVServers = @("ServerName.Domain.com","ServerName.Domain.com")   #Enter HVServer FQDN in format of ("HVServer1","HVServer2")   
$SnapDays = "-30"   #Number of Days to keep past snapshots on the VDI Master VM must be a negitive number
$RCTimeDelay1 = '1' #Recompose Test Pools Delay in hours
$RCTimeDelay2 = '48'    #Recompose Prod Pools Delay in hours
$TestPoolNC = "Test"    #Test pool naming convention that diffirentiates them from standard pool.

$LogLocation = "C:\VDI_Tools\Logs"  #Location to save the logs on the Master VM. They will be copied to share and deleted upon completion of the script.
$ScriptLocation = "C:\VDI_Tools\Scripts"    #Location for the Scripts on the Master VMs. This folder will remain after script completes
$CloneToolsLocation = "C:\VDI_Tools\CloneTools" #Location on the Master VMs where the VMware Optimizer is stored and any other tools.
$SleepTimeInS = "180"   #Wait timer for windows to install Windows Updates via Windows Update Service. NOT needed if using SCCM to install updates. 
$AdobeUpdate = "AdobeAcrobatUpdate.ps1" #Name of Adobe Update Script. NOT needed if using SCCM to install updates.
$FlashUpdate = "FlashUpdate.ps1"    #Name of Flash Update Script. NOT needed if using SCCM to install updates.
$FirefoxUpdate = "FireFoxUpdate.ps1"    #Name of FireFox Update Script. NOT needed if using SCCM to install updates.
$JavaUpdate = "JavaUpdate.ps1"  #Name of Java Update Script. NOT needed if using SCCM to install updates.
$CustomRegPath = "HKLM:\Software\YourCompanyName\Horizon\" #Custom Registry Path to create a Key that keeps record of when it was last updated.
$RunOptimizer = '1' #To run Optimizer enter 1, If you do not want to run enter 0
$RunSEP = '1' #To run Optimizer enter 1, If you do not want to run enter 0
$RunServiceNow = '1'    #To Create Service Now Incidents and Change Tickets with details of the Recompose process. 
$OptimizerTemplateNamingPrefix = "TemplateName" #Template Naming i.e. "CompanyTemplate10" for windows 10 Please make sure to append the namy by 10 for win10, 8 for win8, and 7 for win7
$VMwareOptimizerName = "VMwareOSOptimizationTool.exe"   #Name Of the VMware Optimizer Tool
$ShareLogLocation = "\\ShareName.domain.com\VDI_Tools\Logs" #Network Share to save the logs. This will be the collection point for all logs as each VDI Master VM will copy there local logs to this location.
$ShareScriptLocation = "\\ShareName.domain.com\VDI_Tools\Scripts"   #Network Share location where all the scripts are stored and distributed from. 
$ShareCloneToolsLocation = "\\ShareName.domain.com\VDI_Tools\CloneTools"    #Network Share Location where all the Clone Tools are stored and distributed from.
$DomainName = "Domain.Name"     #The Domain that the Master Images are Joined to.
$CorporateBuildRegistryKeyPath = "HKLM:\Software\YourCompanyName\OS\"
$CorporateBuildRegistryKeyName = "BuildVersion"

There are 3 variables that you can set to turn off or on portions of the script. By entering a 0 it will skip those portions of the script.

$RunOptimizer = ‘1’ #To run Optimizer enter 1, If you do not want to run enter 0
$RunSEP = ‘1’ #To run Optimizer enter 1, If you do not want to run enter 0
$RunServiceNow = ‘1’ #To Create Service Now Incidents and Change Tickets with details of the Recompose process.

ServiceNow:

Looking at the Service Now bits its a bit overwhelmed on the number of variables you ServiceNowneed fill out. But from what I have found its what’s needed for my workflow, you are more than welcome to customize it. The function of the Service Now the piece is that it will open an Incident, and open a change with the Incident as the parent. It will fill out all the change notes with the text from the log files, including what updates were installed, what 3rd party updates were installed and the complete logs of the script.

ServiceNow Variables defined are below. This will require some research on your part. You can follow some of my past posts where I defined how to find the Sys_ID of items in ServiceNow. Link to Building Service Now Functions for adding to existing automation scripts.

#ServiceNow Varibles
$SNAddress = "https://YOURSERVICENOW.service-now.com"

#______________________________________________________________________________________
#Incident Varribles

$SNINCCallerID = "Caller Sys_ID" #Look up the Caller User you want to uses Sys_ID in your Service Now instance
$SNINCUrgency = "2" #Look this up in your Service Now instance
$SNINCImpact = "3" #Look this up in your Service Now instance
$SNINCPriority = "4" #Look this up in your Service Now instance
$SNINCContactType = "email" #Look this up in your Service Now instance
$SNINCNotify = "2" #Look this up in your Service Now instance
$SNINCWatchlist = "Watch List Sys_ID" #Can do comma seperated users Sys_ID's
$SNINCServiceOffering = "Service Offering" #Look this up in your Service Now instance
$SNINCProductionImpact = "No" #Well I hope its a No.
$SNINCCategory = "Your Catagory" #Look this up in your Service Now instance
$SNINCSubcategory = "Your SubCat" #Look this up in your Service Now instance
$SNINCItem = "request" #Look this up in your Item menu
$SNINCAssignmentGroup = "Assignment Group Sys_ID" #Look up the Assignment group you want to uses Sys_ID in your Service Now instance
$SNINCAssignedTo = "Assigned To Sys_ID" #Look up the Assignment to user you want to uses Sys_ID in your Service Now instance
$SNINCShortDescription = "Weekly Patch Cycle Updates VDI Pools for $SNDate" #Short Descriptiong of the task
$SNINCDescription = "Weekly Patch Cycle Update for VDI pools.
The following VDI Master Images are being updated with the latest Windows updates and 3rd Party software.
$HVPoolMSTR
Test Pools will be Refreshed at $SNScriptDate
Production Pools will be Refreshed $SNScriptDate2" #Full description of what you are trying to acomplish this is my example.

#______________________________________________________________________________________
#Change Varribles

$SNCHGRequestedBy = "Requested By Sys_ID" #Look up the Requested by User you want to uses Sys_ID in your Service Now instance, Normaly the same as the Caller for the INC
$SNCHGCategory = "Change Catagory" #Look this up in your Service Now instance
$SNCHGServiceOffering = "Service Offering" #Look this up in your Service Now instance
$SNCHGReason = "Change Reason" #Look this up in your Service Now instance
$SNCHGClientImpact = "No" #Look this up in your Service Now instance
$SNCHGStartDate = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss') #date in string format. Only way it works.
$SNCHGEndDate = (Get-Date).AddHours($RCTimeDelay2+24).ToString('yyyy-MM-dd HH:mm:ss') #24 hour delay of right now (Can Change if needed) Has to be as a string
$SNCHGWatchList = "Watch List Sys_ID" #Can do comma seperated users Sys_ID's
$SNCHGUrgency = "2" #Look this up in your Service Now instance
$SNCHGRisk = "4" #Look this up in your Service Now instance
$SNCHGType = "Standard" #Look this up in your Service Now instance
$SNCHGState = "1" #Look this up in your Service Now instance
$SNCHGAssignmentGroup = "Assignment Group Sys_ID" #Look up the Assignment Group you want to uses Sys_ID in your Service Now instance
$SNCHGAssignedTo = "Assigned To Sys_ID" #Look up the Assigned to User you want to uses Sys_ID in your Service Now instance

#______________________________________________________________________________________
# Example of what I am using for my change information.
$SNCHGJustification = "Weekly Sercurity Patching to install latest Windows updates, 3rd Party updates and Symantec antivirus client update"
$SNCHGChangePlan = "Run report on each VDI Master Image for install Software
Install Windows Updates from SCCM
Install 3rd Party software updates from SCCM
Run Report on each VDI Master Image for installed Software after updates have been completed
Update Custom Reg key to reflect the last date updated
Reboot VDI master VM
Run Shutdown Script that will Run Disk Cleanup, Defragment C drive, Pre-Compile .NET Framework, Run SEP Update, Run full system Scan, Force check-in with SEP server, Run VMware Optimization Tool, Clean out DownLoad's Cache Folder, Clear Event Logs, Release IP, Clear DNS, and Shutdown the VM.
Create a vCenter Snapshot of each VDI Master Image.
Update the vCenter VDI Master Image notes to show current recompose date
Remove Old Snapshots from the VDI Master Images
Power Back on the VDI Master Image
Start all the services
Copy Logs from VDI Master Images to remote Share and upload to this Change.
Refresh each of the pools based on Prod and Test timelines."
$SNCHGTestPlan = "All VDI Clone Pools listed as Test Pools will Be updated 1 hour after script completion, and Production pools will be updated 48 hours later."
$SNCHGBackoutPlan = "If there is a error found, will cancel all future Refresh tasks, and revert the ones that have been refreshed already to the previous snapshot."

There are a couple known bugs:

  1. One is running this more than one time a day will create two snapshots with the same name, and then try to recompose or push the image and get confused as there are two snaps of the same name. So it will fail to update the recompose or push part fo the script. Workaround: Remove the previous snaps for the same day before running the script again. I chose not to put this as the core code as it could delete a running snapshot.
  2. Running the script late in the day, like the last hour of the day. When it runs the script its date dependent. If the script is kicked off on the 12-4-2018 there is a possibility that the snaps might be taken on 12-5-2018, and when the recompose or Push happens it will be looking for a snap from 12-4-2018. In turn, erroring out and failing the Recompose or Push for those pools. Workaround: Run the script early in the day or morning to avoid running into the next day. On at minimum, the script takes 17 mins to run Per Pool. Please plan accordingly.Known Issues
  3. If the credentials that you use to run the script have expiring passwords it will error out and fail the script and not prompt for new creds. (Might be an added feature soon.) Workaround: Use service account with a non-expiring password or delete the password file from the Script Server when you reset your password.
  4. Multi-Domain issues. If your scripting server is in a different domain than your VDI master images you will run into some DNS lookup issues. As in the script, we are not using FQDN to connect to the master Images we are just using hostname. Sorry if this causes an issue. Workaround: Can be fixed pretty simple by adding a domain variable and appending most of the $VMline variables in the script. (Can not promise when I get to fixing this one.)

 

Here are a few of before and after Shots of what is going on.

Snapshots:

Manage Snapshots Before

Snapshots Before

Manage SnapshotsAfter

Snapshots After

 

vCenter Notes:

Notes

vCenter Attributes:

vCenter_Attributes

Pool Details:

HorizonConsolePoolBefore

Pool Before

HorizonConsolePoolAfter

Pool After

Image Push:

HorizonConsoleMachines

Pending Push

HorizonConsoleMachinesAfterPush

Completed Push

Task List:

vCenterTasksAfter

Custom Registry Entry:

RegKeysUpd

Log files in the Share:

LogFilesShare

Installed Software Log Example:

Transcript Log

VMware Optimizer Report:

VMware Optimization Report

Transaction Log Report:

Transcript Log

 

The Code! This has been a long process and a ton of trial and error to get all this to work.

Link to the code on GitHub!

I will continue to update and optimize this code so check back frequently. If There are any issues found please let me know.

 

What is in the works for this script you ask?

  • Breaking the Script into Modules so allow better plug and play and customizations.
  • If no ServiceNow building out email functions for reporting. (If someone wants to devote the time to a good HTML body let me know. I just planned on plain text.
  • Add Multi-Threading (I have run into some issues trying to deploy in this version and have held until I had more time to test.)

Last but not least. A huge thank you to Michael McDonnell for the help. Your help and guidance and mentorship have been much appreciated. And thanks to the MANY blog posts of other people and the mass amount of TechNet and PowerShell docs I have read of the last few months. And big thanks to Wouter Kursten for creating the HV-Helper, and answering some of my odd questions!

Advertisements
Posted in CLI and Powershell, DevOps, Service Now, VDI, Virtulization | Tagged , , , , , , , , , ,

vCenter 6.5 as a Sub CA and Configuring the VAMI cert.

Part of our vCenter build out design was to put the vCenters as a Sub CA of the corporate PKI infrastructure. After doing so…We found an interesting bug or missing step in the procedure.

Instead of reinventing a perfectly good blog post with great detail. Here is what I followed for building out the vCenters as a Sub CA.

https://haveyoutriedreinstalling.com/replacing-vsphere-6-0-certificates-using-vmca-as-a-subordinate-ca/

It goes into great detail and has great pictures to follow for all you Lego people.

After you complete all the steps for setting up your vCenter as a Sub CA it will work great…………………….except one part! Your VAMI will still have the old cert.

Extremely frustrating. There is a workaround for this issue. But there is a bug in the workaround of this issue. It’s missing some details for people like you and me because we are running as a Sub CA.

VMware KB: https://kb.vmware.com/s/article/2136693

vCenter Server Appliance 6.5 & 6.7:
  1. Log in to the vCenter Server Appliance through SSH.
  2. Type shell and press Enter.
  3. Copy CA cert chain to:vcsa-a:/ssl/machineSSL  # cp cachain.cer /etc/applmgmt/appliance/ca.crt

The issue is that your certs are not located in the location above. So instead of using /ssl/machineSSL  use this location /etc/vmware/vmware-vmafd

and use this command instead.

         vcsa-a:/etc/vmware/vmware-vmafd  # cp ca.crt /etc/applmgmt/appliance/ca.crt
  1. Open the /opt/vmware/etc/lighttpd/lighttpd.conf file using a text editor:
  2. Add the entry:ssl.ca-file=”/etc/applmgmt/appliance/ca.crt”
  1. Restart the VAMI service:/etc/init.d/vami-lighttp restart
Now the next time you log into your VAMI all will be right in the world again. And you won’t have security hounding you anymore.
Posted in Certificates, Virtulization | Tagged , , , , , ,

Building Service Now Functions for adding to existing automation scripts.

I have been working on some bigger automation projects here lately. And ran into the need to learn more about Service Now and how to create Incidents and Change Requests via PowerShell and also how to add them to the Scripts I was already working on. So in good fashion, there was not much out there already so here is my rendition of what I needed.

This script is taking what I already did in the last 3 Service Now posts and creatingSNDev functions. This allowing for quick plug and play into the scripts going forward. Just in case you have not read them here are the previous posts that give some background on where this all came from.

Service Now Incident Creation and Updating with PowerShell

Service Now Change Request Creation and Updating with PowerShell

Using the ServiceNow Rest API Explorer

This script is broken into 3 main functions. Create, Update and Get. For my use case, I was creating an Incident and then creating a Change Request with the Incident as the parent.

# Build Service Now Functions for Create, Update, and Get Incidents and Changes

# Chris Hildebrandt

# 11-25-2018

# Ver 1.0

# Script will create a new ServiceNow Incident and Change, Update existing Incidents and Changes, and Get all details of Incidents and Changes via Powershell

#______________________________________________________________________________________

#______________________________________________________________________________________

#ServiceNow Varibles

$SNAddress = "https://YOURSERVICENOW.service-now.com"

#______________________________________________________________________________________

#Incident Varribles

$SNINCCallerID = "Caller Sys_ID"

$SNINCUrgency = "2" #Look this up in your Service Now instance

$SNINCImpact = "3" #Look this up in your Service Now instance

$SNINCPriority = "4" #Look this up in your Service Now instance

$SNINCContactType = "email" #Look this up in your Service Now instance

$SNINCNotify = "2" #Look this up in your Service Now instance

$SNINCWatchlist = "Watch List Sys_ID" #Can do comma seperated users Sys_ID's

$SNINCServiceOffering = "Service Offering" #Look this up in your Service Now instance

$SNINCProductionImpact = "No" #Well I hope its a No.

$SNINCCategory = "Your Catagory" #Look this up in your Service Now instance

$SNINCSubcategory = "Your SubCat" #Look this up in your Service Now instance

$SNINCItem = "request" #Look this up in your Item menu

$SNINCAssignmentGroup = "Assignment Group Sys_ID"

$SNINCAssignedTo = "Assigned To Sys_ID"

$SNINCShortDescription = "Short Discription"

$SNINCDescription = "Full Discription"

$SNINCWorkNotes = "Work Notes"

$SNINComments = "Notes"

#______________________________________________________________________________________

#Change Varribles

$SNCHGRequestedBy = "Requested By Sys_ID"

$SNCHGCategory = "Change Catagory" #Look this up in your Service Now instance

$SNCHGServiceOffering = "Service Offering" #Look this up in your Service Now instance

$SNCHGReason = "Change Reason" #Look this up in your Service Now instance

$SNCHGClientImpact = "No" #Look this up in your Service Now instance

$SNCHGStartDate = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss') #date in string format. Only way it works.

$SNCHGEndDate = (Get-Date).AddHours($RCTimeDelay2+24).ToString('yyyy-MM-dd HH:mm:ss') #24 hour delay of right now (Can Change if needed) Has to be as a string

$SNCHGWatchList = "Watch List Sys_ID" #Can do comma seperated users Sys_ID's

$SNCHGUrgency = "2" #Look this up in your Service Now instance

$SNCHGRisk = "4" #Look this up in your Service Now instance

$SNCHGType = "Standard" #Look this up in your Service Now instance

$SNCHGState = "1" #Look this up in your Service Now instance

$SNCHGAssignmentGroup = "Assignment Group Sys_ID"

$SNCHGAssignedTo = "Assigned To Sys_ID"

$SNCHGShortDescription = "Short Description"

$SNCHGDescription = "Description Test"

$SNCHGJustification = "Justification Notes"

$SNCHGChangePlan = "Change Plan"

$SNCHGTestPlan = "Test Plan Notes"

$SNCHGBackoutPlan = "Back Out Plan Notes"

$SNCHGChangeSummary = "Change Summary Notes"

#______________________________________________________________________________________

#Create Service Now Creds if they do not already exist

if(-Not (Test-Path -Path "C:\VDI_Tools\Scripts\SNAccount.txt" ))

{

Get-Credential-Message "Enter Your ServiceNow Account! Username@domain"|Export-Clixml"C:\VDI_Tools\Scripts\SNAccount.txt"

Write-Host"Created Secure Credentials for ServiceNow"

}

#______________________________________________________________________________________

#Import Service Now Creds

$SNCreds = Import-Clixml "C:\VDI_Tools\Scripts\SNAccount.txt"

Write-Host "Imported Secure Credentials for ServiceNow from Text file"

#______________________________________________________________________________________

#Decrypt Password to imput into ServiceNow

$SNTextPass = $SNCreds.Password | ConvertFrom-SecureString

$SNTextPassPlain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR( (ConvertTo-SecureString $SNTextPass) ))

Write-host "Decrypt Master Password to clear text for import into VM"

#______________________________________________________________________________________

#Create ServiceNow Creds Varribles

$SNuser = $SNCreds.Username

$SNpass = $SNTextPassPlain

#______________________________________________________________________________________

#ServiceNow Method Varibles Do not edit these

$SNMethodPost = "post"

$SNMethodGet = "get"

$SNMethodPut = "put"

$SNMethodPatch = "patch"

$SNINCAddress = "$SNAddress/api/now/table/incident"

$SNCHGAddress = "$SNAddress/api/now/table/change_request"

#______________________________________________________________________________________

#ServiceNow Build Auth Headers

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $SNuser, $SNpass)))

#______________________________________________________________________________________

#ServiceNow Set Header

$SNheaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"

$SNheaders.Add('Authorization',('Basic {0}' -f $base64AuthInfo))

$SNheaders.Add('Accept','application/json')

$SNheaders.Add('Content-Type','application/json')

Function Create-Incident()

{

# Specify request body

$SNCreateINCBody = @{ #Create Body of the Post Request

caller_id=$SNINCCallerID

urgency=$SNINCUrgency

impact=$SNINCImpact

priority=$SNINCPriority

contact_type=$SNINCContactType

notify=$SNINCNotify

watch_list=$SNINCWatchlist

service_offering=$SNINCServiceOffering

u_production_impact=$SNINCProductionImpact

category=$SNINCCategory

subcategory=$SNINCSubcategory

u_item=$SNINCItem

assignment_group=$SNINCAssignmentGroup

assigned_to=$SNINCAssignedTo

short_description=$SNINCShortDescription

description=$SNINCDescription

work_notes=$SNINCWorkNotes

comments=$SNINComments

}

$SNCreateINCbodyjson = $SNCreateINCBody | ConvertTo-Json

# POST to API

Try

{

# Send API request

$SNCreateIncResponse = Invoke-RestMethod -Method $SNMethodPost -Uri $SNINCAddress -Body $SNCreateINCbodyjson -TimeoutSec 100 -Headers $SNheaders -ContentType "application/json"

}

Catch

{

Write-Host $_.Exception.ToString()

$error[0] | Format-List -Force

}

return $SNCreateIncResponse

}

Function Create-Change()

{

#Specify Change Request Body

$SNCreateCHGbody = @{ #Create Body of the Post Request

requested_by=$SNCHGRequestedBy

category=$SNCHGCategory

service_offering=$SNCHGServiceOffering

reason=$SNCHGReason

u_client_impact=$SNCHGClientImpact

start_date=$SNCHGStartDate

end_date=$SNCHGEndDate

watch_list=$SNCHGWatchList

parent=$SNIncidentSysID

urgency=$SNCHGUrgency

risk=$SNCHGRisk

type=$SNCHGType

state=$SNCHGState

assignment_group=$SNCHGAssignmentGroup

assigned_to=$SNCHGAssignedTo

short_description=$SNCHGShortDescription

description=$SNCHGDescription

justification=$SNCHGJustification

change_plan=$SNCHGChangePlan

test_plan=$SNCHGTestPlan

backout_plan=$SNCHGBackoutPlan

u_change_summary=$SNCHGChangeSummary

}

$SNCreateCHGbodyjson = $SNCreateCHGbody | ConvertTo-Json

# POST to API

Try

{

# Send API request

$SNCreateChangeResponse = Invoke-RestMethod -Method $SNMethodPost -Uri $SNCHGAddress -Body $SNCreateCHGbodyjson -TimeoutSec 100 -Headers $SNheaders -ContentType "application/json"

}

Catch

{

Write-Host $_.Exception.ToString()

$error[0] | Format-List -Force

}

return $SNCreateChangeResponse

}

Function Update-Change($SNCHGUpdateComments)

{

# Specify request body

$SNUpdateCHGbody = @{ #Create Body of the Post Request

comments=$SNCHGUpdateComments

}

$SNUpdateCHGbodyjson = $SNUpdateCHGbody | ConvertTo-Json

# Send API request

$SNUpdateChangeResponse = Invoke-RestMethod -Method $SNMethodPatch -Uri "$SNCHGAddress\$SNChangeSysID" -Body $SNUpdateCHGbodyjson -TimeoutSec 100 -Headers $SNheaders -ContentType "application/json"

}

Function Update-Incident($SNINCUpdateWorkNotesUpdate)

{

# Specify request body

$SNUpdateINCbody = @{ #Create Body of the Post Request

work_notes=$SNINCUpdateWorkNotesUpdate

}

$SNUpdateINCbodyjson = $SNUpdateINCbody | ConvertTo-Json

# Send API request

$SNUpdateIncidentResponse = Invoke-RestMethod -Method $SNMethodPatch -Uri "$SNINCAddress\$SNIncidentSysID" -Body $SNUpdateINCbodyjson -TimeoutSec 100 -Headers $SNheaders -ContentType "application/json"

}

Function Get-Incident($SNGetIncidentSysID)

{

# Build URI

$SNGetINCAddress = "$SNINCAddress/$SNGetIncidentSysID" + "?sysparm_fields=parent%2Ccaused_by%2Cwatch_list%2Cu_aging_category%2Cu_call_back_number%2Cupon_reject%2Csys_updated_on%2Cu_resolved_by_tier_1%2Cu_ud_parent%2Cu_resolved_within_1_hour%2Cu_routing_rule%2Capproval_history%2Cskills%2Cu_actual_resolution_date%2Cnumber%2Cu_related_incidents%2Cu_closure_category%2Cstate%2Csys_created_by%2Cknowledge%2Corder%2Cdelivery_plan%2Ccmdb_ci%2Cimpact%2Cu_requested_for%2Cactive%2Cpriority%2Cgroup_list%2Cbusiness_duration%2Cu_template%2Capproval_set%2Cwf_activity%2Cu_requested_by_phone%2Cshort_description%2Cu_itil_watch_list%2Cdelivery_task%2Ccorrelation_display%2Cwork_start%2Cu_ca_reference%2Cadditional_assignee_list%2Cnotify%2Cservice_offering%2Csys_class_name%2Cfollow_up%2Cclosed_by%2Creopened_by%2Cu_csv_comments%2Cu_planned_response_date%2Creassignment_count%2Cassigned_to%2Csla_due%2Cu_actual_response_date%2Cu_sla_met%2Cu_closure_ci%2Cu_reopen_count%2Cescalation%2Cupon_approval%2Cu_service_category%2Ccorrelation_id%2Cu_resolution_duration%2Cu_requested_by_name%2Cmade_sla%2Cu_requested_by_email%2Cu_item%2Cu_svc_desk_created%2Cresolved_by%2Cu_business_service%2Csys_updated_by%2Cuser_input%2Copened_by%2Csys_created_on%2Csys_domain%2Cu_quality_impact%2Cu_req_count%2Ccalendar_stc%2Cclosed_at%2Cu_relationship%2Cu_parent_incident%2Cu_comments_and_work_notes%2Cu_requested_by_not_found%2Cu_requested_by%2Cbusiness_service%2Cu_agile_incident_ref%2Cu_symptom%2Crfc%2Ctime_worked%2Cexpected_start%2Copened_at%2Cwork_end%2Creopened_time%2Cresolved_at%2Ccaller_id%2Cu_client%2Cwork_notes%2Csubcategory%2Cu_ah_incident%2Cclose_code%2Cassignment_group%2Cbusiness_stc%2Cdescription%2Cu_planned_resolved_date%2Ccalendar_duration%2Cu_on_hold_type%2Cu_source%2Cclose_notes%2Cu_closure_subcategory%2Cu_previous_assignment%2Csys_id%2Ccontact_type%2Curgency%2Cproblem_id%2Cu_itil_group_list%2Cu_response_duration%2Cu_best_number%2Ccompany%2Cactivity_due%2Cseverity%2Cu_production_impact%2Ccomments%2Capproval%2Cdue_date%2Csys_mod_count%2Csys_tags%2Clocation%2Ccategory"

# Specify request body

$SNGetINCbody = @{

}

$SNGetINCbodyjson = $SNGetINCbody | ConvertTo-Json

# Send API request

$SNGetIncidentResponse = Invoke-RestMethod -Method $SNMethodGet -Headers $SNHeaders -Uri $SNGetINCAddress

Return $SNGetIncidentResponse

}

Function Get-Change($SNGetChangeSysID)

{

To run the code you can do something like this…

$SNCreateIncResponseReturn = Create-Incident

$SNIncidentID = $SNCreateIncResponseReturn.result.number
$SNIncidentSysID = $SNCreateIncResponseReturn.result.sys_id

Write-Host $SNIncidentSysID
Write-Host $SNIncidentID

Above will create an Incident and then populate the IncidentID and SysID variables. That gives you your INC number and your Sys_ID of the incident.

You can do the same thing with the change. Keep in mind that my code uses the IncidentSysID to create a change with the parent of the Incident we just created.

$SNCreateChangeResponseReturn = Create-Change

$SNChangeID = $SNCreateChangeResponseReturn.result.number
$SNChangeSysID = $SNCreateChangeResponseReturn.result.sys_id

Write-Host $SNChangeSysID
Write-Host $SNChangeID

Same as above this will create the change and give you your Change Number and Sys_ID number.

You can update Incident you created running just the simple command of:

update-incident "Update the change Notes"

Or if you want to import a file contents you can run the following command.

update-incidents $content = [IO.File]::ReadAllText("File Path and name")

This will read all the contents of the file and post it into the Incident Comments. Great when you uploading logs.

Can do the same thing with the change.

update-change "Update Change Work Notes"

or the import file contents

update-incidents $content = [IO.File]::ReadAllText("File Path and name")

Next is the Get Incident and Change. For me, I wanted to save all the change and incident info in a log file for reference later if I ever had an issue.

Get-Incident $SNIncidentSysID

This will write on the console all the contents of the Incident. or you can run the same thing for the Change Request

Get-Change $SNChangeSysID

There are a massive amount of other things you can do with the Service Now API explorer. Maybe as I have time I will dig more into it.

All the contents to this script are posted on my GitHub repo HERE. Along with my other Service Now stuff from the other blogs.

Posted in CLI and Powershell, Random Crap, Service Now | Tagged , ,

Service Now Change Request Creation and Updating with PowerShell

I finally am getting around to posing the addition to my previous blog post for Creating and updating Service Now Incidents.

SNDevSame as before you need to know your Sys_ID’s of the objects you are going to use. Like your user account, The assignment group and anyone else you are going to need to add to this change request.

Finding Sys_IDs is easy once you figure out they are a 32 character code listed in the URL of the objects you are looking for. Same with your Incident’s.

First Open an existing incident with your name in it. On the right of your name is the “i” Click on it and then the “Open Record” button on the upper right-hand side. ChrisHil

This will open your User record in ServiceNow. In the URL you will see your Sys_ID. ChrisHSys_ID

You can do this for the rest of the other Sys_ID’s you need. Also in this change, I have the parent filed in the script, So if you find the Sys_ID of the parent Incident you can put that as the parent for the change.

From there you just need to gather all the info that is required or you would like to use.

# Create New ServiceNow Change

# Chris Hildebrandt

# 10-26-2018

# Ver 1.0

# Script will create a new ServiceNow Change via Powershell

#______________________________________________________________________________________

# Eg. User name="admin", Password="admin" for this code sample.

$SNuser = "admin" #enter your ServiceNow Username

$SNpass = "admin" #enter your ServiceNow Password

# Build auth header

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $SNuser, $SNpass)))

# Set proper headers

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"

$headers.Add('Authorization',('Basic {0}' -f $base64AuthInfo))

$headers.Add('Accept','application/json')

$headers.Add('Content-Type','application/json')

# Specify endpoint uri

$CHGuri = "https://YOURSERVICENOW.service-now.com/api/now/table/change_request"

# Specify HTTP method

$Postmethod = "post"

# Specify request body

$CHGbody = @{ #Create Body of the Post Request

requested_by = "Requested By Sys_ID"

category = "Other"

service_offering = "Other"

reason = "software upgrade"

u_client_impact = "No"

start_date = "2018-11-1 01:00:00"

end_date = "2018-11-30 23:00:00"

watch_list = "Watch List Sys_ID"

parent = "Parent Incident or Change Request"

urgency = "2"

risk = "4"

type = "Standard"

state = "1"

assignment_group = "Assigned To's Group Sys_ID"

assigned_to = "Assigned To Sys_ID"

short_description = "Short Description"

description = "Description: Test"

justification = "Justification Notes"

change_plan = "Change Plan:"

test_plan = "Test Plan: Notes"

backout_plan = "Back Out Plan: Notes"

u_change_summary = "Change Summary: Notes"

}

$CHGbodyjson = $CHGbody | ConvertTo-Json

# POST to API

Try

{

# Send API request

$ChangePOSTResponse = Invoke-RestMethod -Method $Postmethod -Uri $CHGuri -Body $CHGbodyjson -TimeoutSec 100 -Headers $headers -ContentType "application/json"

}

Catch

{

Write-Host $_.Exception.ToString()

$error[0] | Format-List -Force

}

# Pulling ticket ID from response

$ChangeID = $ChangePOSTResponse.result.number

$ChangeSysID = $ChangePOSTResponse.result.sys_id

# Verifying Change created and show ID

IF ($ChangeID -ne $null)

{

"Created Change With ID:$ChangeID"

"Change created With Sys_ID:$ChangeSysID"

}

ELSE

{

"Change Not Created"

}

The script below is an extremely basic script that I have built for my use case but this has huge building blocks from here. In this script, you need to edit the username and password. You can use encrypted if you like. You will need your ServiceNow URL and of course all your Sys_ID’s and info from the fields that have drop-down menus. Later on, in a blog post, I will put something out there on a script I created making all the Service Now code into functions to use in much larger scripts.

 

This script below will update an existing Service Now Change. You will need the Sys_ID for the Change you are updating. That can be found in the URL of the change.

Sys_ID

# Update New ServiceNow Change

# Chris Hildebrandt

# 10-26-2018

# Ver 1.0

# Script will Update a ServiceNow Change via Powershell

#______________________________________________________________________________________

# Eg. User name="admin", Password="admin" for this code sample.

$SNuser = "admin" #enter your ServiceNow Username

$SNpass = "admin" #enter your ServiceNow Password

# Build auth header

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $SNuser, $SNpass)))

# Set proper headers

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"

$headers.Add('Authorization',('Basic {0}' -f $base64AuthInfo))

$headers.Add('Accept','application/json')

$headers.Add('Content-Type','application/json')

# Specify endpoint uri

$UpdateCHGuri = "https://YOURSERVICENOW.service-now.com/api/now/table/change_request/THE Change you want to updates Sys_ID"

# Specify HTTP method

$Patchmethod = "patch"

# Specify request body

$UpdateCHGbody = @{ #Create Body of the Post Request

state="8"

comments="Additional Coments "#Add the comments you want to add to the Change.

u_change_summary="Change Summary"#Add to the Change Summary.

}

$UpdateCHGbodyjson = $UpdateCHGbody | ConvertTo-Json

# Send HTTP request

$response = Invoke-WebRequest -Headers $headers -Method $method -Uri $uri -Body $body

# Send API request

$UpdateChangePOSTResponse = Invoke-RestMethod -Method $Patchmethod -Uri $UpdateCHGuri -Body $UpdateCHGbodyjson -TimeoutSec 100 -Headers $headers -ContentType "application/json"

I was working with Comments and Change Summary you can add other fields as you like.

The Links for these Scripts are on my GitHub repo HERE. Along with a few other Scripts.

Posted in CLI and Powershell, DevOps, Service Now | Tagged , ,

Using the ServiceNow Rest API Explorer

A month or so ago I was introduced into the world of the ServiceNow Rest API explorer. It was a rough into at best.

A little backstory always helps. I am still working on a project to automate most of my daily tasks in the VDI world. The need to create Incidents and Change tickets as part of the process I needed. I reached out to the ServiceNow team at work and asked if he had any automation scripts built, if not could I have access to the API Explorer. And the email responding back to this request was “No I do not have any automation built for SNDevServiceNow, If you would like to use it here is our ServiceNow Dev site URL, and Here are some credentials to log in.” As a person with limited RestAPI skills, this was kind of a dreaded moment. So I pick a weekend and jump in head first with the goal of wanting to be able to create and Update both Incidents and Changes by the end of the weekend.

If you google around you don’t find much out there for building scripts for this. And after the fact, I realize why. I don’t think anyone fully understands the API. Some may laugh at this but as an Infrastructure and VDI guy, this is a different concept for me. I have done a ton of work in PowerShell but limited with the API world so looking at this is more like reading Chinese.

So step One was finding the API Explorer…..This is not on the normal menu on the left side so of course, you have to search for it at the top. The next part is understanding what the API explorer does and how it can help you. Below is what you walk into. API Exp1

Retrieve records from a table  (GET):
Create a record  (POST)
Retrieve a record  (GET)
Modify a record  (PUT)
Delete a record  (DELETE)
Update a record  (PATCH)

These 6 API calls are extremely useful. I have not spent much time with “Get Table” or Delete but getting pretty comfortable with the Post, Get, Put.

 

When I started working with this I had no idea on where to start. I tried to use the Post function first to see what the fields are. But it was rather confusing to me as I could not get it to fill in the caller info and a few other fields that required the Sys_ID. Decided to give up on this as I had no idea on how to use it. I decided to take a different route and went with creating an Incident from the normal create an Incident function from the web GUI. I filled out the Incident with all the fields with all the data I wanted to use, to begin with, so I can backward engineer from there. After creating the incident I started the process of doing a “Retrieve a Record”. Get Record Inc

After clicking on Retrieve a record  (GET) on tableName find Incident. Then put in your Sys_ID. The Sys_ID is in the URL for the Incident. Sys_ID

The Sys_ID is a 32 Character ID that is located in the URL of the objects you are looking up. As you see above this one is for our Incident. Now that you have this info in, you need to scroll down a bit to the sysparm_fields. This is where you choose what info to get back from your Incident. Fileds to show

By default noting is in the Selected Colum out of lack of wanting to dig through the mess on the left I just normally highlight all and add them all. Then you don’t miss any of the fields that you may or may not want.

I leave the Formats in JSON. and then for this, I click the send button. But if you notice below the Send button in the Code Samples below. These are code samples are exactly what you just put in the fields above to retrieve the same info as you requested with the Send button. You can copy and paste the code and use it in your script. For example, this is the Powershell button.

Get INC PowerShell

But further this if you scroll past the send button and the code examples it will show you when the Send button did, and if it was successful. It will show the HTTP method call, you can just copy and paste that URL into a browser and get the data. Also, it shows that the Status of the code was 200 meaning all good. It would give you a 404 error and be in red if you had the wrong Sys_ID in there.

Get HTTP and junk

Going beyond that it will show you the best part. It will show you all your results from your query. Yes all those fields with what service now calls those fields and how they populate them. For me, I just copied the data and pasted it into a Notepad so I could reference it in building my Create Incident script. Response Body

From here there was more of an understanding of what fields are named and what data is expected in the area. And yes that long 32 character code is the Sys_ID for my user. But there are many more referenced in the ticket depending on what fields you populated. From here I felt confident on how to work my way through how to create an incident. After all, I had all the data I wanted to put in there. So go back to the top and choose to Create a record  (POST). Then select the table for Incident again.CreateInc Table

I just left the fields all default as all the data I cared about was below this. Looking below you see the Request Body area. This is where all the magic happens. If you click on “Add a Field” you a row of data you will fill.

Request Body

If you click on “Add a Field” you a row of data you will fill. When you do that you also see what is required in the data field. For example, “Caller” is looking for the Sys_ID code for the person calling this Incident. And Urgency is asking for an Integer, and “Close notes” is looking for a String. I also filled in “Assigned To” to show how it fills in the data below.

Request Body Filled

Once you have entered all your data you can scroll down to the bottom of the page. If you click the Send button it will create an incident with all the data you just put in and show you it all works or does not. But click on the Code Examples that you want to use. For me, it was PowerShell. Click on it and it will give you the code to do what you need to do.

Inc PowerShell Code Example

Here you can just copy all the code, paste it into an ISE window and run it. WRONG. you need to put in your creds is one thing. But there is a hidden JEM of an issue from the raw code. You will the below crap of missing a closing }. I tried to correct it and find a suitable place, but gave up. After some Google-Fu, I found an easy workaround was to just rebuild the Body variable into an array.

Powershell INC Error

Building an array was a pretty easy workaround and also made the code look cleaner. No longer was your body statement one really long line it was now going to be a list. For me, I commented out the existing body line and just started to create my new one below it so I could copy the data I needed from the line.

# Specify request body
$body = @{ #Create Body of the Post Request
caller_id= "29711cc64f2bd308feda99701310c727"
urgency= "2"
impact= "3"
priority= "4"
category= "Your Catagory Find from the drop down menu"
subcategory= "Find the subcategory from the list"
u_item= "request" #Check the Drop down for the options
short_description= "Short Description of the Incident"
description= "Description of the Incident"
work_notes= "Work Notes"
comments= "Additional Comments and Notes"

}
$bodyjson = $body | ConvertTo-Json

# Send HTTP request
$CreateServiceIncident = Invoke-WebRequest -Headers $headers -Method $method -Uri $uri -Body $bodyjson -ContentType "application/json"

With replacing the body of the script now all should work well for you. Make sure you do change the last part of the HTTP request to replace the existing body with

-Body $bodyjson -ContentType “application/json”

This will simplify the issues. Now you should be able to automate your ServiceNow incidents.

In conclusion, you should be able to apply this to the creation of Change tickets and much more. I will try to continue to post on this topic as it seems there Is a lot of lost info in this area. I do have some prebuilt Scripts for Creating an Incident and Updating an Incident located here.

 

Posted in Blogtober, CLI and Powershell, DevOps, Random Crap, Service Now | Tagged , , ,

Service Now Incident Creation and Updating with PowerShell

For those of you that are cursed or blessed by the use of ServiceNow, I have been working on a project to automate a ton of my day to day job. Part of this automation of the service Incidents. I spent a few painful hours messing around with the ServiceNow rest API’s. Keep in mind I am no developer and don’t know Rest but after enough trial SNDevand error, I managed to get something out of it. I thought it would be worth the effort to save you all some pain and anguish.

There are a few things you will need to make this productive. You will need to know the Sys_ID of your ServiceNow account, the Sys_ID of the Assignment Group and Service Offering. Also, remember that this also depends on your Incident Form and what your company has customized. For us, we have a few required fields so I had to make sure those were filled.

Finding Sys_IDs is easy once you figure out they are a 32 character code listed in the URL of the objects you are looking for. Same with your Incident’s.

First Open an existing incident with your name in it. On the right of your name is the “i” Click on it and then the “Open Record” button on the upper right-hand side. ChrisHil

This will open your User record in ServiceNow. In the URL you will see your Sys_ID. ChrisHSys_ID

You can do this for the rest of the other Sys_ID’s you need.

From there you just need to gather all the info that is required or you would like to use.

This is a basic script to fill out all the fields I needed for my use case. In this script, you need to edit the username and password. You can use encrypted if you like. You will need your ServiceNow URL and of course all your Sys_ID’s and info from the fields that have drop-down menus.

# Create New ServiceNow Incident
# Chris Hildebrandt
# 10-26-2018
# Ver 1.0
# Script will create a new ServiceNow Incident via Powershell
#______________________________________________________________________________________

#______________________________________________________________________________________
#ServiceNow creds
$user = "admin"
$pass = "admin"

# Build auth header
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $pass)))

# Set proper headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add('Authorization',('Basic {0}' -f $base64AuthInfo))
$headers.Add('Accept','application/json')
$headers.Add('Content-Type','application/json')

# Specify endpoint uri
$uri = "https://YOURSERVICENOW.service-now.com/api/now/table/incident"

# Specify HTTP method
$method = "post"

# Specify request body
$body = @{ #Create Body of the Post Request
    caller_id= "29711cc64f2bd308feda99701310c727"
    urgency= "2"
    impact= "3"
    priority= "4"
    contact_type= "email"
    notify= "2"
    watch_list= "29711cc64f2bd308feda99701310c727"
    service_offering= "Service Offering 32 Char Sys_ID"
    u_production_impact= "No"
    category= "Your Catagory Find from the drop down menu"
    subcategory= "Find the subcategory from the list"
    u_item= "request"   #Check the Drop down for the options
    assignment_group= "Assignment Group 32 Char Sys_ID"
    assigned_to= "29711cc64f2bd308feda99701310c727"
    short_description= "Short Description of the Incident"
    description= "Description of the Incident"
    work_notes= "Work Notes"
    comments= "Additional Comments and Notes"

}
$bodyjson = $body | ConvertTo-Json

# Send HTTP request
$CreateServiceIncident = Invoke-WebRequest -Headers $headers -Method $method -Uri $uri -Body $bodyjson -ContentType "application/json"

# Print response
$CreateServiceIncident.RawContent

 

This script will update an existing ServiceNow Incident. You will need the Sys_ID for the incident you are updating. That can be found in the URL of the incident.

Sys_ID

# Update Existing ServiceNow Incident

# Chris Hildebrandt

# 10-26-2018

# Ver 1.0

# Script will update existing ServiceNow Incident via Powershell

#______________________________________________________________________________________

#______________________________________________________________________________________

#ServiceNow creds

$user = "admin"

$pass = "admin"

# Build auth header

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $pass)))

# Set proper headers

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"

$headers.Add('Authorization',('Basic {0}' -f $base64AuthInfo))

$headers.Add('Accept','application/json')

$headers.Add('Content-Type','application/json')

# Specify endpoint uri

$uri = "https://YOURSERVICENOW.service-now.com/api/now/table/incident/YourINCIDENTSys_ID"

# Specify HTTP method

$method = "patch"

# Specify request body

$body = @{ #Create Body of the Post Request

work_notes="Update Work Notes"

close_notes="Your Close Notes"

}

$bodyjson = $body | ConvertTo-Json

# Send HTTP request

$response = Invoke-WebRequest -Headers $headers -Method $method -Uri $uri -Body $bodyjson -ContentType "application/json"

# Print response

$response.RawContent

 

This script you can add other fields if you like. For me, I was using Work Notes and Close Notes.

The Links for these Scripts are on my GitHub repo HERE. Along with a few other Scripts.

Posted in Blogtober, CLI and Powershell, DevOps, Service Now | Tagged , , | 2 Comments

Why automate day to day tasks VDI or other?

How many of you have never thought about automating any of the VDI tasks? Or think your environment is too small to automate? Or the best one of them all….I don’t have time to automate!

Slap….Wake up and smell the PowerCLI!

giphy[1]

At one point in time, I believed my environment was too small and I had no time to script. Wow was I wrong! Looking back that was the wrong way to be thinking. In reality, you should be thinking about how to be scripting everything. Even the simple things like create pool, or power on VM. You should really be scripting these for change control. Not only does it force you to do something the same way in a repeatable fashion but, it also creates an automatic record of what you did.

In the early years of my career I would write PowerShell scripts to create users, and groups, folders and stuff in Active Directory. But never dreamed of automating parts of Horizon. I really did not think there was away. Their kind of was but it was more of a hope and pray method a few years back. Not till recent code releases and PowerCLI began to mature did we get to open our wings and do more with it. There is still a ton to be desired with the PowerCLI interface for horizon but its growing quick.

It seems like it was just yesterday I was stumbling around trying to figure out how to make a linked clone pool or make an entitlement change. But really it kind of was. Once I realized how powerful it was to write small bits of PowerShell to create change documents it was so much simpler to document the process and show what you did. Not to mention the time savings as you have either learned how to do the task or you remember where you used it before.

So why write scripts at all? It saves you time, and effort in doing the actual task, not to mention it creates a repeatable process and documents the process for you in the process of writing the task out. And the more you do it the fast your become at pickup and creating new tasks.

My environments too small to automate! That’s BS. If you have to do a task more than once ever than its worth it. If you spend 10 mins figuring out how to create a new VDI pool would it not be worth it to save you 5 mins every time you have to do it from that point forward. Not to mention the above facts of your documentation.

I don’t have time to automate! I was once this person, and still am. But you know what, that’s when you take the time and set it aside, or create a fake meeting to write a few simple task out to free up 10 mins more of your day, and continue this process and create more and more to free up more time so you can take the time and build bigger and more complex tasks to free up more time. In turn, you are automating yourself into having more time to do more automation.

Over the last 8 months or so I have been working on a monster code to automate the update process of a master image for a VDI clone and then the recompose process. Really, it’s not a huge script or extremely complex but for me, it has been a huge learning experience for me. And the process through it has actually created time for me to write more of the code as I was able to use it in stages. The fruits of my labor and passion will, in turn, will save my company 100’s of Thousands of dollars a year in labor. And forced me to learn a ton in the process. More to come on that over the next few weeks.

Posted in Blogtober, CLI and Powershell, VDI | Tagged , , , ,