Archive for July 2010
Automatically add ESX(i) to vCenter from ESX(i)
I have to say, I love my job. Since starting at the end of May, I have had the opportunity to work with some great people and tackle tasks that I have been wanting to complete yet never had the time to do at previous employers. Specifically, I am talking about automating ESX(i) deployments. I have performed many scripted installs before (in fact I had not done a full load of ESX for over 3 years and only recently did so because CNA drivers were not in the ISO), but now I am in the situation where build after build must be exactly the same no matter who is performing the builds. With that, our team started looking at the ESX Deployment Appliance (great appliance BTW), but I quickly noticed some lacking features which I quickly added to fit our current needs. (Keep your eyes out for announcement in the near future on a collaboration myself and @lynxbat will put together regarding a deployment appliance).
With the work I’ve been doing lately, I asked myself the question: why couldn’t an ESX(i) host add itself to vCenter? The easiest answer to this question is that VMware has not written a program or script to perform this task. But is their a technical reason why this would not be possible?
In order to perform any type of action on vCenter, API access is required. There are two ways to access the vCenter APIs: MOB and Web Services API. The MOB, or Managed Object Browser, is a web site that allows retrieving and setting values for vCenter. Traversing the MOB is not easy and requires frequent trips to the vSphere API documentation for assistance. The Web Services API is a web service that can be used to retrieve and set values via a SOAP client. VMware even provides SDKs for Java and Perl.
Do we have an SDK available on ESX(i)? No. This means we must see if we can access the MOB or Web Services API from ESX(i) by writing a script that does not rely on an SDK. Looking through an ESXi host, I noticed python was on the host. Why is python on the host? The MOB is written in python. There is no SOAP client libs loaded for python on ESX(i)(if there are, please post a comment), and this solution should not require loading of additional libraries to ESX(i). With that I set out and wrote a script that will connect an ESX(i) host to vCenter.
***DISCLAIMER***
Use at your own risk. I provide this script as an academic example of how to do this. I am not responsible if it does havoc on your environment. This script has only been tested with vSphere 4.1 ESXi and vCenter. ESX 4.1, ESX 4.0, and vCenter 4.0 have not been tested.
***DISCLAIMER***
First we must import the libraries we need.
import re,os,urllib,urllib2
Next, let’s set some variables that will be needed. This is where it starts to get interesting. <CLUSTER> below needs to be replaced with the cluster the host will be added to. For this exercise, this is a static assignment. This name will be in the form of domain-c21 or something similar and can be found in the MOB.
url = "https://vcenteraddress/mob/?moid=<CLUSTER>&method=addHost" username = "vcenterusername" password = "vcenterpassword"
This section configures the authentication for when we connect to the MOB.
passman = urllib2.HTTPPasswordMgrWithDefaultRealm() passman.add_password(None,url,username,password) authhandler = urllib2.HTTPBasicAuthHandler(passman) opener = urllib2.build_opener(authhandler) urllib2.install_opener(opener)
This next section computes the SHA1 hash for the host and strips out all unnecessary characters. As you can tell, my regex skills are a bit rusty, and this probably could be cleaned up.
cmd = "openssl x509 -sha1 -in /etc/vmware/ssl/rui.crt -noout -fingerprint" tmp = os.popen(cmd) tmp_sha1 = tmp.readline() tmp.close() s1 = re.split('=',tmp_sha1) s2 = s1[1] s3 = re.split('\n', s2) sha1 = s3[0]
This next section creates the ConnectHostSpec information that needs to be passed to the addHost method.
xml = """<spec xsi:type="HostConnectSpec"> <hostName>192.168.188.130</hostName> <sslThumbprint>%s</sslThumbprint> <userName>root</userName> <password>rootpassword</password> <force>1</force> </spec>"""xml = xml.replace("%s",sha1)
Once the ConnectHostSpec is created, we can now encode the parameters that must be sent with the POST to the addHost method. As you can see, besides the ConnectHostSpec, we must also pass values for asConnected, resoursePool, and license. Only spec and asConnected require a value. After the values are encoded, a request can be created and the data sent to the URL.
params = {'spec':xml,'asConnected':'1','resourcePool':'','license':''} e_params = urllib.urlencode(params) req = urllib2.Request(url,e_params) page = urllib2.urlopen(req).read()
And that’s it. This small script will take the parameters needed to add an ESX(i) host to vCenter through the MOB and complete this task from the host itself. I am currently testing integrating this script with scripted installs. Stay tuned as I am already getting more ideas for this script.