Skip to content

Commit 1537052

Browse files
Merge pull request #85 from FlashWebIT/cloning_and_mounting
Cloning VMs and mounting ISO images (fixed)
2 parents a3e0d69 + 90ed314 commit 1537052

File tree

2 files changed

+113
-5
lines changed

2 files changed

+113
-5
lines changed

README.md

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ A JavaScript library to interact with [VirtualBox](https://www.virtualbox.org/)
1414
- [Starting a cold machine: Two ways](#starting-a-cold-machine-two-ways)
1515
- [Stopping a machine](#stopping-a-machine)
1616
- [Pausing, Saving and Resuming a machine](#pausing-saving-and-resuming-a-machine)
17+
- [Export a Machine](#export-a-machine)
18+
- [Snapshot Manage](#snapshot-manage)
19+
- [Cloning a VM](#cloning-vms)
20+
- [Storage](#storage)
21+
- [Manage the IDE controller](#manage-the-ide-controller)
22+
- [Attach a disk image file](#attach-a-disk-image-file)
1723
- [Controlling the guest OS](#controlling-the-guest-os)
1824
- [A note about security :warning:](#a-note-about-security)
1925
- [Running programs in the guest](#running-programs-in-the-guest)
@@ -197,6 +203,66 @@ virtualbox.snapshotRestore("machine_name", "snapshot_name", function(error) {
197203
});
198204
```
199205

206+
## Cloning VMs
207+
208+
Make a full clone (duplicate virtual hard drive) of a machine:
209+
210+
```javascript
211+
virtualbox.clone("source_machine_name", "new_machine_name", function(error) {
212+
if (error) throw error;
213+
console.log('Done fully cloning the virtual machine!');
214+
});
215+
```
216+
217+
Make a linked clone (interdependent-differentially stored virtual hard drive) of a machine:
218+
219+
```javascript
220+
virtualbox.snapshotTake("machine_name", "snapshot_name", function(error, uuid) {
221+
if (error) throw error;
222+
console.log('Snapshot has been taken!');
223+
console.log('UUID: ', uuid);
224+
virtualbox.clone("machine_name", "new_machine_name", "snapshot_name", function(error) {
225+
if (error) throw error;
226+
console.log('Done making a linked clone of the virtual machine!');
227+
});
228+
});
229+
```
230+
231+
## Storage
232+
233+
### Manage the IDE controller
234+
235+
In case the VM doesn't have an IDE controller you can use the storagectl command to add one:
236+
237+
```javascript
238+
virtualbox.storage.addCtl({
239+
vm: "machine_name",
240+
perhiperal_name: "IDE", //optional
241+
type: "ide" //optional
242+
}, function(){
243+
console.log('Controller has been added!');
244+
})
245+
```
246+
247+
### Attach a disk image file
248+
249+
Mount an ISO file to the added controller:
250+
251+
```javascript
252+
virtualbox.storage.attach({
253+
vm: "machine_name",
254+
perhiperal_name: "IDE", //optional
255+
port: "0", //optional
256+
device: "0", //optional
257+
type: "dvddrive", //optional
258+
medium: "X:\Folder\containing\the.iso"
259+
}, function(){
260+
console.log('Image has been mounted!');
261+
})
262+
```
263+
264+
The _medium_ parameter of the options object can be set to the **none** value to unmount.
265+
200266
# Controlling the guest OS
201267

202268
## A note about security :warning:
@@ -292,7 +358,7 @@ var options = {
292358
key: "/VirtualBox/GuestInfo/Net/0/V4/IP"
293359
}
294360

295-
virtualbox.guestproperty(function guestproperty_callback(machines, error) {
361+
virtualbox.guestproperty.get(function guestproperty_callback(machines, error) {
296362
if (error) throw error;
297363
// Act on machines
298364
});
@@ -327,6 +393,8 @@ virtualbox.extradata.set(options, function extradataset_callback(error) {
327393
});
328394
```
329395

396+
_Note: some properties are only available/effective if the Guest OS has the (https://www.virtualbox.org/manual/ch04.html)[Guest Additions] installed and running._
397+
330398
# Putting it all together
331399

332400
```javascript
@@ -366,7 +434,7 @@ virtualbox.start("machine_name", function start_callback(error) {
366434
- `.poweroff({vm:"machine_name"}, callback)`
367435
- `.acpisleepbutton({vm:"machine_name"}, callback)`
368436
- `.acpipowerbutton({vm:"machine_name"}, callback)`
369-
- `.guestproperty({vm:"machine_name", property: "propname"}, callback)`
437+
- `.guestproperty.get({vm:"machine_name", property: "propname"}, callback)`
370438
- `.exec(){vm: "machine_name", cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe", params: "http://google.com"}, callback)`
371439
- `.exec(){vm: "machine_name", user:"Administrator", password: "123456", cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe", params: "http://google.com"}, callback)`
372440
- `.keyboardputscancode("machine_name", [scan_codes], callback)`
@@ -377,6 +445,9 @@ virtualbox.start("machine_name", function start_callback(error) {
377445
- `.snapshotTake({vm:"machine_name"}, {vm:"snapshot_name"}, callback)`
378446
- `.snapshotDelete({vm:"machine_name"}, {vm:"snapshot_UUID"}, callback)`
379447
- `.snapshotRestore({vm:"machine_name"}, {vm:"snapshot_UUID"}, callback)`
448+
- `.clone({vm:"machine_name"}, {vm:"new_machine_name"}, callback)`
449+
- `.storage.addCtl({vm: "machine_name", perhiperal_name: "IDE", type: "ide"}, callback)`
450+
- `.storage.attach({vm: "machine_name", perhiperal_name: "IDE", port: "0", device: "0", type: "dvddrive", medium: "X:\Folder\containing\the.iso"}, callback)`
380451
- `.extradata.get({vm:"machine_name", key:"keyname"}, callback)`
381452
- `.extradata.set({vm:"machine_name", key:"keyname", value:"val"}, callback)`
382453

lib/virtualbox.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const execFile = require('child_process').execFile,
1313

1414
let vBoxManageBinary,
1515
vbox_version;
16-
1716

1817
// Host operating system
1918
if (/^win/.test(host_platform)) {
@@ -34,8 +33,7 @@ if (/^win/.test(host_platform)) {
3433

3534
}
3635

37-
const
38-
allowedBinaries = ["VBoxControl", vBoxManageBinary];
36+
const allowedBinaries = ["VBoxControl", vBoxManageBinary];
3937

4038

4139
execFile(vBoxManageBinary, ["--version"], function(error, stdout, stderr) {
@@ -289,6 +287,43 @@ function snapshotRestore(vmname, uuid, callback) {
289287
vboxmanage(['snapshot', vmname, 'restore', uuid], callback);
290288
}
291289

290+
function clone(vmname, clonevmname, /*optional*/ snapshot, callback) {
291+
logging.info('Cloning machine "%s" to "%s"', vmname, clonevmname);
292+
var cmd = ['clonevm', vmname, '--name', clonevmname, "--register"];
293+
if(typeof snapshot === 'function') {
294+
callback = snapshot;
295+
snapshot = undefined;
296+
}else{
297+
cmd.push("--options");
298+
cmd.push("link");
299+
cmd.push("--snapshot");
300+
cmd.push(snapshot);
301+
}
302+
vboxmanage(cmd, callback);
303+
}
304+
305+
var storage = {
306+
addCtl: function (options, callback){
307+
var vm = options.vm || options.name || options.vmname || options.title,
308+
device_name = options.perhiperal_name || "IDE",
309+
type = options.type || "ide";
310+
logging.info('Adding "%s" controller named "%s" to %s', type, device_name,vm);
311+
var cmd = ['storagectl', vm, '--name', device_name, "--add", type];
312+
vboxmanage(cmd, callback);
313+
},
314+
attach: function (options, callback){
315+
var vm = options.vm || options.name || options.vmname || options.title,
316+
device_name = options.perhiperal_name || "IDE",
317+
port = options.port || "0",
318+
device = options.device || "0",
319+
type = options.type || "dvddrive",
320+
medium = options.medium;
321+
logging.info('Mounting "%s" to controller named "%s" on %s', medium, device_name,vm);
322+
var cmd = ['storageattach', vm, '--storagectl', device_name, "--port", port, "--device", device, "--type", type, "--medium", medium];
323+
vboxmanage(cmd, callback);
324+
}
325+
}
326+
292327
function isRunning(vmname, callback) {
293328
vboxmanage(['list', 'runningvms'], function (error, stdout) {
294329
logging.info('Checking virtual machine "%s" is running or not', vmname);
@@ -509,6 +544,8 @@ module.exports = {
509544
'snapshotRestore': snapshotRestore,
510545
'isRunning': isRunning,
511546
'extradata': extradata,
547+
'clone': clone,
548+
'storage': storage,
512549

513550
'SCAN_CODES': require('./scan-codes')
514551
};

0 commit comments

Comments
 (0)