github.com/vmware/govmomi@v0.51.0/nfc/lease.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package nfc
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  	"io"
    11  	"path"
    12  
    13  	"github.com/vmware/govmomi/property"
    14  	"github.com/vmware/govmomi/task"
    15  	"github.com/vmware/govmomi/vim25"
    16  	"github.com/vmware/govmomi/vim25/methods"
    17  	"github.com/vmware/govmomi/vim25/mo"
    18  	"github.com/vmware/govmomi/vim25/soap"
    19  	"github.com/vmware/govmomi/vim25/types"
    20  )
    21  
    22  type Lease struct {
    23  	types.ManagedObjectReference
    24  
    25  	c *vim25.Client
    26  }
    27  
    28  func NewLease(c *vim25.Client, ref types.ManagedObjectReference) *Lease {
    29  	return &Lease{ref, c}
    30  }
    31  
    32  // Abort wraps methods.Abort
    33  func (l *Lease) Abort(ctx context.Context, fault *types.LocalizedMethodFault) error {
    34  	req := types.HttpNfcLeaseAbort{
    35  		This:  l.Reference(),
    36  		Fault: fault,
    37  	}
    38  
    39  	_, err := methods.HttpNfcLeaseAbort(ctx, l.c, &req)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	return nil
    45  }
    46  
    47  // Complete wraps methods.Complete
    48  func (l *Lease) Complete(ctx context.Context) error {
    49  	req := types.HttpNfcLeaseComplete{
    50  		This: l.Reference(),
    51  	}
    52  
    53  	_, err := methods.HttpNfcLeaseComplete(ctx, l.c, &req)
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	return nil
    59  }
    60  
    61  // GetManifest wraps methods.GetManifest
    62  func (l *Lease) GetManifest(ctx context.Context) ([]types.HttpNfcLeaseManifestEntry, error) {
    63  	req := types.HttpNfcLeaseGetManifest{
    64  		This: l.Reference(),
    65  	}
    66  
    67  	res, err := methods.HttpNfcLeaseGetManifest(ctx, l.c, &req)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	return res.Returnval, nil
    73  }
    74  
    75  // Progress wraps methods.Progress
    76  func (l *Lease) Progress(ctx context.Context, percent int32) error {
    77  	req := types.HttpNfcLeaseProgress{
    78  		This:    l.Reference(),
    79  		Percent: percent,
    80  	}
    81  
    82  	_, err := methods.HttpNfcLeaseProgress(ctx, l.c, &req)
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  // Properties returns a mo.HttpNfcLease with the specified properties.
    91  // If no properties are requested, all properties are returned.
    92  func (l *Lease) Properties(
    93  	ctx context.Context,
    94  	props ...string) (mo.HttpNfcLease, error) {
    95  
    96  	if len(props) == 0 {
    97  		props = []string{
    98  			"initializeProgress",
    99  			"transferProgress",
   100  			"mode",
   101  			"capabilities",
   102  			"info",
   103  			"state",
   104  			"error",
   105  		}
   106  	}
   107  
   108  	var o mo.HttpNfcLease
   109  	pc := property.DefaultCollector(l.c)
   110  	return o, pc.RetrieveOne(ctx, l.Reference(), props, &o)
   111  }
   112  
   113  type LeaseInfo struct {
   114  	types.HttpNfcLeaseInfo
   115  
   116  	Items []FileItem
   117  }
   118  
   119  func (l *Lease) newLeaseInfo(li *types.HttpNfcLeaseInfo, items []types.OvfFileItem) (*LeaseInfo, error) {
   120  	info := &LeaseInfo{
   121  		HttpNfcLeaseInfo: *li,
   122  	}
   123  
   124  	for _, device := range li.DeviceUrl {
   125  		u, err := l.c.ParseURL(device.Url)
   126  		if err != nil {
   127  			return nil, err
   128  		}
   129  
   130  		if device.SslThumbprint != "" {
   131  			// TODO: prefer host management IP
   132  			l.c.SetThumbprint(u.Host, device.SslThumbprint)
   133  		}
   134  
   135  		if len(items) == 0 {
   136  			// this is an export
   137  			item := types.OvfFileItem{
   138  				DeviceId: device.Key,
   139  				Path:     device.TargetId,
   140  				Size:     device.FileSize,
   141  			}
   142  
   143  			if item.Size == 0 {
   144  				item.Size = li.TotalDiskCapacityInKB * 1024
   145  			}
   146  
   147  			if item.Path == "" {
   148  				item.Path = path.Base(device.Url)
   149  			}
   150  
   151  			info.Items = append(info.Items, NewFileItem(u, item))
   152  
   153  			continue
   154  		}
   155  
   156  		// this is an import
   157  		for _, item := range items {
   158  			if device.ImportKey == item.DeviceId {
   159  				fi := NewFileItem(u, item)
   160  				fi.Thumbprint = device.SslThumbprint
   161  
   162  				info.Items = append(info.Items, fi)
   163  
   164  				break
   165  			}
   166  		}
   167  	}
   168  
   169  	return info, nil
   170  }
   171  
   172  func (l *Lease) Wait(ctx context.Context, items []types.OvfFileItem) (*LeaseInfo, error) {
   173  	var lease mo.HttpNfcLease
   174  
   175  	pc := property.DefaultCollector(l.c)
   176  	err := property.Wait(ctx, pc, l.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool {
   177  		done := false
   178  
   179  		for _, c := range pc {
   180  			if c.Val == nil {
   181  				continue
   182  			}
   183  
   184  			switch c.Name {
   185  			case "error":
   186  				val := c.Val.(types.LocalizedMethodFault)
   187  				lease.Error = &val
   188  				done = true
   189  			case "info":
   190  				val := c.Val.(types.HttpNfcLeaseInfo)
   191  				lease.Info = &val
   192  			case "state":
   193  				lease.State = c.Val.(types.HttpNfcLeaseState)
   194  				if lease.State != types.HttpNfcLeaseStateInitializing {
   195  					done = true
   196  				}
   197  			}
   198  		}
   199  
   200  		return done
   201  	})
   202  
   203  	if err != nil {
   204  		return nil, err
   205  	}
   206  
   207  	if lease.State == types.HttpNfcLeaseStateReady {
   208  		return l.newLeaseInfo(lease.Info, items)
   209  	}
   210  
   211  	if lease.Error != nil {
   212  		return nil, &task.Error{LocalizedMethodFault: lease.Error}
   213  	}
   214  
   215  	return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State)
   216  }
   217  
   218  func (l *Lease) StartUpdater(ctx context.Context, info *LeaseInfo) *LeaseUpdater {
   219  	return newLeaseUpdater(ctx, l, info)
   220  }
   221  
   222  func (l *Lease) Upload(ctx context.Context, item FileItem, f io.Reader, opts soap.Upload) error {
   223  	if opts.Progress == nil {
   224  		opts.Progress = item
   225  	}
   226  
   227  	// Non-disk files (such as .iso) use the PUT method.
   228  	// Overwrite: t header is also required in this case (ovftool does the same)
   229  	if item.Create {
   230  		opts.Method = "PUT"
   231  		opts.Headers = map[string]string{
   232  			"Overwrite": "t",
   233  		}
   234  	} else {
   235  		opts.Method = "POST"
   236  		opts.Type = "application/x-vnd.vmware-streamVmdk"
   237  	}
   238  
   239  	return l.c.Upload(ctx, f, item.URL, &opts)
   240  }
   241  
   242  func (l *Lease) DownloadFile(ctx context.Context, file string, item FileItem, opts soap.Download) error {
   243  	if opts.Progress == nil {
   244  		opts.Progress = item
   245  	}
   246  
   247  	return l.c.DownloadFile(ctx, file, item.URL, &opts)
   248  }