file_manager.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. Copyright (c) 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 simulator
  14. import (
  15. "io"
  16. "os"
  17. "path"
  18. "github.com/vmware/govmomi/object"
  19. "github.com/vmware/govmomi/simulator/esx"
  20. "github.com/vmware/govmomi/vim25/methods"
  21. "github.com/vmware/govmomi/vim25/mo"
  22. "github.com/vmware/govmomi/vim25/soap"
  23. "github.com/vmware/govmomi/vim25/types"
  24. )
  25. type FileManager struct {
  26. mo.FileManager
  27. }
  28. func NewFileManager(ref types.ManagedObjectReference) object.Reference {
  29. m := &FileManager{}
  30. m.Self = ref
  31. return m
  32. }
  33. func (f *FileManager) findDatastore(ref mo.Reference, name string) (*Datastore, types.BaseMethodFault) {
  34. var refs []types.ManagedObjectReference
  35. switch obj := ref.(type) {
  36. case *Folder:
  37. refs = obj.ChildEntity
  38. case *StoragePod:
  39. refs = obj.ChildEntity
  40. }
  41. for _, ref := range refs {
  42. switch obj := Map.Get(ref).(type) {
  43. case *Datastore:
  44. if obj.Name == name {
  45. return obj, nil
  46. }
  47. case *Folder, *StoragePod:
  48. ds, _ := f.findDatastore(obj, name)
  49. if ds != nil {
  50. return ds, nil
  51. }
  52. }
  53. }
  54. return nil, &types.InvalidDatastore{Name: name}
  55. }
  56. func (f *FileManager) resolve(dc *types.ManagedObjectReference, name string) (string, types.BaseMethodFault) {
  57. p, fault := parseDatastorePath(name)
  58. if fault != nil {
  59. return "", fault
  60. }
  61. if dc == nil {
  62. if Map.IsESX() {
  63. dc = &esx.Datacenter.Self
  64. } else {
  65. return "", &types.InvalidArgument{InvalidProperty: "dc"}
  66. }
  67. }
  68. folder := Map.Get(*dc).(*Datacenter).DatastoreFolder
  69. ds, fault := f.findDatastore(Map.Get(folder), p.Datastore)
  70. if fault != nil {
  71. return "", fault
  72. }
  73. dir := ds.Info.GetDatastoreInfo().Url
  74. return path.Join(dir, p.Path), nil
  75. }
  76. func (f *FileManager) fault(name string, err error, fault types.BaseFileFault) types.BaseMethodFault {
  77. switch {
  78. case os.IsNotExist(err):
  79. fault = new(types.FileNotFound)
  80. case os.IsExist(err):
  81. fault = new(types.FileAlreadyExists)
  82. }
  83. fault.GetFileFault().File = name
  84. return fault.(types.BaseMethodFault)
  85. }
  86. func (f *FileManager) deleteDatastoreFile(req *types.DeleteDatastoreFile_Task) types.BaseMethodFault {
  87. file, fault := f.resolve(req.Datacenter, req.Name)
  88. if fault != nil {
  89. return fault
  90. }
  91. _, err := os.Stat(file)
  92. if err != nil {
  93. if os.IsNotExist(err) {
  94. return f.fault(file, err, new(types.CannotDeleteFile))
  95. }
  96. }
  97. err = os.RemoveAll(file)
  98. if err != nil {
  99. return f.fault(file, err, new(types.CannotDeleteFile))
  100. }
  101. return nil
  102. }
  103. func (f *FileManager) DeleteDatastoreFileTask(req *types.DeleteDatastoreFile_Task) soap.HasFault {
  104. task := CreateTask(f, "deleteDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
  105. return nil, f.deleteDatastoreFile(req)
  106. })
  107. return &methods.DeleteDatastoreFile_TaskBody{
  108. Res: &types.DeleteDatastoreFile_TaskResponse{
  109. Returnval: task.Run(),
  110. },
  111. }
  112. }
  113. func (f *FileManager) MakeDirectory(req *types.MakeDirectory) soap.HasFault {
  114. body := &methods.MakeDirectoryBody{}
  115. name, fault := f.resolve(req.Datacenter, req.Name)
  116. if fault != nil {
  117. body.Fault_ = Fault("", fault)
  118. return body
  119. }
  120. mkdir := os.Mkdir
  121. if isTrue(req.CreateParentDirectories) {
  122. mkdir = os.MkdirAll
  123. }
  124. err := mkdir(name, 0700)
  125. if err != nil {
  126. fault = f.fault(req.Name, err, new(types.CannotCreateFile))
  127. body.Fault_ = Fault(err.Error(), fault)
  128. return body
  129. }
  130. body.Res = new(types.MakeDirectoryResponse)
  131. return body
  132. }
  133. func (f *FileManager) moveDatastoreFile(req *types.MoveDatastoreFile_Task) types.BaseMethodFault {
  134. src, fault := f.resolve(req.SourceDatacenter, req.SourceName)
  135. if fault != nil {
  136. return fault
  137. }
  138. dst, fault := f.resolve(req.DestinationDatacenter, req.DestinationName)
  139. if fault != nil {
  140. return fault
  141. }
  142. if !isTrue(req.Force) {
  143. _, err := os.Stat(dst)
  144. if err == nil {
  145. return f.fault(dst, nil, new(types.FileAlreadyExists))
  146. }
  147. }
  148. err := os.Rename(src, dst)
  149. if err != nil {
  150. return f.fault(src, err, new(types.CannotAccessFile))
  151. }
  152. return nil
  153. }
  154. func (f *FileManager) MoveDatastoreFileTask(req *types.MoveDatastoreFile_Task) soap.HasFault {
  155. task := CreateTask(f, "moveDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
  156. return nil, f.moveDatastoreFile(req)
  157. })
  158. return &methods.MoveDatastoreFile_TaskBody{
  159. Res: &types.MoveDatastoreFile_TaskResponse{
  160. Returnval: task.Run(),
  161. },
  162. }
  163. }
  164. func (f *FileManager) copyDatastoreFile(req *types.CopyDatastoreFile_Task) types.BaseMethodFault {
  165. src, fault := f.resolve(req.SourceDatacenter, req.SourceName)
  166. if fault != nil {
  167. return fault
  168. }
  169. dst, fault := f.resolve(req.DestinationDatacenter, req.DestinationName)
  170. if fault != nil {
  171. return fault
  172. }
  173. if !isTrue(req.Force) {
  174. _, err := os.Stat(dst)
  175. if err == nil {
  176. return f.fault(dst, nil, new(types.FileAlreadyExists))
  177. }
  178. }
  179. r, err := os.Open(src)
  180. if err != nil {
  181. return f.fault(dst, err, new(types.CannotAccessFile))
  182. }
  183. defer r.Close()
  184. w, err := os.Create(dst)
  185. if err != nil {
  186. return f.fault(dst, err, new(types.CannotCreateFile))
  187. }
  188. defer w.Close()
  189. if _, err = io.Copy(w, r); err != nil {
  190. return f.fault(dst, err, new(types.CannotCreateFile))
  191. }
  192. return nil
  193. }
  194. func (f *FileManager) CopyDatastoreFileTask(req *types.CopyDatastoreFile_Task) soap.HasFault {
  195. task := CreateTask(f, "copyDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
  196. return nil, f.copyDatastoreFile(req)
  197. })
  198. return &methods.CopyDatastoreFile_TaskBody{
  199. Res: &types.CopyDatastoreFile_TaskResponse{
  200. Returnval: task.Run(),
  201. },
  202. }
  203. }