Skip to content

Commit

Permalink
fix: support asterisk URL in import (#1813)
Browse files Browse the repository at this point in the history
- use the correct URL parsing function from govmomi library to replace asterisk with a host when needed

Refs: #1806

Co-authored-by: Ryan Johnson <[email protected]>
  • Loading branch information
pawelprazak and Ryan Johnson authored Oct 20, 2023
1 parent 7c5fae0 commit 5e66f7b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 25 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 2.6.0 (Unreleased)

BUG FIXES:

* `resource/virtual_machine`: Resolves upload error when deploying an OVF/OVA directly to an ESXi host. ([#1813](https://github.com/terraform-providers/terraform-provider-vsphere/pull/1813))

FEATURES:

* `resource/compute_cluster`: Adds support for vSAN Express Storage Architecture in vSphere 8.0. ([#1874](https://github.com/terraform-providers/terraform-provider-vsphere/pull/1874))
Expand Down
49 changes: 25 additions & 24 deletions vsphere/internal/helper/ovfdeploy/ovf_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (pr *ProgressReader) Read(p []byte) (n int, err error) {
return
}

func DeployOvfAndGetResult(ovfCreateImportSpecResult *types.OvfCreateImportSpecResult, resourcePoolObj *object.ResourcePool,
func DeployOvfAndGetResult(client *govmomi.Client, ovfCreateImportSpecResult *types.OvfCreateImportSpecResult, resourcePoolObj *object.ResourcePool,
folder *object.Folder, host *object.HostSystem, filePath string, deployOva bool, fromLocal bool, allowUnverifiedSSL bool) error {

var currBytesRead int64
Expand Down Expand Up @@ -100,15 +100,15 @@ func DeployOvfAndGetResult(ovfCreateImportSpecResult *types.OvfCreateImportSpecR
}
if !deployOva {
if fromLocal {
err = uploadDisksFromLocal(filePath, ovfFileItem, deviceObj, &currBytesRead)
err = uploadDisksFromLocal(client, filePath, ovfFileItem, deviceObj, &currBytesRead)
} else {
err = uploadDisksFromURL(filePath, ovfFileItem, deviceObj, &currBytesRead, allowUnverifiedSSL)
err = uploadDisksFromURL(client, filePath, ovfFileItem, deviceObj, &currBytesRead, allowUnverifiedSSL)
}
} else {
if fromLocal {
err = uploadOvaDisksFromLocal(filePath, ovfFileItem, deviceObj, &currBytesRead)
err = uploadOvaDisksFromLocal(client, filePath, ovfFileItem, deviceObj, &currBytesRead)
} else {
err = uploadOvaDisksFromURL(filePath, ovfFileItem, deviceObj, &currBytesRead, allowUnverifiedSSL)
err = uploadOvaDisksFromURL(client, filePath, ovfFileItem, deviceObj, &currBytesRead, allowUnverifiedSSL)
}
}
if err != nil {
Expand All @@ -125,12 +125,13 @@ func DeployOvfAndGetResult(ovfCreateImportSpecResult *types.OvfCreateImportSpecR
return nfcLease.Complete(context.Background())
}

func upload(ctx context.Context, item types.OvfFileItem, f io.Reader, url string, size int64, totalBytesRead *int64) error {
u, err := soap.ParseURL(url)
func upload(ctx context.Context, client *govmomi.Client, item types.OvfFileItem, f io.Reader, rawUrl string, size int64, totalBytesRead *int64) error {
u, err := client.Client.ParseURL(rawUrl)
if err != nil {
return err
}
c := soap.NewClient(u, true)
url := u.String()
c := client.Client.Client

param := soap.Upload{
ContentLength: size,
Expand Down Expand Up @@ -185,7 +186,7 @@ func upload(ctx context.Context, item types.OvfFileItem, f io.Reader, url string
return err
}

func uploadDisksFromLocal(filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64) error {
func uploadDisksFromLocal(client *govmomi.Client, filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64) error {
absoluteFilePath := ""
if strings.Contains(filePath, string(os.PathSeparator)) {
absoluteFilePath = string(filePath[0 : strings.LastIndex(filePath, string(os.PathSeparator))+1])
Expand All @@ -196,7 +197,7 @@ func uploadDisksFromLocal(filePath string, ovfFileItem types.OvfFileItem, device
if err != nil {
return err
}
err = upload(context.Background(), ovfFileItem, file, deviceObj.Url, ovfFileItem.Size, currBytesRead)
err = upload(context.Background(), client, ovfFileItem, file, deviceObj.Url, ovfFileItem.Size, currBytesRead)
if err != nil {
return fmt.Errorf("error while uploading the file %s %s", vmdkFilePath, err)
}
Expand All @@ -207,27 +208,27 @@ func uploadDisksFromLocal(filePath string, ovfFileItem types.OvfFileItem, device
return nil
}

func uploadDisksFromURL(filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64,
func uploadDisksFromURL(client *govmomi.Client, filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64,
allowUnverifiedSSL bool) error {
absoluteFilePath := ""
if strings.Contains(filePath, "/") {
absoluteFilePath = string(filePath[0 : strings.LastIndex(filePath, "/")+1])
}
vmdkFilePath := absoluteFilePath + ovfFileItem.Path
client := getClient(allowUnverifiedSSL)
resp, err := client.Get(vmdkFilePath)
httpClient := getClient(allowUnverifiedSSL)
resp, err := httpClient.Get(vmdkFilePath)
log.Print(" [DEBUG] Absolute vmdk path: " + vmdkFilePath)
if err != nil {
return err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
err = upload(context.Background(), ovfFileItem, resp.Body, deviceObj.Url, ovfFileItem.Size, currBytesRead)
err = upload(context.Background(), client, ovfFileItem, resp.Body, deviceObj.Url, ovfFileItem.Size, currBytesRead)
return err
}

func uploadOvaDisksFromLocal(filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64) error {
func uploadOvaDisksFromLocal(client *govmomi.Client, filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64) error {
diskName := ovfFileItem.Path
ovaFile, err := os.Open(filePath)
if err != nil {
Expand All @@ -237,23 +238,23 @@ func uploadOvaDisksFromLocal(filePath string, ovfFileItem types.OvfFileItem, dev
_ = ovaFile.Close()
}(ovaFile)

err = findAndUploadDiskFromOva(ovaFile, diskName, ovfFileItem, deviceObj, currBytesRead)
err = findAndUploadDiskFromOva(client, ovaFile, diskName, ovfFileItem, deviceObj, currBytesRead)
return err
}

func uploadOvaDisksFromURL(filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64,
func uploadOvaDisksFromURL(client *govmomi.Client, filePath string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64,
allowUnverifiedSSL bool) error {
diskName := ovfFileItem.Path
client := getClient(allowUnverifiedSSL)
resp, err := client.Get(filePath)
httpClient := getClient(allowUnverifiedSSL)
resp, err := httpClient.Get(filePath)
if err != nil {
return err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
if resp.StatusCode == http.StatusOK {
err = findAndUploadDiskFromOva(resp.Body, diskName, ovfFileItem, deviceObj, currBytesRead)
err = findAndUploadDiskFromOva(client, resp.Body, diskName, ovfFileItem, deviceObj, currBytesRead)
if err != nil {
return err
}
Expand Down Expand Up @@ -345,7 +346,7 @@ func getOvfDescriptorFromOva(ovaFile io.Reader) (string, error) {
return "", fmt.Errorf("ovf file not found inside the ova")
}

func findAndUploadDiskFromOva(ovaFile io.Reader, diskName string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64) error {
func findAndUploadDiskFromOva(client *govmomi.Client, ovaFile io.Reader, diskName string, ovfFileItem types.OvfFileItem, deviceObj types.HttpNfcLeaseDeviceUrl, currBytesRead *int64) error {
ovaReader := tar.NewReader(ovaFile)
for {
fileHdr, err := ovaReader.Next()
Expand All @@ -356,7 +357,7 @@ func findAndUploadDiskFromOva(ovaFile io.Reader, diskName string, ovfFileItem ty
return err
}
if fileHdr.Name == diskName {
err = upload(context.Background(), ovfFileItem, ovaReader, deviceObj.Url, ovfFileItem.Size, currBytesRead)
err = upload(context.Background(), client, ovfFileItem, ovaReader, deviceObj.Url, ovfFileItem.Size, currBytesRead)
if err != nil {
return fmt.Errorf("error while uploading the file %s %s", diskName, err)
}
Expand Down Expand Up @@ -557,7 +558,7 @@ func (o *OvfHelper) GetImportSpec(client *govmomi.Client) (*types.OvfCreateImpor
return is, nil
}

func (o *OvfHelper) DeployOvf(spec *types.OvfCreateImportSpecResult) error {
return DeployOvfAndGetResult(spec, o.ResourcePool, o.Folder, o.HostSystem,
func (o *OvfHelper) DeployOvf(client *govmomi.Client, spec *types.OvfCreateImportSpecResult) error {
return DeployOvfAndGetResult(client, spec, o.ResourcePool, o.Folder, o.HostSystem,
o.FilePath, o.DeployOva, o.IsLocal, o.AllowUnverifiedSSL)
}
2 changes: 1 addition & 1 deletion vsphere/resource_vsphere_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ func resourceVsphereMachineDeployOvfAndOva(d *schema.ResourceData, meta interfac
}

log.Print(" [DEBUG] start deploying from ovf/ova Template")
err = ovfHelper.DeployOvf(ovfImportspec)
err = ovfHelper.DeployOvf(client, ovfImportspec)
if err != nil {
return nil, fmt.Errorf("error while importing ovf/ova template, %s", err)
}
Expand Down

0 comments on commit 5e66f7b

Please sign in to comment.