Update single file firmware card layout
Updates will enable a more dynamic firmware page layout
by inspecting all firmware images for host images.
GETs all firmware inventory at Redfish endpoint
'/redfish/v1/UpdateService/FirmwareInventory'
then checks if any image includes RelatedItem
'/redfish/v1/Systems/system/Bios' to determine whether
the UI should show combined or separate firmware cards
for BMC and Host.
This is part of an effort to make the firmware page more dynamic.
These changes are only visisble with ibm dotenv variables.
Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: I8542a27c6ff421bcb24c8b2570dbe150d5c1ce6c
diff --git a/src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue b/src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue
index b7ad4c5..2e601bd 100644
--- a/src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue
+++ b/src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue
@@ -1,244 +1,68 @@
<template>
<b-container fluid="xl">
<page-title />
- <b-row v-if="isServerPowerOffRequired">
- <b-col xl="10">
- <!-- Operation in progress alert -->
- <alert v-if="isOperationInProgress" variant="info" class="mb-5">
- <p>
- {{ $t('pageFirmware.singleFileUpload.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.singleFileUpload.alert.serverMustBePoweredOffTo')
- }}
- </p>
- <ul class="m-0">
- <li>
- {{
- $t(
- 'pageFirmware.singleFileUpload.alert.switchRunningAndBackupImages'
- )
- }}
- </li>
- <li>
- {{ $t('pageFirmware.singleFileUpload.alert.updateFirmware') }}
- </li>
- </ul>
- <template #action>
- <b-link to="/control/server-power-operations">
- {{
- $t(
- 'pageFirmware.singleFileUpload.alert.viewServerPowerOperations'
- )
- }}
- </b-link>
- </template>
- </alert>
- </b-col>
- </b-row>
+ <alerts-server-power
+ v-if="isServerPowerOffRequired"
+ :is-host-off="isHostOff"
+ />
+
+ <!-- Firmware cards -->
<b-row>
<b-col xl="10">
- <page-section>
- <b-card-group deck>
- <!-- Running image -->
- <b-card>
- <template #header>
- <p class="font-weight-bold m-0">
- {{ $t('pageFirmware.singleFileUpload.runningImage') }}
- </p>
- </template>
- <dl class="mb-0">
- <dt>{{ $t('pageFirmware.singleFileUpload.bmcAndServer') }}</dt>
- <dd class="mb-0">{{ systemFirmwareVersion }}</dd>
- </dl>
- </b-card>
+ <!-- BMC Firmware -->
+ <bmc-cards :is-page-disabled="isPageDisabled" />
- <!-- Backup image -->
- <b-card>
- <template #header>
- <p class="font-weight-bold m-0">
- {{ $t('pageFirmware.singleFileUpload.backupImage') }}
- </p>
- </template>
- <dl>
- <dt>
- {{ $t('pageFirmware.singleFileUpload.bmcAndServer') }}
- </dt>
- <dd>
- <status-icon v-if="showBackupImageStatus" status="danger" />
- <span v-if="showBackupImageStatus" class="sr-only">
- {{ backupFirmwareStatus }}
- </span>
- {{ backupFirmwareVersion }}
- </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 || !isRebootFromBackupAvailable"
- >
- <icon-switch class="d-none d-sm-inline-block" />
- {{ $t('pageFirmware.singleFileUpload.switchToRunning') }}
- </b-btn>
- </b-card>
- </b-card-group>
- </page-section>
- </b-col>
- </b-row>
- <b-row>
- <!-- Update firmware -->
- <b-col sm="8" md="6" xl="4">
- <page-section
- :section-title="$t('pageFirmware.singleFileUpload.updateFirmware')"
- >
- <div class="form-background p-3">
- <b-form @submit.prevent="onSubmitUpload">
- <b-form-group
- v-if="isTftpUploadAvailable"
- :label="$t('pageFirmware.singleFileUpload.fileSource')"
- :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>
- <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.singleFileUpload.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.singleFileUpload.startUpdate') }}
- </b-btn>
- <alert
- v-if="isServerPowerOffRequired && !isHostOff"
- variant="warning"
- :small="true"
- class="mt-4"
- >
- <p class="col-form-label">
- {{
- $t(
- 'pageFirmware.singleFileUpload.alert.serverMustBePoweredOffToUpdateFirmware'
- )
- }}
- </p>
- </alert>
- </b-form>
- </div>
- </page-section>
+ <!-- Host Firmware -->
+ <host-cards v-if="!isSingleFileUploadEnabled" />
</b-col>
</b-row>
- <!-- Modals -->
- <modal-update-firmware
- :running="systemFirmwareVersion"
- :backup="backupFirmwareVersion"
- @ok="updateFirmware"
- />
- <modal-switch-to-running
- :backup="backupFirmwareVersion"
- @ok="switchToRunning"
- />
+ <!-- Update firmware-->
+ <page-section
+ :section-title="
+ $t('pageFirmware.singleFileUpload.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 FormFile from '@/components/Global/FormFile';
-import StatusIcon from '@/components/Global/StatusIcon';
-import ModalUpdateFirmware from './FirmwareSingleImageModalUpdateFirmware';
-import ModalSwitchToRunning from './FirmwareSingleImageModalSwitchToRunning';
-import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin';
-import BVToastMixin from '@/components/Mixins/BVToastMixin';
export default {
name: 'FirmwareSingleImage',
components: {
- Alert,
- FormFile,
- IconSwitch,
- ModalSwitchToRunning,
- ModalUpdateFirmware,
+ AlertsServerPower,
+ BmcCards,
+ FormUpdate,
+ HostCards,
PageSection,
PageTitle,
- StatusIcon,
},
- mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin],
+ mixins: [LoadingBarMixin],
beforeRouteLeave(to, from, next) {
this.hideLoader();
next();
},
data() {
return {
- isWorkstationSelected: true,
- file: null,
- tftpFileAddress: null,
- timeoutId: null,
loading,
isServerPowerOffRequired:
process.env.VUE_APP_SERVER_OFF_REQUIRED === 'true',
@@ -251,152 +75,23 @@
isHostOff() {
return this.hostStatus === 'off' ? true : false;
},
- isOperationInProgress() {
- return this.$store.getters['controls/isOperationInProgress'];
+ isSingleFileUploadEnabled() {
+ return this.$store.getters[
+ 'firmwareSingleImage/isSingleFileUploadEnabled'
+ ];
},
- ...mapGetters('firmwareSingleImage', [
- 'backupFirmwareStatus',
- 'backupFirmwareVersion',
- 'isRebootFromBackupAvailable',
- 'systemFirmwareVersion',
- 'isTftpUploadAvailable',
- ]),
isPageDisabled() {
if (this.isServerPowerOffRequired) {
return !this.isHostOff || this.loading || this.isOperationInProgress;
}
return this.loading || this.isOperationInProgress;
},
- showBackupImageStatus() {
- return (
- this.backupFirmwareStatus === 'Critical' ||
- this.backupFirmwareStatus === 'Warning'
- );
- },
- },
- watch: {
- isWorkstationSelected: function () {
- this.$v.$reset();
- this.file = null;
- this.tftpFileAddress = null;
- },
},
created() {
this.startLoader();
- this.$store.dispatch('firmwareSingleImage/getUpdateServiceSettings');
- Promise.all([
- this.$store.dispatch('global/getHostStatus'),
- this.$store.dispatch('firmwareSingleImage/getFirmwareInformation'),
- ]).finally(() => this.endLoader());
- },
- validations() {
- return {
- file: {
- required: requiredIf(function () {
- return this.isWorkstationSelected;
- }),
- },
- tftpFileAddress: {
- required: requiredIf(function () {
- return !this.isWorkstationSelected;
- }),
- },
- };
- },
- methods: {
- updateFirmware() {
- this.setRebootTimeout(360000, () => {
- this.infoToast(
- this.$t('pageFirmware.singleFileUpload.toast.verifyUpdateMessage'),
- {
- title: this.$t('pageFirmware.singleFileUpload.toast.verifyUpdate'),
- refreshAction: true,
- }
- );
- });
- this.infoToast(
- this.$t('pageFirmware.singleFileUpload.toast.updateStartedMessage'),
- {
- title: this.$t('pageFirmware.singleFileUpload.toast.updateStarted'),
- timestamp: true,
- }
- );
- if (this.isWorkstationSelected) {
- this.dispatchWorkstationUpload();
- } else {
- this.dispatchTftpUpload();
- }
- },
- dispatchWorkstationUpload() {
- this.$store
- .dispatch('firmwareSingleImage/uploadFirmware', this.file)
- .catch(({ message }) => {
- this.errorToast(message);
- this.clearRebootTimeout();
- });
- },
- dispatchTftpUpload() {
- this.$store
- .dispatch(
- 'firmwareSingleImage/uploadFirmwareTFTP',
- this.tftpFileAddress
- )
- .catch(({ message }) => {
- this.errorToast(message);
- this.clearRebootTimeout();
- });
- },
- switchToRunning() {
- this.setRebootTimeout(60000, () => {
- this.infoToast(
- this.$t('pageFirmware.singleFileUpload.toast.verifySwitchMessage'),
- {
- title: this.$t('pageFirmware.singleFileUpload.toast.verifySwitch'),
- refreshAction: true,
- }
- );
- });
- this.$store
- .dispatch('firmwareSingleImage/switchFirmwareAndReboot')
- .then(() =>
- this.infoToast(
- this.$t('pageFirmware.singleFileUpload.toast.rebootStartedMessage'),
- {
- title: this.$t(
- 'pageFirmware.singleFileUpload.toast.rebootStarted'
- ),
- }
- )
- )
- .catch(({ message }) => {
- this.errorToast(message);
- this.clearRebootTimeout();
- });
- },
- setRebootTimeout(timeoutMs = 60000, callback) {
- // Set a timeout to disable page interactions
- // during a BMC reboot
- this.startLoader();
- this.timeoutId = setTimeout(() => {
- this.endLoader();
- if (callback) callback();
- }, timeoutMs);
- },
- clearRebootTimeout() {
- if (this.timeoutId) {
- clearTimeout(this.timeoutId);
- this.endLoader();
- }
- },
- onSubmitUpload() {
- this.$v.$touch();
- if (this.$v.$invalid) return;
- this.$bvModal.show('modal-update-firmware');
- },
- onFileUpload(file) {
- this.file = file;
- this.$v.file.$touch();
- },
+ this.$store
+ .dispatch('firmwareSingleImage/getFirmwareInformation')
+ .finally(() => this.endLoader());
},
};
</script>