github.com/coreos/mantle@v0.13.0/platform/api/esx/lease.go (about) 1 // Copyright (c) 2016 VMware, Inc. All Rights Reserved. 2 // Copyright 2017 CoreOS, Inc. 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 package esx 17 18 import ( 19 "context" 20 "sync" 21 "sync/atomic" 22 "time" 23 24 "github.com/vmware/govmomi/object" 25 "github.com/vmware/govmomi/vim25" 26 ) 27 28 type leaseUpdater struct { 29 lease *object.HttpNfcLease 30 31 pos int64 // Number of bytes 32 total int64 // Total number of bytes 33 34 done chan struct{} // When lease updater should stop 35 36 wg sync.WaitGroup // Track when update loop is done 37 } 38 39 func newLeaseUpdater(client *vim25.Client, lease *object.HttpNfcLease, items []ovfFileItem) *leaseUpdater { 40 l := leaseUpdater{ 41 lease: lease, 42 43 done: make(chan struct{}), 44 } 45 46 for _, item := range items { 47 l.total += item.item.Size 48 go l.waitForProgress(item) 49 } 50 51 // Kickstart update loop 52 l.wg.Add(1) 53 go l.run() 54 55 return &l 56 } 57 58 func (l *leaseUpdater) waitForProgress(item ovfFileItem) { 59 var pos, total int64 60 61 total = item.item.Size 62 63 for { 64 select { 65 case <-l.done: 66 return 67 case p, ok := <-item.ch: 68 // Return in case of error 69 if ok && p.Error() != nil { 70 return 71 } 72 73 if !ok { 74 // Last element on the channel, add to total 75 atomic.AddInt64(&l.pos, total-pos) 76 return 77 } 78 79 // Approximate progress in number of bytes 80 x := int64(float32(total) * (p.Percentage() / 100.0)) 81 atomic.AddInt64(&l.pos, x-pos) 82 pos = x 83 } 84 } 85 } 86 87 func (l *leaseUpdater) run() { 88 defer l.wg.Done() 89 90 tick := time.NewTicker(2 * time.Second) 91 defer tick.Stop() 92 93 for { 94 select { 95 case <-l.done: 96 return 97 case <-tick.C: 98 // From the vim api HttpNfcLeaseProgress(percent) doc, percent == 99 // "Completion status represented as an integer in the 0-100 range." 100 // Always report the current value of percent, as it will renew the 101 // lease even if the value hasn't changed or is 0. 102 percent := int32(float32(100*atomic.LoadInt64(&l.pos)) / float32(l.total)) 103 err := l.lease.HttpNfcLeaseProgress(context.TODO(), percent) 104 if err != nil { 105 plog.Debugf("from lease updater: %s\n", err) 106 } 107 } 108 } 109 } 110 111 func (l *leaseUpdater) Done() { 112 close(l.done) 113 l.wg.Wait() 114 }