// buildVMRelocateSpec builds VirtualMachineRelocateSpec to set a place for a new VirtualMachine. func buildVMRelocateSpec(rp *object.ResourcePool, ds *object.Datastore, vm *object.VirtualMachine) (types.VirtualMachineRelocateSpec, error) { var key int devices, err := vm.Device(context.TODO()) if err != nil { return types.VirtualMachineRelocateSpec{}, err } for _, d := range devices { if devices.Type(d) == "disk" { key = d.GetVirtualDevice().Key } } rpr := rp.Reference() dsr := ds.Reference() return types.VirtualMachineRelocateSpec{ Datastore: &dsr, Pool: &rpr, Disk: []types.VirtualMachineRelocateSpecDiskLocator{ types.VirtualMachineRelocateSpecDiskLocator{ Datastore: dsr, DiskBackingInfo: &types.VirtualDiskFlatVer2BackingInfo{ DiskMode: "persistent", ThinProvisioned: types.NewBool(false), EagerlyScrub: types.NewBool(true), }, DiskId: key, }, }, }, nil }
func (d *Dispatcher) NewVCHFromComputePath(computePath string, name string, v *validate.Validator) (*vm.VirtualMachine, error) { defer trace.End(trace.Begin(fmt.Sprintf("path %q, name %q", computePath, name))) var err error parent, err := v.ResourcePoolHelper(d.ctx, computePath) if err != nil { return nil, err } d.vchPoolPath = path.Join(parent.InventoryPath, name) var vchPool *object.ResourcePool if d.isVC { vapp, err := d.findVirtualApp(d.vchPoolPath) if err != nil { log.Errorf("Failed to get VCH virtual app %q: %s", d.vchPoolPath, err) return nil, err } if vapp != nil { vchPool = vapp.ResourcePool } } if vchPool == nil { vchPool, err = d.session.Finder.ResourcePool(d.ctx, d.vchPoolPath) if err != nil { log.Errorf("Failed to get VCH resource pool %q: %s", d.vchPoolPath, err) return nil, err } } rp := compute.NewResourcePool(d.ctx, d.session, vchPool.Reference()) var vmm *vm.VirtualMachine if vmm, err = rp.GetChildVM(d.ctx, d.session, name); err != nil { log.Errorf("Failed to get VCH VM: %s", err) return nil, err } if vmm == nil { err = errors.Errorf("Didn't find VM %q in resource pool %q", name, rp.Name()) log.Error(err) return nil, err } vmm.InventoryPath = path.Join(d.vchPoolPath, name) // check if it's VCH var ok bool if ok, err = d.isVCH(vmm); err != nil { log.Error(err) return nil, err } if !ok { err = errors.Errorf("Not a VCH") log.Error(err) return nil, err } return vmm, nil }
func createNodes(ctx context.Context, sess *session.Session, pool *object.ResourcePool, node *Node, base string) error { log.Debugf("create node %+v", node) if node == nil { return nil } spec := simulator.NewResourceConfigSpec() node.Name = fmt.Sprintf("%s-%s", base, node.Name) switch node.Kind { case rpNode: child, err := pool.Create(ctx, node.Name, spec) if err != nil { return err } for _, childNode := range node.Children { return createNodes(ctx, sess, child, childNode, base) } case vappNode: confSpec := types.VAppConfigSpec{ VmConfigSpec: types.VmConfigSpec{}, } vapp, err := pool.CreateVApp(ctx, node.Name, spec, confSpec, nil) if err != nil { return err } config := types.VirtualMachineConfigSpec{ Name: node.Name, GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest), Files: &types.VirtualMachineFileInfo{ VmPathName: fmt.Sprintf("[LocalDS_0] %s", node.Name), }, } if _, err = tasks.WaitForResult(ctx, func(ctx context.Context) (tasks.Task, error) { return vapp.CreateChildVM_Task(ctx, config, nil) }); err != nil { return err } case vmNode: config := types.VirtualMachineConfigSpec{ Name: node.Name, GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest), Files: &types.VirtualMachineFileInfo{ VmPathName: fmt.Sprintf("[LocalDS_0] %s", node.Name), }, } folder := sess.Folders(ctx).VmFolder if _, err := tasks.WaitForResult(ctx, func(ctx context.Context) (tasks.Task, error) { return folder.CreateVM(ctx, config, pool, nil) }); err != nil { return err } default: return nil } return nil }
// buildVMRelocateSpec builds VirtualMachineRelocateSpec to set a place for a new VirtualMachine. func buildVMRelocateSpec(finder *find.Finder, rp *object.ResourcePool, ds *object.Datastore, vm *object.VirtualMachine, linked bool) (types.VirtualMachineRelocateSpec, error) { var key int var parent *types.VirtualDiskFlatVer2BackingInfo devices, err := vm.Device(context.TODO()) if err != nil { return types.VirtualMachineRelocateSpec{}, err } for _, d := range devices { if devices.Type(d) == "disk" { vd := d.GetVirtualDevice() parent = vd.Backing.(*types.VirtualDiskFlatVer2BackingInfo) key = vd.Key } } rpr := rp.Reference() relocateSpec := types.VirtualMachineRelocateSpec{} // Treat linked clones a bit differently. if linked { parentDs := strings.SplitN(parent.FileName[1:], "]", 2) parentDsObj, err := finder.Datastore(context.TODO(), parentDs[0]) if err != nil { return types.VirtualMachineRelocateSpec{}, err } parentDbObjRef := parentDsObj.Reference() relocateSpec = types.VirtualMachineRelocateSpec{ Datastore: &parentDbObjRef, Pool: &rpr, DiskMoveType: "createNewChildDiskBacking", } } else { dsr := ds.Reference() relocateSpec = types.VirtualMachineRelocateSpec{ Datastore: &dsr, Pool: &rpr, Disk: []types.VirtualMachineRelocateSpecDiskLocator{ types.VirtualMachineRelocateSpecDiskLocator{ Datastore: dsr, DiskId: key, DiskBackingInfo: &types.VirtualDiskFlatVer2BackingInfo{ DiskMode: "persistent", ThinProvisioned: types.NewBool(false), EagerlyScrub: types.NewBool(true), }, }, }, } } return relocateSpec, nil }
// buildStoragePlacementSpecClone builds StoragePlacementSpec for clone action. func buildStoragePlacementSpecClone(c *govmomi.Client, f *object.DatacenterFolders, vm *object.VirtualMachine, rp *object.ResourcePool, storagePod object.StoragePod) types.StoragePlacementSpec { 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 types.StoragePlacementSpec{} } 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 types.StoragePlacementSpec{} } 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, } return sps }
func (d *Dispatcher) checkExistence(conf *config.VirtualContainerHostConfigSpec, settings *data.InstallerData) error { defer trace.End(trace.Begin("")) var err error d.vchPoolPath = path.Join(settings.ResourcePoolPath, conf.Name) var orp *object.ResourcePool var vapp *object.VirtualApp if d.isVC { vapp, err = d.findVirtualApp(d.vchPoolPath) if err != nil { return err } if vapp != nil { orp = vapp.ResourcePool } } if orp == nil { if orp, err = d.findResourcePool(d.vchPoolPath); err != nil { return err } } if orp == nil { return nil } rp := compute.NewResourcePool(d.ctx, d.session, orp.Reference()) vm, err := rp.GetChildVM(d.ctx, d.session, conf.Name) if err != nil { return err } if vm == nil { if vapp != nil { err = errors.Errorf("virtual app %q is found, but is not VCH, please choose different name", d.vchPoolPath) log.Error(err) return err } return nil } log.Debugf("Appliance is found") if ok, verr := d.isVCH(vm); !ok { verr = errors.Errorf("VM %q is found, but is not VCH appliance, please choose different name", conf.Name) return verr } err = errors.Errorf("Appliance %q exists, to install with same name, please delete it first.", conf.Name) return err }
// buildStoragePlacementSpecCreate builds StoragePlacementSpec for create action. func buildStoragePlacementSpecCreate(f *object.DatacenterFolders, rp *object.ResourcePool, storagePod object.StoragePod, configSpec types.VirtualMachineConfigSpec) types.StoragePlacementSpec { vmfr := f.VmFolder.Reference() rpr := rp.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) return sps }
// buildVMRelocateSpec builds VirtualMachineRelocateSpec to set a place for a new VirtualMachine. func buildVMRelocateSpec(rp *object.ResourcePool, ds *object.Datastore, vm *object.VirtualMachine, linkedClone bool, initType string) (types.VirtualMachineRelocateSpec, error) { var key int var moveType string if linkedClone { moveType = "createNewChildDiskBacking" } else { moveType = "moveAllDiskBackingsAndDisallowSharing" } log.Printf("[DEBUG] relocate type: [%s]", moveType) devices, err := vm.Device(context.TODO()) if err != nil { return types.VirtualMachineRelocateSpec{}, err } for _, d := range devices { if devices.Type(d) == "disk" { key = d.GetVirtualDevice().Key } } isThin := initType == "thin" rpr := rp.Reference() dsr := ds.Reference() return types.VirtualMachineRelocateSpec{ Datastore: &dsr, Pool: &rpr, DiskMoveType: moveType, Disk: []types.VirtualMachineRelocateSpecDiskLocator{ types.VirtualMachineRelocateSpecDiskLocator{ Datastore: dsr, DiskBackingInfo: &types.VirtualDiskFlatVer2BackingInfo{ DiskMode: "persistent", ThinProvisioned: types.NewBool(isThin), EagerlyScrub: types.NewBool(!isThin), }, DiskId: key, }, }, }, nil }
// getVCHs will check vm with same name under this resource pool, to see if that's VCH vm, and it will also check children vApp, to see if that's a VCH. // eventually return all fond VCH VMs func (d *Dispatcher) getChildVCHs(pool *object.ResourcePool, searchVapp bool) ([]*vm.VirtualMachine, error) { defer trace.End(trace.Begin(pool.InventoryPath)) // check if pool itself contains VCH vm. var vchs []*vm.VirtualMachine poolName := pool.Name() computeResource := compute.NewResourcePool(d.ctx, d.session, pool.Reference()) vmm, err := computeResource.GetChildVM(d.ctx, d.session, poolName) if err != nil { return nil, errors.Errorf("Failed to query children VM in resource pool %q: %s", pool.InventoryPath, err) } if vmm != nil { vmm.InventoryPath = path.Join(pool.InventoryPath, poolName) if ok, _ := d.isVCH(vmm); ok { log.Debugf("%q is VCH", vmm.InventoryPath) vchs = append(vchs, vmm) } } if !searchVapp { return vchs, nil } vappPath := path.Join(pool.InventoryPath, "*") vapps, err := d.session.Finder.VirtualAppList(d.ctx, vappPath) if err != nil { if _, ok := err.(*find.NotFoundError); ok { return vchs, nil } log.Debugf("Failed to query vapp %q: %s", vappPath, err) } for _, vapp := range vapps { childVCHs, err := d.getChildVCHs(vapp.ResourcePool, false) if err != nil { return nil, err } vchs = append(vchs, childVCHs...) } return vchs, nil }
func (f *Finder) ResourcePoolList(ctx context.Context, path string) ([]*object.ResourcePool, error) { es, err := f.find(ctx, f.hostFolder, true, path) if err != nil { return nil, err } var rps []*object.ResourcePool for _, e := range es { var rp *object.ResourcePool switch o := e.Object.(type) { case mo.ResourcePool: rp = object.NewResourcePool(f.client, o.Reference()) rp.InventoryPath = e.Path rps = append(rps, rp) } } if len(rps) == 0 { return nil, &NotFoundError{"resource pool", path} } return rps, nil }
// cloneVm creates the virtual machine using a template. func (vm *VirtualMachine) cloneVm(f *object.Folder, p *object.ResourcePool, ds *object.Datastore, h *object.HostSystem) error { Logf("%s cloning virtual machine from %s\n", vm.ID(), vm.TemplateConfig.Use) obj, err := vm.finder.VirtualMachine(vm.ctx, vm.TemplateConfig.Use) if err != nil { return err } folderRef := f.Reference() datastoreRef := ds.Reference() poolRef := p.Reference() var hostRef *types.ManagedObjectReference if h != nil { ref := h.Reference() hostRef = &ref } spec := types.VirtualMachineCloneSpec{ Location: types.VirtualMachineRelocateSpec{ Folder: &folderRef, Datastore: &datastoreRef, Pool: &poolRef, Host: hostRef, }, Template: vm.TemplateConfig.MarkAsTemplate, PowerOn: vm.TemplateConfig.PowerOn, } task, err := obj.Clone(vm.ctx, f, vm.Name, spec) if err != nil { return err } return task.Wait(vm.ctx) }
// 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 }
// 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 }