github.com/vmware/govmomi@v0.37.2/simulator/file_manager.go (about)

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