summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/AppNavigation/AppNavigationMixin.js5
-rw-r--r--src/env/components/AppNavigation/ibm.js5
-rw-r--r--src/env/router/ibm.js9
-rw-r--r--src/locales/en-US.json54
-rw-r--r--src/router/routes.js9
-rw-r--r--src/store/index.js2
-rw-r--r--src/store/modules/Control/FactoryResetStore.js32
-rw-r--r--src/views/Control/FactoryReset/FactoryReset.vue117
-rw-r--r--src/views/Control/FactoryReset/FactoryResetModal.vue113
-rw-r--r--src/views/Control/FactoryReset/index.js2
-rw-r--r--tests/unit/__snapshots__/AppNavigation.spec.js.snap18
11 files changed, 359 insertions, 7 deletions
diff --git a/src/components/AppNavigation/AppNavigationMixin.js b/src/components/AppNavigation/AppNavigationMixin.js
index a83b6c7f..58852197 100644
--- a/src/components/AppNavigation/AppNavigationMixin.js
+++ b/src/components/AppNavigation/AppNavigationMixin.js
@@ -51,6 +51,11 @@ const AppNavigationMixin = {
icon: 'iconControl',
children: [
{
+ id: 'factory-reset',
+ label: this.$t('appNavigation.factoryReset'),
+ route: '/control/factory-reset',
+ },
+ {
id: 'kvm',
label: this.$t('appNavigation.kvm'),
route: '/control/kvm',
diff --git a/src/env/components/AppNavigation/ibm.js b/src/env/components/AppNavigation/ibm.js
index dadb65dd..d4b8e3dc 100644
--- a/src/env/components/AppNavigation/ibm.js
+++ b/src/env/components/AppNavigation/ibm.js
@@ -56,6 +56,11 @@ const AppNavigationMixin = {
icon: 'iconControl',
children: [
{
+ id: 'factory-reset',
+ label: this.$t('appNavigation.factoryReset'),
+ route: '/control/factory-reset',
+ },
+ {
id: 'manage-power-usage',
label: this.$t('appNavigation.managePowerUsage'),
route: '/control/manage-power-usage',
diff --git a/src/env/router/ibm.js b/src/env/router/ibm.js
index 317125e2..e0586e82 100644
--- a/src/env/router/ibm.js
+++ b/src/env/router/ibm.js
@@ -4,6 +4,7 @@ import ClientSessions from '@/views/AccessControl/ClientSessions';
import ConsoleLayout from '@/layouts/ConsoleLayout.vue';
import DateTimeSettings from '@/views/Configuration/DateTimeSettings';
import EventLogs from '@/views/Health/EventLogs';
+import FactoryReset from '@/views/Control/FactoryReset';
import Firmware from '@/views/Configuration/Firmware';
import HardwareStatus from '@/views/Health/HardwareStatus';
import Ldap from '@/views/AccessControl/Ldap';
@@ -206,6 +207,14 @@ const routes = [
},
},
{
+ path: '/control/factory-reset',
+ name: 'factory-reset',
+ component: FactoryReset,
+ meta: {
+ title: i18n.t('appPageTitle.factoryReset'),
+ },
+ },
+ {
path: '/control/reboot-bmc',
name: 'reboot-bmc',
component: RebootBmc,
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index 745fcba8..7a5175a3 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -15,6 +15,7 @@
"filter": "Filter",
"refresh": "Refresh",
"replace": "Replace",
+ "reset": "Reset",
"save": "Save",
"saveSettings": "Save settings",
"selected": "Selected"
@@ -72,7 +73,7 @@
"itemsPerPage": "Items per page",
"selectAll": "Select all",
"selectItem": "Select item",
- "selectedItems":"%{filterCount} of %{count} items",
+ "selectedItems": "%{filterCount} of %{count} items",
"toDate": "To date",
"viewAll": "View all"
},
@@ -102,6 +103,7 @@
"dateTimeSettings": "@:appPageTitle.dateTimeSettings",
"dumps": "@:appPageTitle.dumps",
"eventLogs": "@:appPageTitle.eventLogs",
+ "factoryReset": "@:appPageTitle.factoryReset",
"firmware": "@:appPageTitle.firmware",
"hardwareStatus": "@:appPageTitle.hardwareStatus",
"health": "Health",
@@ -129,6 +131,7 @@
"dateTimeSettings": "Date and time settings",
"dumps": "Dumps",
"eventLogs": "Event logs",
+ "factoryReset": "Factory reset",
"firmware": "Firmware",
"hardwareStatus": "Hardware status",
"kvm": "KVM",
@@ -160,9 +163,9 @@
"newPassword": "New password",
"username": "Username"
},
- "pageClientSessions" : {
+ "pageClientSessions": {
"action": {
- "disconnect" : "Disconnect"
+ "disconnect": "Disconnect"
},
"modal": {
"disconnectTitle": "Disconnect session| Disconnect sessions",
@@ -260,6 +263,43 @@
"successDelete": "Successfully deleted %{count} log. | Successfully deleted %{count} logs."
}
},
+ "pageFactoryReset": {
+ "description": "These functions do not perform a secure delete of any sensitive data.",
+ "form": {
+ "resetOptionsLabel": "Reset options",
+ "resetBiosOptionLabel": "Reset host settings only",
+ "resetBiosOptionHelperText": "Resets firmware settings including: Platform keystore, partition NVRAM, and partition configurations.",
+ "resetToDefaultsOptionLabel": "Reset BMC and host settings",
+ "resetToDefaultsOptionHelperText": "In addition to host settings, this option resets BMC settings, including: all BMC account data, all changed passwords, all policies, LDAP configurations, network addresses, and time of day."
+ },
+ "modal": {
+ "resetBiosTitle": "Reset host settings",
+ "resetBiosHeader": "Do you want to reset the host settings?",
+ "resetBiosSubmitText": "Reset host settings",
+ "resetBiosSettingsList": {
+ "item1": "All manual settings will be deleted.",
+ "item2": "Partition configurations and the platform keystore may be recovered if backups exist."
+ },
+ "resetToDefaultsTitle": "Reset BMC and host settings",
+ "resetToDefaultsHeader": "Do you want to reset both the BMC and host settings?",
+ "resetToDefaultsSubmitText": "Reset BMC and host settings",
+ "resetToDefaultsSettingsList": {
+ "item1": "All manual settings will be deleted.",
+ "item2": "Partition configurations and the platform keystore may be recovered if backups exist.",
+ "item3": "All BMC logs will be erased.",
+ "item4": "Currently active sessions on all network interfaces will be disconnected.",
+ "item5": "The BMC default account and password settings will be restored."
+ },
+ "resetWarningMessage": "Resetting without shutting down the system might cause an unrecoverable error.",
+ "resetWarningCheckLabel": "Continue without shutting down the system"
+ },
+ "toast": {
+ "resetBiosSuccess": "Factory reset of host settings successful.",
+ "resetBiosError": "Factory reset of host settings failed.",
+ "resetToDefaultsSuccess": "Factory reset of BMC and host settings successful.",
+ "resetToDefaultsError": "Factory reset of BMC and host settings failed."
+ }
+ },
"pageFirmware": {
"cardActionSwitchToRunning": "Switch to running",
"cardBodyVersion": "Version",
@@ -579,7 +619,7 @@
"currentPolicy": "Current Policy",
"description": "Configure power policy to determine how the system starts after a power disturbance.",
"powerPoliciesLabel": "Power restore policies",
- "policies" :{
+ "policies": {
"AlwaysOn": "Always on",
"AlwaysOff": "Always off",
"LastState": "Last state"
@@ -620,8 +660,8 @@
},
"toast": {
"errorIpmiDisabled": "Error disabling IPMI security setting.",
- "errorIpmiEnabled":"Error enabling IPMI security setting.",
- "errorSshDisabled":"Error disabling SSH security setting.",
+ "errorIpmiEnabled": "Error enabling IPMI security setting.",
+ "errorSshDisabled": "Error disabling SSH security setting.",
"errorSshEnabled": "Error enabling SSH security setting.",
"successIpmiDisabled": "Successfully disabled IPMI security setting.",
"successIpmiEnabled": "Successfully enabled IPMI security setting.",
@@ -1019,4 +1059,4 @@
"ZW": "Zimbabwe",
"AX": "Ă…land Islands"
}
-} \ No newline at end of file
+}
diff --git a/src/router/routes.js b/src/router/routes.js
index 533f1859..e5812e00 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -3,6 +3,7 @@ import ChangePassword from '@/views/ChangePassword';
import ConsoleLayout from '@/layouts/ConsoleLayout.vue';
import DateTimeSettings from '@/views/Configuration/DateTimeSettings';
import EventLogs from '@/views/Health/EventLogs';
+import FactoryReset from '@/views/Control/FactoryReset';
import Firmware from '@/views/Configuration/Firmware';
import HardwareStatus from '@/views/Health/HardwareStatus';
import Kvm from '@/views/Control/Kvm';
@@ -182,6 +183,14 @@ const routes = [
},
},
{
+ path: '/control/factory-reset',
+ name: 'factory-reset',
+ component: FactoryReset,
+ meta: {
+ title: i18n.t('appPageTitle.factoryReset'),
+ },
+ },
+ {
path: '/control/kvm',
name: 'kvm',
component: Kvm,
diff --git a/src/store/index.js b/src/store/index.js
index fd8b1fcf..93386b1a 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -24,6 +24,7 @@ import ChassisStore from './modules/Health/ChassisStore';
import BmcStore from './modules/Health/BmcStore';
import ProcessorStore from './modules/Health/ProcessorStore';
import SecuritySettingsStore from './modules/Configuration/SecuritySettingsStore';
+import FactoryResetStore from './modules/Control/FactoryResetStore';
import WebSocketPlugin from './plugins/WebSocketPlugin';
import DateTimeStore from './modules/Configuration/DateTimeSettingsStore';
@@ -61,6 +62,7 @@ export default new Vuex.Store({
processors: ProcessorStore,
virtualMedia: VirtualMediaStore,
securitySettings: SecuritySettingsStore,
+ factoryReset: FactoryResetStore,
},
plugins: [WebSocketPlugin],
});
diff --git a/src/store/modules/Control/FactoryResetStore.js b/src/store/modules/Control/FactoryResetStore.js
new file mode 100644
index 00000000..8118cf7f
--- /dev/null
+++ b/src/store/modules/Control/FactoryResetStore.js
@@ -0,0 +1,32 @@
+import api from '@/store/api';
+import i18n from '@/i18n';
+
+const FactoryResetStore = {
+ namespaced: true,
+ actions: {
+ async resetToDefaults() {
+ return await api
+ .post('/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults', {
+ ResetToDefaultsType: 'ResetAll',
+ })
+ .then(() => i18n.t('pageFactoryReset.toast.resetToDefaultsSuccess'))
+ .catch((error) => {
+ console.log('Factory Reset: ', error);
+ throw new Error(
+ i18n.t('pageFactoryReset.toast.resetToDefaultsError')
+ );
+ });
+ },
+ async resetBios() {
+ return await api
+ .post('/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios')
+ .then(() => i18n.t('pageFactoryReset.toast.resetBiosSuccess'))
+ .catch((error) => {
+ console.log('Factory Reset: ', error);
+ throw new Error(i18n.t('pageFactoryReset.toast.resetBiosError'));
+ });
+ },
+ },
+};
+
+export default FactoryResetStore;
diff --git a/src/views/Control/FactoryReset/FactoryReset.vue b/src/views/Control/FactoryReset/FactoryReset.vue
new file mode 100644
index 00000000..897348fc
--- /dev/null
+++ b/src/views/Control/FactoryReset/FactoryReset.vue
@@ -0,0 +1,117 @@
+<template>
+ <b-container fluid="xl">
+ <page-title :description="$t('pageFactoryReset.description')" />
+
+ <!-- Reset Form -->
+ <b-form id="factory-reset" @submit.prevent="onResetSubmit">
+ <b-row>
+ <b-col md="8">
+ <b-form-group :label="$t('pageFactoryReset.form.resetOptionsLabel')">
+ <b-form-radio-group
+ id="factory-reset-options"
+ v-model="resetOption"
+ stacked
+ >
+ <b-form-radio
+ class="mb-1"
+ value="resetBios"
+ aria-describedby="reset-bios"
+ data-test-id="factoryReset-radio-resetBios"
+ >
+ {{ $t('pageFactoryReset.form.resetBiosOptionLabel') }}
+ </b-form-radio>
+ <b-form-text id="reset-bios" class="ml-4 mb-3">
+ {{ $t('pageFactoryReset.form.resetBiosOptionHelperText') }}
+ </b-form-text>
+
+ <b-form-radio
+ class="mb-1"
+ value="resetToDefaults"
+ aria-describedby="reset-to-defaults"
+ data-test-id="factoryReset-radio-resetToDefaults"
+ >
+ {{ $t('pageFactoryReset.form.resetToDefaultsOptionLabel') }}
+ </b-form-radio>
+ <b-form-text id="reset-to-defaults" class="ml-4 mb-3">
+ {{
+ $t('pageFactoryReset.form.resetToDefaultsOptionHelperText')
+ }}
+ </b-form-text>
+ </b-form-radio-group>
+ </b-form-group>
+ <b-button
+ type="submit"
+ variant="primary"
+ data-test-id="factoryReset-button-submit"
+ >
+ {{ $t('global.action.reset') }}
+ </b-button>
+ </b-col>
+ </b-row>
+ </b-form>
+
+ <!-- Modals -->
+ <modal-reset :reset-type="resetOption" @okConfirm="onOkConfirm" />
+ </b-container>
+</template>
+
+<script>
+import PageTitle from '@/components/Global/PageTitle';
+import BVToastMixin from '@/components/Mixins/BVToastMixin';
+import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
+import ModalReset from './FactoryResetModal';
+
+export default {
+ name: 'FactoryReset',
+ components: { PageTitle, ModalReset },
+ mixins: [LoadingBarMixin, BVToastMixin],
+ data() {
+ return {
+ resetOption: 'resetBios',
+ };
+ },
+ created() {
+ this.hideLoader();
+ },
+ methods: {
+ onResetSubmit() {
+ this.$bvModal.show('modal-reset');
+ },
+ onOkConfirm() {
+ if (this.resetOption == 'resetBios') {
+ this.onResetBiosConfirm();
+ } else {
+ this.onResetToDefaultsConfirm();
+ }
+ },
+ onResetBiosConfirm() {
+ this.$store
+ .dispatch('factoryReset/resetBios')
+ .then((title) => {
+ this.successToast('', {
+ title,
+ });
+ })
+ .catch(({ message }) => {
+ this.errorToast('', {
+ title: message,
+ });
+ });
+ },
+ onResetToDefaultsConfirm() {
+ this.$store
+ .dispatch('factoryReset/resetToDefaults')
+ .then((title) => {
+ this.successToast('', {
+ title,
+ });
+ })
+ .catch(({ message }) => {
+ this.errorToast('', {
+ title: message,
+ });
+ });
+ },
+ },
+};
+</script>
diff --git a/src/views/Control/FactoryReset/FactoryResetModal.vue b/src/views/Control/FactoryReset/FactoryResetModal.vue
new file mode 100644
index 00000000..bf92b173
--- /dev/null
+++ b/src/views/Control/FactoryReset/FactoryResetModal.vue
@@ -0,0 +1,113 @@
+<template>
+ <b-modal
+ id="modal-reset"
+ ref="modal"
+ :title="$t(`pageFactoryReset.modal.${resetType}Title`)"
+ title-tag="h2"
+ @hidden="resetConfirm"
+ >
+ <p class="mb-2">
+ <strong>{{ $t(`pageFactoryReset.modal.${resetType}Header`) }}</strong>
+ </p>
+ <ul class="pl-3 mb-4">
+ <li
+ v-for="(item, index) in $t(
+ `pageFactoryReset.modal.${resetType}SettingsList`
+ )"
+ :key="index"
+ class="mt-1 mb-1"
+ >
+ {{ $t(item) }}
+ </li>
+ </ul>
+
+ <!-- Warning message -->
+ <template v-if="!isHostOff">
+ <p class="d-flex mb-2">
+ <status-icon status="danger" />
+ <span id="reset-to-default-warning" class="ml-1">
+ {{ $t(`pageFactoryReset.modal.resetWarningMessage`) }}
+ </span>
+ </p>
+ <b-form-checkbox
+ v-model="confirm"
+ aria-describedby="reset-to-default-warning"
+ @input="$v.confirm.$touch()"
+ >
+ {{ $t(`pageFactoryReset.modal.resetWarningCheckLabel`) }}
+ </b-form-checkbox>
+ <b-form-invalid-feedback
+ role="alert"
+ :state="getValidationState($v.confirm)"
+ >
+ {{ $t('global.form.fieldRequired') }}
+ </b-form-invalid-feedback>
+ </template>
+
+ <template #modal-footer="{ cancel }">
+ <b-button
+ variant="secondary"
+ data-test-id="factoryReset-button-cancel"
+ @click="cancel()"
+ >
+ {{ $t('global.action.cancel') }}
+ </b-button>
+ <b-button
+ type="sumbit"
+ variant="primary"
+ data-test-id="factoryReset-button-confirm"
+ @click="handleConfirm"
+ >
+ {{ $t(`pageFactoryReset.modal.${resetType}SubmitText`) }}
+ </b-button>
+ </template>
+ </b-modal>
+</template>
+<script>
+import StatusIcon from '@/components/Global/StatusIcon';
+import VuelidateMixin from '@/components/Mixins/VuelidateMixin';
+
+export default {
+ components: { StatusIcon },
+ mixins: [VuelidateMixin],
+ props: {
+ resetType: {
+ type: String,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ confirm: false,
+ };
+ },
+ computed: {
+ hostStatus() {
+ return this.$store.getters['global/hostStatus'];
+ },
+ isHostOff() {
+ return this.hostStatus === 'off' ? true : false;
+ },
+ },
+ validations: {
+ confirm: {
+ mustBeTrue: function (value) {
+ return this.isHostOff || value === true;
+ },
+ },
+ },
+ methods: {
+ handleConfirm() {
+ this.$v.$touch();
+ if (this.$v.$invalid) return;
+ this.$emit('okConfirm');
+ this.$nextTick(() => this.$refs.modal.hide());
+ this.resetConfirm();
+ },
+ resetConfirm() {
+ this.confirm = false;
+ this.$v.$reset();
+ },
+ },
+};
+</script>
diff --git a/src/views/Control/FactoryReset/index.js b/src/views/Control/FactoryReset/index.js
new file mode 100644
index 00000000..eae747e0
--- /dev/null
+++ b/src/views/Control/FactoryReset/index.js
@@ -0,0 +1,2 @@
+import FactoryReset from './FactoryReset.vue';
+export default FactoryReset;
diff --git a/tests/unit/__snapshots__/AppNavigation.spec.js.snap b/tests/unit/__snapshots__/AppNavigation.spec.js.snap
index 11db8068..63fc847b 100644
--- a/tests/unit/__snapshots__/AppNavigation.spec.js.snap
+++ b/tests/unit/__snapshots__/AppNavigation.spec.js.snap
@@ -218,6 +218,15 @@ exports[`AppNavigation.vue should render correctly 1`] = `
>
<a
class="nav-link"
+ data-test-id="nav-item-factory-reset"
+ href="#/control/factory-reset"
+ >
+
+ appNavigation.factoryReset
+
+ </a>
+ <a
+ class="nav-link"
data-test-id="nav-item-kvm"
href="#/control/kvm"
>
@@ -743,6 +752,15 @@ exports[`AppNavigation.vue should render with nav-container open 1`] = `
>
<a
class="nav-link"
+ data-test-id="nav-item-factory-reset"
+ href="#/control/factory-reset"
+ >
+
+ appNavigation.factoryReset
+
+ </a>
+ <a
+ class="nav-link"
data-test-id="nav-item-kvm"
href="#/control/kvm"
>