Search This Blog

Wednesday, November 8, 2017

VMware keystroke based automation (The Pythonic Way)




Hi all,

This is based on my another day at work.

I was stuck with an issue "Press any key to boot from CDrom" while automating the unattend windows installation using autounattend.xml

Ofcourse i could have cracked the ISO to fix this up but my company would n't agree to it :)
This really blew me down until i found the following link (URL)

https://www.virtuallyghetto.com/2017/09/automating-vm-keystrokes-using-the-vsphere-api-powercli.html

https://github.com/lamw/vghetto-scripts/blob/master/powershell/VMKeystrokes.ps1

By referring that, i was able to write my own python based implementation of the same (Only takes return"Enter" keystroke as this is my need)
The code snippet is pasted below, feel free to reuse them (pressEnter.py)

import atexit
import argparse
import getpass
import sys
import textwrap
import time

from pyVim import connect
from pyVmomi import vim


def get_args():
    parser = argparse.ArgumentParser()

    # because -h is reserved for 'help' we use -s for service
    parser.add_argument('-s', '--host',
                        required=True,
                        action='store',
                        help='vSphere service to connect to')

    # because we want -p for password, we use -o for port
    parser.add_argument('-o', '--port',
                        type=int,
                        default=443,
                        action='store',
                        help='Port to connect on')

    parser.add_argument('-u', '--user',
                        required=True,
                        action='store',
                        help='User name to use when connecting to host')

    parser.add_argument('-p', '--password',
                        required=False,
                        action='store',
                        help='Password to use when connecting to host')
    parser.add_argument('-n', '--name',
                        required=True,
                        action='store',
                        help='Name of the virtual_machine to look for.')

    args = parser.parse_args()

    if not args.password:
        args.password = getpass.getpass(
            prompt='Enter password for host %s and user %s: ' %
                   (args.host, args.user))

    return args

args = get_args()
si = connect.SmartConnectNoSSL(host=args.host, user=args.user,
                            pwd=args.password, port=args.port)

# doing this means you don't need to remember to
# disconnect your script/objects
atexit.register(connect.Disconnect, si)

# search the whole inventory tree recursively... a brutish but
# effective tactic
vm = None
entity_stack = si.content.rootFolder.childEntity
while entity_stack:
    entity = entity_stack.pop()

    if entity.name == args.name:
        vm = entity
        del entity_stack[0:len(entity_stack)]
    elif hasattr(entity, 'childEntity'):
        entity_stack.extend(entity.childEntity)
    elif isinstance(entity, vim.Datacenter):
        entity_stack.append(entity.vmFolder)

if not isinstance(vm, vim.VirtualMachine):
    print "virtual machine %s not found" % args.name
    sys.exit(-1)

print "Found VirtualMachine: %s Name: %s" % (vm, vm.name)

tmp=vim.UsbScanCodeSpecKeyEvent()
h="0x28"
hidCodeHexToInt = int(h, 16)
hidCodeValue = (hidCodeHexToInt << 16) | 0007
tmp.usbHidCode = hidCodeValue
sp = vim.UsbScanCodeSpec()
sp.keyEvents = [tmp]
r = vm.PutUsbScanCodes(sp)
print r

Here is how you run it.

python pressEnter.py -s <vmware host> -u <user> -p <password> -n <target vm> -o 443

and ofcourse you need pyVmomi library pre-installed :) :P

1 comment:

  1. | 0007 is no longer valid in python3
    Use:
    0o007 if you intend to use octal. Otherwise 0x007 or just 7 should work as well.

    ReplyDelete