github.com/vmware/govmomi@v0.51.0/vslm/object_manager.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package vslm
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  
    11  	"github.com/vmware/govmomi/object"
    12  	"github.com/vmware/govmomi/vim25"
    13  	"github.com/vmware/govmomi/vim25/methods"
    14  	"github.com/vmware/govmomi/vim25/mo"
    15  	"github.com/vmware/govmomi/vim25/types"
    16  )
    17  
    18  // ObjectManager wraps VStorageObjectManagerBase.
    19  type ObjectManager struct {
    20  	types.ManagedObjectReference
    21  	c    *vim25.Client
    22  	isVC bool
    23  }
    24  
    25  // NewObjectManager returns an ObjectManager referencing the VcenterVStorageObjectManager singleton when connected to vCenter or
    26  // the HostVStorageObjectManager singleton when connected to an ESX host.  The optional ref param can be used to specify a ESX
    27  // host instead, when connected to vCenter.
    28  func NewObjectManager(client *vim25.Client, ref ...types.ManagedObjectReference) *ObjectManager {
    29  	mref := *client.ServiceContent.VStorageObjectManager
    30  
    31  	if len(ref) == 1 {
    32  		mref = ref[0]
    33  	}
    34  
    35  	m := ObjectManager{
    36  		ManagedObjectReference: mref,
    37  		c:                      client,
    38  		isVC:                   mref.Type == "VcenterVStorageObjectManager",
    39  	}
    40  
    41  	return &m
    42  }
    43  
    44  // PlaceDisk uses StorageResourceManager datastore placement recommendations to choose a Datastore from a Datastore cluster.
    45  // If the given spec backing Datastore field is not that of type StoragePod, the spec is unmodifed.
    46  // Otherwise, the backing Datastore field is replaced with a Datastore suggestion.
    47  func (m ObjectManager) PlaceDisk(ctx context.Context, spec *types.VslmCreateSpec, pool types.ManagedObjectReference) error {
    48  	backing := spec.BackingSpec.GetVslmCreateSpecBackingSpec()
    49  	if backing.Datastore.Type != "StoragePod" {
    50  		return nil
    51  	}
    52  
    53  	device := &types.VirtualDisk{
    54  		VirtualDevice: types.VirtualDevice{
    55  			Key: 0,
    56  			Backing: &types.VirtualDiskFlatVer2BackingInfo{
    57  				DiskMode:        string(types.VirtualDiskModePersistent),
    58  				ThinProvisioned: types.NewBool(true),
    59  			},
    60  			UnitNumber: types.NewInt32(0),
    61  		},
    62  		CapacityInKB: spec.CapacityInMB * 1024,
    63  	}
    64  
    65  	storage := types.StoragePlacementSpec{
    66  		Type:         string(types.StoragePlacementSpecPlacementTypeCreate),
    67  		ResourcePool: &pool,
    68  		PodSelectionSpec: types.StorageDrsPodSelectionSpec{
    69  			StoragePod: &backing.Datastore,
    70  			InitialVmConfig: []types.VmPodConfigForPlacement{
    71  				{
    72  					StoragePod: backing.Datastore,
    73  					Disk: []types.PodDiskLocator{
    74  						{
    75  							DiskId:          device.Key,
    76  							DiskBackingInfo: device.Backing,
    77  						},
    78  					},
    79  				},
    80  			},
    81  		},
    82  		ConfigSpec: &types.VirtualMachineConfigSpec{
    83  			Name: spec.Name,
    84  			DeviceChange: []types.BaseVirtualDeviceConfigSpec{
    85  				&types.VirtualDeviceConfigSpec{
    86  					Operation:     types.VirtualDeviceConfigSpecOperationAdd,
    87  					FileOperation: types.VirtualDeviceConfigSpecFileOperationCreate,
    88  					Device:        device,
    89  				},
    90  			},
    91  		},
    92  	}
    93  
    94  	req := types.RecommendDatastores{
    95  		This:        *m.c.ServiceContent.StorageResourceManager,
    96  		StorageSpec: storage,
    97  	}
    98  
    99  	res, err := methods.RecommendDatastores(ctx, m.c, &req)
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	r := res.Returnval.Recommendations
   105  	if len(r) == 0 {
   106  		return errors.New("no storage placement recommendations")
   107  	}
   108  
   109  	backing.Datastore = r[0].Action[0].(*types.StoragePlacementAction).Destination
   110  
   111  	return nil
   112  }
   113  
   114  func (m ObjectManager) CreateDisk(ctx context.Context, spec types.VslmCreateSpec) (*object.Task, error) {
   115  	req := types.CreateDisk_Task{
   116  		This: m.Reference(),
   117  		Spec: spec,
   118  	}
   119  
   120  	if m.isVC {
   121  		res, err := methods.CreateDisk_Task(ctx, m.c, &req)
   122  		if err != nil {
   123  			return nil, err
   124  		}
   125  
   126  		return object.NewTask(m.c, res.Returnval), nil
   127  	}
   128  
   129  	res, err := methods.HostCreateDisk_Task(ctx, m.c, (*types.HostCreateDisk_Task)(&req))
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	return object.NewTask(m.c, res.Returnval), nil
   135  }
   136  
   137  func (m ObjectManager) Rename(ctx context.Context, ds mo.Reference, id, name string) error {
   138  	req := types.RenameVStorageObject{
   139  		This:      m.Reference(),
   140  		Datastore: ds.Reference(),
   141  		Id:        types.ID{Id: id},
   142  		Name:      name,
   143  	}
   144  
   145  	if m.isVC {
   146  		_, err := methods.RenameVStorageObject(ctx, m.c, &req)
   147  		return err
   148  	}
   149  
   150  	_, err := methods.HostRenameVStorageObject(ctx, m.c, (*types.HostRenameVStorageObject)(&req))
   151  	return err
   152  }
   153  
   154  func (m ObjectManager) Delete(ctx context.Context, ds mo.Reference, id string) (*object.Task, error) {
   155  	req := types.DeleteVStorageObject_Task{
   156  		This:      m.Reference(),
   157  		Datastore: ds.Reference(),
   158  		Id:        types.ID{Id: id},
   159  	}
   160  
   161  	if m.isVC {
   162  		res, err := methods.DeleteVStorageObject_Task(ctx, m.c, &req)
   163  		if err != nil {
   164  			return nil, err
   165  		}
   166  
   167  		return object.NewTask(m.c, res.Returnval), nil
   168  	}
   169  
   170  	res, err := methods.HostDeleteVStorageObject_Task(ctx, m.c, (*types.HostDeleteVStorageObject_Task)(&req))
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  
   175  	return object.NewTask(m.c, res.Returnval), nil
   176  }
   177  
   178  func (m ObjectManager) Retrieve(ctx context.Context, ds mo.Reference, id string) (*types.VStorageObject, error) {
   179  	req := types.RetrieveVStorageObject{
   180  		This:      m.Reference(),
   181  		Datastore: ds.Reference(),
   182  		Id:        types.ID{Id: id},
   183  	}
   184  
   185  	if m.isVC {
   186  		res, err := methods.RetrieveVStorageObject(ctx, m.c, &req)
   187  		if err != nil {
   188  			return nil, err
   189  		}
   190  
   191  		return &res.Returnval, nil
   192  	}
   193  
   194  	res, err := methods.HostRetrieveVStorageObject(ctx, m.c, (*types.HostRetrieveVStorageObject)(&req))
   195  	if err != nil {
   196  		return nil, err
   197  	}
   198  
   199  	return &res.Returnval, nil
   200  }
   201  
   202  func (m ObjectManager) List(ctx context.Context, ds mo.Reference) ([]types.ID, error) {
   203  	req := types.ListVStorageObject{
   204  		This:      m.Reference(),
   205  		Datastore: ds.Reference(),
   206  	}
   207  
   208  	if m.isVC {
   209  		res, err := methods.ListVStorageObject(ctx, m.c, &req)
   210  		if err != nil {
   211  			return nil, err
   212  		}
   213  
   214  		return res.Returnval, nil
   215  	}
   216  
   217  	res, err := methods.HostListVStorageObject(ctx, m.c, (*types.HostListVStorageObject)(&req))
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  
   222  	return res.Returnval, nil
   223  }
   224  
   225  func (m ObjectManager) RegisterDisk(ctx context.Context, path, name string) (*types.VStorageObject, error) {
   226  	req := types.RegisterDisk{
   227  		This: m.Reference(),
   228  		Path: path,
   229  		Name: name,
   230  	}
   231  
   232  	if m.isVC {
   233  		res, err := methods.RegisterDisk(ctx, m.c, &req)
   234  		if err != nil {
   235  			return nil, err
   236  		}
   237  
   238  		return &res.Returnval, nil
   239  	}
   240  
   241  	res, err := methods.HostRegisterDisk(ctx, m.c, &types.HostRegisterDisk{
   242  		This: m.Reference(),
   243  		Path: path,
   244  		Name: name,
   245  	})
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  
   250  	return &res.Returnval, nil
   251  }
   252  
   253  func (m ObjectManager) ExtendDisk(ctx context.Context, ds mo.Reference, id string, newCapacityInMB int64) (*object.Task, error) {
   254  	req := types.ExtendDisk_Task{
   255  		This:            m.Reference(),
   256  		Id:              types.ID{Id: id},
   257  		Datastore:       ds.Reference(),
   258  		NewCapacityInMB: newCapacityInMB,
   259  	}
   260  
   261  	if m.isVC {
   262  		res, err := methods.ExtendDisk_Task(ctx, m.c, &req)
   263  		if err != nil {
   264  			return nil, err
   265  		}
   266  
   267  		return object.NewTask(m.c, res.Returnval), nil
   268  	}
   269  
   270  	res, err := methods.HostExtendDisk_Task(ctx, m.c, (*types.HostExtendDisk_Task)(&req))
   271  	if err != nil {
   272  		return nil, err
   273  	}
   274  
   275  	return object.NewTask(m.c, res.Returnval), nil
   276  }
   277  
   278  func (m ObjectManager) InflateDisk(ctx context.Context, ds mo.Reference, id string) (*object.Task, error) {
   279  	req := types.InflateDisk_Task{
   280  		This:      m.Reference(),
   281  		Id:        types.ID{Id: id},
   282  		Datastore: ds.Reference(),
   283  	}
   284  
   285  	if m.isVC {
   286  		res, err := methods.InflateDisk_Task(ctx, m.c, &req)
   287  		if err != nil {
   288  			return nil, err
   289  		}
   290  
   291  		return object.NewTask(m.c, res.Returnval), nil
   292  	}
   293  
   294  	res, err := methods.HostInflateDisk_Task(ctx, m.c, (*types.HostInflateDisk_Task)(&req))
   295  	if err != nil {
   296  		return nil, err
   297  	}
   298  
   299  	return object.NewTask(m.c, res.Returnval), nil
   300  }
   301  
   302  func (m ObjectManager) Clone(ctx context.Context, ds mo.Reference, id string, spec types.VslmCloneSpec) (*object.Task, error) {
   303  	req := types.CloneVStorageObject_Task{
   304  		This:      m.Reference(),
   305  		Datastore: ds.Reference(),
   306  		Id:        types.ID{Id: id},
   307  		Spec:      spec,
   308  	}
   309  
   310  	if m.isVC {
   311  		res, err := methods.CloneVStorageObject_Task(ctx, m.c, &req)
   312  		if err != nil {
   313  			return nil, err
   314  		}
   315  
   316  		return object.NewTask(m.c, res.Returnval), nil
   317  	}
   318  
   319  	res, err := methods.HostCloneVStorageObject_Task(ctx, m.c, (*types.HostCloneVStorageObject_Task)(&req))
   320  	if err != nil {
   321  		return nil, err
   322  	}
   323  
   324  	return object.NewTask(m.c, res.Returnval), nil
   325  }
   326  
   327  func (m ObjectManager) CreateSnapshot(ctx context.Context, ds mo.Reference, id, desc string) (*object.Task, error) {
   328  	req := types.VStorageObjectCreateSnapshot_Task{
   329  		This:        m.Reference(),
   330  		Id:          types.ID{Id: id},
   331  		Description: desc,
   332  		Datastore:   ds.Reference(),
   333  	}
   334  
   335  	if m.isVC {
   336  		res, err := methods.VStorageObjectCreateSnapshot_Task(ctx, m.c, &req)
   337  		if err != nil {
   338  			return nil, err
   339  		}
   340  
   341  		return object.NewTask(m.c, res.Returnval), nil
   342  	}
   343  
   344  	res, err := methods.HostVStorageObjectCreateSnapshot_Task(ctx, m.c, (*types.HostVStorageObjectCreateSnapshot_Task)(&req))
   345  	if err != nil {
   346  		return nil, err
   347  	}
   348  
   349  	return object.NewTask(m.c, res.Returnval), nil
   350  }
   351  
   352  func (m ObjectManager) DeleteSnapshot(ctx context.Context, ds mo.Reference, id, sid string) (*object.Task, error) {
   353  	req := types.DeleteSnapshot_Task{
   354  		This:       m.Reference(),
   355  		Datastore:  ds.Reference(),
   356  		Id:         types.ID{Id: id},
   357  		SnapshotId: types.ID{Id: sid},
   358  	}
   359  
   360  	if m.isVC {
   361  		res, err := methods.DeleteSnapshot_Task(ctx, m.c, &req)
   362  		if err != nil {
   363  			return nil, err
   364  		}
   365  
   366  		return object.NewTask(m.c, res.Returnval), nil
   367  	}
   368  
   369  	res, err := methods.HostVStorageObjectDeleteSnapshot_Task(ctx, m.c, (*types.HostVStorageObjectDeleteSnapshot_Task)(&req))
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  
   374  	return object.NewTask(m.c, res.Returnval), nil
   375  }
   376  
   377  func (m ObjectManager) RetrieveSnapshotInfo(ctx context.Context, ds mo.Reference, id string) (*types.VStorageObjectSnapshotInfo, error) {
   378  	req := types.RetrieveSnapshotInfo{
   379  		This:      m.Reference(),
   380  		Datastore: ds.Reference(),
   381  		Id:        types.ID{Id: id},
   382  	}
   383  
   384  	if m.isVC {
   385  		res, err := methods.RetrieveSnapshotInfo(ctx, m.c, &req)
   386  		if err != nil {
   387  			return nil, err
   388  		}
   389  
   390  		return &res.Returnval, nil
   391  	}
   392  
   393  	res, err := methods.HostVStorageObjectRetrieveSnapshotInfo(ctx, m.c, (*types.HostVStorageObjectRetrieveSnapshotInfo)(&req))
   394  	if err != nil {
   395  		return nil, err
   396  	}
   397  
   398  	return &res.Returnval, nil
   399  }
   400  
   401  func (m ObjectManager) AttachTag(ctx context.Context, id string, tag types.VslmTagEntry) error {
   402  	req := &types.AttachTagToVStorageObject{
   403  		This:     m.ManagedObjectReference,
   404  		Id:       types.ID{Id: id},
   405  		Category: tag.ParentCategoryName,
   406  		Tag:      tag.TagName,
   407  	}
   408  
   409  	_, err := methods.AttachTagToVStorageObject(ctx, m.c, req)
   410  	return err
   411  }
   412  
   413  func (m ObjectManager) DetachTag(ctx context.Context, id string, tag types.VslmTagEntry) error {
   414  	req := &types.DetachTagFromVStorageObject{
   415  		This:     m.ManagedObjectReference,
   416  		Id:       types.ID{Id: id},
   417  		Category: tag.ParentCategoryName,
   418  		Tag:      tag.TagName,
   419  	}
   420  
   421  	_, err := methods.DetachTagFromVStorageObject(ctx, m.c, req)
   422  	return err
   423  }
   424  
   425  func (m ObjectManager) ListAttachedObjects(ctx context.Context, category, tag string) ([]types.ID, error) {
   426  	req := &types.ListVStorageObjectsAttachedToTag{
   427  		This:     m.ManagedObjectReference,
   428  		Category: category,
   429  		Tag:      tag,
   430  	}
   431  
   432  	res, err := methods.ListVStorageObjectsAttachedToTag(ctx, m.c, req)
   433  	if err != nil {
   434  		return nil, err
   435  	}
   436  	return res.Returnval, nil
   437  }
   438  
   439  func (m ObjectManager) ListAttachedTags(ctx context.Context, id string) ([]types.VslmTagEntry, error) {
   440  	req := &types.ListTagsAttachedToVStorageObject{
   441  		This: m.ManagedObjectReference,
   442  		Id:   types.ID{Id: id},
   443  	}
   444  
   445  	res, err := methods.ListTagsAttachedToVStorageObject(ctx, m.c, req)
   446  	if err != nil {
   447  		return nil, err
   448  	}
   449  	return res.Returnval, nil
   450  }
   451  
   452  func (m ObjectManager) ReconcileDatastoreInventory(ctx context.Context, ds mo.Reference) (*object.Task, error) {
   453  	req := &types.ReconcileDatastoreInventory_Task{
   454  		This:      m.Reference(),
   455  		Datastore: ds.Reference(),
   456  	}
   457  
   458  	res, err := methods.ReconcileDatastoreInventory_Task(ctx, m.c, req)
   459  	if err != nil {
   460  		return nil, err
   461  	}
   462  	return object.NewTask(m.c, res.Returnval), nil
   463  }