blob: 1089e7a5aa3242d984ecb5109cc3296336964918 [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 />
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700198 </b-container>
199</template>
200
201<script>
202import { requiredIf } from 'vuelidate/lib/validators';
203import { mapGetters } from 'vuex';
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800204import IconSwitch from '@carbon/icons-vue/es/arrows--horizontal/20';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700205
206import PageSection from '@/components/Global/PageSection';
207import PageTitle from '@/components/Global/PageTitle';
208import Alert from '@/components/Global/Alert';
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800209import FormFile from '@/components/Global/FormFile';
210import StatusIcon from '@/components/Global/StatusIcon';
211import ModalUpdateFirmware from './FirmwareSingleImageModalUpdateFirmware';
212import ModalSwitchToRunning from './FirmwareSingleImageModalSwitchToRunning';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700213
214import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
Yoshie Muranakad73f4962020-12-09 08:52:23 -0800215import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin';
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700216import BVToastMixin from '@/components/Mixins/BVToastMixin';
217
218export default {
219 name: 'FirmwareSingleImage',
220 components: {
221 Alert,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800222 FormFile,
223 IconSwitch,
224 ModalSwitchToRunning,
225 ModalUpdateFirmware,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700226 PageSection,
Derick Montague602e98a2020-10-21 16:20:00 -0500227 PageTitle,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800228 StatusIcon,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700229 },
230 mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin],
Derick Montagueefbd4012020-11-03 14:10:45 -0600231 beforeRouteLeave(to, from, next) {
232 this.hideLoader();
Derick Montagueefbd4012020-11-03 14:10:45 -0600233 next();
234 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700235 data() {
236 return {
237 isWorkstationSelected: true,
238 file: null,
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800239 tftpFileAddress: null,
Derick Montague602e98a2020-10-21 16:20:00 -0500240 timeoutId: null,
Yoshie Muranakad73f4962020-12-09 08:52:23 -0800241 loading,
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700242 };
243 },
244 computed: {
245 hostStatus() {
246 return this.$store.getters['global/hostStatus'];
247 },
248 isHostOff() {
249 return this.hostStatus === 'off' ? true : false;
250 },
251 isOperationInProgress() {
252 return this.$store.getters['controls/isOperationInProgress'];
253 },
254 ...mapGetters('firmwareSingleImage', [
255 'backupFirmwareStatus',
256 'backupFirmwareVersion',
257 'isRebootFromBackupAvailable',
Derick Montague602e98a2020-10-21 16:20:00 -0500258 'systemFirmwareVersion',
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700259 ]),
260 isPageDisabled() {
261 return !this.isHostOff || this.loading || this.isOperationInProgress;
Derick Montague602e98a2020-10-21 16:20:00 -0500262 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800263 showBackupImageStatus() {
264 return (
265 this.backupFirmwareStatus === 'Critical' ||
266 this.backupFirmwareStatus === 'Warning'
267 );
268 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700269 },
270 watch: {
Derick Montague602e98a2020-10-21 16:20:00 -0500271 isWorkstationSelected: function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700272 this.$v.$reset();
273 this.file = null;
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800274 this.tftpFileAddress = null;
Derick Montague602e98a2020-10-21 16:20:00 -0500275 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700276 },
277 created() {
278 this.startLoader();
279 this.$store.dispatch('firmwareSingleImage/getUpdateServiceApplyTime');
280 Promise.all([
281 this.$store.dispatch('global/getHostStatus'),
Derick Montague602e98a2020-10-21 16:20:00 -0500282 this.$store.dispatch('firmwareSingleImage/getFirmwareInformation'),
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700283 ]).finally(() => this.endLoader());
284 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700285 validations() {
286 return {
287 file: {
Derick Montague602e98a2020-10-21 16:20:00 -0500288 required: requiredIf(function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700289 return this.isWorkstationSelected;
Derick Montague602e98a2020-10-21 16:20:00 -0500290 }),
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700291 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800292 tftpFileAddress: {
Derick Montague602e98a2020-10-21 16:20:00 -0500293 required: requiredIf(function () {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700294 return !this.isWorkstationSelected;
Derick Montague602e98a2020-10-21 16:20:00 -0500295 }),
296 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700297 };
298 },
299 methods: {
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800300 updateFirmware() {
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800301 this.setRebootTimeout(360000, () => {
302 this.infoToast(
303 this.$t('pageFirmware.singleFileUpload.toast.verifyUpdateMessage'),
304 {
305 title: this.$t('pageFirmware.singleFileUpload.toast.verifyUpdate'),
306 refreshAction: true,
307 }
308 );
309 });
310 this.infoToast(
311 this.$t('pageFirmware.singleFileUpload.toast.updateStartedMessage'),
312 {
313 title: this.$t('pageFirmware.singleFileUpload.toast.updateStarted'),
314 timestamp: true,
315 }
316 );
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700317 if (this.isWorkstationSelected) {
318 this.dispatchWorkstationUpload();
319 } else {
320 this.dispatchTftpUpload();
321 }
322 },
323 dispatchWorkstationUpload() {
324 this.$store
325 .dispatch('firmwareSingleImage/uploadFirmware', this.file)
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700326 .catch(({ message }) => {
327 this.errorToast(message);
328 this.clearRebootTimeout();
329 });
330 },
331 dispatchTftpUpload() {
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700332 this.$store
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800333 .dispatch(
334 'firmwareSingleImage/uploadFirmwareTFTP',
335 this.tftpFileAddress
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700336 )
337 .catch(({ message }) => {
338 this.errorToast(message);
339 this.clearRebootTimeout();
340 });
341 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800342 switchToRunning() {
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800343 this.setRebootTimeout(60000, () => {
344 this.infoToast(
345 this.$t('pageFirmware.singleFileUpload.toast.verifySwitchMessage'),
346 {
347 title: this.$t('pageFirmware.singleFileUpload.toast.verifySwitch'),
348 refreshAction: true,
349 }
350 );
351 });
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700352 this.$store
353 .dispatch('firmwareSingleImage/switchFirmwareAndReboot')
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800354 .then(() =>
355 this.infoToast(
356 this.$t('pageFirmware.singleFileUpload.toast.rebootStartedMessage'),
357 {
358 title: this.$t(
359 'pageFirmware.singleFileUpload.toast.rebootStarted'
360 ),
361 }
362 )
363 )
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700364 .catch(({ message }) => {
365 this.errorToast(message);
366 this.clearRebootTimeout();
367 });
368 },
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800369 setRebootTimeout(timeoutMs = 60000, callback) {
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800370 // Set a timeout to disable page interactions
371 // during a BMC reboot
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700372 this.startLoader();
373 this.timeoutId = setTimeout(() => {
374 this.endLoader();
Yoshie Muranakaf92e2962021-02-09 12:41:53 -0800375 if (callback) callback();
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700376 }, timeoutMs);
377 },
378 clearRebootTimeout() {
379 if (this.timeoutId) {
380 clearTimeout(this.timeoutId);
381 this.endLoader();
382 }
383 },
384 onSubmitUpload() {
385 this.$v.$touch();
386 if (this.$v.$invalid) return;
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800387 this.$bvModal.show('modal-update-firmware');
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700388 },
Yoshie Muranaka6f712842021-02-04 11:23:03 -0800389 onFileUpload(file) {
390 this.file = file;
391 this.$v.file.$touch();
392 },
Derick Montague602e98a2020-10-21 16:20:00 -0500393 },
Yoshie Muranaka0b980db2020-10-06 09:24:14 -0700394};
395</script>