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