RaBU1234 commited on
Commit
f993ca2
·
verified ·
1 Parent(s): 0cbe271

Create firecracker-manager.js

Browse files
Files changed (1) hide show
  1. firecracker-manager.js +171 -0
firecracker-manager.js ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { spawn, exec } = require('child_process');
2
+ const fs = require('fs').promises;
3
+ const path = require('path');
4
+ const { EventEmitter } = require('events');
5
+
6
+ class FirecrackerManager extends EventEmitter {
7
+ constructor() {
8
+ super();
9
+ this.vms = new Map();
10
+ this.basePath = '/tmp/sandboxes';
11
+ this.kernelPath = '/tmp/vmlinux';
12
+ this.rootfsPath = '/tmp/rootfs.ext4';
13
+ this.firecrackerAvailable = false;
14
+ }
15
+
16
+ async initialize() {
17
+ await fs.mkdir(this.basePath, { recursive: true });
18
+
19
+ // Check if Firecracker is available
20
+ try {
21
+ await new Promise((resolve, reject) => {
22
+ exec('firecracker --version', (error, stdout) => {
23
+ if (error) {
24
+ console.warn('⚠️ Firecracker not available');
25
+ this.firecrackerAvailable = false;
26
+ resolve();
27
+ } else {
28
+ console.log('✅ Firecracker available:', stdout.trim());
29
+ this.firecrackerAvailable = true;
30
+ resolve();
31
+ }
32
+ });
33
+ });
34
+ } catch (e) {
35
+ this.firecrackerAvailable = false;
36
+ }
37
+
38
+ // Check for KVM device
39
+ try {
40
+ await fs.access('/dev/kvm');
41
+ console.log('✅ KVM device available');
42
+ } catch (e) {
43
+ console.warn('⚠️ /dev/kvm not found - Firecracker requires KVM');
44
+ this.firecrackerAvailable = false;
45
+ }
46
+
47
+ console.log(`Firecracker Manager initialized (available: ${this.firecrackerAvailable})`);
48
+ }
49
+
50
+ async createVM(vmId, options = {}) {
51
+ if (!this.firecrackerAvailable) {
52
+ throw new Error('Firecracker not available');
53
+ }
54
+
55
+ const vmPath = path.join(this.basePath, vmId);
56
+ await fs.mkdir(vmPath, { recursive: true });
57
+
58
+ const socketPath = path.join(vmPath, 'firecracker.sock');
59
+ const configPath = path.join(vmPath, 'config.json');
60
+
61
+ // Create Firecracker VM configuration
62
+ const config = {
63
+ 'boot-source': {
64
+ kernel_image_path: this.kernelPath,
65
+ boot_args: 'console=ttyS0 reboot=k panic=1 pci=off'
66
+ },
67
+ 'drives': [{
68
+ drive_id: 'rootfs',
69
+ path_on_host: this.rootfsPath,
70
+ is_root_device: true,
71
+ is_read_only: false
72
+ }],
73
+ 'machine-config': {
74
+ vcpu_count: 1,
75
+ mem_size_mib: 512,
76
+ ht_enabled: false
77
+ },
78
+ 'network-interfaces': [{
79
+ iface_id: 'eth0',
80
+ guest_mac: '06:00:AC:10:00:02',
81
+ host_dev_name: 'tap0'
82
+ }]
83
+ };
84
+
85
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2));
86
+
87
+ const vm = {
88
+ vmId,
89
+ path: vmPath,
90
+ socketPath,
91
+ configPath,
92
+ process: null,
93
+ createdAt: Date.now(),
94
+ status: 'created'
95
+ };
96
+
97
+ this.vms.set(vmId, vm);
98
+ return vm;
99
+ }
100
+
101
+ async startVM(vmId) {
102
+ const vm = this.vms.get(vmId);
103
+ if (!vm) throw new Error('VM not found');
104
+
105
+ return new Promise((resolve, reject) => {
106
+ // Start Firecracker process
107
+ const proc = spawn('firecracker', [
108
+ '--api-sock', vm.socketPath,
109
+ '--config-file', vm.configPath
110
+ ], {
111
+ stdio: ['ignore', 'pipe', 'pipe']
112
+ });
113
+
114
+ vm.process = proc;
115
+ vm.status = 'running';
116
+
117
+ proc.stdout.on('data', (data) => {
118
+ console.log(`[${vmId}][stdout]: ${data.toString().trim()}`);
119
+ });
120
+
121
+ proc.stderr.on('data', (data) => {
122
+ console.log(`[${vmId}][stderr]: ${data.toString().trim()}`);
123
+ });
124
+
125
+ proc.on('exit', (code) => {
126
+ console.log(`[${vmId}] VM exited with code: ${code}`);
127
+ vm.status = 'stopped';
128
+ });
129
+
130
+ // Wait for socket to be ready
131
+ setTimeout(() => {
132
+ resolve(vm);
133
+ }, 2000);
134
+ });
135
+ }
136
+
137
+ async executeInVM(vmId, command) {
138
+ const vm = this.vms.get(vmId);
139
+ if (!vm) throw new Error('VM not found');
140
+ if (vm.status !== 'running') throw new Error('VM not running');
141
+
142
+ // Send command via Firecracker API
143
+ // This would use the socket API to communicate with the VM
144
+ // Implementation depends on your rootfs setup
145
+
146
+ return {
147
+ vmId,
148
+ command,
149
+ status: 'executed'
150
+ };
151
+ }
152
+
153
+ async stopVM(vmId) {
154
+ const vm = this.vms.get(vmId);
155
+ if (!vm) return;
156
+
157
+ if (vm.process) {
158
+ vm.process.kill('SIGTERM');
159
+ }
160
+
161
+ try {
162
+ await fs.rm(vm.path, { recursive: true, force: true });
163
+ } catch (e) {
164
+ console.error('Cleanup error:', e.message);
165
+ }
166
+
167
+ this.vms.delete(vmId);
168
+ }
169
+ }
170
+
171
+ module.exports = FirecrackerManager;