1import api from '@/store/api';
2import i18n from '@/i18n';
3
4const FirmwareStore = {
5  namespaced: true,
6  state: {
7    bmcFirmware: [],
8    hostFirmware: [],
9    bmcActiveFirmwareId: null,
10    hostActiveFirmwareId: null,
11    applyTime: null,
12    httpPushUri: null,
13    tftpAvailable: false,
14  },
15  getters: {
16    isTftpUploadAvailable: (state) => state.tftpAvailable,
17    isSingleFileUploadEnabled: (state) => state.hostFirmware.length === 0,
18    activeBmcFirmware: (state) => {
19      return state.bmcFirmware.find(
20        (firmware) => firmware.id === state.bmcActiveFirmwareId
21      );
22    },
23    activeHostFirmware: (state) => {
24      return state.hostFirmware.find(
25        (firmware) => firmware.id === state.hostActiveFirmwareId
26      );
27    },
28    backupBmcFirmware: (state) => {
29      return state.bmcFirmware.find(
30        (firmware) => firmware.id !== state.bmcActiveFirmwareId
31      );
32    },
33    backupHostFirmware: (state) => {
34      return state.hostFirmware.find(
35        (firmware) => firmware.id !== state.hostActiveFirmwareId
36      );
37    },
38  },
39  mutations: {
40    setActiveBmcFirmwareId: (state, id) => (state.bmcActiveFirmwareId = id),
41    setActiveHostFirmwareId: (state, id) => (state.hostActiveFirmwareId = id),
42    setBmcFirmware: (state, firmware) => (state.bmcFirmware = firmware),
43    setHostFirmware: (state, firmware) => (state.hostFirmware = firmware),
44    setApplyTime: (state, applyTime) => (state.applyTime = applyTime),
45    setHttpPushUri: (state, httpPushUri) => (state.httpPushUri = httpPushUri),
46    setTftpUploadAvailable: (state, tftpAvailable) =>
47      (state.tftpAvailable = tftpAvailable),
48  },
49  actions: {
50    async getFirmwareInformation({ dispatch }) {
51      dispatch('getActiveHostFirmware');
52      dispatch('getActiveBmcFirmware');
53      return await dispatch('getFirmwareInventory');
54    },
55    getActiveBmcFirmware({ commit }) {
56      return api
57        .get('/redfish/v1/Managers/bmc')
58        .then(({ data: { Links } }) => {
59          const id = Links?.ActiveSoftwareImage['@odata.id'].split('/').pop();
60          commit('setActiveBmcFirmwareId', id);
61        })
62        .catch((error) => console.log(error));
63    },
64    getActiveHostFirmware({ commit }) {
65      return api
66        .get('/redfish/v1/Systems/system/Bios')
67        .then(({ data: { Links } }) => {
68          const id = Links?.ActiveSoftwareImage['@odata.id'].split('/').pop();
69          commit('setActiveHostFirmwareId', id);
70        })
71        .catch((error) => console.log(error));
72    },
73    async getFirmwareInventory({ commit }) {
74      const inventoryList = await api
75        .get('/redfish/v1/UpdateService/FirmwareInventory')
76        .then(({ data: { Members = [] } = {} }) =>
77          Members.map((item) => api.get(item['@odata.id']))
78        )
79        .catch((error) => console.log(error));
80      await api
81        .all(inventoryList)
82        .then((response) => {
83          const bmcFirmware = [];
84          const hostFirmware = [];
85          response.forEach(({ data }) => {
86            const firmwareType = data?.RelatedItem?.[0]?.['@odata.id']
87              .split('/')
88              .pop();
89            const item = {
90              version: data?.Version,
91              id: data?.Id,
92              location: data?.['@odata.id'],
93              status: data?.Status?.Health,
94            };
95            if (firmwareType === 'bmc') {
96              bmcFirmware.push(item);
97            } else if (firmwareType === 'Bios') {
98              hostFirmware.push(item);
99            }
100          });
101          commit('setBmcFirmware', bmcFirmware);
102          commit('setHostFirmware', hostFirmware);
103        })
104        .catch((error) => {
105          console.log(error);
106        });
107    },
108    getUpdateServiceSettings({ commit }) {
109      api
110        .get('/redfish/v1/UpdateService')
111        .then(({ data }) => {
112          const applyTime =
113            data.HttpPushUriOptions.HttpPushUriApplyTime.ApplyTime;
114          const allowableActions =
115            data?.Actions?.['#UpdateService.SimpleUpdate']?.[
116              'TransferProtocol@Redfish.AllowableValues'
117            ];
118          commit('setApplyTime', applyTime);
119          const httpPushUri = data.HttpPushUri;
120          commit('setHttpPushUri', httpPushUri);
121          if (allowableActions?.includes('TFTP')) {
122            commit('setTftpUploadAvailable', true);
123          }
124        })
125        .catch((error) => console.log(error));
126    },
127    setApplyTimeImmediate({ commit }) {
128      const data = {
129        HttpPushUriOptions: {
130          HttpPushUriApplyTime: {
131            ApplyTime: 'Immediate',
132          },
133        },
134      };
135      return api
136        .patch('/redfish/v1/UpdateService', data)
137        .then(() => commit('setApplyTime', 'Immediate'))
138        .catch((error) => console.log(error));
139    },
140    async uploadFirmware({ state, dispatch }, image) {
141      if (state.applyTime !== 'Immediate') {
142        // ApplyTime must be set to Immediate before making
143        // request to update firmware
144        await dispatch('setApplyTimeImmediate');
145      }
146      return await api
147        .post(state.httpPushUri, image, {
148          headers: { 'Content-Type': 'application/octet-stream' },
149        })
150        .catch((error) => {
151          console.log(error);
152          throw new Error(i18n.t('pageFirmware.toast.errorUpdateFirmware'));
153        });
154    },
155    async uploadFirmwareTFTP({ state, dispatch }, fileAddress) {
156      const data = {
157        TransferProtocol: 'TFTP',
158        ImageURI: fileAddress,
159      };
160      if (state.applyTime !== 'Immediate') {
161        // ApplyTime must be set to Immediate before making
162        // request to update firmware
163        await dispatch('setApplyTimeImmediate');
164      }
165      return await api
166        .post(
167          '/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate',
168          data
169        )
170        .catch((error) => {
171          console.log(error);
172          throw new Error(i18n.t('pageFirmware.toast.errorUpdateFirmware'));
173        });
174    },
175    async switchBmcFirmwareAndReboot({ getters }) {
176      const backupLocation = getters.backupBmcFirmware.location;
177      const data = {
178        Links: {
179          ActiveSoftwareImage: {
180            '@odata.id': backupLocation,
181          },
182        },
183      };
184      return await api
185        .patch('/redfish/v1/Managers/bmc', data)
186        .catch((error) => {
187          console.log(error);
188          throw new Error(i18n.t('pageFirmware.toast.errorSwitchImages'));
189        });
190    },
191  },
192};
193
194export default FirmwareStore;
195