I haven’t worked on VMware for a while but needed to work on a project to automatically install ESXi on a few servers. I invented a tool called KUBAM that was originally for deploying Kubernetes on UCS Bare Metal (KUBAM) but have realized there are a lot of people that can benefit from the use of vMedia policy installations. I’ve written a few articles on this method here and there.
When looking to deploy ESXi we had made the kickstart portion work perfectly and even upgraded it to 6.7. However, when looking for information on how to automatically register the ESXi servers to vCenter after the installation was concluded the best we found was information from the legendary WIlliam Lam at VMware from a post in 2011. Here we are 7 almost 8 years later still trying to accomplish the same thing. The problem is the post was written in 2011 and ESXi updated the version from Python 2 to Python 3 and so parts of the script don’t work. I’ve updated it in a dirty way to make it work and checked the code into the KUBAM project. It could use some cleaning up to make it nice like William’s python. I may do that as time goes on. For now here is the code:
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 107 108 109 110 111 112 113 114 115 116 117 |
import sys,re,os,urllib,base64,syslog,socket import urllib.request as request import ssl # used for unverified SSL/TLS certs. Insecure, not good for public. ssl._create_default_https_context = ssl._create_unverified_context ## Variables that need to be filled out for different environments ## # URL of vcenter, just the IP address vcenter = "10.93.140.100" # Data center #cluster = "<datacenter>/host/<cluster>" cluster = "Lucky Lab (LK02)/host/SandyBridge" # vCenter credentials user = "administrator@vsphere.local" password = "Cisco.123" # host ESXi credentials host_username = "root" host_password = "Cisco.123" url = "https://" + vcenter + "/mob/?moid=SearchIndex&method=findByInventoryPath" passman = request.HTTPPasswordMgrWithDefaultRealm() passman.add_password(None,url, user, password) authhandler = request.HTTPBasicAuthHandler(passman) opener = request.build_opener(authhandler) request.install_opener(opener) #cont = ssl._create_unverified_context() #ssl._create_default_https_context = ssl._create_unverified_context() req = request.Request(url) #cont = ssl._create_unverified_context() #page = request.urlopen(req, context=context) page = request.urlopen(req) page_content = page.read().decode('utf-8') #print(page_content) reg = re.compile('name="vmware-session-nonce" type="hidden" value="?([^\s^"]+)"') nonce = reg.search(page_content).group(1) headers = page.info() cookie = headers.get("Set-Cookie") params = {'vmware-session-nonce':nonce,'inventoryPath':cluster} e_params = urllib.parse.urlencode(params) #print(e_params) bin_data = e_params.encode('utf8') req = request.Request(url, bin_data, headers={"Cookie":cookie}) page = request.urlopen(req) page_content = page.read().decode('utf-8') #print(page_content) clusterMoRef = re.search('domain-c[0-9]*',page_content) if clusterMoRef: print("Found cluster: " + cluster) else: opener.close() sys.exit(1) # cert stuff 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] if sha1: print("Hash: ", sha1) else: opener.close() sys.exit(1) xml = '<spec xsi:type="HostConnectSpec"><hostName>%hostname</hostName><sslThumbprint>%sha</sslThumbprint><userName>%user</userName><password>%pass</password><force>1</force></spec>' # Code to extract IP Address to perform DNS lookup to add FQDN to vCenter hostip = socket.gethostbyname(socket.gethostname()) if hostip: print("IP address of host: ", hostip.strip()) else: opener.close() sys.exit(1) # could add logic to do DNS lookup, but no dns in our environment. xml = xml.replace("%hostname",hostip) xml = xml.replace("%sha",sha1) xml = xml.replace("%user",host_username) xml = xml.replace("%pass",host_password) print(xml) # now join to vcenter cluster try: url = "https://" + vcenter + "/mob/?moid=" + clusterMoRef.group() + "&method=addHost" params = {'vmware-session-nonce':nonce,'spec':xml,'asConnected':'1','resourcePool':'','license':''} e_params = urllib.parse.urlencode(params) bin_data = e_params.encode('utf8') req = request.Request(url, bin_data, headers={"Cookie":cookie}) page = request.urlopen(req).read() except IOError as e: opener.close() print("Couldn't join cluster", e) sys.exit(1) else: print("Joined vcenter cluster!") url = "https://" + vcenter + "/mob/?moid=SessionManager&method=logout" params = {'vmware-session-nonce':nonce} e_params = urllib.parse.urlencode(params) bin_data = e_params.encode('utf8') req = request.Request(url, bin_data, headers={"Cookie":cookie}) page = request.urlopen(req).read() sys.exit(0) |
A few notes here:
- urllib2 was split into different urllib packages so that is no longer included
- The top line sets the default context to not do cert checks. Usually I find in enterprise companies there are no certs so people just accept the cert even though there is no root authority.
- I only have IP addresses for hostnames, but if you have DNS then you will probably want to add contents from William’s script.
- I’m pretty lazy with this and not updating the logs. I’ll probably go back and spend some time doing that in the future if I need to.
The code is found in the KUBAM project here.
To use this code, you can include it in your ESXi Kickstart file. An example in the same directory is here. Notice the key are the last lines:
1 2 3 4 |
# register with vcenter esxcli network firewall ruleset set -e true -r httpClient wget -O vcenter.py http://10.93.140.118/kubam/vcenter.py /bin/python vcenter.py |
We put the script (renamed vcenter.py) in the ~/kubam directory of the installer. Then as the machine boots up it grabs the file and runs the script registering itself.
The install is nice and without glamour. It simply adds a new server to the cluster:
With my example I didn’t add another user account but I recommend it. I also didn’t base encode the passwords but that is something you could do as well.