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