Geaux Virtual

Helping virtualize the datacenter…

Archive for the ‘Scripting’ Category

Working with the Cisco UCS XML API

with 3 comments

Working with Cisco UCS systems on a daily basis, I decided to take some time this weekend to learn more about the XML API.  Honestly, it is a thing of beauty and simplicity.  Working with the Cisco UCS XML API is as simple as sending an HTTP POST with an XML document to the UCS Manager and getting the response.  That’s it.  Isn’t that great?

Seeing as I have a couple of projects that will benefit from interacting with UCS systems, I decided to write a script in PHP to login and logout of a UCS for starters.  Then Rob Markovic asked, “Why not PowerShell?”.  So I wrote the same script in PowerShell as well.  I do need to give credit to Steve Chambers for this post: Access UCS API with Ruby.  This was beneficial as I was reading the XML API documentation and starting to work on my scripts.

***Disclaimer***

I am not an expert in PHP or PowerShell.  I am providing this information for academic purposes only to show how easy it is to work with the UCS XML API.  I am also not responsible for any damage this may cause your systems.

***Disclaimer***

One thing you’ll notice with the Cisco UCS XML API is that the only methods that require a username and password to be passed is the aaaLogin and aaaRefresh methods.  All other methods require a cookie to be passed, which is only obtained by logging in or refreshing your session to the UCS Manager.

Let’s start with what’s needed for PHP to work with the Cisco XML API.  I downloaded and installed HTTP_Request2 from PEAR to make the HTTP call easier.

require_once HTTP/Request2.php;

Now we need to set the url of our server and the XML parameters for logging into the UCS system.

$url = “http://server ip or dns/nuova”;

$aaaLogin = “<aaaLogin inName=’username’ inPassword=’password’ />”;

With the url and XML set, we can now create our HTTP request for logging in.

$request = new HTTP_REQUEST2($url, HTTP_REQUEST2::METHOD_POST);

$request->setHeader(“Content-type: text/xml”);

$request->setBody($aaaLogin);

After the request is created, we can send the data to the UCS Manager and get our response.

$response = $request->send();

To make it easier to work with the response, we are going to create SimpleXMLElement from the response.

$xml = new SimpleXMLElement($response->getBody());

Now to get our cookie from the XML response, we just need to do the following:

$outCookie = $xml->attributes()->outCookie

With the cookie now obtained, we are free to call other UCS XML API methods for interacting with the system.  To logout, we need to create the logout xml and issue an HTTP POST with this data.  (I will not repeat the code for issuing the HTTP POST).  Here is the XML for logging out of the system.

$aaaLogout = “<aaaLogout inCookie=’cookie for session’ />”;

To verify status of logout, you look at the outStatus attribute from the XML response.

$outStatus = $xml->attributes()->outStatus;

Here is how to do the same with PowerShell.

$url = “http://server ip or dns/nuova”

$aaaLogin = “<aaaLogin inName=’username’ inPassword=’password’ />

$request = [System.Net.HttpWebRequest] [System.Net.HttpWebRequest]::Create($url)

$request.Method = “POST”

$request.ContentType = “text/xml”

$sendData = new-object System.IO.StreamWriter($request.GetRequestStream())

$sendData.Write($aaaLogin)

$sendData.Close()

$response = $request.GetResponse()

$sr = new-object System.IO.StreamReader($response.GetReponseStream())

$xml = [xml] $sr.ReadToEnd()

$outCookie = $xml.aaaLogin.outCookie

To logout with PowerShell, we create the aaaLogout XML with the cookie we just obtained and issue another HTTP Request (code not repeated).

$aaaLogout =”<aaaLogout inCookie=’cookie for session’ />”

And to get the status of the logout.

$outstatus = $xml->aaaLogout->outStatus

There you have it.  PHP and PowerShell example code for logging into and out of Cisco UCS Manager.  You can find the programmer’s guide here:  Cisco UCS Manager XML API Programmer’s Guide.  I would also suggest checking out these Cisco blog posts on the Cisco UCS Manager XML API by John McDonough: UCS XML API “Hello World”, UCS XML API “curl and xml”, and UCS XML API Query Methods.

Advertisements

Written by jguidroz

September 19, 2010 at 2:36 pm

Posted in Scripting, UCS

Automating ESXi 4.1 continuation

with 4 comments

William Lam has posted a great article on tips and tricks of automating ESXi 4.1 here.  Go read his post first.

Seriously, go read his post first.

Ok, you’re back?

I wanted to add to his post with some issues and fixes I’ve run across with moving from ESX to ESXi automation.

With ESX 4.0, at the beginning of the ks.cfg file, you would specify an install line.  Nothing else was needed as the url location of the install bits was passed in the PXE config line.  No more.  For ESX(i) 4.1, you must specify the url for the install location in the ks.cfg file.

Beginning with ESX(i) 4.1, ip append 2 in the PXE config boot line no longer works.  What does this do exactly?  This told the ESX(i) to use the same nic it booted from for downloading the install bits.  If this was not specified, ESX(i) would try to use the first nic it detected, vmnic0.  With ESX(i) 4.1, you must specify ksdevice=vmnic(x) if you are booting and installing from a different nic than vmnic0.  I’m not sure why this behavior changed between 4.0 and 4.1.

William did mention vim-cmd.  In ESX, the command is actually vmware-vim-cmd.  For ESXi, be sure to update these commands to vim-cmd.

For disk setup, I have two lines in my ks.cfg file: clearpart –onfirstdisk –overwritevmfs and autopart –onfirstdisk –overwritevmfs.  I did notice this will create the datastore name on each ESXi host as datastore.  I need to investigate if this can be changed at this part, or add a line in the script to update that name.

In my working with scripting ESXi installations, I’ve found it much easier to have everything run after firstboot then trying to run the configurations before firstboot.

Plenty of advanced configurations (SNMP, Active Directory, adding to vCenter) can be handled through the scripted install, but involve writing a python script to handle.  For some, it will be easier using the supplied commands in the vMA or writing PowerShell scripts.

Outside of these differences, scripted ESXi installs are awesome.

Written by jguidroz

September 11, 2010 at 12:07 pm

Posted in Scripting, VMware

Automatically add ESX(i) to vCenter from ESX(i)

with 3 comments

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.

Written by jguidroz

July 25, 2010 at 3:57 pm

Posted in Scripting, VMware