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.old_interface = {}; 18 $scope.interface = {}; 19 $scope.networkDevice = false; 20 $scope.hostname = ''; 21 $scope.defaultgateway = ''; 22 $scope.set_network_error = ''; 23 $scope.set_network_success = false; 24 $scope.selectedInterface = ''; 25 $scope.confirm_settings = false; 26 $scope.loading = false; 27 28 loadNetworkInfo(); 29 30 $scope.selectInterface = function(interfaceId) { 31 $scope.interface = $scope.network.interfaces[interfaceId]; 32 // Copy the interface so we know later if changes were made to the page 33 $scope.old_interface = JSON.parse(JSON.stringify($scope.interface)); 34 $scope.selectedInterface = interfaceId; 35 $scope.networkDevice = false; 36 }; 37 38 $scope.addDNSField = function() { 39 $scope.interface.Nameservers.push(''); 40 }; 41 42 $scope.removeDNSField = function(index) { 43 $scope.interface.Nameservers.splice(index, 1); 44 }; 45 46 $scope.setNetworkSettings = function() { 47 // Hides the confirm network settings modal 48 $scope.confirm_settings = false; 49 $scope.set_network_error = ''; 50 $scope.set_network_success = false; 51 $scope.loading = true; 52 var promises = []; 53 54 // MAC Address are case-insensitive 55 if ($scope.interface.MACAddress.toLowerCase() != 56 dataService.mac_address.toLowerCase()) { 57 promises.push(setMACAddress()); 58 } 59 if ($scope.defaultgateway != dataService.defaultgateway) { 60 promises.push(setDefaultGateway()); 61 } 62 if ($scope.hostname != dataService.hostname) { 63 promises.push(setHostname()); 64 } 65 if ($scope.interface.DHCPEnabled != $scope.old_interface.DHCPEnabled) { 66 promises.push(setDHCPEnabled()); 67 } 68 69 // Remove any empty strings from the array. Important because we add an 70 // empty string to the end so the user can add a new DNS server, if the 71 // user doesn't fill out the field, we don't want to add. 72 $scope.interface.Nameservers = 73 $scope.interface.Nameservers.filter(Boolean); 74 // toString() is a cheap way to compare 2 string arrays 75 if ($scope.interface.Nameservers.toString() != 76 $scope.old_interface.Nameservers.toString()) { 77 promises.push(setNameservers()); 78 } 79 80 // Set IPV4 IP Addresses, Netmask Prefix Lengths, and Gateways 81 if (!$scope.interface.DHCPEnabled) { 82 for (var i in $scope.interface.ipv4.values) { 83 if (!APIUtils.validIPV4IP( 84 $scope.interface.ipv4.values[i].Address)) { 85 $scope.set_network_error = 86 $scope.interface.ipv4.values[i].Address + 87 ' invalid IP parameter'; 88 $scope.loading = false; 89 return; 90 } 91 if (!APIUtils.validIPV4IP( 92 $scope.interface.ipv4.values[i].Gateway)) { 93 $scope.set_network_error = 94 $scope.interface.ipv4.values[i].Address + 95 ' invalid gateway parameter'; 96 $scope.loading = false; 97 return; 98 } 99 // The netmask prefix length will be undefined if outside range 100 if (!$scope.interface.ipv4.values[i].PrefixLength) { 101 $scope.set_network_error = 102 $scope.interface.ipv4.values[i].Address + 103 ' invalid Prefix Length parameter'; 104 $scope.loading = false; 105 return; 106 } 107 if ($scope.interface.ipv4.values[i].Address != 108 $scope.old_interface.ipv4.values[i].Address || 109 $scope.interface.ipv4.values[i].PrefixLength != 110 $scope.old_interface.ipv4.values[i].PrefixLength || 111 $scope.interface.ipv4.values[i].Gateway != 112 $scope.old_interface.ipv4.values[i].Gateway) { 113 promises.push(setIPV4(i)); 114 } 115 } 116 } 117 118 if (promises.length) { 119 $q.all(promises).finally(function() { 120 $scope.loading = false; 121 if (!$scope.set_network_error) { 122 $scope.set_network_success = true; 123 // Since an IPV4 interface (e.g. IP address, gateway, or netmask) 124 // edit is a delete then an add and the GUI can't calculate the 125 // interface id (e.g. 5c083707) beforehand and it is not returned 126 // by the REST call, openbmc#3227, reload the page after an edit, 127 // which makes a 2nd REST call. 128 // Do this for all network changes due to the possibility of a set 129 // network failing even though it returned success, openbmc#1641, 130 // and to update dataService and old_interface to know which 131 // data has changed if the user continues to edit network 132 // settings. 133 // TODO: The reload is not ideal. Revisit this. 134 $timeout(function() { 135 loadNetworkInfo(); 136 }, 4000); 137 } 138 }); 139 } else { 140 $scope.loading = false; 141 } 142 }; 143 144 function setMACAddress() { 145 return APIUtils 146 .setMACAddress( 147 $scope.selectedInterface, $scope.interface.MACAddress) 148 .then( 149 function(data) {}, 150 function(error) { 151 console.log(JSON.stringify(error)); 152 $scope.set_network_error = 'MAC Address'; 153 }); 154 } 155 156 function setDefaultGateway() { 157 return APIUtils.setDefaultGateway($scope.defaultgateway) 158 .then( 159 function(data) {}, 160 function(error) { 161 console.log(JSON.stringify(error)); 162 $scope.set_network_error = 'Default Gateway'; 163 }); 164 } 165 166 function setHostname() { 167 return APIUtils.setHostname($scope.hostname) 168 .then( 169 function(data) {}, 170 function(error) { 171 console.log(JSON.stringify(error)); 172 $scope.set_network_error = 'Hostname'; 173 }); 174 } 175 176 function setDHCPEnabled() { 177 return APIUtils 178 .setDHCPEnabled( 179 $scope.selectedInterface, $scope.interface.DHCPEnabled) 180 .then( 181 function(data) {}, 182 function(error) { 183 console.log(JSON.stringify(error)); 184 $scope.set_network_error = 'DHCP'; 185 }); 186 } 187 188 function setNameservers() { 189 // Nameservers does not allow an empty array, since we remove all empty 190 // strings above, could have an empty array. TODO: openbmc/openbmc#3240 191 if ($scope.interface.Nameservers.length == 0) { 192 $scope.interface.Nameservers.push(''); 193 } 194 return APIUtils 195 .setNameservers( 196 $scope.selectedInterface, $scope.interface.Nameservers) 197 .then( 198 function(data) {}, 199 function(error) { 200 console.log(JSON.stringify(error)); 201 $scope.set_network_error = 'DNS Servers'; 202 }); 203 } 204 205 function setIPV4(index) { 206 // The correct way to edit an IPV4 interface is to remove it and then 207 // add a new one 208 return APIUtils 209 .deleteIPV4( 210 $scope.selectedInterface, $scope.interface.ipv4.ids[index]) 211 .then( 212 function(data) { 213 return APIUtils 214 .addIPV4( 215 $scope.selectedInterface, 216 $scope.interface.ipv4.values[index].Address, 217 $scope.interface.ipv4.values[index].PrefixLength, 218 $scope.interface.ipv4.values[index].Gateway) 219 .then( 220 function(data) {}, 221 function(error) { 222 console.log(JSON.stringify(error)); 223 $scope.set_network_error = 224 $scope.interface.ipv4.values[index].Address; 225 }); 226 }, 227 function(error) { 228 console.log(JSON.stringify(error)); 229 $scope.set_network_error = 230 $scope.interface.ipv4.values[index].Address; 231 }); 232 } 233 234 $scope.refresh = function() { 235 loadNetworkInfo(); 236 }; 237 238 function loadNetworkInfo() { 239 APIUtils.getNetworkInfo().then(function(data) { 240 dataService.setNetworkInfo(data); 241 $scope.network = data.formatted_data; 242 $scope.hostname = data.hostname; 243 $scope.defaultgateway = data.defaultgateway; 244 if ($scope.network.interface_ids.length) { 245 // Use the first network interface if the user hasn't chosen one 246 if (!$scope.selectedInterface || 247 !$scope.network.interfaces[$scope.selectedInterface]) { 248 $scope.selectedInterface = $scope.network.interface_ids[0]; 249 } 250 $scope.interface = 251 $scope.network.interfaces[$scope.selectedInterface]; 252 // Copy the interface so we know later if changes were made to the 253 // page 254 $scope.old_interface = JSON.parse(JSON.stringify($scope.interface)); 255 } 256 }); 257 } 258 } 259 ]); 260})(angular); 261