I was looking for a usable solution how could I script the guest OS inside of the vm in VirtualBox and accidentally I found the automatically installed /usr/lib/virtualbox/vboxshell.py python script, which is also a pretty good Cisco IOS fashioned shell. Its power is the usability and the open API. You can find similar possibility in VBoxManage command, but this is python, and rather a shell.
Let's see an example how good is it.
$ /usr/lib/virtualbox/vboxshell.pyAnd voilà the guest ubuntu just started after listing the virtual machines. Now, from version 3.2 VirtualBox it has a great feature (note, the help command always helps):
Running VirtualBox version 3.2.10
vbox> list
Machine 'OpenSolaris' [e2efac1d-4cd6-40ec-c388-d33fbd3c93b2], machineState=Saved, sessionState=Closed
Machine 'OpenIndiana' [e6434c9f-eef5-43fd-9e63-cac8bf23d1f9], machineState=PoweredOff, sessionState=Closed
Machine 'ubuntu64' [ffdf6bd9-81b5-433b-be0d-b4b342e9fa76], machineState=PoweredOff, sessionState=Closed
vbox> start ubuntu64
vbox> help typeGuestSo let's use it, and type the command of "date" here:
typeGuest: Type arbitrary text in guest: typeGuest Linux "^lls\n&UP;&BKSP;ess /etc/hosts\nq^c" 0.7
vbox> typeGuest ubuntu64 "date\n"And you can check the started VM's screen, it executed the keystrokes. Now it's time to make a screenshot about this output:
vbox> help screenshotand here we go, we got a capture about our guest VM.
screenshot: Take VM screenshot to a file: screenshot Win /tmp/win.png 1024 768
vbox> screenshot ubuntu64 /tmp/bubuntu.png
Saving screenshot (720 x 400) screen 0 in /tmp/bubuntu.png...
vbox>
Now let's play with it, create a snapshot of the guest's state, then change it by a "date" command, try to restore the snapshot of a running machine (you got the error message), turn off (powedown) the vm and restore to the previous snapshot and start the vm:
vbox> snapshot helpNow you can see, you even can reach the shooting starson the sky. :) Why are these good for us? Because it's python, and you can use this shell as a primary, easy-going API, to script the VirtualBox. How? On the host, you will need:
Take snapshot: snapshot vm take name
Restore snapshot: snapshot vm restore name
Merge snapshot: snapshot vm merge name
vbox> snapshot ubuntu64 take 'Snapshot 3' 'blahblah'
vbox> typeGuest ubuntu64 "date\n"
vbox> snapshot ubuntu64 restore 'Snapshot 3'
0x80bb0002 (Cannot delete the current state of the running machine (machine state: Running))
vbox> powerdown ubuntu64
vbox> snapshot ubuntu64 restore 'Snapshot 3'
vbox> start ubuntu64
vbox>
toma@clamshell:~$ mkdir pyboxA few comments, the machine_name is trivial - it's the guest VM's name. The snapshot_name, what we'd like to restore all the time, it's already existing for me in this example. The type how we start the VM, it can be either gui or headless, where the last one can be useful if we'd like to have no graphics output of the running guest. And the last parameter, the delay, is the typing speed. It's pretty low latency. And what is that "|f|o|o"? read as shifted: "FOO". The API is using capitals for special keys such as "SHIFT" so we need to use this kind of escaping.
toma@clamshell:~$ cd pybox
toma@clamshell:~/pybox$ mkdir vboxshell
toma@clamshell:~/pybox$ cp /usr/lib/virtualbox/vboxshell.py vboxshell/__init__.py #making a library from python script
toma@clamshell:~/pybox$ cat - > tst.py
#!/usr/bin/env python
machine_name = 'ubuntu64'
snapshot_name = 'Snapshot 2'
type = 'gui' #'headless' | 'gui'
delay = 0.0001
from vboxshell import * #using our newborn library
from vboxapi import VirtualBoxManager
from time import sleep
style = None
g_virtualBoxManager = VirtualBoxManager(style, None)
ctx = {'global':g_virtualBoxManager,
'mgr':g_virtualBoxManager.mgr,
'vb':g_virtualBoxManager.vbox,
'const':g_virtualBoxManager.constants,
'remote':g_virtualBoxManager.remote,
'type':g_virtualBoxManager.type,
'run': lambda cmd,args: runCommandCb(ctx, cmd, args),
'guestlambda': lambda id,guestLambda,args: runGuestCommandCb(ctx, id, guestLambda, args),
'machById': lambda id: machById(ctx,id),
'argsToMach': lambda args: argsToMach(ctx,args),
'progressBar': lambda p: progressBar(ctx,p),
'typeInGuest': typeInGuest,
'_machlist': None,
'prompt': g_prompt
}
ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
#doing the things with guest vm:
snapshotCmd(ctx, ['snapshot', machine_name, 'restore', snapshot_name])
#if it's already started, let's move on:
try:
startCmd(ctx, ['start', machine_name, type])
except Exception as e:
print e
typeGuestCmd(ctx, ['typeGuest', machine_name, '\n', delay])
typeGuestCmd(ctx, ['typeGuest', machine_name, 'iptables -|p |i|n|p|u|t |a|c|c|e|p|t\n', delay])
typeGuestCmd(ctx, ['typeGuest', machine_name, 'iptables -|p |o|u|t|p|u|t |a|c|c|e|p|t\n', delay])
typeGuestCmd(ctx, ['typeGuest', machine_name, 'iptables -|f\n', delay])
typeGuestCmd(ctx, ['typeGuest', machine_name, 'iptables -|x\n', delay])
sleep(3)
screenshotCmd(ctx, ['screenshot', machine_name, '/tmp/vm.png'])
powerdownCmd(ctx, ['powerdown', machine_name])
toma@clamshell:~/pybox$ chmod 755 tst.py
toma@clamshell:~/pybox$
The g_virtualBoxManager and ctx responsible to get the VirtualBox' context, it's borrowed from the main function of the vboxshell to get the things working.
Now let's run it and see what it does:
$ ./tst.pyIt is its output, which is not much, but in the background it did:
0x80bb0002 (Cannot delete the current state of the running machine (machine state: Running))
0x80bb0007 (A session for the machine 'ubuntu64' is currently open (or being opened or closed))
Saving screenshot (720 x 400) screen 0 in /tmp/vm.png...
- snapshotCmd(ctx, ['snapshot', machine_name, 'restore', snapshot_name]) # restoring the snapshot
- startCmd(ctx, ['start', machine_name, type]) # starting the machine, but if we got exception (that's why we have try/except) if the machine is already running, just go on
- typeGuestCmd(ctx, ['typeGuest', machine_name, '\n', delay]) # press enter
typeGuestCmd(ctx, ['typeGuest', machine_name, 'iptables -|p |i|n|p|u|t |a|c|c|e|p|t\n', delay]) #type "iptables -P INPUT ACCEPT"
[...] - sleep(3) #gues what, 3 secs
- screenshotCmd(ctx, ['screenshot', machine_name, '/tmp/vm.png']) #making a screen capture
- powerdownCmd(ctx, ['powerdown', machine_name]) #turning off the guest vm
Best luck!