github.com/vmware/govmomi@v0.37.1/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 }