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  }