func testAccCheckVSphereVirtualMachineExists(n string, vm *virtualMachine) resource.TestCheckFunc { return func(s *terraform.State) error { if n == "" { return fmt.Errorf("No vm name passed in") } if vm == nil { return fmt.Errorf("No vm obj passed in") } rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { return fmt.Errorf("No ID is set") } client := testAccProvider.Meta().(*govmomi.Client) finder := find.NewFinder(client.Client, true) dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) if err != nil { return fmt.Errorf("error %s", err) } dcFolders, err := dc.Folders(context.TODO()) if err != nil { return fmt.Errorf("error %s", err) } folder := dcFolders.VmFolder if len(rs.Primary.Attributes["folder"]) > 0 { si := object.NewSearchIndex(client.Client) folderRef, err := si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"])) if err != nil { return err } else if folderRef != nil { folder = folderRef.(*object.Folder) } } _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) *vm = virtualMachine{ name: rs.Primary.ID, } return nil } }
func testAccCheckVSphereFolderExistingPathExists(n string, f *folder) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Resource %s not found in %#v", n, s.RootModule().Resources) } if rs.Primary.ID == "" { return fmt.Errorf("No ID is set") } client := testAccProvider.Meta().(*govmomi.Client) finder := find.NewFinder(client.Client, true) dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) if err != nil { return fmt.Errorf("error %s", err) } dcFolders, err := dc.Folders(context.TODO()) if err != nil { return fmt.Errorf("error %s", err) } _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["existing_path"]) *f = folder{ path: rs.Primary.Attributes["path"], } return nil } }
func (i *vSphereInstanceManager) resourcePool(ctx context.Context) (*types.ManagedObjectReference, error) { client, err := i.client(ctx) if err != nil { return nil, err } searchIndex := object.NewSearchIndex(client.Client) clusterRef, err := searchIndex.FindByInventoryPath(ctx, i.paths.ClusterPath) if err != nil { return nil, err } if clusterRef == nil { return nil, fmt.Errorf("cluster not found at %s", i.paths.ClusterPath) } cluster, ok := clusterRef.(*object.ClusterComputeResource) if !ok { return nil, fmt.Errorf("object at %s is %T, but expected ComputeClusterResource", i.paths.ClusterPath, clusterRef) } var mccr mo.ClusterComputeResource err = cluster.Properties(ctx, cluster.Reference(), []string{"resourcePool"}, &mccr) if err != nil { return nil, err } return mccr.ResourcePool, nil }
func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error { client := testAccProvider.Meta().(*govmomi.Client) finder := find.NewFinder(client.Client, true) for _, rs := range s.RootModule().Resources { if rs.Type != "vsphere_virtual_machine" { continue } dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) if err != nil { return fmt.Errorf("error %s", err) } dcFolders, err := dc.Folders(context.TODO()) if err != nil { return fmt.Errorf("error %s", err) } _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["name"]) if err == nil { return fmt.Errorf("Record still exists") } } return nil }
func resourceVSphereFolderRead(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] reading folder: %#v", d) client := meta.(*govmomi.Client) dc, err := getDatacenter(client, d.Get("datacenter").(string)) if err != nil { return err } finder := find.NewFinder(client.Client, true) finder = finder.SetDatacenter(dc) folder, err := object.NewSearchIndex(client.Client).FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", d.Get("datacenter").(string), d.Get("path").(string))) if err != nil { return err } if folder == nil { d.SetId("") } return nil }
func testAccCheckVSphereVirtualMachineExists(n string, vm *virtualMachine) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { return fmt.Errorf("No ID is set") } client := testAccProvider.Meta().(*govmomi.Client) finder := find.NewFinder(client.Client, true) dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) if err != nil { return fmt.Errorf("error %s", err) } dcFolders, err := dc.Folders(context.TODO()) if err != nil { return fmt.Errorf("error %s", err) } _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["name"]) *vm = virtualMachine{ name: rs.Primary.ID, } return nil } }
func deleteFolder(client *govmomi.Client, f *folder) error { dc, err := getDatacenter(client, f.datacenter) if err != nil { return err } var folder *object.Folder currentPath := f.path finder := find.NewFinder(client.Client, true) finder = finder.SetDatacenter(dc) si := object.NewSearchIndex(client.Client) folderRef, err := si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", f.datacenter, f.path)) if err != nil { return fmt.Errorf("[ERROR] Could not locate folder %s: %v", f.path, err) } else { folder = folderRef.(*object.Folder) } log.Printf("[INFO] Deleting empty sub-folders of existing path: %s", f.existingPath) for currentPath != f.existingPath { log.Printf("[INFO] Deleting folder: %s", currentPath) children, err := folder.Children(context.TODO()) if err != nil { return err } if len(children) > 0 { return fmt.Errorf("Folder %s is non-empty and will not be deleted", currentPath) } else { log.Printf("[DEBUG] current folder: %#v", folder) currentPath = path.Dir(currentPath) if currentPath == "." { currentPath = "" } log.Printf("[INFO] parent path of %s is calculated as %s", f.path, currentPath) task, err := folder.Destroy(context.TODO()) if err != nil { return err } err = task.Wait(context.TODO()) if err != nil { return err } folderRef, err = si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", f.datacenter, currentPath)) if err != nil { return err } else if folderRef != nil { folder = folderRef.(*object.Folder) } } } return nil }
// Returns the name of the VM on which this code is running. // This is done by searching for the name of virtual machine by current IP. // Prerequisite: this code assumes VMWare vmtools or open-vm-tools to be installed in the VM. func readInstanceID(cfg *VSphereConfig) (string, error) { addrs, err := net.InterfaceAddrs() if err != nil { return "", err } if len(addrs) == 0 { return "", fmt.Errorf("unable to retrieve Instance ID") } // Create context ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Create vSphere client c, err := vsphereLogin(cfg, ctx) if err != nil { return "", err } defer c.Logout(ctx) // Create a new finder f := find.NewFinder(c.Client, true) // Fetch and set data center dc, err := f.Datacenter(ctx, cfg.Global.Datacenter) if err != nil { return "", err } f.SetDatacenter(dc) s := object.NewSearchIndex(c.Client) var svm object.Reference for _, v := range addrs { ip, _, err := net.ParseCIDR(v.String()) if err != nil { return "", fmt.Errorf("unable to parse cidr from ip") } // Finds a virtual machine or host by IP address. svm, err = s.FindByIp(ctx, dc, ip.String(), true) if err == nil && svm != nil { break } } if svm == nil { return "", fmt.Errorf("unable to retrieve vm reference from vSphere") } var vm mo.VirtualMachine err = s.Properties(ctx, svm.Reference(), []string{"name"}, &vm) if err != nil { return "", err } return vm.Name, nil }
// getDatastoreObject gets datastore object. func getDatastoreObject(client *govmomi.Client, f *object.DatacenterFolders, name string) (types.ManagedObjectReference, error) { s := object.NewSearchIndex(client.Client) ref, err := s.FindChild(context.TODO(), f.DatastoreFolder, name) if err != nil { return types.ManagedObjectReference{}, err } log.Printf("[DEBUG] getDatastoreObject: reference: %#v", ref) return ref.Reference(), nil }
func (rp *ResourcePool) GetChildVM(ctx context.Context, s *session.Session, name string) (*vm.VirtualMachine, error) { searchIndex := object.NewSearchIndex(s.Client.Client) child, err := searchIndex.FindChild(ctx, rp.Reference(), name) if err != nil { return nil, errors.Errorf("Unable to find VM(%s): %s", name, err.Error()) } if child == nil { return nil, nil } // instantiate the vm object return vm.NewVirtualMachine(ctx, s, child.Reference()), nil }
func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error { client := testAccProvider.Meta().(*govmomi.Client) finder := find.NewFinder(client.Client, true) for _, rs := range s.RootModule().Resources { if rs.Type != "vsphere_virtual_machine" { continue } dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) if err != nil { return fmt.Errorf("error %s", err) } dcFolders, err := dc.Folders(context.TODO()) if err != nil { return fmt.Errorf("error %s", err) } folder := dcFolders.VmFolder if len(rs.Primary.Attributes["folder"]) > 0 { si := object.NewSearchIndex(client.Client) folderRef, err := si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"])) if err != nil { return err } else if folderRef != nil { folder = folderRef.(*object.Folder) } } v, err := object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) if v != nil { return fmt.Errorf("Record still exists") } } return nil }
func assertVSphereFolderExists(datacenter string, folder_name string) resource.TestCheckFunc { return func(s *terraform.State) error { client := testAccProvider.Meta().(*govmomi.Client) folder, err := object.NewSearchIndex(client.Client).FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", datacenter, folder_name)) if err != nil { return fmt.Errorf("Error: %s", err) } else if folder == nil { return fmt.Errorf("Folder %s does not exist!", folder_name) } return nil } }
// // getVMTemplate retrieves the VM given a name // // Parameters: // name: name of the VM to retrieve // dcName: name of the datacenter in which VM is residing // client: vSphere client object encapsulating the connection between client // and server // Returns: // *object.VirtualMachine: the VM object // error: errors from not able to find the VM // func (d *Driver) getVMTemplate(name string, dcName string, client *vim25.Client) (*object.VirtualMachine, error) { imageMoRef, err := object.NewSearchIndex(client).FindByInventoryPath( context.TODO(), fmt.Sprintf("%s/vm/%s", dcName, name)) if err != nil { return nil, fmt.Errorf("Error reading vm: %s", err) } if imageMoRef == nil { return nil, fmt.Errorf("Cannot find image %s", name) } image := imageMoRef.(*object.VirtualMachine) return image, nil }
// GetSelf gets VirtualMachine reference for the VM this process is running on func GetSelf(ctx context.Context, s *session.Session) (*vm.VirtualMachine, error) { u, err := UUID() if err != nil { return nil, err } search := object.NewSearchIndex(s.Vim25()) ref, err := search.FindByUuid(ctx, s.Datacenter, u, true, nil) if err != nil { return nil, err } if ref == nil { return nil, fmt.Errorf("can't find the hosting vm") } return vm.NewVirtualMachine(ctx, s, ref.Reference()), nil }
func removeVSphereFolder(datacenter string, folder_name string, existing_path string) resource.TestCheckFunc { f := folder{path: folder_name, datacenter: datacenter, existingPath: existing_path} return func(s *terraform.State) error { client := testAccProvider.Meta().(*govmomi.Client) // finder := find.NewFinder(client.Client, true) folder, _ := object.NewSearchIndex(client.Client).FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", datacenter, folder_name)) if folder != nil { deleteFolder(client, &f) } return nil } }
func createFolder(client *govmomi.Client, f *folder) error { finder := find.NewFinder(client.Client, true) dc, err := finder.Datacenter(context.TODO(), f.datacenter) if err != nil { return fmt.Errorf("error %s", err) } finder = finder.SetDatacenter(dc) si := object.NewSearchIndex(client.Client) dcFolders, err := dc.Folders(context.TODO()) if err != nil { return fmt.Errorf("error %s", err) } folder := dcFolders.VmFolder var workingPath string pathParts := strings.Split(f.path, "/") for _, pathPart := range pathParts { if len(workingPath) > 0 { workingPath += "/" } workingPath += pathPart subfolder, err := si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", f.datacenter, workingPath)) if err != nil { return fmt.Errorf("error %s", err) } else if subfolder == nil { log.Printf("[DEBUG] folder not found; creating: %s", workingPath) folder, err = folder.CreateFolder(context.TODO(), pathPart) if err != nil { return fmt.Errorf("Failed to create folder at %s; %s", workingPath, err) } } else { log.Printf("[DEBUG] folder already exists: %s", workingPath) f.existingPath = workingPath folder = subfolder.(*object.Folder) } } return nil }
func readInstanceID(cfg *VSphereConfig) (string, error) { cmd := exec.Command("bash", "-c", `dmidecode -t 1 | grep UUID | tr -d ' ' | cut -f 2 -d ':'`) var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() if err != nil { return "", err } if out.Len() == 0 { return "", fmt.Errorf("unable to retrieve Instance ID") } // Create context ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Create vSphere client c, err := vsphereLogin(cfg, ctx) if err != nil { return "", err } defer c.Logout(ctx) // Create a new finder f := find.NewFinder(c.Client, true) // Fetch and set data center dc, err := f.Datacenter(ctx, cfg.Global.Datacenter) if err != nil { return "", err } f.SetDatacenter(dc) s := object.NewSearchIndex(c.Client) svm, err := s.FindByUuid(ctx, dc, strings.ToLower(strings.TrimSpace(out.String())), true, nil) var vm mo.VirtualMachine err = s.Properties(ctx, svm.Reference(), []string{"name"}, &vm) if err != nil { return "", err } return vm.Name, nil }
func createVSphereFolder(datacenter string, folder_name string) error { client := testAccProvider.Meta().(*govmomi.Client) f := folder{path: folder_name, datacenter: datacenter} folder, err := object.NewSearchIndex(client.Client).FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", datacenter, folder_name)) if err != nil { return fmt.Errorf("error %s", err) } if folder == nil { createFolder(client, &f) } else { return fmt.Errorf("Folder %s already exists", folder_name) } return nil }
// find the childVM for this resource pool by name func childVM(ctx context.Context, sess *session.Session, name string) (*vm.VirtualMachine, error) { // Search container back through instance UUID uuid, err := instanceUUID(name) if err != nil { detail := fmt.Sprintf("unable to get instance UUID: %s", err) log.Error(detail) return nil, errors.New(detail) } searchIndex := object.NewSearchIndex(sess.Client.Client) child, err := searchIndex.FindByUuid(ctx, sess.Datacenter, uuid, true, nil) if err != nil { return nil, fmt.Errorf("Unable to find container(%s): %s", name, err.Error()) } if child == nil { return nil, fmt.Errorf("Unable to find container %s", name) } // instantiate the vm object return vm.NewVirtualMachine(ctx, sess, child.Reference()), nil }
func (i *vSphereInstanceManager) findBaseVMAndSnapshot(ctx context.Context, name string) (*object.VirtualMachine, types.VirtualMachineSnapshotTree, error) { client, err := i.client(ctx) if err != nil { return nil, types.VirtualMachineSnapshotTree{}, err } searchIndex := object.NewSearchIndex(client.Client) vmRef, err := searchIndex.FindByInventoryPath(ctx, i.paths.BasePath+name) if err != nil { return nil, types.VirtualMachineSnapshotTree{}, err } if vmRef == nil { return nil, types.VirtualMachineSnapshotTree{}, BaseVirtualMachineNotFoundError{Path: i.paths.BasePath, Name: name} } vm, ok := vmRef.(*object.VirtualMachine) if !ok { return nil, types.VirtualMachineSnapshotTree{}, fmt.Errorf("base VM %s is a %T, but expected VirtualMachine", name, vmRef) } var mvm mo.VirtualMachine err = vm.Properties(ctx, vm.Reference(), []string{"snapshot"}, &mvm) if err != nil { return nil, types.VirtualMachineSnapshotTree{}, fmt.Errorf("couldn't get snapshot info for base VM: %s", err) } if mvm.Snapshot == nil { return nil, types.VirtualMachineSnapshotTree{}, fmt.Errorf("invalid base VM (no snapshot)") } snapshotTree, ok := i.findSnapshot(mvm.Snapshot.RootSnapshotList, "base") if !ok { return nil, types.VirtualMachineSnapshotTree{}, fmt.Errorf("invalid base VM (no snapshot named 'base')") } return vm, snapshotTree, nil }
func (i *vSphereInstanceManager) Terminate(ctx context.Context, id string) error { client, err := i.client(ctx) if err != nil { return err } searchIndex := object.NewSearchIndex(client.Client) vmRef, err := searchIndex.FindByInventoryPath(ctx, i.paths.VMPath+id) if err != nil { return err } if vmRef == nil { return VirtualMachineNotFoundError{Path: i.paths.VMPath, ID: id} } vm, ok := vmRef.(*object.VirtualMachine) if !ok { return fmt.Errorf("not a VM") } task, err := vm.PowerOff(ctx) if err != nil { return err } // Ignore error since the VM may already be powered off. vm.Destroy will fail // if the VM is still powered on. _ = task.Wait(ctx) task, err = vm.Destroy(ctx) if err != nil { return err } return task.Wait(ctx) }
func (i *vSphereInstanceManager) Fetch(ctx context.Context, id string) (*Instance, error) { client, err := i.client(ctx) if err != nil { return nil, err } searchIndex := object.NewSearchIndex(client.Client) vmRef, err := searchIndex.FindByInventoryPath(ctx, i.paths.VMPath+id) if err != nil { return nil, VSphereAPIError{UnderlyingError: err} } if vmRef == nil { return nil, VirtualMachineNotFoundError{Path: i.paths.VMPath, ID: id} } vm, ok := vmRef.(*object.VirtualMachine) if !ok { return nil, fmt.Errorf("object at path %s is a %T, but expected VirtualMachine", i.paths.VMPath+id, vmRef) } return i.instanceForVirtualMachine(ctx, vm) }
func (i *vSphereInstanceManager) vmFolder(ctx context.Context) (*object.Folder, error) { client, err := i.client(ctx) if err != nil { return nil, err } searchIndex := object.NewSearchIndex(client.Client) folderRef, err := searchIndex.FindByInventoryPath(ctx, i.paths.VMPath) if err != nil { return nil, err } if folderRef == nil { return nil, fmt.Errorf("VM folder not found") } folder, ok := folderRef.(*object.Folder) if !ok { return nil, fmt.Errorf("VM folder is not a folder but %T", folderRef) } return folder, nil }
// deployVirtualMachine deploys a new VirtualMachine. func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error { dc, err := getDatacenter(c, vm.datacenter) if err != nil { return err } finder := find.NewFinder(c.Client, true) finder = finder.SetDatacenter(dc) template, err := finder.VirtualMachine(context.TODO(), vm.template) if err != nil { return err } log.Printf("[DEBUG] template: %#v", template) 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 } log.Printf("[DEBUG] folder: %#v", vm.folder) folder := dcFolders.VmFolder if len(vm.folder) > 0 { si := object.NewSearchIndex(c.Client) folderRef, err := si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", vm.datacenter, vm.folder)) if err != nil { return fmt.Errorf("Error reading folder %s: %s", vm.folder, err) } else if folderRef == nil { return fmt.Errorf("Cannot find folder %s", vm.folder) } else { folder = folderRef.(*object.Folder) } } var datastore *object.Datastore if vm.datastore == "" { datastore, err = finder.DefaultDatastore(context.TODO()) if err != nil { return err } } else { datastore, err = finder.Datastore(context.TODO(), vm.datastore) if err != nil { // TODO: datastore cluster support in govmomi finder function d, err := getDatastoreObject(c, dcFolders, vm.datastore) if err != nil { return err } if d.Type == "StoragePod" { sp := object.StoragePod{ Folder: object.NewFolder(c.Client, d), } sps := buildStoragePlacementSpecClone(c, dcFolders, template, resourcePool, sp) datastore, err = findDatastore(c, sps) if err != nil { return err } } else { datastore = object.NewDatastore(c.Client, d) } } } log.Printf("[DEBUG] datastore: %#v", datastore) relocateSpec, err := buildVMRelocateSpec(resourcePool, datastore, template, vm.linkedClone, vm.hardDisks[0].initType) if err != nil { return err } log.Printf("[DEBUG] relocate spec: %v", relocateSpec) // network networkDevices := []types.BaseVirtualDeviceConfigSpec{} networkConfigs := []types.CustomizationAdapterMapping{} for _, network := range vm.networkInterfaces { // network device nd, err := buildNetworkDevice(finder, network.label, "vmxnet3") if err != nil { return err } networkDevices = append(networkDevices, nd) // TODO: IPv6 support var ipSetting types.CustomizationIPSettings if network.ipv4Address == "" { ipSetting = types.CustomizationIPSettings{ Ip: &types.CustomizationDhcpIpGenerator{}, } } else { if network.ipv4PrefixLength == 0 { return fmt.Errorf("Error: ipv4_prefix_length argument is empty.") } m := net.CIDRMask(network.ipv4PrefixLength, 32) sm := net.IPv4(m[0], m[1], m[2], m[3]) subnetMask := sm.String() log.Printf("[DEBUG] gateway: %v", vm.gateway) log.Printf("[DEBUG] ipv4 address: %v", network.ipv4Address) log.Printf("[DEBUG] ipv4 prefix length: %v", network.ipv4PrefixLength) log.Printf("[DEBUG] ipv4 subnet mask: %v", subnetMask) ipSetting = types.CustomizationIPSettings{ Gateway: []string{ vm.gateway, }, Ip: &types.CustomizationFixedIp{ IpAddress: network.ipv4Address, }, SubnetMask: subnetMask, } } // network config config := types.CustomizationAdapterMapping{ Adapter: ipSetting, } networkConfigs = append(networkConfigs, config) } log.Printf("[DEBUG] network configs: %v", networkConfigs[0].Adapter) // make config spec configSpec := types.VirtualMachineConfigSpec{ NumCPUs: vm.vcpu, NumCoresPerSocket: 1, MemoryMB: vm.memoryMb, } log.Printf("[DEBUG] virtual machine config spec: %v", configSpec) log.Printf("[DEBUG] starting extra custom config spec: %v", vm.customConfigurations) // make ExtraConfig if len(vm.customConfigurations) > 0 { var ov []types.BaseOptionValue for k, v := range vm.customConfigurations { key := k value := v o := types.OptionValue{ Key: key, Value: &value, } ov = append(ov, &o) } configSpec.ExtraConfig = ov log.Printf("[DEBUG] virtual machine Extra Config spec: %v", configSpec.ExtraConfig) } var template_mo mo.VirtualMachine err = template.Properties(context.TODO(), template.Reference(), []string{"parent", "config.template", "config.guestId", "resourcePool", "snapshot", "guest.toolsVersionStatus2", "config.guestFullName"}, &template_mo) var identity_options types.BaseCustomizationIdentitySettings if strings.HasPrefix(template_mo.Config.GuestId, "win") { var timeZone int if vm.timeZone == "Etc/UTC" { vm.timeZone = "085" } timeZone, err := strconv.Atoi(vm.timeZone) if err != nil { return fmt.Errorf("Error converting TimeZone: %s", err) } guiUnattended := types.CustomizationGuiUnattended{ AutoLogon: false, AutoLogonCount: 1, TimeZone: timeZone, } customIdentification := types.CustomizationIdentification{} userData := types.CustomizationUserData{ ComputerName: &types.CustomizationFixedName{ Name: strings.Split(vm.name, ".")[0], }, ProductId: vm.windowsOptionalConfig.productKey, FullName: "terraform", OrgName: "terraform", } if vm.windowsOptionalConfig.domainUserPassword != "" && vm.windowsOptionalConfig.domainUser != "" && vm.windowsOptionalConfig.domain != "" { customIdentification.DomainAdminPassword = &types.CustomizationPassword{ PlainText: true, Value: vm.windowsOptionalConfig.domainUserPassword, } customIdentification.DomainAdmin = vm.windowsOptionalConfig.domainUser customIdentification.JoinDomain = vm.windowsOptionalConfig.domain } if vm.windowsOptionalConfig.adminPassword != "" { guiUnattended.Password = &types.CustomizationPassword{ PlainText: true, Value: vm.windowsOptionalConfig.adminPassword, } } identity_options = &types.CustomizationSysprep{ GuiUnattended: guiUnattended, Identification: customIdentification, UserData: userData, } } else { identity_options = &types.CustomizationLinuxPrep{ HostName: &types.CustomizationFixedName{ Name: strings.Split(vm.name, ".")[0], }, Domain: vm.domain, TimeZone: vm.timeZone, HwClockUTC: types.NewBool(true), } } // create CustomizationSpec customSpec := types.CustomizationSpec{ Identity: identity_options, GlobalIPSettings: types.CustomizationGlobalIPSettings{ DnsSuffixList: vm.dnsSuffixes, DnsServerList: vm.dnsServers, }, NicSettingMap: networkConfigs, } log.Printf("[DEBUG] custom spec: %v", customSpec) // make vm clone spec cloneSpec := types.VirtualMachineCloneSpec{ Location: relocateSpec, Template: false, Config: &configSpec, PowerOn: false, } if vm.linkedClone { if err != nil { return fmt.Errorf("Error reading base VM properties: %s", err) } if template_mo.Snapshot == nil { return fmt.Errorf("`linkedClone=true`, but image VM has no snapshots") } cloneSpec.Snapshot = template_mo.Snapshot.CurrentSnapshot } log.Printf("[DEBUG] clone spec: %v", cloneSpec) task, err := template.Clone(context.TODO(), folder, vm.name, cloneSpec) if err != nil { return err } _, err = task.WaitForResult(context.TODO(), nil) if err != nil { return err } newVM, err := finder.VirtualMachine(context.TODO(), vm.Path()) if err != nil { return err } log.Printf("[DEBUG] new vm: %v", newVM) devices, err := newVM.Device(context.TODO()) if err != nil { log.Printf("[DEBUG] Template devices can't be found") return err } for _, dvc := range devices { // Issue 3559/3560: Delete all ethernet devices to add the correct ones later if devices.Type(dvc) == "ethernet" { err := newVM.RemoveDevice(context.TODO(), dvc) if err != nil { return err } } } // Add Network devices for _, dvc := range networkDevices { err := newVM.AddDevice( context.TODO(), dvc.GetVirtualDeviceConfigSpec().Device) if err != nil { return err } } // Create the cdroms if needed. if err := createCdroms(newVM, vm.cdroms); err != nil { return err } taskb, err := newVM.Customize(context.TODO(), customSpec) if err != nil { return err } _, err = taskb.WaitForResult(context.TODO(), nil) if err != nil { return err } log.Printf("[DEBUG] VM customization finished") for i := 1; i < len(vm.hardDisks); i++ { err = addHardDisk(newVM, vm.hardDisks[i].size, vm.hardDisks[i].iops, vm.hardDisks[i].initType, datastore, vm.hardDisks[i].vmdkPath) if err != nil { return err } } log.Printf("[DEBUG] virtual machine config spec: %v", configSpec) newVM.PowerOn(context.TODO()) ip, err := newVM.WaitForIP(context.TODO()) if err != nil { return err } log.Printf("[DEBUG] ip address: %v", ip) return nil }
// createVirtualMachine creates a new VirtualMachine. func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error { dc, err := getDatacenter(c, vm.datacenter) if err != nil { return err } finder := find.NewFinder(c.Client, true) 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 } log.Printf("[DEBUG] folder: %#v", vm.folder) folder := dcFolders.VmFolder if len(vm.folder) > 0 { si := object.NewSearchIndex(c.Client) folderRef, err := si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", vm.datacenter, vm.folder)) if err != nil { return fmt.Errorf("Error reading folder %s: %s", vm.folder, err) } else if folderRef == nil { return fmt.Errorf("Cannot find folder %s", vm.folder) } else { folder = folderRef.(*object.Folder) } } // network networkDevices := []types.BaseVirtualDeviceConfigSpec{} for _, network := range vm.networkInterfaces { // network device nd, err := buildNetworkDevice(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, MemoryAllocation: &types.ResourceAllocationInfo{ Reservation: vm.memoryAllocation.reservation, }, DeviceChange: networkDevices, } log.Printf("[DEBUG] virtual machine config spec: %v", configSpec) // make ExtraConfig log.Printf("[DEBUG] virtual machine Extra Config spec start") if len(vm.customConfigurations) > 0 { var ov []types.BaseOptionValue for k, v := range vm.customConfigurations { key := k value := v o := types.OptionValue{ Key: key, Value: &value, } log.Printf("[DEBUG] virtual machine Extra Config spec: %s,%s", k, v) ov = append(ov, &o) } configSpec.ExtraConfig = ov log.Printf("[DEBUG] virtual machine Extra Config spec: %v", configSpec.ExtraConfig) } var datastore *object.Datastore if vm.datastore == "" { datastore, err = finder.DefaultDatastore(context.TODO()) if err != nil { return err } } else { datastore, err = finder.Datastore(context.TODO(), vm.datastore) if err != nil { // TODO: datastore cluster support in govmomi finder function d, err := getDatastoreObject(c, dcFolders, vm.datastore) if err != nil { return err } if d.Type == "StoragePod" { sp := object.StoragePod{ Folder: object.NewFolder(c.Client, d), } sps := buildStoragePlacementSpecCreate(dcFolders, resourcePool, sp, configSpec) datastore, err = findDatastore(c, sps) if err != nil { return err } } else { datastore = object.NewDatastore(c.Client, d) } } } 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 := folder.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.Path()) 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", datastore, hd.vmdkPath) if err != nil { return err } } // Create the cdroms if needed. if err := createCdroms(newVM, vm.cdroms); err != nil { return err } if vm.bootableVmdk { newVM.PowerOn(context.TODO()) ip, err := newVM.WaitForIP(context.TODO()) if err != nil { return err } log.Printf("[DEBUG] ip address: %v", ip) } return nil }
// deployVirtualMachine deploys a new VirtualMachine. func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error { dc, err := getDatacenter(c, vm.datacenter) if err != nil { return err } finder := find.NewFinder(c.Client, true) finder = finder.SetDatacenter(dc) template, err := finder.VirtualMachine(context.TODO(), vm.template) if err != nil { return err } log.Printf("[DEBUG] template: %#v", template) 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 } log.Printf("[DEBUG] folder: %#v", vm.folder) folder := dcFolders.VmFolder if len(vm.folder) > 0 { si := object.NewSearchIndex(c.Client) folderRef, err := si.FindByInventoryPath( context.TODO(), fmt.Sprintf("%v/vm/%v", vm.datacenter, vm.folder)) if err != nil { return fmt.Errorf("Error reading folder %s: %s", vm.folder, err) } else if folderRef == nil { return fmt.Errorf("Cannot find folder %s", vm.folder) } else { folder = folderRef.(*object.Folder) } } var datastore *object.Datastore if vm.datastore == "" { datastore, err = finder.DefaultDatastore(context.TODO()) if err != nil { return err } } else { datastore, err = finder.Datastore(context.TODO(), vm.datastore) if err != nil { // TODO: datastore cluster support in govmomi finder function d, err := getDatastoreObject(c, dcFolders, vm.datastore) if err != nil { return err } if d.Type == "StoragePod" { sp := object.StoragePod{ object.NewFolder(c.Client, d), } sps := buildStoragePlacementSpecClone(c, dcFolders, template, resourcePool, sp) datastore, err = findDatastore(c, sps) if err != nil { return err } } else { datastore = object.NewDatastore(c.Client, d) } } } log.Printf("[DEBUG] datastore: %#v", datastore) relocateSpec, err := buildVMRelocateSpec(resourcePool, datastore, template) if err != nil { return err } log.Printf("[DEBUG] relocate spec: %v", relocateSpec) // network networkDevices := []types.BaseVirtualDeviceConfigSpec{} networkConfigs := []types.CustomizationAdapterMapping{} for _, network := range vm.networkInterfaces { // network device nd, err := buildNetworkDevice(finder, network.label, "vmxnet3") if err != nil { return err } networkDevices = append(networkDevices, nd) // TODO: IPv6 support var ipSetting types.CustomizationIPSettings if network.ipv4Address == "" { ipSetting = types.CustomizationIPSettings{ Ip: &types.CustomizationDhcpIpGenerator{}, } } else { if network.ipv4PrefixLength == 0 { return fmt.Errorf("Error: ipv4_prefix_length argument is empty.") } m := net.CIDRMask(network.ipv4PrefixLength, 32) sm := net.IPv4(m[0], m[1], m[2], m[3]) subnetMask := sm.String() log.Printf("[DEBUG] gateway: %v", vm.gateway) log.Printf("[DEBUG] ipv4 address: %v", network.ipv4Address) log.Printf("[DEBUG] ipv4 prefix length: %v", network.ipv4PrefixLength) log.Printf("[DEBUG] ipv4 subnet mask: %v", subnetMask) ipSetting = types.CustomizationIPSettings{ Gateway: []string{ vm.gateway, }, Ip: &types.CustomizationFixedIp{ IpAddress: network.ipv4Address, }, SubnetMask: subnetMask, } } // network config config := types.CustomizationAdapterMapping{ Adapter: ipSetting, } networkConfigs = append(networkConfigs, config) } log.Printf("[DEBUG] network configs: %v", networkConfigs[0].Adapter) // make config spec configSpec := types.VirtualMachineConfigSpec{ NumCPUs: vm.vcpu, NumCoresPerSocket: 1, MemoryMB: vm.memoryMb, } log.Printf("[DEBUG] virtual machine config spec: %v", configSpec) log.Printf("[DEBUG] starting extra custom config spec: %v", vm.customConfigurations) // make ExtraConfig if len(vm.customConfigurations) > 0 { var ov []types.BaseOptionValue for k, v := range vm.customConfigurations { key := k value := v o := types.OptionValue{ Key: key, Value: &value, } ov = append(ov, &o) } configSpec.ExtraConfig = ov log.Printf("[DEBUG] virtual machine Extra Config spec: %v", configSpec.ExtraConfig) } // create CustomizationSpec customSpec := types.CustomizationSpec{ Identity: &types.CustomizationLinuxPrep{ HostName: &types.CustomizationFixedName{ Name: strings.Split(vm.name, ".")[0], }, Domain: vm.domain, TimeZone: vm.timeZone, HwClockUTC: types.NewBool(true), }, GlobalIPSettings: types.CustomizationGlobalIPSettings{ DnsSuffixList: vm.dnsSuffixes, DnsServerList: vm.dnsServers, }, NicSettingMap: networkConfigs, } log.Printf("[DEBUG] custom spec: %v", customSpec) // make vm clone spec cloneSpec := types.VirtualMachineCloneSpec{ Location: relocateSpec, Template: false, Config: &configSpec, PowerOn: false, } log.Printf("[DEBUG] clone spec: %v", cloneSpec) task, err := template.Clone(context.TODO(), folder, vm.name, cloneSpec) if err != nil { return err } _, err = task.WaitForResult(context.TODO(), nil) if err != nil { return err } newVM, err := finder.VirtualMachine(context.TODO(), vm.Path()) if err != nil { return err } log.Printf("[DEBUG] new vm: %v", newVM) devices, err := newVM.Device(context.TODO()) if err != nil { log.Printf("[DEBUG] Template devices can't be found") return err } for _, dvc := range devices { // Issue 3559/3560: Delete all ethernet devices to add the correct ones later if devices.Type(dvc) == "ethernet" { err := newVM.RemoveDevice(context.TODO(), dvc) if err != nil { return err } } } // Add Network devices for _, dvc := range networkDevices { err := newVM.AddDevice( context.TODO(), dvc.GetVirtualDeviceConfigSpec().Device) if err != nil { return err } } taskb, err := newVM.Customize(context.TODO(), customSpec) if err != nil { return err } _, err = taskb.WaitForResult(context.TODO(), nil) if err != nil { return err } log.Printf("[DEBUG]VM customization finished") for i := 1; i < len(vm.hardDisks); i++ { err = addHardDisk(newVM, vm.hardDisks[i].size, vm.hardDisks[i].iops, "eager_zeroed") if err != nil { return err } } log.Printf("[DEBUG] virtual machine config spec: %v", configSpec) newVM.PowerOn(context.TODO()) ip, err := newVM.WaitForIP(context.TODO()) if err != nil { return err } log.Printf("[DEBUG] ip address: %v", ip) return nil }
func resourceVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*vim25.Client) dc_name := d.Get("datacenter").(string) if dc_name == "" { finder := find.NewFinder(client, false) dc, err := finder.DefaultDatacenter(context.TODO()) if err != nil { return fmt.Errorf("Error reading default datacenter: %s", err) } var dc_mo mo.Datacenter err = dc.Properties(context.TODO(), dc.Reference(), []string{"name"}, &dc_mo) if err != nil { return fmt.Errorf("Error reading datacenter name: %s", err) } dc_name = dc_mo.Name d.Set("datacenter", dc_name) } image_name := d.Get("image").(string) image_ref, err := object.NewSearchIndex(client).FindByInventoryPath(context.TODO(), fmt.Sprintf("%s/vm/%s", dc_name, image_name)) if err != nil { return fmt.Errorf("Error reading vm: %s", err) } if image_ref == nil { return fmt.Errorf("Cannot find image %s", image_name) } image := image_ref.(*object.VirtualMachine) var image_mo mo.VirtualMachine err = image.Properties(context.TODO(), image.Reference(), []string{"parent", "config.template", "resourcePool", "snapshot", "guest.toolsVersionStatus2", "config.guestFullName"}, &image_mo) if err != nil { return fmt.Errorf("Error reading base VM properties: %s", err) } var folder_ref object.Reference var folder *object.Folder if d.Get("folder").(string) != "" { folder_ref, err = object.NewSearchIndex(client).FindByInventoryPath(context.TODO(), fmt.Sprintf("%v/vm/%v", dc_name, d.Get("folder").(string))) if err != nil { return fmt.Errorf("Error reading folder: %s", err) } if folder_ref == nil { return fmt.Errorf("Cannot find folder %s", d.Get("folder").(string)) } folder = folder_ref.(*object.Folder) } else { folder = object.NewFolder(client, *image_mo.Parent) } host_name := d.Get("host").(string) if host_name == "" { if image_mo.Config.Template == true { return fmt.Errorf("Image is a template, 'host' is a required") } else { var pool_mo mo.ResourcePool err = property.DefaultCollector(client).RetrieveOne(context.TODO(), *image_mo.ResourcePool, []string{"owner"}, &pool_mo) if err != nil { return fmt.Errorf("Error reading resource pool of base VM: %s", err) } if strings.Contains(pool_mo.Owner.Value, "domain-s") { var host_mo mo.ComputeResource err = property.DefaultCollector(client).RetrieveOne(context.TODO(), pool_mo.Owner, []string{"name"}, &host_mo) if err != nil { return fmt.Errorf("Error reading host of base VM: %s", err) } host_name = host_mo.Name } else if strings.Contains(pool_mo.Owner.Value, "domain-c") { var cluster_mo mo.ClusterComputeResource err = property.DefaultCollector(client).RetrieveOne(context.TODO(), pool_mo.Owner, []string{"name"}, &cluster_mo) if err != nil { return fmt.Errorf("Error reading cluster of base VM: %s", err) } host_name = cluster_mo.Name } else { return fmt.Errorf("Unknown compute resource format of base VM: %s", pool_mo.Owner.Value) } } } pool_name := d.Get("resource_pool").(string) pool_ref, err := object.NewSearchIndex(client).FindByInventoryPath(context.TODO(), fmt.Sprintf("%v/host/%v/Resources/%v", dc_name, host_name, pool_name)) if err != nil { return fmt.Errorf("Error reading resource pool: %s", err) } if pool_ref == nil { return fmt.Errorf("Cannot find resource pool %s", pool_name) } var relocateSpec types.VirtualMachineRelocateSpec var pool_mor types.ManagedObjectReference pool_mor = pool_ref.Reference() relocateSpec.Pool = &pool_mor if d.Get("linked_clone").(bool) { relocateSpec.DiskMoveType = "createNewChildDiskBacking" } var confSpec types.VirtualMachineConfigSpec if d.Get("cpus") != nil { confSpec.NumCPUs = d.Get("cpus").(int) } if d.Get("memory") != nil { confSpec.MemoryMB = int64(d.Get("memory").(int)) } params := d.Get("configuration_parameters").(map[string]interface{}) var ov []types.BaseOptionValue if len(params) > 0 { for k, v := range params { key := k value := v o := types.OptionValue{ Key: key, Value: &value, } ov = append(ov, &o) } confSpec.ExtraConfig = ov } cloneSpec := types.VirtualMachineCloneSpec{ Location: relocateSpec, Config: &confSpec, PowerOn: d.Get("power_on").(bool), } if d.Get("linked_clone").(bool) { if image_mo.Snapshot == nil { return fmt.Errorf("`linked_clone=true`, but image VM has no snapshots") } cloneSpec.Snapshot = image_mo.Snapshot.CurrentSnapshot } domain := d.Get("domain").(string) ip_address := d.Get("ip_address").(string) if domain != "" { if image_mo.Guest.ToolsVersionStatus2 == "guestToolsNotInstalled" { return fmt.Errorf("VMware tools are not installed in base VM") } if !strings.Contains(image_mo.Config.GuestFullName, "Linux") && !strings.Contains(image_mo.Config.GuestFullName, "CentOS") { return fmt.Errorf("Guest customization is supported only for Linux. Base image OS is: %s", image_mo.Config.GuestFullName) } customizationSpec := types.CustomizationSpec{ GlobalIPSettings: types.CustomizationGlobalIPSettings{}, Identity: &types.CustomizationLinuxPrep{ HostName: &types.CustomizationVirtualMachineName{}, Domain: domain, }, NicSettingMap: []types.CustomizationAdapterMapping{ { Adapter: types.CustomizationIPSettings{}, }, }, } if ip_address != "" { mask := d.Get("subnet_mask").(string) if mask == "" { return fmt.Errorf("'subnet_mask' must be set, if static 'ip_address' is specified") } customizationSpec.NicSettingMap[0].Adapter.Ip = &types.CustomizationFixedIp{ IpAddress: ip_address, } customizationSpec.NicSettingMap[0].Adapter.SubnetMask = d.Get("subnet_mask").(string) gateway := d.Get("gateway").(string) if gateway != "" { customizationSpec.NicSettingMap[0].Adapter.Gateway = []string{gateway} } } else { customizationSpec.NicSettingMap[0].Adapter.Ip = &types.CustomizationDhcpIpGenerator{} } cloneSpec.Customization = &customizationSpec } else if ip_address != "" { return fmt.Errorf("'domain' must be set, if static 'ip_address' is specified") } task, err := image.Clone(context.TODO(), folder, d.Get("name").(string), cloneSpec) if err != nil { return fmt.Errorf("Error clonning vm: %s", err) } info, err := task.WaitForResult(context.TODO(), nil) if err != nil { return fmt.Errorf("Error clonning vm: %s", err) } vm_mor := info.Result.(types.ManagedObjectReference) d.SetId(vm_mor.Value) vm := object.NewVirtualMachine(client, vm_mor) // workaround for https://github.com/vmware/govmomi/issues/218 if ip_address == "" && d.Get("power_on").(bool) { ip, err := vm.WaitForIP(context.TODO()) if err != nil { log.Printf("[ERROR] Cannot read ip address: %s", err) } else { d.Set("ip_address", ip) d.SetConnInfo(map[string]string{ "type": "ssh", "host": ip, }) } } return nil }
func (flag *SearchFlag) searchIndex(c *vim25.Client) *object.SearchIndex { return object.NewSearchIndex(c) }
// Returns the name of the VM and its Cluster on which this code is running. // This is done by searching for the name of virtual machine by current IP. // Prerequisite: this code assumes VMWare vmtools or open-vm-tools to be installed in the VM. func readInstance(cfg *VSphereConfig) (string, string, error) { addrs, err := net.InterfaceAddrs() if err != nil { return "", "", err } if len(addrs) == 0 { return "", "", fmt.Errorf("unable to retrieve Instance ID") } // Create context ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Create vSphere client c, err := vsphereLogin(cfg, ctx) if err != nil { return "", "", err } defer c.Logout(ctx) // Create a new finder f := find.NewFinder(c.Client, true) // Fetch and set data center dc, err := f.Datacenter(ctx, cfg.Global.Datacenter) if err != nil { return "", "", err } f.SetDatacenter(dc) s := object.NewSearchIndex(c.Client) var svm object.Reference for _, v := range addrs { ip, _, err := net.ParseCIDR(v.String()) if err != nil { return "", "", fmt.Errorf("unable to parse cidr from ip") } // Finds a virtual machine or host by IP address. svm, err = s.FindByIp(ctx, dc, ip.String(), true) if err == nil && svm != nil { break } } if svm == nil { return "", "", fmt.Errorf("unable to retrieve vm reference from vSphere") } var vm mo.VirtualMachine err = s.Properties(ctx, svm.Reference(), []string{"name", "resourcePool"}, &vm) if err != nil { return "", "", err } var cluster string if vm.ResourcePool != nil { // Extract the Cluster Name if VM belongs to a ResourcePool var rp mo.ResourcePool err = s.Properties(ctx, *vm.ResourcePool, []string{"parent"}, &rp) if err == nil { var ccr mo.ClusterComputeResource err = s.Properties(ctx, *rp.Parent, []string{"name"}, &ccr) if err == nil { cluster = ccr.Name } else { glog.Warningf("VM %s, does not belong to a vSphere Cluster, will not have FailureDomain label", vm.Name) } } else { glog.Warningf("VM %s, does not belong to a vSphere Cluster, will not have FailureDomain label", vm.Name) } } return vm.Name, cluster, nil }
func testAccCheckVSphereVirtualMachineExistsHasCustomConfig(n string, vm *virtualMachine) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { return fmt.Errorf("No ID is set") } client := testAccProvider.Meta().(*govmomi.Client) finder := find.NewFinder(client.Client, true) dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) if err != nil { return fmt.Errorf("error %s", err) } dcFolders, err := dc.Folders(context.TODO()) if err != nil { return fmt.Errorf("error %s", err) } _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["name"]) if err != nil { return fmt.Errorf("error %s", err) } finder = finder.SetDatacenter(dc) instance, err := finder.VirtualMachine(context.TODO(), rs.Primary.Attributes["name"]) if err != nil { return fmt.Errorf("error %s", err) } var mvm mo.VirtualMachine collector := property.DefaultCollector(client.Client) if err := collector.RetrieveOne(context.TODO(), instance.Reference(), []string{"config.extraConfig"}, &mvm); err != nil { return fmt.Errorf("error %s", err) } var configMap = make(map[string]types.AnyType) if mvm.Config != nil && mvm.Config.ExtraConfig != nil && len(mvm.Config.ExtraConfig) > 0 { for _, v := range mvm.Config.ExtraConfig { value := v.GetOptionValue() configMap[value.Key] = value.Value } } else { return fmt.Errorf("error no ExtraConfig") } if configMap["foo"] == nil { return fmt.Errorf("error no ExtraConfig for 'foo'") } if configMap["foo"] != "bar" { return fmt.Errorf("error ExtraConfig 'foo' != bar") } if configMap["car"] == nil { return fmt.Errorf("error no ExtraConfig for 'car'") } if configMap["car"] != "ferrari" { return fmt.Errorf("error ExtraConfig 'car' != ferrari") } if configMap["num"] == nil { return fmt.Errorf("error no ExtraConfig for 'num'") } // todo this should be an int, getting back a string if configMap["num"] != "42" { return fmt.Errorf("error ExtraConfig 'num' != 42") } *vm = virtualMachine{ name: rs.Primary.ID, } return nil } }