While Content Libraries are becoming more and more used, there are still some features that are not yet implemented in PowerCLI. So is it for example not possible to mount an ISO file located in a Content Library on a VM. The Set-CDDrive cmdlet is currently lacking this functionality, while the Web Client offers this option.
Like often, and one of the VMware PowerCLI features I absolutely like, when a cmdlet is missing a feature, you can fall back on the API to solve the issue.
Introduction
Like so often, the reason I had a closer look at this issue was due to a question in PowerCLI Community on VMTN.
My first step in such cases is always to have a look at the vSphere Web Services API.
But unfortunately, the ReconfigVM_Task method documentation didn’t make me any wiser. There is apparently no object, property, or method to mount an ISO from a Content Library onto a VM.
In the next step I had a look at the vSphere REST API Reference. But in there I could also not find anything specific about Content Library ISOs and VM CD drives.
When all else fails, look at the code!
And with Code Capture we have just that option!
The first thing I noticed while looking at the generated code, there are no ‘special’ object, properties, or method used. Just a plain ReconfigVM_Task call with an edit action on the CD drive device.
The only special feature was the value in the FileName property.
That value definitely pointed to the ISO file in the Content Library. At first I tried to compose that value by hand/script. But it turned out that some parts of the value were not obtainable via normal ways.
I found out then when I use the vimdatastore provider, the returned FullDatastorePath contained exactly the value I neededd.
The Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
function Set-CDDriveCLIso { <# .SYNOPSIS Mount an ISO from a Content Library .DESCRIPTION This function will mount an ISO located on a Content Library on a CDDrive of a VM .NOTES Author: Luc Dekens Version: 1.0 24/12/20 Initial release .PARAMETER VM Specifies the virtual machines on whose guest operating systems you want to run the script. .PARAMETER CDDrive Specifies the CDDrive on which the ISO will be mounted .PARAMETER ContentLibrary Specifies the Content Library on which the ISO is located. .PARAMETER ContentLibraryIso Specifies the ISO item on the Content Library .EXAMPLE $cl = Get-ContentLibrary -Name MyCL $iso = Get-ContentLibraryItem -ContentLibrary $cl -Name MyISO Get-VM -Name 'MyVM' | Get-CDDrive -Name 'CD/DVD drive 0' | Set-CDDriveCLIso -ContentLibraryIso $iso -Confirm:$false .EXAMPLE $cd = Get-VM -Name MyVM | Get-CDDrive Set-CDDriveCLIso -CDDrive $cd -ContentLibraryIso $iso -Confirm:$false #> [cmdletbinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [parameter(Mandatory = $true, ValueFromPipeline = $true)] [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.CDDrive]$CDDrive, [parameter(Mandatory = $true)] [VMware.VimAutomation.ViCore.Types.V1.ContentLibrary.ContentLibraryItem]$ContentLibraryISO ) $target = "VM:$($CDDrive.Parent.Name) CD:$($CDDrive.Name)" $action = "Mount ISO $($ContentLibraryISO.Name) from $($ContentLibraryISO.ContentLibrary.Name)" if ($PSCmdlet.ShouldProcess($target, $action)) { $driveName = -join ((65..90) | Get-Random -Count 3 | ForEach-Object -Process { [char]$_ }) $filter = "$($ContentLibraryISO.Name)*.iso" $ds = Get-Datastore -Name $ContentLibraryISO.ContentLibrary.Datastore New-PSDrive -Name $driveName -PSProvider VimDatastore -Root '\' -Location $ds | Out-Null $clPath = Get-ChildItem -Path "$($driveName):" -Filter "$($ContentLibraryIso.Id)" -Recurse | Select-Object -ExpandProperty FolderPath $isoPath = Get-ChildItem -Path "$($driveName):\$($clPath.Split(' ')[1])" -Filter $filter -Recurse | Select-Object -ExpandProperty DatastoreFullPath Remove-PSDrive -Name $driveName -Confirm:$false | Out-Null $spec = New-Object VMware.Vim.VirtualMachineConfigSpec $change = New-Object VMware.Vim.VirtualDeviceConfigSpec $change.Operation = [Vmware.vim.VirtualDeviceConfigSpecOperation]::edit $dev = $cd.ExtensionData $dev.Backing = New-Object VMware.Vim.VirtualCdromIsoBackingInfo $dev.Backing.FileName = $isoPath $change.Device += $dev $change.Device.Connectable.Connected = $true $spec.DeviceChange = $change $vm.ExtensionData.ReconfigVM($spec) Get-CDDrive -Id $CDDrive.Id } } |
Annotations
Line 34-37: The parameters that the function requires are objects returned by the Get-CDDrive and Get-ContentLibraryItem cmdlets. The function does not implement OBN support.
Line 40-41: This provides meaningful content for the message returned when the WhatIf switch is used.
Line 44-46: To avoid conflicts with PSDrives the user might already have defined, the function generates a 3-letter, random string that will be used as the drivename.
Line 52-53: To avoid a situation where the same ISO file might be uploaded to two different Content Libraries, the function first finds the path to the folder that corresponds with the requested Content Library.
Line 54-55: This search finds the actual path to the desired ISO file.
Line 60-72: A ‘regular’ call to the ReconfigVM_Task method.
Line 74: The function returns the CDDrive object, just like the regular Set-CDDrive cmdlet does. But since there is currently not yet support for ISO files from a Content Library, the filepath looks like a regular path to an ISO file. The Web Client does show that this is an ISO from a Content Library.
Sample Run
Using the function is rather straightforward.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$vmName = 'photonps' $cdName = 'CD/DVD drive 1' $cLibName = 'ConLib1' $cLibItemName = 'photon-minimal-3.0-a0f216d' $vm = Get-VM -Name $vmName $cl = Get-ContentLibrary -Name $cLibName $iso = Get-ContentLibraryItem -Name $cLibItemName -ContentLibrary $cl Get-CDDrive -VM $vm -Name $cdName | Set-CDDriveCLISO -ContentLibraryISO $iso -Confirm:$false |
The Web Client shows that an ISO from a Content Library is loaded.
Enjoy!
Lucas
OK, I figured out the backing issues, there were multiple ISOs of the same name in some different folders. After cleaning those up I can get most of the script to work and now it’s working and I even got it to flow through a foreach array.
Lucas
Have you had any issues trying to run this on vSphere 7.0.3g? I keep getting errors with the property ‘Backing’ not being found, or the subsequent ‘filename’ after that.
LucD
Strange.
Can you post the complete error message you are getting?
Lucas
Here’s the error, I get it running against one machine or multiple:
The property ‘Backing’ cannot be found on this object. Verify that the property exists and can be set.
At line:55 char:1
+ $dev.Backing = New-Object VMware.Vim.VirtualCdromIsoBackingInfo
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
The property ‘FileName’ cannot be found on this object. Verify that the property exists and can be set.
At line:56 char:1
+ $dev.Backing.FileName = $isoPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
The property ‘Connected’ cannot be found on this object. Verify that the property exists and can be set.
At line:58 char:1
+ $change.Device.Connectable.Connected = $true
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
You cannot call a method on a null-valued expression.
At line:60 char:1
+ $vm.ExtensionData.ReconfigVM($spec)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Abul Ahmed
Thanks heaps. makes some of tasks so easy.