Automate your vCenter interactions from the Linux commandline with govmomi and govc

This is the first time in a LONG time that I found a tool I’m really happy with: govc allows you to interact with VMware vCenter without the need for the dreaded vClient, Windows machines or to write your own scripts to access the horrible VMware API. This way you can easily automate many tasks on VMware directly from the command line or your bash scripts.

Disclaimer: I don’t like VMware. I hated every single moment when I was forced to start a Windows VM just to interface with ESX/vCenter, so this tool is exactly what I desired.

First thing first, you’ll need the tool. You can compile it if you want, but there’s handy binaries already available on the project github page: https://github.com/vmware/govmomi/releases

I downloaded it and created a small wrapper for it:

 # curl -LO https://github.com/vmware/govmomi/releases/download/v0.9.0/govc_linux_amd64.gz
# gunzip govc_linux_amd64.gz
# cat >govc <<EOF
#!/bin/bash

export GOVC_URL='https://username:password@vsphere-ip-or-hostname/sdk'
export GOVC_DATACENTER=VSPHERE_DC
export GOVC_INSECURE=true

/usr/bin/govc_linux_amd64 \$@
EOF
# chmod +x govc*
# cp -i govc* /usr/bin/

Note that you only need GOVC_INSECURE=true if you are using self-signed certificates and you don’t have the CA added to your local trusted certs.

At this point by calling /usr/bin/govc you should be able to use the tool without specifying too many options on the command line. For a start, you can get some basic info about your environment:

 # govc about
Name:         VMware vCenter Server
Vendor:       VMware, Inc.
Version:      5.5.0
Build:        4180647
OS type:      linux-x64
API type:     VirtualCenter
API version:  5.5
Product ID:   vpx
UUID:         AAAA-BBBB-CCCC-DDDD-EEEE
# govc datacenter.info
Name:              VSPHERE_DC
Hosts:             10
Clusters:          0
Virtual Machines:  0
Networks:          6
Datastores:        14

What else can we do? Quite a lot of stuff, actually. To get an idea, just run govc without any argument. To see what parameters a command supports, run govc command –help.

For example you can easily get the datastore usage info for the whole datacenter with one simple command:

# govc datastore.info
Name:        ds1_SAS
  Path:      /VSPHERE_DC/datastore/ds1_SAS
  Type:      VMFS
  URL:       ds:///vmfs/volumes/AAAA1-BBBB-CCCC-DDDD/
  Capacity:  833.0 GB
  Free:      424.7 GB
Name:        ds2_SAS
  Path:      /VSPHERE_DC/datastore/ds2_SAS
  Type:      VMFS
  URL:       ds:///vmfs/volumes/AAAA2-BBBB-CCCC-DDDD/
  Capacity:  833.0 GB
  Free:      388.7 GB
[...]

Amazed by this, I thought I could as easily get all the info about the ESX hosts with host.info, but nope:

 # govc host.info
/usr/bin/govc_linux_amd64: default host resolves to multiple instances, please specify
# govc host.info -host.ip=192.168.100.1
Name:              192.168.100.1
  Path:            /VSPHERE_DC/host/192.168.100.1/192.168.100.1
  Manufacturer:    HP
  Logical CPUs:    24 CPUs @ 2294MHz
  Processor type:  Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz
  CPU usage:       2061 MHz (3.7%)
  Memory:          131037MB
  Memory usage:    51020 MB (1.4%)
  Boot time:       2016-08-17 18:54:24.980915 +0000 UTC

It turns out, it doesn’t work the same way. As you see, I had to use the -host.ip parameter to specify the IP address of the ESX host.

At the time I thought the -host.ip parameter was the only way to specify the target, but it’s not accepted by the vm.info command:

 # govc vm.info -host.ip=192.168.100.100
/usr/bin/govc_linux_amd64: flag provided but not defined: -host.ip
# govc vm.info -vm.ip=192.168.100.100
Name:           Control
  Path:         /VSPHERE_DC/vm/services/Control
  UUID:         AAAA-BBBB-CCCC-DDDD-FFFF
  Guest name:   Red Hat Enterprise Linux 6 (64-bit)
  Memory:       4096MB
  CPU:          3 vCPU(s)
  Power state:  poweredOn
  Boot time:    2016-04-27 11:49:10.410135 +0000 UTC
  IP address:   192.168.100.100
  Host:         192.168.100.1

At the time I was quite puzzled because I couldn’t find a good way to iterate over the hosts or VMs. Until I noticed the ls command:

 # govc ls
/VSPHERE_DC/vm
/VSPHERE_DC/network
/VSPHERE_DC/host
/VSPHERE_DC/datastore
# govc ls /VSPHERE_DC/host
/VSPHERE_DC/host/192.168.100.1
/VSPHERE_DC/host/192.168.100.2
[...]
# govc ls /VSPHERE_DC/vm
/VSPHERE_DC/vm/database
/VSPHERE_DC/vm/template
[...]
# govc ls /VSPHERE_DC/vm/database/*
/VSPHERE_DC/vm/database/opencart/DB-OPENCART01
/VSPHERE_DC/vm/database/social/DB-SOCIAL-MASTER03
/VSPHERE_DC/vm/database/social/DB_SOCIAL_SLAVE03
[...]

And after a few more minutes fiddling and reading the –help options I realized you could invoke govc with the result from the ls command as a parameter, for example:

 # govc vm.info /VSPHERE_DC/vm/database/opencart/DB-OPENCART01
Name:           DB-OPENCART01
  Path:         /VSPHERE_DC/vm/database/opencart/DB-OPENCART01
[...]
# govc ls /VSPHERE_DC/vm/database/* | xargs govc vm.info | grep ^Name
Name:           DB-OPENCART01
Name:           DB_SOCIAL_SLAVE03
Name:           DB-SOCIAL-MASTER03
[...]

Iterating over hosts, VMs and datastores is easy!

govc also allows you to run esxcli on the specified host, for example in one of my many experiments I ran:

 # govc host.esxcli --host.ip=192.168.100.1 vm process list | grep DisplayName | awk {'print $2'} | sort
TOMCAT01
TOMCAT-TEST
WS01
WS01-TEST
WS02
WS-TEST

A very important thing to notice is that every command can be run with the parameter -json=true. This outputs a machine-parsable format that includes many more details than the normal text output.

 # govc vm.info -json /VSPHERE_DC/vm/database/opencart/DB-OPENCART01 | python -m json.tool
{
    "VirtualMachines": [
        {
            "AlarmActionsEnabled": true,
            "AvailableField": null,
            "Capability": {
                "BootOptionsSupported": true,
                "BootRetryOptionsSupported": true,
                "ChangeTrackingSupported": true,
                "ConsolePreferencesSupported": false,
[...]

This, of course, could be very handy for your scripts!

More info on the project github page: https://github.com/vmware/govmomi/tree/master/govc

A small introduction to this tool that helped me get started: http://www.virtuallyghetto.com/2014/09/govmomi-vsphere-sdk-for-go-govc-cli-kubernetes-on-vsphere-part-1.html

Step-up Firefox TLS security

For some reason, I’m using the same Firefox configuration since ages. Today, when Asana insisted that my browser was too old, I was a bit puzzled since I’m running the latest Fedora and I was reasonably sure Firefox was updated. It ended up being an old TLS setting.

To change it, open a new tab and type about:config in the address bar. In the new page, search (there’s a search box) for the key security.tls.version.min and make sure it’s set to 3.

Ethernet bonding in CentOS 7

Just a few quick notes about how I configured Ethernet bonding on CentOS 7. I want to write it down because it was subtly different from what I had on CentOS 6, so I’ll have a reference for the future ;)

/etc/sysconfig/network-scripts/ifcfg-bond0

DEVICE=bond0
TYPE=Bond
BONDING_MASTER=yes
IPADDR=192.168.0.100
PREFIX=24
GATEWAY=192.168.0.1
ONBOOT=yes
BOOTPROTO=static
NM_CONTROLLED=no
USERCTL=no
BONDING_OPTS="mode=1 miimon=100 downdelay=300 updelay=30000 primary=enp2s0f0"
DEFROUTE=yes
IPV4_FAILURE_FATAL=yes
IPV6INIT=no
IPV6_AUTOCONF=no
IPV6_DEFROUTE=no
IPV6_PEERDNS=no
IPV6_PEERROUTES=no
IPV6_FAILURE_FATAL=no
DNS1=192.168.0.251
DNS2=192.168.0.252
DNS3=192.168.0.253
DOMAIN=stardata.lan

/etc/sysconfig/network-scripts/ifcfg-enp2s0f0

NAME=enp2s0f0
DEVICE=enp2s0f0
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
NM_CONTROLLED="no"
USERCTL="no"
MASTER="bond0"
SLAVE="yes"

/etc/sysconfig/network-scripts/ifcfg-enp4s0f0

NAME=enp4s0f0
DEVICE=enp4s0f0
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
NM_CONTROLLED="no"
USERCTL="no"
MASTER="bond0"
SLAVE="yes"

For more info and different methods to setup the bonding (nmtui is actually pretty cool), check the official RHEL7 documentation.