blob: 76e632ba72677ee2aac31b385e3dd25108424f72 [file] [log] [blame]
/**
* 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);