diff options
author | Yoshie Muranaka <yoshiemuranaka@gmail.com> | 2020-10-06 19:24:14 +0300 |
---|---|---|
committer | Derick Montague <derick.montague@ibm.com> | 2020-10-26 16:48:19 +0300 |
commit | 0b980dbfe69e1b3f59d5b26e83d16ecbdab95ecb (patch) | |
tree | 57c664cedf5702d50cd2513979bdf36b1b1d71a7 /src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue | |
parent | 7026cad99fbc3b4584e5ce60dbb8476f6c6f41f7 (diff) | |
download | webui-vue-0b980dbfe69e1b3f59d5b26e83d16ecbdab95ecb.tar.xz |
Make copy of single file firmware upload
Make a copy of single file firmware upload component and store
in env directory.
Update IBM router to use copied single file firmware components.
Update IBM store module to use copied single file firmware store.
Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: I046ce6c69a02b90400058866295b84c5435f5a4b
Diffstat (limited to 'src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue')
-rw-r--r-- | src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue b/src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue new file mode 100644 index 00000000..f719631a --- /dev/null +++ b/src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue @@ -0,0 +1,405 @@ +<template> + <b-container fluid="xl"> + <page-title :description="$t('pageFirmware.pageDescription')" /> + <!-- Operation in progress alert --> + <alert v-if="isOperationInProgress" variant="info" class="mb-5"> + <p> + {{ $t('pageFirmware.alert.operationInProgress') }} + </p> + </alert> + <!-- Shutdown server warning alert --> + <alert v-else-if="!isHostOff" variant="warning" class="mb-5"> + <p class="font-weight-bold mb-1"> + {{ $t('pageFirmware.alert.serverShutdownRequiredBeforeUpdate') }} + </p> + {{ $t('pageFirmware.alert.serverShutdownRequiredInfo') }} + <template v-slot:action> + <b-btn variant="link" class="text-nowrap" @click="onClickShutDown"> + {{ $t('pageFirmware.alert.shutDownServer') }} + </b-btn> + </template> + </alert> + <b-row class="mb-4"> + <!-- Firmware on system --> + <b-col md="10" lg="12" xl="8" class="pr-xl-4"> + <page-section :section-title="$t('pageFirmware.firmwareOnSystem')"> + <b-card-group deck> + <!-- Current FW --> + <b-card header-bg-variant="success"> + <template v-slot:header> + <dl class="mb-0"> + <dt>{{ $t('pageFirmware.current') }}</dt> + <dd class="mb-0">{{ systemFirmwareVersion }}</dd> + </dl> + </template> + <b-row> + <b-col xs="6"> + <dl class="my-0"> + <dt>{{ $t('pageFirmware.bmcStatus') }}</dt> + <dd>{{ $t('pageFirmware.running') }}</dd> + </dl> + </b-col> + <b-col xs="6"> + <dl class="my-0"> + <dt>{{ $t('pageFirmware.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> + </b-col> + </b-row> + </b-card> + + <!-- Backup FW --> + <b-card> + <template v-slot:header> + <dl class="mb-0"> + <dt>{{ $t('pageFirmware.backup') }}</dt> + <dd class="mb-0">{{ backupFirmwareVersion }}</dd> + </dl> + </template> + <b-row> + <b-col xs="6"> + <dl class="my-0"> + <dt>{{ $t('pageFirmware.state') }}</dt> + <dd>{{ backupFirmwareStatus }}</dd> + </dl> + </b-col> + </b-row> + </b-card> + </b-card-group> + </page-section> + + <!-- Change to backup image --> + <page-section :section-title="$t('pageFirmware.changeToBackupImage')"> + <dl class="mb-5"> + <dt> + {{ $t('pageFirmware.backupImage') }} + </dt> + <dd>{{ backupFirmwareVersion }}</dd> + </dl> + <b-btn + v-b-modal.modal-reboot-backup + type="button" + variant="primary" + :disabled="isPageDisabled || !isRebootFromBackupAvailable" + > + {{ $t('pageFirmware.changeAndRebootBmc') }} + </b-btn> + </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')" + :disabled="isPageDisabled" + > + <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')" + label-for="image-file" + > + <b-form-text id="image-file-help-block"> + {{ $t('pageFirmware.form.onlyTarFilesAccepted') }} + </b-form-text> + <b-form-file + id="image-file" + v-model="file" + accept=".tar" + aria-describedby="image-file-help-block" + :browse-text="$t('global.fileUpload.browseText')" + :drop-placeholder="$t('global.fileUpload.dropPlaceholder')" + :placeholder="$t('global.fileUpload.placeholder')" + :disabled="isPageDisabled" + :state="getValidationState($v.file)" + @input="$v.file.$touch()" + /> + <b-form-invalid-feedback role="alert"> + {{ $t('global.form.required') }} + </b-form-invalid-feedback> + </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)" + :disabled="isPageDisabled" + 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)" + :disabled="isPageDisabled" + @input="$v.tftpFileName.$touch()" + /> + <b-form-invalid-feedback role="alert"> + {{ $t('global.form.fieldRequired') }} + </b-form-invalid-feedback> + </b-form-group> + </template> + + <!-- 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> + <b-form-group> + <b-btn type="submit" variant="primary" :disabled="isPageDisabled"> + {{ $t('pageFirmware.form.uploadAndRebootBmc') }} + </b-btn> + </b-form-group> + </b-form> + </page-section> + </b-col> + </b-row> + + <!-- Modals --> + <modal-upload @ok="uploadFirmware" /> + <modal-reboot-backup + :current="systemFirmwareVersion" + :backup="backupFirmwareVersion" + @ok="rebootFromBackup" + /> + </b-container> +</template> + +<script> +import { requiredIf } from 'vuelidate/lib/validators'; +import { mapGetters } from 'vuex'; + +import PageSection from '@/components/Global/PageSection'; +import PageTitle from '@/components/Global/PageTitle'; +import Alert from '@/components/Global/Alert'; +import ModalUpload from './FirmwareSingleImageModalUpload'; +import ModalRebootBackup from './FirmwareSingleImageModalRebootBackup'; + +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; +import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; +import BVToastMixin from '@/components/Mixins/BVToastMixin'; + +export default { + name: 'FirmwareSingleImage', + components: { + Alert, + ModalRebootBackup, + ModalUpload, + PageSection, + PageTitle + }, + mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin], + data() { + return { + isWorkstationSelected: true, + file: null, + tftpIpAddress: null, + tftpFileName: null, + timeoutId: null + }; + }, + computed: { + hostStatus() { + return this.$store.getters['global/hostStatus']; + }, + isHostOff() { + return this.hostStatus === 'off' ? true : false; + }, + isOperationInProgress() { + return this.$store.getters['controls/isOperationInProgress']; + }, + ...mapGetters('firmwareSingleImage', [ + 'backupFirmwareStatus', + 'backupFirmwareVersion', + 'isRebootFromBackupAvailable', + 'systemFirmwareVersion' + ]), + isPageDisabled() { + return !this.isHostOff || this.loading || this.isOperationInProgress; + } + }, + watch: { + isWorkstationSelected: function() { + this.$v.$reset(); + this.file = null; + this.tftpIpAddress = null; + this.tftpFileName = null; + } + }, + created() { + this.startLoader(); + this.$store.dispatch('firmwareSingleImage/getUpdateServiceApplyTime'); + Promise.all([ + this.$store.dispatch('global/getHostStatus'), + this.$store.dispatch('firmwareSingleImage/getSystemFirwareVersion') + ]).finally(() => this.endLoader()); + }, + beforeRouteLeave(to, from, next) { + this.hideLoader(); + this.clearRebootTimeout(); + next(); + }, + validations() { + return { + file: { + required: requiredIf(function() { + return this.isWorkstationSelected; + }) + }, + tftpIpAddress: { + required: requiredIf(function() { + return !this.isWorkstationSelected; + }) + }, + tftpFileName: { + required: requiredIf(function() { + return !this.isWorkstationSelected; + }) + } + }; + }, + methods: { + uploadFirmware() { + const startTime = this.$options.filters.formatTime(new Date()); + this.setRebootTimeout(360000); //6 minute timeout + this.infoToast( + this.$t('pageFirmware.toast.infoUploadStartTimeMessage', { startTime }), + this.$t('pageFirmware.toast.infoUploadStartTimeTitle') + ); + if (this.isWorkstationSelected) { + this.dispatchWorkstationUpload(); + } else { + this.dispatchTftpUpload(); + } + }, + dispatchWorkstationUpload() { + this.$store + .dispatch('firmwareSingleImage/uploadFirmware', this.file) + .then(success => + this.infoToast( + success, + this.$t('pageFirmware.toast.successUploadTitle') + ) + ) + .catch(({ message }) => { + this.errorToast(message); + this.clearRebootTimeout(); + }); + }, + dispatchTftpUpload() { + const data = { + address: this.tftpIpAddress, + filename: this.tftpFileName + }; + this.$store + .dispatch('firmwareSingleImage/uploadFirmwareTFTP', data) + .then(success => + this.infoToast( + success, + this.$t('pageFirmware.toast.successUploadTitle') + ) + ) + .catch(({ message }) => { + this.errorToast(message); + this.clearRebootTimeout(); + }); + }, + rebootFromBackup() { + this.setRebootTimeout(); + this.$store + .dispatch('firmwareSingleImage/switchFirmwareAndReboot') + .then(success => + this.infoToast(success, 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'), + this.$t('pageFirmware.toast.infoRefreshApplicationTitle') + ); + }, timeoutMs); + }, + clearRebootTimeout() { + if (this.timeoutId) { + clearTimeout(this.timeoutId); + this.endLoader(); + } + }, + onSubmitUpload() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$bvModal.show('modal-upload'); + }, + onClickShutDown() { + this.$bvModal + .msgBoxConfirm(this.$t('pageFirmware.modal.serverShutdownMessage'), { + title: this.$t('pageFirmware.modal.serverShutdownWillCauseOutage'), + okTitle: this.$t('pageFirmware.modal.shutDownServer'), + okVariant: 'danger' + }) + .then(shutdownConfirmed => { + if (shutdownConfirmed) + this.$store.dispatch('controls/hostSoftPowerOff'); + }); + } + } +}; +</script> + +<style lang="scss" scoped> +.update-code { + border-left: none; + @include media-breakpoint-up(xl) { + border-left: 1px solid gray('300'); + } +} +</style> |