Showing posts with label xml. Show all posts
Showing posts with label xml. Show all posts

Wednesday, February 1, 2012

Dell components check for updates via powershell (remote machine SUU)

Yesterday I posted on my XPath learning that I was going through while playing around with the Dell SUU catalog.xml file.  After further coding today, I threw together a good functional prototype of a powershell script to run SUU checks on remote machine.  It will find the upgradable components for the target machine, and return details like this:

Component      : FlashBIOS Updates
path           : PE2850_BIOS_WIN_A07.EXE
vendorVersion  : A07
currentversion : A05
releaseDate    : May 23, 2008
Criticality    : Optional
AtCurrent      : False

Component      : Embedded Server Management
path           : BMC_FRMW_WIN_R223079.EXE
vendorVersion  : 1.83
currentversion : 1.52
releaseDate    : June 30, 2009
Criticality    : Optional
AtCurrent      : False

for all firmware, bios, and drivers (probably OMSA too).  The AtCurrent value is a true/false test to show if you are at the current level (current to your version of SUU that you are using).  The script takes a server name and path (to your catalog.xml file in the suu\repository folder), and remotely checks the machine.  This works for windows machines only, since it uses WMI.  I'm sure some method of scripting using omreport data could be used to due similiar work for Linux.  Some ideas for using this information for updating, take the file name returned in each component, copy the file from the repository to the remote machine and run the installs with the silent run switch.



#Requires -version 2
#Author: Nathan Linley
#Script: Computer-DellUpdates
#Date: 2/9/2012

param(
 [parameter(mandatory=$true)][ValidateScript({test-path $_ -pathtype 'leaf'})][string]$catalogpath,
 [parameter(mandatory=$true,ValueFromPipeline=$true)][string]$server
)

function changedatacase([string]$str) {
 #we need to change things like this:  subDeviceID="1f17" to subDeviceID="1F17"
 #without changing case of the portion before the =
 if ($str -match "`=`"") {
  $myparts = $str.split("=")
  $result = $myparts[0] + "=" + $myparts[1].toupper()
  return $result
 } else { return $str}
}

$catalog = [xml](get-Content $catalogpath)
$oscodeid = &{
 $caption = (Get-WmiObject win32_operatingsystem -ComputerName $server).caption
 if ($caption -match "2003") {
  if ($caption -match "x64") { "WX64E" } else { "WNET2"}
 } elseif ($caption -match "2008 R2") { 
  "W8R2" 
 } elseif ($caption -match "2008" ) {
   if ($caption -match "x64") { 
    "WSSP2" 
   } else {
    "LHS86"
   } 
 }
}
write-debug $oscodeid

$systemID = (Get-WmiObject -Namespace "root\cimv2\dell" -query "Select Systemid from Dell_CMInventory" -ComputerName $server).systemid
$model = (Get-WmiObject -Namespace "root\cimv2\dell" -query "select Model from Dell_chassis" -ComputerName $server).Model
$model = $model.replace("PowerEdge","PE").replace("PowerVault","PV").split(" ")   #model[0] = Brand Prefix  #model[1] = Model #

$devices = Get-WmiObject -Namespace "root\cimv2\dell" -Class dell_cmdeviceapplication -ComputerName $server
foreach ($dev in $devices) {
 $xpathstr = $parts = $version = ""
 if ($dev.Dependent -match "(version=`")([A-Z\d.-]+)`"") { $version = $matches[2] } else { $version = "unknown" }
 $parts = $dev.Antecedent.split(",")
 for ($i = 2; $i -lt 6; $i++) {
  $parts[$i] = &changedatacase $parts[$i]
 }
 $depparts = $dev.dependent.split(",")
 $componentType = $depparts[0].substring($depparts[0].indexof('"'))
 Write-Debug $parts[1]
 if ($dev.Antecedent -match 'componentID=""') {
  $xpathstr = "//SoftwareComponent[@packageType='LWXP']/SupportedDevices/Device/PCIInfo"
  if ($componentType -match "DRVR") {
   $xpathstr += "[@" + $parts[2] + " and @" + $parts[3] + "]/../../.."
   $xpathstr += "/SupportedOperatingSystems/OperatingSystem[@osVendor=`'Microsoft`' and @osCode=`'" + $osCodeID + "`']/../.."
  } else {
   $xpathstr += "[@" + $parts[2] + " and @" + $parts[3] + " and @" + $parts[4] + " and @" + $parts[5] + "]/../../.."
   #$xpathstr += "/SupportedSystems/Brand[@prefix=`'" + $model[0] + "`']/Model[@systemID=`'" + $systemID + "`']/../../.."
   $xpathstr += "/ComponentType[@value='FRMW']/.."
   
  }
  $xpathstr += "/ComponentType[@value=" + $componentType + "]/.."
 } else {
  $xpathstr = "//SoftwareComponent[@packageType='LWXP']/SupportedDevices/Device[@" 
  $xpathstr += $parts[0].substring($parts[0].indexof("componentID"))
  $xpathstr += "]/../../SupportedSystems/Brand[@prefix=`'" + $model[0] + "`']/Model[@systemID=`'"
  $xpathstr += $systemID + "`']/../../.."
 }
 Write-Debug $xpathstr
 
 $result = Select-Xml $catalog -XPath $xpathstr |Select-Object -ExpandProperty Node
 $result |Select-Object @{Name="Component";Expression = {$_.category.display."#cdata-section"}},path,vendorversion,@{Name="currentversion"; Expression = {$version}},releasedate,@{Name="Criticality"; Expression={($_.Criticality.display."#cdata-section").substring(0,$_.Criticality.display."#cdata-section".indexof("-"))}},@{Name="AtCurrent";Expression = {$_.vendorVersion -le $version}}
}

Tuesday, January 31, 2012

Powershell XML XPATH search example (Dell SUU)

Over the last few years, I have taken a few shots at using powershell's XML features to do some automating of the Dell SUU update system.  In the past, I had some vaguely working prototypes that worked on one system and didn't work on another.  After taking another look at it, I discovered the use of Xpath to help match up available updates for a system.  In the SUU CD/DVD sets, you will find a Catalog.xml file in the Repository folder.  This file contains SoftwareComponents and SoftwareBundle branches.  The Bundle nodes are collections of OS + Device Model information to provide a full list of all updates.  The SoftwareComponents get into the individual updates themselves + OS + SupportedDevices.  Using Dell's WMI extensions (installed with OMSA 4.? and higher); namespace: root\CIMV2\Dell and class Dell_CMDevice to get information about the on board devices.  Each entry in this Class has a deviceID, vendorID, subDeviceID and subVendorID which can be used as an XPath search in the catalog file for the latest update for that component.

Here's an example of getting started with this:

$catalog = [xml](get-content c:\temp\suu\repository\catalog.xml)
$devices = Get-wmiobject -namespace "root\cimv2\dell" -class Dell_cmdevice
$mydevice = $devices[0]
$xpathstr = "//SoftwareComponent[@packageType='LWXP']/SupportedDevices/Device/PCIInfo"
$xpathstr += "[@deviceID=`'" + $mydevice.deviceID + "`' and @vendorID=`'" + $mydevice.vendorID +"`' and @subDeviceID=`'" + $mydevice.subDeviceID + "`' and @subVendorID=`'" + $mydevice.subvendorID + "`']/../../.."
select-xml $catalog -xpath $xpathstr |select-object -expandproperty Node

This will give you something like this:

schemaVersion        : 1.0
packageID              : R222914
releaseID                : R222914
hashMD5                : 6944D638979E5CE651234D216AFDC3C7
path                         : RAC_FRMW_WIN_R222914.EXE
dateTime                  : 2009-06-30T14:33:14-05:00
releaseDate              : June 30, 2009
vendorVersion          : 1.75
dellVersion               : A01
packageType           : LWXP
Name                      : Name
ComponentType      : ComponentType
Description              : Description
LUCategory            : LUCategory
Category                 : Category
SupportedDevices   : SupportedDevices
ImportantInfo           : ImportantInfo
Criticality                 : Criticality

As you can see, the device that is being check is a RAC card.  This is the latest update package for it.  You can use other classes in the Dell WMI namespace to pull the current version details of your devices to compare it to what is available in the SUU repository.  This part its a bit hackish though as you need to look at Dell_CMDeviceApplication and pull data out of the middle of strings, or combine Dell_CMDeviceApplication with Dell_CMApplication class results to get an easier version number.  The Dell_CMDeviceApplication class seems to just bridge between two different classes giving data like this:

Antecedent       : //Server/root/cimv2/dell:Dell_CMDevice.componentID="
                   ",name="Dell Remote Access Controller 4/I",vendorID="1028",d
                   eviceID="0012",subDeviceID="0012",subVendorID="1028",bus="",
                   device="",function=""
Dependent        : //Server/root/cimv2/dell:Dell_CMApplication.componen
                   tType="FRMW",subComponentID="",version="1.35",name="Dell Rem
                   ote Access Controller 4/I Firmware",deviceKey=":Dell Remote
                   Access Controller 4/I:1028:0012:0012:1028:::"

In the future, I will pull this together a bit more and try to provide a working SUU check for all devices on a Dell system along with update options.  Update: Solution sample