PowerCLI

 View Only
Expand all | Collapse all

Mount a content library iso on a live VM

dwchan

dwchanDec 12, 2020 07:38 PM

dwchan

dwchanDec 13, 2020 06:36 AM

  • 1.  Mount a content library iso on a live VM

    Posted Dec 11, 2020 03:38 PM

    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 

     



  • 2.  RE: Mount a content library iso on a live VM

    Posted Dec 11, 2020 05:09 PM

    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)


  • 3.  RE: Mount a content library iso on a live VM

    Posted Dec 11, 2020 08:58 PM

    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



  • 4.  RE: Mount a content library iso on a live VM

    Posted Dec 11, 2020 09:55 PM

    Is there already an ISO or a drive connected before you run the script?
    If yes, try with nothing connected



  • 5.  RE: Mount a content library iso on a live VM

    Posted Dec 11, 2020 11:03 PM

    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.  



  • 6.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 02:46 AM

    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?



  • 7.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 06:25 AM

    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.



  • 8.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 05:57 PM

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



  • 9.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 06:09 PM

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



  • 10.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 06:18 PM

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



  • 11.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 06:37 PM

    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



  • 12.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 07:19 PM

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



  • 13.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 07:33 PM

    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



  • 14.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 07:38 PM

    Let me take a quick look. Thanks



  • 15.  RE: Mount a content library iso on a live VM
    Best Answer

    Posted Dec 12, 2020 08:23 PM

    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.



  • 16.  RE: Mount a content library iso on a live VM

    Posted Dec 12, 2020 10:50 PM

    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



  • 17.  RE: Mount a content library iso on a live VM

    Posted Dec 13, 2020 06:36 AM

    Thank you, that fixed it  



  • 18.  RE: Mount a content library iso on a live VM

    Posted Mar 11, 2022 10:13 PM

    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



  • 19.  RE: Mount a content library iso on a live VM

    Posted Mar 11, 2022 10:37 PM

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



  • 20.  RE: Mount a content library iso on a live VM

    Posted Mar 11, 2022 10:43 PM

    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? 



  • 21.  RE: Mount a content library iso on a live VM

    Posted Mar 12, 2022 06:35 AM

    How did you call the code for that list?
    Can you share the code you used?



  • 22.  RE: Mount a content library iso on a live VM

    Posted Mar 12, 2022 01:20 PM

    I generated lists via Tags and variables for a client

    $client = Read-Host "Enter Client Name"

    $2012Tag = Get-Tag -Name 'Server 2012'

    $2016Tag = Get-Tag -Name 'Server 2016'

    $2019Tag = Get-Tag -Name 'Server 2019'

    Get-Folder -Name $client | Get-VM | where PowerState -eq 'PoweredOn' | Export-Csv -Path 'C:\temp\Client VMs.csv'

    Get-Folder -Name $client | Get-VM -Tag $2012Tag | where PowerState -eq 'PoweredOn' | Export-Csv -Path 'c:\temp\2012 VMs.csv'

    Get-Folder -Name $client | Get-VM -Tag $2016Tag | where PowerState -eq 'PoweredOn' | Export-Csv -Path 'c:\temp\2016 VMs.csv'

    Get-Folder -Name $client | Get-VM -Tag $2012Tag | where PowerState -eq 'PoweredOn' | Export-Csv -Path 'c:\temp\2019 VMs.csv'

    $clientVMs = Import-Csv -Path 'c:\temp\Client VMs.csv' | select -ExpandProperty Name

    $2012VMs = Import-Csv -Path 'c:\temp\2012 VMs.csv' | select -ExpandProperty Name

    $2016VMs = Import-Csv -Path 'c:\temp\2016 VMs.csv' | select -ExpandProperty Name

    $2019VMs = Import-Csv -Path 'c:\temp\2019 VMs.csv' | select -ExpandProperty Name

     

    After the lists are generated I'm trying to run a script via Invoke-vmscript, and I am passing a script block to execute what I need on the ISO that needs to be mounted from the Content Library. This is running across multiple vCenters, version 6.7 and 7.  I have been able to run all of what I need and achieve my goal via a single vCenter with a static ISO location, but I'm trying to expand across our entire infrastructure to account for all the VMs for a client in a single script.



  • 23.  RE: Mount a content library iso on a live VM

    Posted Mar 12, 2022 01:44 PM

    Is there a loop somewhere?
    You can call that code only for a single instance.

    And why the Invoke-VMScript?
    Can't you just run that on a station that can access the vCenter?



  • 24.  RE: Mount a content library iso on a live VM

    Posted Mar 12, 2022 01:59 PM

    I have not quite mastered loops yet, I'm sure there's a way, but I haven't figured that out yet either.

    I have to utilize invoke-vmscript because I have multiple clients across multiple domains and they are each separated and cannot access our vSphere interfaces from their machines. Our vSphere is managed on our own internal infra with our own separate AD, so invoke-vmscript lets me utilize what I need on a client by client basis.

    In the overall logic of the script I'm prompting and storing creds for each client, hence the Read-Host variable.



  • 25.  RE: Mount a content library iso on a live VM

    Posted Mar 12, 2022 03:18 PM

    You need some kind of loop, something like this for example

    $cLibName = 'MyCl'
    $cLibItemName = 'SomeIso'   # The Name as it appears in the CL
    
    $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
    
    $2012Tag = Get-Tag -Name 'Server 2012'
    
    Get-Folder -Name $client | Get-VM -Tag $2012Tag -PipelineVariable vm | 
    where PowerState -EQ 'PoweredOn' | 
    ForEach-Object -Process {
        $cd = Get-CDDrive -VM $vm
    
        $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)
    }
    


  • 26.  RE: Mount a content library iso on a live VM

    Posted Mar 12, 2022 07:01 PM

    well that works in my lab. I will test further with my other environments and see if I can replicate it en masse. Thanks Luc!



  • 27.  RE: Mount a content library iso on a live VM

    Posted Mar 13, 2022 03:22 AM

    alright, we're getting somewhere, but now I'm hitting a wall in this block: 

    $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

    New-PSDrive -Name DS -PSProvider VimDatastore -Root '\' -Location $ds | Out-Null

    New-PSDrive : Cannot bind parameter 'Datastore' to the target. Exception setting "Datastore": "Invalid location type. Location accepts only VIDatastore objects."

     

    I saw another thread where you asked if Get-Datastore <name> restored a valid DatastoreImpl object, and I checked my list of objects populating the $ds variable, and they all return valid responses. The DS variable contains 11 datastores. 

     

    ** I was able to figure out how to use the foreach for the 11 datastores, and I was able to get that block to complete, but now when I'm trying to assign the ISO to the drives, I'm getting an exception, Exception calling "ReconfigVM" with "1" argument(s): "Connection control operation failed for disk 'sata0:0'. Connection control operation failed for disk 'sata0:0'.", which reads on the vCenter side as trying to attach file "emptyBackingstring" as a CD-ROM image. 

    I went line by line with a static variable for one VM and it always gives me an error at the last line. 



  • 28.  RE: Mount a content library iso on a live VM

    Posted Mar 13, 2022 06:36 AM

    I suspect that $clib.Datastore returns nothing ($null) for one of the ContentLibraries.



  • 29.  RE: Mount a content library iso on a live VM

    Posted Mar 14, 2022 04:07 PM

    I found the issue. Apparently, regardless of the name I typed in for the CLIB item, it used the actual file name when uploading on the datastore side, so in this instance "Scripts_ISO" brought back nothing but "Scripts ISO"(Not matching what was in the CL)  returned correctly. 

     

     

    So now the issue I'm having is that the isopath variable will populate with one of the CL datastores, but not necessarily the right one. I'm working with a focused list from one vCenter, but with the others connected for testing, and it keeps failing trying to mount an iso from CLIB datastore A to VM backed by CLIB iso in datastore C.