yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/esxi/vdisk.go (about) 1 // Copyright 2019 Yunion 2 // 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 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package esxi 16 17 import ( 18 "context" 19 "fmt" 20 "path" 21 "path/filepath" 22 "strings" 23 "time" 24 25 "github.com/vmware/govmomi/vim25/types" 26 27 "yunion.io/x/log" 28 "yunion.io/x/pkg/errors" 29 30 "yunion.io/x/cloudmux/pkg/apis/compute" 31 api "yunion.io/x/cloudmux/pkg/apis/compute" 32 "yunion.io/x/cloudmux/pkg/cloudprovider" 33 deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis" 34 "yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient" 35 "yunion.io/x/cloudmux/pkg/multicloud" 36 "yunion.io/x/cloudmux/pkg/multicloud/esxi/vcenter" 37 ) 38 39 var driverMap = map[string]string{ 40 "ahci": "sata", 41 "parascsi": "pvscsi", 42 "buslogic": "scsi", 43 "lsilogic": "scsi", 44 "lsilogicsas": "scsi", 45 } 46 47 type SVirtualDisk struct { 48 multicloud.SDisk 49 multicloud.STagBase 50 51 SVirtualDevice 52 IsRoot bool 53 } 54 55 func NewVirtualDisk(vm *SVirtualMachine, dev types.BaseVirtualDevice, index int) SVirtualDisk { 56 isRoot := dev.GetVirtualDevice().DeviceInfo.GetDescription().Label == rootDiskMark 57 return SVirtualDisk{ 58 SDisk: multicloud.SDisk{}, 59 SVirtualDevice: NewVirtualDevice(vm, dev, index), 60 IsRoot: isRoot, 61 } 62 } 63 64 func (disk *SVirtualDisk) getVirtualDisk() *types.VirtualDisk { 65 return disk.dev.(*types.VirtualDisk) 66 } 67 68 type IDiskBackingInfo interface { 69 GetParent() IDiskBackingInfo 70 GetUuid() string 71 GetDiskMode() string 72 GetWriteThrough() bool 73 GetFileName() string 74 GetDatastore() *types.ManagedObjectReference 75 } 76 77 type sVirtualDiskFlatVer2BackingInfo struct { 78 info *types.VirtualDiskFlatVer2BackingInfo 79 } 80 81 func (s *sVirtualDiskFlatVer2BackingInfo) GetParent() IDiskBackingInfo { 82 if s.info.Parent != nil { 83 return &sVirtualDiskFlatVer2BackingInfo{ 84 info: s.info.Parent, 85 } 86 } 87 return nil 88 } 89 90 func (s *sVirtualDiskFlatVer2BackingInfo) GetUuid() string { 91 return s.info.Uuid 92 } 93 94 func (s *sVirtualDiskFlatVer2BackingInfo) GetDiskMode() string { 95 return s.info.DiskMode 96 } 97 98 func (s *sVirtualDiskFlatVer2BackingInfo) GetWriteThrough() bool { 99 if s.info.WriteThrough != nil && *s.info.WriteThrough == true { 100 return true 101 } else { 102 return false 103 } 104 } 105 106 func (s *sVirtualDiskFlatVer2BackingInfo) GetFileName() string { 107 return s.info.FileName 108 } 109 110 func (s *sVirtualDiskFlatVer2BackingInfo) GetDatastore() *types.ManagedObjectReference { 111 return s.info.Datastore 112 } 113 114 type sVirtualDiskSparseVer2BackingInfo struct { 115 info *types.VirtualDiskSparseVer2BackingInfo 116 } 117 118 func (s *sVirtualDiskSparseVer2BackingInfo) GetParent() IDiskBackingInfo { 119 if s.info.Parent != nil { 120 return &sVirtualDiskSparseVer2BackingInfo{ 121 info: s.info.Parent, 122 } 123 } 124 return nil 125 } 126 127 func (s *sVirtualDiskSparseVer2BackingInfo) GetUuid() string { 128 return s.info.Uuid 129 } 130 131 func (s *sVirtualDiskSparseVer2BackingInfo) GetDiskMode() string { 132 return s.info.DiskMode 133 } 134 135 func (s *sVirtualDiskSparseVer2BackingInfo) GetWriteThrough() bool { 136 if s.info.WriteThrough != nil && *s.info.WriteThrough == true { 137 return true 138 } else { 139 return false 140 } 141 } 142 143 func (s *sVirtualDiskSparseVer2BackingInfo) GetFileName() string { 144 return s.info.FileName 145 } 146 147 func (s *sVirtualDiskSparseVer2BackingInfo) GetDatastore() *types.ManagedObjectReference { 148 return s.info.Datastore 149 } 150 151 type sVirtualDiskRawDiskMappingVer1BackingInfo struct { 152 info *types.VirtualDiskRawDiskMappingVer1BackingInfo 153 } 154 155 func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetParent() IDiskBackingInfo { 156 if s.info.Parent != nil { 157 return &sVirtualDiskRawDiskMappingVer1BackingInfo{ 158 info: s.info.Parent, 159 } 160 } 161 return nil 162 } 163 164 func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetUuid() string { 165 return s.info.Uuid 166 } 167 168 func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetDiskMode() string { 169 return s.info.DiskMode 170 } 171 172 func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetWriteThrough() bool { 173 return false 174 } 175 176 func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetFileName() string { 177 return s.info.FileName 178 } 179 180 func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetDatastore() *types.ManagedObjectReference { 181 return s.info.Datastore 182 } 183 184 type sVirtualDiskSparseVer1BackingInfo struct { 185 info *types.VirtualDiskSparseVer1BackingInfo 186 } 187 188 func (s *sVirtualDiskSparseVer1BackingInfo) GetParent() IDiskBackingInfo { 189 if s.info.Parent != nil { 190 return &sVirtualDiskSparseVer1BackingInfo{ 191 info: s.info.Parent, 192 } 193 } 194 return nil 195 } 196 197 func (s *sVirtualDiskSparseVer1BackingInfo) GetUuid() string { 198 return s.info.Datastore.String() + s.info.FileName 199 } 200 201 func (s *sVirtualDiskSparseVer1BackingInfo) GetDiskMode() string { 202 return s.info.DiskMode 203 } 204 205 func (s *sVirtualDiskSparseVer1BackingInfo) GetWriteThrough() bool { 206 if s.info.WriteThrough != nil && *s.info.WriteThrough == true { 207 return true 208 } else { 209 return false 210 } 211 } 212 213 func (s *sVirtualDiskSparseVer1BackingInfo) GetFileName() string { 214 return s.info.FileName 215 } 216 217 func (s *sVirtualDiskSparseVer1BackingInfo) GetDatastore() *types.ManagedObjectReference { 218 return s.info.Datastore 219 } 220 221 type sVirtualDiskFlatVer1BackingInfo struct { 222 info *types.VirtualDiskFlatVer1BackingInfo 223 } 224 225 func (s *sVirtualDiskFlatVer1BackingInfo) GetParent() IDiskBackingInfo { 226 if s.info.Parent != nil { 227 return &sVirtualDiskFlatVer1BackingInfo{ 228 info: s.info.Parent, 229 } 230 } 231 return nil 232 } 233 234 func (s *sVirtualDiskFlatVer1BackingInfo) GetUuid() string { 235 return s.info.Datastore.String() + s.info.FileName 236 } 237 238 func (s *sVirtualDiskFlatVer1BackingInfo) GetDiskMode() string { 239 return s.info.DiskMode 240 } 241 242 func (s *sVirtualDiskFlatVer1BackingInfo) GetWriteThrough() bool { 243 if s.info.WriteThrough != nil && *s.info.WriteThrough == true { 244 return true 245 } else { 246 return false 247 } 248 } 249 250 func (s *sVirtualDiskFlatVer1BackingInfo) GetFileName() string { 251 return s.info.FileName 252 } 253 254 func (s *sVirtualDiskFlatVer1BackingInfo) GetDatastore() *types.ManagedObjectReference { 255 return s.info.Datastore 256 } 257 258 func (disk *SVirtualDisk) getBackingInfo() IDiskBackingInfo { 259 backing := disk.getVirtualDisk().Backing 260 switch backing.(type) { 261 case *types.VirtualDiskFlatVer2BackingInfo: 262 return &sVirtualDiskFlatVer2BackingInfo{ 263 info: backing.(*types.VirtualDiskFlatVer2BackingInfo), 264 } 265 case *types.VirtualDeviceFileBackingInfo: 266 case *types.VirtualDiskFlatVer1BackingInfo: 267 return &sVirtualDiskFlatVer1BackingInfo{ 268 info: backing.(*types.VirtualDiskFlatVer1BackingInfo), 269 } 270 case *types.VirtualDiskLocalPMemBackingInfo: 271 case *types.VirtualDiskRawDiskMappingVer1BackingInfo: 272 return &sVirtualDiskRawDiskMappingVer1BackingInfo{ 273 info: backing.(*types.VirtualDiskRawDiskMappingVer1BackingInfo), 274 } 275 case *types.VirtualDiskSeSparseBackingInfo: 276 case *types.VirtualDiskSparseVer1BackingInfo: 277 return &sVirtualDiskSparseVer1BackingInfo{ 278 info: backing.(*types.VirtualDiskSparseVer1BackingInfo), 279 } 280 case *types.VirtualDiskSparseVer2BackingInfo: 281 return &sVirtualDiskSparseVer2BackingInfo{ 282 info: backing.(*types.VirtualDiskSparseVer2BackingInfo), 283 } 284 case *types.VirtualFloppyImageBackingInfo: 285 case *types.VirtualNVDIMMBackingInfo: 286 case *types.VirtualParallelPortFileBackingInfo: 287 case *types.VirtualSerialPortFileBackingInfo: 288 case *types.VirtualCdromIsoBackingInfo: 289 } 290 log.Fatalf("unsupported backing info %T", backing) 291 return nil 292 } 293 294 func (disk *SVirtualDisk) GetId() string { 295 backing := disk.getBackingInfo() 296 return backing.GetUuid() 297 } 298 299 func (disk *SVirtualDisk) MatchId(id string) bool { 300 vmid := disk.vm.GetGlobalId() 301 if !strings.HasPrefix(id, vmid) { 302 return false 303 } 304 backingUuid := id[len(vmid)+1:] 305 backing := disk.getBackingInfo() 306 for backing != nil { 307 if backing.GetUuid() == backingUuid { 308 return true 309 } 310 backing = backing.GetParent() 311 } 312 return false 313 } 314 315 func (disk *SVirtualDisk) GetName() string { 316 backing := disk.getBackingInfo() 317 return path.Base(backing.GetFileName()) 318 } 319 320 func (disk *SVirtualDisk) GetGlobalId() string { 321 return fmt.Sprintf("%s-%s", disk.vm.GetGlobalId(), disk.GetId()) 322 } 323 324 func (disk *SVirtualDisk) GetStatus() string { 325 return api.DISK_READY 326 } 327 328 func (disk *SVirtualDisk) Refresh() error { 329 return nil 330 } 331 332 func (disk *SVirtualDisk) IsEmulated() bool { 333 return false 334 } 335 336 func (disk *SVirtualDisk) GetDiskSizeMB() int { 337 capa := disk.getVirtualDisk().CapacityInBytes 338 if capa == 0 { 339 capa = disk.getVirtualDisk().CapacityInKB * 1024 340 } 341 return int(capa / 1024 / 1024) 342 } 343 344 func (disk *SVirtualDisk) GetAccessPath() string { 345 istore, err := disk.GetIStorage() 346 if err != nil { 347 log.Errorf("disk.GetIStorage fail %s", err) 348 return "" 349 } 350 ds := istore.(*SDatastore) 351 return ds.GetFullPath(disk.getBackingInfo().GetFileName()) 352 } 353 354 func (disk *SVirtualDisk) GetDiskFormat() string { 355 return "vmdk" 356 } 357 358 func (disk *SVirtualDisk) GetIStorage() (cloudprovider.ICloudStorage, error) { 359 dsObj := disk.getBackingInfo().GetDatastore() 360 dc, err := disk.vm.GetDatacenter() 361 if err != nil { 362 log.Errorf("fail to find datacenter %s", err) 363 return nil, err 364 } 365 istorage, err := dc.GetIStorageByMoId(moRefId(*dsObj)) 366 if err != nil { 367 return nil, err 368 } 369 return istorage, nil 370 } 371 372 func (disk *SVirtualDisk) GetIsAutoDelete() bool { 373 return true 374 } 375 376 func (disk *SVirtualDisk) GetTemplateId() string { 377 backing := disk.getBackingInfo() 378 if backing.GetParent() != nil { 379 return path.Base(backing.GetParent().GetFileName()) 380 } 381 return "" 382 } 383 384 func (disk *SVirtualDisk) GetDiskType() string { 385 if disk.IsRoot { 386 return api.DISK_TYPE_SYS 387 } 388 return api.DISK_TYPE_DATA 389 } 390 391 func (disk *SVirtualDisk) GetFsFormat() string { 392 return "" 393 } 394 395 func (disk *SVirtualDisk) getDiskMode() string { 396 backing := disk.getBackingInfo() 397 return backing.GetDiskMode() 398 } 399 400 func (disk *SVirtualDisk) GetIsNonPersistent() bool { 401 return disk.getDiskMode() == "persistent" 402 } 403 404 func (disk *SVirtualDisk) GetDriver() string { 405 controller := disk.vm.getVdev(disk.getControllerKey()) 406 name := controller.GetDriver() 407 name = strings.Replace(name, "controller", "", -1) 408 if driver, ok := driverMap[name]; ok { 409 return driver 410 } 411 return name 412 } 413 414 func (disk *SVirtualDisk) GetCacheMode() string { 415 backing := disk.getBackingInfo() 416 if backing.GetWriteThrough() { 417 return "writethrough" 418 } else { 419 return "none" 420 } 421 } 422 423 func (disk *SVirtualDisk) GetMountpoint() string { 424 return "" 425 } 426 427 func (disk *SVirtualDisk) Delete(ctx context.Context) error { 428 istorage, err := disk.GetIStorage() 429 if err != nil { 430 log.Errorf("disk.GetIStorage() fail %s", err) 431 return err 432 } 433 ds := istorage.(*SDatastore) 434 return ds.Delete2(ctx, disk.getBackingInfo().GetFileName(), false, false) 435 } 436 437 func (disk *SVirtualDisk) CreateISnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudSnapshot, error) { 438 return nil, cloudprovider.ErrNotImplemented 439 } 440 441 func (disk *SVirtualDisk) GetISnapshot(idStr string) (cloudprovider.ICloudSnapshot, error) { 442 return nil, cloudprovider.ErrNotImplemented 443 } 444 445 func (disk *SVirtualDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { 446 return nil, cloudprovider.ErrNotImplemented 447 } 448 449 func (disk *SVirtualDisk) Resize(ctx context.Context, newSizeMb int64) error { 450 ndisk := disk.getVirtualDisk() 451 ndisk.CapacityInKB = newSizeMb * 1024 452 453 devSpec := types.VirtualDeviceConfigSpec{} 454 devSpec.Device = ndisk 455 devSpec.Operation = types.VirtualDeviceConfigSpecOperationEdit 456 457 spec := types.VirtualMachineConfigSpec{} 458 spec.DeviceChange = []types.BaseVirtualDeviceConfigSpec{&devSpec} 459 460 vm := disk.vm.getVmObj() 461 462 task, err := vm.Reconfigure(ctx, spec) 463 464 if err != nil { 465 log.Errorf("vm.Reconfigure fail %s", err) 466 return err 467 } 468 469 err = task.Wait(ctx) 470 if err != nil { 471 log.Errorf("task.Wait fail %s", err) 472 return err 473 } 474 475 return err 476 } 477 478 func (disk *SVirtualDisk) ResizePartition(ctx context.Context, accessInfo vcenter.SVCenterAccessInfo) error { 479 diskPath := disk.GetFilename() 480 vmref := disk.vm.GetMoid() 481 diskInfo := deployapi.DiskInfo{ 482 Path: diskPath, 483 } 484 vddkInfo := deployapi.VDDKConInfo{ 485 Host: accessInfo.Host, 486 Port: int32(accessInfo.Port), 487 User: accessInfo.Account, 488 Passwd: accessInfo.Password, 489 Vmref: vmref, 490 } 491 _, err := deployclient.GetDeployClient().ResizeFs(ctx, &deployapi.ResizeFsParams{ 492 DiskInfo: &diskInfo, 493 Hypervisor: compute.HYPERVISOR_ESXI, 494 VddkInfo: &vddkInfo, 495 }) 496 if err != nil { 497 return errors.Wrap(err, "unable to ResizeFs") 498 } 499 return nil 500 } 501 502 func (disk *SVirtualDisk) Reset(ctx context.Context, snapshotId string) (string, error) { 503 return "", cloudprovider.ErrNotImplemented 504 } 505 506 func (disk *SVirtualDisk) GetBillingType() string { 507 return "" 508 } 509 510 // GetCreatedAt return create time by getting the Data of file stored at disk.GetAccessPath 511 func (disk *SVirtualDisk) GetCreatedAt() time.Time { 512 path, name := disk.GetAccessPath(), disk.GetFilename() 513 storage, err := disk.GetIStorage() 514 if err != nil { 515 return time.Time{} 516 } 517 ds := storage.(*SDatastore) 518 files, err := ds.ListDir(context.Background(), filepath.Dir(path)) 519 if err != nil { 520 return time.Time{} 521 } 522 for _, file := range files { 523 if file.Name == name { 524 return file.Date 525 } 526 } 527 return time.Time{} 528 } 529 530 func (disk *SVirtualDisk) GetExpiredAt() time.Time { 531 return time.Time{} 532 } 533 534 func (disk *SVirtualDisk) Rebuild(ctx context.Context) error { 535 return disk.vm.rebuildDisk(ctx, disk, "") 536 } 537 538 func (disk *SVirtualDisk) GetProjectId() string { 539 return disk.vm.GetProjectId() 540 } 541 542 func (disk *SVirtualDisk) GetFilename() string { 543 return disk.getBackingInfo().GetFileName() 544 }