diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/AppNavigation/AppNavigationMixin.js | 5 | ||||
-rw-r--r-- | src/env/components/AppNavigation/ibm.js | 5 | ||||
-rw-r--r-- | src/env/router/ibm.js | 9 | ||||
-rw-r--r-- | src/locales/en-US.json | 54 | ||||
-rw-r--r-- | src/router/routes.js | 9 | ||||
-rw-r--r-- | src/store/index.js | 2 | ||||
-rw-r--r-- | src/store/modules/Control/FactoryResetStore.js | 32 | ||||
-rw-r--r-- | src/views/Control/FactoryReset/FactoryReset.vue | 117 | ||||
-rw-r--r-- | src/views/Control/FactoryReset/FactoryResetModal.vue | 113 | ||||
-rw-r--r-- | src/views/Control/FactoryReset/index.js | 2 |
10 files changed, 341 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; |