github.com/vmware/govmomi@v0.37.1/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 info.Items = append(info.Items, NewFileItem(u, item)) 149 break 150 } 151 } 152 } 153 154 return info, nil 155 } 156 157 func (l *Lease) Wait(ctx context.Context, items []types.OvfFileItem) (*LeaseInfo, error) { 158 var lease mo.HttpNfcLease 159 160 pc := property.DefaultCollector(l.c) 161 err := property.Wait(ctx, pc, l.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool { 162 done := false 163 164 for _, c := range pc { 165 if c.Val == nil { 166 continue 167 } 168 169 switch c.Name { 170 case "error": 171 val := c.Val.(types.LocalizedMethodFault) 172 lease.Error = &val 173 done = true 174 case "info": 175 val := c.Val.(types.HttpNfcLeaseInfo) 176 lease.Info = &val 177 case "state": 178 lease.State = c.Val.(types.HttpNfcLeaseState) 179 if lease.State != types.HttpNfcLeaseStateInitializing { 180 done = true 181 } 182 } 183 } 184 185 return done 186 }) 187 188 if err != nil { 189 return nil, err 190 } 191 192 if lease.State == types.HttpNfcLeaseStateReady { 193 return l.newLeaseInfo(lease.Info, items) 194 } 195 196 if lease.Error != nil { 197 return nil, &task.Error{LocalizedMethodFault: lease.Error} 198 } 199 200 return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State) 201 } 202 203 func (l *Lease) StartUpdater(ctx context.Context, info *LeaseInfo) *LeaseUpdater { 204 return newLeaseUpdater(ctx, l, info) 205 } 206 207 func (l *Lease) Upload(ctx context.Context, item FileItem, f io.Reader, opts soap.Upload) error { 208 if opts.Progress == nil { 209 opts.Progress = item 210 } 211 212 // Non-disk files (such as .iso) use the PUT method. 213 // Overwrite: t header is also required in this case (ovftool does the same) 214 if item.Create { 215 opts.Method = "PUT" 216 opts.Headers = map[string]string{ 217 "Overwrite": "t", 218 } 219 } else { 220 opts.Method = "POST" 221 opts.Type = "application/x-vnd.vmware-streamVmdk" 222 } 223 224 return l.c.Upload(ctx, f, item.URL, &opts) 225 } 226 227 func (l *Lease) DownloadFile(ctx context.Context, file string, item FileItem, opts soap.Download) error { 228 if opts.Progress == nil { 229 opts.Progress = item 230 } 231 232 return l.c.DownloadFile(ctx, file, item.URL, &opts) 233 }