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 }