From 30abccbed83aee950016c2da0ae5bf512df769dc Mon Sep 17 00:00:00 2001 From: Yoshie Muranaka Date: Wed, 11 Mar 2020 12:44:24 -0700 Subject: Add Sensors page - Update api calls to use Redfish - Add column sort to name and status columns - Set default table sort to status column - Added lodash package Github story: https://github.com/openbmc/webui-vue/issues/4 Signed-off-by: Yoshie Muranaka Change-Id: Ic6e76107475fbf5fb34deb01a4de4a4a9ccfeabf --- src/assets/styles/_table.scss | 4 + src/components/AppNavigation/AppNavigation.vue | 2 +- src/locales/en-US.json | 11 +++ src/router/index.js | 7 ++ src/store/index.js | 4 +- src/store/modules/Health/SensorsStore.js | 113 ++++++++++++++++++++++ src/views/Health/Sensors/Sensors.vue | 126 +++++++++++++++++++++++++ src/views/Health/Sensors/index.js | 2 + 8 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 src/store/modules/Health/SensorsStore.js create mode 100644 src/views/Health/Sensors/Sensors.vue create mode 100644 src/views/Health/Sensors/index.js (limited to 'src') diff --git a/src/assets/styles/_table.scss b/src/assets/styles/_table.scss index 528cb805..2372d257 100644 --- a/src/assets/styles/_table.scss +++ b/src/assets/styles/_table.scss @@ -1,6 +1,10 @@ table { position: relative; z-index: $zindex-dropdown; + .status-icon svg { + width: 1rem; + height: auto; + } } .table-light { diff --git a/src/components/AppNavigation/AppNavigation.vue b/src/components/AppNavigation/AppNavigation.vue index 48b94c3d..d0fee43f 100644 --- a/src/components/AppNavigation/AppNavigation.vue +++ b/src/components/AppNavigation/AppNavigation.vue @@ -21,7 +21,7 @@ {{ $t('appNavigation.hardwareStatus') }} - + {{ $t('appNavigation.sensors') }} diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 63247da6..adc11850 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -180,6 +180,17 @@ "successRebootStart": "Rebooting BMC." } }, + "pageSensors": { + "table": { + "currentValue": "Current value", + "lowerWarning": "Lower warning", + "lowerCritical": "Lower critical", + "name": "Name", + "status": "Status", + "upperWarning": "Upper warning", + "upperCritical": "Upper critical" + } + }, "pageServerPowerOperations": { "currentStatus": "Current status", "hostname": "Hostname", diff --git a/src/router/index.js b/src/router/index.js index 0d246cda..cd6cf8bf 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -23,6 +23,13 @@ const routes = [ title: 'appPageTitle.overview' } }, + { + path: '/health/sensors', + component: () => import('@/views/Health/Sensors'), + meta: { + title: 'appPageTitle.sensors' + } + }, { path: '/access-control/local-user-management', name: 'local-users', diff --git a/src/store/index.js b/src/store/index.js index 27216990..08ada05e 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -11,6 +11,7 @@ import ControlStore from './modules/Control/ControlStore'; import PowerControlStore from './modules/Control/PowerControlStore'; import NetworkSettingStore from './modules/Configuration/NetworkSettingsStore'; import EventLogStore from './modules/Health/EventLogStore'; +import SensorsStore from './modules/Health/SensorsStore'; import WebSocketPlugin from './plugins/WebSocketPlugin'; @@ -30,7 +31,8 @@ export default new Vuex.Store({ controls: ControlStore, powerControl: PowerControlStore, networkSettings: NetworkSettingStore, - eventLog: EventLogStore + eventLog: EventLogStore, + sensors: SensorsStore }, plugins: [WebSocketPlugin] }); diff --git a/src/store/modules/Health/SensorsStore.js b/src/store/modules/Health/SensorsStore.js new file mode 100644 index 00000000..5da15156 --- /dev/null +++ b/src/store/modules/Health/SensorsStore.js @@ -0,0 +1,113 @@ +import api from '../../api'; +import { uniqBy } from 'lodash'; + +const SensorsStore = { + namespaced: true, + state: { + sensors: [] + }, + getters: { + sensors: state => state.sensors + }, + mutations: { + setSensors: (state, sensors) => { + state.sensors = uniqBy([...state.sensors, ...sensors], 'name'); + } + }, + actions: { + getAllSensors({ dispatch }) { + dispatch('getChassisCollection').then(collection => { + collection.forEach(item => { + dispatch('getSensors', item); + dispatch('getThermalSensors', item); + dispatch('getPowerSensors', item); + }); + }); + }, + getChassisCollection() { + return api + .get('/redfish/v1/Chassis') + .then(({ data: { Members } }) => + Members.map(member => member['@odata.id']) + ) + .catch(error => console.log(error)); + }, + getSensors({ commit }, id) { + api + .get(`${id}/Sensors`) + .then(({ data: { Members = [] } }) => { + const promises = Members.map(sensor => api.get(sensor['@odata.id'])); + api.all(promises).then( + api.spread((...responses) => { + const sensorData = responses.map(({ data }) => { + return { + name: data.Name, + status: data.Status.Health, + currentValue: data.Reading, + lowerCaution: data.Thresholds.LowerCaution.Reading, + upperCaution: data.Thresholds.UpperCaution.Reading, + lowerCritical: data.Thresholds.LowerCritical.Reading, + upperCritical: data.Thresholds.UpperCritical.Reading, + units: data.ReadingUnits + }; + }); + commit('setSensors', sensorData); + }) + ); + }) + .catch(error => console.log(error)); + }, + getThermalSensors({ commit }, id) { + api + .get(`${id}/Thermal`) + .then(({ data: { Fans = [], Temperatures = [] } }) => { + const sensorData = []; + Fans.forEach(sensor => { + sensorData.push({ + // TODO: add upper/lower threshold + name: sensor.Name, + status: sensor.Status.Health, + currentValue: sensor.Reading, + units: sensor.ReadingUnits + }); + }); + Temperatures.forEach(sensor => { + sensorData.push({ + name: sensor.Name, + status: sensor.Status.Health, + currentValue: sensor.ReadingCelsius, + lowerCaution: sensor.LowerThresholdNonCritical, + upperCaution: sensor.UpperThresholdNonCritical, + lowerCritical: sensor.LowerThresholdCritical, + upperCritical: sensor.UpperThresholdCritical, + units: '℃' + }); + }); + commit('setSensors', sensorData); + }) + .catch(error => console.log(error)); + }, + getPowerSensors({ commit }, id) { + api + .get(`${id}/Power`) + .then(({ data: { Voltages = [] } }) => { + const sensorData = Voltages.map(sensor => { + return { + name: sensor.Name, + status: sensor.Status.Health, + currentValue: sensor.ReadingVolts, + lowerCaution: sensor.LowerThresholdNonCritical, + upperCaution: sensor.UpperThresholdNonCritical, + lowerCritical: sensor.LowerThresholdCritical, + upperCritical: sensor.UpperThresholdCritical, + units: 'Volts' + }; + }); + commit('setSensors', sensorData); + }) + .catch(error => console.log(error)); + } + } +}; + +export default SensorsStore; diff --git a/src/views/Health/Sensors/Sensors.vue b/src/views/Health/Sensors/Sensors.vue new file mode 100644 index 00000000..70d4f90d --- /dev/null +++ b/src/views/Health/Sensors/Sensors.vue @@ -0,0 +1,126 @@ + + + diff --git a/src/views/Health/Sensors/index.js b/src/views/Health/Sensors/index.js new file mode 100644 index 00000000..fc71b611 --- /dev/null +++ b/src/views/Health/Sensors/index.js @@ -0,0 +1,2 @@ +import Sensors from './Sensors.vue'; +export default Sensors; -- cgit v1.2.3