Today everything is virtual, phones, services and especially computers!
One of the first companies that realized the potential in virtualization is VMware.
Using their easy-to-use yet powerful software, VMware introduced a product called VMware Workstation to the market that changed the SOHO/SMB industry and ESX that changed the enterprise industry, as we know it.
The basic idea behind it was simple: if you need a software product to run on several environments, why not use the same hardware?
While Workstation allows users to virtualize a couple of virtual machines, ESX can manage hundreds if not thousands of virtual machines. Both products are considered the top-of-the-line today, and set the industry standard.
Each product achieves its performance/scalability by different assumptions on different environments/hardware. Because of that, several features exist on Workstation for smaller scale management, but are not included on the ESX product (which sucks by the way).
Since most of my work involves ESX and I LOVE Workstation, I thought why not try to mix the two to fill in the gaps and allow enterprise users to enjoy the full potential of the VMware product line. as expected, VMware was nice enough to provide admins with a nice, easy-to-use command-line interface. All I have to do is fill in the blanks.
Naturally, I chose Python for the task and created a short wrapper to allow fellow Pythoneers (developers in the Python language) to enjoy a simple API using the command line interface via SSH.
1: class ESX_Wrapper(object):2: def __init__(self):3: import paramiko4: from string import strip5: self.ssh = paramiko.SSHClient()6: self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())7:8: def Connect(self, ip, usr, passwd):9: from socket import error10: try:11: print "Establishing SSH connection to the server... ",12: self.ssh.connect(ip, username=usr, password=passwd)13:14: except error:15: print "unreachable!"16: raise SystemExit17:18: except KeyboardInterrupt:19: print "aborted by user!"20:21: else:22: print "done!"23:24: def ListAllVirtualMachines(self):25: stdin, stdout, stderr = self.ssh.exec_command("vim-cmd vmsvc/getallvms")26: vms = stdout.readlines()27: print "\nVirtual Machines\n================\n"28: for i in xrange(len(vms)):29: print vms[i],30:31: def MapVMIDtoNameInDict(self):32: print "\nMapping VMIDs to Names... ",33: stdin, stdout, stderr = self.ssh.exec_command("vim-cmd vmsvc/getallvms")34: vms = stdout.readlines()35: self.dict = {}36: for i in xrange(len(vms)):37: for j in xrange(4):38: if vms[i][j].isdigit() == False:39: if j !=0 and vms[i][j-1].isdigit() == True:40: self.dict.update({int(vms[i][j-1]):self.GetVMName(int(vms[i][j-1]))})41: print "done!"42: return self.dict43:44: def GetVMName(self, vmid):45: command = "vim-cmd vmsvc/get.summary "46: command += str(vmid) + " |grep name |awk -F '\"' \'{print $2}\'"47: stdin, stdout, stderr = self.ssh.exec_command(command)48: return str(stdout.readlines()).strip("[]'\\n")49:50: def GetVMStatus(self, vmid):51: command = "vim-cmd vmsvc/power.getstate " + str(vmid)52: stdin, stdout, stderr = self.ssh.exec_command(command)53: vm_status = stdout.readlines()54: print "\nMachine Status\n=============="55: for i in xrange(len(vm_status)):56: print vm_status[i],57:58: def TurnOffVM(self, vmid):59: command = "vim-cmd vmsvc/power.off " + str(vmid)60: stdin, stdout, stderr = self.ssh.exec_command(command)61: return stdout.readlines()62:63: def ForceVMShutdown(self, vmid):64: command = "vim-cmd vmsvc/shutdown.off " + str(vmid)65: stdin, stdout, stderr = self.ssh.exec_command(command)66: return stdout.readlines()67:68: def TurnOnVM(self, vmid):69: command = "vim-cmd vmsvc/power.on " + str(vmid)70: stdin, stdout, stderr = self.ssh.exec_command(command)71: return stdout.readlines()72:73: def RebootVM(self, vmid):74: command = "vim-cmd vmsvc/power.reboot " + str(vmid)75: stdin, stdout, stderr = self.ssh.exec_command(command)76: return stdout.readlines()77:78: def SuspendVM(self, vmid):79: command = "vim-cmd vmsvc/power.suspend " + str(vmid)80: stdin, stdout, stderr = self.ssh.exec_command(command)81: return stdout.readlines()82:83: def WakeFromSuspend(self, vmid):84: command = "vim-cmd vmsvc/power.on " + str(vmid)85: stdin, stdout, stderr = self.ssh.exec_command(command)86: return stdout.readlines()87:88: def CreateSnapshot(self, vmid, snapshotName, snapshotDesc="", includeMemory=""):89: base_string = str(vmid) + " " + snapshotName90: if snapshotDesc !="":91: base_string = base_string + " " + "\"" + snapshotDesc + "\""92:93: if includeMemory !="":94: base_string = base_string + " " + includeMemory95:96: command = "vim-cmd vmsvc/snapshot.create " + base_string97: stdin, stdout, stderr = self.ssh.exec_command(command)98: return stdout.readlines()99:100: def RevertToSnapshot(self, vmid, testid=1, suppressPowerOff="yes"):101: base_string = str(vmid) + " " + str(testid) + " " + suppressPowerOff102: command = "vim-cmd vmsvc/snapshot.revert " + base_string103: stdin, stdout, stderr = self.ssh.exec_command(command)104: return stdout.readlines()
The constructor uses the paramiko library to connect to the ESX, and send the command-line requests via SSH. The class may look a bit clumsy, but I prefer it this way for readability.
A sample use of this class:
1: def main():2: dict = {}3: esx_object = ESX_Wrapper()4: esx_object.Connect("192.168.2.2","root", "password")5: esx_object.ListAllVirtualMachines()6: dict = esx_object.MapVMIDtoNameInDict()7: machine_vmid = raw_input("Specify the machine vmid you wish to turn on: ")8: machine_name = dict[int(machine_vmid)]9: print "Sending TurnOn command to " + machine_name + "... ",10: esx_object.TurnOnVM(machine_vmid)11: print "sent!"12:13: if __name__ == '__main__':14: main()
Hope you’ll find it useful as I did…
Cheers,
at0m q[^_^]p