This is the second post around developing Go code against the vSphere/vCenter APIs using govmomi, if you’re new to this then I would recommend you start with https://thebsdbox.co.uk/2019/07/04/First-steps-with-Govmomi to fully grasp the basic concepts.
Extending our example
The example that we built in the previous post was a very simplistic example that contained only the basic functionality to log into a vSphere/vCenter server, other than testing a users credentials it had no real functionality. In this post we will extend its functionality in order for it to actually interact with various objects and types that exist in both vSphere and vCenter.
Proposed functionality
The next version of our demo application will have the following functionality:
Retrieve objects
Select objects via type VM/Network/Storage
Implement RegEX filters to sort results
The credentials will be passed via environment variables, and the the search parameters will be passed in through CLI flags.
// Check that an address was actually entered if v.address == "" { return nil, fmt.Errorf("No VMware vCenter URL/Address has been submitted") }
// Check that the URL can be parsed u, err := url.Parse(v.address) if err != nil { return nil, fmt.Errorf("URL can't be parsed, ensure it is https://username:password/<address>/sdk") }
// Check if a username was entered if v.username == "" { // if no username does one exist as part of the url if u.User.Username() == "" { return nil, fmt.Errorf("No VMware vCenter Username has been submitted") } } else { // A username was submitted update the url u.User = url.User(v.username) }
if v.password == "" { _, set := u.User.Password() if set == false { return nil, fmt.Errorf("No VMware vCenter Password has been submitted") } } else { u.User = url.UserPassword(u.User.Username(), v.password) } return u, nil }
// Create a new finder that will discover the defaults and are looked for Networks/Datastores f := find.NewFinder(c.Client, true)
// Find one and only datacenter, not sure how VMware linked mode will work dc, err := f.DatacenterOrDefault(ctx, "") if err != nil { return fmt.Errorf("No Datacenter instance could be found inside of vCenter %v", err) }
// Make future calls local to this datacenter f.SetDatacenter(dc)
// Set the host that the VM will be created on i.hostSystem, err = f.HostSystemOrDefault(ctx, i.findHost) if err != nil { return fmt.Errorf("%v", err) }
// Find the resource pool attached to this host i.resourcePool, err = i.hostSystem.ResourcePool(ctx) if err != nil { return fmt.Errorf("Error locating default resource pool") }
i.network, err = f.NetworkOrDefault(ctx, i.findNetwork) if err != nil { return fmt.Errorf("Network could not be found") }
// Create a new finder that will discover the defaults and are looked for Networks/Datastores f := find.NewFinder(c.Client, true)
// Find one and only datacenter, not sure how VMware linked mode will work dc, err := f.DatacenterOrDefault(ctx, "") if err != nil { return nil, fmt.Errorf("No Datacenter instance could be found inside of vCenter %v", err) }
// Make future calls local to this datacenter f.SetDatacenter(dc)
vms, err := f.VirtualMachineList(ctx, "*")
if sortVMs == true { // Sort function to sort by name sort.Slice(vms, func(i, j int) bool { switch strings.Compare(vms[i].Name(), vms[j].Name()) { case -1: return true case 1: return false } return vms[i].Name() > vms[j].Name() }) }
return vms, nil }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
func searchVMS(searchString string, v []*object.VirtualMachine) ([]*object.VirtualMachine, error) {
var newVMList []*object.VirtualMachine var err error for x := range v { matched, err := regexp.MatchString(searchString, v[x].Name()) if err != nil { break } // If the regex matches then add it to the new subset if matched == true { newVMList = append(newVMList, v[x]) } } if err == nil { return newVMList, nil } return nil, err }