| /** |
| * Controller for power-operations |
| * |
| * @module app/serverControl |
| * @exports powerOperationsController |
| * @name powerOperationsController |
| */ |
| |
| window.angular && (function(angular) { |
| 'use strict'; |
| |
| angular.module('app.serverControl').controller('powerOperationsController', [ |
| '$scope', 'APIUtils', 'dataService', 'Constants', '$interval', '$q', |
| 'toastService', '$uibModal', |
| function( |
| $scope, APIUtils, dataService, Constants, $interval, $q, toastService, |
| $uibModal) { |
| $scope.dataService = dataService; |
| $scope.loading = true; |
| $scope.oneTimeBootEnabled = false; |
| $scope.bootOverrideError = false; |
| $scope.bootSources = []; |
| $scope.boot = {}; |
| $scope.defaultRebootSetting = 'warm-reboot'; |
| $scope.defaultShutdownSetting = 'warm-shutdown'; |
| |
| $scope.activeModal; |
| |
| // When a power operation is in progress, set to true, |
| // when a power operation completes (success/fail) set to false. |
| // This property is used to show/hide the 'in progress' message |
| // in markup. |
| $scope.operationPending = false; |
| |
| const modalTemplate = require('./power-operations-modal.html'); |
| |
| const powerOperations = |
| {WARM_REBOOT: 0, COLD_REBOOT: 1, WARM_SHUTDOWN: 2, COLD_SHUTDOWN: 3}; |
| |
| /** |
| * Checks the host status provided by the dataService using an |
| * interval timer |
| * @param {string} statusType : host status type to check for |
| * @param {number} timeout : timeout limit, defaults to 5 minutes |
| * @param {string} error : error message, defaults to 'Time out' |
| * @returns {Promise} : returns a deferred promise that will be fulfilled |
| * if the status is met or be rejected if the timeout is reached |
| */ |
| const checkHostStatus = |
| (statusType, timeout = 300000, error = 'Time out.') => { |
| const deferred = $q.defer(); |
| const start = new Date(); |
| const checkHostStatusInverval = $interval(() => { |
| let now = new Date(); |
| let timePassed = now.getTime() - start.getTime(); |
| if (timePassed > timeout) { |
| deferred.reject(error); |
| $interval.cancel(checkHostStatusInverval); |
| } |
| if (dataService.server_state === statusType) { |
| deferred.resolve(); |
| $interval.cancel(checkHostStatusInverval); |
| } |
| }, Constants.POLL_INTERVALS.POWER_OP); |
| return deferred.promise; |
| }; |
| |
| /** |
| * Initiate Orderly reboot |
| * Attempts to stop all software |
| */ |
| const warmReboot = () => { |
| $scope.operationPending = true; |
| dataService.setUnreachableState(); |
| APIUtils.hostReboot() |
| .then(() => { |
| // Check for off state |
| return checkHostStatus( |
| Constants.HOST_STATE_TEXT.off, Constants.TIMEOUT.HOST_OFF, |
| Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT); |
| }) |
| .then(() => { |
| // Check for on state |
| return checkHostStatus( |
| Constants.HOST_STATE_TEXT.on, Constants.TIMEOUT.HOST_ON, |
| Constants.MESSAGES.POLL.HOST_ON_TIMEOUT); |
| }) |
| .catch(error => { |
| console.log(error); |
| toastService.error( |
| Constants.MESSAGES.POWER_OP.WARM_REBOOT_FAILED); |
| }) |
| .finally(() => { |
| $scope.operationPending = false; |
| }); |
| }; |
| |
| /** |
| * Initiate Immediate reboot |
| * Does not attempt to stop all software |
| */ |
| const coldReboot = () => { |
| $scope.operationPending = true; |
| dataService.setUnreachableState(); |
| APIUtils.chassisPowerOff() |
| .then(() => { |
| // Check for off state |
| return checkHostStatus( |
| Constants.HOST_STATE_TEXT.off, |
| Constants.TIMEOUT.HOST_OFF_IMMEDIATE, |
| Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT); |
| }) |
| .then(() => { |
| return APIUtils.hostPowerOn(); |
| }) |
| .then(() => { |
| // Check for on state |
| return checkHostStatus( |
| Constants.HOST_STATE_TEXT.on, Constants.TIMEOUT.HOST_ON, |
| Constants.MESSAGES.POLL.HOST_ON_TIMEOUT); |
| }) |
| .catch(error => { |
| console.log(error); |
| toastService.error( |
| Constants.MESSAGES.POWER_OP.COLD_REBOOT_FAILED); |
| }) |
| .finally(() => { |
| $scope.operationPending = false; |
| }); |
| }; |
| |
| /** |
| * Initiate Orderly shutdown |
| * Attempts to stop all software |
| */ |
| const orderlyShutdown = () => { |
| $scope.operationPending = true; |
| dataService.setUnreachableState(); |
| APIUtils.hostPowerOff() |
| .then(() => { |
| // Check for off state |
| return checkHostStatus( |
| Constants.HOST_STATE_TEXT.off, Constants.TIMEOUT.HOST_OFF, |
| Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT); |
| }) |
| .catch(error => { |
| console.log(error); |
| toastService.error( |
| Constants.MESSAGES.POWER_OP.ORDERLY_SHUTDOWN_FAILED); |
| }) |
| .finally(() => { |
| $scope.operationPending = false; |
| }); |
| }; |
| |
| /** |
| * Initiate Immediate shutdown |
| * Does not attempt to stop all software |
| */ |
| const immediateShutdown = () => { |
| $scope.operationPending = true; |
| dataService.setUnreachableState(); |
| APIUtils.chassisPowerOff() |
| .then(() => { |
| // Check for off state |
| return checkHostStatus( |
| Constants.HOST_STATE_TEXT.off, |
| Constants.TIMEOUT.HOST_OFF_IMMEDIATE, |
| Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT); |
| }) |
| .then(() => { |
| dataService.setPowerOffState(); |
| }) |
| .catch(error => { |
| console.log(error); |
| toastService.error( |
| Constants.MESSAGES.POWER_OP.IMMEDIATE_SHUTDOWN_FAILED); |
| }) |
| .finally(() => { |
| $scope.operationPending = false; |
| }); |
| }; |
| |
| /** |
| * Initiate Power on |
| */ |
| $scope.powerOn = () => { |
| $scope.operationPending = true; |
| dataService.setUnreachableState(); |
| APIUtils.hostPowerOn() |
| .then(() => { |
| // Check for on state |
| return checkHostStatus( |
| Constants.HOST_STATE_TEXT.on, Constants.TIMEOUT.HOST_ON, |
| Constants.MESSAGES.POLL.HOST_ON_TIMEOUT); |
| }) |
| .catch(error => { |
| console.log(error); |
| toastService.error(Constants.MESSAGES.POWER_OP.POWER_ON_FAILED); |
| }) |
| .finally(() => { |
| $scope.operationPending = false; |
| }); |
| }; |
| |
| /* |
| * Power operations modal |
| */ |
| const initPowerOperation = function(powerOperation) { |
| switch (powerOperation) { |
| case powerOperations.WARM_REBOOT: |
| warmReboot(); |
| break; |
| case powerOperations.COLD_REBOOT: |
| coldReboot(); |
| break; |
| case powerOperations.WARM_SHUTDOWN: |
| orderlyShutdown(); |
| break; |
| case powerOperations.COLD_SHUTDOWN: |
| immediateShutdown(); |
| break; |
| default: |
| // do nothing |
| } |
| }; |
| |
| const powerOperationModal = function() { |
| $uibModal |
| .open({ |
| template: modalTemplate, |
| windowTopClass: 'uib-modal', |
| scope: $scope, |
| ariaLabelledBy: 'modal-operation' |
| }) |
| .result |
| .then(function(activeModal) { |
| initPowerOperation(activeModal); |
| }) |
| .finally(function() { |
| $scope.activeModal = undefined; |
| }); |
| }; |
| |
| $scope.rebootConfirmModal = function() { |
| if ($scope.rebootForm.radioReboot.$modelValue == 'warm-reboot') { |
| $scope.activeModal = powerOperations.WARM_REBOOT; |
| } else if ($scope.rebootForm.radioReboot.$modelValue == 'cold-reboot') { |
| $scope.activeModal = powerOperations.COLD_REBOOT; |
| } |
| powerOperationModal(); |
| }; |
| |
| $scope.shutdownConfirmModal = function() { |
| if ($scope.shutdownForm.radioShutdown.$modelValue == 'warm-shutdown') { |
| $scope.activeModal = powerOperations.WARM_SHUTDOWN; |
| } else if ( |
| $scope.shutdownForm.radioShutdown.$modelValue == 'cold-shutdown') { |
| $scope.activeModal = powerOperations.COLD_SHUTDOWN; |
| } |
| powerOperationModal(); |
| }; |
| |
| $scope.resetForm = function() { |
| $scope.boot = angular.copy($scope.originalBoot); |
| $scope.TPMToggle = angular.copy($scope.originalTPMToggle); |
| }; |
| |
| /* |
| * Get boot settings |
| */ |
| const loadBootSettings = function() { |
| APIUtils.getBootOptions() |
| .then(function(response) { |
| const boot = response.Boot; |
| const BootSourceOverrideEnabled = |
| boot['BootSourceOverrideEnabled']; |
| const BootSourceOverrideTarget = boot['BootSourceOverrideTarget']; |
| const bootSourceValues = |
| boot['BootSourceOverrideTarget@Redfish.AllowableValues']; |
| |
| $scope.bootSources = bootSourceValues; |
| |
| $scope.boot = { |
| BootSourceOverrideEnabled: BootSourceOverrideEnabled, |
| BootSourceOverrideTarget: BootSourceOverrideTarget |
| }; |
| |
| if (BootSourceOverrideEnabled == 'Once') { |
| $scope.boot.oneTimeBootEnabled = true; |
| } |
| |
| $scope.originalBoot = angular.copy($scope.boot); |
| }) |
| .catch(function(error) { |
| $scope.bootOverrideError = true; |
| toastService.error('Unable to get boot override values.'); |
| console.log( |
| 'Error loading boot settings:', JSON.stringify(error)); |
| }); |
| $scope.loading = false; |
| }; |
| |
| /* |
| * Get TPM status |
| */ |
| const loadTPMStatus = function() { |
| APIUtils.getTPMStatus() |
| .then(function(response) { |
| $scope.TPMToggle = response.data; |
| $scope.originalTPMToggle = angular.copy($scope.TPMToggle); |
| }) |
| .catch(function(error) { |
| toastService.error('Unable to get TPM policy status.'); |
| console.log('Error loading TPM status', JSON.stringify(error)); |
| }); |
| $scope.loading = false; |
| }; |
| |
| /* |
| * Save boot settings |
| */ |
| $scope.saveBootSettings = function() { |
| if ($scope.hostBootSettings.bootSelected.$dirty || |
| $scope.hostBootSettings.oneTime.$dirty) { |
| const data = {}; |
| data.Boot = {}; |
| |
| let isOneTimeBoot = $scope.boot.oneTimeBootEnabled; |
| let overrideTarget = $scope.boot.BootSourceOverrideTarget || 'None'; |
| let overrideEnabled = 'Disabled'; |
| |
| if (isOneTimeBoot) { |
| overrideEnabled = 'Once'; |
| } else if (overrideTarget !== 'None') { |
| overrideEnabled = 'Continuous'; |
| } |
| |
| data.Boot.BootSourceOverrideEnabled = overrideEnabled; |
| data.Boot.BootSourceOverrideTarget = overrideTarget; |
| |
| APIUtils.saveBootSettings(data).then( |
| function(response) { |
| $scope.originalBoot = angular.copy($scope.boot); |
| toastService.success('Successfully updated boot settings.'); |
| }, |
| function(error) { |
| toastService.error('Unable to save boot settings.'); |
| console.log(JSON.stringify(error)); |
| }); |
| } |
| }; |
| |
| /* |
| * Save TPM required policy |
| */ |
| $scope.saveTPMPolicy = function() { |
| if ($scope.hostBootSettings.toggle.$dirty) { |
| const tpmEnabled = $scope.TPMToggle.TPMEnable; |
| |
| if (tpmEnabled === undefined) { |
| return; |
| } |
| |
| APIUtils.saveTPMEnable(tpmEnabled) |
| .then( |
| function(response) { |
| $scope.originalTPMToggle = angular.copy($scope.TPMToggle); |
| toastService.success( |
| 'Sucessfully updated TPM required policy.'); |
| }, |
| function(error) { |
| toastService.error('Unable to update TPM required policy.'); |
| console.log(JSON.stringify(error)); |
| }); |
| } |
| }; |
| |
| /** |
| * Callback when boot setting option changed |
| */ |
| $scope.onChangeBootSetting = function() { |
| const bootSetting = $scope.hostBootSettings.bootSelected.$viewValue; |
| if (bootSetting === 'None') { |
| $scope.boot.oneTimeBootEnabled = false; |
| } |
| }; |
| |
| /* |
| * Emitted every time the view is reloaded |
| */ |
| $scope.$on('$viewContentLoaded', function() { |
| APIUtils.getLastPowerTime() |
| .then( |
| function(data) { |
| if (data.data == 0) { |
| $scope.powerTime = 'not available'; |
| } else { |
| $scope.powerTime = data.data; |
| } |
| }, |
| function(error) { |
| toastService.error( |
| 'Unable to get last power operation time.'); |
| console.log(JSON.stringify(error)); |
| }) |
| .finally(function() { |
| $scope.loading = false; |
| }); |
| |
| loadBootSettings(); |
| loadTPMStatus(); |
| }); |
| } |
| ]); |
| })(angular); |