Two More Jython Samples Managing VMware vSphere
Yesterday I posted an article introducing the virtual appliance Timo created last week. I am sure some of you have given it a try. I hope you liked it. If you haven’t done so, you can download it from Timo’s post.
The virtual appliance ships with only two samples. Definitely not enough. That is why the community needs to work together so that we can match the functionalities of vSphere PowerCLI.
The following are two samples by David Rousseau who is an independent consultant living in Paris. Thanks for his permission to publish his code here. He owns the copyright of the code. If you want to use it, you can contact him or leave a message in this post.
- jython_rest.py: This code shows how to use the tiny Client REST API I created. Check out this article for more details of the API itself.
- jython_test.py: list all the hosts, resource pools, virtual machines and vApps that are found at the server.
To help you understand the code, I added a little comment before each file.
1. jython_rest.py: This code shows how to use the tiny Client REST API I created. Check out this blog for more details of the API itself.
# pre requisities: xml2dict.py and simplejson lib installed w/ jython
# test variables needed
# please change lines below according to your environment
# get MOB ids using <a href="http://%3cvirtualcenter_ip%3e/mob/">http://<virtualcenter_IP>/mob/</a>
VM_MOB_ID = 'vm-52'
VM_NEW_NAME = 'plop'
DC_MOB_ID = 'datacenter-21'
VIRTUALCENTER = '10.170.232.12'
USERNAME = 'username'
PASSWORD = 'password'
from java.io import StringReader
from java.util import Hashtable
from java.util import Map
from datetime import datetime
from javax.xml.xpath import XPath
from javax.xml.xpath import XPathFactory
from org.xml.sax import InputSource
from com.vmware.vim.rest import CachedManagedObject
from com.vmware.vim.rest import RestClient
from com.vmware.vim.rest import RestManagedObject
def main():
rc = RestClient("<a href="https://%s">https://%s</a>" % VIRTUALCENTER, USERNAME, PASSWORD)
runRestLevel(rc)
runMOLevel(rc)
def runMOLevel(rc):
si = RestManagedObject(rc, "ServiceInstance")
print "name:" + si.getPropertyAsString("content.about.fullName")
print si.invoke("currentTime")
print si.invoke("retrieveContent")
allXml = si.getAllProperties()
print allXml
csi = CachedManagedObject(allXml)
print "name: " + csi.getProperty("content.about.fullName")
searchIndex_id = si.getPropertyAsString("content.searchIndex")
searchIndex = RestManagedObject(rc, searchIndex_id)
print searchIndex.getPropertyAsString("FindByUuid")
print "cap: " + si.getPropertyAsString("capability.multiHostSupported")
print "Server clock: " + csi.getProperty("searchIndex.FindAllByUuid")
vm = RestManagedObject(rc, VM_MOB_ID)
print "reload: " + vm.invoke("reload")
cvm = CachedManagedObject(vm.getAllProperties())
print "Roles: " + cvm.getProperty("effectiveRole")
def runRestLevel(rc):
contentXml = rc.get("moid=ServiceInstance&doPath=content")
print contentXml
print rc.get(None)
# retrieve all VM's properties
vm_properties = rc.get("?moid=%s" % VM_MOB_ID)
print vm_properties
# get a specific property from vm_properties
xpath = XPathFactory.newInstance().newXPath()
# for example retrieve VM name
print xpath.evaluate("//name/text()", InputSource(StringReader(vm_properties)))
# rename a VM
para = Hashtable()
para.put("newName", VM_NEW_NAME)
print rc.post("moid=%s&method=rename" % VM_MOB_ID, para)
# retrieve MksTicket for a given VM
para1 = Hashtable()
mks = rc.post("?moid=%s&method=acquireMksTicket" % VM_MOB_ID, para1)
print "XML output"
print mks
print
# let's transform this xml in something more readable / user friendly
import xml2dict
from xml.etree import ElementTree
root = ElementTree.XML(mks)
myDict = xml2dict.XmlDictConfig(root)
print "python dict output"
print myDict
print
from simplejson import dumps
print "json output"
print dumps(myDict)
if __name__ == '__main__':
main()
2. jython_test.py: list all the hosts, resource pools, virtual machines and vApps that are found at the server.
from com.vmware.vim25 import *
from com.vmware.vim25.mo import *
from com.vmware.vim25.mo.util import *
from java.net import *
from java.util import Hashtable
def mor2mo(si, mor):
"""convert mor to mo
take 2 arguments:
si: ServiceInstance used
mor: managed object reference to convert to managed object
return managed object (mo)
"""
return MorUtil.createExactManagedEntity(si.getServerConnection(), mor)
def displayVM(si, vm):
print " %s %svCPU(s) %sMB %s %s" % (
vm.name,
vm.summary.config.numCpu,
vm.summary.config.memorySizeMB,
vm.runtime.powerState,
vm.guest.toolsStatus,
)
displayNetwork(si, vm)
def displayNetwork(si, vm):
print " %s network(s): %s" % (
len(vm.networks),
", ".join([net.name for net in vm.networks])
)
def main():
si = ServiceInstance(URL("<a href="https://10.170.232.12/sdk">https://10.170.232.12/sdk</a>"), "drousseau", "ecocenter", 1)
rootFolder = si.getRootFolder()
vms = InventoryNavigator(rootFolder).searchManagedEntities("VirtualMachine");
hosts = InventoryNavigator(rootFolder).searchManagedEntities("HostSystem");
pools = InventoryNavigator(rootFolder).searchManagedEntities("ResourcePool")
allVapps = []
if pools:
for pool in pools:
if isinstance(pool, VirtualApp):
allVapps.append(pool)
if allVapps:
print "%s parent vApps found:" % (len(allVapps),)
for vapp in allVapps:
i = 0
print "- %s" % (vapp.name,)
if vapp.VMs:
print " %s VM(s):" % (len(vapp.VMs),)
for vm in vapp.VMs:
i += 1
print " # %s" % (vm.name)
if vapp.resourcePools:
print " this vApp has %s nested vApp(s):" % (len(vapp.resourcePools),)
for nested in vapp.resourcePools:
print " * %s" % (nested.name,)
if nested.VMs:
print " %s VM(s):" % (len(nested.VMs),)
for vm in nested.VMs:
i += 1
print " # %s" % (vm.name)
print " total VM(s): %s" % (i,)
print
if pools:
for curpool in pools:
if isinstance(curpool, VirtualApp):
print "vApp %s" % (curpool.name,)
if curpool.VMs:
for vm in curpool.VMs:
displayVM(si, vm)
host = mor2mo(si, vm.runtime.host)
print " on host %s" % (host.name,)
if curpool.resourcePools:
for nested in curpool.resourcePools:
print " %s" % (nested.name,)
for vm in nested.VMs:
displayVM(si, vm)
# convert mor to mo
host = mor2mo(si, vm.runtime.host)
print " on host %s" % (host.name,)
if vms:
for curvm in vms:
if curvm.runtime.connectionState.toString() == "connected":
host = curvm.runtime.host
print "VM : [%s] | %s | %s | %svCPU(s) | %sMB | %s" % (
curvm.getName(),
curvm.runtime.powerState,
curvm.guest.toolsStatus,
curvm.summary.config.numCpu,
curvm.summary.config.memorySizeMB,
host.val # as an example, use mor2mo in order to retrieve host.name
)
print
if hosts:
for curhost in hosts:
print "Host : %s %s" % (
curhost.name,
curhost.summary
)
print
vms = InventoryNavigator(rootFolder).searchManagedEntities("VirtualMachine")
if vms == None or len(vms) == 0:
return
vm = vms[0]
print "retrieve a property from a single managed object."
status = vm.getPropertyByPath("guest.toolsStatus")
print "toolStatus:" + status.toString()
print "\nretrieve multiple properties from a single managed object."
props = vm.getPropertiesByPaths(["name",
"config.cpuFeatureMask",
"guest.toolsStatus",
"guest.guestId"])
print vm
print props
print "\nretrieve multiple properties from multiple managed objects."
pTables = PropertyCollectorUtil.retrieveProperties(vms, "VirtualMachine",
["name",
"config.cpuFeatureMask",
"guest.toolsStatus",
"guest.guestId"
])
i=0
for vm in vms:
print vm
print pTables[i].toString()
i += 1
si.getServerConnection().logout();
if __name__ == '__main__':
main()
3. xml2dict.py: a utility used by the above two programs
# hacked by David Rousseau to ignore attributes nodes
# based on ElementTree, by default in Jython 2.5rc2
from xml.etree import ElementTree
class XmlListConfig(list):
def __init__(self, aList):
for element in aList:
if element:
# treat like dict
if len(element) == 1 or element[0].tag != element[1].tag:
self.append(XmlDictConfig(element))
# treat like list
elif element[0].tag == element[1].tag:
self.append(XmlListConfig(element))
elif element.text:
text = element.text.strip()
if text:
self.append(text)
class XmlDictConfig(dict):
'''
Example usage:
>>> tree = ElementTree.parse('your_file.xml')
>>> root = tree.getroot()
>>> xmldict = XmlDictConfig(root)
Or, if you want to use an XML string:
>>> root = ElementTree.XML(xml_string)
>>> xmldict = XmlDictConfig(root)
And then use xmldict for what it is... a dict.
'''
def __init__(self, parent_element):
if parent_element.items():
self.update(dict(parent_element.items()))
for element in parent_element:
if element:
# treat like dict - we assume that if the first two tags
# in a series are different, then they are all different.
if len(element) == 1 or element[0].tag != element[1].tag:
aDict = XmlDictConfig(element)
# treat like list - we assume that if the first two tags
# in a series are the same, then the rest are the same.
else:
# here, we put the list in dictionary; the key is the
# tag name the list elements all share in common, and
# the value is the list itself
aDict = {element[0].tag: XmlListConfig(element)}
# if the tag has attributes, add those to the dict
if element.items():
aDict.update(dict(element.items()))
self.update({element.tag: aDict})
# this assumes that if you've got an attribute in a tag,
# you won't be having any text. This may or may not be a
# good idea -- time will tell. It works for the way we are
# currently doing XML configuration files...
# HACK by DR
#elif element.items():
# self.update({element.tag: dict(element.items())})
# finally, if there are no child tags and no attributes, extract
# the text
else:
self.update({element.tag: element.text})
Good article. Very useful. I’m working on a Java project, and would like to have more sample codes.
I tried VMSnapshot.java; but found listSnapshots(vm) doesn’t quite work. The compiler complains about method undefined.
Any idea?
Thanks.
Hi Paul,
Glad you liked it.
Did you use this one: http://vijava.svn.sourceforge.net/viewvc/vijava/trunk/src/com/vmware/vim25/mo/samples/vm/VMSnapshot.java?view=markup?
What method did the compiler complain?
-Steve