summaryrefslogtreecommitdiff
path: root/src/env
diff options
context:
space:
mode:
Diffstat (limited to 'src/env')
-rw-r--r--src/env/components/FirmwareSingleImage/FirmwareSingleImage.vue405
-rw-r--r--src/env/components/FirmwareSingleImage/FirmwareSingleImageModalRebootBackup.vue33
-rw-r--r--src/env/components/FirmwareSingleImage/FirmwareSingleImageModalUpload.vue18
-rw-r--r--src/env/components/FirmwareSingleImage/index.js2
-rw-r--r--src/env/router/ibm.js234
-rw-r--r--src/env/store/FirmwareSingleImage/FirmwareSingleImageStore.js161
-rw-r--r--src/env/store/ibm.js6
7 files changed, 844 insertions, 15 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>
diff --git a/src/env/components/FirmwareSingleImage/FirmwareSingleImageModalRebootBackup.vue b/src/env/components/FirmwareSingleImage/FirmwareSingleImageModalRebootBackup.vue
new file mode 100644
index 00000000..a8fb3ad5
--- /dev/null
+++ b/src/env/components/FirmwareSingleImage/FirmwareSingleImageModalRebootBackup.vue
@@ -0,0 +1,33 @@
+<template>
+ <b-modal
+ id="modal-reboot-backup"
+ :ok-title="$t('pageFirmware.modal.rebootFromBackup.primaryAction')"
+ :title="$t('pageFirmware.modal.rebootFromBackup.title')"
+ @ok="$emit('ok')"
+ >
+ <p>
+ {{ $t('pageFirmware.modal.rebootFromBackup.message1', { backup }) }}
+ </p>
+ <p>
+ {{ $t('pageFirmware.modal.rebootFromBackup.message2', { current }) }}
+ </p>
+ <p class="font-weight-bold">
+ {{ $t('pageFirmware.modal.rebootFromBackup.message3', { backup }) }}
+ </p>
+ </b-modal>
+</template>
+
+<script>
+export default {
+ props: {
+ current: {
+ type: String,
+ required: true
+ },
+ backup: {
+ type: String,
+ required: true
+ }
+ }
+};
+</script>
diff --git a/src/env/components/FirmwareSingleImage/FirmwareSingleImageModalUpload.vue b/src/env/components/FirmwareSingleImage/FirmwareSingleImageModalUpload.vue
new file mode 100644
index 00000000..d092becd
--- /dev/null
+++ b/src/env/components/FirmwareSingleImage/FirmwareSingleImageModalUpload.vue
@@ -0,0 +1,18 @@
+<template>
+ <b-modal
+ id="modal-upload"
+ :title="$t('pageFirmware.modal.uploadAndReboot.title')"
+ :ok-title="$t('pageFirmware.modal.uploadAndReboot.primaryAction')"
+ @ok="$emit('ok')"
+ >
+ <p>
+ {{ $t('pageFirmware.modal.uploadAndReboot.message1') }}
+ </p>
+ <p>
+ {{ $t('pageFirmware.modal.uploadAndReboot.message2') }}
+ </p>
+ <p class="font-weight-bold">
+ {{ $t('pageFirmware.modal.uploadAndReboot.message3') }}
+ </p>
+ </b-modal>
+</template>
diff --git a/src/env/components/FirmwareSingleImage/index.js b/src/env/components/FirmwareSingleImage/index.js
new file mode 100644
index 00000000..06f31f91
--- /dev/null
+++ b/src/env/components/FirmwareSingleImage/index.js
@@ -0,0 +1,2 @@
+import FirmwareSingleImage from './FirmwareSingleImage.vue';
+export default FirmwareSingleImage;
diff --git a/src/env/router/ibm.js b/src/env/router/ibm.js
index 213920db..bfba0f0e 100644
--- a/src/env/router/ibm.js
+++ b/src/env/router/ibm.js
@@ -1,15 +1,225 @@
-import { remove } from 'lodash';
-import routes from '@/router/routes';
+import AppLayout from '@/layouts/AppLayout.vue';
+import ChangePassword from '@/views/ChangePassword';
+import ConsoleLayout from '@/layouts/ConsoleLayout.vue';
+import DateTimeSettings from '@/views/Configuration/DateTimeSettings';
+import EventLogs from '@/views/Health/EventLogs';
+import HardwareStatus from '@/views/Health/HardwareStatus';
+import Ldap from '@/views/AccessControl/Ldap';
+import LocalUserManagement from '@/views/AccessControl/LocalUserManagement';
+import Login from '@/views/Login';
+import LoginLayout from '@/layouts/LoginLayout';
+import ManagePowerUsage from '@/views/Control/ManagePowerUsage';
+import NetworkSettings from '@/views/Configuration/NetworkSettings';
+import Overview from '@/views/Overview';
+import PageNotFound from '@/views/PageNotFound';
+import ProfileSettings from '@/views/ProfileSettings';
+import RebootBmc from '@/views/Control/RebootBmc';
+import Sensors from '@/views/Health/Sensors';
+import SerialOverLan from '@/views/Control/SerialOverLan';
+import SerialOverLanConsole from '@/views/Control/SerialOverLan/SerialOverLanConsole';
+import ServerLed from '@/views/Control/ServerLed';
+import ServerPowerOperations from '@/views/Control/ServerPowerOperations';
+import SslCertificates from '@/views/AccessControl/SslCertificates';
+import VirtualMedia from '@/views/Control/VirtualMedia';
+import i18n from '@/i18n';
-const customRoutes = routes.map(route => {
- // Removes router definition that includes kvm
- // in name property (main and console layouts)
+// Custom components
+import FirmwareSingleImage from '../components/FirmwareSingleImage';
- // TODO: will revisit this, removing the definition
- // removes the route from the application but
- // the component is still included in the final build
- remove(route.children, ({ name }) => name.includes('kvm'));
- return route;
-});
+const routes = [
+ {
+ path: '/login',
+ component: LoginLayout,
+ children: [
+ {
+ path: '',
+ name: 'login',
+ component: Login,
+ meta: {
+ title: i18n.t('appPageTitle.login')
+ }
+ },
+ {
+ path: '/change-password',
+ name: 'change-password',
+ component: ChangePassword,
+ meta: {
+ title: i18n.t('appPageTitle.changePassword'),
+ requiresAuth: true
+ }
+ }
+ ]
+ },
+ {
+ path: '/console',
+ component: ConsoleLayout,
+ meta: {
+ requiresAuth: true
+ },
+ children: [
+ {
+ path: 'serial-over-lan-console',
+ name: 'serial-over-lan-console',
+ component: SerialOverLanConsole,
+ meta: {
+ title: i18n.t('appPageTitle.serialOverLan')
+ }
+ }
+ ]
+ },
+ {
+ path: '/',
+ meta: {
+ requiresAuth: true
+ },
+ component: AppLayout,
+ children: [
+ {
+ path: '',
+ name: 'overview',
+ component: Overview,
+ meta: {
+ title: i18n.t('appPageTitle.overview')
+ }
+ },
+ {
+ path: '/profile-settings',
+ name: 'profile-settings',
+ component: ProfileSettings,
+ meta: {
+ title: i18n.t('appPageTitle.profileSettings')
+ }
+ },
+ {
+ path: '/health/event-logs',
+ name: 'event-logs',
+ component: EventLogs,
+ meta: {
+ title: i18n.t('appPageTitle.eventLogs')
+ }
+ },
+ {
+ path: '/health/hardware-status',
+ name: 'hardware-status',
+ component: HardwareStatus,
+ meta: {
+ title: i18n.t('appPageTitle.hardwareStatus')
+ }
+ },
+ {
+ path: '/health/sensors',
+ name: 'sensors',
+ component: Sensors,
+ meta: {
+ title: i18n.t('appPageTitle.sensors')
+ }
+ },
+ {
+ path: '/access-control/ldap',
+ name: 'ldap',
+ component: Ldap,
+ meta: {
+ title: i18n.t('appPageTitle.ldap')
+ }
+ },
+ {
+ path: '/access-control/local-user-management',
+ name: 'local-users',
+ component: LocalUserManagement,
+ meta: {
+ title: i18n.t('appPageTitle.localUserManagement')
+ }
+ },
+ {
+ path: '/access-control/ssl-certificates',
+ name: 'ssl-certificates',
+ component: SslCertificates,
+ meta: {
+ title: i18n.t('appPageTitle.sslCertificates')
+ }
+ },
+ {
+ path: '/configuration/date-time-settings',
+ name: 'date-time-settings',
+ component: DateTimeSettings,
+ meta: {
+ title: i18n.t('appPageTitle.dateTimeSettings')
+ }
+ },
+ {
+ path: '/configuration/firmware',
+ name: 'firmware',
+ component: FirmwareSingleImage,
+ meta: {
+ title: i18n.t('appPageTitle.firmware')
+ }
+ },
+ {
+ path: '/control/manage-power-usage',
+ name: 'manage-power-usage',
+ component: ManagePowerUsage,
+ meta: {
+ title: i18n.t('appPageTitle.managePowerUsage')
+ }
+ },
+ {
+ path: '/configuration/network-settings',
+ name: 'network-settings',
+ component: NetworkSettings,
+ meta: {
+ title: i18n.t('appPageTitle.networkSettings')
+ }
+ },
+ {
+ path: '/control/reboot-bmc',
+ name: 'reboot-bmc',
+ component: RebootBmc,
+ meta: {
+ title: i18n.t('appPageTitle.rebootBmc')
+ }
+ },
+ {
+ path: '/control/server-led',
+ name: 'server-led',
+ component: ServerLed,
+ meta: {
+ title: i18n.t('appPageTitle.serverLed')
+ }
+ },
+ {
+ path: '/control/serial-over-lan',
+ name: 'serial-over-lan',
+ component: SerialOverLan,
+ meta: {
+ title: i18n.t('appPageTitle.serialOverLan')
+ }
+ },
+ {
+ path: '/control/server-power-operations',
+ name: 'server-power-operations',
+ component: ServerPowerOperations,
+ meta: {
+ title: i18n.t('appPageTitle.serverPowerOperations')
+ }
+ },
+ {
+ path: '/control/virtual-media',
+ name: 'virtual-media',
+ component: VirtualMedia,
+ meta: {
+ title: i18n.t('appPageTitle.virtualMedia')
+ }
+ },
+ {
+ path: '*',
+ name: 'page-not-found',
+ component: PageNotFound,
+ meta: {
+ title: i18n.t('appPageTitle.pageNotFound')
+ }
+ }
+ ]
+ }
+];
-export default customRoutes;
+export default routes;
diff --git a/src/env/store/FirmwareSingleImage/FirmwareSingleImageStore.js b/src/env/store/FirmwareSingleImage/FirmwareSingleImageStore.js
new file mode 100644
index 00000000..d00c5f71
--- /dev/null
+++ b/src/env/store/FirmwareSingleImage/FirmwareSingleImageStore.js
@@ -0,0 +1,161 @@
+import api from '@/store/api';
+import i18n from '@/i18n';
+
+const FirmwareSingleImageStore = {
+ namespaced: true,
+ state: {
+ activeFirmware: {
+ version: '--',
+ id: null,
+ location: null
+ },
+ backupFirmware: {
+ version: '--',
+ id: null,
+ location: null,
+ status: '--'
+ },
+ applyTime: null
+ },
+ getters: {
+ systemFirmwareVersion: state => state.activeFirmware.version,
+ backupFirmwareVersion: state => state.backupFirmware.version,
+ backupFirmwareStatus: state => state.backupFirmware.status,
+ isRebootFromBackupAvailable: state =>
+ state.backupFirmware.id ? true : false
+ },
+ mutations: {
+ setActiveFirmware: (state, { version, id, location }) => {
+ state.activeFirmware.version = version;
+ state.activeFirmware.id = id;
+ state.activeFirmware.location = location;
+ },
+ setBackupFirmware: (state, { version, id, location, status }) => {
+ state.backupFirmware.version = version;
+ state.backupFirmware.id = id;
+ state.backupFirmware.location = location;
+ state.backupFirmware.status = status;
+ },
+ setApplyTime: (state, applyTime) => (state.applyTime = applyTime)
+ },
+ actions: {
+ async getSystemFirwareVersion({ commit }) {
+ return await api
+ .get('/redfish/v1/Managers/bmc')
+ .then(({ data: { Links } }) => {
+ const currentLocation = Links.ActiveSoftwareImage['@odata.id'];
+ // Check SoftwareImages list for not ActiveSoftwareImage id
+ const backupLocation = Links.SoftwareImages.map(
+ item => item['@odata.id']
+ ).find(location => {
+ const id = location.split('/').pop();
+ const currentId = currentLocation.split('/').pop();
+ return id !== currentId;
+ });
+ return { currentLocation, backupLocation };
+ })
+ .then(async ({ currentLocation, backupLocation }) => {
+ const currentData = await api.get(currentLocation);
+ let backupData = {};
+
+ if (backupLocation) {
+ backupData = await api.get(backupLocation);
+ }
+
+ commit('setActiveFirmware', {
+ version: currentData?.data?.Version,
+ id: currentData?.data?.Id,
+ location: currentData?.data?.['@odata.id']
+ });
+ commit('setBackupFirmware', {
+ version: backupData.data?.Version,
+ id: backupData.data?.Id,
+ location: backupData.data?.['@odata.id'],
+ status: backupData.data?.Status?.State
+ });
+ })
+ .catch(error => console.log(error));
+ },
+ getUpdateServiceApplyTime({ commit }) {
+ api
+ .get('/redfish/v1/UpdateService')
+ .then(({ data }) => {
+ const applyTime =
+ data.HttpPushUriOptions.HttpPushUriApplyTime.ApplyTime;
+ commit('setApplyTime', applyTime);
+ })
+ .catch(error => console.log(error));
+ },
+ setApplyTimeImmediate({ commit }) {
+ const data = {
+ HttpPushUriOptions: {
+ HttpPushUriApplyTime: {
+ ApplyTime: 'Immediate'
+ }
+ }
+ };
+ return api
+ .patch('/redfish/v1/UpdateService', data)
+ .then(() => commit('setApplyTime', 'Immediate'))
+ .catch(error => console.log(error));
+ },
+ async uploadFirmware({ state, dispatch }, image) {
+ if (state.applyTime !== 'Immediate') {
+ // ApplyTime must be set to Immediate before making
+ // request to update firmware
+ await dispatch('setApplyTimeImmediate');
+ }
+ return await api
+ .post('/redfish/v1/UpdateService', image, {
+ headers: { 'Content-Type': 'application/octet-stream' }
+ })
+ .then(() => dispatch('getSystemFirwareVersion'))
+ .then(() => i18n.t('pageFirmware.toast.successUploadMessage'))
+ .catch(error => {
+ console.log(error);
+ throw new Error(i18n.t('pageFirmware.toast.errorUploadAndReboot'));
+ });
+ },
+ async uploadFirmwareTFTP({ state, dispatch }, { address, filename }) {
+ const data = {
+ TransferProtocol: 'TFTP',
+ ImageURI: `${address}/${filename}`
+ };
+ if (state.applyTime !== 'Immediate') {
+ // ApplyTime must be set to Immediate before making
+ // request to update firmware
+ await dispatch('setApplyTimeImmediate');
+ }
+ return await api
+ .post(
+ '/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate',
+ data
+ )
+ .then(() => dispatch('getSystemFirwareVersion'))
+ .then(() => i18n.t('pageFirmware.toast.successUploadMessage'))
+ .catch(error => {
+ console.log(error);
+ throw new Error(i18n.t('pageFirmware.toast.errorUploadAndReboot'));
+ });
+ },
+ async switchFirmwareAndReboot({ state }) {
+ const backupLoaction = state.backupFirmware.location;
+ const data = {
+ Links: {
+ ActiveSoftwareImage: {
+ '@odata.id': backupLoaction
+ }
+ }
+ };
+ return await api
+ .patch('/redfish/v1/Managers/bmc', data)
+ .then(() => i18n.t('pageFirmware.toast.successRebootFromBackup'))
+ .catch(error => {
+ console.log(error);
+ throw new Error(i18n.t('pageFirmware.toast.errorRebootFromBackup'));
+ });
+ }
+ }
+};
+
+export default FirmwareSingleImageStore;
diff --git a/src/env/store/ibm.js b/src/env/store/ibm.js
index 70c9b98a..12fd0865 100644
--- a/src/env/store/ibm.js
+++ b/src/env/store/ibm.js
@@ -1,7 +1,7 @@
import store from '@/store';
+import FirmwareSingleImageStore from './FirmwareSingleImage/FirmwareSingleImageStore';
-// Use store.registerModule() to register env specific
-// store modules
-// https://vuex.vuejs.org/api/#registermodule
+store.unregisterModule('firmware');
+store.registerModule('firmwareSingleImage', FirmwareSingleImageStore);
export default store;