blob: 517e5fa1aaac7ec4e61374e649e4fc72a0b71333 [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 />
4 <b-row>
5 <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 Muranaka6f712842021-02-04 11:23:03 -0800104 :label="$t('pageFirmware.singleFileUpload.fileSource')"
105 :disabled="isPageDisabled"
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700106 >
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800107 <b-form-radio v-model="isWorkstationSelected" :value="true">
108 {{ $t('pageFirmware.form.workstation') }}
109 </b-form-radio>
110 <b-form-radio v-model="isWorkstationSelected" :value="false">
111 {{ $t('pageFirmware.form.tftpServer') }}
112 </b-form-radio>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700113 </b-form-group>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700114
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800115 <!-- Workstation Upload -->
116 <template v-if="isWorkstationSelected">
117 <b-form-group
118 :label="$t('pageFirmware.form.imageFile')"
119 label-for="image-file"
120 >
121 <b-form-text id="image-file-help-block">
122 {{ $t('pageFirmware.form.onlyTarFilesAccepted') }}
123 </b-form-text>
124 <form-file
125 id="image-file"
126 accept=".tar"
127 :disabled="isPageDisabled"
128 :state="getValidationState($v.file)"
129 aria-describedby="image-file-help-block"
130 @input="onFileUpload($event)"
131 >
132 <template #invalid>
133 <b-form-invalid-feedback role="alert">
134 {{ $t('global.form.required') }}
135 </b-form-invalid-feedback>
136 </template>
137 </form-file>
138 </b-form-group>
139 </template>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700140
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800141 <!-- TFTP Server Upload -->
142 <template v-else>
143 <b-form-group
144 :label="$t('pageFirmware.singleFileUpload.fileAddress')"
145 label-for="tftp-address"
146 >
147 <b-form-input
148 id="tftp-address"
149 v-model="tftpFileAddress"
150 type="text"
151 :state="getValidationState($v.tftpFileAddress)"
152 :disabled="isPageDisabled"
153 @input="$v.tftpFileAddress.$touch()"
154 />
155 <b-form-invalid-feedback role="alert">
156 {{ $t('global.form.fieldRequired') }}
157 </b-form-invalid-feedback>
158 </b-form-group>
159 </template>
160 <b-btn
161 data-test-id="firmware-button-startUpdate"
162 type="submit"
163 variant="primary"
164 :disabled="isPageDisabled"
165 >
166 {{ $t('pageFirmware.singleFileUpload.startUpdate') }}
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700167 </b-btn>
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800168 <alert
169 v-if="!isHostOff"
170 variant="warning"
171 :small="true"
172 class="mt-4"
173 >
174 <p class="col-form-label">
175 {{
176 $t(
177 'pageFirmware.singleFileUpload.alert.serverMustBePoweredOffToUpdateFirmware'
178 )
179 }}
180 </p>
181 </alert>
182 </b-form>
183 </div>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700184 </page-section>
185 </b-col>
186 </b-row>
187
188 <!-- Modals -->
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800189 <modal-update-firmware
190 :running="systemFirmwareVersion"
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700191 :backup="backupFirmwareVersion"
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800192 @ok="updateFirmware"
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700193 />
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800194 <modal-switch-to-running
195 :backup="backupFirmwareVersion"
196 @ok="switchToRunning"
197 />
198
199 <!-- Toasts -->
200 <b-toast id="switch-images" variant="info" solid :no-auto-hide="true">
201 <template #toast-title>
202 <status-icon status="info" class="toast-icon" />
203 <strong>{{
204 $t('pageFirmware.singleFileUpload.toast.rebootStarted')
205 }}</strong>
206 </template>
207 <p class="m-0">
208 {{ $t('pageFirmware.singleFileUpload.toast.rebootStartedMessage') }}
209 </p>
210 </b-toast>
211
212 <b-toast id="switch-images-2" variant="info" solid :no-auto-hide="true">
213 <template #toast-title>
214 <status-icon status="info" class="toast-icon" />
215 <strong>{{
216 $t('pageFirmware.singleFileUpload.toast.verifySwitch')
217 }}</strong>
218 </template>
219 <p>
220 {{ $t('pageFirmware.singleFileUpload.toast.verifySwitchMessage') }}
221 </p>
222 <b-link @click="onClickRefresh">{{ $t('global.action.refresh') }}</b-link>
223 </b-toast>
224
225 <b-toast id="update-firmware" variant="info" solid :no-auto-hide="true">
226 <template #toast-title>
227 <status-icon status="info" class="toast-icon" />
228 <strong>{{
229 $t('pageFirmware.singleFileUpload.toast.updateStarted')
230 }}</strong>
231 </template>
232 <p>
233 {{ $t('pageFirmware.singleFileUpload.toast.updateStartedMessage') }}
234 </p>
235 <p class="m-0">
236 {{ $t('pageFirmware.singleFileUpload.toast.startTime') }}
237 {{ $options.filters.formatTime(new Date()) }}
238 </p>
239 </b-toast>
240
241 <b-toast id="update-firmware-2" variant="info" solid :no-auto-hide="true">
242 <template #toast-title>
243 <status-icon status="info" class="toast-icon" />
244 <strong>{{
245 $t('pageFirmware.singleFileUpload.toast.verifyUpdate')
246 }}</strong>
247 </template>
248 <p>
249 {{ $t('pageFirmware.singleFileUpload.toast.verifyUpdateMessage') }}
250 </p>
251 <b-link @click="onClickRefresh">{{ $t('global.action.refresh') }}</b-link>
252 </b-toast>
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700253 </b-container>
254</template>
255
256<script>
257import { requiredIf } from 'vuelidate/lib/validators';
258import { mapGetters } from 'vuex';
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800259import IconSwitch from '@carbon/icons-vue/es/arrows--horizontal/20';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700260
261import PageSection from '@/components/Global/PageSection';
262import PageTitle from '@/components/Global/PageTitle';
263import Alert from '@/components/Global/Alert';
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800264import FormFile from '@/components/Global/FormFile';
265import StatusIcon from '@/components/Global/StatusIcon';
266import ModalUpdateFirmware from './FirmwareSingleImageModalUpdateFirmware';
267import ModalSwitchToRunning from './FirmwareSingleImageModalSwitchToRunning';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700268
269import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
Yoshie Muranakad73f4962020-12-09 08:52:23 -0800270import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700271import BVToastMixin from '@/components/Mixins/BVToastMixin';
272
273export default {
274 name: 'FirmwareSingleImage',
275 components: {
276 Alert,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800277 FormFile,
278 IconSwitch,
279 ModalSwitchToRunning,
280 ModalUpdateFirmware,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700281 PageSection,
Derick Montague602e98a2020-10-21 16:20:00 -0500282 PageTitle,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800283 StatusIcon,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700284 },
285 mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin],
Derick Montagueefbd4012020-11-03 14:10:45 -0600286 beforeRouteLeave(to, from, next) {
287 this.hideLoader();
288 this.clearRebootTimeout();
289 next();
290 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700291 data() {
292 return {
293 isWorkstationSelected: true,
294 file: null,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800295 tftpFileAddress: null,
Derick Montague602e98a2020-10-21 16:20:00 -0500296 timeoutId: null,
Yoshie Muranakad73f4962020-12-09 08:52:23 -0800297 loading,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700298 };
299 },
300 computed: {
301 hostStatus() {
302 return this.$store.getters['global/hostStatus'];
303 },
304 isHostOff() {
305 return this.hostStatus === 'off' ? true : false;
306 },
307 isOperationInProgress() {
308 return this.$store.getters['controls/isOperationInProgress'];
309 },
310 ...mapGetters('firmwareSingleImage', [
311 'backupFirmwareStatus',
312 'backupFirmwareVersion',
313 'isRebootFromBackupAvailable',
Derick Montague602e98a2020-10-21 16:20:00 -0500314 'systemFirmwareVersion',
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700315 ]),
316 isPageDisabled() {
317 return !this.isHostOff || this.loading || this.isOperationInProgress;
Derick Montague602e98a2020-10-21 16:20:00 -0500318 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800319 showBackupImageStatus() {
320 return (
321 this.backupFirmwareStatus === 'Critical' ||
322 this.backupFirmwareStatus === 'Warning'
323 );
324 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700325 },
326 watch: {
Derick Montague602e98a2020-10-21 16:20:00 -0500327 isWorkstationSelected: function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700328 this.$v.$reset();
329 this.file = null;
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800330 this.tftpFileAddress = null;
Derick Montague602e98a2020-10-21 16:20:00 -0500331 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700332 },
333 created() {
334 this.startLoader();
335 this.$store.dispatch('firmwareSingleImage/getUpdateServiceApplyTime');
336 Promise.all([
337 this.$store.dispatch('global/getHostStatus'),
Derick Montague602e98a2020-10-21 16:20:00 -0500338 this.$store.dispatch('firmwareSingleImage/getFirmwareInformation'),
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700339 ]).finally(() => this.endLoader());
340 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700341 validations() {
342 return {
343 file: {
Derick Montague602e98a2020-10-21 16:20:00 -0500344 required: requiredIf(function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700345 return this.isWorkstationSelected;
Derick Montague602e98a2020-10-21 16:20:00 -0500346 }),
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700347 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800348 tftpFileAddress: {
Derick Montague602e98a2020-10-21 16:20:00 -0500349 required: requiredIf(function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700350 return !this.isWorkstationSelected;
Derick Montague602e98a2020-10-21 16:20:00 -0500351 }),
352 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700353 };
354 },
355 methods: {
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800356 updateFirmware() {
357 this.setRebootTimeout(360000, 'update-firmware-2'); //6 minute timeout
358 this.$bvToast.show('update-firmware');
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700359 if (this.isWorkstationSelected) {
360 this.dispatchWorkstationUpload();
361 } else {
362 this.dispatchTftpUpload();
363 }
364 },
365 dispatchWorkstationUpload() {
366 this.$store
367 .dispatch('firmwareSingleImage/uploadFirmware', this.file)
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700368 .catch(({ message }) => {
369 this.errorToast(message);
370 this.clearRebootTimeout();
371 });
372 },
373 dispatchTftpUpload() {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700374 this.$store
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800375 .dispatch(
376 'firmwareSingleImage/uploadFirmwareTFTP',
377 this.tftpFileAddress
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700378 )
379 .catch(({ message }) => {
380 this.errorToast(message);
381 this.clearRebootTimeout();
382 });
383 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800384 switchToRunning() {
385 this.setRebootTimeout(60000, 'switch-images-2');
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700386 this.$store
387 .dispatch('firmwareSingleImage/switchFirmwareAndReboot')
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800388 .then(() => this.$bvToast.show('switch-images'))
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700389 .catch(({ message }) => {
390 this.errorToast(message);
391 this.clearRebootTimeout();
392 });
393 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800394 setRebootTimeout(timeoutMs = 60000, toastId) {
395 // Set a timeout to disable page interactions
396 // during a BMC reboot
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700397 this.startLoader();
398 this.timeoutId = setTimeout(() => {
399 this.endLoader();
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800400 if (toastId) {
401 this.$bvToast.show(toastId);
402 }
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700403 }, timeoutMs);
404 },
405 clearRebootTimeout() {
406 if (this.timeoutId) {
407 clearTimeout(this.timeoutId);
408 this.endLoader();
409 }
410 },
411 onSubmitUpload() {
412 this.$v.$touch();
413 if (this.$v.$invalid) return;
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800414 this.$bvModal.show('modal-update-firmware');
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700415 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800416 onFileUpload(file) {
417 this.file = file;
418 this.$v.file.$touch();
419 },
420 onClickRefresh() {
421 this.$root.$emit('refresh-application');
Derick Montague602e98a2020-10-21 16:20:00 -0500422 },
423 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700424};
425</script>