blob: b7ad4c535dfe7bc84e1a326c4e72f3db0e0b5e1b [file] [log] [blame]
Yoshie Muranaka0b980db2020-10-06 09:24:14 -07001<template>
2 <b-container fluid="xl">
Yoshie Muranaka6f712842021-02-04 11:23:03 -08003 <page-title />
Yoshie Muranakafc387aa2021-02-11 08:27:36 -08004 <b-row v-if="isServerPowerOffRequired">
Yoshie Muranaka6f712842021-02-04 11:23:03 -08005 <b-col xl="10">
6 <!-- Operation in progress alert -->
7 <alert v-if="isOperationInProgress" variant="info" class="mb-5">
8 <p>
9 {{ $t('pageFirmware.singleFileUpload.alert.operationInProgress') }}
10 </p>
11 </alert>
12 <!-- Power off server warning alert -->
13 <alert v-else-if="!isHostOff" variant="warning" class="mb-5">
14 <p class="mb-0">
15 {{
16 $t('pageFirmware.singleFileUpload.alert.serverMustBePoweredOffTo')
17 }}
18 </p>
19 <ul class="m-0">
20 <li>
21 {{
22 $t(
23 'pageFirmware.singleFileUpload.alert.switchRunningAndBackupImages'
24 )
25 }}
26 </li>
27 <li>
28 {{ $t('pageFirmware.singleFileUpload.alert.updateFirmware') }}
29 </li>
30 </ul>
31 <template #action>
32 <b-link to="/control/server-power-operations">
33 {{
34 $t(
35 'pageFirmware.singleFileUpload.alert.viewServerPowerOperations'
36 )
37 }}
38 </b-link>
39 </template>
40 </alert>
41 </b-col>
42 </b-row>
43 <b-row>
44 <b-col xl="10">
45 <page-section>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -070046 <b-card-group deck>
Yoshie Muranaka6f712842021-02-04 11:23:03 -080047 <!-- Running image -->
Yoshie Muranaka0b980db2020-10-06 09:24:14 -070048 <b-card>
Derick Montague602e98a2020-10-21 16:20:00 -050049 <template #header>
Yoshie Muranaka6f712842021-02-04 11:23:03 -080050 <p class="font-weight-bold m-0">
51 {{ $t('pageFirmware.singleFileUpload.runningImage') }}
52 </p>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -070053 </template>
Yoshie Muranaka6f712842021-02-04 11:23:03 -080054 <dl class="mb-0">
55 <dt>{{ $t('pageFirmware.singleFileUpload.bmcAndServer') }}</dt>
56 <dd class="mb-0">{{ systemFirmwareVersion }}</dd>
57 </dl>
58 </b-card>
59
60 <!-- Backup image -->
61 <b-card>
62 <template #header>
63 <p class="font-weight-bold m-0">
64 {{ $t('pageFirmware.singleFileUpload.backupImage') }}
65 </p>
66 </template>
67 <dl>
68 <dt>
69 {{ $t('pageFirmware.singleFileUpload.bmcAndServer') }}
70 </dt>
71 <dd>
72 <status-icon v-if="showBackupImageStatus" status="danger" />
73 <span v-if="showBackupImageStatus" class="sr-only">
74 {{ backupFirmwareStatus }}
75 </span>
76 {{ backupFirmwareVersion }}
77 </dd>
78 </dl>
79 <b-btn
80 v-b-modal.modal-switch-to-running
81 data-test-id="firmware-button-switchToRunning"
82 variant="link"
83 size="sm"
84 class="py-0 px-1 mt-2"
85 :disabled="isPageDisabled || !isRebootFromBackupAvailable"
86 >
87 <icon-switch class="d-none d-sm-inline-block" />
88 {{ $t('pageFirmware.singleFileUpload.switchToRunning') }}
89 </b-btn>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -070090 </b-card>
91 </b-card-group>
92 </page-section>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -070093 </b-col>
Yoshie Muranaka6f712842021-02-04 11:23:03 -080094 </b-row>
95 <b-row>
96 <!-- Update firmware -->
97 <b-col sm="8" md="6" xl="4">
98 <page-section
99 :section-title="$t('pageFirmware.singleFileUpload.updateFirmware')"
100 >
101 <div class="form-background p-3">
102 <b-form @submit.prevent="onSubmitUpload">
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700103 <b-form-group
Yoshie Muranaka7cc1fd42021-02-11 09:23:14 -0800104 v-if="isTftpUploadAvailable"
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800105 :label="$t('pageFirmware.singleFileUpload.fileSource')"
106 :disabled="isPageDisabled"
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700107 >
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800108 <b-form-radio v-model="isWorkstationSelected" :value="true">
109 {{ $t('pageFirmware.form.workstation') }}
110 </b-form-radio>
111 <b-form-radio v-model="isWorkstationSelected" :value="false">
112 {{ $t('pageFirmware.form.tftpServer') }}
113 </b-form-radio>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700114 </b-form-group>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700115
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800116 <!-- Workstation Upload -->
117 <template v-if="isWorkstationSelected">
118 <b-form-group
119 :label="$t('pageFirmware.form.imageFile')"
120 label-for="image-file"
121 >
122 <b-form-text id="image-file-help-block">
123 {{ $t('pageFirmware.form.onlyTarFilesAccepted') }}
124 </b-form-text>
125 <form-file
126 id="image-file"
127 accept=".tar"
128 :disabled="isPageDisabled"
129 :state="getValidationState($v.file)"
130 aria-describedby="image-file-help-block"
131 @input="onFileUpload($event)"
132 >
133 <template #invalid>
134 <b-form-invalid-feedback role="alert">
135 {{ $t('global.form.required') }}
136 </b-form-invalid-feedback>
137 </template>
138 </form-file>
139 </b-form-group>
140 </template>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700141
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800142 <!-- TFTP Server Upload -->
143 <template v-else>
144 <b-form-group
145 :label="$t('pageFirmware.singleFileUpload.fileAddress')"
146 label-for="tftp-address"
147 >
148 <b-form-input
149 id="tftp-address"
150 v-model="tftpFileAddress"
151 type="text"
152 :state="getValidationState($v.tftpFileAddress)"
153 :disabled="isPageDisabled"
154 @input="$v.tftpFileAddress.$touch()"
155 />
156 <b-form-invalid-feedback role="alert">
157 {{ $t('global.form.fieldRequired') }}
158 </b-form-invalid-feedback>
159 </b-form-group>
160 </template>
161 <b-btn
162 data-test-id="firmware-button-startUpdate"
163 type="submit"
164 variant="primary"
165 :disabled="isPageDisabled"
166 >
167 {{ $t('pageFirmware.singleFileUpload.startUpdate') }}
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700168 </b-btn>
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800169 <alert
Yoshie Muranakafc387aa2021-02-11 08:27:36 -0800170 v-if="isServerPowerOffRequired && !isHostOff"
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800171 variant="warning"
172 :small="true"
173 class="mt-4"
174 >
175 <p class="col-form-label">
176 {{
177 $t(
178 'pageFirmware.singleFileUpload.alert.serverMustBePoweredOffToUpdateFirmware'
179 )
180 }}
181 </p>
182 </alert>
183 </b-form>
184 </div>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700185 </page-section>
186 </b-col>
187 </b-row>
188
189 <!-- Modals -->
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800190 <modal-update-firmware
191 :running="systemFirmwareVersion"
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700192 :backup="backupFirmwareVersion"
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800193 @ok="updateFirmware"
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700194 />
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800195 <modal-switch-to-running
196 :backup="backupFirmwareVersion"
197 @ok="switchToRunning"
198 />
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700199 </b-container>
200</template>
201
202<script>
203import { requiredIf } from 'vuelidate/lib/validators';
204import { mapGetters } from 'vuex';
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800205import IconSwitch from '@carbon/icons-vue/es/arrows--horizontal/20';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700206
207import PageSection from '@/components/Global/PageSection';
208import PageTitle from '@/components/Global/PageTitle';
209import Alert from '@/components/Global/Alert';
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800210import FormFile from '@/components/Global/FormFile';
211import StatusIcon from '@/components/Global/StatusIcon';
212import ModalUpdateFirmware from './FirmwareSingleImageModalUpdateFirmware';
213import ModalSwitchToRunning from './FirmwareSingleImageModalSwitchToRunning';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700214
215import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
Yoshie Muranakad73f4962020-12-09 08:52:23 -0800216import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700217import BVToastMixin from '@/components/Mixins/BVToastMixin';
218
219export default {
220 name: 'FirmwareSingleImage',
221 components: {
222 Alert,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800223 FormFile,
224 IconSwitch,
225 ModalSwitchToRunning,
226 ModalUpdateFirmware,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700227 PageSection,
Derick Montague602e98a2020-10-21 16:20:00 -0500228 PageTitle,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800229 StatusIcon,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700230 },
231 mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin],
Derick Montagueefbd4012020-11-03 14:10:45 -0600232 beforeRouteLeave(to, from, next) {
233 this.hideLoader();
Derick Montagueefbd4012020-11-03 14:10:45 -0600234 next();
235 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700236 data() {
237 return {
238 isWorkstationSelected: true,
239 file: null,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800240 tftpFileAddress: null,
Derick Montague602e98a2020-10-21 16:20:00 -0500241 timeoutId: null,
Yoshie Muranakad73f4962020-12-09 08:52:23 -0800242 loading,
Yoshie Muranakafc387aa2021-02-11 08:27:36 -0800243 isServerPowerOffRequired:
244 process.env.VUE_APP_SERVER_OFF_REQUIRED === 'true',
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700245 };
246 },
247 computed: {
248 hostStatus() {
249 return this.$store.getters['global/hostStatus'];
250 },
251 isHostOff() {
252 return this.hostStatus === 'off' ? true : false;
253 },
254 isOperationInProgress() {
255 return this.$store.getters['controls/isOperationInProgress'];
256 },
257 ...mapGetters('firmwareSingleImage', [
258 'backupFirmwareStatus',
259 'backupFirmwareVersion',
260 'isRebootFromBackupAvailable',
Derick Montague602e98a2020-10-21 16:20:00 -0500261 'systemFirmwareVersion',
Yoshie Muranaka7cc1fd42021-02-11 09:23:14 -0800262 'isTftpUploadAvailable',
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700263 ]),
264 isPageDisabled() {
Yoshie Muranakafc387aa2021-02-11 08:27:36 -0800265 if (this.isServerPowerOffRequired) {
266 return !this.isHostOff || this.loading || this.isOperationInProgress;
267 }
268 return this.loading || this.isOperationInProgress;
Derick Montague602e98a2020-10-21 16:20:00 -0500269 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800270 showBackupImageStatus() {
271 return (
272 this.backupFirmwareStatus === 'Critical' ||
273 this.backupFirmwareStatus === 'Warning'
274 );
275 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700276 },
277 watch: {
Derick Montague602e98a2020-10-21 16:20:00 -0500278 isWorkstationSelected: function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700279 this.$v.$reset();
280 this.file = null;
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800281 this.tftpFileAddress = null;
Derick Montague602e98a2020-10-21 16:20:00 -0500282 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700283 },
284 created() {
285 this.startLoader();
Yoshie Muranaka7cc1fd42021-02-11 09:23:14 -0800286 this.$store.dispatch('firmwareSingleImage/getUpdateServiceSettings');
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700287 Promise.all([
288 this.$store.dispatch('global/getHostStatus'),
Derick Montague602e98a2020-10-21 16:20:00 -0500289 this.$store.dispatch('firmwareSingleImage/getFirmwareInformation'),
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700290 ]).finally(() => this.endLoader());
291 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700292 validations() {
293 return {
294 file: {
Derick Montague602e98a2020-10-21 16:20:00 -0500295 required: requiredIf(function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700296 return this.isWorkstationSelected;
Derick Montague602e98a2020-10-21 16:20:00 -0500297 }),
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700298 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800299 tftpFileAddress: {
Derick Montague602e98a2020-10-21 16:20:00 -0500300 required: requiredIf(function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700301 return !this.isWorkstationSelected;
Derick Montague602e98a2020-10-21 16:20:00 -0500302 }),
303 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700304 };
305 },
306 methods: {
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800307 updateFirmware() {
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800308 this.setRebootTimeout(360000, () => {
309 this.infoToast(
310 this.$t('pageFirmware.singleFileUpload.toast.verifyUpdateMessage'),
311 {
312 title: this.$t('pageFirmware.singleFileUpload.toast.verifyUpdate'),
313 refreshAction: true,
314 }
315 );
316 });
317 this.infoToast(
318 this.$t('pageFirmware.singleFileUpload.toast.updateStartedMessage'),
319 {
320 title: this.$t('pageFirmware.singleFileUpload.toast.updateStarted'),
321 timestamp: true,
322 }
323 );
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700324 if (this.isWorkstationSelected) {
325 this.dispatchWorkstationUpload();
326 } else {
327 this.dispatchTftpUpload();
328 }
329 },
330 dispatchWorkstationUpload() {
331 this.$store
332 .dispatch('firmwareSingleImage/uploadFirmware', this.file)
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700333 .catch(({ message }) => {
334 this.errorToast(message);
335 this.clearRebootTimeout();
336 });
337 },
338 dispatchTftpUpload() {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700339 this.$store
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800340 .dispatch(
341 'firmwareSingleImage/uploadFirmwareTFTP',
342 this.tftpFileAddress
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700343 )
344 .catch(({ message }) => {
345 this.errorToast(message);
346 this.clearRebootTimeout();
347 });
348 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800349 switchToRunning() {
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800350 this.setRebootTimeout(60000, () => {
351 this.infoToast(
352 this.$t('pageFirmware.singleFileUpload.toast.verifySwitchMessage'),
353 {
354 title: this.$t('pageFirmware.singleFileUpload.toast.verifySwitch'),
355 refreshAction: true,
356 }
357 );
358 });
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700359 this.$store
360 .dispatch('firmwareSingleImage/switchFirmwareAndReboot')
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800361 .then(() =>
362 this.infoToast(
363 this.$t('pageFirmware.singleFileUpload.toast.rebootStartedMessage'),
364 {
365 title: this.$t(
366 'pageFirmware.singleFileUpload.toast.rebootStarted'
367 ),
368 }
369 )
370 )
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700371 .catch(({ message }) => {
372 this.errorToast(message);
373 this.clearRebootTimeout();
374 });
375 },
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800376 setRebootTimeout(timeoutMs = 60000, callback) {
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800377 // Set a timeout to disable page interactions
378 // during a BMC reboot
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700379 this.startLoader();
380 this.timeoutId = setTimeout(() => {
381 this.endLoader();
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800382 if (callback) callback();
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700383 }, timeoutMs);
384 },
385 clearRebootTimeout() {
386 if (this.timeoutId) {
387 clearTimeout(this.timeoutId);
388 this.endLoader();
389 }
390 },
391 onSubmitUpload() {
392 this.$v.$touch();
393 if (this.$v.$invalid) return;
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800394 this.$bvModal.show('modal-update-firmware');
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700395 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800396 onFileUpload(file) {
397 this.file = file;
398 this.$v.file.$touch();
399 },
Derick Montague602e98a2020-10-21 16:20:00 -0500400 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700401};
402</script>