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