lease.go 5.1 KB

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