summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/AppNavigation/AppNavigation.vue2
-rw-r--r--src/locales/en.json22
-rw-r--r--src/router/index.js8
-rw-r--r--src/store/modules/Control/ControlStore.js79
-rw-r--r--src/views/Control/ServerPowerOperations/ServerPowerOperations.vue184
-rw-r--r--src/views/Control/ServerPowerOperations/index.js2
6 files changed, 296 insertions, 1 deletions
diff --git a/src/components/AppNavigation/AppNavigation.vue b/src/components/AppNavigation/AppNavigation.vue
index 62ffe982..07d1cdb9 100644
--- a/src/components/AppNavigation/AppNavigation.vue
+++ b/src/components/AppNavigation/AppNavigation.vue
@@ -42,7 +42,7 @@
<b-nav-item href="javascript:void(0)">
{{ $t('appNavigation.serverLed') }}
</b-nav-item>
- <b-nav-item href="javascript:void(0)">
+ <b-nav-item to="/control/server-power-operations">
{{ $t('appNavigation.serverPowerOperations') }}
</b-nav-item>
</b-collapse>
diff --git a/src/locales/en.json b/src/locales/en.json
index 30bfc88d..0de52987 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -183,5 +183,27 @@
"errorRebootStart": "Error rebooting BMC.",
"successRebootStart": "Rebooting BMC."
}
+ },
+ "pageServerPowerOperations": {
+ "currentStatus": "Current status",
+ "hostname": "Hostname",
+ "hostStatus": "Host status",
+ "immediateReboot": "Immediate – Server reboots without OS shutting down; may cause data corruption",
+ "immediateShutdown": "Immediate - Server shuts down without OS shutting down; may cause data corruption",
+ "operationInProgress": "There are no options to display while a power operation is in progress. When complete, power operations will be displayed here.",
+ "operations": "Operations",
+ "orderlyReboot": "Orderly – OS shuts down, then server reboots",
+ "orderlyShutdown": "Orderly - OS shuts down, then server shuts down",
+ "powerOn": "Power on",
+ "reboot": "Reboot",
+ "rebootServer": "Reboot server",
+ "shutDown": "Shut down",
+ "shutdownServer": "Shutdown server",
+ "modal": {
+ "confirmRebootMessage": "Are you sure you want to reboot?",
+ "confirmRebootTitle": "Server reboot will cause outage",
+ "confirmShutdownMessage": "Are you sure you want to shut down?",
+ "confirmShutdownTitle": "Server shutdown will cause outage"
+ }
}
} \ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
index dda4daf5..0d246cda 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -40,6 +40,14 @@ const routes = [
}
},
{
+ path: '/control/server-power-operations',
+ name: 'server-power-operations',
+ component: () => import('@/views/Control/ServerPowerOperations'),
+ meta: {
+ title: 'appPageTitle.serverPowerOperations'
+ }
+ },
+ {
path: '/unauthorized',
name: 'unauthorized',
component: () => import('@/views/Unauthorized'),
diff --git a/src/store/modules/Control/ControlStore.js b/src/store/modules/Control/ControlStore.js
index 9b2e4592..6f9ced43 100644
--- a/src/store/modules/Control/ControlStore.js
+++ b/src/store/modules/Control/ControlStore.js
@@ -1,8 +1,45 @@
import api from '../../api';
import i18n from '../../../i18n';
+/**
+ * Watch for hostStatus changes in GlobalStore module
+ * to set isOperationInProgress state
+ * Stop watching status changes and resolve Promise when
+ * hostStatus value matches passed argument or after 5 minutes
+ * @param {string} hostStatus
+ * @returns {Promise}
+ */
+const checkForHostStatus = function(hostStatus) {
+ return new Promise(resolve => {
+ const timer = setTimeout(() => {
+ resolve();
+ unwatch();
+ }, 300000 /*5mins*/);
+ const unwatch = this.watch(
+ state => state.global.hostStatus,
+ value => {
+ if (value === hostStatus) {
+ resolve();
+ unwatch();
+ clearTimeout(timer);
+ }
+ }
+ );
+ });
+};
+
const ControlStore = {
namespaced: true,
+ state: {
+ isOperationInProgress: false
+ },
+ getters: {
+ isOperationInProgress: state => state.isOperationInProgress
+ },
+ mutations: {
+ setOperationInProgress: (state, inProgress) =>
+ (state.isOperationInProgress = inProgress)
+ },
actions: {
async rebootBmc() {
const data = { ResetType: 'GracefulRestart' };
@@ -13,6 +50,48 @@ const ControlStore = {
console.log(error);
throw new Error(i18n.t('pageRebootBmc.toast.errorRebootStart'));
});
+ },
+ async hostPowerOn({ dispatch, commit }) {
+ const data = { ResetType: 'On' };
+ dispatch('hostPowerChange', data);
+ await checkForHostStatus.bind(this, 'on')();
+ commit('setOperationInProgress', false);
+ },
+ async hostSoftReboot({ dispatch, commit }) {
+ const data = { ResetType: 'GracefulRestart' };
+ dispatch('hostPowerChange', data);
+ await checkForHostStatus.bind(this, 'on')();
+ commit('setOperationInProgress', false);
+ },
+ async hostHardReboot({ dispatch, commit }) {
+ // TODO: Update when ForceWarmReboot property
+ // available
+ dispatch('hostPowerChange', { ResetType: 'ForceOff' });
+ await checkForHostStatus.bind(this, 'off')();
+ dispatch('hostPowerChange', { ResetType: 'On' });
+ await checkForHostStatus.bind(this, 'on')();
+ commit('setOperationInProgress', false);
+ },
+ async hostSoftPowerOff({ dispatch, commit }) {
+ const data = { ResetType: 'GracefulShutdown' };
+ dispatch('hostPowerChange', data);
+ await checkForHostStatus.bind(this, 'off')();
+ commit('setOperationInProgress', false);
+ },
+ async hostHardPowerOff({ dispatch, commit }) {
+ const data = { ResetType: 'ForceOff' };
+ dispatch('hostPowerChange', data);
+ await checkForHostStatus.bind(this, 'off')();
+ commit('setOperationInProgress', false);
+ },
+ hostPowerChange({ commit }, data) {
+ commit('setOperationInProgress', true);
+ api
+ .post('/redfish/v1/Systems/system/Actions/ComputerSystem.Reset', data)
+ .catch(error => {
+ console.log(error);
+ commit('setOperationInProgress', false);
+ });
}
}
};
diff --git a/src/views/Control/ServerPowerOperations/ServerPowerOperations.vue b/src/views/Control/ServerPowerOperations/ServerPowerOperations.vue
new file mode 100644
index 00000000..c9b02b3e
--- /dev/null
+++ b/src/views/Control/ServerPowerOperations/ServerPowerOperations.vue
@@ -0,0 +1,184 @@
+<template>
+ <b-container fluid>
+ <page-title />
+ <b-row>
+ <b-col md="8" lg="8" xl="6">
+ <page-section
+ :section-title="$t('pageServerPowerOperations.currentStatus')"
+ >
+ <dl>
+ <dt>{{ $t('pageServerPowerOperations.hostname') }}</dt>
+ <dd>{{ hostname }}</dd>
+ </dl>
+ <dl>
+ <dt>{{ $t('pageServerPowerOperations.hostStatus') }}</dt>
+ <dd v-if="hostStatus === 'on'">
+ {{ $t('global.status.on') }}
+ </dd>
+ <dd v-else-if="hostStatus === 'off'">
+ {{ $t('global.status.off') }}
+ </dd>
+ <dd v-else>
+ {{ $t('global.status.notAvailable') }}
+ </dd>
+ </dl>
+ </page-section>
+ </b-col>
+ </b-row>
+ <b-row>
+ <b-col md="8" lg="7" xl="8">
+ <page-section
+ :section-title="$t('pageServerPowerOperations.operations')"
+ >
+ <template v-if="isOperationInProgress">
+ {{ $t('pageServerPowerOperations.operationInProgress') }}
+ </template>
+ <template v-else-if="hostStatus === 'off'">
+ <b-button variant="primary" @click="powerOn">
+ {{ $t('pageServerPowerOperations.powerOn') }}
+ </b-button>
+ </template>
+ <template v-else-if="hostStatus === 'on'">
+ <!-- Reboot server options -->
+ <b-form novalidate class="mb-5" @submit.prevent="rebootServer">
+ <b-form-group
+ :label="$t('pageServerPowerOperations.rebootServer')"
+ >
+ <b-form-radio
+ v-model="form.rebootOption"
+ name="reboot-option"
+ value="orderly"
+ >
+ {{ $t('pageServerPowerOperations.orderlyReboot') }}
+ </b-form-radio>
+ <b-form-radio
+ v-model="form.rebootOption"
+ name="reboot-option"
+ value="immediate"
+ >
+ {{ $t('pageServerPowerOperations.immediateReboot') }}
+ </b-form-radio>
+ </b-form-group>
+ <b-button variant="primary" type="submit">
+ {{ $t('pageServerPowerOperations.reboot') }}
+ </b-button>
+ </b-form>
+ <!-- Shutdown server options -->
+ <b-form novalidate @submit.prevent="shutdownServer">
+ <b-form-group
+ :label="$t('pageServerPowerOperations.shutdownServer')"
+ >
+ <b-form-radio
+ v-model="form.shutdownOption"
+ name="shutdown-option"
+ value="orderly"
+ >
+ {{ $t('pageServerPowerOperations.orderlyShutdown') }}
+ </b-form-radio>
+ <b-form-radio
+ v-model="form.shutdownOption"
+ name="shutdown-option"
+ value="immediate"
+ >
+ {{ $t('pageServerPowerOperations.immediateShutdown') }}
+ </b-form-radio>
+ </b-form-group>
+ <b-button variant="primary" type="submit">
+ {{ $t('pageServerPowerOperations.shutDown') }}
+ </b-button>
+ </b-form>
+ </template>
+ <template v-else>
+ {{ $t('global.status.notAvailable') }}
+ </template>
+ </page-section>
+ </b-col>
+ </b-row>
+ </b-container>
+</template>
+
+<script>
+import PageTitle from '../../../components/Global/PageTitle';
+import PageSection from '../../../components/Global/PageSection';
+import BVToastMixin from '../../../components/Mixins/BVToastMixin';
+
+export default {
+ name: 'ServerPowerOperations',
+ components: { PageTitle, PageSection },
+ mixins: [BVToastMixin],
+ data() {
+ return {
+ form: {
+ rebootOption: 'orderly',
+ shutdownOption: 'orderly'
+ }
+ };
+ },
+ computed: {
+ hostStatus() {
+ return this.$store.getters['global/hostStatus'];
+ },
+ hostname() {
+ return this.$store.getters['global/hostName'];
+ },
+ isOperationInProgress() {
+ return this.$store.getters['controls/isOperationInProgress'];
+ }
+ },
+ created() {
+ this.$store.dispatch('global/getHostName');
+ },
+ methods: {
+ powerOn() {
+ this.$store.dispatch('controls/hostPowerOn');
+ },
+ rebootServer() {
+ const modalMessage = this.$t(
+ 'pageServerPowerOperations.modal.confirmRebootMessage'
+ );
+ const modalOptions = {
+ title: this.$t('pageServerPowerOperations.modal.confirmRebootTitle'),
+ okTitle: this.$t('global.action.confirm')
+ };
+
+ if (this.form.rebootOption === 'orderly') {
+ this.$bvModal
+ .msgBoxConfirm(modalMessage, modalOptions)
+ .then(confirmed => {
+ if (confirmed) this.$store.dispatch('controls/hostSoftReboot');
+ });
+ } else if (this.form.rebootOption === 'immediate') {
+ this.$bvModal
+ .msgBoxConfirm(modalMessage, modalOptions)
+ .then(confirmed => {
+ if (confirmed) this.$store.dispatch('controls/hostHardReboot');
+ });
+ }
+ },
+ shutdownServer() {
+ const modalMessage = this.$t(
+ 'pageServerPowerOperations.modal.confirmShutdownMessage'
+ );
+ const modalOptions = {
+ title: this.$t('pageServerPowerOperations.modal.confirmShutdownTitle'),
+ okTitle: this.$t('global.action.confirm')
+ };
+
+ if (this.form.shutdownOption === 'orderly') {
+ this.$bvModal
+ .msgBoxConfirm(modalMessage, modalOptions)
+ .then(confirmed => {
+ if (confirmed) this.$store.dispatch('controls/hostSoftPowerOff');
+ });
+ }
+ if (this.form.shutdownOption === 'immediate') {
+ this.$bvModal
+ .msgBoxConfirm(modalMessage, modalOptions)
+ .then(confirmed => {
+ if (confirmed) this.$store.dispatch('controls/hostHardPowerOff');
+ });
+ }
+ }
+ }
+};
+</script>
diff --git a/src/views/Control/ServerPowerOperations/index.js b/src/views/Control/ServerPowerOperations/index.js
new file mode 100644
index 00000000..10430047
--- /dev/null
+++ b/src/views/Control/ServerPowerOperations/index.js
@@ -0,0 +1,2 @@
+import ServerPowerOperations from './ServerPowerOperations.vue';
+export default ServerPowerOperations;