WilliamLam.com

  • About
    • About
    • Privacy
  • VMware Cloud Foundation
  • VKS
  • Homelab
    • Hardware Options
    • Hardware Reviews
    • Lab Deployment Scripts
    • Nested Virtualization
    • Homelab Podcasts
  • VMware Nostalgia
  • Apple

How to automatically add ESX(i) host to vCenter in Kickstart

03.29.2011 by William Lam // 65 Comments

While recently updating my Automating Active Directory Domain Join in ESX(i) Kickstart article, it reminded me an old blog post by Justin Guidroz who initially identified a way to add an ESXi host to vCenter using python and the vSphere MOB. The approach was very neat but was not 100% automated as it required some user interaction with the vSphere MOB to identify certain API properties before one could potentially script it within a kickstart installation.

I decided to revisit this problem as it was something I had investigated awhile back. There are numerous ways on getting something like this to work in your environment, but it all boils down to your constraints, naming convention and provisioning process. If you have a well defined environment and utilizing a good naming structure and can easily identify which vCenter a given ESX(i) host should be managed from, then this can easily be integrated into your existing kickstart with minor tweaks. This script was tested on vCenter 4.1 Update 1 and ESXi 4.1 and 4.1 Update1.

UPDATE (03/29/2011): Updated the IP Address extraction to use gethostbyname and added proper logout logic after joining vCenter.

UPDATE (02/01/2013): I have provided a download link to the joinvCenter.py script below as there have been some funky formatting issues when displaying the script. For ESXi 5.x hosts, you will need to ensure httpClient is enabled (disabled by default) on the ESXi firewall else it will not be able to connect to your vCenter Server. Please refer below for the instructions.

There are a few steps that are necessary before we get started and a recommended one for those that have security concerns around this solution.

Step 1 - You will need to extract some information from the vCenter server in which you would like your ESX(i) hosts to join. You will need to generate an inventory path to the vCenter cluster which will take the form of: [datacenter-name]/host/[cluster-name], this will automatically locate the managed object ID of your vCenter cluster which is required as part of the host add process. This was a manual process in Justin's original solution.

In this example, I have a datacenter called "Primp-Skunkworks" and a cluster under that datacenter called "Primp-Skunkworks-Cluster", the inventory path will look like the following:  

"Primp-Skunkworks/host/Primp-Skunkworks-Cluster"

You will need this value to populate a variable in the script which will be described a little bit later

Step 2 - As you may have guessed, to add an ESX(i) host to vCenter, you will need to connect to vCenter server and use an account that has the permission to add a host. It is recommended that you do not use or expose any administrative accounts for this as the credentials are stored within the script unencrypted. A work around is to create a service account whether that is a local account or an Active Directory account with only the permission to add an ESX(i) host to a vCenter cluster. You will create a new role, in this example I call it "JoinvCenter" and you just need to provide the Host->Inventory->Add host to cluster privilege.

Once you have created the role, you will need to assign this role to the service account user either globally in vCenter if you want to add to multiple cluster or a given datacenter/cluster.

Now that we have the pre-requisites satisfied, we will need to populate a few variables within the script which will be used in your %post section of ESX(i) kickstart configuration file.

This variable defines the name of your vCenter server, please provide the FQDN:

This variable define the vCenter cluster path which was generated earlier:

These variables define the server account credentials used to add an ESX(i) host to vCenter. You will need to run the following command to encode the selected password. You will need access to a system with python interpreter to run the following command:

python -c "import base64; 
print base64.b64encode('MySuperDuperSecretPasswordYo')"

Note: This does not encrypt your password but obfuscate it slightly so that you are not storing the password in plain text. If a user has access to the encoded hash, it is trivial to decode it.

These variables define the ESX(i) root credentials which is required as part of the vCenter add process. If you do not want to store these in plain text, you will also need to encode them using the command in previous section:

We are now all done and ready to move forward with the actual script which will be included in your kickstart configuration. As a sanity check, you can run this script manually on an existing ESX(i) host to ensure that the process works before testing in kickstart. For ESXi 5.x hosts, ensure httpClient firewall ruleset is enabled by following ESXCLI command:

esxcli network firewall ruleset set -e true -r httpClient

 You should also ensure this is the very last script to execute as I ran into a race condition while the root password was being updated automatically from the default 999.* scripts. To ensure this is the very last script, set the --level to something like 9999 in your %firstboot stanza

Download: joinvCenter.py

To aide in troubleshooting, the script also outputs the details to syslog and on ESX(i), it will be stored in /var/log/messages and you can just search for the string "GHETTO-JOIN-VC". If everything is successful, after %firstboot section has completed, you should be able to see an ESX(i) host join vCenter and the following in the logs.

Tips: You should only see "Success" messages, if you see any "Failed" messages, something went wrong. If you are still running into issues, make sure your ESX(i) host has it's hostname configured with FQDN and you should see an error on your vCenter server if it fails to whether it's due to hostname and/or credentials. You can also redirect the output of the script to local VMFS volume for post-troubleshooting.

Depending on your provision process and how you determine which ESX(i) host should join which vCenter/cluster, you can easily add logic in the main kickstart configuration file to automatically determine or extract from a configuration file and dynamically update joinvCenter.py script prior to execution.

I would like to thank Justin Guidroz and VMTN user klich for their contributions on the python snippets that were used in the script. 

FYI - I am sure the python code could be cleaner but I will leave that as an exercise for those more adept to python. My python-fu is not very strong 😉

Categories // Uncategorized Tags // ESXi 4.1, kickstart, vCenter Server

Automating Active Directory User Management in ESXi Kickstart

02.24.2011 by William Lam // 2 Comments

In the previous post we looked at Automating Active Directory Domain Join in ESXi Kickstart. We are now going to look at adding domain users without having to manually go through vSphere Client or external scripts after an ESXi host has been provisioned. We are going to be leveraging vim-cmd to accomplish this during the kickstart installation. Before doing so, you will need to know the the available roles on a default ESXi host and the syntax for a given permission.

To see the available roles, you can run the following command on an already provisioned ESXi host:

vim-cmd vimsvc/auth/roles | less

The default roles on an ESXi host are:

  • NoAccess
  • ReadOnly
  • Admin

To see the existing permissions, you can run the following command on an already provisioned ESXi host:

vim-cmd vimsvc/auth/permissions

These entries will match what you see in the vSphere Client and dictate who has login access to the ESXi host.

To add a new permission, we will be using the "vim-cmd vimsvc/auth/entity_permission_add" and it requires five parameters.

  • First - Entity (This can be found by looking at the output from permissions)
  • Second - Username
  • Third - Boolean on whether this is a group or not (should be false)
  • Fourth - The role to be applied to the user
  • Fifth - Boolean on whether to propagate this permission

If you manually add a domain user, you can easily verify the user can login by running the "id" command which will perform a look up on the user. If it is successful, it should return an entry corresponding to something like this:

Note: We need to use the double slash "\" to escape the initial slash when running the query. Also make note of the domain name as it may or may not match your full domain name.

We are now ready to craft a simple script that will add domain users as part of the ESXi kickstart process. The following snippet should be placed in the %firstboot section of your kickstart and after your Active Directory domain join code. Make sure you replace the DOMAIN_NAME variable along with the usernames. In the example I have two separate for loops to handle ReadOnly and Admin users, you do not need both if you are only adding one type of users.

The script basically performs a simple 60sec sleep to ensure the domain join process has completed before continuing. If you do not place a sleep, the subsequent code will fail to execute. The next step is to validate the user by doing a simple lookup using "id" command and upon successful look up of the user, we add the appropriate permissions.

Note: We only have two add these two entities: "vim.Folder:ha-folder-root" and "vim.ComputeResource:ha-compute-res" to properly add a permission.

If everything was successful, after your ESXi installation you now should have your host joined to your Active Directory and a list of domain users who now have permission to login to the ESXi host. You can verify by using the vSphere Client and taking a look at the Permissions tab.

If you would like to create custom roles on your ESXi host, you can use the following command:

vim-cmd vimsvc/auth/role_add

Note: The syntax for the privileges parameter lists only five, but it actually accepts as many as you need with the custom role

Categories // Uncategorized Tags // active directory, ESXi 4.1, kickstart, mob, vimsh

Automating Active Directory Domain Join in ESX(i) Kickstart

02.23.2011 by William Lam // 10 Comments

I recently received an email asking if it was possible to automate the joining of an ESXi 4.1 host to Active Directory within a kickstart installation. The simple answer is yes; you can easily do so using the same trick found in tip #7 in Automating ESXi 4.1 Kickstart Tips & Tricks post which connects locally to the vSphere MOB using python.

Having said that, there is a small caveat to this solution in which the credentials used to join the ESX(i) host must be exposed in clear-text, this may or may not be acceptable. A potential way of getting this to work is to create a dedicated windows service account with limited privileges to add only ESXi hosts to your domain.

The reason for the use of clear-text password is the vSphere API method that is used to join an ESX(i) host to AD domain, joinDomain(), only supports plain text.

Ideally, the password parameter should accept either an encrypted hash or some type of certificate which can be validated by Active Directory server. The actual solution is pretty straight forward, by crafting the appropriate call to vSphere MOB, we are able to generate a python script during the %firstboot section of ESX(i) kickstart installation which will execute upon the initial boot up of the host.

Update (03/26/11):  Thanks to VMTN user klich who has found a solution to embed the password of the Active Directory user in a base64 encoding so that it is not visible in plain text for anyone who has access to the kickstart configuration file. To create the encoded hash, you will need access to either a ESX(i) or UNIX/Linux system which has python interpreter installed.

You will need to run the following command and substitute the password you wish to encode.

python -c "import base64;
print base64.b64encode('MySuperSecurePasswordYo')"

The output will be your encoded hash:

Note: Make sure your ESX(i) hostname is configured with a FQDN (Fully Qualified Domain Name), else you will get an error when trying to join to AD domain.

The following snippet should be added to your %firstboot section of your kickstart. Remember to replace the variables: domainname, ad_username and encodedpassword with your configurations and make sure to leave the password variable blank.

ESX(i) 4.1
cat > /tmp/joinActiveDirectory.py << __JOIN_AD__

import sys,re,os,urllib,urllib2

# MOB url
url = "https://localhost/mob/?moid=ha-ad-auth&method=joinDomain"

# mob login credentials -- use password = "" for build scripting
username = "root"
password = ""

# which domain to join, and associated OU
# e.g.
#       "primp-industries.com"
#       "primp-industries.com/VMware Server OU"
domainname = "primp-industries.com"

# active directory credentials using encoded base64 password
ad_username = "*protected email*"
encodedpassword = "TXlTdXBlclNlY3VyZVBhc3N3b3JkWW8"
ad_password = base64.b64decode(encodedpassword)

#auth
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None,url,username,password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)

#execute method
params = {'domainName':domainname,'userName':ad_username,'password':ad_password}
e_params = urllib.urlencode(params)
req = urllib2.Request(url,e_params)
page = urllib2.urlopen(req).read()
__JOIN_AD__

#execute python script to Join AD
python /tmp/joinActiveDirectory.py

If you are using ESX(i) 4.1 Update 1 or if you run into the "urllib2.HTTPError: HTTP Error 403: Forbidden: Possible Cross-Site Request Forgery" you will need to use the following snippet below which includes the session cookie as part of the request to the vSphere MOB due to a recent CSRF patch from VMware identified by VMTN user klitch.

ESX(i) 4.1 Update 1

cat > /tmp/joinActiveDirectory.py << __JOIN_AD__

import sys,re,os,urllib,urllib2,base64

# mob url
url = "https://localhost/mob/?moid=ha-ad-auth&method=joinDomain"

# mob login credentials -- use password = "" for build scripting
username = "root"
password = ""

# which domain to join, and associated OU
# e.g.
#       "primp-industries.com"
#       "primp-industries.com/VMware Server OU"
domainname = "primp-industries.com"

# active directory credentials using encoded base64 password
ad_username = "*protected email*"
encodedpassword = "TXlTdXBlclNlY3VyZVBhc3N3b3JkWW8"
ad_password = base64.b64decode(encodedpassword)

# Create global variables
global passman,authhandler,opener,req,page,page_content,nonce,headers,cookie,params,e_params

# Code to build opener with HTTP Basic Authentication
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None,url,username,password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)

### Code to capture required page data and cookie required for post back to meet CSRF requirements  ###
req = urllib2.Request(url)
page = urllib2.urlopen(req)
page_content= page.read()

# regex to get the vmware-session-nonce value from the hidden form entry
reg = re.compile('name="vmware-session-nonce" type="hidden" value="?([^\s^"]+)"')
nonce = reg.search(page_content).group(1)

# get the page headers to capture the cookie
headers = page.info()
cookie = headers.get("Set-Cookie")

# Code to join the domain
params = {'vmware-session-nonce':nonce,'domainName':domainname,'userName':ad_username,'password':ad_password}
e_params = urllib.urlencode(params)
req = urllib2.Request(url, e_params, headers={"Cookie":cookie})
page = urllib2.urlopen(req).read()

__JOIN_AD__

#execute python script to Join AD
python /tmp/joinActiveDirectory.py
After your ESXi host has completed installation, you can login to the ESX(i) host using the vSphere Client and you should see a recent successful task on the domain join process.

You can also verify by clicking on Configurations->Authentication Services and verify that your ESX(i) host is now part of the Active Directory domain.

In the next post, I will go over the details of adding domain users within the ESX(i) kickstart.

As a side note, it is quite unfortunate that ESXi only supports Microsoft Active Directory and does not integrate with other well known directory services such as NIS/NIS+, Kerberos, OpenLDAP, eDirectory, etc; this was actually possible with classic ESX. VMware has continued to focus on Windows-centric solutions and neglect the UNIX/Linux community by not supporting OS agnostic management tools that integrate with their vSphere platform. I hope this will change in the future for true interoperability.

Categories // Uncategorized Tags // active directory, ESXi 4.1, kickstart, mob

  • « Previous Page
  • 1
  • …
  • 9
  • 10
  • 11
  • 12
  • Next Page »

Search

Thank Author

Author

William is Distinguished Platform Engineering Architect in the VMware Cloud Foundation (VCF) Division at Broadcom. His primary focus is helping customers and partners build, run and operate a modern Private Cloud using the VMware Cloud Foundation (VCF) platform.

Connect

  • Bluesky
  • Email
  • GitHub
  • LinkedIn
  • Mastodon
  • Reddit
  • RSS
  • Twitter
  • Vimeo

Recent

  • VCF 9.0 Hardware Considerations 05/30/2025
  • VMware Flings is now available in Free Downloads of Broadcom Support Portal (BSP) 05/19/2025
  • VMUG Connect 2025 - Minimal VMware Cloud Foundation (VCF) 5.x in a Box  05/15/2025
  • Programmatically accessing the Broadcom Compatibility Guide (BCG) 05/06/2025
  • Quick Tip - Validating Broadcom Download Token  05/01/2025

Advertisment

Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here: Cookie Policy

Copyright WilliamLam.com © 2025