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 }