From 033025f33dd0872c2d23f06c471fd5278c7ddd41 Mon Sep 17 00:00:00 2001 From: Gunnar Mills Date: Tue, 6 Mar 2018 14:49:40 -0600 Subject: Update the GUI after an image activated When activating an image the firmware page does not refresh after the image is activated and show the image as "Active". To get the image to show as "Active", a user must refresh the page. The activating image code now waits until the image is activated and the REST call returns "Active" or "Failed" and then refreshes the page. Resolves openbmc/openbmc#2966 Tested: Activated an image and verfied it refreshed after "Active". Change-Id: Ic68e3c9e6cb5c2ea4f5d66f48fd09252c4807f26 Signed-off-by: Gunnar Mills --- app/common/services/api-utils.js | 13 ++++ app/common/services/constants.js | 6 ++ .../controllers/firmware-controller.js | 71 +++++++++++++++++----- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js index 980f1a2..c20b2ca 100644 --- a/app/common/services/api-utils.js +++ b/app/common/services/api-utils.js @@ -634,6 +634,19 @@ window.angular && (function (angular) { console.log(error); }); }, + getActivation: function(imageId){ + return $http({ + method: 'GET', + url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/attr/Activation", + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + withCredentials: true + }).then(function(response){ + return response.data; + }); + }, getFirmwares: function(){ var deferred = $q.defer(); $http({ diff --git a/app/common/services/constants.js b/app/common/services/constants.js index 57e2e19..af0965d 100644 --- a/app/common/services/constants.js +++ b/app/common/services/constants.js @@ -110,6 +110,12 @@ window.angular && (function (angular) { ACTIVATE_FIRMWARE: 'xyz.openbmc_project.Software.Activation.RequestedActivations.Active', FUNCTIONAL_OBJPATH: '/xyz/openbmc_project/software/functional' }, + POLL_INTERVALS: { + ACTIVATION: 5000 + }, + TIMEOUT: { + ACTIVATION: 1000 * 60 * 10, // 10 mins + }, MESSAGES: { SENSOR: { NO_SENSOR_DATA: 'There are no sensors found.', diff --git a/app/configuration/controllers/firmware-controller.js b/app/configuration/controllers/firmware-controller.js index b9a87b7..8fe0e83 100644 --- a/app/configuration/controllers/firmware-controller.js +++ b/app/configuration/controllers/firmware-controller.js @@ -20,7 +20,9 @@ window.angular && (function (angular) { '$location', '$anchorScroll', 'Constants', - function ($scope, $window, APIUtils, dataService, $location, $anchorScroll, Constants) { + '$interval', + '$q', + function ($scope, $window, APIUtils, dataService, $location, $anchorScroll, Constants, $interval, $q) { $scope.dataService = dataService; //Scroll to target anchor @@ -47,6 +49,8 @@ window.angular && (function (angular) { $scope.file_empty = true; $scope.uploading = false; + var pollActivationTimer = undefined; + $scope.error = { modal_title: "", title: "", @@ -66,22 +70,58 @@ window.angular && (function (angular) { $scope.display_error = true; } + function waitForActive(imageId){ + var deferred = $q.defer(); + var startTime = new Date(); + pollActivationTimer = $interval(function(){ + APIUtils.getActivation(imageId).then(function(state){ + //@TODO: display an error message if image "Failed" + if(((/\.Active$/).test(state.data)) || ((/\.Failed$/).test(state.data))){ + $interval.cancel(pollActivationTimer); + pollActivationTimer = undefined; + deferred.resolve(state); + } + }, function(error){ + $interval.cancel(pollActivationTimer); + pollActivationTimer = undefined; + console.log(error); + deferred.reject(error); + }); + var now = new Date(); + if((now.getTime() - startTime.getTime()) >= Constants.TIMEOUT.ACTIVATION){ + $interval.cancel(pollActivationTimer); + pollActivationTimer = undefined; + console.log("Time out activating image, " + imageId); + deferred.reject("Time out. Image did not activate in allotted time."); + } + }, Constants.POLL_INTERVALS.ACTIVATION); + return deferred.promise; + } + $scope.activateConfirmed = function(){ - $scope.uploading = true; - APIUtils.activateImage($scope.activate_image_id).then(function(response){ - $scope.uploading = false; - if(response.status == 'error'){ - $scope.displayError({ - modal_title: response.data.description, - title: response.data.description, - desc: response.data.exception, - type: 'Error' - }); - }else{ - $scope.loadFirmwares(); - } + APIUtils.activateImage($scope.activate_image_id).then(function(state){ + $scope.loadFirmwares(); + return state; + }, function(error){ + $scope.displayError({ + modal_title: 'Error during activation call', + title: 'Error during activation call', + desc: JSON.stringify(error.data), + type: 'Error' + }); + }).then(function(activationState){ + waitForActive($scope.activate_image_id).then(function(state){ + $scope.loadFirmwares(); + }, function(error){ + $scope.displayError({ + modal_title: 'Error during image activation', + title: 'Error during image activation', + desc: JSON.stringify(error.data), + type: 'Error' + }); }); - $scope.activate_confirm = false; + }); + $scope.activate_confirm = false; } $scope.upload = function(){ @@ -188,7 +228,6 @@ window.angular && (function (angular) { $scope.file_empty = false; } - $scope.uploading = false; $scope.filters = { bmc: { imageType: 'BMC' -- cgit v1.2.1