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 }