vmware
Govmomi and listening for vSphere events
For a while, i’ve wanted to get some experience in Go (or Golang, if you prefer), but never found the time. Recently I found the need for something that allows me to capture all the VM events on an ESXi host and handle according to them.
Next to pyVmomi, VMware also has a vSphere SDK for Go, called govmomi, and I thought that this was the perfect moment to dive into Go and get my hands dirty as i already know how to work with the pyVmomi library and the vSphere SDK/API.
Coming from a (basic) Python background and not being a real developer, moving to Go was quite an adjustment and after only one or two days of playing around with it, i still have to learn a lot.
However, i can compare govmomi vs pyVmomi and one thing is immediately clear about Go and govmomi: It is fast… Really fast. What normally would take a couple of seconds in pyVmomi, takes less than a second in govmomi.
To get started with Go, you can visit the Go Tour, it helps a lot to explain the basics of Go and the important aspects. However, as all developers know, the best way to get to know a programming language, is by using it. So let’s dive deeper in how govmomi works.
pyVmomi 6.0.0, vSphere 6.0 and SSL
VMware released a new version of pyVmomi to better integrate with vSphere 6.0. This release introduces a change on the creation of an SSL connection. After struggling with some issues on this change, I wanted to write something down for future reference.
On the GitHub documentation it says pyVmomi 6.0.0 supports python 2.7, but it would be more accurate to say pyVmomi 6.0.0 supports python 2.7.9+, as in python 2.7.9 the ssl.SSLContext object has been introduced. This object allows you to specify a verification mode and a SSL Protocol. This object is needed if you want to connect correctly to the vSphere API.
You can check your python version with python --version
Workaround for python versions below 2.7.9
To get everything working in python versions below 2.7.9, the easiest way is to downgrade pyvmomi to 5.5.0.2014.1.1. To achieve this, do the following:
1 |
pip install pyvmomi==5.5.0.2014.1.1 |
This will downgrade your pyvmomi to a workable version. This version also doesn’t force SSL certificate verification, so your code can be very simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import requests from pyVim.connect import SmartConnect, Disconnect from pyVmomi import vim, vmodl # Disabling urllib3 ssl warnings requests.packages.urllib3.disable_warnings() vc = None vcenter_host = "10.0.0.10" vcenter_port = 443 vcenter_username = "root" vcenter_password = "vmware" # Connecting to vCenter try: vc = SmartConnect(host=vcenter_host, user=vcenter_username, pwd=vcenter_password, port=vcenter_port) except IOError as e: print "I/O error({0}): {1}".format(e.errno, e.strerror) # Do stuff |
Working with untrusted SSL connections with pyVmomi 6.0.0 and python 2.7.9+
If you want to connect to a vSphere 6.0 API without certificate verification using pyVmomi 6.0.0 and python 2.7.9+, you will have to create a new SSLContext which disables the certificate verification. Using pyVmomi’s SmartConnect() , there is now a new attribute you can pass, called sslContext . Below is an example on how to achieve this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import ssl import requests from pyVim.connect import SmartConnect, Disconnect from pyVmomi import vim, vmodl # Disabling urllib3 ssl warnings requests.packages.urllib3.disable_warnings() # Disabling SSL certificate verification context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) context.verify_mode = ssl.CERT_NONE vc = None vcenter_host = "10.0.0.10" vcenter_port = 443 vcenter_username = "root" vcenter_password = "vmware" # Connecting to vCenter try: vc = SmartConnect(host=vcenter_host, user=vcenter_username, pwd=vcenter_password, port=vcenter_port, sslContext=context) except IOError as e: print "I/O error({0}): {1}".format(e.errno, e.strerror) # Do stuff |
Support for both versions
If you write scripts which can run on different python and pyVmomi versions and you want to keep supporting both, you could do so by looking at the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import ssl from pyVim.connect import SmartConnect, Disconnect from pyVmomi import vim, vmodl context = None # Disabling urllib3 ssl warnings requests.packages.urllib3.disable_warnings() # Disabling SSL certificate verification if hasattr(ssl, 'SSLContext'): context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) context.verify_mode = ssl.CERT_NONE vc = None vcenter_host = "10.0.0.10" vcenter_port = 443 vcenter_username = "root" vcenter_password = "vmware" # Connecting to vCenter try: if context: vc = SmartConnect(host=vcenter_host, user=vcenter_username, pwd=vcenter_password, port=vcenter_port, sslContext=context) else: vc = SmartConnect(host=vcenter_host, user=vcenter_username, pwd=vcenter_password, port=vcenter_port) except IOError as e: print "I/O error({0}): {1}".format(e.errno, e.strerror) # Do stuff |
I have updated all my pyVmomi scripts on my GitHub repository to start working with both version with the above fix.
Upgrading vCenter Server Appliance 5.5 to 6.0 using CLI
In 6.0 the standard installation and upgrade of the vCenter Server Appliance has changed to an ISO which you can mount in Windows. This ISO provides a web interface. This interfaces asks you to install the Client Integration Plugin 6.0, after which you can use the web interface to install or upgrade your vCenter Server Appliance.
Of course, this gives us Unix users another hurdle to overcome with installing the vSphere environment. Also, the Client Integration Plugin has some issues working with the latest versions of Chrome and Firefox. Lastly, hardly anybody likes using a web interface for this kind of installations.
Luckily, VMware has been kind enough to provide us with a CLI installer as well! I’ve seen a couple of blog posts about using the CLI installer to install a new VCSA, but not as much about upgrading an existing VCSA. So i decided to do a little write-up providing some examples.
Overview of the upgrade
The tool will use a json template file containing all the information to perform the upgrade. It uses the information to first deploy a new VCSA VM on a target host. This new VCSA VM is provisioned with a temporary network. It will then migrate all the data from the existing VCSA to the new one. Once this is done, it will shut down the existing VCSA and reconfigure the network on the new VCSA to take all the settings from the old VCSA.
JSON template
Below is an example of a JSON template file that can be used to upgrade a 5.5 VCSA to a 6.0 VCSA. There are more templates inside the ISO (folder vcsa-cli-installer/templates) which you can use, but i’ve noticed some issues with these templates missing important sections.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
{ "__version": "1.0", "__comments": "Sample template to upgrade a vCenter Server with an embedded Platform Services Controller from 5.5 to 6.0.", "source.vc": { "esx": { "hostname": "<IP of ESXi with current vCenter on>", "username": "root", "password": "vmware" }, "vc.vcsa": { "hostname": "<IP of current vCenter", "username": "administrator@vsphere.local", "password": "vmware", "root.password": "vmware" } }, "target.vcsa": { "appliance": { "deployment.network": "<Name of your Management network Port group on your target ESXi>", "deployment.option": "<tiny|small|medium|large>", "name": "<VM name, this has to be different from the current vCenter VM>", "thin.disk.mode": true }, "os": { "ssh.enable": true }, "sso": { "site-name": "First-Default-Site" }, "temporary.network": { "hostname": "<Temporary hostname, does not have to be DNS resolvable>", "dns.servers": [ "<First DNS server IP>", "<Second DNS server IP>" ], "gateway": "<Gateway IP>", "ip": "<Temporary IP for migration>", "ip.family": "ipv4", "mode": "static", "prefix": "<network prefix, for instance: 24>" }, "esx": { "hostname": "<IP of ESXi to which the new VCSA should be placed on>", "username": "root", "password": "vmware", "datastore": "<The datastore name inside the target ESXi where to store the VCSA VM>" } } } |
Of course I kept some values to the default, but i’m sure you can figure out what to change where. There are a couple of important mentions I would like to mention:
- username and password in your source.vc > vc.vcsa section have to be the SSO administrator user and password (default user = administrator@vsphere.local, default pass = vmware)
- target.vcsa > appliance > name value is the name the VM will get, this has to be unique in your environment, so it can not be the same as your current VCSA, it has no impact on the hostname
- target.vcsa > sso > site-name value is just for your SSO, it has to be filled in, but just do something simple (‘First-Default-Site’ should be fine)
- target.vcsa > temporary.network: This is just temporary for during the upgrade/migration. After the migration, all the network sections are taken from the old VCSA.
- target.vcsa > esx : This is the info of the ESXi where you want to place the new VCSA VM, can be the same as the source, can be a different one. Just make sure the info is correct (if confused with the POD43 file: my local datastores have been named the same as the ESXi IP, to easily differentiate.)
Running the CLI installer
I will run this installer directly from the ISO mounted on /mnt/vcsa on a Linux machine.
I would first suggest to do a dry run, you can do so with the following command:
1 |
/mnt/vcsa/vcsa-cli-installer/lin64/vcsa-deploy upgrade --verify-only --accept-eula --no-esx-ssl-verify vcsa-upgrade-template.json |
This command will verify the configuration and all the connectivity. It will return a list of warnings and errors. Some of the more common warnings and errors you might encounter:
- Warnings about Postgresql password that will be the same as the root password of the new VCSA, this can be safely ignored.
- Warnings about port 22, this can also be safely ignored, just make sure the old and new VCSA’s can communicate through SSH
- Errors about SSO and certificates: This will prevent any upgrade, so this is something you will have to look at. Most of the time it’s an indication that your certificates were generated with a different hostname or IP than currently used. You can rectify this by going to the 5.5 VCSA’s administration web interface check that the hostname, IP and DNS settings are all correct and regenerate the certificates if needed (this requires a reboot).
After you fixed any errors, you can run the command without the --verify-only option:
1 |
/mnt/vcsa/vcsa-cli-installer/lin64/vcsa-deploy upgrade --accept-eula --no-esx-ssl-verify vcsa-upgrade-template.json |
This will start the upgrade and migration, just follow along with what is happening, you get some good info on the progress. It can take a while to finish (half an hour to an hour, easily. If you have a slow connection between the machine you are running the command and the appliances & esxi’s, it might take longer for the data transfers)
multi-clone.py improvements & random-vmotion.py
For a project i needed a couple of tools, so i improved my multi-clone.py script and created a new script: random-vmotion.py
multi-clone.py: setting advanced configuration parameters
The multi-clone.py script is improved so you are able to set advanced configuration parameters of the created VMs, this can be used if you have other tools that need some metadata or configuration.
To accomplish this, you have to use the CSV feature. The fields in the CSV have been changed slightly in comparison with the previous version:
1 2 |
'<Clone name>';'[Resouce Pool]';'[Folder]';'[MAC Address]';'[Post-processing Script]';'[Advanced VM Parameters in JSON format]' |
Fields indicated with <> are mandatory, fields indicated with [] can be left empty.
For a full documentation, you can visit the GitHub repository.
random-vmotion.py
For some testing i needed a script which would be able to vMotion a set of VMs randomly to a set of Hosts. This script does exactly that.
The script accepts a file which contains the names of the VMs to move, one per line:
1 2 3 4 |
VM01 VM02 VM03 VM04 |
It also accepts a file which contains the names of the Hosts to randomly move to, one per line:
1 2 |
host1.domain.tld host2.domain.tld |
In the default way of working, it will continue to vMotion the VMs to a random host over and over again. For example: if you use the files above with the command:
1 |
random-vmotion.py -H vcenter.domain.tld -t hosts.list -u administrator@vsphere.local -V vms.list |
It will start moving the first VM to one of the two hosts, wait 30 seconds and do the same for the second VM, and so on. Once it moved the fourth VM, it will start again with the first one.
There are more options which provide extra functionality:
- Option to move each VM only once
- Option to work in threads
- Option to decrease the interval
The full documentation can be found on the GitHub page and an overview of the options can be found below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
usage: random-vmotion.py [-h] [-d] -H HOST [-i INTERVAL] [-l LOGFILE] [-o PORT] [-p PASSWORD] [-S] -t TARGETFILE [-T THREADS] -u USERNAME [-v] -V VMFILE Randomly vMotion each VM from a list one by one to a random host from a list, until stopped. optional arguments: -h, --help show this help message and exit -d, --debug Enable debug output -H HOST, --host HOST The vCenter or ESXi host to connect to -i INTERVAL, --interval INTERVAL The amount of time to wait after a vMotion is finished to schedule a new one (default 30 seconds) -l LOGFILE, --log-file LOGFILE File to log to (default = stdout) -o PORT, --port PORT Server port to connect to (default = 443) -p PASSWORD, --password PASSWORD The password with which to connect to the host. If not specified, the user is prompted at runtime for a password -S, --disable-SSL-certificate-verification Disable SSL certificate verification on connect -t TARGETFILE, --targets TARGETFILE File with the list of target hosts to vMotion to -T THREADS, --threads THREADS Amount of simultanious vMotions to execute at once. (default = 1) -u USERNAME, --user USERNAME The username with which to connect to the host -v, --verbose Enable verbose output -V VMFILE, --vms VMFILE File with the list of VMs to vMotion |
multi-clone.py: CSV import and MAC customization
After a very busy year, I finally came around to improving my multi-clone.py pyVmomi script. I have added a minor improvement, being able to disable SSL certificate warnings, and two major improvements: CSV import and MAC customization
CSV Import
There is a new command line flag, -C, which allows you to specify a CSV file. This CSV file provides multi-clone.py with the necessary information to clone the template into a VM for each line. The fields in the CSV should be:
- VM Name (mandatory)
- Resource Pool (can be empty)
- Folder (can be empty)
- MAC address (can be empty)
- Post-processing script (can be empty)
A line should look like this:
1 |
"VM Name";"Resource Pool";"Folder";"MAC address";"Post-processing script" |
If one of the fields is empty, but the command line flag is provided, the value from the command line is used. For instance, if you started the script with the following command line:
1 |
python multi-clone.py -C /tmp/clone.csv -H vcenter01.sub.domain.tld -S -t DSL -T 4 -u user@vsphere.local -r Development -f Linux -s /tmp/script.sh |
and used the following CSV:
1 2 |
"VM01";"Testing";"Tools";"";"/tmp/tools.sh" "VM02";"";"";"";"" |
What would happen is:
- VM01 is created in the Resource Pool ‘Testing’, in the folder ‘Tools’ and the post-processing script ‘/tmp/tools.sh’ will run
- VM02 is created in the Resource Pool ‘Development’, in the folder ‘Linux’ and the post-processing script ‘/tmp/script.sh’ will run
So, the command line values are only used if no values in the CSV are provided.
Mac customization
In the CSV, you can provide a MAC address for each VM. This MAC address will be assigned to the first NIC the script finds on the new VM before powering it on (if that is not disabled).
Two warnings:
- It is your responsibility to provide MAC addresses that are not in use on your network
- The order in which the NICs are presented to the script when there are more than one, is not always the same. In all my tests it seems it will provide the first one that has been added as the first, but i can not guarantee that.
Overview
As always, you can find the script on my GitHub page: https://github.com/pdellaert/vSphere-Python/blob/master/multi-clone.py
For more documentation: https://github.com/pdellaert/vSphere-Python/blob/master/docs/multi-clone.md
And just for good measure, the full description of all flags as presented by the -h flag:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
usage: multi-clone.py [-h] [-6] [-b BASENAME] [-c COUNT] [-C CSVFILE] [-d] [-f FOLDER] -H HOST [-i] [-m] [-l LOGFILE] [-n AMOUNT] [-o PORT] [-p PASSWORD] [-P] [-r RESOURCE_POOL] [-s POST_SCRIPT] [-S] -t TEMPLATE [-T THREADS] -u USERNAME [-v] [-w MAXWAIT] Deploy a template into multiple VM's. You can get information returned with the name of the virtual machine created and it's main mac and ip address. Either in IPv4 or IPv6 format. You can specify which folder and/or resource pool the clone should be placed in. Verbose and debug output can either be send to stdout, or saved to a log file. A post-script can be specified for post-processing. And it can all be done in a number of parallel threads you specify. The script also provides the ability to use a CSV for a lot of it settings and if you want to specify the mac address of the clones (usefull for DHCP/PXE configuration). optional arguments: -h, --help show this help message and exit -6, --six Get IPv6 address for VMs instead of IPv4 -b BASENAME, --basename BASENAME Basename of the newly deployed VMs -c COUNT, --count COUNT Starting count, the name of the first VM deployed will be <basename>-<count>, the second will be <basename>-<count+1> (default = 1) -C CSVFILE, --csv CSVFILE An optional CSV overwritting the basename and count. For each line, a clone will be created. A line consits of the following fields, fields inside <> are mandatory, fields with [] are not: "<Clone name>";"[Resouce Pool]";"[Folder]";"[MAC Address]";"[Post Script]" -d, --debug Enable debug output -f FOLDER, --folder FOLDER The folder in which the new VMs should reside (default = same folder as source virtual machine) -H HOST, --host HOST The vCenter or ESXi host to connect to -i, --print-ips Enable IP output -m, --print-macs Enable MAC output -l LOGFILE, --log-file LOGFILE File to log to (default = stdout) -n AMOUNT, --number AMOUNT Amount of VMs to deploy (default = 1) -o PORT, --port PORT Server port to connect to (default = 443) -p PASSWORD, --password PASSWORD The password with which to connect to the host. If not specified, the user is prompted at runtime for a password -P, --disable-power-on Disable power on of cloned VMs -r RESOURCE_POOL, --resource-pool RESOURCE_POOL The resource pool in which the new VMs should reside, (default = Resources, the root resource pool) -s POST_SCRIPT, --post-script POST_SCRIPT Script to be called after each VM is created and booted. Arguments passed: name mac-address ip-address -S, --disable-SSL-certificate-verification Disable SSL certificate verification on connect -t TEMPLATE, --template TEMPLATE Template to deploy -T THREADS, --threads THREADS Amount of threads to use. Choose the amount of threads with the speed of your datastore in mind, each thread starts the creation of a virtual machine. (default = 1) -u USERNAME, --user USERNAME The username with which to connect to the host -v, --verbose Enable verbose output -w MAXWAIT, --wait-max MAXWAIT Maximum amount of seconds to wait when gathering information (default = 120) |