blob: 2f4fd3d481897296717cab0ae7089f7d2973cea4 [file] [log] [blame]
Iftekharul Islamcd789502017-04-19 14:37:55 -05001/**
2 * Controller for date-time
3 *
4 * @module app/configuration
5 * @exports dateTimeController
6 * @name dateTimeController
Iftekharul Islamcd789502017-04-19 14:37:55 -05007 */
8
Andrew Geisslerba5e3f32018-05-24 10:58:00 -07009window.angular && (function(angular) {
10 'use strict';
Iftekharul Islamcd789502017-04-19 14:37:55 -050011
Andrew Geisslerd27bb132018-05-24 11:07:27 -070012 angular.module('app.configuration').controller('dateTimeController', [
beccabroek27ce84d2019-02-05 15:43:17 -060013 '$scope', '$window', 'APIUtils', '$route', '$q', 'toastService',
14 function($scope, $window, APIUtils, $route, $q, toastService) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050015 $scope.bmc = {};
Gunnar Millseab32132018-09-27 10:07:17 -050016 // Only used when the owner is "Split"
Gunnar Millsb7ea2792018-07-18 13:01:48 -050017 $scope.host = {};
18 $scope.ntp = {servers: []};
Gunnar Mills2f955bd2018-10-13 16:56:10 -050019 $scope.time = {mode: '', owner: ''};
20 // Possible time owners
21 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Time/Owner.interface.yaml#L13
22 $scope.timeOwners = ['BMC', 'Host', 'Both', 'Split'];
Gunnar Mills7de38662018-07-18 13:01:48 -050023 $scope.loading = true;
Gunnar Mills2f955bd2018-10-13 16:56:10 -050024 var timePath = '/xyz/openbmc_project/time/';
Gunnar Mills7de38662018-07-18 13:01:48 -050025
Gunnar Millsc74d4342018-07-18 14:52:02 -050026 var getTimePromise = APIUtils.getTime().then(
Gunnar Mills7de38662018-07-18 13:01:48 -050027 function(data) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050028 // The time is returned as Epoch microseconds convert to
29 // milliseconds.
Gunnar Mills2f955bd2018-10-13 16:56:10 -050030 if (data.data[timePath + 'bmc'] &&
31 data.data[timePath + 'bmc'].hasOwnProperty('Elapsed')) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050032 $scope.bmc.date =
Gunnar Mills2f955bd2018-10-13 16:56:10 -050033 new Date(data.data[timePath + 'bmc'].Elapsed / 1000);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050034 // Don't care about milliseconds and don't want them displayed
35 $scope.bmc.date.setMilliseconds(0);
Alexander Filippovdbf04812018-11-16 16:26:04 +030036
37 // Examples:
38 // Central Standard Time (UTC-06:00)
39 // Moscow Standard Time (UTC+03:00)
40 $scope.bmc.timezone = getUserTimezone($scope.bmc.date) + ' ' +
41 createOffset($scope.bmc.date);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050042 }
Gunnar Mills2f955bd2018-10-13 16:56:10 -050043 if (data.data[timePath + 'host'] &&
44 data.data[timePath + 'host'].hasOwnProperty('Elapsed')) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050045 $scope.host.date =
Gunnar Mills2f955bd2018-10-13 16:56:10 -050046 new Date(data.data[timePath + 'host'].Elapsed / 1000);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050047 $scope.host.date.setMilliseconds(0);
Alexander Filippovdbf04812018-11-16 16:26:04 +030048 $scope.host.timezone = getUserTimezone($scope.bmc.date) + ' ' +
49 createOffset($scope.bmc.date);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050050 }
Gunnar Mills2f955bd2018-10-13 16:56:10 -050051 if (data.data[timePath + 'owner'] &&
52 data.data[timePath + 'owner'].hasOwnProperty('TimeOwner')) {
53 $scope.time.owner =
54 data.data[timePath + 'owner'].TimeOwner.split('.').pop();
Gunnar Millsb7ea2792018-07-18 13:01:48 -050055 }
Gunnar Mills2f955bd2018-10-13 16:56:10 -050056 if (data.data[timePath + 'sync_method'] &&
57 data.data[timePath + 'sync_method'].hasOwnProperty(
Gunnar Millsb7ea2792018-07-18 13:01:48 -050058 'TimeSyncMethod')) {
Gunnar Mills2f955bd2018-10-13 16:56:10 -050059 $scope.time.mode = data.data[timePath + 'sync_method']
Gunnar Millsb7ea2792018-07-18 13:01:48 -050060 .TimeSyncMethod.split('.')
61 .pop();
62 }
Gunnar Mills7de38662018-07-18 13:01:48 -050063 },
64 function(error) {
65 console.log(JSON.stringify(error));
66 });
67
Gunnar Millsb7ea2792018-07-18 13:01:48 -050068 var getNTPPromise = APIUtils.getNTPServers().then(
69 function(data) {
70 $scope.ntp.servers = data.data;
71 },
72 function(error) {
73 console.log(JSON.stringify(error));
74 });
75
76 var promises = [
77 getTimePromise,
78 getNTPPromise,
79 ];
80
81 $q.all(promises).finally(function() {
Gunnar Mills7de38662018-07-18 13:01:48 -050082 $scope.loading = false;
83 });
Gunnar Millsb7ea2792018-07-18 13:01:48 -050084
85 $scope.setTime = function() {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050086 $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 = [];
Gunnar Mills2f955bd2018-10-13 16:56:10 -050095 if ($scope.time.mode == 'Manual') {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050096 // 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
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500100 if ($scope.time.owner != 'Host') {
Gunnar Millseab32132018-09-27 10:07:17 -0500101 manual_promises.push(
102 setBMCTime($scope.bmc.date.getTime() * 1000));
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500103 }
Gunnar Millseab32132018-09-27 10:07:17 -0500104 // Even though we are setting Host time, we are setting from
105 // the BMC date and time fields labeled "BMC and Host Time"
106 // currently.
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500107 if ($scope.time.owner == 'Host') {
Gunnar Millseab32132018-09-27 10:07:17 -0500108 manual_promises.push(
109 setHostTime($scope.bmc.date.getTime() * 1000));
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500110 }
111 }
Gunnar Millseab32132018-09-27 10:07:17 -0500112 // Set the Host if Split even if NTP. In split mode, the host has
113 // its own date and time field. Set from it.
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500114 if ($scope.time.owner == 'Split') {
Gunnar Millseab32132018-09-27 10:07:17 -0500115 manual_promises.push(
116 setHostTime($scope.host.date.getTime() * 1000));
Gunnar Millsf378c772018-09-27 08:53:07 -0500117 }
118
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500119 $q.all(manual_promises)
120 .then(
121 function() {
beccabroek27ce84d2019-02-05 15:43:17 -0600122 toastService.success('Date and time settings saved');
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500123 },
124 function(errors) {
125 console.log(JSON.stringify(errors));
beccabroek27ce84d2019-02-05 15:43:17 -0600126 toastService.error(
beccabroek30444c62019-01-10 15:27:03 -0600127 'Date and time settings could not be saved');
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500128 })
129 .finally(function() {
130 $scope.loading = false;
131 });
132 },
133 function(errors) {
134 console.log(JSON.stringify(errors));
beccabroek27ce84d2019-02-05 15:43:17 -0600135 toastService.error('Date and time settings could not be saved');
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500136 $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
Gunnar Mills90121f32018-09-16 21:22:45 -0500147 $scope.removeNTPField = function(index) {
148 $scope.ntp.servers.splice(index, 1);
149 };
150
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500151 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.' +
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500167 $scope.time.mode);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500168 }
169
170 function setTimeOwner() {
171 return APIUtils.setTimeOwner(
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500172 'xyz.openbmc_project.Time.Owner.Owners.' + $scope.time.owner);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500173 }
174
Gunnar Millseab32132018-09-27 10:07:17 -0500175 function setBMCTime(time) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500176 // Add the separate date and time objects and convert to Epoch time in
177 // microseconds.
Gunnar Millseab32132018-09-27 10:07:17 -0500178 return APIUtils.setBMCTime(time);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500179 }
180
Gunnar Millseab32132018-09-27 10:07:17 -0500181 function setHostTime(time) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500182 // Add the separate date and time objects and convert to Epoch time
183 // microseconds.
Gunnar Millseab32132018-09-27 10:07:17 -0500184 return APIUtils.setHostTime(time);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500185 }
beccabroek569ccf62018-10-29 13:46:53 -0500186 function createOffset(date) {
187 // https://stackoverflow.com/questions/9149556/how-to-get-utc-offset-in-javascript-analog-of-timezoneinfo-getutcoffset-in-c
188 var sign = (date.getTimezoneOffset() > 0) ? '-' : '+';
189 var offset = Math.abs(date.getTimezoneOffset());
190 var hours = pad(Math.floor(offset / 60));
191 var minutes = pad(offset % 60);
192 return '(UTC' + sign + hours + ':' + minutes + ')';
193 }
Alexander Filippovdbf04812018-11-16 16:26:04 +0300194 function getUserTimezone(date) {
195 const ro = Intl.DateTimeFormat().resolvedOptions();
196 // A safe, easy way to get the timezone (e.g. Central Standard Time) is
197 // to subtract the time string without a timezone from the time string
198 // with a timezone.
199 // Hardcoded to 'en-US' so all timezones are displayed in English
200 // (e.g. Moscow Standard Time).
201 var ret = date.toLocaleTimeString('en-US', {timeZoneName: 'long'})
202 .replace(date.toLocaleTimeString('en-US'), '')
203 .trim();
204 // Do not return GMT+/-offset.
205 if (ret.indexOf('GMT') >= 0) {
206 return '';
207 }
208 return ret;
209 }
beccabroek569ccf62018-10-29 13:46:53 -0500210 function pad(value) {
211 return value < 10 ? '0' + value : value;
212 }
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700213 }
214 ]);
Iftekharul Islamcd789502017-04-19 14:37:55 -0500215})(angular);