A JavaScript library to interact with VirtualBox virtual machines.
- Installation
- Controlling Power and State
- Export a Machine
- Snapshot Manage
- Cloning a VM
- Storage
- Controlling the guest OS
- Meta information about machine
- Putting it all together
- Available Methods
- Troubleshooting
- More Examples
- License (MIT)
- Contributing
Obtain the package
$ npm install virtualbox [--save] [-g]
and then use it
var virtualbox = require('virtualbox');
The general formula for commands is:
virtualbox. API command ( "registered vm name", [parameters], callback );
Available API commands are listed at the end of this document.
node-virtualbox
provides convenience methods to command the guest machine's power state in the customary ways.
Virtual machines will start headless by default, but you can pass a boolean parameter to start them with a GUI:
virtualbox.start("machine_name", true, function start_callback(error) {
if (error) throw error;
console.log("Virtual Machine has started WITH A GUI!");
});
So as not to break pre-0.1.0 implementations, the old method still works (which also defaults to headless):
virtualbox.start("machine_name", function start_callback(error) {
if (error) throw error;
console.log("Virtual Machine has started HEADLESS!");
});
Note: For historical reasons, .stop
is an alias to .savestate
.
virtualbox.stop("machine_name", function stop_callback(error) {
if (error) throw error;
console.log("Virtual Machine has been saved");
});
To halt a machine completely, you can use poweroff
or acpipowerbutton
:
virtualbox.poweroff("machine_name", function poweroff_callback(error) {
if (error) throw error;
console.log("Virtual Machine has been powered off!");
});
virtualbox.acpipowerbutton("machine_name", function acpipower_callback(error) {
if (error) throw error;
console.log("Virtual Machine's ACPI power button was pressed.");
});
Noting the caveat above that .stop
is actually an alias to .savestate
...
virtualbox.pause("machine_name", function pause_callback(error) {
if (error) throw error;
console.log("Virtual Machine is now paused!");
});
virtualbox.savestate("machine_name", function save_callback(error) {
if (error) throw error;
console.log("Virtual Machine is now paused!");
});
And, in the same family, acpisleepbutton
:
virtualbox.acpisleepbutton("machine_name", function acpisleep_callback(error) {
if (error) throw error;
console.log("Virtual Machine's ACPI sleep button signal was sent.");
});
Note that you should probably resume a machine which is in one of the above three states.
virtualbox.resume("machine_name", function resume_callback(error) {
if (error) throw error;
console.log("Virtual Machine is now paused!");
});
And, of course, a reset button method:
virtualbox.reset("machine_name", function reset_callback(error) {
if (error) throw error;
console.log("Virtual Machine's reset button was pressed!");
});
You can export with export
method:
virtualbox.export("machine_name", "output", function export_callback(error) {
if(error) throw error;
console.log("Virtual Machine was exported!");
});
You can show snapshot list with snapshotList
method:
virtualbox.snapshotList("machine_name", function(error, snapshotList, currentSnapshotUUID) {
if(error) throw error;
if(snapshotList) {
console.log(JSON.stringify(snapshotList), JSON.stringify(currentSnapshotUUID));
}
});
And, you can take a snapshot:
virtualbox.snapshotTake("machine_name", "snapshot_name", function(error, uuid) {
if (error) throw error;
console.log('Snapshot has been taken!');
console.log('UUID: ', uuid);
});
Or, delete a snapshot:
virtualbox.snapshotDelete("machine_name", "snapshot_name", function(error) {
if (error) throw error;
console.log('Snapshot has been deleted!');
});
Or, restore a snapshot:
virtualbox.snapshotRestore("machine_name", "snapshot_name", function(error) {
if (error) throw error;
console.log('Snapshot has been restored!');
});
Make a full clone (duplicate virtual hard drive) of a machine:
virtualbox.clone("source_machine_name", "new_machine_name", function(error) {
if (error) throw error;
console.log('Done fully cloning the virtual machine!');
});
Make a linked clone (interdependent-differentially stored virtual hard drive) of a machine:
virtualbox.snapshotTake("machine_name", "snapshot_name", function(error, uuid) {
if (error) throw error;
console.log('Snapshot has been taken!');
console.log('UUID: ', uuid);
virtualbox.clone("machine_name", "new_machine_name", "snapshot_name", function(error) {
if (error) throw error;
console.log('Done making a linked clone of the virtual machine!');
});
});
In case the VM doesn't have an IDE controller you can use the storagectl command to add one:
virtualbox.storage.addCtl({
vm: "machine_name",
perhiperal_name: "IDE", //optional
type: "ide" //optional
}, function(){
console.log('Controller has been added!');
})
Mount an ISO file to the added controller:
virtualbox.storage.attach({
vm: "machine_name",
perhiperal_name: "IDE", //optional
port: "0", //optional
device: "0", //optional
type: "dvddrive", //optional
medium: "X:\Folder\containing\the.iso"
}, function(){
console.log('Image has been mounted!');
})
The medium parameter of the options object can be set to the none value to unmount.
node-virtualbox
is not opinionated: we believe that you know best what you need to do with your virtual machine. Maybe that includes issuing sudo rm -rf /
for some reason.
To that end, the virtualbox
APIs provided by this module take absolutely no steps to prevent you shooting yourself in the foot.
virtualbox
.
For more details and discussion, see issue #29.
This method takes an options object with the name of the virtual machine, the path to the binary to be executed and any parameters to pass:
var options = {
vm: "machine_name",
cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe",
params: "https://google.com"
}
virtualbox.exec(options, function exec_callback(error, stdout) {
if (error) throw error;
console.log('Started Internet Explorer...');
});
Pass username and password information in an options
object:
var options = {
vm: "machine_name",
user:"Administrator",
password: "123456",
cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe",
params: "https://google.com"
};
Tasks can be killed in the guest as well. In Windows guests this calls taskkill.exe /im
and on Linux, BSD and OS X (Darwin) guests, it calls sudo killall
:
virtualbox.kill({
vm: "machine_name",
cmd: "iexplore.exe"
}, function kill_callback(error) {
if (error) throw error;
console.log('Terminated Internet Explorer.');
});
Keyboard scan code sequences can be piped directly to a virtual machine's console:
var SCAN_CODES = virtualbox.SCAN_CODES;
var sequence = [
{ key: 'SHIFT', type: 'make', code: SCAN_CODES['SHIFT']},
{ key: 'A', type: 'make', code: SCAN_CODES['A']},
{ key: 'SHIFT', type: 'break', code: SCAN_CODES.getBreakCode('SHIFT')},
{ key: 'A', type: 'break', code: SCAN_CODES.getBreakCode('A')}
];
virtualbox.keyboardputscancode("machine_name", sequence, function keyscan_callback(err) {
if (error) throw error;
console.log('Sent SHIFT A');
});
List all registered machines, returns an array:
virtualbox.list(function list_callback(machines, error) {
if (error) throw error;
// Act on machines
});
Obtaining a guest property by key name:
var options = {
vm: "machine_name",
key: "/VirtualBox/GuestInfo/Net/0/V4/IP"
}
virtualbox.guestproperty.get(function guestproperty_callback(machines, error) {
if (error) throw error;
// Act on machines
});
Obtaining an extra property by key name:
var options = {
vm: "machine_name",
key: "GUI/Fullscreen"
}
virtualbox.extradata.get(options, function extradataget_callback(error, value) {
if (error) throw error;
console.log('Virtual Machine "%s" extra "%s" value is "%s"', options.vm, options.key, value);
});
Writing an extra property by key name:
var options = {
vm: "machine_name",
key: "GUI/Fullscreen",
value: "true"
}
virtualbox.extradata.set(options, function extradataset_callback(error) {
if (error) throw error;
console.log('Set Virtual Machine "%s" extra "%s" value to "%s"', options.vm, options.key, options.value);
});
var virtualbox = require('virtualbox');
virtualbox.start("machine_name", function start_callback(error) {
if (error) throw error;
console.log('VM "w7" has been successfully started');
virtualbox.exec({
vm: "machine_name",
cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe",
params: "http://google.com"
}, function (error) {
if (error) throw error;
console.log('Running Internet Explorer...');
});
});
virtualbox
.pause({vm:"machine_name"}, callback)
.reset({vm:"machine_name"}, callback)
.resume({vm:"machine_name"}, callback)
.start({vm:"machine_name"}, callback)
and.start({vm:"machine_name"}, true, callback)
.stop({vm:"machine_name"}, callback)
.savestate({vm:"machine_name"}, callback)
.export({vm:"machine_name"}, {output: "output"}, callback)
.poweroff({vm:"machine_name"}, callback)
.acpisleepbutton({vm:"machine_name"}, callback)
.acpipowerbutton({vm:"machine_name"}, callback)
.guestproperty.get({vm:"machine_name", property: "propname"}, callback)
.exec(){vm: "machine_name", cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe", params: "http://google.com"}, callback)
.exec(){vm: "machine_name", user:"Administrator", password: "123456", cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe", params: "http://google.com"}, callback)
.keyboardputscancode("machine_name", [scan_codes], callback)
.kill({vm:"machine_name"}, callback)
.list(callback)
.isRunning({vm:"machine_name"}, callback)
.snapshotList({vm:"machine_name"}, callback)
.snapshotTake({vm:"machine_name"}, {vm:"snapshot_name"}, callback)
.snapshotDelete({vm:"machine_name"}, {vm:"snapshot_UUID"}, callback)
.snapshotRestore({vm:"machine_name"}, {vm:"snapshot_UUID"}, callback)
.clone({vm:"machine_name"}, {vm:"new_machine_name"}, callback)
.clone({vm:"machine_name"}, {vm:"new_machine_name"}, callback)
.storage.addCtl({vm: "machine_name", perhiperal_name: "IDE", type: "ide"}, callback)
.storage.attach({vm: "machine_name", perhiperal_name: "IDE", port: "0", device: "0", type: "dvddrive", medium: "X:\Folder\containing\the.iso"}, callback)
.extradata.get({vm:"machine_name", key:"keyname"}, callback)
.extradata.set({vm:"machine_name", key:"keyname", value:"val"}, callback)
- Make sure that Guest account is enabled on the VM.
- Make sure your linux guest can
sudo
withNOPASSWD
(at least for now). - VMs start headlessly by default: if you're having trouble with executing a command, start the VM with GUI and observe the screen after executing same command.
- To avoid having "Concurrent guest process limit is reached" error message, execute your commands as an administrator.
- Don't forget that this whole thing is asynchronous, and depends on the return of
vboxmanage
not the actual running state/runlevel of services within the guest. See Node-Virtualization#9
Please do!
- File an issue
- Fork and send a pull request.
Please abide by the Contributor Code of Conduct.