Socket
Socket
Sign inDemoInstall

virtualbox

Package Overview
Dependencies
13
Maintainers
2
Versions
15
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.2 to 1.1.0

test/helpers/logger.js

1070

lib/virtualbox.js

@@ -1,438 +0,587 @@

"use strict";
'use strict';
// @todo use a promise library instead of so many callbacks
const execFile = require('child_process').execFile,
log4js = require('log4js'),
host_platform = process.platform,
logging = require('./logging'),
known_OS_types = {
known_OS_types = {
WINDOWS: 'windows',
MAC: 'mac',
LINUX: 'linux'
};
LINUX: 'linux',
},
defaultExecutor = (bin, cmd) => {
return new Promise((resolve, reject) => {
if (!allowedBinaries.includes(bin)) {
reject(new Error('Not an allowed binary'));
} else {
execFile(bin, cmd, function (err, stdout, stderr) {
if (
!err &&
stderr &&
cmd.indexOf('pause') !== -1 &&
cmd.indexOf('savestate') !== -1
) {
reject(new Error(stderr));
}
let vBoxManageBinary,
vbox_version;
resolve({ err, stdout, stderr });
});
}
});
},
defaultLoggingConfig = {
appenders: {
out: {
type: 'stdout',
layout: {
type: 'pattern',
pattern: '%[[%d{yyyy-MM-dd hh:mm:ss.SSS}] [%p] %c - %]%m',
},
},
},
categories: { default: { appenders: ['out'], level: 'info' } },
},
defaultLoggerFn = () => {
log4js.configure(defaultLoggingConfig);
return log4js.getLogger('VirtualBox');
},
defaultLogger = defaultLoggerFn(),
defaultvboxmanage = function (cmd, callback) {
try {
this._executor(this._vBoxManageBinary, cmd)
.then(({ err, stdout, stderr }) => callback(err, stdout, stderr))
.catch(defaultErrorHandler);
} catch (err) {
this._logging.error(err);
}
},
defaultErrorHandler = (err) => {
console.error(err);
},
allowedBinaries = ['VBoxControl'];
// Host operating system
if (/^win/.test(host_platform)) {
class Virtualbox {
constructor(logging = defaultLogger, executor = defaultExecutor) {
this._logging = logging;
this._executor = executor;
this._setVboxManageBinary();
allowedBinaries.push(this._vBoxManageBinary);
this._logging.debug(allowedBinaries);
this._detectVboxVersion();
this.storage = new VboxStorage(
this._logging,
this._executor,
this._vBoxManageBinary
);
this.guestproperty = new VboxGuestProperty(
this._logging,
this._executor,
this._vBoxManageBinary
);
this.extradata = new VboxExtraData(
this._logging,
this._executor,
this._vBoxManageBinary
);
this.vboxmanage = defaultvboxmanage;
this.SCAN_CODES = require('./scan-codes');
}
// Path may not contain VBoxManage.exe but it provides this environment variable
var vBoxInstallPath = process.env.VBOX_INSTALL_PATH || process.env.VBOX_MSI_INSTALL_PATH;
vBoxManageBinary = '"' + vBoxInstallPath + '\\VBoxManage.exe' + '" ';
static create(logging, executor) {
const logger = !!logging ? logging : defaultLogger;
return new Virtualbox(logger, executor);
}
} else if (/^darwin/.test(host_platform) || /^linux/.test(host_platform)) {
pause(vmname, callback) {
this._logging.info('Pausing VM "%s"', vmname);
this.vboxmanage(['controlvm', vmname, 'pause'], function (error, _) {
callback(error);
});
}
// Mac OS X and most Linux use the same binary name, in the path
vBoxManageBinary = 'vboxmanage ';
list(callback) {
const parse_listdata = (raw_data) => {
var _raw = raw_data.split(/\r?\n/g);
var _data = {};
if (_raw.length > 0) {
for (var _i = 0; _i < _raw.length; _i += 1) {
var _line = _raw[_i];
if (_line === '') {
continue;
}
// "centos6" {64ec13bb-5889-4352-aee9-0f1c2a17923d}
var rePattern = /^"(.+)" \{(.+)\}$/;
var arrMatches = _line.match(rePattern);
// {'64ec13bb-5889-4352-aee9-0f1c2a17923d': 'centos6'}
if (arrMatches && arrMatches.length === 3) {
_data[arrMatches[2].toString()] = {
name: arrMatches[1].toString(),
};
}
}
}
return _data;
};
} else {
this._logging.info('Listing VMs');
this.vboxmanage(['list', 'runningvms'], (_, stdout) => {
var _runningvms = parse_listdata(stdout);
this.vboxmanage(['list', 'vms'], function (error, fullStdout) {
var _all = parse_listdata(fullStdout);
var _keys = Object.keys(_all);
for (var _i = 0; _i < _keys.length; _i += 1) {
var _key = _keys[_i];
if (_runningvms[_key]) {
_all[_key].running = true;
} else {
_all[_key].running = false;
}
}
callback(_all, error);
});
});
}
// Otherwise (e.g., SunOS) hope it's in the path
vBoxManageBinary = 'vboxmanage ';
reset(vmname, callback) {
this._logging.info('Resetting VM "%s"', vmname);
this.vboxmanage(['controlvm', vmname, 'reset'], function (error, _) {
callback(error);
});
}
}
const allowedBinaries = ["VBoxControl", vBoxManageBinary];
execFile(vBoxManageBinary, ["--version"], function(error, stdout, stderr) {
// e.g., "4.3.38r106717" or "5.0.20r106931"
vbox_version = stdout.split(".")[0];
logging.info("Virtualbox version detected as %s", vbox_version);
});
function command(bin, cmd, callback) {
if(!allowedBinaries.includes(bin)) {
throw new Error("Not an allowed binary");
resume(vmname, callback) {
this._logging.info('Resuming VM "%s"', vmname);
this.vboxmanage(['controlvm', vmname, 'resume'], function (error, _) {
callback(error);
});
}
execFile(bin, cmd, function(err, stdout, stderr) {
if (!err && stderr && cmd.indexOf("pause") !== -1 && cmd.indexOf("savestate") !== -1) {
err = new Error(stderr);
start(vmname, useGui, callback) {
if (typeof useGui === 'function') {
callback = useGui;
useGui = false;
}
var vmType = useGui ? 'gui' : 'headless';
callback(err, stdout);
});
}
this._logging.info('Starting VM "%s" with options: ', vmname, vmType);
function vboxcontrol(cmd, callback) {
command("VBoxControl", cmd, callback);
}
function vboxmanage(cmd, callback) {
command(vBoxManageBinary, cmd, callback);
}
function pause(vmname, callback) {
logging.info('Pausing VM "%s"', vmname);
vboxmanage(["controlvm", vmname, "pause"], function(error, stdout) {
callback(error);
});
}
function list(callback) {
logging.info('Listing VMs');
vboxmanage(['list', 'runningvms'], function(error, stdout) {
var _list = {};
var _runningvms = parse_listdata(stdout);
vboxmanage(["list", "vms"], function(error, fullStdout) {
var _all = parse_listdata(fullStdout);
var _keys = Object.keys(_all);
for (var _i = 0; _i < _keys.length; _i += 1) {
var _key = _keys[_i];
if (_runningvms[_key]) {
_all[_key].running = true;
} else {
_all[_key].running = false;
}
this.vboxmanage(['-nologo', 'startvm', vmname, '--type', vmType], function (
error,
_
) {
if (error && /VBOX_E_INVALID_OBJECT_STATE/.test(error.message)) {
error = undefined;
}
callback(_all, error);
callback(error);
});
});
}
}
function parse_listdata(raw_data) {
var _raw = raw_data.split(/\r?\n/g);
var _data = {};
if (_raw.length > 0) {
for (var _i = 0; _i < _raw.length; _i += 1) {
var _line = _raw[_i];
if (_line === '') {
continue;
}
// "centos6" {64ec13bb-5889-4352-aee9-0f1c2a17923d}
var rePattern = /^"(.+)" \{(.+)\}$/;
var arrMatches = _line.match(rePattern);
// {'64ec13bb-5889-4352-aee9-0f1c2a17923d': 'centos6'}
if (arrMatches && arrMatches.length === 3) {
_data[arrMatches[2].toString()] = {
name: arrMatches[1].toString()
};
}
}
stop(vmname, callback) {
this._logging.info('Stopping VM "%s"', vmname);
this.vboxmanage(['controlvm', vmname, 'savestate'], function (error, _) {
callback(error);
});
}
return _data;
}
function reset(vmname, callback) {
logging.info('Resetting VM "%s"', vmname);
vboxmanage(["controlvm", vmname, "reset"], function(error, stdout) {
callback(error);
});
}
savestate(vmname, callback) {
this._logging.info('Saving State (alias to stop) VM "%s"', vmname);
this.stop(vmname, callback);
}
function resume(vmname, callback) {
logging.info('Resuming VM "%s"', vmname);
vboxmanage(["controlvm", vmname, "resume"], function(error, stdout) {
callback(error);
});
}
vmExport(vmname, output, callback) {
this._logging.info('Exporting VM "%s"', vmname);
this.vboxmanage(['export', vmname, '--output', output], function (
error,
_
) {
callback(error);
});
}
function start(vmname, useGui, callback) {
if ((typeof useGui) === 'function') {
callback = useGui;
useGui = false;
poweroff(vmname, callback) {
this._logging.info('Powering off VM "%s"', vmname);
this.vboxmanage(['controlvm', vmname, 'poweroff'], function (error, _) {
callback(error);
});
}
var vmType = (useGui ? "gui" : "headless");
logging.info('Starting VM "%s" with options: ', vmname, vmType);
acpipowerbutton(vmname, callback) {
this._logging.info('ACPI power button VM "%s"', vmname);
this.vboxmanage(['controlvm', vmname, 'acpipowerbutton'], function (error) {
callback(error);
});
}
vboxmanage(["-nologo", "startvm", vmname, "--type", vmType], function(error, stdout) {
if (error && /VBOX_E_INVALID_OBJECT_STATE/.test(error.message)) {
error = undefined;
}
callback(error);
});
}
acpisleepbutton(vmname, callback) {
this._logging.info('ACPI sleep button VM "%s"', vmname);
this.vboxmanage(['controlvm', vmname, 'acpisleepbutton'], function (
error,
_
) {
callback(error);
});
}
function stop(vmname, callback) {
logging.info('Stopping VM "%s"', vmname);
vboxmanage(["controlvm", vmname, "savestate"], function(error, stdout) {
callback(error);
});
}
modify(vname, properties, callback) {
this._logging.info('Modifying VM %s', vname);
var args = [vname];
function savestate(vmname, callback) {
logging.info('Saving State (alias to stop) VM "%s"', vmname);
stop(vmname, callback);
}
for (var property in properties) {
if (properties.hasOwnProperty(property)) {
var value = properties[property];
args.push('--' + property);
function vmExport(vmname, output, callback) {
logging.info('Exporting VM "%s"', vmname);
vboxmanage(['export', vmname, '--output', output], function(error, stdout) {
callback(error);
});
}
if (Array.isArray(value)) {
Array.prototype.push.apply(args, value);
} else {
args.push(value.toString());
}
}
}
function poweroff(vmname, callback) {
logging.info('Powering off VM "%s"', vmname);
vboxmanage(['controlvm', vmname, 'poweroff'], function(error, stdout) {
callback(error);
});
}
this.vboxmanage(['modifyvm', ...args], function (error, _) {
callback(error);
});
}
function acpipowerbutton(vmname, callback) {
logging.info('ACPI power button VM "%s"', vmname);
vboxmanage(['controlvm', vmname, 'acpipowerbutton'], function(error, stdout) {
callback(error);
});
}
snapshotList(vmname, callback) {
this._logging.info('Listing snapshots for VM "%s"', vmname);
this.vboxmanage(
['snapshot', vmname, 'list', '--machinereadable'],
function (error, stdout) {
if (error) {
callback(error);
return;
}
function acpisleepbutton(vmname, callback) {
logging.info('ACPI sleep button VM "%s"', vmname);
vboxmanage(['controlvm', vmname, 'acpisleepbutton'], function(error, stdout) {
callback(error);
});
}
var s;
var snapshots = [];
var currentSnapshot;
var lines = (stdout || '').split(require('os').EOL);
function modify(vname, properties, callback) {
logging.info('Modifying VM %s', vname);
var args = [vname];
lines.forEach(function (line) {
line
.trim()
.replace(
/^(CurrentSnapshotUUID|SnapshotName|SnapshotUUID).*\="(.*)"$/,
function (l, k, v) {
if (k === 'CurrentSnapshotUUID') {
currentSnapshot = v;
} else if (k === 'SnapshotName') {
s = {
name: v,
};
snapshots.push(s);
} else {
s.uuid = v;
}
}
);
});
for (var property in properties) {
if (properties.hasOwnProperty(property)) {
var value = properties[property];
args.push('--' + property);
if (Array.isArray(value)) {
Array.prototype.push.apply(args, value);
callback(null, snapshots, currentSnapshot);
}
else {
args.push(value.toString());
}
}
);
}
vboxmanage(['modifyvm', ...args], function (error, stdout) {
callback(error);
});
}
snapshotTake(
vmname,
name,
/*optional*/ description,
/*optional*/ live,
callback
) {
this._logging.info('Taking snapshot for VM "%s"', vmname);
function snapshotList(vmname, callback) {
logging.info('Listing snapshots for VM "%s"', vmname);
vboxmanage(['snapshot', vmname, 'list', '--machinereadable'], function(error, stdout) {
if (typeof description === 'function') {
callback = description;
description = undefined;
} else if (typeof live === 'function') {
callback = live;
live = false;
}
if (error) {
callback(error);
return;
var cmd = ['snapshot', vmname, 'take', name];
if (description) {
cmd.push('--description');
cmd.push(description);
}
var s;
var snapshots = [];
var currentSnapshot;
var lines = (stdout || '').split(require('os').EOL);
if (live === true) {
cmd.push('--live');
}
lines.forEach(function(line) {
line.trim().replace(/^(CurrentSnapshotUUID|SnapshotName|SnapshotUUID).*\="(.*)"$/, function(l, k, v) {
if (k === 'CurrentSnapshotUUID') {
currentSnapshot = v;
}
else if (k === 'SnapshotName') {
s = {
'name': v
};
snapshots.push(s);
}
else {
s.uuid = v;
}
this.vboxmanage(cmd, function (error, stdout) {
var uuid;
stdout.trim().replace(/UUID\: ([a-f0-9\-]+)$/, function (l, u) {
uuid = u;
});
callback(error, uuid);
});
}
callback(null, snapshots, currentSnapshot);
});
}
function snapshotTake(vmname, name, /*optional*/ description, /*optional*/ live, callback) {
logging.info('Taking snapshot for VM "%s"', vmname);
if(typeof description === 'function') {
callback = description;
description = undefined;
snapshotDelete(vmname, uuid, callback) {
this._logging.info('Deleting snapshot "%s" for VM "%s"', uuid, vmname);
this.vboxmanage(['snapshot', vmname, 'delete', uuid], callback);
}
else if(typeof live === 'function') {
callback = live;
live = false;
}
var cmd = ['snapshot', vmname, 'take', name];
if(description) {
cmd.push('--description');
cmd.push(description);
snapshotRestore(vmname, uuid, callback) {
this._logging.info('Restoring snapshot "%s" for VM "%s"', uuid, vmname);
this.vboxmanage(['snapshot', vmname, 'restore', uuid], callback);
}
if(live === true) {
cmd.push('--live');
clone(vmname, clonevmname, /*optional*/ snapshot, callback) {
this._logging.info('Cloning machine "%s" to "%s"', vmname, clonevmname);
var cmd = ['clonevm', vmname, '--name', clonevmname, '--register'];
if (typeof snapshot === 'function') {
callback = snapshot;
snapshot = undefined;
} else {
cmd.push('--options');
cmd.push('link');
cmd.push('--snapshot');
cmd.push(snapshot);
}
this.vboxmanage(cmd, callback);
}
vboxmanage(cmd, function(error, stdout) {
var uuid;
stdout.trim().replace(/UUID\: ([a-f0-9\-]+)$/, function(l, u) {
uuid = u;
isRunning(vmname, callback) {
this.vboxmanage(['list', 'runningvms'], (error, stdout) => {
this._logging.info(
'Checking virtual machine "%s" is running or not',
vmname
);
if (stdout.indexOf(vmname) === -1) {
callback(error, false);
} else {
callback(error, true);
}
});
callback(error, uuid);
});
}
}
function snapshotDelete(vmname, uuid, callback) {
logging.info('Deleting snapshot "%s" for VM "%s"', uuid, vmname);
vboxmanage(['snapshot', vmname, 'delete', uuid], callback);
}
keyboardputscancode(vmname, codes, callback) {
var codeStr = codes
.map(function (code) {
var s = code.toString(16);
function snapshotRestore(vmname, uuid, callback) {
logging.info('Restoring snapshot "%s" for VM "%s"', uuid, vmname);
vboxmanage(['snapshot', vmname, 'restore', uuid], callback);
}
function clone(vmname, clonevmname, /*optional*/ snapshot, callback) {
logging.info('Cloning machine "%s" to "%s"', vmname, clonevmname);
var cmd = ['clonevm', vmname, '--name', clonevmname, "--register"];
if(typeof snapshot === 'function') {
callback = snapshot;
snapshot = undefined;
}else{
cmd.push("--options");
cmd.push("link");
cmd.push("--snapshot");
cmd.push(snapshot);
if (s.length === 1) {
s = '0' + s;
}
return s;
})
.join(' ');
this._logging.info(
'Sending VM "%s" keyboard scan codes "%s"',
vmname,
codeStr
);
this.vboxmanage(
['controlvm', vmname, 'keyboardputscancode', codeStr],
function (error, stdout) {
callback(error, stdout);
}
);
}
vboxmanage(cmd, callback);
}
var storage = {
addCtl: function (options, callback) {
exec(options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,
device_name = options.perhiperal_name || "IDE",
type = options.type || "ide";
logging.info('Adding "%s" controller named "%s" to %s', type, device_name, vm);
var cmd = ['storagectl', vm, '--name', device_name, "--add", type];
vboxmanage(cmd, callback);
},
attach: function (options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,
device_name = options.perhiperal_name || "IDE",
port = options.port || "0",
device = options.device || "0",
type = options.type || "dvddrive",
medium = options.medium;
logging.info('Mounting "%s" to controller named "%s" on %s', medium, device_name, vm);
var cmd = ['storageattach', vm, '--storagectl', device_name, "--port", port, "--device", device, "--type", type, "--medium", medium];
vboxmanage(cmd, callback);
}
};
username = options.user || options.username || 'Guest',
password = options.pass || options.passwd || options.password,
path =
options.path ||
options.cmd ||
options.command ||
options.exec ||
options.execute ||
options.run,
cmd,
params = options.params || options.parameters || options.args;
function isRunning(vmname, callback) {
vboxmanage(['list', 'runningvms'], function (error, stdout) {
logging.info('Checking virtual machine "%s" is running or not', vmname);
if (stdout.indexOf(vmname) === -1) {
callback(error, false);
} else {
callback(error, true);
if (Array.isArray(params)) {
params = params.join(' ');
}
});
}
function keyboardputscancode(vmname, codes, callback) {
var codeStr = codes.map(function(code) {
var s = code.toString(16);
if (s.length === 1) {
s = '0' + s;
if (params === undefined) {
params = '';
}
return s;
}).join(' ');
logging.info('Sending VM "%s" keyboard scan codes "%s"', vmname, codeStr);
vboxmanage(['controlvm', vmname, 'keyboardputscancode', codeStr], function(error, stdout) {
callback(error, stdout);
});
}
function vmExec(options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,
username = options.user || options.username || 'Guest',
password = options.pass || options.passwd || options.password,
path = options.path || options.cmd || options.command || options.exec || options.execute || options.run,
cmd,
params = options.params || options.parameters || options.args;
const getOSTypeCb = (os_type) => {
var cmd = ['guestcontrol', vm];
var runcmd = this._vboxVersion > 5 ? ['run'] : ['execute', '--image'];
cmd = [...cmd, ...runcmd];
switch (os_type) {
case known_OS_types.WINDOWS:
path = path.replace(/\\/g, '\\\\');
cmd.push('cmd.exe', '--username', username);
break;
case known_OS_types.MAC:
cmd.push('/usr/bin/open', '-a', '--username', username);
break;
case known_OS_types.LINUX:
cmd.push('/bin/sh', '--username', username);
break;
default:
break;
}
if (Array.isArray(params)) {
params = params.join(" ");
}
if (password) {
cmd.push('--password', password);
}
cmd.push('--', '/c', path, params);
if (params === undefined) {
params = "";
this._logging.info(
'Executing command "vboxmanage %s" on VM "%s" detected OS type "%s"',
cmd,
vm,
os_type
);
this.vboxmanage(cmd, function (error, stdout) {
callback(error, stdout);
});
};
this.guestproperty.os(vm, getOSTypeCb);
}
guestproperty.os(vm, getOSTypeCb);
kill(options, callback) {
options = options || {};
var vm = options.vm || options.name || options.vmname || options.title,
path =
options.path ||
options.cmd ||
options.command ||
options.exec ||
options.execute ||
options.run,
image_name = options.image_name || path;
function getOSTypeCb(os_type) {
var cmd = ['guestcontrol', vm];
var runcmd = vbox_version === 5 ? ['run'] : ['execute', '--image'];
cmd.push(runcmd);
switch (os_type) {
case known_OS_types.WINDOWS:
path = path.replace(/\\/g, '\\\\');
cmd.push('cmd.exe', '--username', username);
break;
case known_OS_types.MAC:
cmd.push('/usr/bin/open', '-a', '--username', username);
break;
case known_OS_types.LINUX:
cmd.push('/bin/sh', '--username', username);
break;
default:
break;
}
this.guestproperty.os(vm, (os_type) => {
switch (os_type) {
case known_OS_types.WINDOWS:
this._executor(
{
vm: vm,
user: options.user,
password: options.password,
path: 'C:\\Windows\\System32\\taskkill.exe /im ',
params: image_name,
},
callback
);
break;
case known_OS_types.MAC:
case known_OS_types.LINUX:
this._executor(
{
vm: vm,
user: options.user,
password: options.password,
path: 'sudo killall ',
params: image_name,
},
callback
);
break;
}
});
}
if (password) {
cmd.push('--password', password);
_setVboxManageBinary() {
this._logging.info(host_platform);
if (/^win/.test(host_platform)) {
// Path may not contain VBoxManage.exe but it provides this environment variable
var vBoxInstallPath =
process.env.VBOX_INSTALL_PATH || process.env.VBOX_MSI_INSTALL_PATH;
this._vBoxManageBinary =
'"' + vBoxInstallPath + '\\VBoxManage.exe' + '" ';
} else if (/^darwin/.test(host_platform) || /^linux/.test(host_platform)) {
// Mac OS X and most Linux use the same binary name, in the path
this._vBoxManageBinary = 'vboxmanage';
} else {
// Otherwise (e.g., SunOS) hope it's in the path
this._vBoxManageBinary = 'vboxmanage';
}
cmd.push('--', '/c', path, params);
}
logging.info('Executing command "vboxmanage %s" on VM "%s" detected OS type "%s"', cmd, vm, os_type);
vboxmanage(cmd, function(error, stdout) {
callback(error, stdout);
});
_detectVboxVersion() {
this._executor(this._vBoxManageBinary, ['--version']).then(
({ error, stdout }) => {
if (error) {
throw error;
} else {
this._vboxVersion = stdout.split('.')[0];
this._logging.info(
'Virtualbox version detected as %s',
this._vboxVersion
);
}
}
);
}
}
function vmKill(options, callback) {
options = options || {};
var vm = options.vm || options.name || options.vmname || options.title,
path = options.path || options.cmd || options.command || options.exec || options.execute || options.run,
image_name = options.image_name || path;
class VboxStorage {
constructor(logging, executor, vBoxManageBinary) {
this._logging = logging;
this._executor = executor;
this._vBoxManageBinary = vBoxManageBinary;
this.vboxmanage = defaultvboxmanage;
}
guestproperty.os(vm, function(os_type) {
switch (os_type) {
case known_OS_types.WINDOWS:
vmExec({
vm: vm,
user: options.user,
password: options.password,
path: 'C:\\Windows\\System32\\taskkill.exe /im ',
params: image_name
}, callback);
break;
case known_OS_types.MAC:
case known_OS_types.LINUX:
vmExec({
vm: vm,
user: options.user,
password: options.password,
path: 'sudo killall ',
params: image_name
}, callback);
break;
}
});
addCtl(options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,
device_name = options.perhiperal_name || 'IDE',
type = options.type || 'ide';
this._logging.info(
'Adding "%s" controller named "%s" to %s',
type,
device_name,
vm
);
var cmd = ['storagectl', vm, '--name', device_name, '--add', type];
this.vboxmanage(cmd, callback);
}
attach(options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,
device_name = options.perhiperal_name || 'IDE',
port = options.port || '0',
device = options.device || '0',
type = options.type || 'dvddrive',
medium = options.medium;
this._logging.info(
'Mounting "%s" to controller named "%s" on %s',
medium,
device_name,
vm
);
var cmd = [
'storageattach',
vm,
'--storagectl',
device_name,
'--port',
port,
'--device',
device,
'--type',
type,
'--medium',
medium,
];
this.vboxmanage(cmd, callback);
}
}
var guestproperty = {
get: function(options, callback) {
class VboxGuestProperty {
constructor(logging, executor, vBoxManageBinary) {
this._logging = logging;
this._executor = executor;
this._vBoxManageBinary = vBoxManageBinary;
this.os_type = null;
this.vboxmanage = defaultvboxmanage;
}
get(options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,

@@ -442,6 +591,7 @@ key = options.key,

guestproperty.os(vm, getOSTypeCallback);
function getOSTypeCallback(os_type) {
vboxmanage(['guestproperty', 'get', vm, key], function(error, stdout) {
this.os(vm, (os_type) => {
this.vboxmanage(['guestproperty', 'get', vm, key], function (
error,
stdout
) {
if (error) {

@@ -456,42 +606,104 @@ throw error;

});
});
}
os(vmname, callback) {
if (this.os_type) {
return callback(this.os_type);
}
},
try {
this.vboxmanage(
['showvminfo', '--machinereadable', vmname],
(error, stdout, _) => {
if (error) {
throw error;
}
os_type: null, // cached
// The ostype is matched against the ID attribute of 'vboxmanage list ostypes'
if (stdout.indexOf('ostype="Windows') !== -1) {
this.os_type = known_OS_types.WINDOWS;
} else if (
['ostype="MacOS', 'ostype="Mac OS machine'].includes(stdout)
) {
this.os_type = known_OS_types.MAC;
} else {
this.os_type = known_OS_types.LINUX;
}
this._logging.debug('Detected guest OS as: ' + this.os_type);
callback(this.os_type);
}
);
} catch (e) {
this._logging.error(e);
this._logging.info('Could not showvminfo for %s', vmname);
}
}
os: function(vmname, callback) {
function getOSTypeCallback(error, stdout, stderr) {
if (error) {
throw error;
}
/**
* Function to return an array of this object:
* {
* "key": "ResumeCounter",
* "value": 0,
* "namespace": "VMInfo",
* "timestamp": 1596902741176896000,
* "flags": ["TRANSIENT", "RDONLYGUEST"]
* }
* @param {String} vmname The name of the VM to enumerate guest properties on.
* @param {Function} callback The callback to handle the output.
* @returns {void} The output of stdout will be an array of properties objects.
*/
enumerate(vmname, callback) {
this.vboxmanage(
['guestproperty', 'enumerate', vmname],
(err, stdout, _) => {
if (err) {
throw err;
}
const arrOfProps = stdout.split('\n');
const nameRegex = /(?<=Name: ).+?(?=\,)/;
const valueRegex = /(?<=value: ).+?(?=\,)/;
const timestampRegex = /(?<=timestamp: ).+?(?=\,)/;
const flagsRegex = /(?<=flags: ).*/;
// The ostype is matched against the ID attribute of 'vboxmanage list ostypes'
if (stdout.indexOf('ostype="Windows') !== -1) {
guestproperty.os_type = known_OS_types.WINDOWS;
} else if (['ostype="MacOS', 'ostype="Mac OS machine'].includes(stdout)) {
guestproperty.os_type = known_OS_types.MAC;
} else {
guestproperty.os_type = known_OS_types.LINUX;
const arrOfPropsParsed = [];
arrOfProps
.filter((prop) => !!prop)
.forEach((prop) => {
const nameMatch = prop.match(nameRegex).shift(),
value = prop.match(valueRegex).shift(),
timestamp = prop.match(timestampRegex).shift(),
flags = prop
.match(flagsRegex)
.shift()
.split(',')
.map((flag) => flag.replace(' ', '')),
nameMatchSplit = nameMatch
.split('/')
.filter((name) => name !== ''),
key = nameMatchSplit[2],
namespace = nameMatchSplit[1];
arrOfPropsParsed.push({
key,
value,
namespace,
timestamp,
flags,
});
});
callback(err, arrOfPropsParsed);
}
logging.debug('Detected guest OS as: ' + guestproperty.os_type);
callback(guestproperty.os_type);
}
);
}
}
if (guestproperty.os_type) {
return callback(guestproperty.os_type);
}
try {
vboxmanage(['showvminfo', '--machinereadable', vmname], getOSTypeCallback);
} catch (e) {
logging.error(e);
logging.info('Could not showvminfo for %s', vmname);
}
class VboxExtraData {
constructor(logging, executor, vBoxManageBinary) {
this._logging = logging;
this._executor = executor;
this._vBoxManageBinary = vBoxManageBinary;
this.vboxmanage = defaultvboxmanage;
}
};
var extradata = {
get: function(options, callback) {
get(options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,

@@ -501,3 +713,3 @@ key = options.key,

vboxmanage(['getextradata', vm, key], function(error, stdout) {
this.vboxmanage(['getextradata', vm, key], function (error, stdout) {
if (error) {

@@ -513,5 +725,5 @@ callback(error);

});
},
}
set: function(options, callback) {
set(options, callback) {
var vm = options.vm || options.name || options.vmname || options.title,

@@ -521,36 +733,40 @@ key = options.key,

var cmd = 'setextradata "' + vm + '" "' + key + '" "' + value + '"';
vboxmanage(cmd, function(error, stdout) {
callback(error);
var cmd = ['setextradata', vm, key, value];
this.vboxmanage(cmd, function (error, stdout) {
callback(error);
});
}
};
}
module.exports = {
'exec': vmExec,
'kill': vmKill,
'list': list,
'pause': pause,
'reset': reset,
'resume': resume,
'start': start,
'stop': stop,
'savestate': savestate,
'export': vmExport,
'poweroff': poweroff,
'acpisleepbutton': acpisleepbutton,
'acpipowerbutton': acpipowerbutton,
'modify': modify,
'guestproperty': guestproperty,
'keyboardputscancode': keyboardputscancode,
'snapshotList': snapshotList,
'snapshotTake': snapshotTake,
'snapshotDelete': snapshotDelete,
'snapshotRestore': snapshotRestore,
'isRunning': isRunning,
'extradata': extradata,
'clone': clone,
'storage': storage,
// module.exports = {
// 'exec': vmExec,
// 'kill': vmKill,
// 'list': list,
// 'pause': pause,
// 'reset': reset,
// 'resume': resume,
// 'start': start,
// 'stop': stop,
// 'savestate': savestate,
// 'export': vmExport,
// 'poweroff': poweroff,
// 'acpisleepbutton': acpisleepbutton,
// 'acpipowerbutton': acpipowerbutton,
// 'modify': modify,
// 'guestproperty': guestproperty,
// 'keyboardputscancode': keyboardputscancode,
// 'snapshotList': snapshotList,
// 'snapshotTake': snapshotTake,
// 'snapshotDelete': snapshotDelete,
// 'snapshotRestore': snapshotRestore,
// 'isRunning': isRunning,
// 'extradata': extradata,
// 'clone': clone,
// 'storage': storage,
'SCAN_CODES': require('./scan-codes')
};
// 'SCAN_CODES': require('./scan-codes')
// };
module.exports = new Virtualbox();
module.exports.create = Virtualbox.create;
module.exports.Virtualbox = Virtualbox;
{
"name": "virtualbox",
"version": "1.0.2",
"version": "1.1.0",
"description": "A library to interact with VirtualBox.",

@@ -74,3 +74,3 @@ "author": "Azer Koculu <azer@kodfabrik.com>",

"jest": "^26.0.1",
"jshint": "^2.10.2"
"jshint": "^2.12.0"
},

@@ -77,0 +77,0 @@ "engines": {

@@ -12,19 +12,10 @@ # node-virtualbox

# Table of Contents
- [Installation](#installation)
- [Controlling Power and State](#controlling-power-and-state)
- [Starting a cold machine: Two ways](#starting-a-cold-machine-two-ways)
- [Stopping a machine](#stopping-a-machine)
- [Pausing, Saving and Resuming a machine](#pausing-saving-and-resuming-a-machine)
- [Controlling Power and State](#controlling-power-and-state) - [Starting a cold machine: Two ways](#starting-a-cold-machine-two-ways) - [Stopping a machine](#stopping-a-machine) - [Pausing, Saving and Resuming a machine](#pausing-saving-and-resuming-a-machine)
- [Export a Machine](#export-a-machine)
- [Snapshot Manage](#snapshot-manage)
- [Cloning a VM](#cloning-vms)
- [Storage](#storage)
- [Manage the IDE controller](#manage-the-ide-controller)
- [Attach a disk image file](#attach-a-disk-image-file)
- [Controlling the guest OS](#controlling-the-guest-os)
- [A note about security :warning:](#a-note-about-security)
- [Running programs in the guest](#running-programs-in-the-guest)
- [Executing commands as Administrators on Windows guests](#executing-commands-as-administrators-on-windows-guests)
- [Killing programs in the guest](#killing-programs-in-the-guest)
- [Sending keystrokes to a virtual machine](#sending-keystrokes-to-a-virtual-machine)
- [Storage](#storage) - [Manage the IDE controller](#manage-the-ide-controller) - [Attach a disk image file](#attach-a-disk-image-file)
- [Controlling the guest OS](#controlling-the-guest-os) - [A note about security :warning:](#a-note-about-security) - [Running programs in the guest](#running-programs-in-the-guest) - [Executing commands as Administrators on Windows guests](#executing-commands-as-administrators-on-windows-guests) - [Killing programs in the guest](#killing-programs-in-the-guest) - [Sending keystrokes to a virtual machine](#sending-keystrokes-to-a-virtual-machine)
- [Meta information about machine](#meta-information-about-machine)

@@ -37,2 +28,3 @@ - [Putting it all together](#putting-it-all-together)

- [Contributing](#contributing)
- [Testing](#testing)

@@ -68,5 +60,5 @@ # Installation

```javascript
virtualbox.start("machine_name", true, function start_callback(error) {
virtualbox.start('machine_name', true, function start_callback(error) {
if (error) throw error;
console.log("Virtual Machine has started WITH A GUI!");
console.log('Virtual Machine has started WITH A GUI!');
});

@@ -78,5 +70,5 @@ ```

```javascript
virtualbox.start("machine_name", function start_callback(error) {
virtualbox.start('machine_name', function start_callback(error) {
if (error) throw error;
console.log("Virtual Machine has started HEADLESS!");
console.log('Virtual Machine has started HEADLESS!');
});

@@ -90,5 +82,5 @@ ```

```javascript
virtualbox.stop("machine_name", function stop_callback(error) {
virtualbox.stop('machine_name', function stop_callback(error) {
if (error) throw error;
console.log("Virtual Machine has been saved");
console.log('Virtual Machine has been saved');
});

@@ -100,5 +92,5 @@ ```

```javascript
virtualbox.poweroff("machine_name", function poweroff_callback(error) {
virtualbox.poweroff('machine_name', function poweroff_callback(error) {
if (error) throw error;
console.log("Virtual Machine has been powered off!");
console.log('Virtual Machine has been powered off!');
});

@@ -108,3 +100,3 @@ ```

```javascript
virtualbox.acpipowerbutton("machine_name", function acpipower_callback(error) {
virtualbox.acpipowerbutton('machine_name', function acpipower_callback(error) {
if (error) throw error;

@@ -120,5 +112,5 @@ console.log("Virtual Machine's ACPI power button was pressed.");

```javascript
virtualbox.pause("machine_name", function pause_callback(error) {
virtualbox.pause('machine_name', function pause_callback(error) {
if (error) throw error;
console.log("Virtual Machine is now paused!");
console.log('Virtual Machine is now paused!');
});

@@ -128,5 +120,5 @@ ```

```javascript
virtualbox.savestate("machine_name", function save_callback(error) {
virtualbox.savestate('machine_name', function save_callback(error) {
if (error) throw error;
console.log("Virtual Machine is now paused!");
console.log('Virtual Machine is now paused!');
});

@@ -138,3 +130,3 @@ ```

```javascript
virtualbox.acpisleepbutton("machine_name", function acpisleep_callback(error) {
virtualbox.acpisleepbutton('machine_name', function acpisleep_callback(error) {
if (error) throw error;

@@ -148,5 +140,5 @@ console.log("Virtual Machine's ACPI sleep button signal was sent.");

```javascript
virtualbox.resume("machine_name", function resume_callback(error) {
virtualbox.resume('machine_name', function resume_callback(error) {
if (error) throw error;
console.log("Virtual Machine is now paused!");
console.log('Virtual Machine is now paused!');
});

@@ -158,3 +150,3 @@ ```

```javascript
virtualbox.reset("machine_name", function reset_callback(error) {
virtualbox.reset('machine_name', function reset_callback(error) {
if (error) throw error;

@@ -165,3 +157,2 @@ console.log("Virtual Machine's reset button was pressed!");

## Export a machine

@@ -172,5 +163,5 @@

```javascript
virtualbox.export("machine_name", "output", function export_callback(error) {
if(error) throw error;
console.log("Virtual Machine was exported!");
virtualbox.export('machine_name', 'output', function export_callback(error) {
if (error) throw error;
console.log('Virtual Machine was exported!');
});

@@ -184,6 +175,13 @@ ```

```javascript
virtualbox.snapshotList("machine_name", function(error, snapshotList, currentSnapshotUUID) {
if(error) throw error;
if(snapshotList) {
console.log(JSON.stringify(snapshotList), JSON.stringify(currentSnapshotUUID));
virtualbox.snapshotList('machine_name', function (
error,
snapshotList,
currentSnapshotUUID
) {
if (error) throw error;
if (snapshotList) {
console.log(
JSON.stringify(snapshotList),
JSON.stringify(currentSnapshotUUID)
);
}

@@ -196,6 +194,9 @@ });

```javascript
virtualbox.snapshotTake("machine_name", "snapshot_name", function(error, uuid) {
virtualbox.snapshotTake('machine_name', 'snapshot_name', function (
error,
uuid
) {
if (error) throw error;
console.log('Snapshot has been taken!');
console.log('UUID: ', uuid);
console.log('Snapshot has been taken!');
console.log('UUID: ', uuid);
});

@@ -207,5 +208,5 @@ ```

```javascript
virtualbox.snapshotDelete("machine_name", "snapshot_name", function(error) {
virtualbox.snapshotDelete('machine_name', 'snapshot_name', function (error) {
if (error) throw error;
console.log('Snapshot has been deleted!');
console.log('Snapshot has been deleted!');
});

@@ -217,5 +218,5 @@ ```

```javascript
virtualbox.snapshotRestore("machine_name", "snapshot_name", function(error) {
virtualbox.snapshotRestore('machine_name', 'snapshot_name', function (error) {
if (error) throw error;
console.log('Snapshot has been restored!');
console.log('Snapshot has been restored!');
});

@@ -229,5 +230,5 @@ ```

```javascript
virtualbox.clone("source_machine_name", "new_machine_name", function(error) {
virtualbox.clone('source_machine_name', 'new_machine_name', function (error) {
if (error) throw error;
console.log('Done fully cloning the virtual machine!');
console.log('Done fully cloning the virtual machine!');
});

@@ -239,10 +240,18 @@ ```

```javascript
virtualbox.snapshotTake("machine_name", "snapshot_name", function(error, uuid) {
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!');
});
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!');
}
);
});

@@ -258,9 +267,12 @@ ```

```javascript
virtualbox.storage.addCtl({
vm: "machine_name",
perhiperal_name: "IDE", //optional
type: "ide" //optional
}, function(){
console.log('Controller has been added!');
})
virtualbox.storage.addCtl(
{
vm: 'machine_name',
perhiperal_name: 'IDE', //optional
type: 'ide', //optional
},
function () {
console.log('Controller has been added!');
}
);
```

@@ -273,12 +285,15 @@

```javascript
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!');
})
virtualbox.storage.attach(
{
vm: 'machine_name',
perhiperal_name: 'IDE', //optional
port: '0', //optional
device: '0', //optional
type: 'dvddrive', //optional
medium: 'X:Foldercontaining\the.iso',
},
function () {
console.log('Image has been mounted!');
}
);
```

@@ -306,10 +321,10 @@

var options = {
vm: "machine_name",
cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe",
params: "https://google.com"
}
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...');
if (error) throw error;
console.log('Started Internet Explorer...');
});

@@ -324,7 +339,7 @@ ```

var options = {
vm: "machine_name",
user:"Administrator",
password: "123456",
cmd: "C:\\Program Files\\Internet Explorer\\iexplore.exe",
params: "https://google.com"
vm: 'machine_name',
user: 'Administrator',
password: '123456',
cmd: 'C:\\Program Files\\Internet Explorer\\iexplore.exe',
params: 'https://google.com',
};

@@ -338,9 +353,12 @@ ```

```javascript
virtualbox.kill({
vm: "machine_name",
cmd: "iexplore.exe"
}, function kill_callback(error) {
virtualbox.kill(
{
vm: 'machine_name',
cmd: 'iexplore.exe',
},
function kill_callback(error) {
if (error) throw error;
console.log('Terminated Internet Explorer.');
});
}
);
```

@@ -355,12 +373,16 @@

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')}
{ 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) {
virtualbox.keyboardputscancode(
'machine_name',
sequence,
function keyscan_callback(err) {
if (error) throw error;
console.log('Sent SHIFT A');
});
}
);
```

@@ -383,5 +405,5 @@

var options = {
vm: "machine_name",
key: "/VirtualBox/GuestInfo/Net/0/V4/IP"
}
vm: 'machine_name',
key: '/VirtualBox/GuestInfo/Net/0/V4/IP',
};

@@ -398,9 +420,14 @@ virtualbox.guestproperty.get(function guestproperty_callback(machines, error) {

var options = {
vm: "machine_name",
key: "GUI/Fullscreen"
}
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);
console.log(
'Virtual Machine "%s" extra "%s" value is "%s"',
options.vm,
options.key,
value
);
});

@@ -413,10 +440,15 @@ ```

var options = {
vm: "machine_name",
key: "GUI/Fullscreen",
value: "true"
}
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);
console.log(
'Set Virtual Machine "%s" extra "%s" value to "%s"',
options.vm,
options.key,
options.value
);
});

@@ -432,19 +464,18 @@ ```

virtualbox.start("machine_name", function start_callback(error) {
virtualbox.start('machine_name', function start_callback(error) {
if (error) throw error;
if (error) throw error;
console.log('VM "w7" has been successfully started');
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.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...');
}
);
});

@@ -475,3 +506,3 @@ ```

- `.snapshotList({vm:"machine_name"}, callback)`
- `.snapshotTake({vm:"machine_name"}, {vm:"snapshot_name"}, callback)`
- `.snapshotTake({vm:"machine_name"}, {vm:"snapshot_name"}, callback)`
- `.snapshotDelete({vm:"machine_name"}, {vm:"snapshot_UUID"}, callback)`

@@ -509,1 +540,5 @@ - `.snapshotRestore({vm:"machine_name"}, {vm:"snapshot_UUID"}, callback)`

Please abide by the [Contributor Code of Conduct](https://github.com/Node-Virtualization/node-virtualbox/blob/master/code_of_conduct.md).
## Testing
We currently do not have a complete unit testing suite. However, example scripts and a Vagrantfile are provided. Test your changes by writing a new script and/or running through all the test scripts to make sure they behave as expected. To do this [install vagrant](https://www.vagrantup.com/docs/installation) and run `vagrant up` in this repository's root directory. Then run the example scripts by using node: `node test/integration/<script-name>.js`. Please be ready to provide test output upon opening a pull request.
'use strict';
const virtualbox = require('../lib/virtualbox'),
args = process.argv.slice(2);
const { logger } = require('./helpers/logger');
const { create } = require('../lib/virtualbox');
jest.mock('child_process');
describe('Virtualbox#guestproperty', () => {
afterEach(() => {
virtualbox.guestproperty.os_type = null;
});
it('should not throw an error when getting a guest property with ostype of MacOS', (done) => {
const { execFile } = require('child_process');
execFile
.mockImplementationOnce((_, __, callback) => {
callback(null, 'ostype="MacOS', '');
})
.mockImplementationOnce((_, __, callback) => {
callback(null, 'somevalue', '');
});
const executor = jest
.fn()
.mockReturnValueOnce(
new Promise((resolve) =>
resolve({ err: null, stdout: 'somevalue', stderr: '' })
)
)
.mockReturnValueOnce(
new Promise((resolve) =>
resolve({ err: null, stdout: 'ostype="MacOS', stderr: '' })
)
)
.mockReturnValueOnce(
new Promise((resolve) =>
resolve({
err: null,
stdout: 'somevalue',
stderr: '',
})
)
);
const virtualbox = create(logger, executor);
virtualbox.guestproperty.get(

@@ -32,10 +41,32 @@ { vm: 'testmachine', key: 'someProperty' },

it('should not throw an error when getting a guest property with ostype of Mac OS machine', (done) => {
const { execFile } = require('child_process');
execFile
.mockImplementationOnce((_, __, callback) => {
callback(null, 'ostype="Mac OS machine', '');
})
.mockImplementationOnce((_, __, callback) => {
callback(null, 'somevalue', '');
});
const executor = jest
.fn()
.mockReturnValueOnce(
new Promise((resolve) =>
resolve({
err: null,
stdout: 'somevalue',
stderr: '',
})
)
)
.mockReturnValueOnce(
new Promise((resolve) =>
resolve({
err: null,
stdout: 'ostype="Mac OS machine',
stderr: '',
})
)
)
.mockReturnValueOnce(
new Promise((resolve) =>
resolve({
err: null,
stdout: 'somevalue',
stderr: '',
})
)
);
const virtualbox = create(logger, executor);
virtualbox.guestproperty.get(

@@ -42,0 +73,0 @@ { vm: 'testmachine', key: 'someProperty' },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc