VMware Cloud Community
dwchan
Enthusiast
Enthusiast
Jump to solution

Mount a content library iso on a live VM

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 

 

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

View solution in original post

Reply
0 Kudos
28 Replies
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

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.  

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

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?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

is there a way to use wildcard for a string inside powerCLI?  $a = sql* versus $a = sql-2016-blahblah

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Tried that, but since that code is calling the API, no cigar I'm afraid.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

lol, so it seem currently, the best route is to move the SQL ISO into a datastore and mount it that want

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

?  Do not understand.  Can you phrase it another way ?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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.

cl-item.png


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

Let me take a quick look. Thanks

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
dwchan
Enthusiast
Enthusiast
Jump to solution

Thank you, that fixed it 😉 

Reply
0 Kudos
DJKrafty
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Did you check that $vm, $cd and $clib each only contain 1 object?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
DJKrafty
Enthusiast
Enthusiast
Jump to solution

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? 

Reply
0 Kudos