blob: a08a141155083b09f1edc2ab52800e3762ed6482 [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', [
Gunnar Millsb7ea2792018-07-18 13:01:48 -050013 '$scope', '$window', 'APIUtils', '$route', '$q',
14 function($scope, $window, APIUtils, $route, $q) {
15 $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'];
23 $scope.error = false;
24 $scope.success = false;
Gunnar Mills7de38662018-07-18 13:01:48 -050025 $scope.loading = true;
Gunnar Mills2f955bd2018-10-13 16:56:10 -050026 var timePath = '/xyz/openbmc_project/time/';
Gunnar Mills7de38662018-07-18 13:01:48 -050027
Gunnar Millsc74d4342018-07-18 14:52:02 -050028 var getTimePromise = APIUtils.getTime().then(
Gunnar Mills7de38662018-07-18 13:01:48 -050029 function(data) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050030 // The time is returned as Epoch microseconds convert to
31 // milliseconds.
Gunnar Mills2f955bd2018-10-13 16:56:10 -050032 if (data.data[timePath + 'bmc'] &&
33 data.data[timePath + 'bmc'].hasOwnProperty('Elapsed')) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050034 $scope.bmc.date =
Gunnar Mills2f955bd2018-10-13 16:56:10 -050035 new Date(data.data[timePath + 'bmc'].Elapsed / 1000);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050036 // Don't care about milliseconds and don't want them displayed
37 $scope.bmc.date.setMilliseconds(0);
Alexander Filippovdbf04812018-11-16 16:26:04 +030038
39 // Examples:
40 // Central Standard Time (UTC-06:00)
41 // Moscow Standard Time (UTC+03:00)
42 $scope.bmc.timezone = getUserTimezone($scope.bmc.date) + ' ' +
43 createOffset($scope.bmc.date);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050044 }
Gunnar Mills2f955bd2018-10-13 16:56:10 -050045 if (data.data[timePath + 'host'] &&
46 data.data[timePath + 'host'].hasOwnProperty('Elapsed')) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -050047 $scope.host.date =
Gunnar Mills2f955bd2018-10-13 16:56:10 -050048 new Date(data.data[timePath + 'host'].Elapsed / 1000);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050049 $scope.host.date.setMilliseconds(0);
Alexander Filippovdbf04812018-11-16 16:26:04 +030050 $scope.host.timezone = getUserTimezone($scope.bmc.date) + ' ' +
51 createOffset($scope.bmc.date);
Gunnar Millsb7ea2792018-07-18 13:01:48 -050052 }
Gunnar Mills2f955bd2018-10-13 16:56:10 -050053 if (data.data[timePath + 'owner'] &&
54 data.data[timePath + 'owner'].hasOwnProperty('TimeOwner')) {
55 $scope.time.owner =
56 data.data[timePath + 'owner'].TimeOwner.split('.').pop();
Gunnar Millsb7ea2792018-07-18 13:01:48 -050057 }
Gunnar Mills2f955bd2018-10-13 16:56:10 -050058 if (data.data[timePath + 'sync_method'] &&
59 data.data[timePath + 'sync_method'].hasOwnProperty(
Gunnar Millsb7ea2792018-07-18 13:01:48 -050060 'TimeSyncMethod')) {
Gunnar Mills2f955bd2018-10-13 16:56:10 -050061 $scope.time.mode = data.data[timePath + 'sync_method']
Gunnar Millsb7ea2792018-07-18 13:01:48 -050062 .TimeSyncMethod.split('.')
63 .pop();
64 }
Gunnar Mills7de38662018-07-18 13:01:48 -050065 },
66 function(error) {
67 console.log(JSON.stringify(error));
68 });
69
Gunnar Millsb7ea2792018-07-18 13:01:48 -050070 var getNTPPromise = APIUtils.getNTPServers().then(
71 function(data) {
72 $scope.ntp.servers = data.data;
73 },
74 function(error) {
75 console.log(JSON.stringify(error));
76 });
77
78 var promises = [
79 getTimePromise,
80 getNTPPromise,
81 ];
82
83 $q.all(promises).finally(function() {
Gunnar Mills7de38662018-07-18 13:01:48 -050084 $scope.loading = false;
85 });
Gunnar Millsb7ea2792018-07-18 13:01:48 -050086
87 $scope.setTime = function() {
Gunnar Mills2f955bd2018-10-13 16:56:10 -050088 $scope.error = false;
89 $scope.success = false;
Gunnar Millsb7ea2792018-07-18 13:01:48 -050090 $scope.loading = true;
91 var promises = [setTimeMode(), setTimeOwner(), setNTPServers()];
92
93 $q.all(promises).then(
94 function() {
95 // Have to set the time mode and time owner first to avoid a
96 // insufficient permissions if the time mode or time owner had
97 // changed.
98 var manual_promises = [];
Gunnar Mills2f955bd2018-10-13 16:56:10 -050099 if ($scope.time.mode == 'Manual') {
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500100 // If owner is 'Split' set both.
101 // If owner is 'Host' set only it.
102 // Else set BMC only. See:
103 // https://github.com/openbmc/phosphor-time-manager/blob/master/README.md
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500104 if ($scope.time.owner != 'Host') {
Gunnar Millseab32132018-09-27 10:07:17 -0500105 manual_promises.push(
106 setBMCTime($scope.bmc.date.getTime() * 1000));
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500107 }
Gunnar Millseab32132018-09-27 10:07:17 -0500108 // Even though we are setting Host time, we are setting from
109 // the BMC date and time fields labeled "BMC and Host Time"
110 // currently.
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500111 if ($scope.time.owner == 'Host') {
Gunnar Millseab32132018-09-27 10:07:17 -0500112 manual_promises.push(
113 setHostTime($scope.bmc.date.getTime() * 1000));
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500114 }
115 }
Gunnar Millseab32132018-09-27 10:07:17 -0500116 // Set the Host if Split even if NTP. In split mode, the host has
117 // its own date and time field. Set from it.
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500118 if ($scope.time.owner == 'Split') {
Gunnar Millseab32132018-09-27 10:07:17 -0500119 manual_promises.push(
120 setHostTime($scope.host.date.getTime() * 1000));
Gunnar Millsf378c772018-09-27 08:53:07 -0500121 }
122
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500123 $q.all(manual_promises)
124 .then(
125 function() {
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500126 $scope.success = true;
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500127 },
128 function(errors) {
129 console.log(JSON.stringify(errors));
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500130 $scope.error = true;
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500131 })
132 .finally(function() {
133 $scope.loading = false;
134 });
135 },
136 function(errors) {
137 console.log(JSON.stringify(errors));
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500138 $scope.error = true;
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500139 $scope.loading = false;
140 });
141 };
142 $scope.refresh = function() {
143 $route.reload();
144 };
145
146 $scope.addNTPField = function() {
147 $scope.ntp.servers.push('');
148 };
149
Gunnar Mills90121f32018-09-16 21:22:45 -0500150 $scope.removeNTPField = function(index) {
151 $scope.ntp.servers.splice(index, 1);
152 };
153
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500154 function setNTPServers() {
155 // Remove any empty strings from the array. Important because we add an
156 // empty string to the end so the user can add a new NTP server, if the
157 // user doesn't fill out the field, we don't want to add.
158 $scope.ntp.servers = $scope.ntp.servers.filter(Boolean);
159 // NTP servers does not allow an empty array, since we remove all empty
160 // strings above, could have an empty array. TODO: openbmc/openbmc#3240
161 if ($scope.ntp.servers.length == 0) {
162 $scope.ntp.servers.push('');
163 }
164 return APIUtils.setNTPServers($scope.ntp.servers);
165 }
166
167 function setTimeMode() {
168 return APIUtils.setTimeMode(
169 'xyz.openbmc_project.Time.Synchronization.Method.' +
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500170 $scope.time.mode);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500171 }
172
173 function setTimeOwner() {
174 return APIUtils.setTimeOwner(
Gunnar Mills2f955bd2018-10-13 16:56:10 -0500175 'xyz.openbmc_project.Time.Owner.Owners.' + $scope.time.owner);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500176 }
177
Gunnar Millseab32132018-09-27 10:07:17 -0500178 function setBMCTime(time) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500179 // Add the separate date and time objects and convert to Epoch time in
180 // microseconds.
Gunnar Millseab32132018-09-27 10:07:17 -0500181 return APIUtils.setBMCTime(time);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500182 }
183
Gunnar Millseab32132018-09-27 10:07:17 -0500184 function setHostTime(time) {
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500185 // Add the separate date and time objects and convert to Epoch time
186 // microseconds.
Gunnar Millseab32132018-09-27 10:07:17 -0500187 return APIUtils.setHostTime(time);
Gunnar Millsb7ea2792018-07-18 13:01:48 -0500188 }
beccabroek569ccf62018-10-29 13:46:53 -0500189 function createOffset(date) {
190 // https://stackoverflow.com/questions/9149556/how-to-get-utc-offset-in-javascript-analog-of-timezoneinfo-getutcoffset-in-c
191 var sign = (date.getTimezoneOffset() > 0) ? '-' : '+';
192 var offset = Math.abs(date.getTimezoneOffset());
193 var hours = pad(Math.floor(offset / 60));
194 var minutes = pad(offset % 60);
195 return '(UTC' + sign + hours + ':' + minutes + ')';
196 }
Alexander Filippovdbf04812018-11-16 16:26:04 +0300197 function getUserTimezone(date) {
198 const ro = Intl.DateTimeFormat().resolvedOptions();
199 // A safe, easy way to get the timezone (e.g. Central Standard Time) is
200 // to subtract the time string without a timezone from the time string
201 // with a timezone.
202 // Hardcoded to 'en-US' so all timezones are displayed in English
203 // (e.g. Moscow Standard Time).
204 var ret = date.toLocaleTimeString('en-US', {timeZoneName: 'long'})
205 .replace(date.toLocaleTimeString('en-US'), '')
206 .trim();
207 // Do not return GMT+/-offset.
208 if (ret.indexOf('GMT') >= 0) {
209 return '';
210 }
211 return ret;
212 }
beccabroek569ccf62018-10-29 13:46:53 -0500213 function pad(value) {
214 return value < 10 ? '0' + value : value;
215 }
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700216 }
217 ]);
Iftekharul Islamcd789502017-04-19 14:37:55 -0500218})(angular);