MrPointy's journey designing, building and deploying private clouds

pyVmomi - Creating Datacenters and Clusters

2015-10-15

This post is part 2 of a small series of articles about how to use pyVMomi to build, configure and manage vmware vsphere environments.

For more information on the earlier posts please refer to Part 1

Updating our YAML file for Datacenters and Clusters

You will recall that the strategy for our sample program is to encapsulate the configuration we want to achieve in a simple YAML file.

In this section we will extend that YAML file structure noting that in a vSphere environment you may want to create multiple datacenters and multiple clusters. For our design we want to be able to cater for multiple datacenters that may contain zero (or more clusters).

For this post we wont add the hosts into the cluster as we’ll cover that in part 3.

YAML configuration file

Previously we had the following definition :

1
2
3
4
5
6
7
cat labconfig.yaml
lab:
vsphere:
vcenter:
ip: 192.168.10.11
user: administrator@vsphere.local
pw: vmware

We will now extend this by adding a section for datacenters that may contain cluster definitions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat labconfig.yaml
lab:
vsphere:
vcenter:
ip: 192.168.10.11
user: administrator@vsphere.local
pw: vmware
topology:
- dc:
name: LABDC
clusters:
- name: LABC
- dc:
name: LABDC1

As you can see, a topology section has been added. Basically, this allows us to represent multiple ‘dc’ items that can in turn encapsulate multiple (or no) cluster?

Now, let’s look at the code side of things. The YAML parser will take care of capturing our configuration from the labconfig.yaml file. We need to use that information to make the correct calls to the vSphere SDK via pyVmomi.

Before we start we need to have some idea how the objects that we want to create Datacenters and Clusters are reprented in the pyVmomi SDK.

The first place we should look is the github site where the pyVmomi project lives https://github.com/vmware/pyvmomi/.

Let’s drill a little deeper into the documentation and browse through the docs/vim directory. Here we can find considerable documentation on how the vSphere API is mapped to python functions and classes.

A quick browse shows us that we have documentation on Datacenters, Clusters and Folders.

Why Folders?

In vSphere, objects live in folders. You cannot create a datacenter object outside of the folder structure and you can see by browsing the Folder.rst file that CreateCluster is actually a method of the vim.Folder class.

We have discovered that to create a datacenter we need a folder to put it in. What folder should we use? The choice is arbitrary for this blog so we choose the top of the folder hierarchy known as the rootFolder unless we specifically request a folder name.

Handling Errors?

Since we are creating and modifying objects we need a strategy to handle situations when objects pre-exist or cannot be modified.

pyVmomi and python in general offer some easy to grasp strategies. pyVmomi allows us to query the vSphere environment to see if objects exist and python allows us to use tryexcept blocks to recover from faults passed back to us from vSphere.

As Datacenters and Clusters are easily identifiable objects we can search for them by name. If they exist then we’ll leave them alone, otherwise we’ll create them.

To search for objects in pyVmomi we’ll add the following helper function to our VCenter class.

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_obj(self, vimtype, name):
"""
Get the vsphere object associated with a given text name
"""
obj = None
container = self.content.viewManager.CreateContainerView(self.content.rootFolder, vimtype, True)
for c in container.view:
if c.name == name:
obj = c
break
return obj

This generic method allows us to query the vSphere environment for an object by name. For example, the following code snippet allows us to query for datacenters by name.

1
2
3
4
5
6
datacenter = get_obj([vim.Datacenter], "LABDC")
if datacenter is not None:
print("datacenter %s already exists" % dcname)
return datacenter

A similar strategy would be used for Clusters, however, in that case the class is vim.ClusterComputerResource

At this point we can extend our initial program to include the following functionality :

  1. Checking to see if a Datacenter exists and if it does not then create it in the root folder.
  2. If required, check to see if a specified cluster exists and if it does not then create it in the specified datacenter.

Here is the complete program :

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/python
"""
Using the pyVmomi python bindings for vSphere connect to a VCSA and configure Datacenters and Clusters
as per th spefified configuration file.
"""
import atexit
import yaml
import inspect
class Vcenter(object):
def __init__(self, vcenter_params):
self.pyVmomi = __import__("pyVmomi")
self.server = vcenter_params['ip']
self.username = vcenter_params['user']
self.password = vcenter_params['pw']
self.connect_to_vcenter()
def create_datacenter(self, dcname=None, folder=None):
datacenter = self.get_obj([self.pyVmomi.vim.Datacenter], dcname)
if datacenter is not None:
print("datacenter %s already exists" % dcname)
return datacenter
else:
if len(dcname) > 79:
raise ValueError("The name of the datacenter must be under 80 characters.")
if folder is None:
folder = self.service_instance.content.rootFolder
if folder is not None and isinstance(folder, self.pyVmomi.vim.Folder):
print("Creating Datacenter %s " % dcname )
dc_moref = folder.CreateDatacenter(name=dcname)
return dc_moref
def create_cluster(self, cluster_name, datacenter):
cluster = self.get_obj([self.pyVmomi.vim.ClusterComputeResource], cluster_name)
if cluster is not None:
print("cluster already exists")
return cluster
else:
if cluster_name is None:
raise ValueError("Missing value for name.")
if datacenter is None:
raise ValueError("Missing value for datacenter.")
print("Creating Cluster %s " % cluster_name )
cluster_spec = self.pyVmomi.vim.cluster.ConfigSpecEx()
host_folder = datacenter.hostFolder
cluster = host_folder.CreateClusterEx(name=cluster_name, spec=cluster_spec)
return cluster
def get_obj(self, vimtype, name):
"""
Get the vsphere object associated with a given text name
"""
obj = None
container = self.content.viewManager.CreateContainerView(self.content.rootFolder, vimtype, True)
for c in container.view:
if c.name == name:
obj = c
break
return obj
def connect_to_vcenter(self):
from pyVim import connect
print("Connecting to %s using username %s" % (self.server, self.username))
self.service_instance = connect.SmartConnect(host=self.server,
user=self.username,
pwd=self.password,
port=443)
self.content = self.service_instance.RetrieveContent()
about = self.service_instance.content.about
print("Connected to %s, %s" % (self.server, about.fullName))
atexit.register(connect.Disconnect, self.service_instance)
def main():
config = yaml.load(open("labconfig.yaml"))
vc=Vcenter(config["lab"]["vsphere"]["vcenter"]);
dc=config["lab"]["vsphere"]["topology"]
# for each datacenter, get the name and optionally if there is a key for clusters
# then create matching clusters
# in this datacenter, otherwise just create the datacenter.
for i in dc:
datacenter = vc.create_datacenter(dcname=i['dc']['name'])
if i['dc'].has_key('clusters') :
for j in i['dc']['clusters']:
cluster=vc.create_cluster(j['name'],datacenter)
return 0
# Start program
if __name__ == "__main__":
main()

Here is what the VCSA looked like before the job executed.

before
1
2
3
4
5
6
7
8
$ ./buildLabConfig.py
Connecting to 192.168.10.11 using username administrator@vsphere.local
/usr/lib/python2.7/site-packages/urllib3/connectionpool.py:769: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
InsecureRequestWarning)
Connected to 192.168.10.11, VMware vCenter Server 5.5.0 build-2183111
Creating Datacenter LABDC
Creating Cluster LABC
Creating Datacenter LABDC1

and this is what it looks like after execution.

after

If the program is executed a second or subsequent time then you will see warnings as follows :

1
2
3
4
5
6
7
8
$ ./buildLabConfig.py
Connecting to 192.168.10.11 using username administrator@vsphere.local
/usr/lib/python2.7/site-packages/urllib3/connectionpool.py:769: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
InsecureRequestWarning)
Connected to 192.168.10.11, VMware vCenter Server 5.5.0 build-2183111
datacenter LABDC already exists
cluster already exists
datacenter LABDC1 already exists

Other parts in the series can be found below :

  1. Part 1 :- Connecting to the VCSA
  2. Part 2 :- Creating Datacenters and Clusters
  3. Part 3 :- Adding Hosts to Clusters
  4. Part 4 :- Adding a NFS Share to a Cluster of Hosts