Showing posts with label Python-Challenge. Show all posts
Showing posts with label Python-Challenge. Show all posts

Friday, July 20, 2012

Virtual manipulation

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 paramiko
  4:     from string import strip
  5:     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 error
 10:     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 SystemExit
 17: 
 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.dict
 43: 
 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) + " " + snapshotName
 90:     if snapshotDesc !="":
 91:       base_string = base_string + " " + "\"" + snapshotDesc + "\""
 92: 
 93:     if includeMemory !="":
 94:       base_string = base_string + " " + includeMemory
 95: 
 96:     command = "vim-cmd vmsvc/snapshot.create " + base_string
 97:     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) + " " + suppressPowerOff
102:     command = "vim-cmd vmsvc/snapshot.revert " + base_string
103:     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

Sunday, April 22, 2012

Windows Power Options, meet Python

According to Mac users, the world is divided into two main groups: those who use Macs and everyone else.

Not much of a fan of Apple’s products, but even I can’t deny they’re doing a great job with keeping a high uptime laptops using a precise power consumption control. Using power options built into drivers, with an operating system built from ground-up optimized for long use and with breakthrough battery technology, Macs today have the best energy efficient systems out there.

Although Windows lack a high level of power consumption, it offers a good infrastructure for developers.

My initial approach was to allow Windows to recognize some of the uses I make of my computer, and adapt itself accordingly.

There are two ways to accomplish this:

  1. Monitor processes via Windows Task Manager. If a known process was detected, act accordingly and change the power scheme.
  2. Monitor the currently active window by interacting with Windows GUI. If a known process was detected, act accordingly and change the power scheme.

Method 1

Advantages:

  1. See the big picture, If a user minimize the window for several seconds you’ll still be able to determine what’s running in the background.

Disadvantages:

  1. If a user minimize a known process, the code needs to be adjusted to detect the process is not in use.
  2. Additional coding is required to avoid conflicts between processes. If a user minimizes two known processes, the code should adjust itself.
  3. To efficiently scan the process list, the code should either enumerate every process which can take up the very same resources we’re trying to save, or query only for known processes, which can take up some memory maintaining such process list.

Method 2

Advantages:

  1. The code is always relevant to what the user is currently doing
  2. No need to enumerate the entire process list, only fetching the active window from the GUI using Windows API.

Disadvantages:

  1. In case a user minimizes a program, it can greatly affect its performance.
  2. Since the code doesn’t know the user intention, and since the user can minimize a program just for a couple of seconds, it is possible that switching several power schemes in a short time may affect your hardware in the long run.

Combining method 2 with a short grace period between fetching the active window, can eliminate disadvantage #2. Assuming enough power schemes will be created, it is possible to avoid disadvantage #1.

Let’s get busy
  1: #-------------------------------------------------------------------------
  2: # Name:        ActiveWindowSniffer
  3: # Author:      at0m
  4: # Created:     22/04/2012
  5: # Copyright:   (c) at0m 2012
  6: #-------------------------------------------------------------------------
  7: 
  8: #!/usr/bin/env python
  9: 
 10: import win32gui
 11: from time import sleep
 12: from subprocess import call
 13: from re import findall
 14: 
 15: w=win32gui
 16: powerschemes = {"Balanced":"381b4222-f694-41f0-9685-ff5bb260df2e",
 17:                 "Adobe Audition": "7a601a49-8d15-46d2-8160-55163f627070",
 18:                 "Internet":"8b12c7c4-a5e9-4e27-9283-338dc2138c2e",
 19:                 "Internet-Media":"b0e87387-1585-4351-894c-267adb53e563",
 20:                 "High Performance":"8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c",
 21:                 "Power Saver":"a1841308-3541-4fab-bc81-f71556f20b4a",
 22:                 "Balanced_TB_ON":"b18511ef-e34a-4f4b-85e7-2ea5cd1ac989",
 23:                 "Shuteye":"d7925c9e-bfc0-47d7-98c3-028edd2acb81",
 24:                 "Reading":"7c2951ff-7d0e-4609-9f68-d6428869cf5e",
 25:                 "Video Optimized":"e21061ef-9975-4822-9af5-6215c973a982"}
 26: 
 27: while True:
 28:     try:
 29:         sleep(15)
 30:         active_window = w.GetWindowText (w.GetForegroundWindow())
 31:         print_string = str(active_window) + " was detected, adjusting"
 32:         print print_string
 33: 
 34:         if "Mozilla Firefox" in active_window:
 35:             if "YouTube" in active_window or "Facebook" in active_window:
 36:                 call(["POWERCFG","-SETACTIVE",powerschemes["Internet-Media"]])
 37: 
 38:             elif "application/pdf Object" in active_window:
 39:                 call(["POWERCFG","-SETACTIVE",powerschemes["Reading"]])
 40: 
 41:             else:
 42:                 call(["POWERCFG","-SETACTIVE",powerschemes["Internet"]])
 43: 
 44:         elif "Adobe Audition" in active_window or "Saving" in active_window:
 45:             call(["POWERCFG","-SETACTIVE",powerschemes["Adobe Audition"]])
 46: 
 47:         elif "Torrent" in active_window:
 48:             call(["POWERCFG","-SETACTIVE",powerschemes["Shuteye"]])
 49: 
 50:         elif findall("\.(avi|wmv|mp4|mkv|mpg|mpeg)$", active_window) != None:
 51:             call(["POWERCFG", "-SETACTIVE", powerschemes["Video Optimized"]])
 52: 
 53:         else:
 54:             call(["POWERCFG","-SETACTIVE",powerschemes["Power Saver"]])
 55: 
 56:     except KeyboardInterrupt:
 57:         raise SystemExit

At lines 10-13 we’re importing the modules we need, amongst them is win32gui which is the heart of this all program.


At line 15, we’re allocating the Windows GUI to an object.


At line 16, I’ve created a dictionary to allow me to fetch my power schemes quickly. You can see your power schemes by using launching POWERCFG –L from the command line.


At line 29, we’re adding the 15 seconds grace period, you can change it to suit your needs.


Line 30 is the heart of this program, and using the GetForegroundWindow() function, Windows will retrieve the currently active window from Windows GUI API


Line 34-55, if a pattern was detected, activate the power scheme corresponding to the pattern using POWERCFG –SETACTIVE <power_scheme_GUID>


Cheers,


at0m q[^_^]p

Tuesday, April 10, 2012

Playing around with Bluetooth and Python

For those of you who don’t know Python, Python is a relatively new computer language that was quickly adopted by software giants such as Google, Microsoft, Red-Hat. Since Python has a very clear (almost algorithmic) syntax, anyone can learn it quickly, and if you have a little background in computer programing, it’s even easier. Because of those reasons, M.I.T had chosen Python in their introduction to computer programming.

If you’d like to get your hands a bit dirty, IronPython has a great tutorial with some hands on, highly recommended.

Since most of my work around computers involves Python for the past two years or so, I’ve decided to open a new section called the Python Challenge.

This week I was presented with a cool challenge: find a way to make your computer screen lock while you’re away from the computer.

My initial thought, Bluetooth! It has a short range, and Microsoft provides a nice interface to the Bluetooth stack. The only “disadvantage” is that you have to initially pair the device using Windows. This actually works for my advantage since it prevents possible malicious use.

The code below works only for locking the screen while away, and as a security precaution I’ve chosen not to include the section where the computer immediately logs on while you’re close to the computer.

Let’s get busy
  1: #!/usr/bin/env python
  2: 
  3: # Importing modules
  4: from bluetooth import *
  5: import time
  6: import subprocess
  7: 
  8: print "\nPlease wait while discovering devices...\n"
  9: 
 10: # Discovering devices
 11: devices = discover_devices(lookup_names=True)
 12: counter = 0
 13: for i,j in devices:
 14:     counter+=1
 15:     print "%d) %s - %s" % (counter,i,j)
 16: 
 17: device_num = raw_input("\n\nPlease select a device: ")
 18: selected_device =str(devices[int(device_num) - 1][0])
 19: print "Please wait, pairing with %s" % i
 20: 
 21: # Create the client socket
 22: client_socket=BluetoothSocket( RFCOMM )
 23: 
 24: # Attempt to pair
 25: try:
 26:     client_socket.connect((selected_device, 3))
 27: 
 28: except IOError:
 29:     print "Bluetooth error, check your settings"
 30:     raise SystemExit
 31: 
 32: except KeyboardInterrupt:
 33:     raise SystemExit
 34: 
 35: else:
 36:     print "Paired with %s... monitoring" % j
 37:     connected = True
 38:     locked = False
 39: 
 40: # Send Hi every second, and detect when connection is broken
 41: while 1:
 42:     try:
 43:         client_socket.send("Hi")
 44: 
 45:     except IOError:
 46:         if locked !=True:
 47:             locked = True
 48:             connected = False
 49:             subprocess.call("rundll32.exe user32.dll,LockWorkStation")
 50: 
 51:         if connected == False:
 52:             try:
 53:                 client_socket=BluetoothSocket( RFCOMM )
 54:                 client_socket.connect((selected_device, 3))
 55: 
 56:             except IOError:
 57:                 continue
 58: 
 59:             else:
 60:                 connected = True
 61: 
 62:     except KeyboardInterrupt:
 63:         client_socket.close()
 64: 
 65:     else:
 66:         locked = False
 67:         time.sleep(1)

Cheers,


at0m q[^_^]p