summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/common/directives/input.js19
-rw-r--r--app/common/services/api-utils.js100
-rw-r--r--app/configuration/controllers/date-time-controller.html84
-rw-r--r--app/configuration/controllers/date-time-controller.js161
-rw-r--r--app/configuration/controllers/network-controller.html2
-rw-r--r--app/configuration/controllers/network-controller.js15
-rw-r--r--app/configuration/styles/date-time.scss67
-rw-r--r--app/index.js1
8 files changed, 378 insertions, 71 deletions
diff --git a/app/common/directives/input.js b/app/common/directives/input.js
new file mode 100644
index 0000000..cb4d830
--- /dev/null
+++ b/app/common/directives/input.js
@@ -0,0 +1,19 @@
+window.angular && (function(angular) {
+ 'use strict';
+
+ angular.module('app.common.directives')
+ .directive('setFocusOnNewInput', function() {
+ return function(scope, element, attrs) {
+ var elem = window.document.getElementById(element[0].id);
+ // Focus on the newly created input.
+ // Since this directive is also called when initializing fields
+ // on a page load, need to determine if the call is from a page load
+ // or from the user pressing the "Add new" button. The easiest way to
+ // do this is to check if the field is empty, if it is we know this is
+ // a new field since all empty fields are removed from the array.
+ if (!scope[attrs.ngModel] && elem) {
+ elem.focus();
+ }
+ };
+ });
+})(window.angular);
diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
index 434ca2f..a9fb99a 100644
--- a/app/common/services/api-utils.js
+++ b/app/common/services/api-utils.js
@@ -1052,6 +1052,106 @@ window.angular && (function(angular) {
return response.data;
});
},
+ // Even though NTPServers is a network interface specific path
+ // (e.g. /xyz/openbmc_project/network/eth0/attr/NTPServers) it acts
+ // like a global setting. Just use eth0 for setting and getting the
+ // NTP Servers until it is moved to a non-network interface specific
+ // path like it is in Redfish. TODO: openbmc/phosphor-time-manager#4
+ getNTPServers: function() {
+ return $http({
+ method: 'GET',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/network/eth0/attr/NTPServers',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ withCredentials: true
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ },
+ setNTPServers: function(ntpServers) {
+ return $http({
+ method: 'PUT',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/network/eth0/attr/NTPServers',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ withCredentials: true,
+ data: JSON.stringify({'data': ntpServers})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ },
+ setTimeMode: function(timeMode) {
+ return $http({
+ method: 'PUT',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/time/sync_method/attr/TimeSyncMethod',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ withCredentials: true,
+ data: JSON.stringify({'data': timeMode})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ },
+ setTimeOwner: function(timeOwner) {
+ return $http({
+ method: 'PUT',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/time/owner/attr/TimeOwner',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ withCredentials: true,
+ data: JSON.stringify({'data': timeOwner})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ },
+ setBMCTime: function(time) {
+ return $http({
+ method: 'PUT',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/time/bmc/attr/Elapsed',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ withCredentials: true,
+ data: JSON.stringify({'data': time})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ },
+ setHostTime: function(time) {
+ return $http({
+ method: 'PUT',
+ url: DataService.getHost() +
+ '/xyz/openbmc_project/time/host/attr/Elapsed',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ withCredentials: true,
+ data: JSON.stringify({'data': time})
+ })
+ .then(function(response) {
+ return response.data;
+ });
+ },
getHardwares: function(callback) {
$http({
method: 'GET',
diff --git a/app/configuration/controllers/date-time-controller.html b/app/configuration/controllers/date-time-controller.html
index a64a001..491ab56 100644
--- a/app/configuration/controllers/date-time-controller.html
+++ b/app/configuration/controllers/date-time-controller.html
@@ -1,31 +1,65 @@
<loader loading="loading"></loader>
<div id="configuration-date-time">
<div class="row column">
- <h1>Date time settings</h1>
+ <h1>Date and time settings</h1>
</div>
- <div class="page-header">
- <h2 class="bold h4">Time information</h2>
- </div>
- <fieldset>
- <div class="column large-8">
- <ul class="date-time__metadata-wrapper">
- <li class="date-time__metadata-block">
- <p class="content-label">BMC <span ng-if="time_owner != 'Split'">and Host</span> Time</p>
- <p class="courier-bold">{{bmc_time | date:'medium'}}</p>
- </li>
- <li class="date-time__metadata-block" ng-if="time_owner == 'Split'">
- <p class="content-label">Host Time</p>
- <p class="courier-bold">{{host_time | date:'medium'}}</p>
- </li>
- <li class="date-time__metadata-block">
- <p class="content-label">Time Owner</p>
- <p class="courier-bold">{{time_owner}}</p>
- </li>
- <li class="date-time__metadata-block">
- <p class="content-label">Time Mode</p>
- <p class="courier-bold">{{time_mode}}</p>
- </li>
- </ul>
+ <form class="time__form" role="form" action="">
+ <div class="page-header">
+ <h2 class="bold h4">Date and time set to Network Time Protocol (NTP) or manually</h2>
+ </div>
+ <fieldset>
+ <div class="column large-8">
+ <div class="row column">
+ <label class="control-radio" for="ntp-time">Obtain Automatically from a Network Time Protocol (NTP) Server
+ <input type="radio" id="ntp-time" ng-model="time_mode" value="NTP">
+ <span class="control__indicator control__indicator-on"></span>
+ </label>
+ </div>
+ <div class="row column date-time__ntp-servers-wrap">
+ <fieldset class="date-time__ntp-servers" ng-repeat="server in ntp.servers track by $index">
+ <label for="ntp-server{{$index+1}}">NTP Server Address {{$index+1}}</label>
+ <input id="ntp-server{{$index+1}}" type="text" ng-readonly="time_mode != 'NTP'" ng-model="server" ng-blur="ntp.servers[$index] = server" set-focus-on-new-input/>
+ </fieldset>
+ <button type="button" class="btn-primary inline" ng-click="addNTPField()">Add new NTP server</button>
+ </div>
+ <div class="row column">
+ <label class="control-radio" for="manual-time">Manually set date and time
+ <input type="radio" id="manual-time" ng-model="time_mode" value="Manual"/>
+ <span class="control__indicator control__indicator-on"></span>
+ </label>
+ </div>
+ <ul class="date-time__metadata-wrapper">
+ <li class="date-time__metadata-block">
+ <p class="content-label">BMC <span ng-if="time_owner != 'Split'">and Host</span> Time</p>
+ <div class="inline">
+ <input type="date" ng-model="bmc.date" ng-readonly="time_mode == 'NTP'" min="2018-01-01" max="2099-12-31"/>
+ <input type="time" ng-model="bmc.date" ng-readonly="time_mode == 'NTP'" />
+ <p class="courier-bold">{{bmc.timezone}}</p>
+ </div>
+ </li>
+ <li class="date-time__metadata-block" ng-if="time_owner == 'Split'">
+ <p class="content-label">Host Time</p>
+ <div class="inline">
+ <!--- Ideally, would just use one input, datetime-local, but datetime-local is not supported on Firefox.--->
+ <input type="date" ng-model="host.date" min="2018-01-01" max="2099-12-31"/>
+ <input type="time" ng-model="host.date"/>
+ <p class="courier-bold">{{host.timezone}}</p>
+ </div>
+ </li>
+ <li class="date-time__metadata-block">
+ <label class="content-label">Time Owner</label>
+ <select ng-model="time_owner" class="date-time__owner-dropdown">
+ <option class="courier-bold" ng-repeat="owner in time_owners">{{owner}}</option>
+ </select>
+ </li>
+ </ul>
+ </div>
+ </fieldset>
+ <div class="time__submit-wrapper">
+ <button type="button" class="btn-primary inline" ng-click="setTime()">Save settings</button>
+ <button type="button" class="btn-secondary inline" ng-click="refresh()">Cancel</button>
</div>
- </fieldset>
+ <p class="success-msg" ng-show="set_time_success" role="alert">Success! Time changed!</p>
+ <p class="set_time_error error-msg" ng-show="set_time_error" role="alert">Error setting time!</p>
+ </form>
</div>
diff --git a/app/configuration/controllers/date-time-controller.js b/app/configuration/controllers/date-time-controller.js
index cbc7443..02752fe 100644
--- a/app/configuration/controllers/date-time-controller.js
+++ b/app/configuration/controllers/date-time-controller.js
@@ -10,35 +10,164 @@ window.angular && (function(angular) {
'use strict';
angular.module('app.configuration').controller('dateTimeController', [
- '$scope', '$window', 'APIUtils',
- function($scope, $window, APIUtils) {
- $scope.bmc_time = '';
+ '$scope', '$window', 'APIUtils', '$route', '$q',
+ function($scope, $window, APIUtils, $route, $q) {
+ $scope.bmc = {};
+ $scope.host = {};
+ $scope.ntp = {servers: []};
$scope.time_mode = '';
$scope.time_owner = '';
+ $scope.time_owners = ['BMC', 'Host', 'Both', 'Split'];
+ $scope.set_time_error = false;
+ $scope.set_time_success = false;
$scope.loading = true;
+ var time_path = '/xyz/openbmc_project/time/';
var getTimePromise = APIUtils.getTime().then(
function(data) {
- $scope.bmc_time =
- data.data['/xyz/openbmc_project/time/bmc'].Elapsed / 1000;
- $scope.host_time =
- data.data['/xyz/openbmc_project/time/host'].Elapsed / 1000;
-
- $scope.time_owner = data.data['/xyz/openbmc_project/time/owner']
- .TimeOwner.split('.')
- .pop();
- $scope.time_mode =
- data.data['/xyz/openbmc_project/time/sync_method']
- .TimeSyncMethod.split('.')
- .pop();
+ // The time is returned as Epoch microseconds convert to
+ // milliseconds.
+ if (data.data[time_path + 'bmc'] &&
+ data.data[time_path + 'bmc'].hasOwnProperty('Elapsed')) {
+ $scope.bmc.date =
+ new Date(data.data[time_path + 'bmc'].Elapsed / 1000);
+ // Don't care about milliseconds and don't want them displayed
+ $scope.bmc.date.setMilliseconds(0);
+ // https://stackoverflow.com/questions/1091372/getting-the-clients-timezone-in-javascript
+ // GMT-0400 (EDT)
+ $scope.bmc.timezone =
+ $scope.bmc.date.toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1];
+ }
+ if (data.data[time_path + 'host'] &&
+ data.data[time_path + 'host'].hasOwnProperty('Elapsed')) {
+ $scope.host.date =
+ new Date(data.data[time_path + 'host'].Elapsed / 1000);
+ $scope.host.date.setMilliseconds(0);
+ $scope.host.timezone =
+ $scope.host.date.toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1];
+ }
+ if (data.data[time_path + 'owner'] &&
+ data.data[time_path + 'owner'].hasOwnProperty('TimeOwner')) {
+ $scope.time_owner =
+ data.data[time_path + 'owner'].TimeOwner.split('.').pop();
+ }
+ if (data.data[time_path + 'sync_method'] &&
+ data.data[time_path + 'sync_method'].hasOwnProperty(
+ 'TimeSyncMethod')) {
+ $scope.time_mode = data.data[time_path + 'sync_method']
+ .TimeSyncMethod.split('.')
+ .pop();
+ }
},
function(error) {
console.log(JSON.stringify(error));
});
- getTimePromise.finally(function() {
+ var getNTPPromise = APIUtils.getNTPServers().then(
+ function(data) {
+ $scope.ntp.servers = data.data;
+ },
+ function(error) {
+ console.log(JSON.stringify(error));
+ });
+
+ var promises = [
+ getTimePromise,
+ getNTPPromise,
+ ];
+
+ $q.all(promises).finally(function() {
$scope.loading = false;
});
+
+ $scope.setTime = function() {
+ $scope.set_time_error = false;
+ $scope.set_time_success = false;
+ $scope.loading = true;
+ var promises = [setTimeMode(), setTimeOwner(), setNTPServers()];
+
+ $q.all(promises).then(
+ function() {
+ // Have to set the time mode and time owner first to avoid a
+ // insufficient permissions if the time mode or time owner had
+ // changed.
+ var manual_promises = [];
+ if ($scope.time_mode == 'Manual') {
+ // If owner is 'Split' set both.
+ // If owner is 'Host' set only it.
+ // Else set BMC only. See:
+ // https://github.com/openbmc/phosphor-time-manager/blob/master/README.md
+ if ($scope.time_owner != 'Host') {
+ manual_promises.push(setBMCTime());
+ }
+
+ if ($scope.time_owner == 'Host' ||
+ $scope.time_owner == 'Split') {
+ manual_promises.push(setHostTime());
+ }
+ }
+ $q.all(manual_promises)
+ .then(
+ function() {
+ $scope.set_time_success = true;
+ },
+ function(errors) {
+ console.log(JSON.stringify(errors));
+ $scope.set_time_error = true;
+ })
+ .finally(function() {
+ $scope.loading = false;
+ });
+ },
+ function(errors) {
+ console.log(JSON.stringify(errors));
+ $scope.set_time_error = true;
+ $scope.loading = false;
+ });
+ };
+ $scope.refresh = function() {
+ $route.reload();
+ };
+
+ $scope.addNTPField = function() {
+ $scope.ntp.servers.push('');
+ };
+
+ function setNTPServers() {
+ // Remove any empty strings from the array. Important because we add an
+ // empty string to the end so the user can add a new NTP server, if the
+ // user doesn't fill out the field, we don't want to add.
+ $scope.ntp.servers = $scope.ntp.servers.filter(Boolean);
+ // NTP servers does not allow an empty array, since we remove all empty
+ // strings above, could have an empty array. TODO: openbmc/openbmc#3240
+ if ($scope.ntp.servers.length == 0) {
+ $scope.ntp.servers.push('');
+ }
+ return APIUtils.setNTPServers($scope.ntp.servers);
+ }
+
+ function setTimeMode() {
+ return APIUtils.setTimeMode(
+ 'xyz.openbmc_project.Time.Synchronization.Method.' +
+ $scope.time_mode);
+ }
+
+ function setTimeOwner() {
+ return APIUtils.setTimeOwner(
+ 'xyz.openbmc_project.Time.Owner.Owners.' + $scope.time_owner);
+ }
+
+ function setBMCTime() {
+ // Add the separate date and time objects and convert to Epoch time in
+ // microseconds.
+ return APIUtils.setBMCTime($scope.bmc.date.getTime() * 1000);
+ }
+
+ function setHostTime() {
+ // Add the separate date and time objects and convert to Epoch time
+ // microseconds.
+ return APIUtils.setHostTime($scope.host.date.getTime() * 1000);
+ }
}
]);
})(angular);
diff --git a/app/configuration/controllers/network-controller.html b/app/configuration/controllers/network-controller.html
index 1dd92eb..4bc210a 100644
--- a/app/configuration/controllers/network-controller.html
+++ b/app/configuration/controllers/network-controller.html
@@ -77,7 +77,7 @@
<!-- Call Nameservers "DNS Servers" on the GUI -->
<fieldset class="net-config__static-ip-wrap" ng-repeat="dns in interface.Nameservers track by $index">
<label for="net-config__prime-dns{{$index+1}}">DNS Server {{$index+1}}</label>
- <input id="net-config__prime-dns{{$index+1}}" type="text" ng-model="dns" ng-blur="interface.Nameservers[$index] = dns" set-focus-dns-field/>
+ <input id="net-config__prime-dns{{$index+1}}" type="text" ng-model="dns" ng-blur="interface.Nameservers[$index] = dns" set-focus-on-new-input//>
</fieldset>
<button type="button" class="btn-primary inline" ng-click="addDNSField()">Add new DNS server</button>
</div>
diff --git a/app/configuration/controllers/network-controller.js b/app/configuration/controllers/network-controller.js
index 431b97e..9bec746 100644
--- a/app/configuration/controllers/network-controller.js
+++ b/app/configuration/controllers/network-controller.js
@@ -9,21 +9,6 @@
window.angular && (function(angular) {
'use strict';
- angular.module('app.configuration').directive('setFocusDnsField', function() {
- return function(scope, element, attrs) {
- var elem = window.document.getElementById(element[0].id);
- // Focus on the newly created DNS server field
- // Since this directive is also called when initializing DNS server fields
- // on a page load, need to determine if the call is from a page load or
- // from the user pressing the "Add new DNS server" button. The easiest way
- // to do this is to check if the field is empty, if it is we know
- // this is a new field since all empty fields are removed from the array.
- if (!scope[attrs.ngModel] && elem) {
- elem.focus();
- }
- };
- });
-
angular.module('app.configuration').controller('networkController', [
'$scope', '$window', 'APIUtils', 'dataService', '$timeout', '$route', '$q',
function($scope, $window, APIUtils, dataService, $timeout, $route, $q) {
diff --git a/app/configuration/styles/date-time.scss b/app/configuration/styles/date-time.scss
index 670e549..d5d9b40 100644
--- a/app/configuration/styles/date-time.scss
+++ b/app/configuration/styles/date-time.scss
@@ -1,19 +1,58 @@
// Date Time SCSS
+.time__form {
-.date-time__metadata-wrapper {
- margin: 0;
- padding: 0;
-}
+ input {
+ height: 2.1em;
+ margin-bottom: 0em;
+ }
-.date-time__metadata-block {
- list-style-type: none;
- width: 47%;
- margin-bottom: 1.8em;
- margin-right: .7em;
- display: inline-block;
- white-space: normal;
- word-break: break-all;
- @include mediaQuery(small) {
- float: left;
+ fieldset {
+ padding-left: 1.8em;
+ }
+
+ .date-time__metadata-wrapper {
+ margin: 0;
+ padding: 0;
+ }
+ .date-time__owner-dropdown {
+ width: 200px;
+ &:hover {
+ background: $dropdown__focus-bg;
+ }
+ }
+ .date-time__ntp-servers{
+ padding-bottom: .6em;
+ padding-top: .6em;
+ padding-left: 0em;
+ width: 300px;
+ }
+ .date-time__ntp-servers-wrap{
+ padding-bottom: 1em;
+ padding-top: 1em;
+ padding-left: 3em;
+ }
+ .date-time__metadata-block {
+ list-style-type: none;
+ width: 47%;
+ margin-bottom: .7em;
+ margin-top: 1.8em;
+ margin-right: .7em;
+ margin-left: 3em;
+ display: inline;
+ white-space: normal;
+ word-break: break-all;
+ @include mediaQuery(small) {
+ float: left;
+ }
+ }
+ .time__submit-wrapper {
+ width: 100%;
+ margin-top: 3em;
+ padding-top: 1em;
+ border-top: 1px solid $medgrey;
+ button {
+ float: right;
+ margin: .5em;
+ }
}
}
diff --git a/app/index.js b/app/index.js
index cde0296..602d601 100644
--- a/app/index.js
+++ b/app/index.js
@@ -47,6 +47,7 @@ import log_search_control from './common/directives/log-search-control.js';
import toggle_flag from './common/directives/toggle-flag.js';
import firmware_list from './common/directives/firmware-list.js';
import file from './common/directives/file.js';
+import input from './common/directives/input.js';
import loader from './common/directives/loader.js';
import paginate from './common/directives/paginate.js';
import serial_console from './common/directives/serial-console.js';
OpenPOWER on IntegriCloud