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

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