-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli.js
166 lines (149 loc) · 4.75 KB
/
cli.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/env node
const fs = require('fs');
const neodoc = require('neodoc');
const path = require('path');
const io = require('socket.io-client');
const resolve = require('path').resolve;
const readline = require('readline-sync');
// <nodes> format: like 1#2#3#4#5#14
const args = neodoc.run(`
Usage: dlion start <nodes>
dlion stop <nodes>
dlion restart <nodes>
dlion burn [-i|--ignore] <nodes> <binname>
dlion erase <nodes>
dlion show
dlion [-h|--help]
Options:
-i --ignore Ignore burning process info.
-h --help Show this screen.
`, { optionsFirst: true, smartOptions: true });
// load secret token
let secret_token = null;
const dlion_dir = path.join(require('os').homedir(), '.dlion');
const token_file = path.join(dlion_dir, 'secret_token');
if(!fs.existsSync(dlion_dir)) fs.mkdirSync(dlion_dir);
if(!fs.existsSync(token_file)) {
// create new secret token
secret_token = readline.question("SECRET TOKEN: ");
fs.writeFileSync(token_file, secret_token);
}
else {
secret_token = fs.readFileSync(token_file);
}
const socket = io.connect('http://thulpwan.top:8443', { query: 'whoami='+secret_token });
const charm = require('charm')();
let progress_bar = {};
let complete_cnt = 0;
let clear_num = 0;
socket.on('reconnecting', (num) => {
console.log('attempt number %d: reconnecting to server...', num);
});
// parse <nodes> like '3-10#13-18#19#60'
function parse_nodes(nodes) {
function f(x) {
range = x.split('-');
if (range.length == 2) {
let s1 = Number(range[0])
let s2 = Number(range[1])
let l = Array.from({length: s2-s1+1}, (v, k) => k+s1);
return l;
}
else return parseInt(x);
}
return Array.prototype.concat.apply([], nodes.split('#').map(f))
}
socket.on('connect', () => {
// if args['<nodes>'] is a single num, its type is int
const nodes = parse_nodes(String(args['<nodes>']));
if (args['start']) {
socket.emit('start node', nodes);
socket.disconnect();
}
else if (args['stop']) {
socket.emit('stop node', nodes);
socket.disconnect();
}
else if (args['restart']) {
socket.emit('restart node', nodes);
socket.disconnect();
}
else if (args['restartrpi']) {
socket.emit('restart rpi', nodes);
socket.disconnect();
}
else if (args['erase']) {
socket.emit('erase node', nodes);
socket.disconnect();
}
else if (args['show']) {
socket.emit('show', (res, nodeinfo) => {
info_str = 'NodeID\tState\t\tIP\n';
for (let node of nodeinfo) {
info_str += [node['nid'], node['state'], '\t'+node['ip'], '\n'].join('\t');
}
console.log(info_str);
socket.disconnect();
});
}
else if (args['burn']) {
let binname = resolve(args['<binname>']);
let bin = fs.readFileSync(binname);
let num = nodes.length;
complete_cnt = 0;
clear_num = 0;
// set charm
charm.pipe(process.stdout);
// set cursor invisible
charm.cursor(false);
// reset bars
progress_bar = {};
for (let node of nodes) {
progress_bar[node] = 0;
}
socket.emit('burn node', nodes, binname, bin);
// draw progress bar
const draw = () => {
node_cnt = 0;
for (let node of nodes) {
charm.write('#'+(node+' '.repeat(3)).slice(0,4));
charm.write((' '.repeat(6)+progress_bar[node]).slice(-6)+'% ');
if (++node_cnt % 4 == 0) charm.write('\n');
}
if (node_cnt < 4) charm.write('\n');
charm.left(100);
clear_num = Math.floor(node_cnt/4);
charm.up(clear_num);
}
if (args['-i']) {
socket.disconnect();
}
else {
let timer = setInterval(() => {
draw();
// All burning processes are done
// stop timer and close websocket connection
if (complete_cnt === num) {
charm.write('\n'.repeat(clear_num+1));
clearInterval(timer);
// set cusor visible
charm.cursor(true);
socket.disconnect();
}
}, 10);
}
}
});
socket.on('progress bar', (nid, data) => {
progress_bar[nid] = data;
// finish one node
if (data === '100.00') complete_cnt++;
});
// clear window when burning processing is not done
process.on('SIGINT', function() {
charm.write('\n'.repeat(clear_num+1));
// set cusor visible
charm.cursor(true);
socket.disconnect();
process.exit();
});