1/**
2 * Controller for date-time
3 *
4 * @module app/configuration
5 * @exports dateTimeController
6 * @name dateTimeController
7 */
8
9window.angular && (function(angular) {
10  'use strict';
11
12  angular.module('app.configuration').controller('dateTimeController', [
13    '$scope', '$window', 'APIUtils', '$route', '$q',
14    function($scope, $window, APIUtils, $route, $q) {
15      $scope.bmc = {};
16      // Only used when the owner is "Split"
17      $scope.host = {};
18      $scope.ntp = {servers: []};
19      $scope.time_mode = '';
20      $scope.time_owner = '';
21      $scope.time_owners = ['BMC', 'Host', 'Both', 'Split'];
22      $scope.set_time_error = false;
23      $scope.set_time_success = false;
24      $scope.loading = true;
25      var time_path = '/xyz/openbmc_project/time/';
26
27      var getTimePromise = APIUtils.getTime().then(
28          function(data) {
29            // The time is returned as Epoch microseconds convert to
30            // milliseconds.
31            if (data.data[time_path + 'bmc'] &&
32                data.data[time_path + 'bmc'].hasOwnProperty('Elapsed')) {
33              $scope.bmc.date =
34                  new Date(data.data[time_path + 'bmc'].Elapsed / 1000);
35              // Don't care about milliseconds and don't want them displayed
36              $scope.bmc.date.setMilliseconds(0);
37              // https://stackoverflow.com/questions/1091372/getting-the-clients-timezone-in-javascript
38              // GMT-0400 (EDT)
39              $scope.bmc.timezone =
40                  $scope.bmc.date.toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1];
41            }
42            if (data.data[time_path + 'host'] &&
43                data.data[time_path + 'host'].hasOwnProperty('Elapsed')) {
44              $scope.host.date =
45                  new Date(data.data[time_path + 'host'].Elapsed / 1000);
46              $scope.host.date.setMilliseconds(0);
47              $scope.host.timezone =
48                  $scope.host.date.toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1];
49            }
50            if (data.data[time_path + 'owner'] &&
51                data.data[time_path + 'owner'].hasOwnProperty('TimeOwner')) {
52              $scope.time_owner =
53                  data.data[time_path + 'owner'].TimeOwner.split('.').pop();
54            }
55            if (data.data[time_path + 'sync_method'] &&
56                data.data[time_path + 'sync_method'].hasOwnProperty(
57                    'TimeSyncMethod')) {
58              $scope.time_mode = data.data[time_path + 'sync_method']
59                                     .TimeSyncMethod.split('.')
60                                     .pop();
61            }
62          },
63          function(error) {
64            console.log(JSON.stringify(error));
65          });
66
67      var getNTPPromise = APIUtils.getNTPServers().then(
68          function(data) {
69            $scope.ntp.servers = data.data;
70          },
71          function(error) {
72            console.log(JSON.stringify(error));
73          });
74
75      var promises = [
76        getTimePromise,
77        getNTPPromise,
78      ];
79
80      $q.all(promises).finally(function() {
81        $scope.loading = false;
82      });
83
84      $scope.setTime = function() {
85        $scope.set_time_error = false;
86        $scope.set_time_success = false;
87        $scope.loading = true;
88        var promises = [setTimeMode(), setTimeOwner(), setNTPServers()];
89
90        $q.all(promises).then(
91            function() {
92              // Have to set the time mode and time owner first to avoid a
93              // insufficient permissions if the time mode or time owner had
94              // changed.
95              var manual_promises = [];
96              if ($scope.time_mode == 'Manual') {
97                // If owner is 'Split' set both.
98                // If owner is 'Host' set only it.
99                // Else set BMC only. See:
100                // https://github.com/openbmc/phosphor-time-manager/blob/master/README.md
101                if ($scope.time_owner != 'Host') {
102                  manual_promises.push(
103                      setBMCTime($scope.bmc.date.getTime() * 1000));
104                }
105                // Even though we are setting Host time, we are setting from
106                // the BMC date and time fields labeled "BMC and Host Time"
107                // currently.
108                if ($scope.time_owner == 'Host') {
109                  manual_promises.push(
110                      setHostTime($scope.bmc.date.getTime() * 1000));
111                }
112              }
113              // Set the Host if Split even if NTP. In split mode, the host has
114              // its own date and time field. Set from it.
115              if ($scope.time_owner == 'Split') {
116                manual_promises.push(
117                    setHostTime($scope.host.date.getTime() * 1000));
118              }
119
120              $q.all(manual_promises)
121                  .then(
122                      function() {
123                        $scope.set_time_success = true;
124                      },
125                      function(errors) {
126                        console.log(JSON.stringify(errors));
127                        $scope.set_time_error = true;
128                      })
129                  .finally(function() {
130                    $scope.loading = false;
131                  });
132            },
133            function(errors) {
134              console.log(JSON.stringify(errors));
135              $scope.set_time_error = true;
136              $scope.loading = false;
137            });
138      };
139      $scope.refresh = function() {
140        $route.reload();
141      };
142
143      $scope.addNTPField = function() {
144        $scope.ntp.servers.push('');
145      };
146
147      $scope.removeNTPField = function(index) {
148        $scope.ntp.servers.splice(index, 1);
149      };
150
151      function setNTPServers() {
152        // Remove any empty strings from the array. Important because we add an
153        // empty string to the end so the user can add a new NTP server, if the
154        // user doesn't fill out the field, we don't want to add.
155        $scope.ntp.servers = $scope.ntp.servers.filter(Boolean);
156        // NTP servers does not allow an empty array, since we remove all empty
157        // strings above, could have an empty array. TODO: openbmc/openbmc#3240
158        if ($scope.ntp.servers.length == 0) {
159          $scope.ntp.servers.push('');
160        }
161        return APIUtils.setNTPServers($scope.ntp.servers);
162      }
163
164      function setTimeMode() {
165        return APIUtils.setTimeMode(
166            'xyz.openbmc_project.Time.Synchronization.Method.' +
167            $scope.time_mode);
168      }
169
170      function setTimeOwner() {
171        return APIUtils.setTimeOwner(
172            'xyz.openbmc_project.Time.Owner.Owners.' + $scope.time_owner);
173      }
174
175      function setBMCTime(time) {
176        // Add the separate date and time objects and convert to Epoch time in
177        // microseconds.
178        return APIUtils.setBMCTime(time);
179      }
180
181      function setHostTime(time) {
182        // Add the separate date and time objects and convert to Epoch time
183        // microseconds.
184        return APIUtils.setHostTime(time);
185      }
186    }
187  ]);
188})(angular);
189