// findDatastore finds Datastore object. func findDatastore(c *govmomi.Client, sps types.StoragePlacementSpec) (*object.Datastore, error) { var datastore *object.Datastore log.Printf("[DEBUG] findDatastore: StoragePlacementSpec: %#v\n", sps) srm := object.NewStorageResourceManager(c.Client) rds, err := srm.RecommendDatastores(context.TODO(), sps) if err != nil { return nil, err } log.Printf("[DEBUG] findDatastore: recommendDatastores: %#v\n", rds) spa := rds.Recommendations[0].Action[0].(*types.StoragePlacementAction) datastore = object.NewDatastore(c.Client, spa.Destination) log.Printf("[DEBUG] findDatastore: datastore: %#v", datastore) return datastore, nil }
func (cmd *clone) cloneVM(ctx context.Context) (*object.Task, error) { // search for the first network card of the source devices, err := cmd.VirtualMachine.Device(ctx) if err != nil { return nil, err } var card *types.VirtualEthernetCard for _, device := range devices { if c, ok := device.(types.BaseVirtualEthernetCard); ok { card = c.GetVirtualEthernetCard() break } } if card == nil { return nil, fmt.Errorf("No network device found.") } // get the new backing information dev, err := cmd.NetworkFlag.Device() if err != nil { return nil, err } //set backing info card.Backing = dev.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard().Backing // prepare virtual device config spec for network card configSpecs := []types.BaseVirtualDeviceConfigSpec{ &types.VirtualDeviceConfigSpec{ Operation: types.VirtualDeviceConfigSpecOperationEdit, Device: card, }, } folderref := cmd.Folder.Reference() poolref := cmd.ResourcePool.Reference() relocateSpec := types.VirtualMachineRelocateSpec{ DeviceChange: configSpecs, Folder: &folderref, Pool: &poolref, } if cmd.HostSystem != nil { hostref := cmd.HostSystem.Reference() relocateSpec.Host = &hostref } cloneSpec := &types.VirtualMachineCloneSpec{ Location: relocateSpec, PowerOn: false, Template: cmd.template, } // clone to storage pod datastoreref := types.ManagedObjectReference{} if cmd.StoragePod != nil && cmd.Datastore == nil { storagePod := cmd.StoragePod.Reference() // Build pod selection spec from config spec podSelectionSpec := types.StorageDrsPodSelectionSpec{ StoragePod: &storagePod, } // Get the virtual machine reference vmref := cmd.VirtualMachine.Reference() // Build the placement spec storagePlacementSpec := types.StoragePlacementSpec{ Folder: &folderref, Vm: &vmref, CloneName: cmd.name, CloneSpec: cloneSpec, PodSelectionSpec: podSelectionSpec, Type: string(types.StoragePlacementSpecPlacementTypeClone), } // Get the storage placement result storageResourceManager := object.NewStorageResourceManager(cmd.Client) result, err := storageResourceManager.RecommendDatastores(ctx, storagePlacementSpec) if err != nil { return nil, err } // Get the recommendations recommendations := result.Recommendations if len(recommendations) == 0 { return nil, fmt.Errorf("no recommendations") } // Get the first recommendation datastoreref = recommendations[0].Action[0].(*types.StoragePlacementAction).Destination } else if cmd.StoragePod == nil && cmd.Datastore != nil { datastoreref = cmd.Datastore.Reference() } else { return nil, fmt.Errorf("Please provide either a datastore or a storagepod") } // Set the destination datastore cloneSpec.Location.Datastore = &datastoreref // Check if vmx already exists if !cmd.force { vmxPath := fmt.Sprintf("%s/%s.vmx", cmd.name, cmd.name) datastore := object.NewDatastore(cmd.Client, datastoreref) _, err := datastore.Stat(ctx, vmxPath) if err == nil { dsPath := cmd.Datastore.Path(vmxPath) return nil, fmt.Errorf("File %s already exists", dsPath) } } // check if customization specification requested if len(cmd.customization) > 0 { // get the customization spec manager customizationSpecManager := object.NewCustomizationSpecManager(cmd.Client) // check if customization specification exists exists, err := customizationSpecManager.DoesCustomizationSpecExist(ctx, cmd.customization) if err != nil { return nil, err } if exists == false { return nil, fmt.Errorf("Customization specification %s does not exists.", cmd.customization) } // get the customization specification customSpecItem, err := customizationSpecManager.GetCustomizationSpec(ctx, cmd.customization) if err != nil { return nil, err } customSpec := customSpecItem.Spec // set the customization cloneSpec.Customization = &customSpec } // clone virtualmachine return cmd.VirtualMachine.Clone(ctx, cmd.Folder, cmd.name, *cloneSpec) }
// createVirtualMchine creates a new VirtualMachine. func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error { var dc *object.Datacenter var err error finder := find.NewFinder(c.Client, true) if vm.datacenter != "" { dc, err = finder.Datacenter(context.TODO(), vm.datacenter) if err != nil { return err } } else { dc, err = finder.DefaultDatacenter(context.TODO()) if err != nil { return err } } finder = finder.SetDatacenter(dc) var resourcePool *object.ResourcePool if vm.resourcePool == "" { if vm.cluster == "" { resourcePool, err = finder.DefaultResourcePool(context.TODO()) if err != nil { return err } } else { resourcePool, err = finder.ResourcePool(context.TODO(), "*"+vm.cluster+"/Resources") if err != nil { return err } } } else { resourcePool, err = finder.ResourcePool(context.TODO(), vm.resourcePool) if err != nil { return err } } log.Printf("[DEBUG] resource pool: %#v", resourcePool) dcFolders, err := dc.Folders(context.TODO()) if err != nil { return err } // network networkDevices := []types.BaseVirtualDeviceConfigSpec{} for _, network := range vm.networkInterfaces { // network device nd, err := createNetworkDevice(finder, network.label, "e1000") if err != nil { return err } networkDevices = append(networkDevices, nd) } // make config spec configSpec := types.VirtualMachineConfigSpec{ GuestId: "otherLinux64Guest", Name: vm.name, NumCPUs: vm.vcpu, NumCoresPerSocket: 1, MemoryMB: vm.memoryMb, DeviceChange: networkDevices, } log.Printf("[DEBUG] virtual machine config spec: %v", configSpec) var datastore *object.Datastore if vm.datastore == "" { datastore, err = finder.DefaultDatastore(context.TODO()) if err != nil { return err } } else { s := object.NewSearchIndex(c.Client) ref, err := s.FindChild(context.TODO(), dcFolders.DatastoreFolder, vm.datastore) if err != nil { return err } log.Printf("[DEBUG] findDatastore: reference: %#v", ref) mor := ref.Reference() if mor.Type == "StoragePod" { storagePod := object.NewFolder(c.Client, mor) vmfr := dcFolders.VmFolder.Reference() rpr := resourcePool.Reference() spr := storagePod.Reference() sps := types.StoragePlacementSpec{ Type: "create", ConfigSpec: &configSpec, PodSelectionSpec: types.StorageDrsPodSelectionSpec{ StoragePod: &spr, }, Folder: &vmfr, ResourcePool: &rpr, } log.Printf("[DEBUG] findDatastore: StoragePlacementSpec: %#v\n", sps) srm := object.NewStorageResourceManager(c.Client) rds, err := srm.RecommendDatastores(context.TODO(), sps) if err != nil { return err } log.Printf("[DEBUG] findDatastore: recommendDatastores: %#v\n", rds) spa := rds.Recommendations[0].Action[0].(*types.StoragePlacementAction) datastore = object.NewDatastore(c.Client, spa.Destination) if err != nil { return err } } else { datastore = object.NewDatastore(c.Client, mor) } } log.Printf("[DEBUG] datastore: %#v", datastore) var mds mo.Datastore if err = datastore.Properties(context.TODO(), datastore.Reference(), []string{"name"}, &mds); err != nil { return err } log.Printf("[DEBUG] datastore: %#v", mds.Name) scsi, err := object.SCSIControllerTypes().CreateSCSIController("scsi") if err != nil { log.Printf("[ERROR] %s", err) } configSpec.DeviceChange = append(configSpec.DeviceChange, &types.VirtualDeviceConfigSpec{ Operation: types.VirtualDeviceConfigSpecOperationAdd, Device: scsi, }) configSpec.Files = &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", mds.Name)} task, err := dcFolders.VmFolder.CreateVM(context.TODO(), configSpec, resourcePool, nil) if err != nil { log.Printf("[ERROR] %s", err) } err = task.Wait(context.TODO()) if err != nil { log.Printf("[ERROR] %s", err) } newVM, err := finder.VirtualMachine(context.TODO(), vm.name) if err != nil { return err } log.Printf("[DEBUG] new vm: %v", newVM) log.Printf("[DEBUG] add hard disk: %v", vm.hardDisks) for _, hd := range vm.hardDisks { log.Printf("[DEBUG] add hard disk: %v", hd.size) log.Printf("[DEBUG] add hard disk: %v", hd.iops) err = addHardDisk(newVM, hd.size, hd.iops, "thin") if err != nil { return err } } return nil }
func (cmd *create) recommendDatastore(ctx context.Context, spec *types.VirtualMachineConfigSpec) (*object.Datastore, error) { sp := cmd.StoragePod.Reference() // Build pod selection spec from config spec podSelectionSpec := types.StorageDrsPodSelectionSpec{ StoragePod: &sp, } // Keep list of disks that need to be placed var disks []*types.VirtualDisk // Collect disks eligible for placement for _, deviceConfigSpec := range spec.DeviceChange { s := deviceConfigSpec.GetVirtualDeviceConfigSpec() if s.Operation != types.VirtualDeviceConfigSpecOperationAdd { continue } if s.FileOperation != types.VirtualDeviceConfigSpecFileOperationCreate { continue } d, ok := s.Device.(*types.VirtualDisk) if !ok { continue } podConfigForPlacement := types.VmPodConfigForPlacement{ StoragePod: sp, Disk: []types.PodDiskLocator{ { DiskId: d.Key, DiskBackingInfo: d.Backing, }, }, } podSelectionSpec.InitialVmConfig = append(podSelectionSpec.InitialVmConfig, podConfigForPlacement) disks = append(disks, d) } sps := types.StoragePlacementSpec{ Type: string(types.StoragePlacementSpecPlacementTypeCreate), ResourcePool: types.NewReference(cmd.ResourcePool.Reference()), PodSelectionSpec: podSelectionSpec, ConfigSpec: spec, } srm := object.NewStorageResourceManager(cmd.Client) result, err := srm.RecommendDatastores(ctx, sps) if err != nil { return nil, err } // Use result to pin disks to recommended datastores recs := result.Recommendations if len(recs) == 0 { return nil, fmt.Errorf("no recommendations") } ds := recs[0].Action[0].(*types.StoragePlacementAction).Destination var mds mo.Datastore err = property.DefaultCollector(cmd.Client).RetrieveOne(ctx, ds, []string{"name"}, &mds) if err != nil { return nil, err } datastore := object.NewDatastore(cmd.Client, ds) datastore.InventoryPath = mds.Name // Apply recommendation to eligible disks for _, disk := range disks { backing := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo) backing.Datastore = &ds } return datastore, nil }
// findDatastore finds Datastore object. func findDatastore(c *govmomi.Client, f *object.DatacenterFolders, vm *object.VirtualMachine, rp *object.ResourcePool, name string) (*object.Datastore, error) { var datastore *object.Datastore s := object.NewSearchIndex(c.Client) ref, err := s.FindChild(context.TODO(), f.DatastoreFolder, name) if err != nil { return nil, err } log.Printf("[DEBUG] findDatastore: reference: %#v", ref) mor := ref.Reference() if mor.Type == "StoragePod" { storagePod := object.NewFolder(c.Client, mor) vmr := vm.Reference() vmfr := f.VmFolder.Reference() rpr := rp.Reference() spr := storagePod.Reference() var o mo.VirtualMachine err := vm.Properties(context.TODO(), vmr, []string{"datastore"}, &o) if err != nil { return nil, err } ds := object.NewDatastore(c.Client, o.Datastore[0]) log.Printf("[DEBUG] findDatastore: datastore: %#v\n", ds) devices, err := vm.Device(context.TODO()) if err != nil { return nil, err } var key int for _, d := range devices.SelectByType((*types.VirtualDisk)(nil)) { key = d.GetVirtualDevice().Key log.Printf("[DEBUG] findDatastore: virtual devices: %#v\n", d.GetVirtualDevice()) } sps := types.StoragePlacementSpec{ Type: "clone", Vm: &vmr, PodSelectionSpec: types.StorageDrsPodSelectionSpec{ StoragePod: &spr, }, CloneSpec: &types.VirtualMachineCloneSpec{ Location: types.VirtualMachineRelocateSpec{ Disk: []types.VirtualMachineRelocateSpecDiskLocator{ types.VirtualMachineRelocateSpecDiskLocator{ Datastore: ds.Reference(), DiskBackingInfo: &types.VirtualDiskFlatVer2BackingInfo{}, DiskId: key, }, }, Pool: &rpr, }, PowerOn: false, Template: false, }, CloneName: "dummy", Folder: &vmfr, } log.Printf("[DEBUG] findDatastore: StoragePlacementSpec: %#v\n", sps) srm := object.NewStorageResourceManager(c.Client) rds, err := srm.RecommendDatastores(context.TODO(), sps) if err != nil { return nil, err } log.Printf("[DEBUG] findDatastore: recommendDatastores: %#v\n", rds) spa := rds.Recommendations[0].Action[0].(*types.StoragePlacementAction) datastore = object.NewDatastore(c.Client, spa.Destination) } else { datastore = object.NewDatastore(c.Client, mor) } log.Printf("[DEBUG] findDatastore: datastore: %#v", datastore) return datastore, nil }