We used a content library repo to hold our iso and template. I am able to mount OS iso during VM creation without issue, something like this
$ConLibName = 'Repo'
$strSQLiso = 'en_win_server_2016_standard_x64_dvd_8701871'
$VMiso = Get-ContentLibraryItem -Name $strSQLiso
VMware.VimAutomation.Core\Get-VM -Name $strVMName | New-CDDrive -ContentLibraryIso $VMiso -Verbose
However, this doesn't seem to work on a power-on VM . (trying to do a SQL install) due to a power-on state
New-CDDrive : 12/11/2020 10:32:35 AM New-CDDrive com.vmware.vapi.std.errors.not_allowed_in_current_state {'messages':
[com.vmware.vapi.std.localizable_message {'id': com.vmware.vdcs.iso-main.invalid_power_state_mount, 'default_message': The
library item (en_sql_server_2016_standard_x64_dvd_8701871) cannot be mounted on the virtual machine (SQL) in the current
state: poweredOn. The virtual machine must be in the state: poweredOff., 'args':
However, I can't use the set-cddrive cmdlet either as it doesn't seem to work with content library.
Any suggestion or new approach would be appreciated
I did some further exploring, the following snippet seems to work for me, in all situations.
$vmName = 'MyVM'
$cLibName = 'MyCl'
$cLibItemName = 'SomeIso' # The Name as it appears in the CL
$vm = Get-VM -Name $vmName
$cd = Get-CDDrive -VM $vm
$clib = Get-ContentLibrary -Name $cLibName
$ds = Get-Datastore -Name $clib.Datastore
New-PSDrive -Name DS -PSProvider VimDatastore -Root '\' -Location $ds | Out-Null
$isoPath = Get-ChildItem -Path "DS:" -Recurse -Filter "$($cLibItemName)*.iso" | Select -ExpandProperty DatastoreFullPath
Remove-PSDrive -Name DS -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)
The difference is that I get the path of the ISO in the Content Library via the VimDatastore provider.
Apparently, the name has to have the UUID of the file in the path used.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That functionality is currently not supported by the cmdlets.
But you can use the API method.
The drawback is that the ISO will be marked as a Datastore ISO, not a Content Library ISO
$vmName = 'MyVM'
$cLibName = 'MyCL'
$cLibItemName = 'someISO' # The Name as it appears in the CL
$vm = Get-VM -Name $vmName
$cd = Get-CDDrive -VM $vm
$clib = Get-ContentLibrary -Name $cLibName
$cLibItem = Get-ContentLibraryItem -ContentLibrary $cLibName -Name $cLibItemName
$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 = "[$($clib.Datastore)] contentlib-$($clib.Id)/$($cLibItem.Id)/$($cLibItem.Name).$($cLibItem.ItemType)"
$change.Device += $dev
$spec.DeviceChange = $change
$vm.ExtensionData.ReconfigVM($spec)
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I update my code based on your input
$vm = Get-VM -Name $strVMName
$ConLibName = 'Repo'
$strSQLiso = 'en_sql_server_2016_standard_x64_dvd_8701871'
$CLib = Get-ContentLibrary -Name $ConLibName
$VMiso = Get-ContentLibraryItem -ContentLibrary $ConLibName -Name $strSQLiso
$oCDROM = Get-CDDrive -VM $strVMName
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$change = New-Object VMware.Vim.VirtualDeviceConfigSpec
$change.Operation = [Vmware.vim.VirtualDeviceConfigSpecOperation]::edit
$oDevice = $oCDROM.ExtensionData
$oDevice.Backing = New-Object VMware.Vim.VirtualCdromIsoBackingInfo
$oDevice.Backing.FileName = "[$($CLib.Datastore)] contentlib-$($CLib.Id)/$($VMiso.Id)/$($VMiso.Name).$($VMiso.ItemType)"
$oDevice.Connectable.StartConnected = $true
$oDevice.Connectable.Connected = $true
$change.Device += $oDevice
$spec.DeviceChange = $change
$vm.ExtensionData.ReconfigVM($spec)
However, I can't seem to get the drive actually connect (map to the iso inside the content library, just not connecting. I tried it with the GUI and it failed. I even tried with a follow command
Get-CDDrive -vm $strVMName|Set-CDDrive -Connected:$true -Confirm:$false
PS C:\Users\Administrator> Get-cddrive -vm $strVMName|Set-CDDrive -Connected:$true -Confirm:$false
Set-CDDrive : 12/11/2020 3:38:26 PM Set-CDDrive The operation for the entity "SQL" failed with the following message:
"Connection control operation failed for disk 'ide0:0'.". Connection control operation failed for disk 'ide0:0'.
At line:1 char:28
+ ... t-cddrive -vm $strVMName|Set-CDDrive -Connected:$true -Confirm:$false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-CDDrive], GenericVmConfigFault
+ FullyQualifiedErrorId : Client20_TaskServiceImpl_CheckServerSideTaskUpdates_OperationFailed,VMware.VimAutomation.ViCore
.Cmdlets.Commands.VirtualDevice.SetCDDrive
Is there already an ISO or a drive connected before you run the script?
If yes, try with nothing connected
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
the iso from the content library. The script did update the path to the iso. It even show up in the GUI, just will not connect.
I discovered something interesting, but not sure the fix yet. Per your code from earlier
$oDevice.Backing.FileName = "[$($CLib.Datastore)] contentlib-$($CLib.Id)/$($VMiso.Id)/$($VMiso.Name).$($VMiso.ItemType)"
to build out the actual path to the iso from a datastore point of view, the output were
PS C:\Users\Administrator> echo $CLib.Datastore
Name FreeSpaceGB CapacityGB
---- ----------- ----------
SSD_VM 70.388 223.500
PS C:\Users\Administrator> echo $CLib.Id
e46c6898-9ecc-4fcd-8145-8639bfc7611f
PS C:\Users\Administrator> echo $VMiso.Id
b835b797-a146-4c10-bcbc-537b74e6eb4a
PS C:\Users\Administrator> echo $VMiso.Name
en_sql_server_2016_standard_x64_dvd_8701871
PS C:\Users\Administrator> echo $VMiso.Itemtype
iso
So the code should stitch together the following value
[SSD_VM] contentlib-e46c6898-9ecc-4fcd-8145-8639bfc7611f/b835b797-a146-4c10-bcbc-537b74e6eb4a/en_sql_server_2016_standard_x64_d
vd_8701871.iso
However, when I manually attach the iso through the GUI by using the datastore path (not content library), and I reparse the vm.extensiondata manual, I got the following
[SSD_VM] contentlib-e46c6898-9ecc-4fcd-8145-8639bfc7611f/b835b797-a146-4c10-bcbc-537b74e6eb4a/en_sql_server_2016_standard_x64_d
vd_8701871_1900ce00-de5c-4b91-a526-2af7057ddc3f.iso
the name of the iso actually change after I uploaded it. It is masked if I try to view from the content library , but it is clearly visible (I also confirmed) if you view it from the datastore view. So the question is what is this extra data (metadata? ID?) '1900ce00-de5c-4b91-a526-2af7057ddc3f' come from?
I noticed the same when I try with an ISO that I gave another name in the Content Library.
Not sure how to explain that behavior.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
is there a way to use wildcard for a string inside powerCLI? $a = sql* versus $a = sql-2016-blahblah
Tried that, but since that code is calling the API, no cigar I'm afraid.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
lol, so it seem currently, the best route is to move the SQL ISO into a datastore and mount it that want
I uploaded an ISO to a Content Library without giving it another name.
It then took the name of the ISO.
Then the script I provided seems to work
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
? Do not understand. Can you phrase it another way ?
When you import an ISO into a Content Library the Item name field automatically gets the same name as the name of the ISO, minus the filetype.
The snippet works for me when I don't change that Item name field.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Let me take a quick look. Thanks
I did some further exploring, the following snippet seems to work for me, in all situations.
$vmName = 'MyVM'
$cLibName = 'MyCl'
$cLibItemName = 'SomeIso' # The Name as it appears in the CL
$vm = Get-VM -Name $vmName
$cd = Get-CDDrive -VM $vm
$clib = Get-ContentLibrary -Name $cLibName
$ds = Get-Datastore -Name $clib.Datastore
New-PSDrive -Name DS -PSProvider VimDatastore -Root '\' -Location $ds | Out-Null
$isoPath = Get-ChildItem -Path "DS:" -Recurse -Filter "$($cLibItemName)*.iso" | Select -ExpandProperty DatastoreFullPath
Remove-PSDrive -Name DS -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)
The difference is that I get the path of the ISO in the Content Library via the VimDatastore provider.
Apparently, the name has to have the UUID of the file in the path used.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Nice, I see you are using the datastore to parse the name for the full path. This seem to work, but will do some clean up and further testing to confirm. Thank you
Thank you, that fixed it 😉
I am trying this now and running into an issue referencing Backing, any ideas, or has Powercli been updated since this post and I'm missing an obvious solution?
$dev = $cd.ExtensionData
The property 'Backing' cannot be found on this object. Verify that the property exists and can be set.
At line:2 char:1
+ $dev.Backing = New-Object VMware.Vim.VirtualCdromIsoBackingInfo
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
The property 'FileName' cannot be found on this object. Verify that the property exists and can be set.
At line:3 char:1
+ $dev.Backing.FileName = $isoPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
Exception setting "Device": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type "VMware.Vim.VirtualDevice"."
At line:5 char:1
+ $change.Device += $dev
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
The property 'Connected' cannot be found on this object. Verify that the property exists and can be set.
At line:6 char:1
+ $change.Device.Connectable.Connected = $true
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
Exception calling "ReconfigVM" with "1" argument(s): "
Required property device is missing from data object of type VirtualDeviceConfigSpec
while parsing serialized DataObject of type vim.vm.device.VirtualDeviceSpec
at line 1, column 257
while parsing property "deviceChange" of static type ArrayOfVirtualDeviceConfigSpec
while parsing serialized DataObject of type vim.vm.ConfigSpec
at line 1, column 251
while parsing call information for method ReconfigVM_Task
at line 1, column 171
while parsing SOAP body
at line 1, column 64
while parsing SOAP envelope
at line 1, column 0
while parsing HTTP request for method reconfigure
on object of type vim.VirtualMachine
at line 1, column 0"
At line:11 char:1
+ $vm.ExtensionData.ReconfigVM($spec)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException
Did you check that $vm, $cd and $clib each only contain 1 object?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
so that is my issues, I'm trying to pass a list so I can perform operations across multiple vCenters. Any ideas how I could accomplish this?