In this final post we will walk through an improved and more universal version of the first script. It is more about Powershell in general than about ImageBuilder, so it will definitely help if you are already somewhat familiar with Powershell. But even if this is not the case you can still benefit by just using the improved script as it is. It took me some time to write it, because - according to Powershell - I was an absolute beginner when starting. I learnt a lot while developing it, but it is probably still not perfect ...
You can just download a copy of the script and use it. For the curious here is the listing:
# # ESXi-Customizer-PS.ps1 - a script to build a customized ESXi installation ISO using ImageBuilder # Version: 1.0 # Author: Andreas Peetz ([email protected]) # param( [string]$obDir = $(Split-Path $MyInvocation.MyCommand.Path), [string]$isoDir = $(Split-Path $MyInvocation.MyCommand.Path), [switch]$hp = $false, [switch]$help = $false ) $AccLevel = @{"VMwareCertified" = 1; "VMwareAccepted" = 2; "PartnerSupported" = 3; "CommunitySupported" = 4} function AddVIB2Profile($vib) { if ($AccLevel[$vib.AcceptanceLevel.ToString()] -gt $AccLevel[$MyProfile.AcceptanceLevel.ToString()]) { write-host -nonewline (" [New AcceptanceLevel: " + $vib.AcceptanceLevel + "]") $MyProfile.AcceptanceLevel = $vib.AcceptanceLevel } Add-EsxSoftwarePackage -SoftwarePackage $vib -ImageProfile $MyProfile | Out-Null if ($?) { " [OK]" } else { " [FAILED]" } } # Write info and help if requested write-host "`nScript to build a customized ESXi installation ISO using ImageBuilder" if ($help) { write-host "Optional parameters:" write-host " -help : display this help" write-host " -obDir <dir> : directory of Offline bundles to add (default = script directory)" write-host " -isoDir <dir> : directory to store the customized ISO (default = script directory)" write-host " -hp : add packages from the HP VIBs Depot (default = no)`n" exit } else { write-host "(Call with -help for instructions)" } # Load the ImageBuilder Snapin (if not already loaded) if (!(Get-PSSnapin -name VMware.ImageBuilder -ErrorAction:SilentlyContinue)) { if (!(Add-PSSnapin -PassThru VMware.ImageBuilder)) { # Error out if loading fails write-host "FATAL ERROR: Cannot load the ImageBuilder Snapin. Is the PowerCLI installed?" exit } } # Add the VMware ESXi base depot write-host -nonewline "`nConnecting the VMware ESXi base depot ..." if ($baseDepot = Add-EsxSoftwareDepot https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml) { write-host " [OK]" } else { write-host "`n FATAL ERROR: Cannot add VMware base Online depot. Please check your internet connectivity and/or proxy settings!" exit } # Get the newest ImageProfile from the base depot $LatestIP = (Get-EsxImageProfile "ESXi-5.0.0-20*-standard" | Sort-Object -Descending Name)[0] write-host ("Using latest ImageProfile " + $LatestIP.Name) write-host ("(dated " + $LatestIP.CreationTime + ", AcceptanceLevel: " + $LatestIP.AcceptanceLevel + ",") write-host ($LatestIP.Description + ")") # Create your own Imageprofile $MyProfile = New-EsxImageProfile -CloneProfile $LatestIP -Name ($LatestIP.Name + "-customized") -Description ($LatestIP.Description + " + customizations") if ($hp) { # Add the HP VIBs depot write-host -nonewline "`nConnecting the HP Online Depot ..." if ($hpDepot = Add-EsxSoftwareDepot http://vibsdepot.hp.com) { write-host " [OK]" } else { write-host "`n FATAL ERROR: Cannot add HP Online depot. Please check your internet connectivity and/or proxy settings!" exit } $hpDepot.Channels[0] | Get-EsxSoftwarePackage | foreach { write-host -nonewline (" Add VIB " + $_.Name + $_.Version ) AddVIB2Profile $_ } } # Loop over Offline bundles write-host "`nAdding Offline bundles from" $obDir ... foreach ($oBundle in Get-Item $obDir\*.zip) { write-host -nonewline " Adding" $oBundle ... if ($ob = Add-EsxSoftwareDepot $oBundle) { write-host " [OK]" $ob.Channels[0] | Get-EsxSoftwarePackage | foreach { write-host -nonewline " Add VIB" $_.Name $_.Version AddVIB2Profile $_ } } else { write-host " [FAILED]`n Probably not a valid Offline bundle, ignoring." } } # Export the Imageprofile into an installation ISO file $isoFile = $isoDir + "\" + $MyProfile.Name + ".iso" write-host -nonewline ("`nExporting to ISO file " + $isoFile + ". Please be patient ...") Export-EsxImageProfile -ImageProfile $MyProfile -ExportToIso -FilePath $isoFile -Force if ($?) { " [OK]" } else { " [FAILED]" } write-host "`nAll done."Let's look at the script line by line:
Line 7 - 12: The script accepts command line parameters that are defined inside a param() statement. One of the possible parameters is the switch -help. If specified the script will print a help text (explaining the rest of the parameters) and exit (see line 25ff.). Another optional switch is -hp which will add the HP Online VIBs depot (s. line 65ff.). Using -obDir you can specify a directory where the script will look for Offline bundle zip files to be added. And with -isoDir you can specify the directory to store the created ISO file. The default for both directories is the path where the script itself is stored (which is determined by $(Split-Path $MyInvocation.MyCommand.Path)).
Line 14: One of the advanced Powershell features is using hash tables like the one that is created here. It contains the string representations of the four possible acceptance levels that a package or an image profile can have. They are assigned a ranking value (1 to 4) that is used to determine what the most restrictive acceptance level is ("VMwareCertified" = 1) as opposed to the least restrictive ("CommunitySupported" = 4).
Line 16 - 23: In these lines we define a Powershell function named AddVIB2Profile that adds a VIB package ($vib) that is passed as an argument to the custom image profile. As a first step it compares the acceptance level of the software package with that of the image profile (line 17) to determine if the latter needs to be lowered in order to accept the package (line 18 - 19). This is where the above mentioned hash table is used. Then it adds the package using the Add-EsxSoftwarePackage cmdlet. As I want the output of the script to be pretty and not garbled by useless information I pipe the output of the cmdlet into out-null. That means that it is just discarded. In line 22 I use the special Powershell variable $? to test whether the previous command was successful or not. This is a basic and the easiest way to add error handling to a Powershell script, and I will use that a lot here.
Line 25 - 36: This is actually the start of the main script. It prints a title line (line 26), then it will either display a help text and exit the script if -help was specified (line 27 - 33), or it will display only a short line explaining that -help can be used for instructions (line 35) and continue. BTW the special characters `n represent a new line when used in Powershell strings.
Line 39 to 45: Here we will check whether the required snapin VMware.ImageBuilder was already loaded (e.g. because you used the PowerCLI desktop shortcut to start your Powershell session). If not then we try to load it with Add-PSSnapin (line 40). If this fails (e.g. because PowerCLI is not installed on the computer) then the script errors out, because it depends on the ImageBuilder snapin being available and loaded.
Line 47 to 54: Now we add the VMware ESXi Online depot to the ImageBuilder session (also with some error handling). Nothing spectacular, we've seen this before.
Line 57 to 60: In line 57 we grab all standard image profiles from the VMware depot, create a sorted array of them and just pick the first one (with index [0]). This is the newest one, because we sorted the array in descending order. In the following lines we output some information about this image profile that is stored in its attributes.
Line 63: Here we create our custom image profile by cloning the latest one from the VMware depot. Its name and description are derived from the original VMware profile's properties.
Line 65 to 78: If the command line switch -hp was specified then we connect the HP Online VIBs depot to the ImageBuilder session (line 68 to 73) and add all included software packages using the AddVIB2Profile function that we defined at the beginning of the script.
Line 81 to 93: The foreach loop starting at line 82 is another essential part of the script code: Here we loop over all zip files that are located in the obDir directory and try to add them as Offline bundles to the ImageBuilder session (line 84). If it succeeds because a zip file is a valid Offline bundle (and not some other sort of file archive) then all software packages that are included in the bundle will be added to the custom image profile, again using our self-defined AddVIB2Profile function (line 88).
Line 96 to 99: Finally we export the custom image profile into an installation ISO. Its file name is derived from the image profile's name.
How do you run this Powershell script (and others)?
Open a plain Powershell window from the Start menu, or use the PowerCLI desktop shortcut to start an already customized Powershell session.
By default Powershell will only execute scripts that were electronically signed for security reasons. This script (and most other useful scripts that you will find in other places) is not signed, so you will need to relax the security check by using the Set-ExecutionPolicy cmdlet like shown in the following screenshot. You can do this for the current user only by specifying -Scope CurrentUser. This will also work if you do not have administrative permissions on the computer. If you have administrative permissions then you can leave the -Scope parameter and make the setting system global. Setting the execution policy needs to be done only once - it will be saved to the registry and reused for future Powershell sessions.
You can just call the script by its name (adding parameters as required). Since the script is from an "untrusted" source you still need to confirm its execution every time you start it:
ESXi-Customizer-PS help screen |
ESXi-Customizer-PS example run |
Update (2012-06-07): In the meantime I updated this script to fix errors. Please watch out for the latest version using this download link!