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