diff options
author | Yoshie Muranaka <yoshiemuranaka@gmail.com> | 2020-12-08 00:04:11 +0300 |
---|---|---|
committer | Derick Montague <derick.montague@ibm.com> | 2021-01-05 22:54:01 +0300 |
commit | f415a0898b6f1f5cee8aa43259e8aedf07d395aa (patch) | |
tree | c4cb17fba51d9d4c6caa266081f07b95778abf9d /src | |
parent | 22d4d527af48d87ca70a8766bacc5b1ec0cfe9b7 (diff) | |
download | webui-vue-f415a0898b6f1f5cee8aa43259e8aedf07d395aa.tar.xz |
Add DumpsStore API calls
Ties in API requests to the Dumps page and adds ability to:
- Create new System or BMC dump
- Delete single or multiple BMC dumps. Uses ClearLog service to
delete all and DELETE request for single dump deletion
Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: Iae928fa3b8fab00e549c33c0ab914a4b04de0f40
Diffstat (limited to 'src')
-rw-r--r-- | src/assets/styles/bmc/custom/_forms.scss | 2 | ||||
-rw-r--r-- | src/env/components/Dumps/Dumps.vue | 46 | ||||
-rw-r--r-- | src/env/components/Dumps/DumpsForm.vue | 38 | ||||
-rw-r--r-- | src/env/components/Dumps/DumpsModalConfirmation.vue | 75 | ||||
-rw-r--r-- | src/env/store/Dumps/DumpsStore.js | 91 | ||||
-rw-r--r-- | src/locales/en-US.json | 25 |
6 files changed, 259 insertions, 18 deletions
diff --git a/src/assets/styles/bmc/custom/_forms.scss b/src/assets/styles/bmc/custom/_forms.scss index cea5ef50..428a40c2 100644 --- a/src/assets/styles/bmc/custom/_forms.scss +++ b/src/assets/styles/bmc/custom/_forms.scss @@ -51,7 +51,7 @@ .custom-select, .custom-control-label, .form-control { - color: theme-color("dark"); + color: theme-color("dark") !important; font-size: 1rem; } diff --git a/src/env/components/Dumps/Dumps.vue b/src/env/components/Dumps/Dumps.vue index eba90b7a..3bf5579a 100644 --- a/src/env/components/Dumps/Dumps.vue +++ b/src/env/components/Dumps/Dumps.vue @@ -3,14 +3,14 @@ <page-title /> <b-row> <b-col sm="6" lg="5" xl="4"> - <page-section :section-title="$t('pageDumps.newDump')"> + <page-section :section-title="$t('pageDumps.initiateDump')"> <dumps-form /> </page-section> </b-col> </b-row> <b-row> <b-col xl="10"> - <page-section :section-title="$t('pageDumps.dumpHistory')"> + <page-section :section-title="$t('pageDumps.dumpsAvailableOnBmc')"> <b-row class="align-items-start"> <b-col sm="8" xl="6" class="d-sm-flex align-items-end"> <search @@ -41,6 +41,7 @@ hover sort-icon-left no-sort-reset + sort-desc selectable no-select-on-click responsive="md" @@ -121,6 +122,7 @@ import BVTableSelectableMixin, { tableHeaderCheckboxModel, tableHeaderCheckboxIndeterminate, } from '@/components/Mixins/BVTableSelectableMixin'; +import BVToastMixin from '@/components/Mixins/BVToastMixin'; import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; import SearchFilterMixin, { searchFilter, @@ -141,6 +143,7 @@ export default { }, mixins: [ BVTableSelectableMixin, + BVToastMixin, LoadingBarMixin, SearchFilterMixin, TableFilterMixin, @@ -202,7 +205,7 @@ export default { }, computed: { dumps() { - return this.$store.getters['dumps/allDumps']; + return this.$store.getters['dumps/bmcDumps']; }, tableItems() { return this.dumps.map((item) => { @@ -246,7 +249,7 @@ export default { this.filterStartDate = fromDate; this.filterEndDate = toDate; }, - onTableRowAction(action) { + onTableRowAction(action, dump) { if (action === 'delete') { this.$bvModal .msgBoxConfirm(this.$tc('pageDumps.modal.deleteDumpConfirmation'), { @@ -255,7 +258,19 @@ export default { cancelTitle: this.$t('global.action.cancel'), }) .then((deleteConfrimed) => { - if (deleteConfrimed); // delete dump + if (deleteConfrimed) { + this.$store + .dispatch('dumps/deleteDumps', [dump]) + .then((messages) => { + messages.forEach(({ type, message }) => { + if (type === 'success') { + this.successToast(message); + } else if (type === 'error') { + this.errorToast(message); + } + }); + }); + } }); } }, @@ -280,7 +295,26 @@ export default { } ) .then((deleteConfrimed) => { - if (deleteConfrimed); // delete dump + if (deleteConfrimed) { + if (this.selectedRows.length === this.dumps.length) { + this.$store + .dispatch('dumps/deleteAllDumps') + .then((success) => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); + } else { + this.$store + .dispatch('dumps/deleteDumps', this.selectedRows) + .then((messages) => { + messages.forEach(({ type, message }) => { + if (type === 'success') { + this.successToast(message); + } else if (type === 'error') { + this.errorToast(message); + } + }); + }); + } + } }); } }, diff --git a/src/env/components/Dumps/DumpsForm.vue b/src/env/components/Dumps/DumpsForm.vue index ed81b3a8..9dc8bcb1 100644 --- a/src/env/components/Dumps/DumpsForm.vue +++ b/src/env/components/Dumps/DumpsForm.vue @@ -21,20 +21,28 @@ {{ $t('global.form.required') }} </b-form-invalid-feedback> </b-form-group> + <alert variant="info" class="mb-3" :show="selectedDumpType === 'system'"> + {{ $t('pageDumps.form.systemDumpInfo') }} + </alert> <b-button variant="primary" type="submit" form="form-new-dump"> - {{ $t('pageDumps.form.createNewDump') }} + {{ $t('pageDumps.form.initiateDump') }} </b-button> </b-form> + <modal-confirmation @ok="createSystemDump" /> </div> </template> <script> import { required } from 'vuelidate/lib/validators'; +import ModalConfirmation from './DumpsModalConfirmation'; +import Alert from '@/components/Global/Alert'; + import BVToastMixin from '@/components/Mixins/BVToastMixin'; import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; export default { + components: { Alert, ModalConfirmation }, mixins: [BVToastMixin, VuelidateMixin], data() { return { @@ -54,7 +62,33 @@ export default { handleSubmit() { this.$v.$touch(); if (this.$v.$invalid) return; - this.successToast(this.$t('pageDumps.toast.successStartDump')); + if (this.selectedDumpType === 'system') { + this.showConfirmationModal(); + } else { + this.$store + .dispatch('dumps/createBmcDump') + .then(() => + this.infoToast( + this.$t('pageDumps.toast.successStartBmcDump'), + this.$t('pageDumps.toast.successStartBmcDumpTitle') + ) + ) + .catch(({ message }) => this.errorToast(message)); + } + }, + showConfirmationModal() { + this.$bvModal.show('modal-confirmation'); + }, + createSystemDump() { + this.$store + .dispatch('dumps/createSystemDump') + .then(() => + this.infoToast( + this.$t('pageDumps.toast.successStartSystemDump'), + this.$t('pageDumps.toast.successStartSystemDumpTitle') + ) + ) + .catch(({ message }) => this.errorToast(message)); }, }, }; diff --git a/src/env/components/Dumps/DumpsModalConfirmation.vue b/src/env/components/Dumps/DumpsModalConfirmation.vue new file mode 100644 index 00000000..f8e20cfd --- /dev/null +++ b/src/env/components/Dumps/DumpsModalConfirmation.vue @@ -0,0 +1,75 @@ +<template> + <b-modal + id="modal-confirmation" + ref="modal" + :title="$t('pageDumps.modal.initiateSystemDump')" + @hidden="resetForm" + > + <p> + <strong> + {{ $t('pageDumps.modal.initiateSystemDumpMessage1') }} + </strong> + </p> + <p> + {{ $t('pageDumps.modal.initiateSystemDumpMessage2') }} + </p> + <p> + <status-icon status="danger" /> + {{ $t('pageDumps.modal.initiateSystemDumpMessage3') }} + </p> + <b-form-checkbox v-model="confirmed" @input="$v.confirmed.$touch()"> + {{ $t('pageDumps.modal.initiateSystemDumpMessage4') }} + </b-form-checkbox> + <b-form-invalid-feedback + :state="getValidationState($v.confirmed)" + role="alert" + > + {{ $t('global.form.required') }} + </b-form-invalid-feedback> + <template #modal-footer="{ cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button variant="danger" @click="handleSubmit"> + {{ $t('pageDumps.form.initiateDump') }} + </b-button> + </template> + </b-modal> +</template> + +<script> +import StatusIcon from '@/components/Global/StatusIcon'; +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; + +export default { + components: { StatusIcon }, + mixins: [VuelidateMixin], + data() { + return { + confirmed: false, + }; + }, + validations: { + confirmed: { + mustBeTrue: (value) => value === true, + }, + }, + methods: { + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$emit('ok'); + this.closeModal(); + }, + resetForm() { + this.confirmed = false; + this.$v.$reset(); + }, + }, +}; +</script> diff --git a/src/env/store/Dumps/DumpsStore.js b/src/env/store/Dumps/DumpsStore.js index 45f446c0..3b91354b 100644 --- a/src/env/store/Dumps/DumpsStore.js +++ b/src/env/store/Dumps/DumpsStore.js @@ -1,4 +1,5 @@ -import api from '@/store/api'; +import api, { getResponseCount } from '@/store/api'; +import i18n from '@/i18n'; const DumpsStore = { namespaced: true, @@ -6,16 +7,17 @@ const DumpsStore = { bmcDumps: [], }, getters: { - allDumps: (state) => state.bmcDumps, + bmcDumps: (state) => state.bmcDumps, }, mutations: { setBmcDumps: (state, dumps) => { state.bmcDumps = dumps.map((dump) => ({ + data: dump.AdditionalDataURI, dateTime: new Date(dump.Created), dumpType: dump.Name, id: dump.Id, + location: dump['@odata.id'], size: dump.AdditionalDataSizeBytes, - data: dump.AdditionalDataURI, })); }, }, @@ -26,6 +28,89 @@ const DumpsStore = { .then(({ data = {} }) => commit('setBmcDumps', data.Members || [])) .catch((error) => console.log(error)); }, + async createBmcDump() { + return await api + .post( + '/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData', + { + DiagnosticDataType: 'Manager', + OEMDiagnosticDataType: '', + } + ) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageDumps.toast.errorStartBmcDump')); + }); + }, + async createSystemDump() { + return await api + .post( + '/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.CollectDiagnosticData', + { + DiagnosticDataType: 'OEM', + OEMDiagnosticDataType: 'System', + } + ) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageDumps.toast.errorStartSystemDump')); + }); + }, + async deleteDumps({ dispatch }, dumps) { + const promises = dumps.map(({ location }) => + api.delete(location).catch((error) => { + console.log(error); + return error; + }) + ); + return await api + .all(promises) + .then((response) => { + dispatch('getBmcDumps'); + return response; + }) + .then( + api.spread((...responses) => { + const { successCount, errorCount } = getResponseCount(responses); + const toastMessages = []; + + if (successCount) { + const message = i18n.tc( + 'pageDumps.toast.successDeleteDump', + successCount + ); + toastMessages.push({ type: 'success', message }); + } + + if (errorCount) { + const message = i18n.tc( + 'pageDumps.toast.errorDeleteDump', + errorCount + ); + toastMessages.push({ type: 'error', message }); + } + + return toastMessages; + }) + ); + }, + async deleteAllDumps({ commit, state }) { + const totalDumpCount = state.bmcDumps.length; + return await api + .post( + '/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.ClearLog' + ) + .then(() => { + commit('setBmcDumps', []); + return i18n.tc('pageDumps.toast.successDeleteDump', totalDumpCount); + }) + .catch((error) => { + console.log(error); + throw new Error( + i18n.tc('pageDumps.toast.errorDeleteDump', totalDumpCount) + ); + }); + }, }, }; diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 1d564ca6..ab9d8238 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -201,17 +201,23 @@ } }, "pageDumps": { - "dumpHistory": "Dump history", - "newDump": "New dump", + "dumpsAvailableOnBmc": "Dumps available on BMC", + "initiateDump": "Initiate dump", "form": { "bmcDump": "BMC dump", - "createNewDump": "Create new dump", + "initiateDump": "Initiate dump", "selectDumpType": "Select dump type", - "systemDump": "System dump (disruptive)" + "systemDump": "System dump (disruptive)", + "systemDumpInfo": "System dumps will be offloaded to the operating system and will not appear in the table below." }, "modal": { "deleteDump": "Delete dump | Delete dumps", - "deleteDumpConfirmation": "Are you sure you want to delete %{count} dump? This action cannot be undone. | Are you sure you want to delete %{count} dumps? This action cannot be undone." + "deleteDumpConfirmation": "Are you sure you want to delete %{count} dump? This action cannot be undone. | Are you sure you want to delete %{count} dumps? This action cannot be undone.", + "initiateSystemDump": "Initiate system dump", + "initiateSystemDumpMessage1": "Are you sure?", + "initiateSystemDumpMessage2": "You will not be able to initiate any other dumps while a system dump is in progress.", + "initiateSystemDumpMessage3": "Initiating a system dump will abnormally terminate all active system partitions.", + "initiateSystemDumpMessage4": "Proceed with dump initiation" }, "table": { "createdBy": "Created by", @@ -222,7 +228,14 @@ "size": "Size" }, "toast": { - "successStartDump": "Successfully started new dump." + "errorDeleteDump": "Error deleting %{count} dump. | Error deleting %{count} dumps.", + "errorStartBmcDump": "Error starting new BMC dump.", + "errorStartSystemDump": "Error starting new System dump.", + "successDeleteDump": "Successfully deleted %{count} dump. | Successfully deleted %{count} dumps.", + "successStartBmcDump": "The dump will take some time to complete. Refresh the application to see the completed dump in the table.", + "successStartBmcDumpTitle": "BMC dump started", + "successStartSystemDump": "The dump will take some time to complete. The dump will be offloaded to the operating system.", + "successStartSystemDumpTitle": "System dump started" } }, "pageEventLogs": { |