| /** |
| * Controller for firmware |
| * |
| * @module app/configuration |
| * @exports firmwareController |
| * @name firmwareController |
| */ |
| |
| window.angular && (function (angular) { |
| 'use strict'; |
| |
| angular |
| .module('app.configuration') |
| .controller('firmwareController', [ |
| '$scope', |
| '$window', |
| 'APIUtils', |
| 'dataService', |
| '$location', |
| '$anchorScroll', |
| 'Constants', |
| '$interval', |
| '$q', |
| '$timeout', |
| function ($scope, $window, APIUtils, dataService, $location, $anchorScroll, Constants, $interval, $q, $timeout) { |
| $scope.dataService = dataService; |
| |
| //Scroll to target anchor |
| $scope.gotoAnchor = function () { |
| $location.hash('upload'); |
| $anchorScroll(); |
| }; |
| |
| $scope.firmwares = []; |
| $scope.bmcActiveVersion = ""; |
| $scope.hostActiveVersion = ""; |
| $scope.display_error = false; |
| $scope.activate_confirm = false; |
| $scope.delete_image_id = ""; |
| $scope.delete_image_version = ""; |
| $scope.activate_image_id = ""; |
| $scope.activate_image_version = ""; |
| $scope.activate_image_type = ""; |
| $scope.priority_image_id = ""; |
| $scope.priority_image_version = ""; |
| $scope.priority_from = -1; |
| $scope.priority_to = -1; |
| $scope.confirm_priority = false; |
| $scope.file_empty = true; |
| $scope.uploading = false; |
| $scope.upload_success = false; |
| $scope.activate = { reboot: true }; |
| $scope.download_error_msg = ""; |
| $scope.download_success = false; |
| |
| var pollActivationTimer = undefined; |
| var pollDownloadTimer = undefined; |
| |
| $scope.error = { |
| modal_title: "", |
| title: "", |
| desc: "", |
| type: "warning" |
| }; |
| |
| $scope.activateImage = function(imageId, imageVersion, imageType){ |
| $scope.activate_image_id = imageId; |
| $scope.activate_image_version = imageVersion; |
| $scope.activate_image_type = imageType; |
| $scope.activate_confirm = true; |
| } |
| |
| $scope.displayError = function(data){ |
| $scope.error = data; |
| $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(){ |
| 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' |
| }); |
| }).then(function(state){ |
| // Only look at reboot if it's a BMC image |
| if($scope.activate.reboot && ($scope.activate_image_type == 'BMC')){ |
| // Despite the new image being active, issue, |
| // https://github.com/openbmc/openbmc/issues/2764, can cause a |
| // system to brick, if the system reboots before the service to set |
| // the U-Boot variables is complete. Wait 10 seconds before rebooting |
| // to ensure this service is complete. This issue is fixed in newer images, but |
| // the user may be updating from an older image that does not that have this fix. |
| // TODO: remove this timeout after sufficient time has passed. |
| $timeout(function() { |
| APIUtils.bmcReboot(function(response){}, function(error){ |
| $scope.displayError({ |
| modal_title: 'Error during BMC reboot', |
| title: 'Error during BMC reboot', |
| desc: JSON.stringify(error.data), |
| type: 'Error' |
| }); |
| }); |
| }, 10000); |
| } |
| }); |
| }); |
| $scope.activate_confirm = false; |
| } |
| |
| $scope.upload = function(){ |
| if($scope.file) { |
| $scope.uploading = true; |
| $scope.upload_success = false; |
| APIUtils.uploadImage($scope.file).then(function(response){ |
| $scope.file = ""; |
| $scope.uploading = false; |
| $scope.upload_success = true; |
| $scope.loadFirmwares(); |
| }, function(error){ |
| $scope.uploading = false; |
| console.log(error); |
| $scope.displayError({ |
| modal_title: 'Error during image upload', |
| title: 'Error during image upload', |
| desc: error, |
| type: 'Error' |
| }); |
| }); |
| } |
| } |
| |
| //TODO: openbmc/openbmc#1691 Add support to return |
| //the id of the newly created image, downloaded via |
| //tftp. Polling the number of software objects is a |
| //near term solution. |
| function waitForDownload(){ |
| var deferred = $q.defer(); |
| var startTime = new Date(); |
| pollDownloadTimer = $interval(function(){ |
| var now = new Date(); |
| if((now.getTime() - startTime.getTime()) >= Constants.TIMEOUT.DOWNLOAD_IMAGE){ |
| $interval.cancel(pollDownloadTimer); |
| pollDownloadTimer = undefined; |
| deferred.reject(new Error(Constants.MESSAGES.POLL.DOWNLOAD_IMAGE_TIMEOUT)); |
| } |
| |
| APIUtils.getFirmwares().then(function(response){ |
| if(response.data.length === $scope.firmwares.length + 1){ |
| $interval.cancel(pollDownloadTimer); |
| pollDownloadTimer = undefined; |
| deferred.resolve(response.data); |
| } |
| }, function(error){ |
| $interval.cancel(pollDownloadTimer); |
| pollDownloadTimer = undefined; |
| deferred.reject(error); |
| }); |
| }, Constants.POLL_INTERVALS.DOWNLOAD_IMAGE); |
| |
| return deferred.promise; |
| } |
| |
| $scope.download = function(){ |
| $scope.download_success = false; |
| $scope.download_error_msg = ""; |
| if(!$scope.download_host || !$scope.download_filename){ |
| $scope.download_error_msg = "Field is required!"; |
| return false; |
| } |
| |
| $scope.downloading = true; |
| APIUtils.getFirmwares().then(function(response){ |
| $scope.firmwares = response.data; |
| }).then(function(){ |
| return APIUtils.downloadImage($scope.download_host, |
| $scope.download_filename).then(function(downloadStatus){ |
| return downloadStatus; |
| }); |
| }).then(function(downloadStatus){ |
| return waitForDownload(); |
| }).then(function(newFirmwareList){ |
| $scope.download_host = ""; |
| $scope.download_filename = ""; |
| $scope.downloading = false; |
| $scope.download_success = true; |
| $scope.loadFirmwares(); |
| }, function(error){ |
| console.log(error); |
| $scope.displayError({ |
| modal_title: 'Error during downloading Image', |
| title: 'Error during downloading Image', |
| desc: error, |
| type: 'Error' |
| }); |
| $scope.downloading = false; |
| }); |
| } |
| |
| $scope.changePriority = function(imageId, imageVersion, from, to){ |
| $scope.priority_image_id = imageId; |
| $scope.priority_image_version = imageVersion; |
| $scope.priority_from = from; |
| $scope.priority_to = to; |
| $scope.confirm_priority = true; |
| } |
| |
| $scope.confirmChangePriority = function(){ |
| $scope.loading = true; |
| APIUtils.changePriority($scope.priority_image_id, $scope.priority_to).then(function(response){ |
| $scope.loading = 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(); |
| } |
| }); |
| $scope.confirm_priority = false; |
| } |
| $scope.deleteImage = function(imageId, imageVersion){ |
| $scope.delete_image_id = imageId; |
| $scope.delete_image_version = imageVersion; |
| $scope.confirm_delete = true; |
| } |
| $scope.confirmDeleteImage = function(){ |
| $scope.loading = true; |
| APIUtils.deleteImage($scope.delete_image_id).then(function(response){ |
| $scope.loading = 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(); |
| } |
| }); |
| $scope.confirm_delete = false; |
| } |
| $scope.fileNameChanged = function(){ |
| $scope.file_empty = false; |
| } |
| |
| $scope.filters = { |
| bmc: { |
| imageType: 'BMC' |
| }, |
| host: { |
| imageType: 'Host' |
| } |
| }; |
| |
| $scope.loadFirmwares = function(){ |
| APIUtils.getFirmwares().then(function(result){ |
| $scope.firmwares = result.data; |
| $scope.bmcActiveVersion = result.bmcActiveVersion; |
| $scope.hostActiveVersion = result.hostActiveVersion; |
| }); |
| } |
| |
| $scope.loadFirmwares(); |
| } |
| ] |
| ); |
| |
| })(angular); |