1/** 2 * Controller for network 3 * 4 * @module app/configuration 5 * @exports networkController 6 * @name networkController 7 */ 8 9window.angular && (function(angular) { 10 'use strict'; 11 12 angular.module('app.configuration').controller('networkController', [ 13 '$scope', '$window', 'APIUtils', 'dataService', '$timeout', '$route', '$q', 14 function($scope, $window, APIUtils, dataService, $timeout, $route, $q) { 15 $scope.dataService = dataService; 16 $scope.network = {}; 17 $scope.oldInterface = {}; 18 $scope.interface = {}; 19 $scope.networkDevice = false; 20 $scope.hostname = ''; 21 $scope.defaultGateway = ''; 22 $scope.setNetworkError = ''; 23 $scope.setNetworkSuccess = false; 24 $scope.selectedInterface = ''; 25 $scope.confirmSettings = false; 26 $scope.loading = false; 27 $scope.ipv4sToDelete = []; 28 29 loadNetworkInfo(); 30 31 $scope.selectInterface = function(interfaceId) { 32 $scope.interface = $scope.network.interfaces[interfaceId]; 33 // Copy the interface so we know later if changes were made to the page 34 $scope.oldInterface = JSON.parse(JSON.stringify($scope.interface)); 35 $scope.selectedInterface = interfaceId; 36 $scope.networkDevice = false; 37 }; 38 39 $scope.addDNSField = function() { 40 $scope.interface.Nameservers.push(''); 41 }; 42 43 $scope.removeDNSField = function(index) { 44 $scope.interface.Nameservers.splice(index, 1); 45 }; 46 47 $scope.addIpv4Field = function() { 48 $scope.interface.ipv4.values.push( 49 {Address: '', PrefixLength: '', Gateway: ''}); 50 }; 51 52 $scope.removeIpv4Address = function(index) { 53 // Check if the IPV4 being removed has an id. This indicates that it is 54 // an existing address and needs to be removed in the back end. 55 if ($scope.interface.ipv4.values[index].id) { 56 $scope.ipv4sToDelete.push($scope.interface.ipv4.values[index]); 57 } 58 $scope.interface.ipv4.values.splice(index, 1); 59 }; 60 61 $scope.setNetworkSettings = function() { 62 // Hides the confirm network settings modal 63 $scope.confirmSettings = false; 64 $scope.setNetworkError = ''; 65 $scope.setNetworkSuccess = false; 66 $scope.loading = true; 67 var promises = []; 68 69 // MAC Address are case-insensitive 70 if ($scope.interface.MACAddress.toLowerCase() != 71 dataService.mac_address.toLowerCase()) { 72 promises.push(setMACAddress()); 73 } 74 if ($scope.defaultGateway != dataService.defaultgateway) { 75 promises.push(setDefaultGateway()); 76 } 77 if ($scope.hostname != dataService.hostname) { 78 promises.push(setHostname()); 79 } 80 if ($scope.interface.DHCPEnabled != $scope.oldInterface.DHCPEnabled) { 81 promises.push(setDHCPEnabled()); 82 } 83 84 // Remove any empty strings from the array. Important because we add an 85 // empty string to the end so the user can add a new DNS server, if the 86 // user doesn't fill out the field, we don't want to add. 87 $scope.interface.Nameservers = 88 $scope.interface.Nameservers.filter(Boolean); 89 // toString() is a cheap way to compare 2 string arrays 90 if ($scope.interface.Nameservers.toString() != 91 $scope.oldInterface.Nameservers.toString()) { 92 promises.push(setNameservers()); 93 } 94 95 // Set IPV4 IP Addresses, Netmask Prefix Lengths, and Gateways 96 if (!$scope.interface.DHCPEnabled) { 97 // Delete existing IPV4 addresses that were removed 98 promises.push(removeIPV4s()); 99 // Update any changed IPV4 addresses and add new 100 for (var i in $scope.interface.ipv4.values) { 101 if (!APIUtils.validIPV4IP( 102 $scope.interface.ipv4.values[i].Address)) { 103 $scope.setNetworkError = $scope.interface.ipv4.values[i].Address + 104 ' invalid IP parameter'; 105 $scope.loading = false; 106 return; 107 } 108 if (!APIUtils.validIPV4IP( 109 $scope.interface.ipv4.values[i].Gateway)) { 110 $scope.setNetworkError = $scope.interface.ipv4.values[i].Address + 111 ' invalid gateway parameter'; 112 $scope.loading = false; 113 return; 114 } 115 // The netmask prefix length will be undefined if outside range 116 if (!$scope.interface.ipv4.values[i].PrefixLength) { 117 $scope.setNetworkError = $scope.interface.ipv4.values[i].Address + 118 ' invalid Prefix Length parameter'; 119 $scope.loading = false; 120 return; 121 } 122 if ($scope.interface.ipv4.values[i].updateAddress || 123 $scope.interface.ipv4.values[i].updateGateway || 124 $scope.interface.ipv4.values[i].updatePrefix) { 125 // If IPV4 has an id it means it already exists in the back end, 126 // and in order to update it is required to remove previous IPV4 127 // address and add new one. See openbmc/openbmc/issues/2163. 128 // TODO: update to use PUT once issue 2163 is resolved. 129 if ($scope.interface.ipv4.values[i].id) { 130 promises.push(updateIPV4(i)); 131 } else { 132 promises.push(addIPV4(i)); 133 } 134 } 135 } 136 } 137 138 if (promises.length) { 139 $q.all(promises).finally(function() { 140 $scope.loading = false; 141 if (!$scope.setNetworkError) { 142 $scope.setNetworkSuccess = true; 143 // Since an IPV4 interface (e.g. IP address, gateway, or netmask) 144 // edit is a delete then an add and the GUI can't calculate the 145 // interface id (e.g. 5c083707) beforehand and it is not returned 146 // by the REST call, openbmc#3227, reload the page after an edit, 147 // which makes a 2nd REST call. 148 // Do this for all network changes due to the possibility of a set 149 // network failing even though it returned success, openbmc#1641, 150 // and to update dataService and oldInterface to know which 151 // data has changed if the user continues to edit network 152 // settings. 153 // TODO: The reload is not ideal. Revisit this. 154 $timeout(function() { 155 loadNetworkInfo(); 156 }, 4000); 157 } 158 }); 159 } else { 160 $scope.loading = false; 161 } 162 }; 163 164 function setMACAddress() { 165 return APIUtils 166 .setMACAddress( 167 $scope.selectedInterface, $scope.interface.MACAddress) 168 .then( 169 function(data) {}, 170 function(error) { 171 console.log(JSON.stringify(error)); 172 $scope.setNetworkError = 'MAC Address'; 173 }); 174 } 175 176 function setDefaultGateway() { 177 return APIUtils.setDefaultGateway($scope.defaultGateway) 178 .then( 179 function(data) {}, 180 function(error) { 181 console.log(JSON.stringify(error)); 182 $scope.setNetworkError = 'Default Gateway'; 183 }); 184 } 185 186 function setHostname() { 187 return APIUtils.setHostname($scope.hostname) 188 .then( 189 function(data) {}, 190 function(error) { 191 console.log(JSON.stringify(error)); 192 $scope.setNetworkError = 'Hostname'; 193 }); 194 } 195 196 function setDHCPEnabled() { 197 return APIUtils 198 .setDHCPEnabled( 199 $scope.selectedInterface, $scope.interface.DHCPEnabled) 200 .then( 201 function(data) {}, 202 function(error) { 203 console.log(JSON.stringify(error)); 204 $scope.setNetworkError = 'DHCP'; 205 }); 206 } 207 208 function setNameservers() { 209 // Nameservers does not allow an empty array, since we remove all empty 210 // strings above, could have an empty array. TODO: openbmc/openbmc#3240 211 if ($scope.interface.Nameservers.length == 0) { 212 $scope.interface.Nameservers.push(''); 213 } 214 return APIUtils 215 .setNameservers( 216 $scope.selectedInterface, $scope.interface.Nameservers) 217 .then( 218 function(data) {}, 219 function(error) { 220 console.log(JSON.stringify(error)); 221 $scope.setNetworkError = 'DNS Servers'; 222 }); 223 } 224 225 function removeIPV4s() { 226 return $scope.ipv4sToDelete.map(function(ipv4) { 227 return APIUtils.deleteIPV4($scope.selectedInterface, ipv4.id) 228 .then( 229 function(data) {}, 230 function(error) { 231 console.log(JSON.stringify(error)); 232 $scope.setNetworkError = ipv4.Address; 233 }) 234 }); 235 } 236 237 function addIPV4(index) { 238 return APIUtils 239 .addIPV4( 240 $scope.selectedInterface, 241 $scope.interface.ipv4.values[index].Address, 242 $scope.interface.ipv4.values[index].PrefixLength, 243 $scope.interface.ipv4.values[index].Gateway) 244 .then( 245 function(data) {}, 246 function(error) { 247 console.log(JSON.stringify(error)); 248 $scope.setNetworkError = 249 $scope.interface.ipv4.values[index].Address; 250 }) 251 } 252 253 function updateIPV4(index) { 254 // The correct way to edit an IPV4 interface is to remove it and then 255 // add a new one 256 return APIUtils 257 .deleteIPV4( 258 $scope.selectedInterface, 259 $scope.interface.ipv4.values[index].id) 260 .then( 261 function(data) { 262 return APIUtils 263 .addIPV4( 264 $scope.selectedInterface, 265 $scope.interface.ipv4.values[index].Address, 266 $scope.interface.ipv4.values[index].PrefixLength, 267 $scope.interface.ipv4.values[index].Gateway) 268 .then( 269 function(data) {}, 270 function(error) { 271 console.log(JSON.stringify(error)); 272 $scope.setNetworkError = 273 $scope.interface.ipv4.values[index].Address; 274 }); 275 }, 276 function(error) { 277 console.log(JSON.stringify(error)); 278 $scope.setNetworkError = 279 $scope.interface.ipv4.values[index].Address; 280 }); 281 } 282 283 $scope.refresh = function() { 284 loadNetworkInfo(); 285 }; 286 287 function loadNetworkInfo() { 288 APIUtils.getNetworkInfo().then(function(data) { 289 dataService.setNetworkInfo(data); 290 $scope.network = data.formatted_data; 291 $scope.hostname = data.hostname; 292 $scope.defaultGateway = data.defaultgateway; 293 if ($scope.network.interface_ids.length) { 294 // Use the first network interface if the user hasn't chosen one 295 if (!$scope.selectedInterface || 296 !$scope.network.interfaces[$scope.selectedInterface]) { 297 $scope.selectedInterface = $scope.network.interface_ids[0]; 298 } 299 $scope.interface = 300 $scope.network.interfaces[$scope.selectedInterface]; 301 // Copy the interface so we know later if changes were made to the 302 // page 303 $scope.oldInterface = JSON.parse(JSON.stringify($scope.interface)); 304 } 305 // Add id values and update flags to corresponding IPV4 objects 306 for (var i = 0; i < $scope.interface.ipv4.values.length; i++) { 307 $scope.interface.ipv4.values[i].id = $scope.interface.ipv4.ids[i]; 308 $scope.interface.ipv4.values[i].updateAddress = false; 309 $scope.interface.ipv4.values[i].updateGateway = false; 310 $scope.interface.ipv4.values[i].updatePrefix = false; 311 } 312 }); 313 } 314 } 315 ]); 316})(angular); 317