forked from hpchud/vccjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclusternet.js
More file actions
252 lines (235 loc) · 7.24 KB
/
clusternet.js
File metadata and controls
252 lines (235 loc) · 7.24 KB
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/usr/bin/env node
var os = require("os");
var network = require("network");
var promise = require("deferred");
var vccutil = require("./vccutil.js");
var logger = require("./log.js");
// convert async network functions to promises
var getInterfacesList = promise.promisify(network.get_interfaces_list);
var getActiveInterface = promise.promisify(network.get_active_interface);
/**
* Represents a VCC container's network configuration
* @constructor
* @param {Object} config - A configuration object (usually loaded from vccutil.GetConfig)
*/
var ClusterNet = function (config) {
this.config = config;
this.interfaces_list = null;
this.active_interface = null;
this.name_to_ip = null;
this.ip_to_name = null;
};
/**
* Get a list of network interfaces, and the active interface if available.
*/
ClusterNet.prototype.getInterfaces = function () {
var deferred = promise();
var me = this;
getInterfacesList().then(function (interfaces_list) {
me.interfaces_list = interfaces_list;
getActiveInterface().then(function (active_interface) {
me.active_interface = active_interface;
deferred.resolve();
}, function (err) {
me.active_interface = {};
deferred.resolve();
});
}, function (err) {
me.interfaces_list = [];
deferred.resolve();
});
return deferred.promise;
}
/**
* See if we should filter an interface or not
* @param {Object} interface - An interface object
* @returns {Boolean}
*/
ClusterNet.prototype.filterInterface = function (i) {
if (i.name.startsWith("docker")) {
return true;
} else if (i.name.startsWith("dummy")) {
return true;
} else {
return false;
}
}
/**
* Parse the list of interfaces
* @returns {Array} [names to ips, ips to names]
*/
ClusterNet.prototype.parseInterfacesList = function () {
var me = this;
// convert interfaces list into something we can work with
var name_to_ip = this.interfaces_list.reduce(function (r, i) {
if (!me.filterInterface(i)) {
if (i.ip_address) {
r[i.name] = i.ip_address;
}
}
return r;
}, {});
var ip_to_name = this.interfaces_list.reduce(function (r, i) {
if (!me.filterInterface(i)) {
if (i.ip_address) {
r[i.ip_address] = i.name;
}
}
return r;
}, {});
this.name_to_ip = name_to_ip;
this.ip_to_name = ip_to_name;
return [name_to_ip, ip_to_name];
}
/**
* See if we have a saved IP address
* @returns {String|Boolean} the IP address, or false if not
*/
ClusterNet.prototype.hasSavedAddress = function () {
// if an address is already set, we see if an interface is available with that address
// if not, we override the manually set address with our discovered one
if(this.config.myaddress) {
logger.debug("there is a saved address", this.config.myaddress);
if(this.config.myaddress in this.ip_to_name) {
logger.debug("found interface for saved address", this.ip_to_name[this.config.myaddress]);
return this.config.myaddress;
} else {
logger.warn("there is no interface for saved address, ignoring it...");
return false;
}
} else {
logger.debug("there is no saved address");
return false;
}
}
/**
* See if we have a dynamic ethwe* interface with an IP address
* @returns {String|Boolean} the IP address, or false if not
*/
ClusterNet.prototype.hasEthweInterface = function () {
// see if there is a ethwe
for(var iface in this.name_to_ip) {
if(iface.includes('ethwe')) {
logger.debug("found ethwe* interface");
return this.name_to_ip[iface];
}
}
logger.debug("there is no ethwe* interface");
return false;
}
/**
* See if we have an exposed IP address on the Weave interface
* (not a dynamic ethwe* interface)
* @returns {String|Boolean} the IP address, or false if not
*/
ClusterNet.prototype.hasWeaveInterface = function () {
// see if there is a weave interface
if('weave' in this.name_to_ip) {
logger.debug("found weave interface");
return this.name_to_ip['weave'];
} else {
logger.debug("there is no weave interface");
return false;
}
}
/**
* See if there is an active network interface on the system
* @returns {String|Boolean} the IP address, or false if not
*/
ClusterNet.prototype.hasActiveInterface = function () {
// detect the active interface
if (this.active_interface) {
logger.debug("active interface is", this.active_interface.name);
return this.active_interface.ip_address;
} else {
logger.warn("could not determine active interface");
return false;
}
}
/**
* See if there is any network interface on the system
* @returns {String|Boolean} the IP address, or false if not
*/
ClusterNet.prototype.hasAvailableInterface = function () {
// return first available interface
if (Object.keys(this.name_to_ip).length > 0) {
var firstint = Object.keys(this.name_to_ip).sort()[0];
logger.warn("using first available interface", firstint);
return this.name_to_ip[firstint];
} else {
logger.error("there are no interfaces available");
return false;
}
}
/**
* Call each has* function in the best order to determine IP address
* @returns {String|Boolean} the IP address, or false if not
*/
ClusterNet.prototype.getAddress = function () {
// try our options
var ip = this.hasSavedAddress();
if(ip) {
return ip;
}
ip = this.hasEthweInterface();
if(ip) {
return ip;
}
ip = this.hasWeaveInterface();
if(ip) {
return ip;
}
ip = this.hasActiveInterface();
if(ip) {
return ip;
}
ip = this.hasAvailableInterface();
if(ip) {
return ip;
}
logger.error("could not get an address");
return false;
}
/**
* Write a new version of the system config file (loaded by subsequent modules)
* @param {String} address - The determined IP address
* @returns {Promise}
*/
ClusterNet.prototype.writeConfig = function (address) {
var deferred = promise();
logger.info("our IP address is", address);
logger.info("our hostname is", os.hostname());
// update the config file with our address and hostname
this.config.myaddress = address;
this.config.myhostname = os.hostname();
logger.debug("going to write config");
vccutil.writeConfig(this.config).then(function () {
logger.info("updated config");
deferred.resolve();
},
function (err) {
logger.error("failed to write config");
logger.error(err);
deferred.reject(err);
});
return deferred.promise;
};
/**
* The main function to call if we are loaded as a daemon
*/
ClusterNet.prototype.main = function () {
var me = this;
// get the interfaces
this.getInterfaces().then(function () {
// parse the interface list
me.parseInterfacesList();
// write the discovered address
me.writeConfig(me.getAddress());
});
}
if (require.main === module) {
var clusternet = new ClusterNet(vccutil.getConfig());
clusternet.main();
} else {
module.exports = ClusterNet;
}