First steps with Govmomi
This guide will assume that there is at least the basic familiarity to install the GO (golang) compiler tools, anyone looking for a start will find pretty much everything they need here -> https://golang.org/doc/install
What is Govmomi
The VMware virtual machine products (vSphere/ vCenter) expose the functionality through an API that is documented here -> (https://www.vmware.com/support/pubs/sdk_pubs.html). The technology that these APIs are exposed through is called SOAP (https://en.wikipedia.org/wiki/SOAP) and can be a little bit of a headache to interact with directly. However to ease the lives of anyone wanting to develop code against this SOAP api, VMware have released SDKs and libraries in a variety of languages (python, Java, .Net etc..). The Govmomi library is a GO package that provides the majority of functionality that an end user needs in order to communicate with the VMware vSphere/vCenter APIs.
Getting govmomi
All of the required source code for the VMware vSphere/vCenter GO SDK can be found on github at the following url -> (https://github.com/vmware/govmomi) as mentioned on the README has the go command for pulling the govmomi package.
go get -u github.com/vmware/govmomi
Note: The -u
flag instructs go to pull any named dependencies.
To ensure that the govmomi packages were downloaded correctly we should be able to see all the code source tree by running the following command:
ls -la $(go env GOPATH)/src/github.com/vmware/govmomi
Hello World
Just to check that our environment is working as expected lets quickly create the hello world example to just to verify your GO environment. The following code snipped will create a file called govmomi/example.go
which we can then use to ensure that things are working as expected.
The following commands can be copy and pasted into a terminal and will create a local govmomi
directory and create the example.go
file that we will use for development moving forward.
Hello World source code
1 | mkdir govmomi; cd govmomi |
To run the above code we can use the following command go run example.go
, and we should see Hello world
printed to STDOUT.
Logging into VMware vSphere or vCenter
The following code snippet will extend on our previous example, and will make use of additional packages including the govmomi
package to provide our required functionality.
Note: This code uses the url of the vSphere/vCenter instance were trying to interact with. This url will always require the following formatting:
protocol
://username
:password
@hostname
/sdk
A correct example would be:
https://administrator@vsphere.local:pass1234@vcenter.devlab.local/sdk
Updated source code
1 | package main |
To understand this code we will deconstruct the various important sections.
Imports
To provide the required functionality were pulling in a lot more packages, for a bit more understanding I’ve added either the project URL or the godoc location.
context
- https://golang.org/pkg/context/flag
- https://golang.org/pkg/flag/fmt
- https://golang.org/pkg/fmt/net/url
- https://golang.org/pkg/net/url/govmomi
- https://github.com/vmware/govmomi
Flags
There are a number of different methods a developer could use to pass data into a program, it could even be hardcoded into the code itself (not recommended). The main options for getting data into a simple CLI program are:
- Read the data from a file
- Pass data from environment variables
- Pass data to the program at runtime through command line flags
In our example we will be using flags thats are provided through the standard library and work in a key/value fashion. The key being the name of the flag -url
and the value being data we pass to this key https://{...}
.
The following two lines taken from the code above will handle the user input from the CLI.
This first line will declare a variable vURL
that will be assigned from the flag named url
.vURL := flag.String("url", "", "The URL of a vCenter server")
The second line will parse all of the created flags to ensure that they’re read correctly or assigned their default values etc..flag.Parse()
URL Parsing
The govmomi
client requires a URL object not just a string representation of the vCenter URL. So we will use the net/url
library to parse the string taken from the flag -url
as done with the line u, err := url.Parse(*vURL)
Context
The two lines around context
(explained above) are used to ensure that a state is shared across multiple APIs, functions and goroutines. In our simple example we don’t need to delve into this in two much detail, but if were to imaging that there were multiple operations taking place such as processing some data, logging into vCenter etc.. and one of the operations failed for a reason, the context would be used to share the fact that all of the other operations sharing that context needs cancelling.
Creating a vCenter/vSphere client
At this point in the code we’ve taken the VMware vCenter URL from a CLI flag and we’ve set up a context to handle a shared state, we will now use these in order to create our vCenter client with the line c, err := govmomi.NewClient(ctx, u, true)
.
Quickly deconstructing this line:
c, err
- Return the client objectc
and an error objecterr
(more orerr
in a second)govmomi.NewClient
- Call the function from thegovmomi
packagectx
- Pass in the shared contextu
- Pass in the “parsed” url (ultimately taken from the-url
string)true
- A Boolean valuetrue/false
that dictates if the client will tolerate an insecure certificate (self-signed)
If the function call doesn’t return an error
object then the login was successful so we print a message to STDOUT and call the logout method on the govmomi
client object.
Error handling
A lot of functions in GO will typically return more than one variable/object and the majority of them will return an object of type error
, we can see this by looking at the returns from the url.Parse()
and govmomi.NewClient()
function calls. In the event of a function being successful then the function will return nil
in the place of an error
object. However when things go wrong then a function should create a new error
object with the appropriate error details/messaging.
To check if a function has failed the boiler plate code would typically look like:
1 | if err != nil { |
Running our code
To run our code is very simple, we have two options we can compile it directly into a binary or run it directly from the source
Build a binary
We will build our code into a program called govmomi
with the command go build -o govmomi
we can now run our code with the command:
1 | go build -o govmomi |
Run from source
To run directly from the source code we use the go run
command as shown below:
1 | go run example.go -url "https://dan@vsphere.local:CorrectPass@vcenter.devlab.local/sdk" |
Next Steps
If everything worked as expected then there should be a success message printed on screen, in the next post we will look at extending our very basic example into something that offers a lot more functionality.
BONUS POINTS
In this example we pass in the URL through the use of flags on the CLI, another user on the same host will be able to find the vCenter URL and credentials by looking at teh list of processes. The use of environment variables will keep that hidden and within a users session.
Think about removing the flag.String
and look at os.Genenv
:-)
Further reading -> https://golang.org/pkg/os/#example_Getenv
Clearing up
To remove all of the code examples that we created we will just need to remove the govmomi
folder we created in the Hello World section.