1966 lines
64 KiB
Diff
1966 lines
64 KiB
Diff
|
|
From 64626ebac7529a4cc471781ed45f0782d1b0c79f Mon Sep 17 00:00:00 2001
|
||
|
|
From: roly <Rolyli.Li@luxshare-ict.com>
|
||
|
|
Date: Thu, 9 Jan 2025 19:49:05 +0800
|
||
|
|
Subject: [PATCH] Support luxshare oem firmware update
|
||
|
|
|
||
|
|
---
|
||
|
|
src/components/Global/LinkButton.vue | 57 ++
|
||
|
|
src/components/Global/UploadFile.vue | 146 ++++
|
||
|
|
src/locales/en-US.json | 84 +-
|
||
|
|
src/store/modules/Operations/FirmwareStore.js | 220 ++++-
|
||
|
|
src/utilities/bus.js | 2 +
|
||
|
|
src/views/Operations/Firmware/Firmware.vue | 104 ++-
|
||
|
|
.../Operations/Firmware/FirmwareCardsBmc.vue | 27 +
|
||
|
|
.../Operations/Firmware/FirmwareCardsFPGA.vue | 40 +
|
||
|
|
.../Firmware/FirmwareCardsFcbCPLD.vue | 40 +
|
||
|
|
.../Operations/Firmware/FirmwareCardsMe.vue | 40 +
|
||
|
|
.../Firmware/FirmwareModalUpdateFirmware.vue | 29 +
|
||
|
|
.../Firmware/FirmwareUpdateStatus.vue | 822 ++++++++++++++++++
|
||
|
|
12 files changed, 1590 insertions(+), 21 deletions(-)
|
||
|
|
create mode 100755 src/components/Global/LinkButton.vue
|
||
|
|
create mode 100755 src/components/Global/UploadFile.vue
|
||
|
|
create mode 100755 src/utilities/bus.js
|
||
|
|
create mode 100755 src/views/Operations/Firmware/FirmwareCardsFPGA.vue
|
||
|
|
create mode 100755 src/views/Operations/Firmware/FirmwareCardsFcbCPLD.vue
|
||
|
|
create mode 100755 src/views/Operations/Firmware/FirmwareCardsMe.vue
|
||
|
|
create mode 100755 src/views/Operations/Firmware/FirmwareUpdateStatus.vue
|
||
|
|
|
||
|
|
diff --git a/src/components/Global/LinkButton.vue b/src/components/Global/LinkButton.vue
|
||
|
|
new file mode 100755
|
||
|
|
index 0000000..2a2022b
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/components/Global/LinkButton.vue
|
||
|
|
@@ -0,0 +1,57 @@
|
||
|
|
+<template>
|
||
|
|
+ <span
|
||
|
|
+ :class="{
|
||
|
|
+ 'action-btn': true,
|
||
|
|
+ 'action-btn-primary': !danger,
|
||
|
|
+ 'action-disabled': disabled,
|
||
|
|
+ 'action-btn-danger': danger,
|
||
|
|
+ }"
|
||
|
|
+ @click="handleClick()"
|
||
|
|
+ >
|
||
|
|
+ <slot></slot>
|
||
|
|
+ </span>
|
||
|
|
+</template>
|
||
|
|
+
|
||
|
|
+<script>
|
||
|
|
+export default {
|
||
|
|
+ props: {
|
||
|
|
+ disabled: {
|
||
|
|
+ type: Boolean,
|
||
|
|
+ default: false,
|
||
|
|
+ },
|
||
|
|
+ danger: {
|
||
|
|
+ type: Boolean,
|
||
|
|
+ default: false,
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ methods: {
|
||
|
|
+ handleClick() {
|
||
|
|
+ if (this.disabled) return;
|
||
|
|
+ else this.$emit('click');
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+};
|
||
|
|
+</script>
|
||
|
|
+
|
||
|
|
+<style lang="css" scoped>
|
||
|
|
+.action-btn {
|
||
|
|
+ white-space: nowrap;
|
||
|
|
+}
|
||
|
|
+.action-disabled {
|
||
|
|
+ cursor: not-allowed !important;
|
||
|
|
+ color: #ccc !important;
|
||
|
|
+}
|
||
|
|
+.action-btn {
|
||
|
|
+ cursor: pointer;
|
||
|
|
+}
|
||
|
|
+.action-btn:hover {
|
||
|
|
+ opacity: 0.7;
|
||
|
|
+}
|
||
|
|
+.action-btn-primary {
|
||
|
|
+ color: var(--primary);
|
||
|
|
+}
|
||
|
|
+.action-btn-danger {
|
||
|
|
+ margin: 0 5px;
|
||
|
|
+ color: var(--danger);
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
diff --git a/src/components/Global/UploadFile.vue b/src/components/Global/UploadFile.vue
|
||
|
|
new file mode 100755
|
||
|
|
index 0000000..3e492bd
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/components/Global/UploadFile.vue
|
||
|
|
@@ -0,0 +1,146 @@
|
||
|
|
+<template>
|
||
|
|
+ <b-form
|
||
|
|
+ class="d-flex align-items-center oem-upload-file"
|
||
|
|
+ style="max-width: 700px"
|
||
|
|
+ @submit.prevent="onSubmitUpload"
|
||
|
|
+ >
|
||
|
|
+ <b-form-file
|
||
|
|
+ v-model="file"
|
||
|
|
+ :class="disabled ? 'upload-file-disabled' : undefined"
|
||
|
|
+ :disabled="disabled"
|
||
|
|
+ :placeholder="$t('global.fileUpload.browseText')"
|
||
|
|
+ ></b-form-file>
|
||
|
|
+ <div class="d-flex align-items-center ml-2">
|
||
|
|
+ <b-button
|
||
|
|
+ :disabled="disabled"
|
||
|
|
+ class="btn-file"
|
||
|
|
+ variant="primary"
|
||
|
|
+ size="sm"
|
||
|
|
+ type="submit"
|
||
|
|
+ >{{ $t('pageFirmware.form.updateFirmware.startUpload') }}</b-button
|
||
|
|
+ >
|
||
|
|
+ <b-button
|
||
|
|
+ v-show="!!file"
|
||
|
|
+ :disabled="disabled"
|
||
|
|
+ class="btn-file"
|
||
|
|
+ variant="danger"
|
||
|
|
+ size="sm"
|
||
|
|
+ @click="file = null"
|
||
|
|
+ ><icon-trashcan class="delete-icon"
|
||
|
|
+ /></b-button>
|
||
|
|
+ </div>
|
||
|
|
+ <div class="file-error-tips">
|
||
|
|
+ {{ fileErrorTips }}
|
||
|
|
+ </div>
|
||
|
|
+ </b-form>
|
||
|
|
+</template>
|
||
|
|
+
|
||
|
|
+<script>
|
||
|
|
+import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
|
||
|
|
+export default {
|
||
|
|
+ components: {
|
||
|
|
+ IconTrashcan,
|
||
|
|
+ },
|
||
|
|
+ props: {
|
||
|
|
+ value: {
|
||
|
|
+ type: File,
|
||
|
|
+ default: () => {},
|
||
|
|
+ },
|
||
|
|
+ disabled: {
|
||
|
|
+ type: Boolean,
|
||
|
|
+ default: false,
|
||
|
|
+ },
|
||
|
|
+ required: {
|
||
|
|
+ type: Boolean,
|
||
|
|
+ default: false,
|
||
|
|
+ },
|
||
|
|
+ validtedFile: {
|
||
|
|
+ type: Function,
|
||
|
|
+ default: () => {},
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ data() {
|
||
|
|
+ return {
|
||
|
|
+ file: null,
|
||
|
|
+ fileErrorTips: '',
|
||
|
|
+ };
|
||
|
|
+ },
|
||
|
|
+ watch: {
|
||
|
|
+ value(newVal) {
|
||
|
|
+ this.file = newVal;
|
||
|
|
+ },
|
||
|
|
+ file: {
|
||
|
|
+ handler(newVal) {
|
||
|
|
+ this.$emit('input', newVal);
|
||
|
|
+ if (!newVal) {
|
||
|
|
+ this.fileErrorTips = '';
|
||
|
|
+ } else {
|
||
|
|
+ this.validtedFile(newVal)
|
||
|
|
+ .then(() => {
|
||
|
|
+ this.fileErrorTips = '';
|
||
|
|
+ })
|
||
|
|
+ .catch((e) => {
|
||
|
|
+ this.fileErrorTips = e;
|
||
|
|
+ });
|
||
|
|
+ }
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ methods: {
|
||
|
|
+ onSubmitUpload() {
|
||
|
|
+ if (!this.file && this.required) {
|
||
|
|
+ this.fileErrorTips = this.$t('global.form.required');
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+ this.validtedFile(this.file)
|
||
|
|
+ .then(() => {
|
||
|
|
+ this.$emit('submit', this.file);
|
||
|
|
+ })
|
||
|
|
+ .catch((e) => {
|
||
|
|
+ this.fileErrorTips = e;
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+};
|
||
|
|
+</script>
|
||
|
|
+
|
||
|
|
+<style lang="scss" scoped>
|
||
|
|
+$btn-height: 33px;
|
||
|
|
+.btn-file {
|
||
|
|
+ height: $btn-height;
|
||
|
|
+ white-space: nowrap;
|
||
|
|
+}
|
||
|
|
+.file-error-tips {
|
||
|
|
+ position: absolute;
|
||
|
|
+ top: 40px;
|
||
|
|
+ font-size: 0.875rem;
|
||
|
|
+ line-height: 1.25rem;
|
||
|
|
+ color: #da1416;
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
+<style lang="css" scoped>
|
||
|
|
+.oem-upload-file /deep/ .custom-file-label::after {
|
||
|
|
+ content: '. . .';
|
||
|
|
+ cursor: pointer;
|
||
|
|
+ color: #fff;
|
||
|
|
+ background: var(--primary);
|
||
|
|
+}
|
||
|
|
+.oem-upload-file /deep/ .custom-file-label {
|
||
|
|
+ margin-bottom: 0;
|
||
|
|
+}
|
||
|
|
+.oem-upload-file /deep/ .custom-file {
|
||
|
|
+ height: 35px !important;
|
||
|
|
+}
|
||
|
|
+.oem-upload-file /deep/ .custom-file-input {
|
||
|
|
+ height: 35px !important;
|
||
|
|
+ width: 400px;
|
||
|
|
+}
|
||
|
|
+.oem-upload-file /deep/ .custom-file-label {
|
||
|
|
+ height: 35px !important;
|
||
|
|
+}
|
||
|
|
+.upload-file-disabled /deep/ .custom-file-label::after {
|
||
|
|
+ cursor: not-allowed;
|
||
|
|
+ color: #999;
|
||
|
|
+ background: #ccc;
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
|
||
|
|
index 93ad806..0a67945 100644
|
||
|
|
--- a/src/locales/en-US.json
|
||
|
|
+++ b/src/locales/en-US.json
|
||
|
|
@@ -331,6 +331,12 @@
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"pageFirmware": {
|
||
|
|
+ "primaryImage": "Primary",
|
||
|
|
+ "secondaryImage": "Secondary",
|
||
|
|
+ "both": "Both (Not recommended)",
|
||
|
|
+ "sectionTitleMeCards": "ME Firmware",
|
||
|
|
+ "sectionTitleFcbCPLDCards": "Fan Board CPLD",
|
||
|
|
+ "sectionTitleFPGACards": "FPGA",
|
||
|
|
"cardActionSwitchToRunning": "Switch to running",
|
||
|
|
"cardBodyVersion": "Version",
|
||
|
|
"cardBodyReleaseDate": "Release Date",
|
||
|
|
@@ -340,19 +346,41 @@
|
||
|
|
"cardTitleFBCpld": "Fan Board CPLD",
|
||
|
|
"sectionTitleBmcCards": "BMC",
|
||
|
|
"sectionTitleBmcCardsCombined": "BMC and server",
|
||
|
|
- "sectionTitleHostCards": "Host",
|
||
|
|
+ "sectionTitleHostCards": "BIOS",
|
||
|
|
"sectionTitleUpdateFirmware": "Update firmware",
|
||
|
|
"sectionTitleCPLDCards": "CPLD",
|
||
|
|
+ "sectionTitleUpdateFirmwareStatus": "Update firmware status",
|
||
|
|
"alert": {
|
||
|
|
"operationInProgress": "Server power operation in progress.",
|
||
|
|
"serverMustBePoweredOffTo": "Server must be powered off to:",
|
||
|
|
"serverMustBePoweredOffToUpdateFirmware": "Server must be powered off to update firmware",
|
||
|
|
"switchRunningAndBackupImages": "Switch running and backup images",
|
||
|
|
"updateFirmware": "Update firmware",
|
||
|
|
- "viewServerPowerOperations": "View server power operations"
|
||
|
|
+ "viewServerPowerOperations": "View server power operations",
|
||
|
|
+ "boxupdateFirmware": "Box Update firmware",
|
||
|
|
+ "updateTask": "Background Update Task"
|
||
|
|
},
|
||
|
|
"form": {
|
||
|
|
+ "invalidFiletype": "Invalid file type",
|
||
|
|
+ "updateOptions": {
|
||
|
|
+ "keep": "Keep all configurations update",
|
||
|
|
+ "clear": "Non keep configuration update",
|
||
|
|
+ "partialKeep": "Keep partial configuration update",
|
||
|
|
+ "factoryReset": "Factory reset"
|
||
|
|
+ },
|
||
|
|
"updateFirmware": {
|
||
|
|
+ "updateTimeout": "Update timeout",
|
||
|
|
+ "UploadedFirmware": "Uploaded %{type}",
|
||
|
|
+ "updateBmcRestFail": "BMC reset failed",
|
||
|
|
+ "updateSecondaryInfo": "Secondary BMC is now updating, please wait",
|
||
|
|
+ "updateFinished": "%{type} %{version} Updated",
|
||
|
|
+ "ok": "Ok",
|
||
|
|
+ "version": "Version",
|
||
|
|
+ "biosKeepConfig": "Keep Configuration",
|
||
|
|
+ "biosNonKeepConfig": "Non Keep Configuration",
|
||
|
|
+ "options": "Options",
|
||
|
|
+ "startUpload": "Upload image",
|
||
|
|
+ "updateAll": "Update all",
|
||
|
|
"fileAddress": "File address",
|
||
|
|
"fileSource": "File source",
|
||
|
|
"imageFile": "Image file",
|
||
|
|
@@ -362,6 +390,11 @@
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"modal": {
|
||
|
|
+ "updateAllConfirm": "Are you sure you want to update all?",
|
||
|
|
+ "deleteConfirm": "Are you sure you want to delete the %{firmware} firmware?",
|
||
|
|
+ "updateFirmwareInfoOemBmc": "The primary(secondary) BMC firmware will be updated as you choose. In some scenarios, the BMC will reboot. Please confirm whether to update BMC firmware immediately?",
|
||
|
|
+ "updateSuccessOem": "update task is queued and will be activated when host DC power cycle by BMC (IPMI command or Redfish I/F)",
|
||
|
|
+ "updateFirmwareInfoOem": "The new image will be async activated. After that, the host will reboot automatically to run from the new image.",
|
||
|
|
"switchImages": "Switch images",
|
||
|
|
"switchRunningImage": "Switch running image",
|
||
|
|
"switchRunningImageInfo": "A BMC reboot is required to run the backup image. The application might be unresponsive during this time.",
|
||
|
|
@@ -372,16 +405,61 @@
|
||
|
|
"updateFirmwareInfoDefault": "The new image will be uploaded and activated. After that, the BMC or host will reboot automatically to run from the new image."
|
||
|
|
},
|
||
|
|
"toast": {
|
||
|
|
+ "errorUpdateAsyncAndSync": "BMC and other firmware cannot be updated simultaneously.",
|
||
|
|
+ "errorUpdateInPost": "The unit is in POST stage, can not flash BMC. Please wait a moment and try again.",
|
||
|
|
+ "errorUpdateInPeerNodeUpdating": "The peer node is upgrading components. Shared components do not allow dual nodes to be upgraded at the same time. Please try again later.",
|
||
|
|
+ "bmcUpdateTips": "BMC updates can cause other firmware to be lost.",
|
||
|
|
+ "errorUpdateFirmwareSign": "The firmware update failed or the signature was invalid.",
|
||
|
|
+ "errorInPostStatus": "BMC firmware can not update in BIOS POST status",
|
||
|
|
+ "uploadStarted": "Upload started",
|
||
|
|
+ "uploadStartedMessage": "Wait for the firmware upload notification before making any changes.",
|
||
|
|
+ "timeoutUpload": "Update timeout",
|
||
|
|
+ "timeoutUploadMessage": "Upload firmware image timeout",
|
||
|
|
+ "uploadSuccess": "Upload success",
|
||
|
|
+ "uploadSuccessMessage": "The firmware upload successfully",
|
||
|
|
+ "uploadFailed": "Upload failed",
|
||
|
|
+ "uploadFailedMessage": "The firmware upload failed",
|
||
|
|
+ "errorVerifyFirmware": "Failed to verify the signature image",
|
||
|
|
+ "errorUploadFirmware": "Failed to extract or verify the image",
|
||
|
|
"errorSwitchImages": "Error switching running and backup images.",
|
||
|
|
"errorUpdateFirmware": "Error starting firmware update.",
|
||
|
|
"rebootStarted": "Reboot started",
|
||
|
|
"rebootStartedMessage": "Successfully started reboot from backup image.",
|
||
|
|
"updateStarted": "Update started",
|
||
|
|
"updateStartedMessage": "Wait for the firmware update notification before making any changes.",
|
||
|
|
+ "updateSuccess": "Update success",
|
||
|
|
+ "updateSuccessMessage": "Successfully update the firmware, Please wait for the image refresh",
|
||
|
|
+ "updateFailed": "Update failed",
|
||
|
|
+ "updateFailedMessage": "Failed in update the firmware.",
|
||
|
|
"verifySwitch": "Verify switch",
|
||
|
|
"verifySwitchMessage": "Refresh the application to verify the running and backup images switched.",
|
||
|
|
"verifyUpdate": "Verify update",
|
||
|
|
- "verifyUpdateMessage": "Refresh the application to verify firmware updated successfully"
|
||
|
|
+ "verifyUpdateMessage": "Refresh the application to verify firmware updated successfully",
|
||
|
|
+ "errorGetUpdateStatus": "Failed to retrieve firmware update status.",
|
||
|
|
+ "deleteSuccess": "Deletion successful.",
|
||
|
|
+ "firmwareDeleted": "Firmware %{firmware} has been deleted.",
|
||
|
|
+ "deleteFailed": "Failed to delete firmware %{firmware}.",
|
||
|
|
+ "bmcUpdatingTips": "The page functionality is temporarily unavailable during the BMC firmware update.",
|
||
|
|
+ "bmcUpdateCompleteTips": "BMC upgrade completed. Please refresh the page after a moment. Note that the IP address may change in some cases.",
|
||
|
|
+ "validateFirmwareFailed": "Failed to validate the %{firmware} firmware image.",
|
||
|
|
+ "firmwareIdMismatch": "The %{firmware} firmware does not match"
|
||
|
|
+ },
|
||
|
|
+ "table": {
|
||
|
|
+ "updateComplete": "Update completed",
|
||
|
|
+ "updateFailed": "Update failed",
|
||
|
|
+ "updating": "Updating",
|
||
|
|
+ "waitUpdate": "Wait for update",
|
||
|
|
+ "emptyMessage": "No firmware available",
|
||
|
|
+ "update": "update",
|
||
|
|
+ "delete": "delete",
|
||
|
|
+ "noupdate": "No update",
|
||
|
|
+ "name": "Unit name",
|
||
|
|
+ "status": "Update Status",
|
||
|
|
+ "time": "Estimated time",
|
||
|
|
+ "progress": "Progress",
|
||
|
|
+ "firmwareName": "Name",
|
||
|
|
+ "firmwareStatus": "Status",
|
||
|
|
+ "firmwareVersion": "Version"
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"pageInventory": {
|
||
|
|
diff --git a/src/store/modules/Operations/FirmwareStore.js b/src/store/modules/Operations/FirmwareStore.js
|
||
|
|
index 001eaf6..39b71e8 100644
|
||
|
|
--- a/src/store/modules/Operations/FirmwareStore.js
|
||
|
|
+++ b/src/store/modules/Operations/FirmwareStore.js
|
||
|
|
@@ -1,20 +1,57 @@
|
||
|
|
import api from '@/store/api';
|
||
|
|
import i18n from '@/i18n';
|
||
|
|
+import { bus } from '@/utilities/bus';
|
||
|
|
|
||
|
|
+const FIRMWARE_PURPOSE = {
|
||
|
|
+ BMC: 'xyz.openbmc_project.Software.Version.VersionPurpose.BMC',
|
||
|
|
+ CPLD: 'xyz.openbmc_project.Software.Version.VersionPurpose.CPLD',
|
||
|
|
+ FPGA: 'xyz.openbmc_project.Software.Version.VersionPurpose.FPGA',
|
||
|
|
+ BIOS: 'xyz.openbmc_project.Software.Version.VersionPurpose.Host',
|
||
|
|
+ PSU: 'xyz.openbmc_project.Software.Version.VersionPurpose.PSU',
|
||
|
|
+ HSBP: 'xyz.openbmc_project.Software.Version.VersionPurpose.HSBP',
|
||
|
|
+ FCB: 'xyz.openbmc_project.Software.Version.VersionPurpose.FCB',
|
||
|
|
+};
|
||
|
|
const FirmwareStore = {
|
||
|
|
namespaced: true,
|
||
|
|
state: {
|
||
|
|
bmcFirmware: [],
|
||
|
|
hostFirmware: [],
|
||
|
|
+ uploadFirmwareType: null,
|
||
|
|
+ uploadFirmwareState: null,
|
||
|
|
+ uploadFirmwareId: null,
|
||
|
|
+ firmwareFunctionData: [],
|
||
|
|
+ meFirmware: [],
|
||
|
|
cpldFirmware: [],
|
||
|
|
- fbcpldFirmware: [],
|
||
|
|
+ fcbCpldFirmware: [],
|
||
|
|
+ fpgaFirmware: [],
|
||
|
|
bmcActiveFirmwareId: null,
|
||
|
|
hostActiveFirmwareId: null,
|
||
|
|
applyTime: null,
|
||
|
|
httpPushUri: null,
|
||
|
|
tftpAvailable: false,
|
||
|
|
+ firmwareStatus: null,
|
||
|
|
+ isFirmwareProgress: false,
|
||
|
|
+ isNeedCycle: false,
|
||
|
|
+ bmcIsUpdating: false,
|
||
|
|
+ bmcIsUpdatingfCurrentPartition: false,
|
||
|
|
},
|
||
|
|
getters: {
|
||
|
|
+ uploadFirmwareId: (state) => state.uploadFirmwareId,
|
||
|
|
+ uploadFirmwareState: (state) => state.uploadFirmwareState,
|
||
|
|
+ uploadFirmwareType: (state) => state.uploadFirmwareType,
|
||
|
|
+ priorityFirmware: (state) => {
|
||
|
|
+ return state.firmwareFunctionData.find(
|
||
|
|
+ (firmware) => firmware.Purpose === FIRMWARE_PURPOSE.BMC
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
+ meFirmware: (state) => {
|
||
|
|
+ return state.meFirmware.find((firmware) => firmware.id === 'me');
|
||
|
|
+ },
|
||
|
|
+ fpgaFirmware: (state) => {
|
||
|
|
+ return state.fpgaFirmware.find(
|
||
|
|
+ (firmware) => firmware.id === 'fpga_active'
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
isTftpUploadAvailable: (state) => state.tftpAvailable,
|
||
|
|
isSingleFileUploadEnabled: (state) => state.hostFirmware.length === 0,
|
||
|
|
activeBmcFirmware: (state) => {
|
||
|
|
@@ -29,7 +66,9 @@ const FirmwareStore = {
|
||
|
|
},
|
||
|
|
backupBmcFirmware: (state) => {
|
||
|
|
return state.bmcFirmware.find(
|
||
|
|
- (firmware) => firmware.id !== state.bmcActiveFirmwareId
|
||
|
|
+ (firmware) =>
|
||
|
|
+ firmware.id !== state.bmcActiveFirmwareId &&
|
||
|
|
+ firmware.state === 'Enabled'
|
||
|
|
);
|
||
|
|
},
|
||
|
|
backupHostFirmware: (state) => {
|
||
|
|
@@ -42,28 +81,53 @@ const FirmwareStore = {
|
||
|
|
(firmware) => firmware.id === 'cpld_active'
|
||
|
|
);
|
||
|
|
},
|
||
|
|
- fbcpldFirmware: (state) => {
|
||
|
|
- return state.fbcpldFirmware.find(
|
||
|
|
- (firmware) => firmware.id === 'fb_cpld_active'
|
||
|
|
+ fcbCpldFirmware: (state) => {
|
||
|
|
+ return state.fcbCpldFirmware.find(
|
||
|
|
+ (firmware) => firmware.id === 'fcb_cpld_active'
|
||
|
|
);
|
||
|
|
},
|
||
|
|
+ allFirmwareStatus: (state) => state.firmwareStatus,
|
||
|
|
+ isFirmwareProgress: (state) => state.isFirmwareProgress,
|
||
|
|
+ isNeedCycle: (state) => state.isNeedCycle,
|
||
|
|
+ bmcIsUpdating: (state) => state.bmcIsUpdating,
|
||
|
|
+ bmcIsUpdatingfCurrentPartition: (state) =>
|
||
|
|
+ state.bmcIsUpdatingfCurrentPartition,
|
||
|
|
},
|
||
|
|
mutations: {
|
||
|
|
+ setFirmwareFunctionData: (state, firmware) =>
|
||
|
|
+ (state.firmwareFunctionData = firmware),
|
||
|
|
+ setMeFirmware: (state, firmware) => (state.meFirmware = firmware),
|
||
|
|
+ setFPGAFirmware: (state, firmware) => (state.fpgaFirmware = firmware),
|
||
|
|
setActiveBmcFirmwareId: (state, id) => (state.bmcActiveFirmwareId = id),
|
||
|
|
setActiveHostFirmwareId: (state, id) => (state.hostActiveFirmwareId = id),
|
||
|
|
setBmcFirmware: (state, firmware) => (state.bmcFirmware = firmware),
|
||
|
|
setHostFirmware: (state, firmware) => (state.hostFirmware = firmware),
|
||
|
|
setCPLDFirmware: (state, firmware) => (state.cpldFirmware = firmware),
|
||
|
|
- setFBCPLDFirmware: (state, firmware) => (state.fbcpldFirmware = firmware),
|
||
|
|
+ setFcbCpldFirmware: (state, firmware) => (state.fcbCpldFirmware = firmware),
|
||
|
|
setApplyTime: (state, applyTime) => (state.applyTime = applyTime),
|
||
|
|
setHttpPushUri: (state, httpPushUri) => (state.httpPushUri = httpPushUri),
|
||
|
|
setTftpUploadAvailable: (state, tftpAvailable) =>
|
||
|
|
(state.tftpAvailable = tftpAvailable),
|
||
|
|
+ setFirmwareUpdateStatus: (state, status) => (state.firmwareStatus = status),
|
||
|
|
+ setIsFirmwareProgress: (state, isProgress) =>
|
||
|
|
+ (state.isFirmwareProgress = isProgress),
|
||
|
|
+ setIsNeedCycle: (state, isNeedCycle) => (state.isNeedCycle = isNeedCycle),
|
||
|
|
+ setBmcIsUpdating: (state, bmcIsUpdating) =>
|
||
|
|
+ (state.bmcIsUpdating = bmcIsUpdating),
|
||
|
|
+ setBmcIsUpdatingfCurrentPartition: (state, bool) => {
|
||
|
|
+ state.bmcIsUpdatingfCurrentPartition = bool;
|
||
|
|
+ },
|
||
|
|
+ setBmcUpdateProgress: (state, progress) => {
|
||
|
|
+ const bmcFirmware = state.firmwareStatus.find((it) => it.BMC);
|
||
|
|
+ bmcFirmware.BMC.UpdateProgress = progress;
|
||
|
|
+ bmcFirmware.BMC.UpdateStatus = progress === 100 ? 'Updated' : 'Updating';
|
||
|
|
+ },
|
||
|
|
},
|
||
|
|
actions: {
|
||
|
|
async getFirmwareInformation({ dispatch }) {
|
||
|
|
dispatch('getActiveHostFirmware');
|
||
|
|
dispatch('getActiveBmcFirmware');
|
||
|
|
+ dispatch('getFirmwareFunctionData');
|
||
|
|
return await dispatch('getFirmwareInventory');
|
||
|
|
},
|
||
|
|
getActiveBmcFirmware({ commit }) {
|
||
|
|
@@ -94,10 +158,12 @@ const FirmwareStore = {
|
||
|
|
await api
|
||
|
|
.all(inventoryList)
|
||
|
|
.then((response) => {
|
||
|
|
+ const meFirmware = [];
|
||
|
|
+ const fpgaFirmware = [];
|
||
|
|
const bmcFirmware = [];
|
||
|
|
const hostFirmware = [];
|
||
|
|
const cpldFirmware = [];
|
||
|
|
- const fbcpldFirmware = [];
|
||
|
|
+ const fcbCpldFirmware = [];
|
||
|
|
response.forEach(({ data }) => {
|
||
|
|
const firmwareType = data?.RelatedItem?.[0]?.['@odata.id']
|
||
|
|
.split('/')
|
||
|
|
@@ -108,24 +174,29 @@ const FirmwareStore = {
|
||
|
|
location: data?.['@odata.id'],
|
||
|
|
status: data?.Status?.Health,
|
||
|
|
reldate: data?.ReleaseDate,
|
||
|
|
+ state: data?.Status?.State,
|
||
|
|
};
|
||
|
|
if (firmwareType === 'bmc') {
|
||
|
|
bmcFirmware.push(item);
|
||
|
|
} else if (firmwareType === 'Bios') {
|
||
|
|
hostFirmware.push(item);
|
||
|
|
}
|
||
|
|
-
|
||
|
|
if (item.id === 'cpld_active') {
|
||
|
|
cpldFirmware.push(item);
|
||
|
|
- }
|
||
|
|
- if (item.id === 'fb_cpld_active') {
|
||
|
|
- fbcpldFirmware.push(item);
|
||
|
|
+ } else if (item.id === 'fpga_active') {
|
||
|
|
+ fpgaFirmware.push(item);
|
||
|
|
+ } else if (item.id === 'me') {
|
||
|
|
+ meFirmware.push(item);
|
||
|
|
+ } else if (item.id === 'fcb_cpld_active') {
|
||
|
|
+ fcbCpldFirmware.push(item);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
commit('setBmcFirmware', bmcFirmware);
|
||
|
|
commit('setHostFirmware', hostFirmware);
|
||
|
|
commit('setCPLDFirmware', cpldFirmware);
|
||
|
|
- commit('setFBCPLDFirmware', fbcpldFirmware);
|
||
|
|
+ commit('setFcbCpldFirmware', fcbCpldFirmware);
|
||
|
|
+ commit('setFPGAFirmware', fpgaFirmware);
|
||
|
|
+ commit('setMeFirmware', meFirmware);
|
||
|
|
})
|
||
|
|
.catch((error) => {
|
||
|
|
console.log(error);
|
||
|
|
@@ -214,6 +285,131 @@ const FirmwareStore = {
|
||
|
|
throw new Error(i18n.t('pageFirmware.toast.errorSwitchImages'));
|
||
|
|
});
|
||
|
|
},
|
||
|
|
+ // ======================== firmware OEM ========================
|
||
|
|
+ getFirmwareFunctionData({ commit }) {
|
||
|
|
+ return api
|
||
|
|
+ .get('/xyz/openbmc_project/software/functional')
|
||
|
|
+ .then((response) =>
|
||
|
|
+ api.all(response.data.data.endpoints.map((bmcurl) => api.get(bmcurl)))
|
||
|
|
+ )
|
||
|
|
+ .then((bmcResult) => {
|
||
|
|
+ const bmcStateData = bmcResult.map((datas) => datas.data.data);
|
||
|
|
+ commit('setFirmwareFunctionData', bmcStateData);
|
||
|
|
+ })
|
||
|
|
+ .catch((error) => {
|
||
|
|
+ console.log(error);
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ // ----------------- firmware update ----------
|
||
|
|
+ async uploadFirmwareOEM({ commit }, image) {
|
||
|
|
+ console.log('image', image);
|
||
|
|
+ const data = new FormData();
|
||
|
|
+ data.append('fwimage', image);
|
||
|
|
+ commit('setIsFirmwareProgress', true);
|
||
|
|
+ return await api
|
||
|
|
+ .post(
|
||
|
|
+ '/redfish/v1/UpdateService/Actions/Oem/Luxshare/FirmwareFile',
|
||
|
|
+ data
|
||
|
|
+ )
|
||
|
|
+ .then((response) => {
|
||
|
|
+ console.log('upload success', response);
|
||
|
|
+ return response;
|
||
|
|
+ })
|
||
|
|
+ .catch((error) => {
|
||
|
|
+ console.log('upload error', error);
|
||
|
|
+ throw new Error(i18n.t('pageFirmware.toast.errorUploadFirmware'));
|
||
|
|
+ })
|
||
|
|
+ .finally(() => commit('setIsFirmwareProgress', false));
|
||
|
|
+ },
|
||
|
|
+ async getAllUpdateStatus({ commit }) {
|
||
|
|
+ return await api
|
||
|
|
+ .get('/redfish/v1/UpdateService/Actions/Oem/Luxshare/FirmwareStatus')
|
||
|
|
+ .then((response) => {
|
||
|
|
+ // if (state.bmcIsUpdating) return;
|
||
|
|
+ commit('setFirmwareUpdateStatus', response.data.Oem.Luxshare);
|
||
|
|
+ const isNeedCycle = response.data.Oem.Luxshare.find((firmware) => {
|
||
|
|
+ const entries = Object.entries(firmware);
|
||
|
|
+ return (
|
||
|
|
+ entries[0][1].UpdateStatus === 'Queued' ||
|
||
|
|
+ (entries[0][0] === 'Retimer' &&
|
||
|
|
+ entries[0][1].UpdateStatus === 'Updated')
|
||
|
|
+ );
|
||
|
|
+ });
|
||
|
|
+ commit('setIsNeedCycle', !!isNeedCycle);
|
||
|
|
+ })
|
||
|
|
+ .catch((error) => {
|
||
|
|
+ console.log(error);
|
||
|
|
+ throw new Error(i18n.t('pageFirmware.toast.errorGetUpdateStatus'));
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ async startUpdate({ commit }, updateConfigs) {
|
||
|
|
+ commit('setIsFirmwareProgress', true);
|
||
|
|
+ return await api
|
||
|
|
+ .post(
|
||
|
|
+ '/redfish/v1/UpdateService/Actions/Oem/Luxshare/FirmwareUpdate',
|
||
|
|
+ updateConfigs
|
||
|
|
+ )
|
||
|
|
+ .finally(() => commit('setIsFirmwareProgress', false));
|
||
|
|
+ },
|
||
|
|
+ async deleteFirmware(_, target) {
|
||
|
|
+ console.log('target', target);
|
||
|
|
+ return await api.delete(
|
||
|
|
+ '/redfish/v1/UpdateService/Actions/Oem/Luxshare/FirmwareUpdate',
|
||
|
|
+ {
|
||
|
|
+ data: {
|
||
|
|
+ Target: target,
|
||
|
|
+ },
|
||
|
|
+ }
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
+ async pollingBmcUpdateStatus() {
|
||
|
|
+ const timeout = 3000;
|
||
|
|
+ return new Promise((resolve, reject) => {
|
||
|
|
+ setTimeout(() => {
|
||
|
|
+ reject();
|
||
|
|
+ }, timeout);
|
||
|
|
+ api
|
||
|
|
+ .get('/redfish/v1/UpdateService/Actions/Oem/Luxshare/FirmwareStatus')
|
||
|
|
+ .then((res) => {
|
||
|
|
+ const progress = res.data.Oem.Luxshare?.[0]?.BMC?.UpdateProgress;
|
||
|
|
+ resolve(progress);
|
||
|
|
+ })
|
||
|
|
+ .catch((error) => {
|
||
|
|
+ reject(error);
|
||
|
|
+ });
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ getBmcUpdateStatus({ state, commit, dispatch }) {
|
||
|
|
+ dispatch('pollingBmcUpdateStatus')
|
||
|
|
+ .then((progress) => {
|
||
|
|
+ const bmcFirmware = state.firmwareStatus.find((it) => it.BMC);
|
||
|
|
+ if (bmcFirmware.BMC.UpdateProgress === 100) {
|
||
|
|
+ return;
|
||
|
|
+ } else if (
|
||
|
|
+ progress !== undefined &&
|
||
|
|
+ progress > bmcFirmware.BMC.UpdateProgress
|
||
|
|
+ ) {
|
||
|
|
+ commit('setBmcUpdateProgress', progress);
|
||
|
|
+ }
|
||
|
|
+ if (progress === 100) {
|
||
|
|
+ bus.$emit('bmcUpdateComplete');
|
||
|
|
+ localStorage.setItem('loggingStatus', 'logout');
|
||
|
|
+ commit('authentication/logout', null, { root: true });
|
||
|
|
+ } else {
|
||
|
|
+ setTimeout(() => {
|
||
|
|
+ dispatch('getBmcUpdateStatus');
|
||
|
|
+ }, 3000);
|
||
|
|
+ }
|
||
|
|
+ })
|
||
|
|
+ .catch(() => {
|
||
|
|
+ const bmcFirmware = state.firmwareStatus.find((it) => it.BMC);
|
||
|
|
+ if (bmcFirmware.BMC.UpdateProgress === 100) return;
|
||
|
|
+ setTimeout(() => {
|
||
|
|
+ dispatch('getBmcUpdateStatus');
|
||
|
|
+ }, 3000);
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ // ======================== END ========================
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
diff --git a/src/utilities/bus.js b/src/utilities/bus.js
|
||
|
|
new file mode 100755
|
||
|
|
index 0000000..68259ae
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/utilities/bus.js
|
||
|
|
@@ -0,0 +1,2 @@
|
||
|
|
+import Vue from 'vue';
|
||
|
|
+export const bus = new Vue();
|
||
|
|
diff --git a/src/views/Operations/Firmware/Firmware.vue b/src/views/Operations/Firmware/Firmware.vue
|
||
|
|
index 25fe0bb..106da18 100644
|
||
|
|
--- a/src/views/Operations/Firmware/Firmware.vue
|
||
|
|
+++ b/src/views/Operations/Firmware/Firmware.vue
|
||
|
|
@@ -13,15 +13,37 @@
|
||
|
|
<bmc-cards :is-page-disabled="isPageDisabled" />
|
||
|
|
|
||
|
|
<!-- Host Firmware -->
|
||
|
|
- <host-cards v-if="!isSingleFileUploadEnabled" />
|
||
|
|
-
|
||
|
|
- <!-- CPLD Firmware -->
|
||
|
|
- <cpld-cards v-if="cpld" />
|
||
|
|
+ <b-row>
|
||
|
|
+ <b-col xl="6">
|
||
|
|
+ <!-- Host Firmware -->
|
||
|
|
+ <host-cards v-if="!isSingleFileUploadEnabled" />
|
||
|
|
+ </b-col>
|
||
|
|
+ <b-col xl="6">
|
||
|
|
+ <!-- Me Firmware -->
|
||
|
|
+ <me-cards v-if="me" />
|
||
|
|
+ </b-col>
|
||
|
|
+ </b-row>
|
||
|
|
+ <b-row>
|
||
|
|
+ <b-col xl="6">
|
||
|
|
+ <!-- CPLD Firmware -->
|
||
|
|
+ <cpld-cards v-if="cpld" />
|
||
|
|
+ </b-col>
|
||
|
|
+ <b-col xl="6">
|
||
|
|
+ <!--Fan CPLD Firmware -->
|
||
|
|
+ <fcb-cpld-cards v-if="fcbCpld" />
|
||
|
|
+ </b-col>
|
||
|
|
+ </b-row>
|
||
|
|
+ <b-row>
|
||
|
|
+ <b-col xl="6">
|
||
|
|
+ <fpga-cards v-if="fpga" />
|
||
|
|
+ </b-col>
|
||
|
|
+ </b-row>
|
||
|
|
</b-col>
|
||
|
|
</b-row>
|
||
|
|
|
||
|
|
<!-- Update firmware-->
|
||
|
|
<page-section
|
||
|
|
+ v-if="!isOEMUpdate"
|
||
|
|
:section-title="$t('pageFirmware.sectionTitleUpdateFirmware')"
|
||
|
|
>
|
||
|
|
<b-row>
|
||
|
|
@@ -34,17 +56,29 @@
|
||
|
|
</b-col>
|
||
|
|
</b-row>
|
||
|
|
</page-section>
|
||
|
|
+
|
||
|
|
+ <!-- Update firmware status-->
|
||
|
|
+ <page-section
|
||
|
|
+ v-if="isOEMUpdate"
|
||
|
|
+ :section-title="$t('pageFirmware.sectionTitleUpdateFirmwareStatus')"
|
||
|
|
+ >
|
||
|
|
+ <update-status :is-page-disabled="isPageDisabled"></update-status>
|
||
|
|
+ </page-section>
|
||
|
|
</b-container>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
import AlertsServerPower from './FirmwareAlertServerPower';
|
||
|
|
+import MeCards from './FirmwareCardsMe';
|
||
|
|
+import FcbCpldCards from './FirmwareCardsFcbCPLD';
|
||
|
|
+import FpgaCards from './FirmwareCardsFPGA';
|
||
|
|
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 CpldCards from './FirmwareCardsCPLD';
|
||
|
|
+import UpdateStatus from './FirmwareUpdateStatus';
|
||
|
|
|
||
|
|
import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin';
|
||
|
|
|
||
|
|
@@ -52,12 +86,16 @@ export default {
|
||
|
|
name: 'FirmwareSingleImage',
|
||
|
|
components: {
|
||
|
|
AlertsServerPower,
|
||
|
|
+ MeCards,
|
||
|
|
+ FcbCpldCards,
|
||
|
|
+ FpgaCards,
|
||
|
|
BmcCards,
|
||
|
|
FormUpdate,
|
||
|
|
HostCards,
|
||
|
|
PageSection,
|
||
|
|
PageTitle,
|
||
|
|
CpldCards,
|
||
|
|
+ UpdateStatus,
|
||
|
|
},
|
||
|
|
mixins: [LoadingBarMixin],
|
||
|
|
beforeRouteLeave(to, from, next) {
|
||
|
|
@@ -66,12 +104,36 @@ export default {
|
||
|
|
},
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
+ isOEMUpdate: true, //false: original openbmc update
|
||
|
|
+ isUploaded: false,
|
||
|
|
loading,
|
||
|
|
isServerPowerOffRequired:
|
||
|
|
process.env.VUE_APP_SERVER_OFF_REQUIRED === 'true',
|
||
|
|
};
|
||
|
|
},
|
||
|
|
computed: {
|
||
|
|
+ // is in upload or update, Used to gray out when switching back and forth with other pages.
|
||
|
|
+ isFirmwareProgress() {
|
||
|
|
+ return this.$store.getters['firmware/isFirmwareProgress'];
|
||
|
|
+ },
|
||
|
|
+ uploadFirmwareId() {
|
||
|
|
+ return this.$store.getters['firmware/uploadFirmwareId'];
|
||
|
|
+ },
|
||
|
|
+ uploadFirmwareType() {
|
||
|
|
+ return this.$store.getters['firmware/uploadFirmwareType'];
|
||
|
|
+ },
|
||
|
|
+ uploadFirmwareState() {
|
||
|
|
+ return this.$store.getters['firmware/uploadFirmwareState'];
|
||
|
|
+ },
|
||
|
|
+ me() {
|
||
|
|
+ return this.$store.getters['firmware/meFirmware'];
|
||
|
|
+ },
|
||
|
|
+ fcbCpld() {
|
||
|
|
+ return this.$store.getters['firmware/fcbCpldFirmware'];
|
||
|
|
+ },
|
||
|
|
+ fpga() {
|
||
|
|
+ return this.$store.getters['firmware/fpgaFirmware'];
|
||
|
|
+ },
|
||
|
|
serverStatus() {
|
||
|
|
return this.$store.getters['global/serverStatus'];
|
||
|
|
},
|
||
|
|
@@ -81,11 +143,28 @@ export default {
|
||
|
|
isSingleFileUploadEnabled() {
|
||
|
|
return this.$store.getters['firmware/isSingleFileUploadEnabled'];
|
||
|
|
},
|
||
|
|
+ isOperationInProgress() {
|
||
|
|
+ return this.$store.getters['controls/isOperationInProgress'];
|
||
|
|
+ },
|
||
|
|
+ isReadOnly() {
|
||
|
|
+ return this.$store.getters['global/userPrivilege'] === 'ReadOnly';
|
||
|
|
+ },
|
||
|
|
isPageDisabled() {
|
||
|
|
if (this.isServerPowerOffRequired) {
|
||
|
|
- return !this.isServerOff || this.loading || this.isOperationInProgress;
|
||
|
|
+ return (
|
||
|
|
+ !this.isServerOff ||
|
||
|
|
+ this.loading ||
|
||
|
|
+ this.isOperationInProgress ||
|
||
|
|
+ this.isFirmwareProgress ||
|
||
|
|
+ this.isReadOnly
|
||
|
|
+ );
|
||
|
|
}
|
||
|
|
- return this.loading || this.isOperationInProgress;
|
||
|
|
+ return (
|
||
|
|
+ this.loading ||
|
||
|
|
+ this.isOperationInProgress ||
|
||
|
|
+ this.isFirmwareProgress ||
|
||
|
|
+ this.isReadOnly
|
||
|
|
+ );
|
||
|
|
},
|
||
|
|
cpld() {
|
||
|
|
return this.$store.getters['firmware/cpldFirmware'];
|
||
|
|
@@ -93,9 +172,22 @@ export default {
|
||
|
|
},
|
||
|
|
created() {
|
||
|
|
this.startLoader();
|
||
|
|
+ this.$root.$on('set-upload-event', (evt, isUploaded) => {
|
||
|
|
+ this.isUploaded = isUploaded;
|
||
|
|
+ this.loading = evt;
|
||
|
|
+ });
|
||
|
|
+ this.$root.$on('set-update-event', (evt) => {
|
||
|
|
+ this.loading = evt;
|
||
|
|
+ });
|
||
|
|
this.$store
|
||
|
|
.dispatch('firmware/getFirmwareInformation')
|
||
|
|
.finally(() => this.endLoader());
|
||
|
|
},
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
+
|
||
|
|
+<style lang="scss" scoped>
|
||
|
|
+.upload-cell {
|
||
|
|
+ padding-bottom: $spacer * 1;
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
diff --git a/src/views/Operations/Firmware/FirmwareCardsBmc.vue b/src/views/Operations/Firmware/FirmwareCardsBmc.vue
|
||
|
|
index 8765f77..37c9cf8 100644
|
||
|
|
--- a/src/views/Operations/Firmware/FirmwareCardsBmc.vue
|
||
|
|
+++ b/src/views/Operations/Firmware/FirmwareCardsBmc.vue
|
||
|
|
@@ -10,6 +10,8 @@
|
||
|
|
</p>
|
||
|
|
</template>
|
||
|
|
<dl class="mb-0">
|
||
|
|
+ <dd>{{ priorityFirmware }}</dd>
|
||
|
|
+
|
||
|
|
<dt>{{ $t('pageFirmware.cardBodyVersion') }}</dt>
|
||
|
|
<dd class="mb-0">{{ runningVersion }}</dd>
|
||
|
|
</dl>
|
||
|
|
@@ -28,6 +30,8 @@
|
||
|
|
</p>
|
||
|
|
</template>
|
||
|
|
<dl>
|
||
|
|
+ <dd>{{ backupFirmware }}</dd>
|
||
|
|
+
|
||
|
|
<dt>{{ $t('pageFirmware.cardBodyVersion') }}</dt>
|
||
|
|
<dd>
|
||
|
|
<status-icon v-if="showBackupImageStatus" status="danger" />
|
||
|
|
@@ -82,6 +86,26 @@ export default {
|
||
|
|
};
|
||
|
|
},
|
||
|
|
computed: {
|
||
|
|
+ priorityFirmware() {
|
||
|
|
+ const pri = this.$store.getters['firmware/priorityFirmware'];
|
||
|
|
+ if (pri?.Priority === 0) {
|
||
|
|
+ return this.$t('pageFirmware.primaryImage');
|
||
|
|
+ }
|
||
|
|
+ if (pri?.Priority === 1) {
|
||
|
|
+ return this.$t('pageFirmware.secondaryImage');
|
||
|
|
+ }
|
||
|
|
+ return '';
|
||
|
|
+ },
|
||
|
|
+ backupFirmware() {
|
||
|
|
+ const pri = this.$store.getters['firmware/priorityFirmware'];
|
||
|
|
+ if (pri?.Priority === 0) {
|
||
|
|
+ return this.$t('pageFirmware.secondaryImage');
|
||
|
|
+ }
|
||
|
|
+ if (pri?.Priority === 1) {
|
||
|
|
+ return this.$t('pageFirmware.primaryImage');
|
||
|
|
+ }
|
||
|
|
+ return '';
|
||
|
|
+ },
|
||
|
|
isSingleFileUploadEnabled() {
|
||
|
|
return this.$store.getters['firmware/isSingleFileUploadEnabled'];
|
||
|
|
},
|
||
|
|
@@ -114,6 +138,9 @@ export default {
|
||
|
|
this.backupStatus === 'Critical' || this.backupStatus === 'Warning'
|
||
|
|
);
|
||
|
|
},
|
||
|
|
+ backupReleaseDate() {
|
||
|
|
+ return this.backup?.reldate || '--';
|
||
|
|
+ },
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
switchToRunning() {
|
||
|
|
diff --git a/src/views/Operations/Firmware/FirmwareCardsFPGA.vue b/src/views/Operations/Firmware/FirmwareCardsFPGA.vue
|
||
|
|
new file mode 100755
|
||
|
|
index 0000000..f1f5ddd
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/views/Operations/Firmware/FirmwareCardsFPGA.vue
|
||
|
|
@@ -0,0 +1,40 @@
|
||
|
|
+<template>
|
||
|
|
+ <page-section :section-title="$t('pageFirmware.sectionTitleFPGACards')">
|
||
|
|
+ <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>
|
||
|
|
+ </b-card-group>
|
||
|
|
+ </page-section>
|
||
|
|
+</template>
|
||
|
|
+
|
||
|
|
+<script>
|
||
|
|
+import PageSection from '@/components/Global/PageSection';
|
||
|
|
+
|
||
|
|
+export default {
|
||
|
|
+ components: { PageSection },
|
||
|
|
+ computed: {
|
||
|
|
+ running() {
|
||
|
|
+ return this.$store.getters['firmware/fpgaFirmware'];
|
||
|
|
+ },
|
||
|
|
+ runningVersion() {
|
||
|
|
+ return this.running?.version || '--';
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+};
|
||
|
|
+</script>
|
||
|
|
+
|
||
|
|
+<style lang="scss" scoped>
|
||
|
|
+.page-section {
|
||
|
|
+ margin-top: -$spacer * 1.5;
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
diff --git a/src/views/Operations/Firmware/FirmwareCardsFcbCPLD.vue b/src/views/Operations/Firmware/FirmwareCardsFcbCPLD.vue
|
||
|
|
new file mode 100755
|
||
|
|
index 0000000..79294d5
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/views/Operations/Firmware/FirmwareCardsFcbCPLD.vue
|
||
|
|
@@ -0,0 +1,40 @@
|
||
|
|
+<template>
|
||
|
|
+ <page-section :section-title="$t('pageFirmware.sectionTitleFcbCPLDCards')">
|
||
|
|
+ <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>
|
||
|
|
+ </b-card-group>
|
||
|
|
+ </page-section>
|
||
|
|
+</template>
|
||
|
|
+
|
||
|
|
+<script>
|
||
|
|
+import PageSection from '@/components/Global/PageSection';
|
||
|
|
+
|
||
|
|
+export default {
|
||
|
|
+ components: { PageSection },
|
||
|
|
+ computed: {
|
||
|
|
+ running() {
|
||
|
|
+ return this.$store.getters['firmware/fcbCpldFirmware'];
|
||
|
|
+ },
|
||
|
|
+ runningVersion() {
|
||
|
|
+ return this.running?.version || '--';
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+};
|
||
|
|
+</script>
|
||
|
|
+
|
||
|
|
+<style lang="scss" scoped>
|
||
|
|
+.page-section {
|
||
|
|
+ margin-top: -$spacer * 1.5;
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
diff --git a/src/views/Operations/Firmware/FirmwareCardsMe.vue b/src/views/Operations/Firmware/FirmwareCardsMe.vue
|
||
|
|
new file mode 100755
|
||
|
|
index 0000000..8828463
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/views/Operations/Firmware/FirmwareCardsMe.vue
|
||
|
|
@@ -0,0 +1,40 @@
|
||
|
|
+<template>
|
||
|
|
+ <page-section :section-title="$t('pageFirmware.sectionTitleMeCards')">
|
||
|
|
+ <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>
|
||
|
|
+ </b-card-group>
|
||
|
|
+ </page-section>
|
||
|
|
+</template>
|
||
|
|
+
|
||
|
|
+<script>
|
||
|
|
+import PageSection from '@/components/Global/PageSection';
|
||
|
|
+
|
||
|
|
+export default {
|
||
|
|
+ components: { PageSection },
|
||
|
|
+ computed: {
|
||
|
|
+ running() {
|
||
|
|
+ return this.$store.getters['firmware/meFirmware'];
|
||
|
|
+ },
|
||
|
|
+ runningVersion() {
|
||
|
|
+ return this.running?.version || '--';
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+};
|
||
|
|
+</script>
|
||
|
|
+
|
||
|
|
+<style lang="scss" scoped>
|
||
|
|
+.page-section {
|
||
|
|
+ margin-top: -$spacer * 1.5;
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
diff --git a/src/views/Operations/Firmware/FirmwareModalUpdateFirmware.vue b/src/views/Operations/Firmware/FirmwareModalUpdateFirmware.vue
|
||
|
|
index 1835521..79ee979 100644
|
||
|
|
--- a/src/views/Operations/Firmware/FirmwareModalUpdateFirmware.vue
|
||
|
|
+++ b/src/views/Operations/Firmware/FirmwareModalUpdateFirmware.vue
|
||
|
|
@@ -6,6 +6,9 @@
|
||
|
|
:cancel-title="$t('global.action.cancel')"
|
||
|
|
@ok="$emit('ok')"
|
||
|
|
>
|
||
|
|
+ <p v-if="uploadFirmwareType === 'BMC' && firmwareLength > 1">
|
||
|
|
+ {{ $t('pageFirmware.toast.bmcUpdateTips') }}
|
||
|
|
+ </p>
|
||
|
|
<template v-if="isSingleFileUploadEnabled">
|
||
|
|
<p>
|
||
|
|
{{ $t('pageFirmware.modal.updateFirmwareInfo') }}
|
||
|
|
@@ -21,6 +24,22 @@
|
||
|
|
{{ $t('pageFirmware.modal.updateFirmwareInfo3') }}
|
||
|
|
</p>
|
||
|
|
</template>
|
||
|
|
+ <template
|
||
|
|
+ v-else-if="
|
||
|
|
+ uploadFirmwareType == 'BIOS' ||
|
||
|
|
+ uploadFirmwareType == 'CPLD' ||
|
||
|
|
+ uploadFirmwareType == 'FPGA' ||
|
||
|
|
+ uploadFirmwareType == 'HSBP' ||
|
||
|
|
+ uploadFirmwareType == 'FCB'
|
||
|
|
+ "
|
||
|
|
+ >
|
||
|
|
+ {{ $t('pageFirmware.modal.updateFirmwareInfoOem') }}
|
||
|
|
+ </template>
|
||
|
|
+ <template
|
||
|
|
+ v-else-if="uploadFirmwareType && uploadFirmwareType.indexOf('BMC') !== -1"
|
||
|
|
+ >
|
||
|
|
+ {{ $t('pageFirmware.modal.updateFirmwareInfoOemBmc') }}
|
||
|
|
+ </template>
|
||
|
|
<template v-else>
|
||
|
|
{{ $t('pageFirmware.modal.updateFirmwareInfoDefault') }}
|
||
|
|
</template>
|
||
|
|
@@ -29,6 +48,16 @@
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
+ props: {
|
||
|
|
+ uploadFirmwareType: {
|
||
|
|
+ type: String,
|
||
|
|
+ default: '',
|
||
|
|
+ },
|
||
|
|
+ firmwareLength: {
|
||
|
|
+ type: Number,
|
||
|
|
+ default: 0,
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
computed: {
|
||
|
|
runningBmc() {
|
||
|
|
return this.$store.getters['firmware/activeBmcFirmware'];
|
||
|
|
diff --git a/src/views/Operations/Firmware/FirmwareUpdateStatus.vue b/src/views/Operations/Firmware/FirmwareUpdateStatus.vue
|
||
|
|
new file mode 100755
|
||
|
|
index 0000000..e2fd859
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/views/Operations/Firmware/FirmwareUpdateStatus.vue
|
||
|
|
@@ -0,0 +1,822 @@
|
||
|
|
+<template>
|
||
|
|
+ <b-overlay
|
||
|
|
+ z-index="2000"
|
||
|
|
+ class="firmware-overlay"
|
||
|
|
+ :show="showOverlay"
|
||
|
|
+ :opacity="opacity"
|
||
|
|
+ spinner-type="none"
|
||
|
|
+ >
|
||
|
|
+ <b-container
|
||
|
|
+ class="firmware-update-container"
|
||
|
|
+ fluid="xl"
|
||
|
|
+ style="max-width: 1440px"
|
||
|
|
+ >
|
||
|
|
+ <b-row>
|
||
|
|
+ <b-col xl="10" style="margin-bottom: 30px">
|
||
|
|
+ <div class="d-flex justify-content-between align-items-center">
|
||
|
|
+ <upload-file
|
||
|
|
+ v-model="file"
|
||
|
|
+ required
|
||
|
|
+ :disabled="isPageDisabled"
|
||
|
|
+ :validted-file="validtedFileType"
|
||
|
|
+ @submit="uploadImage"
|
||
|
|
+ ></upload-file>
|
||
|
|
+ <b-button
|
||
|
|
+ v-if="!hasUploadedBmc"
|
||
|
|
+ :disabled="
|
||
|
|
+ runningOnSecondaryContainBMC ||
|
||
|
|
+ isPageDisabled ||
|
||
|
|
+ !allFirmwareStatus.some((it) => it.UpdateStatus === 'Uploaded')
|
||
|
|
+ "
|
||
|
|
+ variant="primary"
|
||
|
|
+ size="sm"
|
||
|
|
+ class="btn-file"
|
||
|
|
+ style="flex-shrink: 0; margin-left: 50px; height: 35px"
|
||
|
|
+ @click="updateAll"
|
||
|
|
+ >{{ $t('pageFirmware.form.updateFirmware.updateAll') }}</b-button
|
||
|
|
+ >
|
||
|
|
+ </div>
|
||
|
|
+ </b-col>
|
||
|
|
+ <b-col xl="10">
|
||
|
|
+ <b-table
|
||
|
|
+ show-empty
|
||
|
|
+ :empty-text="$t('pageFirmware.table.emptyMessage')"
|
||
|
|
+ :fields="fields"
|
||
|
|
+ striped
|
||
|
|
+ hover
|
||
|
|
+ :items="allFirmwareStatus"
|
||
|
|
+ >
|
||
|
|
+ <template #row-details="row">
|
||
|
|
+ <div v-if="row.item.name === 'BMC'">
|
||
|
|
+ <b-form-group
|
||
|
|
+ :label="$t('pageFirmware.form.updateFirmware.options')"
|
||
|
|
+ >
|
||
|
|
+ <div class="d-flex">
|
||
|
|
+ <b-form-radio-group
|
||
|
|
+ v-model="bmcConfig"
|
||
|
|
+ style="margin-right: 40px"
|
||
|
|
+ :disabled="bmcConfigDisabled"
|
||
|
|
+ :options="getUpdateOptions('BMC')"
|
||
|
|
+ stacked
|
||
|
|
+ ></b-form-radio-group>
|
||
|
|
+ <b-form-radio-group
|
||
|
|
+ v-model="bmcConfig2"
|
||
|
|
+ :disabled="isPageDisabled"
|
||
|
|
+ :options="bmcConfigOptions"
|
||
|
|
+ stacked
|
||
|
|
+ ></b-form-radio-group>
|
||
|
|
+ </div>
|
||
|
|
+ </b-form-group>
|
||
|
|
+ </div>
|
||
|
|
+ <div v-if="row.item.name === 'BIOS'">
|
||
|
|
+ <b-form-group
|
||
|
|
+ :label="$t('pageFirmware.form.updateFirmware.options')"
|
||
|
|
+ :disabled="isPageDisabled"
|
||
|
|
+ >
|
||
|
|
+ <b-form-radio-group
|
||
|
|
+ v-model="biosConfig2"
|
||
|
|
+ :disabled="isPageDisabled"
|
||
|
|
+ :options="biosConfigOptions"
|
||
|
|
+ stacked
|
||
|
|
+ ></b-form-radio-group>
|
||
|
|
+ </b-form-group>
|
||
|
|
+ </div>
|
||
|
|
+ <div v-if="row.item.name === 'Retimer'">
|
||
|
|
+ <b-form-group
|
||
|
|
+ :label="$t('pageFirmware.form.updateFirmware.options')"
|
||
|
|
+ :disabled="isPageDisabled"
|
||
|
|
+ style="width: 200px"
|
||
|
|
+ >
|
||
|
|
+ <b-form-select
|
||
|
|
+ v-model="retimerConfig"
|
||
|
|
+ :options="retimerOptions"
|
||
|
|
+ ></b-form-select>
|
||
|
|
+ </b-form-group>
|
||
|
|
+ </div>
|
||
|
|
+ </template>
|
||
|
|
+ <template #cell(status)="{ item }">
|
||
|
|
+ <div
|
||
|
|
+ v-if="item.UpdateStatus === 'Updating'"
|
||
|
|
+ class="d-flex align-items-center"
|
||
|
|
+ >
|
||
|
|
+ <div style="width: 140px">
|
||
|
|
+ <b-progress style="border-radius: 20px" :max="100">
|
||
|
|
+ <b-progress-bar
|
||
|
|
+ :value="item.UpdateProgress"
|
||
|
|
+ ></b-progress-bar>
|
||
|
|
+ </b-progress>
|
||
|
|
+ </div>
|
||
|
|
+ <div>
|
||
|
|
+ {{ updatingBmcPartitionName(item) }}
|
||
|
|
+ {{ item.UpdateStatus }}-{{ item.UpdateProgress }}%
|
||
|
|
+ </div>
|
||
|
|
+ </div>
|
||
|
|
+ <div
|
||
|
|
+ v-else-if="item.UpdateStatus === 'Updated'"
|
||
|
|
+ class="d-flex align-items-center"
|
||
|
|
+ >
|
||
|
|
+ {{ updatingBmcPartitionName(item) }}
|
||
|
|
+ {{
|
||
|
|
+ updatingBmcPartitionName(item) !== 'Updating'
|
||
|
|
+ ? ' Updated'
|
||
|
|
+ : ''
|
||
|
|
+ }}
|
||
|
|
+ </div>
|
||
|
|
+ <div v-else class="d-flex align-items-center">
|
||
|
|
+ <div
|
||
|
|
+ v-if="item.UpdateStatus === 'Conflicted'"
|
||
|
|
+ class="mr-1"
|
||
|
|
+ :title="
|
||
|
|
+ $t('pageFirmware.toast.errorUpdateInPeerNodeUpdating')
|
||
|
|
+ "
|
||
|
|
+ >
|
||
|
|
+ <status-icon status="danger" />
|
||
|
|
+ </div>
|
||
|
|
+ {{ item.UpdateStatus }}
|
||
|
|
+ </div>
|
||
|
|
+ </template>
|
||
|
|
+ <template #cell(version)="{ item }">{{
|
||
|
|
+ item.VersionStatus
|
||
|
|
+ }}</template>
|
||
|
|
+ <template #cell(Action)="{ item }">
|
||
|
|
+ <link-button
|
||
|
|
+ :disabled="isPageDisabled || item.UpdateStatus !== 'Uploaded'"
|
||
|
|
+ @click="handleUpdate(item)"
|
||
|
|
+ >{{ $t('pageFirmware.table.update') }}</link-button
|
||
|
|
+ >
|
||
|
|
+ <link-button
|
||
|
|
+ :disabled="
|
||
|
|
+ isPageDisabled ||
|
||
|
|
+ ['Updated', 'Updating'].includes(item.UpdateStatus)
|
||
|
|
+ "
|
||
|
|
+ danger
|
||
|
|
+ @click="handleDelete(item)"
|
||
|
|
+ >{{ $t('pageFirmware.table.delete') }}</link-button
|
||
|
|
+ >
|
||
|
|
+ </template>
|
||
|
|
+ </b-table></b-col
|
||
|
|
+ ></b-row
|
||
|
|
+ >
|
||
|
|
+ <modal-update-firmware
|
||
|
|
+ :upload-firmware-type="updatingFirmware && updatingFirmware.name"
|
||
|
|
+ :firmware-length="allFirmwareStatus && allFirmwareStatus.length"
|
||
|
|
+ @ok="handleUpdateFirmware"
|
||
|
|
+ />
|
||
|
|
+ </b-container>
|
||
|
|
+ </b-overlay>
|
||
|
|
+</template>
|
||
|
|
+
|
||
|
|
+<script>
|
||
|
|
+// import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
|
||
|
|
+// import IconChevron from '@carbon/icons-vue/es/chevron--down/20';
|
||
|
|
+import BVToastMixin from '@/components/Mixins/BVToastMixin';
|
||
|
|
+import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
|
||
|
|
+import LinkButton from '@/components/Global/LinkButton';
|
||
|
|
+import UploadFile from '@/components/Global/UploadFile';
|
||
|
|
+import ModalUpdateFirmware from './FirmwareModalUpdateFirmware';
|
||
|
|
+import { BOverlay } from 'bootstrap-vue';
|
||
|
|
+import { bus } from '@/utilities/bus';
|
||
|
|
+// import TableRowExpandMixin, {
|
||
|
|
+// expandRowLabel,
|
||
|
|
+// } from '@/components/Mixins/TableRowExpandMixin';
|
||
|
|
+export default {
|
||
|
|
+ components: {
|
||
|
|
+ // IconTrashcan,
|
||
|
|
+ LinkButton,
|
||
|
|
+ UploadFile,
|
||
|
|
+ ModalUpdateFirmware,
|
||
|
|
+ BOverlay,
|
||
|
|
+ // IconChevron,
|
||
|
|
+ },
|
||
|
|
+ mixins: [BVToastMixin, LoadingBarMixin],
|
||
|
|
+ props: {
|
||
|
|
+ isPageDisabled: {
|
||
|
|
+ type: Boolean,
|
||
|
|
+ default: false,
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ data() {
|
||
|
|
+ return {
|
||
|
|
+ console,
|
||
|
|
+ file: null,
|
||
|
|
+ fileErrorTips: '',
|
||
|
|
+ bmcConfig: 'Keep',
|
||
|
|
+ bmcConfig2: 'BMC',
|
||
|
|
+ biosConfig: 'Keep',
|
||
|
|
+ biosConfig2: 'BIOS',
|
||
|
|
+ retimerConfig: 'Retimer0',
|
||
|
|
+ isKeepConfigs: true,
|
||
|
|
+ updatingFirmware: null,
|
||
|
|
+ getStatustimerId: undefined,
|
||
|
|
+ isNeedReboot: false,
|
||
|
|
+ showOverlay: false,
|
||
|
|
+ opacity: 0,
|
||
|
|
+ // expandRowLabel,
|
||
|
|
+ fields: [
|
||
|
|
+ {
|
||
|
|
+ key: 'expandRow',
|
||
|
|
+ label: '',
|
||
|
|
+ tdClass: 'table-row-expand',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ key: 'name',
|
||
|
|
+ label: this.$t('pageFirmware.table.firmwareName'),
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ key: 'status',
|
||
|
|
+ label: this.$t('pageFirmware.table.firmwareStatus'),
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ key: 'version',
|
||
|
|
+ label: this.$t('pageFirmware.table.firmwareVersion'),
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ key: 'Action',
|
||
|
|
+ label: '',
|
||
|
|
+ },
|
||
|
|
+ ],
|
||
|
|
+ retimerOptions: [
|
||
|
|
+ 'Retimer0',
|
||
|
|
+ 'Retimer1',
|
||
|
|
+ 'Retimer2',
|
||
|
|
+ 'Retimer3',
|
||
|
|
+ 'Retimer4',
|
||
|
|
+ 'Retimer5',
|
||
|
|
+ 'Retimer6',
|
||
|
|
+ 'Retimer7',
|
||
|
|
+ 'All',
|
||
|
|
+ ],
|
||
|
|
+ };
|
||
|
|
+ },
|
||
|
|
+ computed: {
|
||
|
|
+ allFirmwareStatus() {
|
||
|
|
+ const allFirmware = this.$store.getters['firmware/allFirmwareStatus'];
|
||
|
|
+
|
||
|
|
+ return (
|
||
|
|
+ allFirmware?.reduce((res, item) => {
|
||
|
|
+ const [temp] = Object.entries(item);
|
||
|
|
+ res.push({
|
||
|
|
+ name: temp[0],
|
||
|
|
+ ...temp[1],
|
||
|
|
+ _showDetails:
|
||
|
|
+ temp[1].UpdateStatus === 'Uploaded' &&
|
||
|
|
+ (temp[0] === 'BMC' ||
|
||
|
|
+ temp[0] === 'BIOS' ||
|
||
|
|
+ temp[0] === 'Retimer'),
|
||
|
|
+ });
|
||
|
|
+ return res;
|
||
|
|
+ }, []) || []
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
+ priorityFirmware() {
|
||
|
|
+ const pri = this.$store.getters['firmware/priorityFirmware'];
|
||
|
|
+ return pri?.Priority ?? null;
|
||
|
|
+ },
|
||
|
|
+ bmcConfigDisabled() {
|
||
|
|
+ return (
|
||
|
|
+ this.isPageDisabled ||
|
||
|
|
+ this.flagForBmcConfig ||
|
||
|
|
+ this.flagForPrimaryBmcConfig
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
+ flagForBmcConfig() {
|
||
|
|
+ return this.priorityFirmware === 1 && this.bmcConfig2 === 'BMC';
|
||
|
|
+ },
|
||
|
|
+ flagForPrimaryBmcConfig() {
|
||
|
|
+ return this.priorityFirmware === 0 && this.bmcConfig2 === 'BMC_Secondary';
|
||
|
|
+ },
|
||
|
|
+ // Upgrade the primary from the primary or upgrade the backup from the backup.
|
||
|
|
+ isPrimaryToPrimaryOrSecondaryToSecondary() {
|
||
|
|
+ return (
|
||
|
|
+ (this.priorityFirmware === 0 && this.bmcConfig2 === 'BMC') ||
|
||
|
|
+ (this.priorityFirmware === 1 && this.bmcConfig2 === 'BMC_Secondary')
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
+ // bmcIsUpdatingfCurrentPartition
|
||
|
|
+ bmcIsUpdatingfCurrentPartition() {
|
||
|
|
+ return this.$store.getters['firmware/bmcIsUpdatingfCurrentPartition'];
|
||
|
|
+ },
|
||
|
|
+ runningOnSecondaryContainBMC() {
|
||
|
|
+ if (
|
||
|
|
+ this.allFirmwareStatus.find(
|
||
|
|
+ (it) => it.UpdateStatus === 'Uploaded' && it.name === 'BMC'
|
||
|
|
+ )
|
||
|
|
+ ) {
|
||
|
|
+ if (this.bmcConfig2 === 'BMC' || this.bmcConfig2 === 'BMC_Secondary') {
|
||
|
|
+ return this.priorityFirmware === 1;
|
||
|
|
+ }
|
||
|
|
+ return false;
|
||
|
|
+ }
|
||
|
|
+ return false;
|
||
|
|
+ },
|
||
|
|
+ bmcConfigOptions() {
|
||
|
|
+ const opts = [
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.primaryImage'),
|
||
|
|
+ value: 'BMC',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.secondaryImage'),
|
||
|
|
+ value: 'BMC_Secondary',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.both'),
|
||
|
|
+ value: 'Both',
|
||
|
|
+ },
|
||
|
|
+ ];
|
||
|
|
+ const firmwareStatus =
|
||
|
|
+ this.$store.getters['firmware/allFirmwareStatus'] || [];
|
||
|
|
+ const bothEnabled = firmwareStatus.some(
|
||
|
|
+ (it) => it.BMC?.BothUpdateEnable === true
|
||
|
|
+ );
|
||
|
|
+ if (!bothEnabled) {
|
||
|
|
+ opts.splice(2, 1);
|
||
|
|
+ }
|
||
|
|
+ return this.priorityFirmware === 1 ? opts.slice(0, 1) : opts;
|
||
|
|
+ },
|
||
|
|
+ biosConfigOptions() {
|
||
|
|
+ const opts = [
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.primaryImage'),
|
||
|
|
+ value: 'BIOS',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.secondaryImage'),
|
||
|
|
+ value: 'BIOS_Secondary',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.both'),
|
||
|
|
+ value: 'Both',
|
||
|
|
+ },
|
||
|
|
+ ];
|
||
|
|
+ const firmwareStatus =
|
||
|
|
+ this.$store.getters['firmware/allFirmwareStatus'] || [];
|
||
|
|
+ const bothEnabled = firmwareStatus.some(
|
||
|
|
+ (it) => it.BIOS?.BothUpdateEnable === true
|
||
|
|
+ );
|
||
|
|
+ if (!bothEnabled) {
|
||
|
|
+ opts.splice(2, 1);
|
||
|
|
+ }
|
||
|
|
+ return opts;
|
||
|
|
+ },
|
||
|
|
+ hasUploadedBmc() {
|
||
|
|
+ return this.allFirmwareStatus.find(
|
||
|
|
+ (it) => it.UpdateStatus === 'Uploaded' && it.name === 'BMC'
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ watch: {
|
||
|
|
+ flagForBmcConfig: {
|
||
|
|
+ immediate: true,
|
||
|
|
+ handler(newVal) {
|
||
|
|
+ if (newVal) this.bmcConfig = 'FactoryReset';
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ flagForPrimaryBmcConfig: {
|
||
|
|
+ immediate: true,
|
||
|
|
+ handler(newVal) {
|
||
|
|
+ if (newVal) this.bmcConfig = 'Keep';
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+ created() {
|
||
|
|
+ // this.$store.dispatch('firmware/getAllUpdateStatus');
|
||
|
|
+ this.getFirmwareStatus();
|
||
|
|
+ setTimeout(() => {
|
||
|
|
+ this.getFirmwareStatusTimer();
|
||
|
|
+ }, 5000);
|
||
|
|
+ },
|
||
|
|
+ beforeDestroy() {
|
||
|
|
+ clearTimeout(this.getStatustimerId);
|
||
|
|
+ this.getStatustimerId = null;
|
||
|
|
+ },
|
||
|
|
+ methods: {
|
||
|
|
+ updatingBmcPartitionName(item) {
|
||
|
|
+ if (item.name !== 'BMC' || !this.$store.state.firmware.bmcIsUpdating)
|
||
|
|
+ return '';
|
||
|
|
+ // When upgrading BMC and BMC's Update progress is null and Update Status is Updated, Updating is displayed
|
||
|
|
+ if (
|
||
|
|
+ item.UpdateStatus === 'Updated' &&
|
||
|
|
+ this.$store.state.firmware.bmcIsUpdating &&
|
||
|
|
+ item.UpdateProgress === null
|
||
|
|
+ ) {
|
||
|
|
+ return 'Updating';
|
||
|
|
+ }
|
||
|
|
+ const currentPartition =
|
||
|
|
+ this.priorityFirmware === 0 ? 'Primary' : 'Secondary';
|
||
|
|
+ const map = {
|
||
|
|
+ Primary: 'Secondary',
|
||
|
|
+ Secondary: 'Primary',
|
||
|
|
+ };
|
||
|
|
+ if (this.bmcIsUpdatingfCurrentPartition) {
|
||
|
|
+ return currentPartition;
|
||
|
|
+ } else {
|
||
|
|
+ return map[currentPartition];
|
||
|
|
+ }
|
||
|
|
+ },
|
||
|
|
+ // get FirmwareStatus
|
||
|
|
+ getFirmwareStatus() {
|
||
|
|
+ this.loadingVisible(true);
|
||
|
|
+ this.$store.dispatch('firmware/getAllUpdateStatus').finally(() => {
|
||
|
|
+ this.loadingVisible(false);
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ // timer
|
||
|
|
+ async getFirmwareStatusTimer() {
|
||
|
|
+ try {
|
||
|
|
+ await this.$store.dispatch('firmware/getAllUpdateStatus');
|
||
|
|
+ } finally {
|
||
|
|
+ if (this.getStatustimerId !== null) {
|
||
|
|
+ this.getStatustimerId = setTimeout(() => {
|
||
|
|
+ this.getFirmwareStatusTimer();
|
||
|
|
+ }, 5000);
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ },
|
||
|
|
+ loadingVisible(bool) {
|
||
|
|
+ bool ? this.startLoader() : this.endLoader();
|
||
|
|
+ this.$root.$emit('set-upload-event', bool);
|
||
|
|
+ },
|
||
|
|
+ getUpdateOptions() {
|
||
|
|
+ const all = [
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.form.updateOptions.keep'),
|
||
|
|
+ value: 'Keep',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.form.updateOptions.clear'),
|
||
|
|
+ value: 'Clear',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.form.updateOptions.partialKeep'),
|
||
|
|
+ value: 'PartialKeep',
|
||
|
|
+ },
|
||
|
|
+ {
|
||
|
|
+ text: this.$t('pageFirmware.form.updateOptions.factoryReset'),
|
||
|
|
+ value: 'FactoryReset',
|
||
|
|
+ },
|
||
|
|
+ ];
|
||
|
|
+ // return type === 'BMC' ? all : all.slice(0, 2);
|
||
|
|
+ return all.slice(0, 2);
|
||
|
|
+ },
|
||
|
|
+ uploadImage() {
|
||
|
|
+ this.loadingVisible(true);
|
||
|
|
+ const timerId = setTimeout(() => {
|
||
|
|
+ this.loadingVisible(false);
|
||
|
|
+ this.errorToast(this.$t('pageFirmware.toast.timeoutUploadMessage'), {
|
||
|
|
+ title: this.$t('pageFirmware.toast.timeoutUpload'),
|
||
|
|
+ });
|
||
|
|
+ }, 1000000);
|
||
|
|
+ const toastId = 'upload-started-toast' + Date.now();
|
||
|
|
+ this.infoToast(this.$t('pageFirmware.toast.uploadStartedMessage'), {
|
||
|
|
+ title: this.$t('pageFirmware.toast.uploadStarted'),
|
||
|
|
+ timestamp: true,
|
||
|
|
+ id: toastId,
|
||
|
|
+ });
|
||
|
|
+ this.dispatchUpload(timerId, toastId);
|
||
|
|
+ },
|
||
|
|
+ dispatchUpload(timerId, toastId) {
|
||
|
|
+ console.log('file', this.file);
|
||
|
|
+ this.$store
|
||
|
|
+ .dispatch('firmware/uploadFirmwareOEM', this.file)
|
||
|
|
+ .then((res) => {
|
||
|
|
+ setTimeout(() => {
|
||
|
|
+ this.$bvToast.hide(toastId);
|
||
|
|
+ }, 10000);
|
||
|
|
+ this.file = null;
|
||
|
|
+ if (!res) return;
|
||
|
|
+ const oemData = res?.data?.Oem?.Luxshare?.[0];
|
||
|
|
+ const firmwareKey = oemData ? Object.keys(oemData)[0] : '';
|
||
|
|
+ const versionStatus = oemData
|
||
|
|
+ ? oemData[firmwareKey]?.VersionStatus
|
||
|
|
+ : '';
|
||
|
|
+ const uploadStatus = oemData
|
||
|
|
+ ? oemData[firmwareKey]?.UpdateStatus
|
||
|
|
+ : '';
|
||
|
|
+ if (uploadStatus === 'Failed') {
|
||
|
|
+ let errorToast = this.$t('pageFirmware.toast.errorUploadFirmware');
|
||
|
|
+ if (versionStatus === 'Invalid') {
|
||
|
|
+ errorToast = this.$t(
|
||
|
|
+ 'pageFirmware.toast.validateFirmwareFailed',
|
||
|
|
+ {
|
||
|
|
+ firmware: firmwareKey,
|
||
|
|
+ }
|
||
|
|
+ );
|
||
|
|
+ } else if (versionStatus === 'Mismatch') {
|
||
|
|
+ errorToast = this.$t('pageFirmware.toast.firmwareIdMismatch', {
|
||
|
|
+ firmware: firmwareKey,
|
||
|
|
+ });
|
||
|
|
+ }
|
||
|
|
+ this.errorToast(errorToast);
|
||
|
|
+ } else {
|
||
|
|
+ this.successToast(
|
||
|
|
+ this.$t('pageFirmware.toast.uploadSuccessMessage'),
|
||
|
|
+ {
|
||
|
|
+ title: this.$t('pageFirmware.toast.uploadSuccess'),
|
||
|
|
+ timestamp: true,
|
||
|
|
+ }
|
||
|
|
+ );
|
||
|
|
+ }
|
||
|
|
+ this.getFirmwareStatus();
|
||
|
|
+ })
|
||
|
|
+ .catch(({ message }) => {
|
||
|
|
+ this.errorToast(message);
|
||
|
|
+ })
|
||
|
|
+ .finally(() => {
|
||
|
|
+ this.loadingVisible(false);
|
||
|
|
+ clearTimeout(timerId);
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ validtedFileType(file) {
|
||
|
|
+ return new Promise((resolve, reject) => {
|
||
|
|
+ const fileExtension = file.name.split('.').pop().toLowerCase();
|
||
|
|
+ if (fileExtension === 'tar') {
|
||
|
|
+ resolve('');
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+ if (fileExtension === 'gz' || fileExtension === 'tgz') {
|
||
|
|
+ resolve('');
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ const temporaryFileReader = new FileReader();
|
||
|
|
+ temporaryFileReader.onerror = () => {
|
||
|
|
+ temporaryFileReader.abort();
|
||
|
|
+ reject(this.$t('pageFirmware.form.invalidFiletype'));
|
||
|
|
+ };
|
||
|
|
+ temporaryFileReader.onload = (e) => {
|
||
|
|
+ const arr = new Uint8Array(e.target.result).subarray(0, 4);
|
||
|
|
+ let header = '';
|
||
|
|
+ for (let i = 0; i < arr.length; i++) {
|
||
|
|
+ header += arr[i].toString(16);
|
||
|
|
+ }
|
||
|
|
+ let type = null;
|
||
|
|
+ switch (header) {
|
||
|
|
+ case '504b34':
|
||
|
|
+ type = 'application/x-zip-compressed';
|
||
|
|
+ break;
|
||
|
|
+ case '1f8b88':
|
||
|
|
+ type = 'application/x-gzip';
|
||
|
|
+ break;
|
||
|
|
+ default:
|
||
|
|
+ type = 'unknown';
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+ const validateFiletype = [
|
||
|
|
+ 'application/x-gzip',
|
||
|
|
+ 'application/x-zip-compressed',
|
||
|
|
+ 'application/x-tar',
|
||
|
|
+ ];
|
||
|
|
+ if (validateFiletype.includes(type)) {
|
||
|
|
+ resolve('');
|
||
|
|
+ } else {
|
||
|
|
+ reject(this.$t('pageFirmware.form.invalidFiletype'));
|
||
|
|
+ }
|
||
|
|
+ };
|
||
|
|
+ temporaryFileReader.readAsArrayBuffer(file);
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ formatStatus(item) {
|
||
|
|
+ if (item.UpdateStatus === 'Updating') {
|
||
|
|
+ // return <b-progress variant="primary"></b-progress>;
|
||
|
|
+ return 'Updating - ' + item.UpdateProgress + '%';
|
||
|
|
+ } else return item.UpdateStatus;
|
||
|
|
+ },
|
||
|
|
+ handleUpdate(item) {
|
||
|
|
+ this.updatingFirmware = item;
|
||
|
|
+ this.$bvModal.show('modal-update-firmware');
|
||
|
|
+ },
|
||
|
|
+ getAllUpdateAction() {
|
||
|
|
+ if (
|
||
|
|
+ this.allFirmwareStatus.find(
|
||
|
|
+ (it) => it.UpdateStatus === 'Uploaded' && it.name === 'BMC'
|
||
|
|
+ )
|
||
|
|
+ ) {
|
||
|
|
+ return this.bmcConfig;
|
||
|
|
+ } else if (
|
||
|
|
+ this.allFirmwareStatus.find(
|
||
|
|
+ (it) => it.UpdateStatus === 'Uploaded' && it.name === 'BIOS'
|
||
|
|
+ )
|
||
|
|
+ ) {
|
||
|
|
+ return this.biosConfig;
|
||
|
|
+ } else {
|
||
|
|
+ return undefined;
|
||
|
|
+ }
|
||
|
|
+ },
|
||
|
|
+ getTarget() {
|
||
|
|
+ if (this.updatingFirmware.name === 'BMC') {
|
||
|
|
+ return this.bmcConfig2;
|
||
|
|
+ } else if (this.updatingFirmware.name === 'BIOS') {
|
||
|
|
+ return this.biosConfig2;
|
||
|
|
+ } else if (this.updatingFirmware.name === 'Retimer') {
|
||
|
|
+ return this.retimerConfig;
|
||
|
|
+ } else {
|
||
|
|
+ return this.updatingFirmware.name;
|
||
|
|
+ }
|
||
|
|
+ },
|
||
|
|
+ checkIsNeedReboot(isAll) {
|
||
|
|
+ // Single update: it's BMC and it upgrades the primary from the primary or the backup from the backup.
|
||
|
|
+ // it's BMC and the Both is selected.
|
||
|
|
+ return (
|
||
|
|
+ !isAll &&
|
||
|
|
+ this.updatingFirmware?.name === 'BMC' &&
|
||
|
|
+ (this.bmcConfig2 === 'Both' ||
|
||
|
|
+ this.isPrimaryToPrimaryOrSecondaryToSecondary)
|
||
|
|
+ );
|
||
|
|
+ },
|
||
|
|
+ handleUpdateFirmware(isAll) {
|
||
|
|
+ this.isNeedReboot = this.checkIsNeedReboot(isAll);
|
||
|
|
+ if (
|
||
|
|
+ !isAll &&
|
||
|
|
+ this.updatingFirmware.name === 'BMC' &&
|
||
|
|
+ this.bmcConfig2 === 'Both'
|
||
|
|
+ ) {
|
||
|
|
+ isAll = true;
|
||
|
|
+ }
|
||
|
|
+ if (
|
||
|
|
+ !isAll &&
|
||
|
|
+ this.updatingFirmware.name === 'BIOS' &&
|
||
|
|
+ this.biosConfig2 === 'Both'
|
||
|
|
+ ) {
|
||
|
|
+ isAll = true;
|
||
|
|
+ }
|
||
|
|
+ this.loadingVisible(true);
|
||
|
|
+ const timerId = setTimeout(() => {
|
||
|
|
+ const message = this.$t(
|
||
|
|
+ 'pageFirmware.form.updateFirmware.updateTimeout'
|
||
|
|
+ );
|
||
|
|
+ this.updateInfoFail(timerId, message);
|
||
|
|
+ }, 1500000);
|
||
|
|
+ this.infoToast(this.$t('pageFirmware.toast.updateStartedMessage'), {
|
||
|
|
+ title: this.$t('pageFirmware.toast.updateStarted'),
|
||
|
|
+ timestamp: true,
|
||
|
|
+ });
|
||
|
|
+ let updateConfigs;
|
||
|
|
+ if (isAll) {
|
||
|
|
+ updateConfigs = {
|
||
|
|
+ Target: 'All',
|
||
|
|
+ Action: this.getAllUpdateAction(),
|
||
|
|
+ };
|
||
|
|
+ } else {
|
||
|
|
+ updateConfigs = {
|
||
|
|
+ Target: this.getTarget(),
|
||
|
|
+ Action:
|
||
|
|
+ this.updatingFirmware.name.search(/BIOS|BMC/) !== -1
|
||
|
|
+ ? this[`${this.updatingFirmware.name.toLowerCase()}Config`]
|
||
|
|
+ : undefined,
|
||
|
|
+ };
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ this.$store
|
||
|
|
+ .dispatch('firmware/startUpdate', updateConfigs)
|
||
|
|
+ .then((res) => {
|
||
|
|
+ if (!res) return;
|
||
|
|
+ if (this.isNeedReboot) {
|
||
|
|
+ this.$store.commit('firmware/setBmcIsUpdating', true);
|
||
|
|
+ this.warningToast(
|
||
|
|
+ this.$t('pageFirmware.toast.bmcUpdatingTips'),
|
||
|
|
+ {
|
||
|
|
+ toaster: 'b-toaster-top-center',
|
||
|
|
+ id: 'bmcUpdatingTips',
|
||
|
|
+ },
|
||
|
|
+ true
|
||
|
|
+ );
|
||
|
|
+ bus.$on('bmcUpdateComplete', () => {
|
||
|
|
+ this.$bvToast.hide();
|
||
|
|
+ this.successToast(
|
||
|
|
+ this.$t('pageFirmware.toast.bmcUpdateCompleteTips'),
|
||
|
|
+ {
|
||
|
|
+ toaster: 'b-toaster-top-center',
|
||
|
|
+ },
|
||
|
|
+ true
|
||
|
|
+ );
|
||
|
|
+ this.opacity = 0.1;
|
||
|
|
+ });
|
||
|
|
+ let flag = false;
|
||
|
|
+ bus.$on('updateCurrentPartition', () => {
|
||
|
|
+ if (flag) return;
|
||
|
|
+ flag = true;
|
||
|
|
+ clearTimeout(this.getStatustimerId);
|
||
|
|
+ this.getStatustimerId = null;
|
||
|
|
+ this.$store.commit('firmware/setBmcUpdateProgress', 0);
|
||
|
|
+ this.$store.commit(
|
||
|
|
+ 'firmware/setBmcIsUpdatingfCurrentPartition',
|
||
|
|
+ true
|
||
|
|
+ );
|
||
|
|
+ this.$store.dispatch('firmware/getBmcUpdateStatus');
|
||
|
|
+ });
|
||
|
|
+ this.showOverlay = true;
|
||
|
|
+ }
|
||
|
|
+ this.updateInfoSuccess(timerId, isAll);
|
||
|
|
+ })
|
||
|
|
+ .catch((e) => {
|
||
|
|
+ const errorCode = e?.response?.status;
|
||
|
|
+ let errMsg;
|
||
|
|
+ if (errorCode === 405 && isAll) {
|
||
|
|
+ errMsg = this.$t('pageFirmware.toast.errorUpdateAsyncAndSync');
|
||
|
|
+ } else if (errorCode === 503) {
|
||
|
|
+ errMsg = this.$t('pageFirmware.toast.errorUpdateInPost');
|
||
|
|
+ } else if (errorCode === 409) {
|
||
|
|
+ errMsg = this.$t(
|
||
|
|
+ 'pageFirmware.toast.errorUpdateInPeerNodeUpdating'
|
||
|
|
+ );
|
||
|
|
+ } else {
|
||
|
|
+ errMsg = this.$t('pageFirmware.toast.errorUpdateFirmware');
|
||
|
|
+ }
|
||
|
|
+ this.updateInfoFail(undefined, errMsg);
|
||
|
|
+ })
|
||
|
|
+ .finally(() => {
|
||
|
|
+ clearTimeout(timerId);
|
||
|
|
+ this.loadingVisible(false);
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ async updateAll() {
|
||
|
|
+ const isBMCUploaded = this.allFirmwareStatus.some(
|
||
|
|
+ (it) => it.name === 'BMC' && it.UpdateStatus === 'Uploaded'
|
||
|
|
+ );
|
||
|
|
+ const tips =
|
||
|
|
+ isBMCUploaded && this.allFirmwareStatus.length > 1
|
||
|
|
+ ? this.$t('pageFirmware.toast.bmcUpdateTips')
|
||
|
|
+ : null;
|
||
|
|
+ const confirmTitle = this.$t('pageFirmware.modal.updateAllConfirm');
|
||
|
|
+
|
||
|
|
+ try {
|
||
|
|
+ const value = tips
|
||
|
|
+ ? await this.$bvModal.msgBoxConfirm(tips, { title: confirmTitle })
|
||
|
|
+ : await this.$bvModal.msgBoxConfirm(confirmTitle);
|
||
|
|
+
|
||
|
|
+ if (value) {
|
||
|
|
+ this.handleUpdateFirmware(true);
|
||
|
|
+ }
|
||
|
|
+ } catch (error) {
|
||
|
|
+ console.error('Update all error', error);
|
||
|
|
+ }
|
||
|
|
+ },
|
||
|
|
+ updateInfoSuccess(isAll) {
|
||
|
|
+ this.uploadResultMessage = !isAll
|
||
|
|
+ ? this.$t('pageFirmware.form.updateFirmware.updateFinished', {
|
||
|
|
+ type: this.updatingFirmware.name,
|
||
|
|
+ version: this.updatingFirmware.VersionStatus,
|
||
|
|
+ })
|
||
|
|
+ : this.$t('pageFirmware.table.updateComplete');
|
||
|
|
+ this.infoToast(this.$t('pageFirmware.toast.verifyUpdateMessage'), {
|
||
|
|
+ title: this.$t('pageFirmware.toast.verifyUpdate'),
|
||
|
|
+ refreshAction: true,
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ updateInfoFail(timerId, message) {
|
||
|
|
+ this.errorToast(message);
|
||
|
|
+ timerId && this.loadingVisible(false);
|
||
|
|
+ timerId && clearTimeout(timerId);
|
||
|
|
+ },
|
||
|
|
+ handleDelete(item) {
|
||
|
|
+ this.$bvModal
|
||
|
|
+ .msgBoxConfirm(
|
||
|
|
+ this.$t('pageFirmware.modal.deleteConfirm', {
|
||
|
|
+ firmware: item.name,
|
||
|
|
+ })
|
||
|
|
+ )
|
||
|
|
+ .then((value) => {
|
||
|
|
+ if (value) {
|
||
|
|
+ this.loadingVisible(true);
|
||
|
|
+ this.$store
|
||
|
|
+ .dispatch('firmware/deleteFirmware', item.name)
|
||
|
|
+ .then(() => {
|
||
|
|
+ this.successToast(
|
||
|
|
+ this.$t('pageFirmware.toast.firmwareDeleted', {
|
||
|
|
+ firmware: item.name,
|
||
|
|
+ }),
|
||
|
|
+ {
|
||
|
|
+ title: this.$t('pageFirmware.toast.deleteSuccess'),
|
||
|
|
+ }
|
||
|
|
+ );
|
||
|
|
+ clearTimeout(this.getStatustimerId);
|
||
|
|
+ this.getStatustimerId = null;
|
||
|
|
+ this.getFirmwareStatusTimer().finally(() => {
|
||
|
|
+ this.loadingVisible(false);
|
||
|
|
+ });
|
||
|
|
+ })
|
||
|
|
+ .catch(() => {
|
||
|
|
+ this.loadingVisible(false);
|
||
|
|
+ this.errorToast(
|
||
|
|
+ this.$t('pageFirmware.toast.deleteFailed', {
|
||
|
|
+ firmware: item.name,
|
||
|
|
+ })
|
||
|
|
+ );
|
||
|
|
+ });
|
||
|
|
+ }
|
||
|
|
+ });
|
||
|
|
+ },
|
||
|
|
+ },
|
||
|
|
+};
|
||
|
|
+</script>
|
||
|
|
+<style lang="scss" scoped>
|
||
|
|
+$btn-height: 33px;
|
||
|
|
+.btn-file {
|
||
|
|
+ height: $btn-height;
|
||
|
|
+ white-space: nowrap;
|
||
|
|
+}
|
||
|
|
+.firmware-overlay {
|
||
|
|
+ height: 100vh;
|
||
|
|
+}
|
||
|
|
+</style>
|
||
|
|
--
|
||
|
|
2.25.1
|
||
|
|
|