diff options
author | Yoshie Muranaka <yoshiemuranaka@gmail.com> | 2021-02-19 02:24:14 +0300 |
---|---|---|
committer | Derick Montague <derick.montague@ibm.com> | 2021-03-01 16:45:05 +0300 |
commit | 33d755f4e62beff72101f6ca07e4d31b04e13826 (patch) | |
tree | a67d890472f0c7f27951b8e86d472e220dac066e /src/views | |
parent | 9a25c80591e8872297f2c33ad9bcd6a97639f04c (diff) | |
download | webui-vue-33d755f4e62beff72101f6ca07e4d31b04e13826.tar.xz |
Update the default firmware page
- Minor updates made to the general layout and styles
- Changes to some page copy
- Moves update firmware form to bottom of page
- Adds dynamic TFTP upload option
- Adds dynamic card layout for BMC and host firmwre
- 2 cards for combined
- 4 cards for separate
- Removes FirmwareSingleImage components that were used for IBM builds
Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: Ib5465ecc30dd1505824bf41c82d33b7655d5e598
Diffstat (limited to 'src/views')
10 files changed, 599 insertions, 409 deletions
diff --git a/src/views/Configuration/Firmware/Firmware.vue b/src/views/Configuration/Firmware/Firmware.vue index 5001702a..e27c8a26 100644 --- a/src/views/Configuration/Firmware/Firmware.vue +++ b/src/views/Configuration/Firmware/Firmware.vue @@ -1,378 +1,93 @@ <template> <b-container fluid="xl"> - <page-title :description="$t('pageFirmware.pageDescription')" /> - <b-row class="mb-4"> - <b-col md="10" lg="12" xl="8" class="pr-xl-4"> - <!-- Firmware on BMC --> - <page-section :section-title="$t('pageFirmware.firmwareOnBmc')"> - <b-card-group deck> - <!-- Current FW --> - <b-card header-bg-variant="success"> - <template #header> - <dl class="mb-0"> - <dt>{{ $t('pageFirmware.current') }}</dt> - <dd class="mb-0">{{ bmcFirmwareCurrentVersion }}</dd> - </dl> - </template> - <dl class="my-0"> - <dt>{{ $t('pageFirmware.state') }}:</dt> - <dd>{{ bmcFirmwareCurrentState }}</dd> - </dl> - <template #footer></template> - </b-card> - - <!-- Backup FW --> - <b-card footer-class="p-0"> - <template #header> - <dl class="mb-0"> - <dt>{{ $t('pageFirmware.backup') }}</dt> - <dd class="mb-0">{{ bmcFirmwareBackupVersion }}</dd> - </dl> - </template> - <dl class="my-0"> - <dt>{{ $t('pageFirmware.state') }}:</dt> - <dd>{{ bmcFirmwareBackupState }}</dd> - </dl> - <template #footer> - <b-btn - v-b-modal.modal-reboot-backup-bmc - :disabled="!bmcFirmwareBackupVersion" - variant="link" - size="sm" - > - <icon-switch class="d-none d-sm-inline-block" /> - {{ $t('pageFirmware.makeCurrentVersion') }}</b-btn - > - </template> - </b-card> - </b-card-group> - </page-section> - - <!-- Firmware on Host --> - <page-section :section-title="$t('pageFirmware.firmwareOnHost')"> - <b-card-group deck> - <!-- Current FW --> - <b-card header-bg-variant="success"> - <template #header> - <dl class="mb-0"> - <dt>{{ $t('pageFirmware.current') }}</dt> - <dd class="mb-0">{{ hostFirmwareCurrentVersion }}</dd> - </dl> - </template> - <!-- State --> - <dl class="my-0"> - <dt>{{ $t('pageFirmware.state') }}:</dt> - <dd>{{ hostFirmwareCurrentState }}</dd> - </dl> - </b-card> - - <!-- Backup FW --> - <b-card> - <template #header> - <dl class="mb-0"> - <dt>{{ $t('pageFirmware.backup') }}</dt> - <dd class="mb-0">{{ hostFirmwareBackupVersion }}</dd> - </dl> - </template> - <!-- State --> - <dl class="my-0"> - <dt>{{ $t('pageFirmware.state') }}:</dt> - <dd>{{ hostFirmwareBackupState }}</dd> - </dl> - </b-card> - </b-card-group> - </page-section> - </b-col> - - <!-- Update code --> - <b-col sm="8" xl="4" class="update-code pl-xl-4"> - <page-section :section-title="$t('pageFirmware.updateCode')"> - <b-form @submit.prevent="onSubmitUpload"> - <b-form-group :label="$t('pageFirmware.form.uploadLocation')"> - <b-form-radio v-model="isWorkstationSelected" :value="true"> - {{ $t('pageFirmware.form.workstation') }} - </b-form-radio> - <b-form-radio v-model="isWorkstationSelected" :value="false"> - {{ $t('pageFirmware.form.tftpServer') }} - </b-form-radio> - </b-form-group> - - <!-- Workstation Upload --> - <template v-if="isWorkstationSelected"> - <b-form-group :label="$t('pageFirmware.form.imageFile')"> - <b-form-text id="image-file-help-block"> - {{ $t('pageFirmware.form.onlyTarFilesAccepted') }} - </b-form-text> - <form-file - id="image-file" - accept=".tar" - :state="getValidationState($v.file)" - aria-describedby="image-file-help-block" - @input="onFileUpload($event)" - > - <template #invalid> - <b-form-invalid-feedback role="alert"> - {{ $t('global.form.required') }} - </b-form-invalid-feedback> - </template> - </form-file> - </b-form-group> - </template> - - <!-- TFTP Server Upload --> - <template v-else> - <b-form-group - :label="$t('pageFirmware.form.tftpServerAddress')" - label-for="tftp-ip" - > - <b-form-text id="server-address-help-block"> - {{ $t('pageFirmware.form.tftpServerAddressHelper') }} - </b-form-text> - <b-form-input - id="tftp-id" - v-model="tftpIpAddress" - type="text" - :state="getValidationState($v.tftpIpAddress)" - aria-describedby="server-address-help-block" - @input="$v.tftpIpAddress.$touch()" - /> - <b-form-invalid-feedback role="alert"> - {{ $t('global.form.fieldRequired') }} - </b-form-invalid-feedback> - </b-form-group> - <b-form-group - :label="$t('pageFirmware.form.imageFileName')" - label-for="tftp-file-name" - > - <b-form-input - id="tftp-file-name" - v-model="tftpFileName" - type="text" - :state="getValidationState($v.tftpFileName)" - @input="$v.tftpFileName.$touch()" - /> - <b-form-invalid-feedback role="alert"> - {{ $t('global.form.fieldRequired') }} - </b-form-invalid-feedback> - </b-form-group> - </template> + <page-title /> + <alerts-server-power + v-if="isServerPowerOffRequired" + :is-host-off="isHostOff" + /> - <!-- Info alert --> - <alert variant="info" class="mt-4 mb-5"> - <p class="font-weight-bold mb-1"> - {{ $t('pageFirmware.alert.updateProcess') }} - </p> - <p>{{ $t('pageFirmware.alert.updateProcessInfo') }}</p> - </alert> + <!-- Firmware cards --> + <b-row> + <b-col xl="10"> + <!-- BMC Firmware --> + <bmc-cards :is-page-disabled="isPageDisabled" /> - <b-btn type="submit" variant="primary"> - {{ $t('pageFirmware.form.uploadAndRebootBmcOrHost') }} - </b-btn> - </b-form> - </page-section> + <!-- Host Firmware --> + <host-cards v-if="!isSingleFileUploadEnabled" /> </b-col> </b-row> - <!-- Modals --> - <modal-upload @ok="uploadFirmware" /> - <modal-reboot-backup-bmc - :current="bmcFirmwareCurrentVersion || '--'" - :backup="bmcFirmwareBackupVersion || '--'" - @ok="switchBmcFirmware" - /> + <!-- Update firmware--> + <page-section + :section-title="$t('pageFirmware.sectionTitleUpdateFirmware')" + > + <b-row> + <b-col sm="8" md="6" xl="4"> + <!-- Update form --> + <form-update + :is-host-off="isHostOff" + :is-page-disabled="isPageDisabled" + /> + </b-col> + </b-row> + </page-section> </b-container> </template> <script> -import { requiredIf } from 'vuelidate/lib/validators'; -import { mapGetters } from 'vuex'; -import IconSwitch from '@carbon/icons-vue/es/arrows--horizontal/20'; - +import AlertsServerPower from './FirmwareAlertServerPower'; +import BmcCards from './FirmwareCardsBmc'; +import FormUpdate from './FirmwareFormUpdate'; +import HostCards from './FirmwareCardsHost'; import PageSection from '@/components/Global/PageSection'; import PageTitle from '@/components/Global/PageTitle'; -import Alert from '@/components/Global/Alert'; -import ModalUpload from './FirmwareModalUpload'; -import ModalRebootBackupBmc from './FirmwareModalRebootBackupBmc'; -import FormFile from '@/components/Global/FormFile'; -import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; -import BVToastMixin from '@/components/Mixins/BVToastMixin'; export default { - name: 'Firmware', + name: 'FirmwareSingleImage', components: { - Alert, - IconSwitch, - ModalRebootBackupBmc, - ModalUpload, + AlertsServerPower, + BmcCards, + FormUpdate, + HostCards, PageSection, PageTitle, - FormFile, }, - mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin], + mixins: [LoadingBarMixin], beforeRouteLeave(to, from, next) { this.hideLoader(); - this.clearRebootTimeout(); next(); }, data() { return { - isWorkstationSelected: true, - file: null, - tftpIpAddress: null, - tftpFileName: null, - timeoutId: null, - loading: loading, + loading, + isServerPowerOffRequired: + process.env.VUE_APP_SERVER_OFF_REQUIRED === 'true', }; }, computed: { - ...mapGetters('firmware', [ - 'bmcFirmwareCurrentVersion', - 'bmcFirmwareCurrentState', - 'bmcFirmwareBackupVersion', - 'bmcFirmwareBackupState', - 'hostFirmwareCurrentVersion', - 'hostFirmwareCurrentState', - 'hostFirmwareBackupVersion', - 'hostFirmwareBackupState', - ]), - }, - watch: { - isWorkstationSelected: function () { - this.$v.$reset(); - this.file = null; - this.tftpIpAddress = null; - this.tftpFileName = null; + hostStatus() { + return this.$store.getters['global/hostStatus']; + }, + isHostOff() { + return this.hostStatus === 'off' ? true : false; + }, + isSingleFileUploadEnabled() { + return this.$store.getters['firmware/isSingleFileUploadEnabled']; + }, + isPageDisabled() { + if (this.isServerPowerOffRequired) { + return !this.isHostOff || this.loading || this.isOperationInProgress; + } + return this.loading || this.isOperationInProgress; }, }, created() { this.startLoader(); - this.$store.dispatch('firmware/getUpdateServiceApplyTime'); this.$store .dispatch('firmware/getFirmwareInformation') .finally(() => this.endLoader()); }, - validations() { - return { - file: { - required: requiredIf(function () { - return this.isWorkstationSelected; - }), - }, - tftpIpAddress: { - required: requiredIf(function () { - return !this.isWorkstationSelected; - }), - }, - tftpFileName: { - required: requiredIf(function () { - return !this.isWorkstationSelected; - }), - }, - }; - }, - methods: { - onFileUpload(file) { - this.file = file; - this.$v.file.$touch(); - }, - uploadFirmware() { - const startTime = this.$options.filters.formatTime(new Date()); - this.setRebootTimeout(360000); //6 minute timeout - this.infoToast( - this.$t('pageFirmware.toast.infoUploadStartTimeMessage', { startTime }), - { title: this.$t('pageFirmware.toast.infoUploadStartTimeTitle') } - ); - if (this.isWorkstationSelected) { - this.dispatchWorkstationUpload(); - } else { - this.dispatchTftpUpload(); - } - }, - dispatchWorkstationUpload() { - this.$store - .dispatch('firmware/uploadFirmware', this.file) - .then((success) => - this.infoToast(success, { - title: this.$t('pageFirmware.toast.successUploadTitle'), - }) - ) - .catch(({ message }) => { - this.errorToast(message); - this.clearRebootTimeout(); - }); - }, - dispatchTftpUpload() { - const data = { - address: this.tftpIpAddress, - filename: this.tftpFileName, - }; - this.$store - .dispatch('firmware/uploadFirmwareTFTP', data) - .then((success) => - this.infoToast(success, { - title: this.$t('pageFirmware.toast.successUploadTitle'), - }) - ) - .catch(({ message }) => { - this.errorToast(message); - this.clearRebootTimeout(); - }); - }, - switchBmcFirmware() { - this.setRebootTimeout(); - this.$store - .dispatch('firmware/switchBmcFirmware') - .then((success) => - this.infoToast(success, { title: this.$t('global.status.success') }) - ) - .catch(({ message }) => { - this.errorToast(message); - this.clearRebootTimeout(); - }); - }, - setRebootTimeout(timeoutMs = 60000) { - // Set a timeout to disable page interactions while - // an upload or BMC reboot is in progress - this.startLoader(); - this.timeoutId = setTimeout(() => { - this.endLoader(); - this.infoToast( - this.$t('pageFirmware.toast.infoRefreshApplicationMessage'), - { - title: this.$t('pageFirmware.toast.infoRefreshApplicationTitle'), - refreshAction: true, - } - ); - }, timeoutMs); - }, - clearRebootTimeout() { - if (this.timeoutId) { - clearTimeout(this.timeoutId); - this.endLoader(); - } - }, - onSubmitUpload() { - this.$v.$touch(); - if (this.$v.$invalid) return; - this.$bvModal.show('modal-upload'); - }, - }, }; </script> - -<style lang="scss" scoped> -.update-code { - border-left: none; - @include media-breakpoint-up(xl) { - border-left: 1px solid gray('300'); - } -} -.card-footer { - height: 40px; -} -.card-body { - padding: 0.75rem 1.25rem; -} -</style> diff --git a/src/views/Configuration/Firmware/FirmwareAlertServerPower.vue b/src/views/Configuration/Firmware/FirmwareAlertServerPower.vue new file mode 100644 index 00000000..04713115 --- /dev/null +++ b/src/views/Configuration/Firmware/FirmwareAlertServerPower.vue @@ -0,0 +1,50 @@ +<template> + <b-row> + <b-col xl="10"> + <!-- Operation in progress alert --> + <alert v-if="isOperationInProgress" variant="info" class="mb-5"> + <p> + {{ $t('pageFirmware.alert.operationInProgress') }} + </p> + </alert> + <!-- Power off server warning alert --> + <alert v-else-if="!isHostOff" variant="warning" class="mb-5"> + <p class="mb-0"> + {{ $t('pageFirmware.alert.serverMustBePoweredOffTo') }} + </p> + <ul class="m-0"> + <li> + {{ $t('pageFirmware.alert.switchRunningAndBackupImages') }} + </li> + <li> + {{ $t('pageFirmware.alert.updateFirmware') }} + </li> + </ul> + <template #action> + <b-link to="/control/server-power-operations"> + {{ $t('pageFirmware.alert.viewServerPowerOperations') }} + </b-link> + </template> + </alert> + </b-col> + </b-row> +</template> + +<script> +import Alert from '@/components/Global/Alert'; + +export default { + components: { Alert }, + props: { + isHostOff: { + required: true, + type: Boolean, + }, + }, + computed: { + isOperationInProgress() { + return this.$store.getters['controls/isOperationInProgress']; + }, + }, +}; +</script> diff --git a/src/views/Configuration/Firmware/FirmwareCardsBmc.vue b/src/views/Configuration/Firmware/FirmwareCardsBmc.vue new file mode 100644 index 00000000..2f038b9e --- /dev/null +++ b/src/views/Configuration/Firmware/FirmwareCardsBmc.vue @@ -0,0 +1,133 @@ +<template> + <div> + <page-section :section-title="sectionTitle"> + <b-card-group deck> + <!-- Running image --> + <b-card> + <template #header> + <p class="font-weight-bold m-0"> + {{ $t('pageFirmware.cardTitleRunning') }} + </p> + </template> + <dl class="mb-0"> + <dt>{{ $t('pageFirmware.cardBodyVersion') }}</dt> + <dd class="mb-0">{{ runningVersion }}</dd> + </dl> + </b-card> + + <!-- Backup image --> + <b-card> + <template #header> + <p class="font-weight-bold m-0"> + {{ $t('pageFirmware.cardTitleBackup') }} + </p> + </template> + <dl> + <dt>{{ $t('pageFirmware.cardBodyVersion') }}</dt> + <dd> + <status-icon v-if="showBackupImageStatus" status="danger" /> + <span v-if="showBackupImageStatus" class="sr-only"> + {{ backupStatus }} + </span> + {{ backupVersion }} + </dd> + </dl> + <b-btn + v-b-modal.modal-switch-to-running + data-test-id="firmware-button-switchToRunning" + variant="link" + size="sm" + class="py-0 px-1 mt-2" + :disabled="isPageDisabled || !backup" + > + <icon-switch class="d-none d-sm-inline-block" /> + {{ $t('pageFirmware.cardActionSwitchToRunning') }} + </b-btn> + </b-card> + </b-card-group> + </page-section> + <modal-switch-to-running :backup="backupVersion" @ok="switchToRunning" /> + </div> +</template> + +<script> +import IconSwitch from '@carbon/icons-vue/es/arrows--horizontal/20'; +import PageSection from '@/components/Global/PageSection'; +import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; +import BVToastMixin from '@/components/Mixins/BVToastMixin'; + +import ModalSwitchToRunning from './FirmwareModalSwitchToRunning'; + +export default { + components: { IconSwitch, ModalSwitchToRunning, PageSection }, + mixins: [BVToastMixin, LoadingBarMixin], + props: { + isPageDisabled: { + required: true, + type: Boolean, + default: false, + }, + }, + data() { + return { + loading, + }; + }, + computed: { + isSingleFileUploadEnabled() { + return this.$store.getters['firmware/isSingleFileUploadEnabled']; + }, + sectionTitle() { + if (this.isSingleFileUploadEnabled) { + return this.$t('pageFirmware.sectionTitleBmcCardsCombined'); + } + return this.$t('pageFirmware.sectionTitleBmcCards'); + }, + running() { + return this.$store.getters['firmware/activeBmcFirmware']; + }, + backup() { + return this.$store.getters['firmware/backupBmcFirmware']; + }, + runningVersion() { + return this.running?.version || '--'; + }, + backupVersion() { + return this.backup?.version || '--'; + }, + backupStatus() { + return this.backup?.status || null; + }, + showBackupImageStatus() { + return ( + this.backupStatus === 'Critical' || this.backupStatus === 'Warning' + ); + }, + }, + methods: { + switchToRunning() { + this.startLoader(); + const timerId = setTimeout(() => { + this.endLoader(); + this.infoToast(this.$t('pageFirmware.toast.verifySwitchMessage'), { + title: this.$t('pageFirmware.toast.verifySwitch'), + refreshAction: true, + }); + }, 60000); + + this.$store + .dispatch('firmware/switchBmcFirmwareAndReboot') + .then(() => + this.infoToast(this.$t('pageFirmware.toast.rebootStartedMessage'), { + title: this.$t('pageFirmware.toast.rebootStarted'), + }) + ) + .catch(({ message }) => { + this.errorToast(message); + clearTimeout(timerId); + this.endLoader(); + }); + }, + }, +}; +</script> diff --git a/src/views/Configuration/Firmware/FirmwareCardsHost.vue b/src/views/Configuration/Firmware/FirmwareCardsHost.vue new file mode 100644 index 00000000..b4a8e90d --- /dev/null +++ b/src/views/Configuration/Firmware/FirmwareCardsHost.vue @@ -0,0 +1,73 @@ +<template> + <page-section :section-title="$t('pageFirmware.sectionTitleHostCards')"> + <b-card-group deck> + <!-- Running image --> + <b-card> + <template #header> + <p class="font-weight-bold m-0"> + {{ $t('pageFirmware.cardTitleRunning') }} + </p> + </template> + <dl class="mb-0"> + <dt>{{ $t('pageFirmware.cardBodyVersion') }}</dt> + <dd class="mb-0">{{ runningVersion }}</dd> + </dl> + </b-card> + + <!-- Backup image --> + <b-card> + <template #header> + <p class="font-weight-bold m-0"> + {{ $t('pageFirmware.cardTitleBackup') }} + </p> + </template> + <dl class="mb-0"> + <dt>{{ $t('pageFirmware.cardBodyVersion') }}</dt> + <dd class="mb-0"> + <status-icon v-if="showBackupImageStatus" status="danger" /> + <span v-if="showBackupImageStatus" class="sr-only"> + {{ backupStatus }} + </span> + {{ backupVersion }} + </dd> + </dl> + </b-card> + </b-card-group> + </page-section> +</template> + +<script> +import PageSection from '@/components/Global/PageSection'; + +export default { + components: { PageSection }, + computed: { + running() { + return this.$store.getters['firmware/activeHostFirmware']; + }, + backup() { + return this.$store.getters['firmware/backupHostFirmware']; + }, + runningVersion() { + return this.running?.version || '--'; + }, + backupVersion() { + return this.backup?.version || '--'; + }, + backupStatus() { + return this.backup?.status || null; + }, + showBackupImageStatus() { + return ( + this.backupStatus === 'Critical' || this.backupStatus === 'Warning' + ); + }, + }, +}; +</script> + +<style lang="scss" scoped> +.page-section { + margin-top: -$spacer * 1.5; +} +</style> diff --git a/src/views/Configuration/Firmware/FirmwareFormUpdate.vue b/src/views/Configuration/Firmware/FirmwareFormUpdate.vue new file mode 100644 index 00000000..9f67e8d0 --- /dev/null +++ b/src/views/Configuration/Firmware/FirmwareFormUpdate.vue @@ -0,0 +1,204 @@ +<template> + <div> + <div class="form-background p-3"> + <b-form @submit.prevent="onSubmitUpload"> + <b-form-group + v-if="isTftpUploadAvailable" + :label="$t('pageFirmware.form.updateFirmware.fileSource')" + :disabled="isPageDisabled" + > + <b-form-radio v-model="isWorkstationSelected" :value="true"> + {{ $t('pageFirmware.form.updateFirmware.workstation') }} + </b-form-radio> + <b-form-radio v-model="isWorkstationSelected" :value="false"> + {{ $t('pageFirmware.form.updateFirmware.tftpServer') }} + </b-form-radio> + </b-form-group> + + <!-- Workstation Upload --> + <template v-if="isWorkstationSelected"> + <b-form-group + :label="$t('pageFirmware.form.updateFirmware.imageFile')" + label-for="image-file" + > + <b-form-text id="image-file-help-block"> + {{ $t('pageFirmware.form.updateFirmware.imageFileHelperText') }} + </b-form-text> + <form-file + id="image-file" + accept=".tar" + :disabled="isPageDisabled" + :state="getValidationState($v.file)" + aria-describedby="image-file-help-block" + @input="onFileUpload($event)" + > + <template #invalid> + <b-form-invalid-feedback role="alert"> + {{ $t('global.form.required') }} + </b-form-invalid-feedback> + </template> + </form-file> + </b-form-group> + </template> + + <!-- TFTP Server Upload --> + <template v-else> + <b-form-group + :label="$t('pageFirmware.form.updateFirmware.fileAddress')" + label-for="tftp-address" + > + <b-form-input + id="tftp-address" + v-model="tftpFileAddress" + type="text" + :state="getValidationState($v.tftpFileAddress)" + :disabled="isPageDisabled" + @input="$v.tftpFileAddress.$touch()" + /> + <b-form-invalid-feedback role="alert"> + {{ $t('global.form.fieldRequired') }} + </b-form-invalid-feedback> + </b-form-group> + </template> + <b-btn + data-test-id="firmware-button-startUpdate" + type="submit" + variant="primary" + :disabled="isPageDisabled" + > + {{ $t('pageFirmware.form.updateFirmware.startUpdate') }} + </b-btn> + <alert + v-if="isServerPowerOffRequired && !isHostOff" + variant="warning" + :small="true" + class="mt-4" + > + <p class="col-form-label"> + {{ + $t('pageFirmware.alert.serverMustBePoweredOffToUpdateFirmware') + }} + </p> + </alert> + </b-form> + </div> + + <!-- Modals --> + <modal-update-firmware @ok="updateFirmware" /> + </div> +</template> + +<script> +import { requiredIf } from 'vuelidate/lib/validators'; + +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; + +import Alert from '@/components/Global/Alert'; +import FormFile from '@/components/Global/FormFile'; +import ModalUpdateFirmware from './FirmwareModalUpdateFirmware'; + +export default { + components: { Alert, FormFile, ModalUpdateFirmware }, + mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin], + props: { + isPageDisabled: { + required: true, + type: Boolean, + default: false, + }, + isHostOff: { + required: true, + type: Boolean, + }, + }, + data() { + return { + loading, + isWorkstationSelected: true, + file: null, + tftpFileAddress: null, + isServerPowerOffRequired: + process.env.VUE_APP_SERVER_OFF_REQUIRED === 'true', + }; + }, + computed: { + isTftpUploadAvailable() { + return this.$store.getters['firmware/isTftpUploadAvailable']; + }, + }, + watch: { + isWorkstationSelected: function () { + this.$v.$reset(); + this.file = null; + this.tftpFileAddress = null; + }, + }, + validations() { + return { + file: { + required: requiredIf(function () { + return this.isWorkstationSelected; + }), + }, + tftpFileAddress: { + required: requiredIf(function () { + return !this.isWorkstationSelected; + }), + }, + }; + }, + created() { + this.$store.dispatch('firmware/getUpdateServiceSettings'); + }, + methods: { + updateFirmware() { + this.startLoader(); + const timerId = setTimeout(() => { + this.endLoader(); + this.infoToast(this.$t('pageFirmware.toast.verifyUpdateMessage'), { + title: this.$t('pageFirmware.toast.verifyUpdate'), + refreshAction: true, + }); + }, 360000); + this.infoToast(this.$t('pageFirmware.toast.updateStartedMessage'), { + title: this.$t('pageFirmware.toast.updateStarted'), + timestamp: true, + }); + if (this.isWorkstationSelected) { + this.dispatchWorkstationUpload(timerId); + } else { + this.dispatchTftpUpload(timerId); + } + }, + dispatchWorkstationUpload(timerId) { + this.$store + .dispatch('firmware/uploadFirmware', this.file) + .catch(({ message }) => { + this.endLoader(); + this.errorToast(message); + clearTimeout(timerId); + }); + }, + dispatchTftpUpload(timerId) { + this.$store + .dispatch('firmware/uploadFirmwareTFTP', this.tftpFileAddress) + .catch(({ message }) => { + this.endLoader(); + this.errorToast(message); + clearTimeout(timerId); + }); + }, + onSubmitUpload() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$bvModal.show('modal-update-firmware'); + }, + onFileUpload(file) { + this.file = file; + this.$v.file.$touch(); + }, + }, +}; +</script> diff --git a/src/views/Configuration/Firmware/FirmwareModalRebootBackupBmc.vue b/src/views/Configuration/Firmware/FirmwareModalRebootBackupBmc.vue deleted file mode 100644 index 305bb6cb..00000000 --- a/src/views/Configuration/Firmware/FirmwareModalRebootBackupBmc.vue +++ /dev/null @@ -1,34 +0,0 @@ -<template> - <b-modal - id="modal-reboot-backup-bmc" - :ok-title="$t('pageFirmware.modal.rebootFromBackup.primaryAction')" - :cancel-title="$t('global.action.cancel')" - :title="$t('pageFirmware.modal.rebootFromBackup.title')" - @ok="$emit('ok')" - > - <p> - {{ $t('pageFirmware.modal.rebootFromBackup.message1', { backup }) }} - </p> - <p> - {{ $t('pageFirmware.modal.rebootFromBackup.message2', { current }) }} - </p> - <p class="font-weight-bold"> - {{ $t('pageFirmware.modal.rebootFromBackup.message3', { backup }) }} - </p> - </b-modal> -</template> - -<script> -export default { - props: { - current: { - type: String, - required: true, - }, - backup: { - type: String, - required: true, - }, - }, -}; -</script> diff --git a/src/views/Configuration/Firmware/FirmwareModalSwitchToRunning.vue b/src/views/Configuration/Firmware/FirmwareModalSwitchToRunning.vue new file mode 100644 index 00000000..dc4a4973 --- /dev/null +++ b/src/views/Configuration/Firmware/FirmwareModalSwitchToRunning.vue @@ -0,0 +1,31 @@ +<template> + <b-modal + id="modal-switch-to-running" + :ok-title="$t('pageFirmware.modal.switchImages')" + :cancel-title="$t('global.action.cancel')" + :title="$t('pageFirmware.modal.switchRunningImage')" + @ok="$emit('ok')" + > + <p> + {{ $t('pageFirmware.modal.switchRunningImageInfo') }} + </p> + <p class="m-0"> + {{ + $t('pageFirmware.modal.switchRunningImageInfo2', { + backup, + }) + }} + </p> + </b-modal> +</template> + +<script> +export default { + props: { + backup: { + type: String, + required: true, + }, + }, +}; +</script> diff --git a/src/views/Configuration/Firmware/FirmwareModalUpdateFirmware.vue b/src/views/Configuration/Firmware/FirmwareModalUpdateFirmware.vue new file mode 100644 index 00000000..18355217 --- /dev/null +++ b/src/views/Configuration/Firmware/FirmwareModalUpdateFirmware.vue @@ -0,0 +1,44 @@ +<template> + <b-modal + id="modal-update-firmware" + :title="$t('pageFirmware.sectionTitleUpdateFirmware')" + :ok-title="$t('pageFirmware.form.updateFirmware.startUpdate')" + :cancel-title="$t('global.action.cancel')" + @ok="$emit('ok')" + > + <template v-if="isSingleFileUploadEnabled"> + <p> + {{ $t('pageFirmware.modal.updateFirmwareInfo') }} + </p> + <p> + {{ + $t('pageFirmware.modal.updateFirmwareInfo2', { + running: runningBmcVersion, + }) + }} + </p> + <p class="m-0"> + {{ $t('pageFirmware.modal.updateFirmwareInfo3') }} + </p> + </template> + <template v-else> + {{ $t('pageFirmware.modal.updateFirmwareInfoDefault') }} + </template> + </b-modal> +</template> + +<script> +export default { + computed: { + runningBmc() { + return this.$store.getters['firmware/activeBmcFirmware']; + }, + runningBmcVersion() { + return this.runningBmc?.version || '--'; + }, + isSingleFileUploadEnabled() { + return this.$store.getters['firmware/isSingleFileUploadEnabled']; + }, + }, +}; +</script> diff --git a/src/views/Configuration/Firmware/FirmwareModalUpload.vue b/src/views/Configuration/Firmware/FirmwareModalUpload.vue deleted file mode 100644 index 3425904f..00000000 --- a/src/views/Configuration/Firmware/FirmwareModalUpload.vue +++ /dev/null @@ -1,20 +0,0 @@ -<template> - <b-modal - id="modal-upload" - ok-variant="danger" - :title="$t('pageFirmware.modal.uploadAndRebootBmcOrHost.title')" - :ok-title="$t('pageFirmware.modal.uploadAndRebootBmcOrHost.primaryAction')" - :cancel-title="$t('global.action.cancel')" - @ok="$emit('ok')" - > - <p> - {{ $t('pageFirmware.modal.uploadAndRebootBmcOrHost.message1') }} - </p> - <p> - {{ $t('pageFirmware.modal.uploadAndRebootBmcOrHost.message2') }} - </p> - <p class="font-weight-bold"> - {{ $t('pageFirmware.modal.uploadAndRebootBmcOrHost.message3') }} - </p> - </b-modal> -</template> diff --git a/src/views/Overview/Overview.vue b/src/views/Overview/Overview.vue index 1d2da441..2436e393 100644 --- a/src/views/Overview/Overview.vue +++ b/src/views/Overview/Overview.vue @@ -104,13 +104,6 @@ export default { PageSection, }, mixins: [LoadingBarMixin], - data() { - return { - firmwareStoreModuleName: this.$store.hasModule('firmwareSingleImage') - ? 'firmwareSingleImage' - : 'firmware', - }; - }, computed: { ...mapState({ server: (state) => state.system.systems[0], @@ -129,15 +122,18 @@ export default { if (this.server) return this.server.serialNumber || '--'; return '--'; }, - hostFirmwareVersion() { - if (this.server) return this.server.firmwareVersion || '--'; - return '--'; - }, }), + activeHostFirmware() { + return this.$store.getters[`firmware/activeHostFirmware`]; + }, + hostFirmwareVersion() { + return this.activeHostFirmware?.version || '--'; + }, + activeBmcFirmware() { + return this.$store.getters[`firmware/activeBmcFirmware`]; + }, bmcFirmwareVersion() { - return this.$store.getters[ - `${this.firmwareStoreModuleName}/bmcFirmwareCurrentVersion` - ]; + return this.activeBmcFirmware?.version || '--'; }, }, created() { @@ -153,9 +149,7 @@ export default { }); Promise.all([ this.$store.dispatch('system/getSystem'), - this.$store.dispatch( - `${this.firmwareStoreModuleName}/getFirmwareInformation` - ), + this.$store.dispatch(`firmware/getFirmwareInformation`), this.$store.dispatch('powerControl/getPowerControl'), quicklinksPromise, networkPromise, |