xref: /openbmc/phosphor-webui/app/configuration/controllers/network-controller.js (revision 9a3b542275499825d36d67f4a02aec8ad2144491)
1cd789508SIftekharul Islam/**
2cd789508SIftekharul Islam * Controller for network
3cd789508SIftekharul Islam *
4cd789508SIftekharul Islam * @module app/configuration
5cd789508SIftekharul Islam * @exports networkController
6cd789508SIftekharul Islam * @name networkController
7cd789508SIftekharul Islam */
8cd789508SIftekharul Islam
9cd789508SIftekharul Islamwindow.angular && (function(angular) {
10cd789508SIftekharul Islam  'use strict';
11cd789508SIftekharul Islam
12d27bb135SAndrew Geissler  angular.module('app.configuration').controller('networkController', [
130af165b9SGunnar Mills    '$scope', '$window', 'APIUtils', 'dataService', '$timeout', '$route', '$q',
14*9a3b5422Sbeccabroek    'ngToast',
15*9a3b5422Sbeccabroek    function(
16*9a3b5422Sbeccabroek        $scope, $window, APIUtils, dataService, $timeout, $route, $q, ngToast) {
17cd789508SIftekharul Islam      $scope.dataService = dataService;
182a489554SIftekharul Islam      $scope.network = {};
19067a1cd1Sbeccabroek      $scope.oldInterface = {};
202a489554SIftekharul Islam      $scope.interface = {};
212a489554SIftekharul Islam      $scope.networkDevice = false;
22ba5e3f34SAndrew Geissler      $scope.hostname = '';
23067a1cd1Sbeccabroek      $scope.defaultGateway = '';
247ddc7274SGunnar Mills      $scope.selectedInterface = '';
25067a1cd1Sbeccabroek      $scope.confirmSettings = false;
2684981f0aSGunnar Mills      $scope.loading = false;
27067a1cd1Sbeccabroek      $scope.ipv4sToDelete = [];
282a489554SIftekharul Islam
29a3f75320SGunnar Mills      loadNetworkInfo();
30a3f75320SGunnar Mills
312a489554SIftekharul Islam      $scope.selectInterface = function(interfaceId) {
322a489554SIftekharul Islam        $scope.interface = $scope.network.interfaces[interfaceId];
33a45c3852SGunnar Mills        // Copy the interface so we know later if changes were made to the page
34067a1cd1Sbeccabroek        $scope.oldInterface = JSON.parse(JSON.stringify($scope.interface));
352a489554SIftekharul Islam        $scope.selectedInterface = interfaceId;
362a489554SIftekharul Islam        $scope.networkDevice = false;
37ba5e3f34SAndrew Geissler      };
38bc3ab72cSGunnar Mills
39bc3ab72cSGunnar Mills      $scope.addDNSField = function() {
40bc3ab72cSGunnar Mills        $scope.interface.Nameservers.push('');
41bc3ab72cSGunnar Mills      };
42bc3ab72cSGunnar Mills
43cff61508Sbeccabroek      $scope.removeDNSField = function(index) {
44cff61508Sbeccabroek        $scope.interface.Nameservers.splice(index, 1);
45cff61508Sbeccabroek      };
46cff61508Sbeccabroek
471a0e7d06Sbeccabroek      $scope.addIpv4Field = function() {
481a0e7d06Sbeccabroek        $scope.interface.ipv4.values.push(
491a0e7d06Sbeccabroek            {Address: '', PrefixLength: '', Gateway: ''});
501a0e7d06Sbeccabroek      };
511a0e7d06Sbeccabroek
52971ac1aaSbeccabroek      $scope.removeIpv4Address = function(index) {
53971ac1aaSbeccabroek        // Check if the IPV4 being removed has an id. This indicates that it is
54971ac1aaSbeccabroek        // an existing address and needs to be removed in the back end.
55971ac1aaSbeccabroek        if ($scope.interface.ipv4.values[index].id) {
56067a1cd1Sbeccabroek          $scope.ipv4sToDelete.push($scope.interface.ipv4.values[index]);
57971ac1aaSbeccabroek        }
58971ac1aaSbeccabroek        $scope.interface.ipv4.values.splice(index, 1);
59971ac1aaSbeccabroek      };
60971ac1aaSbeccabroek
617ddc7274SGunnar Mills      $scope.setNetworkSettings = function() {
62d01504cfSGunnar Mills        // Hides the confirm network settings modal
63067a1cd1Sbeccabroek        $scope.confirmSettings = false;
6484981f0aSGunnar Mills        $scope.loading = true;
65dca79d73SGunnar Mills        var promises = [];
66dca79d73SGunnar Mills
67659651e8SGunnar Mills        // MAC Address are case-insensitive
68659651e8SGunnar Mills        if ($scope.interface.MACAddress.toLowerCase() !=
69659651e8SGunnar Mills            dataService.mac_address.toLowerCase()) {
70dca79d73SGunnar Mills          promises.push(setMACAddress());
71659651e8SGunnar Mills        }
72067a1cd1Sbeccabroek        if ($scope.defaultGateway != dataService.defaultgateway) {
73dca79d73SGunnar Mills          promises.push(setDefaultGateway());
74659651e8SGunnar Mills        }
75659651e8SGunnar Mills        if ($scope.hostname != dataService.hostname) {
76309e06abSGunnar Mills          promises.push(setHostname());
77659651e8SGunnar Mills        }
78067a1cd1Sbeccabroek        if ($scope.interface.DHCPEnabled != $scope.oldInterface.DHCPEnabled) {
79cb2c3060SGunnar Mills          promises.push(setDHCPEnabled());
80cb2c3060SGunnar Mills        }
81309e06abSGunnar Mills
8282658298SGunnar Mills        // Remove any empty strings from the array. Important because we add an
8382658298SGunnar Mills        // empty string to the end so the user can add a new DNS server, if the
8482658298SGunnar Mills        // user doesn't fill out the field, we don't want to add.
8582658298SGunnar Mills        $scope.interface.Nameservers =
8682658298SGunnar Mills            $scope.interface.Nameservers.filter(Boolean);
870646782dSGunnar Mills        // toString() is a cheap way to compare 2 string arrays
880646782dSGunnar Mills        if ($scope.interface.Nameservers.toString() !=
89067a1cd1Sbeccabroek            $scope.oldInterface.Nameservers.toString()) {
900646782dSGunnar Mills          promises.push(setNameservers());
910646782dSGunnar Mills        }
920646782dSGunnar Mills
93a45c3852SGunnar Mills        // Set IPV4 IP Addresses, Netmask Prefix Lengths, and Gateways
94a45c3852SGunnar Mills        if (!$scope.interface.DHCPEnabled) {
95971ac1aaSbeccabroek          // Delete existing IPV4 addresses that were removed
96971ac1aaSbeccabroek          promises.push(removeIPV4s());
971a0e7d06Sbeccabroek          // Update any changed IPV4 addresses and add new
98a45c3852SGunnar Mills          for (var i in $scope.interface.ipv4.values) {
996549114eSGunnar Mills            if (!APIUtils.validIPV4IP(
1006549114eSGunnar Mills                    $scope.interface.ipv4.values[i].Address)) {
101*9a3b5422Sbeccabroek              ngToast.danger(
102*9a3b5422Sbeccabroek                  $scope.interface.ipv4.values[i].Address +
103*9a3b5422Sbeccabroek                  ' invalid IP parameter');
1046549114eSGunnar Mills              $scope.loading = false;
1056549114eSGunnar Mills              return;
1066549114eSGunnar Mills            }
1076549114eSGunnar Mills            if (!APIUtils.validIPV4IP(
1086549114eSGunnar Mills                    $scope.interface.ipv4.values[i].Gateway)) {
109*9a3b5422Sbeccabroek              ngToast.danger(
110*9a3b5422Sbeccabroek                  $scope.interface.ipv4.values[i].Address +
111*9a3b5422Sbeccabroek                  ' invalid gateway parameter');
1126549114eSGunnar Mills              $scope.loading = false;
1136549114eSGunnar Mills              return;
1146549114eSGunnar Mills            }
1156549114eSGunnar Mills            // The netmask prefix length will be undefined if outside range
1166549114eSGunnar Mills            if (!$scope.interface.ipv4.values[i].PrefixLength) {
117*9a3b5422Sbeccabroek              ngToast.danger(
118*9a3b5422Sbeccabroek                  $scope.interface.ipv4.values[i].Address +
119*9a3b5422Sbeccabroek                  ' invalid Prefix Length parameter');
1206549114eSGunnar Mills              $scope.loading = false;
1216549114eSGunnar Mills              return;
1226549114eSGunnar Mills            }
123067a1cd1Sbeccabroek            if ($scope.interface.ipv4.values[i].updateAddress ||
124067a1cd1Sbeccabroek                $scope.interface.ipv4.values[i].updateGateway ||
125067a1cd1Sbeccabroek                $scope.interface.ipv4.values[i].updatePrefix) {
1261a0e7d06Sbeccabroek              // If IPV4 has an id it means it already exists in the back end,
1271a0e7d06Sbeccabroek              // and in order to update it is required to remove previous IPV4
1281a0e7d06Sbeccabroek              // address and add new one. See openbmc/openbmc/issues/2163.
1291a0e7d06Sbeccabroek              // TODO: update to use PUT once issue 2163 is resolved.
1301a0e7d06Sbeccabroek              if ($scope.interface.ipv4.values[i].id) {
1311a0e7d06Sbeccabroek                promises.push(updateIPV4(i));
1321a0e7d06Sbeccabroek              } else {
1331a0e7d06Sbeccabroek                promises.push(addIPV4(i));
1341a0e7d06Sbeccabroek              }
135a45c3852SGunnar Mills            }
136a45c3852SGunnar Mills          }
137a45c3852SGunnar Mills        }
138a45c3852SGunnar Mills
1390af165b9SGunnar Mills        if (promises.length) {
140*9a3b5422Sbeccabroek          $q.all(promises).then(
141*9a3b5422Sbeccabroek              function(response) {
142*9a3b5422Sbeccabroek                // Since an IPV4 interface (e.g. IP address, gateway, or
143*9a3b5422Sbeccabroek                // netmask) edit is a delete then an add and the GUI can't
144*9a3b5422Sbeccabroek                // calculate the interface id (e.g. 5c083707) beforehand and it
145*9a3b5422Sbeccabroek                // is not returned by the REST call, openbmc#3227, reload the
146*9a3b5422Sbeccabroek                // page after an edit, which makes a 2nd REST call. Do this for
147*9a3b5422Sbeccabroek                // all network changes due to the possibility of a set network
148*9a3b5422Sbeccabroek                // failing even though it returned success, openbmc#1641, and to
149*9a3b5422Sbeccabroek                // update dataService and oldInterface to know which data has
150*9a3b5422Sbeccabroek                // changed if the user continues to edit network settings.
1510af165b9SGunnar Mills                // TODO: The reload is not ideal. Revisit this.
1520af165b9SGunnar Mills                $timeout(function() {
153a3f75320SGunnar Mills                  loadNetworkInfo();
154*9a3b5422Sbeccabroek                  $scope.loading = false;
155*9a3b5422Sbeccabroek                  ngToast.success('Network settings saved');
1560af165b9SGunnar Mills                }, 4000);
157*9a3b5422Sbeccabroek              },
158*9a3b5422Sbeccabroek              function(error) {
159*9a3b5422Sbeccabroek                $scope.loading = false;
160*9a3b5422Sbeccabroek                ngToast.danger('Network settings could not be saved');
161*9a3b5422Sbeccabroek              })
1620af165b9SGunnar Mills        } else {
1630af165b9SGunnar Mills          $scope.loading = false;
1640af165b9SGunnar Mills        }
165dca79d73SGunnar Mills      };
166dca79d73SGunnar Mills
167dca79d73SGunnar Mills      function setMACAddress() {
168dca79d73SGunnar Mills        return APIUtils
1697ddc7274SGunnar Mills            .setMACAddress(
1707ddc7274SGunnar Mills                $scope.selectedInterface, $scope.interface.MACAddress)
1717ddc7274SGunnar Mills            .then(
172dca79d73SGunnar Mills                function(data) {},
1737ddc7274SGunnar Mills                function(error) {
174dca79d73SGunnar Mills                  console.log(JSON.stringify(error));
175*9a3b5422Sbeccabroek                  return $q.reject();
1767ddc7274SGunnar Mills                });
177dca79d73SGunnar Mills      }
178dca79d73SGunnar Mills
179dca79d73SGunnar Mills      function setDefaultGateway() {
180067a1cd1Sbeccabroek        return APIUtils.setDefaultGateway($scope.defaultGateway)
181dca79d73SGunnar Mills            .then(
182dca79d73SGunnar Mills                function(data) {},
183dca79d73SGunnar Mills                function(error) {
184dca79d73SGunnar Mills                  console.log(JSON.stringify(error));
185*9a3b5422Sbeccabroek                  return $q.reject();
186dca79d73SGunnar Mills                });
187dca79d73SGunnar Mills      }
188309e06abSGunnar Mills
189309e06abSGunnar Mills      function setHostname() {
190309e06abSGunnar Mills        return APIUtils.setHostname($scope.hostname)
191309e06abSGunnar Mills            .then(
192309e06abSGunnar Mills                function(data) {},
193309e06abSGunnar Mills                function(error) {
194309e06abSGunnar Mills                  console.log(JSON.stringify(error));
195*9a3b5422Sbeccabroek                  return $q.reject();
196309e06abSGunnar Mills                });
197309e06abSGunnar Mills      }
198309e06abSGunnar Mills
199cb2c3060SGunnar Mills      function setDHCPEnabled() {
200cb2c3060SGunnar Mills        return APIUtils
201cb2c3060SGunnar Mills            .setDHCPEnabled(
202cb2c3060SGunnar Mills                $scope.selectedInterface, $scope.interface.DHCPEnabled)
203cb2c3060SGunnar Mills            .then(
204cb2c3060SGunnar Mills                function(data) {},
205cb2c3060SGunnar Mills                function(error) {
206cb2c3060SGunnar Mills                  console.log(JSON.stringify(error));
207*9a3b5422Sbeccabroek                  return $q.reject();
208cb2c3060SGunnar Mills                });
209cb2c3060SGunnar Mills      }
210cb2c3060SGunnar Mills
2110646782dSGunnar Mills      function setNameservers() {
21282658298SGunnar Mills        // Nameservers does not allow an empty array, since we remove all empty
2139863d121SGunnar Mills        // strings above, could have an empty array. TODO: openbmc/openbmc#3240
21482658298SGunnar Mills        if ($scope.interface.Nameservers.length == 0) {
21582658298SGunnar Mills          $scope.interface.Nameservers.push('');
21682658298SGunnar Mills        }
2170646782dSGunnar Mills        return APIUtils
2180646782dSGunnar Mills            .setNameservers(
2190646782dSGunnar Mills                $scope.selectedInterface, $scope.interface.Nameservers)
2200646782dSGunnar Mills            .then(
2210646782dSGunnar Mills                function(data) {},
2220646782dSGunnar Mills                function(error) {
2230646782dSGunnar Mills                  console.log(JSON.stringify(error));
224*9a3b5422Sbeccabroek                  return $q.reject();
2250646782dSGunnar Mills                });
2260646782dSGunnar Mills      }
2270646782dSGunnar Mills
228971ac1aaSbeccabroek      function removeIPV4s() {
229067a1cd1Sbeccabroek        return $scope.ipv4sToDelete.map(function(ipv4) {
230971ac1aaSbeccabroek          return APIUtils.deleteIPV4($scope.selectedInterface, ipv4.id)
231971ac1aaSbeccabroek              .then(
232971ac1aaSbeccabroek                  function(data) {},
233971ac1aaSbeccabroek                  function(error) {
234971ac1aaSbeccabroek                    console.log(JSON.stringify(error));
235*9a3b5422Sbeccabroek                    return $q.reject();
236971ac1aaSbeccabroek                  })
237971ac1aaSbeccabroek        });
238971ac1aaSbeccabroek      }
239971ac1aaSbeccabroek
2401a0e7d06Sbeccabroek      function addIPV4(index) {
2411a0e7d06Sbeccabroek        return APIUtils
2421a0e7d06Sbeccabroek            .addIPV4(
2431a0e7d06Sbeccabroek                $scope.selectedInterface,
2441a0e7d06Sbeccabroek                $scope.interface.ipv4.values[index].Address,
2451a0e7d06Sbeccabroek                $scope.interface.ipv4.values[index].PrefixLength,
2461a0e7d06Sbeccabroek                $scope.interface.ipv4.values[index].Gateway)
2471a0e7d06Sbeccabroek            .then(
2481a0e7d06Sbeccabroek                function(data) {},
2491a0e7d06Sbeccabroek                function(error) {
2501a0e7d06Sbeccabroek                  console.log(JSON.stringify(error));
251*9a3b5422Sbeccabroek                  return $q.reject();
2521a0e7d06Sbeccabroek                })
2531a0e7d06Sbeccabroek      }
2541a0e7d06Sbeccabroek
2551a0e7d06Sbeccabroek      function updateIPV4(index) {
256a45c3852SGunnar Mills        // The correct way to edit an IPV4 interface is to remove it and then
257a45c3852SGunnar Mills        // add a new one
258a45c3852SGunnar Mills        return APIUtils
259a45c3852SGunnar Mills            .deleteIPV4(
2601a0e7d06Sbeccabroek                $scope.selectedInterface,
2611a0e7d06Sbeccabroek                $scope.interface.ipv4.values[index].id)
262a45c3852SGunnar Mills            .then(
263a45c3852SGunnar Mills                function(data) {
264a45c3852SGunnar Mills                  return APIUtils
265a45c3852SGunnar Mills                      .addIPV4(
266a45c3852SGunnar Mills                          $scope.selectedInterface,
267a45c3852SGunnar Mills                          $scope.interface.ipv4.values[index].Address,
268a45c3852SGunnar Mills                          $scope.interface.ipv4.values[index].PrefixLength,
269a45c3852SGunnar Mills                          $scope.interface.ipv4.values[index].Gateway)
270a45c3852SGunnar Mills                      .then(
271a45c3852SGunnar Mills                          function(data) {},
272a45c3852SGunnar Mills                          function(error) {
273a45c3852SGunnar Mills                            console.log(JSON.stringify(error));
274*9a3b5422Sbeccabroek                            return $q.reject();
275a45c3852SGunnar Mills                          });
276a45c3852SGunnar Mills                },
277a45c3852SGunnar Mills                function(error) {
278a45c3852SGunnar Mills                  console.log(JSON.stringify(error));
279*9a3b5422Sbeccabroek                  return $q.reject();
280a45c3852SGunnar Mills                });
281a45c3852SGunnar Mills      }
282a45c3852SGunnar Mills
2839a0094dcSGunnar Mills      $scope.refresh = function() {
284a3f75320SGunnar Mills        loadNetworkInfo();
2859a0094dcSGunnar Mills      };
286a3f75320SGunnar Mills
287a3f75320SGunnar Mills      function loadNetworkInfo() {
2882a489554SIftekharul Islam        APIUtils.getNetworkInfo().then(function(data) {
289659651e8SGunnar Mills          dataService.setNetworkInfo(data);
2902a489554SIftekharul Islam          $scope.network = data.formatted_data;
2912a489554SIftekharul Islam          $scope.hostname = data.hostname;
292067a1cd1Sbeccabroek          $scope.defaultGateway = data.defaultgateway;
2932a489554SIftekharul Islam          if ($scope.network.interface_ids.length) {
294ffdef96dSRebecca Shaw            // Use the first network interface if the user hasn't chosen one
295a3f75320SGunnar Mills            if (!$scope.selectedInterface ||
296a3f75320SGunnar Mills                !$scope.network.interfaces[$scope.selectedInterface]) {
2972a489554SIftekharul Islam              $scope.selectedInterface = $scope.network.interface_ids[0];
298a3f75320SGunnar Mills            }
299d27bb135SAndrew Geissler            $scope.interface =
300d27bb135SAndrew Geissler                $scope.network.interfaces[$scope.selectedInterface];
301a45c3852SGunnar Mills            // Copy the interface so we know later if changes were made to the
302a45c3852SGunnar Mills            // page
303067a1cd1Sbeccabroek            $scope.oldInterface = JSON.parse(JSON.stringify($scope.interface));
3042a489554SIftekharul Islam          }
3051a0e7d06Sbeccabroek          // Add id values and update flags to corresponding IPV4 objects
306971ac1aaSbeccabroek          for (var i = 0; i < $scope.interface.ipv4.values.length; i++) {
307971ac1aaSbeccabroek            $scope.interface.ipv4.values[i].id = $scope.interface.ipv4.ids[i];
308067a1cd1Sbeccabroek            $scope.interface.ipv4.values[i].updateAddress = false;
309067a1cd1Sbeccabroek            $scope.interface.ipv4.values[i].updateGateway = false;
310067a1cd1Sbeccabroek            $scope.interface.ipv4.values[i].updatePrefix = false;
311971ac1aaSbeccabroek          }
3122a489554SIftekharul Islam        });
313cd789508SIftekharul Islam      }
314a3f75320SGunnar Mills    }
315ba5e3f34SAndrew Geissler  ]);
316cd789508SIftekharul Islam})(angular);
317