/
virtualbox.js
132 lines (109 loc) · 3.78 KB
/
virtualbox.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
const fs = require('fs-extra');
const path = require('path');
const vbox = require('node-virtualbox');
const VBoxProvider = require('node-virtualbox/lib/VBoxProvider');
const env = require('../env');
const { slimdir, registry } = env.vars();
const privateKey = path.join(slimdir, 'baker_rsa');
class VirtualBox {
constructor()
{
this.defaultOptions =
{
cpus: 1,
mem: 1024,
syncs: [],
disk: false,
verbose: true,
ssh_port: undefined // auto-find a ssh available port
}
this.driver = new VBoxProvider();
this.privateKey = privateKey
}
/**
* Returns State of a VM
* @param {String} VMName
*/
async getState(VMName) {
let vmInfo = await this.driver.info(VMName);
return vmInfo.VMState.replace(/"/g,'');
}
async _getUsedPorts(name)
{
let ports = [];
let properties = await this.driver.info(name);
for( let prop in properties )
{
if( prop.indexOf('Forwarding(') >= 0 )
{
try {
ports.push( parseInt( properties[prop].split(',')[3]) );
}
catch(e) { console.error(e); }
}
}
return ports;
}
/**
* Get ssh configurations
* @param {Obj} machine
* @param {Obj} nodeName Optionally give name of machine when multiple machines declared.
*/
async getSSHConfig(machine, nodeName) {
// Use VirtualBox driver
let vmInfo = await this.driver.info(machine);
let port = null;
Object.keys(vmInfo).forEach(key => {
if(vmInfo[key].includes('guestssh')){
port = parseInt( vmInfo[key].split(',')[3]);
}
});
return {user: 'root', port: port, host: machine, hostname: '127.0.0.1', private_key: this.privateKey};
}
async create(name, options)
{
let iso = path.join(registry, options.image, 'slim.iso');
console.log(iso);
let args = {
vmname: name,
micro: true,
attach_iso: iso,
quickBoot: true,
cpus: options.cpus || this.defaultOptions.cpus,
mem: options.mem || this.defaultOptions.mem,
syncs: options.syncs || this.defaultOptions.syncs,
disk: options.disk || this.defaultOptions.disk,
verbose: options.verbose || this.defaultOptions.verbose,
ssh_port: options.ssh_port || this.defaultOptions.ssh_port,
};
if ((await this.driver.list()).filter(e => e.name === name).length == 0) {
await vbox(args);
} else if((await this.getState(name)) != 'running') {
await vbox({start: true, vmname: name, syncs: [], verbose: true});
}
let sshInfo = await this.getSSHConfig(name);
console.log(`ssh -i ${sshInfo.private_key} ${sshInfo.user}@${sshInfo.hostname} -p ${sshInfo.port} -o StrictHostKeyChecking=no`)
}
async stop(name, force = false) {
await vbox({ stopCmd: true, vmname: name, syncs: [], verbose: false }).catch(e => e);
}
async delete(name) {
let state = await this.getState(name);
if (state == 'running') {
await this.stop(name);
} else if (state === 'not_found') {
throw new Error(`vm ${name} does not exist`);
}
await vbox({ deleteCmd: true, vmname: name, syncs: [], verbose: false }).catch(e => e);
}
async exists(name) {
return await fs.exists(path.join(registry, name, 'slim.iso'));
}
async size(name) {
return fs.statSync(path.join(registry, name, 'slim.iso')).size;
}
async list() {
return await this.driver.list();
}
}
module.exports = new VirtualBox();