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