Get Dell ESX host warranty info via PowerCLI version 3

Had a script that was doing a screen scrape of Dell's support page for warranty info.  Now they require a log in.  So it was time to finally revise my script to use Dell's wsdl (SOAP) interface.


I was able to simplify the script a bit using the code provided by Jon Gurgul to pull from Dell's provided SOAP service.  I copied the code into a Get-DellAssetInformation.psm1 file so I could call the function as a module.

The variable you should probably update is the $ServiceDescription variable to match the warranty type you expect from your boxes so you get an actual return of data.

I simply plugged this into my existing code removing the screen scrape code and this is what I ended up with:


Add-PSsnapin VMware.VimAutomation.Core
#Module code courtesy of Jon Gurgul
Import-Module C:\myModuleDirectory\Get-DellAssetInformation.psm1 $VIServer = Connect-VIServer myvCenterServer $date = Get-Date $htmpath = "C:\inetpub\wwwroot\" $csvpath = "C:\inetpub\wwwroot\csv\" $htmname = "VMHostInvReport.htm" $csvname = "VMHostInvReport.csv"
#You can find out what service descriptions are available by using calling the Get-DellAssetInformation module and seeing what ones are available to you. Like so:
#[xml]$AssetInfo = Get-DellAssetInformation servicetagname
#$AssetInfo.ArrayOfAsset.Asset.entitlements.entitlementdata | select ServiceLevelDescription
$ServiceDescription  = "4HR"

#Report Title appears in <title> section and shows in the browser window.
$ReportTitle     = "VM/ESX Host Inventory Data"

#IconPath is the icon that is rendered on supported web browsers tab or address bar
$IconPath        = "/images/mySuperAwesomeIcon.ico"

#AppleIconType, set this to "Apple-touch-icon" if you would like the iOS device to render a glass effect on top of your custom icon.
#Otherwise use "Apple-touch-icon-precomposed" to just use your stock image.  45x45 is recommended, but higher rez can be used.
$AppleIconType     = "apple-touch-icon-precomposed"

#AppleTouchIcon is the image that appears on an iOS and/or Android device when a home screen bookmark is created.
$AppleTouchIcon = "/images/apple-touch-icon.png"

#Stylesheet is the path where your CSS file lies.
$Stylesheet        = "./styles/style.css"

#SortScript is where the sorttable.js script resides.  This allows dynamic sorting of table information within the browser.
$SortScript     = "./scripts/sorttable.js"

#Used to generate encrypted xml password file
#New-VICredentialStoreItem -Host doesntreallymatter -User root -Password "" -File "C:\CredentialStore\yourESXiRootCreds.xml"
#xml is only valid w/ the account that created the xml file, so create it with the service account you plan to run w/ this.
$Creds = Get-VICredentialStoreItem -File C:\CredentialStore\yourESXiRootCreds.xml
$ESXServers = Get-VMHost -Server $VIServer
$ESXServerView = @()
$Count = $ESXServers.Count
While ($Count -gt 0)
$Count = $Count - 1
$VIESXHost = Connect-VIServer $ESXServers[($Count)].Name -User $Creds.User -Password $Creds.Password
If ($? -ne $true){}
Else{$ESXServerView += Get-VMHost -Server $VIESXHost | Get-View}
Disconnect-VIServer -Server $VIESXHost -Confirm:$false
#$ESXServerView = $ESXServers | Get-View
#$ServiceTagList = foreach($VMHost in $ESXServerView){($VMHost.hardware.systeminfo.OtherIdentifyingInfo | where {$_.IdentifierType.Key -eq "servicetag"}).identifierValue}
$ESXInfo = @()

Foreach ($ESX in $ESXServers){
$TargetESXServerView = $ESXServerView | where {$_.Name -eq $ESX.Name}
$NewObj         = "" | Select Cluster, Name, Model, Version, BIOs, ServiceTag, AssetTag, ShipDate, ExpiryDate
$NewObj.Cluster = $ESX.Parent.Name
$NewObj.Name    = $ESX.Name
$NewObj.Model    = $ESX.Model
$NewObj.Version    = $ESX.Version
$NewObj.BIOs    = (($TargetESXServerView.Runtime.HealthSystemRuntime.SystemHealthInfo.NumericSensorInfo | where {$_.Name -like "*BIOS*"  -and $_.SensorType -eq "Software Components"}).Name) -replace(".* BIOS ","") -replace(" .*","")
$NewObj.ServiceTag     = ($TargetESXServerView.hardware.systeminfo.OtherIdentifyingInfo | where {$_.IdentifierType.Key -eq "servicetag"}).identifierValue -replace(" ","")
$NewObj.AssetTag    = ($TargetESXServerView.hardware.systeminfo.OtherIdentifyingInfo | where {$_.IdentifierType.Key -eq "assettag"}).identifierValue -replace(" ","")

## Gets ServiceTag Info from Dell
$ServiceTag = $null
If ($NewObj.ServiceTag -eq $null -or $NewObj.ServiceTag -eq "unknown" -or $NewObj.ServiceTag -eq "") {$ServiceTag = $NewObj.AssetTag} Else {$ServiceTag = $NewObj.ServiceTag}

[xml]$AssetInfo = Get-DellAssetInformation $ServiceTag
$Warranty = $null
If ($Warranty -ne $null -or $Warranty -eq " " -and $ESX.Manufacturer -match "Dell"){$Warranty = "Expired"}
$Warranty = $AssetInfo.ArrayOfAsset.Asset.entitlements.entitlementdata | where {$_.DaysLeft -gt "0" -and $_.ServiceLevelDescription -match "$($ServiceDescription)" -and $_.EntitlementType -match "Active"}

$ShipDate = ([datetime]$AssetInfo.ArrayOfAsset.Asset.AssetHeaderData.SystemShipDate).toShortDateString()
$EndDate = ([datetime]$Warranty.EndDate).toShortDateString()

If ($Warranty -ne "Expired")
If ([int]$Warranty.DaysLeft -lt "15") {$EndDateHTM = "<p style=`"font-weight:bold;color:red`">$($EndDate)</p>"}
ElseIf ([int]$Warranty.DaysLeft -lt "90") {$EndDateHTM = "<p style=`"font-weight:bold;color:orange`">$($EndDate)</p>"}
ElseIf ([int]$Warranty.DaysLeft -gt "90") {$EndDateHTM = $EndDate}
If ($Warranty -eq "Expired") {$EndDateHTM = "<p style=`"font-weight:bold;color:red`">$($Warranty)</p>"}
$NewObj.ShipDate = $ShipDate $NewObj.ExpiryDate = $EndDateHTM $ESXInfo += $NewObj $ShipDate = $null $EndDate = $null $EndDateHTM = $null } $Head = "<LINK REL=`"SHORTCUT ICON`" HREF=`"$($IconPath)`"><link rel=`"$($AppleIconType)`" href=`"$($AppleTouchIcon)`"/><title>$($ReportTitle)</title><link rel=`"stylesheet`" type=`"text/css`" href=`"$($Stylesheet)`"><script src=`"$($SortScript)`"></script>" $ESXInfo | ConvertTo-Html –body "<a name=`"Data`"></a><strong>$ReportTitle $date</strong> <br><a href=./csv/$($csvname)>(Click here to download csv copy)</a>" -head "$($Head)" | foreach {$_.replace("&lt;","<").replace("&gt;",">").replace("<tr><th>","<table class=`"sortable`"><thead><tr><th>").replace("</th></tr>","</th></tr></thead><tbody>").replace("</table>","</tbody><tfoot></tfoot></table>").replace("&quot;","`"")} | Out-File -Encoding ASCII -FilePath "$($htmpath)$($htmname)" $ESXInfo | convertto-csv -NoTypeInformation | foreach {$_ -replace("<p style=`"`"font-weight:bold;color:orange`"`">","") -replace("<p style=`"`"font-weight:bold;color:red`"`">","") -replace("</p>","")} | Out-File -Encoding ASCII -FilePath "$($csvpath)$($csvname)"

Disconnect-VIServer -Confirm:$false -Server $VIServer

Auto-Remediation vCenter Alarm

I've been dealing w/ issues on Emulex OCe11102-FM logging out of the vSAN Fabric and not recovering.

Long story short, it's been a firmware problem and I was able to get a alpha firmware that fixed the issue.

In the meantime, I had created a PowerCLI script to auto-remediate every hour if a degraded path was detected.  I wasn't fond of the solution, so I looked to vCenter alarms to see if I could have them do it for me.  Turns out they can, but there are caveats to this approach.

What follows is an example of how to set something like this up and details specific to the errors/configuration I was dealing with.

SOAP(y) Powershell fun w/ BT Diamond's IPAM (Part 2)

Since my initial attempt using New-WebServiceProxy failed because it didn't like the XML return from IPControl, I needed to find out why.  This is where I downloaded SOAPUI to dig in and find out why.  More importantly, I found that I could use the info from it to plug into the Invoke-WebRequest cmdlet.

[I'm going to be using Dell's web service as an example simply because it's easier from an example standpoint.  Dell's service actually works w/ the New-WebServiceProxy cmdlet.  The basic concept of what I'm doing is the exact same though.]

SOAP(y) Powershell fun w/ BT Diamond's IPAM (Part 1)

  1. API Access
  2. Powershell 2.0 +
    1. I'm using 3.0 now.  I assume these examples work in 2.0 as well, but I'm too lazy to test.
This was a bit of an interesting exercise for me since I've mostly only ever used cmdlets.  I'm still using cmdlets, but calling SOAP based web services to gather information.

Here is what I've been experimenting with:
#Credentials are needed when working w/ a secure web service.
$Creds = Get-Credential

#I was able to find the correct API address by clicking the help link on the login page.  They seem to have a different web service per API instruction type.  In this case, I just want to 'get' address information thusly demonstrated below.
$IPControlGetService = New-WebServiceProxy "https://myIPControlServerNameorIP/inc-ws/services/Gets?wsdl" -Credential $creds

#This is where it gets interesting, from here I can essentially browse what properties and methods are available to me by calling the $IPControlGetService variable.
#This provides me a list of properties and methods I can call against this SOAP service.
$IPControlGetService | get-member

The downside, I was unable to successfully receive a valid xml response from IPControl that Powershell's New-WebServiceProxy cmdlet liked.  Error:
Exception calling "getDeviceByHostname" with "1" argument(s): "There is an error in XML document (1, 2947)."

Long story short, it appears to be related to the xml return 'style' being 'RPC' rather than 'Document', but I cannot say for certain.  I only noticed this while using SOAPUI to see the returned xml and noticing the 'style' property compared to that of Dell's web service.

To be continued in Part 2...Using SOAPUI and Powershell's Invoke-WebRequest cmdlet...

RacADM, Powershell, and Kerberos KeyTabs

I was looking to automate configuration of iDRAC's (Dell Remote Admin Console) synonymous w/ iLOM and many other acronyms.  I also wanted to enable domain authentication in a somewhat secure manner.  By using a kerberos keytag, I'm able to in the very least obfuscate the username and password into a file for upload into the iDRAC.  What follows is a journey into a ridiculous realm.


  2. ktpass
  3. Powershell 3.0 (2.0 probably works too, but I was using 3.0 @ the time)
  4. Your root CA's cert
    1. This is so it AD Authentication can be setup
It's not a complete solution, but hopefully it'll help you get started in your own endeavors.  Below assumes the iDRAC has been configured and is available on the network in default config.

To generate a kerbero's keytab, you simply need the name and password of a service account (this is simply a Active Directory user account) in your domain.

ktpass /pass ReallySecurePas5word /ptype KRB5_NT_PRINCIPAL /princ /out C:\directoryofyourchoice\aNameThatMakesSense.keytab

$IPAddress=""  #This would be the IP of your iDRAC.
$DNS1=""  #These are google's DNS and likely don't know about your AD so don't use these.
$myDomainName="" #If it's not obvious, you want to change this to something appropriate to you.
$myRootDomain="" # mydomainname and rootdomain may be the same, iDRAC uses this to look up a list of domain controllers defined as GC's
$nameofADGroup="domain admins" # You want to populate this a domain group that you want to have admin rights to the iDRAC.
$RootCALocation="C:\certs\myDomainsCA.cer"  # If you don't have this, you can forego it, but your authentication calls to AD will be unencrypted.
$EnableCertValidation="Enabled" #Disable this if you don't upload a root CA cert.  "Disabled" is valid
$TimeZone="US/Eastern"  # You can check the GUI to see what options would be valid.
$iDracSchema="2" # 2 means that your Active Directory has not been extended w/ Dell's Schema.  If it has you can change this to 1, but I don't know if there other things you need to configure.

Write-Host "Disabling annoying error message" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.Tuning.DefaultCredentialWarning Disabled

Write-Host "Uploading RootCA Cert" -ForegroundColor:Green
# The '-t 2' portion is specifying that you are uploading 
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin sslcertupload -f $RootCALocation -t 2
Write-Host "Uploading Kerberos KeyTab File" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin krbkeytabupload -f $KeyTabLocation

Write-Host "Configuring TimeZone" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.Time.Timezone "$($TimeZone)"

Write-Host "Configuring NTP" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.NTPConfigGroup.NTP1 $NTP1
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.NTPConfigGroup.NTP2 $NTP2
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.NTPConfigGroup.NTPEnable Enabled

Write-Host "Configuration AD User Domain" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.UserDomain.1.Name $myDomainName

Write-Host "Configuring Enable DNS from DHCP (Needed for AD Configuration)" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.IPv4.DNSFromDHCP Enabled
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.IPv4Static.DNS1 $DNS1
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.IPv4Static.DNS2 $DNS2

Write-Host "Sorry waiting 15 seconds to make sure AD recognizes configured DNS settings." -ForegroundColor:Green
Start-Sleep -Seconds 15

Write-Host "Configuring Active Directory Authentication" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.CertValidationEnable Enabled
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.DCLookupByUserDomain Enabled
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.DCLookupEnable Enabled
# These particular options rely upon DNS to work and setting them prior to DNS recognition causes an error.
$count = 0
While ($? -ne $true -and $count -lt 5){
$count ++
Write-Host "Sorry, I seem to have failed in setting the DC Lookup Option.  Trying again, Try count: $($count)" -ForegroundColor:Yellow
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.DCLookupEnable Enabled
If ($? -ne $true -and $count -eq 5){Write-Host "Unfortunately, I was unable to successfully enable Active Directory Domain Controller lookup.  Please do so manually." -ForegroundColor:Red }
Start-Sleep -Seconds 5
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.GCLookupEnable Enabled
# These particular options rely upon DNS to work and setting them prior to DNS recognition causes an error.
$count = 0
While ($? -ne $true -and $count -lt 5){
$count ++
Write-Host "Sorry, I seem to have failed in setting the GC Lookup Option.  Trying again, Try count: $($count)" -ForegroundColor:Yellow
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.GCLookupEnable Enabled
If ($? -ne $true -and $count -eq 5){Write-Host "Unfortunately, I was unable to successfully enable Active Directory Global Catalog lookup.  Please do so manually." -ForegroundColor:Red }
Start-Sleep -Seconds 5
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.GCRootDomain $myRootDomain
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.Schema 2
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.SSOEnable Enabled
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ActiveDirectory.Enable Enabled

Write-Host "Configuring Active Directory Group" -ForegroundColor:Green
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ADGroup.1.Domain $myDomainName
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ADGroup.1.Name $nameofADGroup
& 'C:\Program Files\Dell\SysMgt\rac5\racadm.exe' -r $IPAddress -u root -p calvin set iDRAC.ADGroup.1.Privilege 0x1ff