VMware Cloud Community
txadmin
Contributor
Contributor

Is there a way to Export-VApp similar to OVFtool --makedeltadisks?

I have several large VMs that I would like to offload my Vcenter in either OVF or OVA format.  I know the OVFtool can accomplish this but I'm getting nowhere with that after spending several hours with it.  Export-VApp can work but it will take several DAYS each for these VMs to complete exporting.  Is there a way to compress the exported size of these VMs in order to expedite the process?

0 Kudos
7 Replies
LucD
Leadership
Leadership

Don't think there is an option to compress the transferred files.

I have been experimenting with a script that uses the ExportVM method and then the HttpNfc methods to download the files.

I have been playing with the buffersize for reading and writing the transferred files.

By playing with size, you try to find the sweet spot for the duration of the Export.

Have a try, and let me know if it improves the Export duration.

#

# When in vSphere 6.5 ==> connect to the ESXi node

#

$vmName = 'TestVM'

$ovfPath = 'C:\OVFFolder'

# Advanced export options

$includeMac = $true

$includeUuid = $true

$includeExtraConfig = $true

$si = Get-View ServiceInstance

$ovfMgr = Get-View -Id $si.Content.OvfManager

$vm = Get-VM -Name $vmName

$lease = Get-View -Id ($vm.ExtensionData.ExportVm())

$files = @()

while($lease.State -eq [VMware.Vim.HttpNfcLeaseState]::initializing){

    sleep 1

    $lease.UpdateViewData('State')

}

$lease.UpdateViewData()

if($lease.State -eq [VMware.Vim.HttpNfcLeaseState]::ready){

    Write-Host "Lease timeout $($lease.Info.LeaseTimeout)"

    $bufferSize = 10KB

    $Timeout = 300

    $bytesWritten = 0

    foreach($device in ($lease.Info.DeviceUrl | where{$_.Disk})){

        Write-Host "Transferring $($device.Url.Split('/')[-1])"

        $ovfFile = "$($ovfPath)\$($device.Url.Split('/')[-1])"

        $url = $device.Url.Replace('*',$vm.VMHost.Name)

        $webRequest = [System.Net.WebRequest]::Create($url)

        $response = $webRequest.GetResponse()

        $responseStream = $response.GetResponseStream()

        $fileStream = [System.IO.File]::OpenWrite($ovfFile)

        $chunk = New-Object byte[] $bufferSize

        while (($bytesRead = $responseStream.Read($chunk,0,$bufferSize)))

        {

            $totalBytesRead += $bytesRead

            $fileStream.Write($chunk,0,$bytesRead)

            $fileStream.Flush()

        }

        $bytesWritten += $fileStream.Length

        $ovfFileObj = New-Object VMware.Vim.OvfFile

        $ovfFileObj.DeviceId = $device.Key

        $ovfFileObj.Path = $device.Url.Split('/')[-1]

        $ovfFileObj.Size = $fileStream.Length

        $files += $ovfFileObj

        $FileStream.Close()

        $responseStream.Close()

        $lease.HttpNfcLeaseProgress([int]($bytesWritten/($lease.Info.TotalDiskCapacityInKB * 1KB) *100))

        Write-Host "Bytes written $($bytesWritten)"

    }

    $cdp = New-Object VMware.Vim.OvfCreateDescriptorParams

    $cdp.Description = 'Test OVF Export'

    $cdp.Name = "$($vmName)"

    if($includeMac){

        $cdp.ExportOption += 'mac'

    }

    if($includeUuid){

        $cdp.ExportOption += 'uuid'

    }

    if($includeExtraConfig){

        $cdp.ExportOption += 'extraconfig'

    }

    $cdp.OvfFiles = $files

   

    $ovfResult = $ovfMgr.CreateDescriptor($vm.ExtensionData.MoRef,$cdp)

    ([xml]$ovfResult.OvfDescriptor).Save("$($ovfPath)\$($vmName).ovf")

    $lease.HttpNfcLeaseProgress(100)

    $lease.HttpNfcLeaseComplete()

    Write-Host "Export complete"

}

else{

    Write-Host "Export failed"

    Write-Host $lease.Error[0].LocalizedMessage

}


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

0 Kudos
txadmin
Contributor
Contributor

Thanks LucD​ but it doesn't seem to be working out for me.  Looks like $webrequest times out.

0 Kudos
LucD
Leadership
Leadership

Did you try playing with the timeout value?


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

0 Kudos
txadmin
Contributor
Contributor

I did but the URL that is created doesn't respond to pings, even if I try https://<my host ip> so it may be something wrong on my end?

EDIT: I realize this wouldn't work anyway now.  Also I see what may be a problem.  The host name is an IP address...would you think this would cause issues?

0 Kudos
LucD
Leadership
Leadership

It could be, I have seen this before, mostly in relation with the certificate.
You could try to replace IP address with the FQDN.

Something like this

$hostName = Resolve-DnsName -Name $vm.VMHost.Name | Select-Object -ExpandProperty NameHost

$url = $device.Url.Replace('*',$hostName)

$webRequest = [System.Net.WebRequest]::Create($url)


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

0 Kudos
txadmin
Contributor
Contributor

I also just realized that these hosts are not domain joined either.  So with that said I'm wondering if I can even use the OVFtool to accomplish this task.

0 Kudos
LucD
Leadership
Leadership

You can try with OVFtool, but I don't think belonging to a domain or not has any impact.


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

0 Kudos