github.com/vmware/govmomi@v0.37.2/simulator/virtual_disk_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  	"fmt"
    21  	"os"
    22  	"strings"
    23  
    24  	"github.com/google/uuid"
    25  
    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 VirtualDiskManager struct {
    33  	mo.VirtualDiskManager
    34  }
    35  
    36  func (m *VirtualDiskManager) MO() mo.VirtualDiskManager {
    37  	return m.VirtualDiskManager
    38  }
    39  
    40  func vdmNames(name string) []string {
    41  	return []string{
    42  		strings.Replace(name, ".vmdk", "-flat.vmdk", 1),
    43  		name,
    44  	}
    45  }
    46  
    47  func vdmCreateVirtualDisk(op types.VirtualDeviceConfigSpecFileOperation, req *types.CreateVirtualDisk_Task) types.BaseMethodFault {
    48  	fm := Map.FileManager()
    49  
    50  	file, fault := fm.resolve(req.Datacenter, req.Name)
    51  	if fault != nil {
    52  		return fault
    53  	}
    54  
    55  	shouldReplace := op == types.VirtualDeviceConfigSpecFileOperationReplace
    56  	shouldExist := op == ""
    57  	for _, name := range vdmNames(file) {
    58  		_, err := os.Stat(name)
    59  		if err == nil {
    60  			if shouldExist {
    61  				return nil
    62  			}
    63  			if shouldReplace {
    64  				if err = os.Truncate(file, 0); err != nil {
    65  					return fm.fault(name, err, new(types.CannotCreateFile))
    66  				}
    67  				return nil
    68  			}
    69  			return fm.fault(name, nil, new(types.FileAlreadyExists))
    70  		} else if shouldExist {
    71  			return fm.fault(name, nil, new(types.FileNotFound))
    72  		}
    73  
    74  		f, err := os.Create(name)
    75  		if err != nil {
    76  			return fm.fault(name, err, new(types.CannotCreateFile))
    77  		}
    78  
    79  		_ = f.Close()
    80  	}
    81  
    82  	return nil
    83  }
    84  
    85  func (m *VirtualDiskManager) CreateVirtualDiskTask(ctx *Context, req *types.CreateVirtualDisk_Task) soap.HasFault {
    86  	task := CreateTask(m, "createVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
    87  		if err := vdmCreateVirtualDisk(types.VirtualDeviceConfigSpecFileOperationCreate, req); err != nil {
    88  			return "", err
    89  		}
    90  		return req.Name, nil
    91  	})
    92  
    93  	return &methods.CreateVirtualDisk_TaskBody{
    94  		Res: &types.CreateVirtualDisk_TaskResponse{
    95  			Returnval: task.Run(ctx),
    96  		},
    97  	}
    98  }
    99  
   100  func (m *VirtualDiskManager) DeleteVirtualDiskTask(ctx *Context, req *types.DeleteVirtualDisk_Task) soap.HasFault {
   101  	task := CreateTask(m, "deleteVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
   102  		fm := Map.FileManager()
   103  
   104  		for _, name := range vdmNames(req.Name) {
   105  			err := fm.deleteDatastoreFile(&types.DeleteDatastoreFile_Task{
   106  				Name:       name,
   107  				Datacenter: req.Datacenter,
   108  			})
   109  
   110  			if err != nil {
   111  				return nil, err
   112  			}
   113  		}
   114  
   115  		return nil, nil
   116  	})
   117  
   118  	return &methods.DeleteVirtualDisk_TaskBody{
   119  		Res: &types.DeleteVirtualDisk_TaskResponse{
   120  			Returnval: task.Run(ctx),
   121  		},
   122  	}
   123  }
   124  
   125  func (m *VirtualDiskManager) MoveVirtualDiskTask(ctx *Context, req *types.MoveVirtualDisk_Task) soap.HasFault {
   126  	task := CreateTask(m, "moveVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
   127  		fm := ctx.Map.FileManager()
   128  
   129  		dest := vdmNames(req.DestName)
   130  
   131  		for i, name := range vdmNames(req.SourceName) {
   132  			err := fm.moveDatastoreFile(&types.MoveDatastoreFile_Task{
   133  				SourceName:            name,
   134  				SourceDatacenter:      req.SourceDatacenter,
   135  				DestinationName:       dest[i],
   136  				DestinationDatacenter: req.DestDatacenter,
   137  				Force:                 req.Force,
   138  			})
   139  
   140  			if err != nil {
   141  				return nil, err
   142  			}
   143  		}
   144  
   145  		return nil, nil
   146  	})
   147  
   148  	return &methods.MoveVirtualDisk_TaskBody{
   149  		Res: &types.MoveVirtualDisk_TaskResponse{
   150  			Returnval: task.Run(ctx),
   151  		},
   152  	}
   153  }
   154  
   155  func (m *VirtualDiskManager) CopyVirtualDiskTask(ctx *Context, req *types.CopyVirtualDisk_Task) soap.HasFault {
   156  	task := CreateTask(m, "copyVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
   157  		if req.DestSpec != nil {
   158  			if ctx.Map.IsVPX() {
   159  				return nil, new(types.NotImplemented)
   160  			}
   161  		}
   162  
   163  		fm := ctx.Map.FileManager()
   164  
   165  		dest := vdmNames(req.DestName)
   166  
   167  		for i, name := range vdmNames(req.SourceName) {
   168  			err := fm.copyDatastoreFile(&types.CopyDatastoreFile_Task{
   169  				SourceName:            name,
   170  				SourceDatacenter:      req.SourceDatacenter,
   171  				DestinationName:       dest[i],
   172  				DestinationDatacenter: req.DestDatacenter,
   173  				Force:                 req.Force,
   174  			})
   175  
   176  			if err != nil {
   177  				return nil, err
   178  			}
   179  		}
   180  
   181  		return nil, nil
   182  	})
   183  
   184  	return &methods.CopyVirtualDisk_TaskBody{
   185  		Res: &types.CopyVirtualDisk_TaskResponse{
   186  			Returnval: task.Run(ctx),
   187  		},
   188  	}
   189  }
   190  
   191  func virtualDiskUUID(dc *types.ManagedObjectReference, file string) string {
   192  	if dc != nil {
   193  		file = dc.String() + file
   194  	}
   195  	return uuid.NewSHA1(uuid.NameSpaceOID, []byte(file)).String()
   196  }
   197  
   198  func (m *VirtualDiskManager) QueryVirtualDiskUuid(ctx *Context, req *types.QueryVirtualDiskUuid) soap.HasFault {
   199  	body := new(methods.QueryVirtualDiskUuidBody)
   200  
   201  	fm := ctx.Map.FileManager()
   202  
   203  	file, fault := fm.resolve(req.Datacenter, req.Name)
   204  	if fault != nil {
   205  		body.Fault_ = Fault("", fault)
   206  		return body
   207  	}
   208  
   209  	_, err := os.Stat(file)
   210  	if err != nil {
   211  		fault = fm.fault(req.Name, err, new(types.CannotAccessFile))
   212  		body.Fault_ = Fault(fmt.Sprintf("File %s was not found", req.Name), fault)
   213  		return body
   214  	}
   215  
   216  	body.Res = &types.QueryVirtualDiskUuidResponse{
   217  		Returnval: virtualDiskUUID(req.Datacenter, file),
   218  	}
   219  
   220  	return body
   221  }
   222  
   223  func (m *VirtualDiskManager) SetVirtualDiskUuid(_ *Context, req *types.SetVirtualDiskUuid) soap.HasFault {
   224  	body := new(methods.SetVirtualDiskUuidBody)
   225  	// TODO: validate uuid format and persist
   226  	body.Res = new(types.SetVirtualDiskUuidResponse)
   227  	return body
   228  }