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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
|
/**
* Controller for network
*
* @module app/configuration
* @exports networkController
* @name networkController
*/
window.angular && (function(angular) {
'use strict';
angular.module('app.configuration').controller('networkController', [
'$scope', '$window', 'APIUtils', 'dataService', '$timeout', '$route', '$q',
'toastService',
function(
$scope, $window, APIUtils, dataService, $timeout, $route, $q,
toastService) {
$scope.dataService = dataService;
$scope.network = {};
$scope.oldInterface = {};
$scope.interface = {};
$scope.networkDevice = false;
$scope.hostname = '';
$scope.defaultGateway = '';
$scope.selectedInterface = '';
$scope.confirmSettings = false;
$scope.loading = false;
$scope.ipv4sToDelete = [];
loadNetworkInfo();
$scope.selectInterface = function(interfaceId) {
$scope.interface = $scope.network.interfaces[interfaceId];
// Copy the interface so we know later if changes were made to the page
$scope.oldInterface = JSON.parse(JSON.stringify($scope.interface));
$scope.selectedInterface = interfaceId;
$scope.networkDevice = false;
};
$scope.addDNSField = function() {
$scope.interface.Nameservers.push('');
};
$scope.removeDNSField = function(index) {
$scope.interface.Nameservers.splice(index, 1);
};
$scope.addIpv4Field = function() {
$scope.interface.ipv4.values.push(
{Address: '', PrefixLength: '', Gateway: ''});
};
$scope.removeIpv4Address = function(index) {
// Check if the IPV4 being removed has an id. This indicates that it is
// an existing address and needs to be removed in the back end.
if ($scope.interface.ipv4.values[index].id) {
$scope.ipv4sToDelete.push($scope.interface.ipv4.values[index]);
}
$scope.interface.ipv4.values.splice(index, 1);
};
$scope.setNetworkSettings = function() {
// Hides the confirm network settings modal
$scope.confirmSettings = false;
$scope.loading = true;
var promises = [];
// MAC Address are case-insensitive
if ($scope.interface.MACAddress.toLowerCase() !=
dataService.mac_address.toLowerCase()) {
promises.push(setMACAddress());
}
if ($scope.defaultGateway != dataService.defaultgateway) {
promises.push(setDefaultGateway());
}
if ($scope.hostname != dataService.hostname) {
promises.push(setHostname());
}
if ($scope.interface.DHCPEnabled != $scope.oldInterface.DHCPEnabled) {
promises.push(setDHCPEnabled());
}
// Remove any empty strings from the array. Important because we add an
// empty string to the end so the user can add a new DNS server, if the
// user doesn't fill out the field, we don't want to add.
$scope.interface.Nameservers =
$scope.interface.Nameservers.filter(Boolean);
// toString() is a cheap way to compare 2 string arrays
if ($scope.interface.Nameservers.toString() !=
$scope.oldInterface.Nameservers.toString()) {
promises.push(setNameservers());
}
// Set IPV4 IP Addresses, Netmask Prefix Lengths, and Gateways
if (!$scope.interface.DHCPEnabled) {
// Delete existing IPV4 addresses that were removed
promises.push(removeIPV4s());
// Update any changed IPV4 addresses and add new
for (var i in $scope.interface.ipv4.values) {
if (!APIUtils.validIPV4IP(
$scope.interface.ipv4.values[i].Address)) {
toastService.error(
$scope.interface.ipv4.values[i].Address +
' invalid IP parameter');
$scope.loading = false;
return;
}
if ($scope.interface.ipv4.values[i].Gateway &&
!APIUtils.validIPV4IP(
$scope.interface.ipv4.values[i].Gateway)) {
toastService.error(
$scope.interface.ipv4.values[i].Address +
' invalid gateway parameter');
$scope.loading = false;
return;
}
// The netmask prefix length will be undefined if outside range
if (!$scope.interface.ipv4.values[i].PrefixLength) {
toastService.error(
$scope.interface.ipv4.values[i].Address +
' invalid Prefix Length parameter');
$scope.loading = false;
return;
}
if ($scope.interface.ipv4.values[i].updateAddress ||
$scope.interface.ipv4.values[i].updateGateway ||
$scope.interface.ipv4.values[i].updatePrefix) {
// If IPV4 has an id it means it already exists in the back end,
// and in order to update it is required to remove previous IPV4
// address and add new one. See openbmc/openbmc/issues/2163.
// TODO: update to use PUT once issue 2163 is resolved.
if ($scope.interface.ipv4.values[i].id) {
promises.push(updateIPV4(i));
} else {
promises.push(addIPV4(i));
}
}
}
}
if (promises.length) {
$q.all(promises).then(
function(response) {
// Since an IPV4 interface (e.g. IP address, gateway, or
// netmask) edit is a delete then an add and the GUI can't
// calculate the interface id (e.g. 5c083707) beforehand and it
// is not returned by the REST call, openbmc#3227, reload the
// page after an edit, which makes a 2nd REST call. Do this for
// all network changes due to the possibility of a set network
// failing even though it returned success, openbmc#1641, and to
// update dataService and oldInterface to know which data has
// changed if the user continues to edit network settings.
// TODO: The reload is not ideal. Revisit this.
$timeout(function() {
loadNetworkInfo();
$scope.loading = false;
toastService.success('Network settings saved');
}, 4000);
},
function(error) {
$scope.loading = false;
toastService.error('Network settings could not be saved');
})
} else {
$scope.loading = false;
}
};
function setMACAddress() {
return APIUtils
.setMACAddress(
$scope.selectedInterface, $scope.interface.MACAddress)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
});
}
function setDefaultGateway() {
return APIUtils.setDefaultGateway($scope.defaultGateway)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
});
}
function setHostname() {
return APIUtils.setHostname($scope.hostname)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
});
}
function setDHCPEnabled() {
return APIUtils
.setDHCPEnabled(
$scope.selectedInterface, $scope.interface.DHCPEnabled)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
});
}
function setNameservers() {
return APIUtils
.setNameservers(
$scope.selectedInterface, $scope.interface.Nameservers)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
});
}
function removeIPV4s() {
return $scope.ipv4sToDelete.map(function(ipv4) {
return APIUtils.deleteIPV4($scope.selectedInterface, ipv4.id)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
})
});
}
function addIPV4(index) {
return APIUtils
.addIPV4(
$scope.selectedInterface,
$scope.interface.ipv4.values[index].Address,
$scope.interface.ipv4.values[index].PrefixLength,
$scope.interface.ipv4.values[index].Gateway)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
})
}
function updateIPV4(index) {
// The correct way to edit an IPV4 interface is to remove it and then
// add a new one
return APIUtils
.deleteIPV4(
$scope.selectedInterface,
$scope.interface.ipv4.values[index].id)
.then(
function(data) {
return APIUtils
.addIPV4(
$scope.selectedInterface,
$scope.interface.ipv4.values[index].Address,
$scope.interface.ipv4.values[index].PrefixLength,
$scope.interface.ipv4.values[index].Gateway)
.then(
function(data) {},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
});
},
function(error) {
console.log(JSON.stringify(error));
return $q.reject();
});
}
$scope.refresh = function() {
loadNetworkInfo();
};
function loadNetworkInfo() {
APIUtils.getNetworkInfo().then(function(data) {
dataService.setNetworkInfo(data);
$scope.network = data.formatted_data;
$scope.hostname = data.hostname;
$scope.defaultGateway = data.defaultgateway;
if ($scope.network.interface_ids.length) {
// Use the first network interface if the user hasn't chosen one
if (!$scope.selectedInterface ||
!$scope.network.interfaces[$scope.selectedInterface]) {
$scope.selectedInterface = $scope.network.interface_ids[0];
}
$scope.interface =
$scope.network.interfaces[$scope.selectedInterface];
// Copy the interface so we know later if changes were made to the
// page
$scope.oldInterface = JSON.parse(JSON.stringify($scope.interface));
}
// Add id values and update flags to corresponding IPV4 objects
for (var i = 0; i < $scope.interface.ipv4.values.length; i++) {
$scope.interface.ipv4.values[i].id = $scope.interface.ipv4.ids[i];
$scope.interface.ipv4.values[i].updateAddress = false;
$scope.interface.ipv4.values[i].updateGateway = false;
$scope.interface.ipv4.values[i].updatePrefix = false;
}
});
}
}
]);
})(angular);
|