diff --git a/src/layouts/admin-menu.jsx b/src/layouts/admin-menu.jsx index f66eee87..f4d630a3 100644 --- a/src/layouts/admin-menu.jsx +++ b/src/layouts/admin-menu.jsx @@ -617,6 +617,14 @@ const renderMenu = (t) => { children: [], hasBreadcrumb: true, }, + { + path: '/monitor-center/openstack-service-admin', + name: t('OpenStack Service'), + key: 'monitorOpenstackServiceAdmin', + level: 1, + children: [], + hasBreadcrumb: true, + }, ], }, { diff --git a/src/pages/monitor/containers/OpenstackService/Services.jsx b/src/pages/monitor/containers/OpenstackService/Services.jsx new file mode 100644 index 00000000..1d82faaa --- /dev/null +++ b/src/pages/monitor/containers/OpenstackService/Services.jsx @@ -0,0 +1,85 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import React from 'react'; +import { Col, Collapse, List, Tooltip } from 'antd'; +import { CheckCircleTwoTone, InfoCircleTwoTone } from '@ant-design/icons'; +import styles from './index.less'; + +const { Panel } = Collapse; + +const statusToIcon = { + up: ( + + ), + // , + down: ( + + ), +}; + +const Services = (props) => { + const { serviceMap } = props; + return ( + item.key)} ghost> + {serviceMap.map((item) => ( + {item.title}} + key={item.key} + > + ( + + + {it.engine_id ? ( + + {it.serviceName} + + ) : ( + it.serviceName + )} + + + {it.hostname} + + + {t('Current Status')} + {statusToIcon[it.state]} + + + {t('Last 24H Status')} + {it[`${it.serviceName}24`] + ? statusToIcon[it[`${it.serviceName}24`]] + : statusToIcon.up} + + + )} + /> + + ))} + + ); +}; + +export default Services; diff --git a/src/pages/monitor/containers/OpenstackService/index.jsx b/src/pages/monitor/containers/OpenstackService/index.jsx new file mode 100644 index 00000000..7ec7c1cf --- /dev/null +++ b/src/pages/monitor/containers/OpenstackService/index.jsx @@ -0,0 +1,87 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import React, { Component } from 'react'; +import { observer } from 'mobx-react'; +import { OpenstackServiceStore } from 'stores/prometheus/openstack-service'; +import { SyncOutlined } from '@ant-design/icons'; +import { Button } from 'antd'; +import Services from './Services'; +import styles from '../PhysicalNode/index.less'; + +@observer +class OpenstackService extends Component { + constructor(props) { + super(props); + this.store = new OpenstackServiceStore(); + } + + componentDidMount() { + this.getData(); + } + + getData = async () => { + // await this.store.getNodes(); + await this.store.getChartData(); + }; + + handleRefresh = () => { + this.getData(); + }; + + render() { + const { nova_service, network_service, other_service, cinder_service } = + this.store; + const serviceMap = [ + { + key: 'nova_service', + title: t('Nova Service'), + ...nova_service, + }, + { + key: 'network_service', + title: t('Neutron Service'), + ...network_service, + }, + { + key: 'cinder_service', + title: t('Cinder Service'), + ...cinder_service, + }, + { + key: 'other_service', + title: t('Other Service'), + ...other_service, + }, + ]; + + return ( +
+
+
+
+
+
+ ); + } +} + +export default OpenstackService; diff --git a/src/pages/monitor/containers/OpenstackService/index.less b/src/pages/monitor/containers/OpenstackService/index.less new file mode 100644 index 00000000..8c3bce24 --- /dev/null +++ b/src/pages/monitor/containers/OpenstackService/index.less @@ -0,0 +1,32 @@ +.header { + font-size: 16px; + font-weight: 500; + color: rgba(0, 0, 0, 0.85); + line-height: 22px; +} + + +.list { + background-color: #FFFFFF; + box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.05); + border: none; + + .item { + height: 76px; + + .title { + display: flex; + font-size: 16px; + font-weight: 400; + color: rgba(0, 0, 0, 0.65); + } + + .status { + display: flex; + font-size: 14px; + font-weight: 400; + color: rgba(0, 0, 0, 0.65); + } + } +} + diff --git a/src/pages/monitor/routes/index.js b/src/pages/monitor/routes/index.js index d795dd42..33bff036 100644 --- a/src/pages/monitor/routes/index.js +++ b/src/pages/monitor/routes/index.js @@ -16,6 +16,7 @@ import BaseLayout from 'layouts/Basic'; import E404 from 'pages/base/containers/404'; import PhysicalNode from '../containers/PhysicalNode'; import StorageCluster from '../containers/StorageCluster'; +import OpenstackService from '../containers/OpenstackService'; import Overview from '../containers/Overview'; const PATH = '/monitor-center'; @@ -35,6 +36,11 @@ export default [ component: StorageCluster, exact: true, }, + { + path: `${PATH}/openstack-service-admin`, + component: OpenstackService, + exact: true, + }, { path: '*', component: E404 }, ], }, diff --git a/src/stores/prometheus/openstack-service.js b/src/stores/prometheus/openstack-service.js index 2dad01d3..4032ec40 100644 --- a/src/stores/prometheus/openstack-service.js +++ b/src/stores/prometheus/openstack-service.js @@ -77,64 +77,70 @@ export class OpenstackServiceStore extends MonitorBase { isLoading: true, data: [], }); - const [currentState, last24State, libvirtdState, libvirtd24State] = - await Promise.all(getPromises.call(this, 'openstackService.novaService')); - const { - data: { result: currentStateResult }, - } = currentState; const tmp = []; - currentStateResult.forEach((service) => { + try { + const [currentState, last24State, libvirtdState, libvirtd24State] = + await Promise.all( + getPromises.call(this, 'openstackService.novaService') + ); const { - metric: { - service: serviceName = '', - adminState = '', - hostname = '', - } = {}, - } = service; - tmp.push({ - hostname, - serviceName, - state: adminState === 'enabled' ? 'up' : 'down', + data: { result: currentStateResult }, + } = currentState; + currentStateResult.forEach((service) => { + const { + metric: { + service: serviceName = '', + adminState = '', + hostname = '', + } = {}, + } = service; + tmp.push({ + hostname, + serviceName, + state: adminState === 'enabled' ? 'up' : 'down', + }); }); - }); - const { - data: { result: last24HResult }, - } = last24State; - last24HResult.forEach((service) => { - const { metric: { service: serviceName = '', hostname = '' } = {} } = - service; - const idx = tmp.findIndex( - (item) => item.serviceName === serviceName && item.hostname === hostname - ); - tmp[idx][`${serviceName}24`] = 'down'; - }); - const { - data: { result: data }, - } = libvirtdState; - data.forEach((item) => { - const { metric, value } = item; - tmp.push({ - // hard code - serviceName: 'nova_libvirt', - hostname: metric.hostname, - state: value[1] === 'enabled' ? 'up' : 'down', + const { + data: { result: last24HResult }, + } = last24State; + last24HResult.forEach((service) => { + const { metric: { service: serviceName = '', hostname = '' } = {} } = + service; + const idx = tmp.findIndex( + (item) => + item.serviceName === serviceName && item.hostname === hostname + ); + tmp[idx][`${serviceName}24`] = 'down'; }); - }); - const { - data: { result: libvirtd24Result }, - } = libvirtd24State; - libvirtd24Result.forEach((service) => { - const { metric: { hostname = '' } = {} } = service; - const idx = tmp.findIndex( - (item) => - item.serviceName === 'nova_libvirt' && item.hostname === hostname - ); - tmp[idx].nova_libvirt24 = 'down'; - }); - set(this.nova_service, { - isLoading: false, - data: tmp, - }); + const { + data: { result: data }, + } = libvirtdState; + data.forEach((item) => { + const { metric, value } = item; + tmp.push({ + // hard code + serviceName: 'nova_libvirt', + hostname: metric.hostname, + state: value[1] === 'enabled' ? 'up' : 'down', + }); + }); + const { + data: { result: libvirtd24Result }, + } = libvirtd24State; + libvirtd24Result.forEach((service) => { + const { metric: { hostname = '' } = {} } = service; + const idx = tmp.findIndex( + (item) => + item.serviceName === 'nova_libvirt' && item.hostname === hostname + ); + tmp[idx].nova_libvirt24 = 'down'; + }); + } finally { + set(this.nova_service, { + isLoading: false, + data: tmp, + }); + } }; @action @@ -143,42 +149,46 @@ export class OpenstackServiceStore extends MonitorBase { isLoading: true, data: [], }); - const [currentState, last24State] = await Promise.all( - getPromises.call(this, 'openstackService.networkService') - ); - const { - data: { result: currentStateResult }, - } = currentState; const tmp = []; - currentStateResult.forEach((service) => { - const { - metric: { - service: serviceName = '', - adminState = '', - hostname = '', - } = {}, - } = service; - tmp.push({ - serviceName, - hostname, - state: adminState, - }); - }); - const { - data: { result: last24HResult }, - } = last24State; - last24HResult.forEach((service) => { - const { metric: { service: serviceName = '', hostname = '' } = {} } = - service; - const idx = tmp.findIndex( - (item) => item.serviceName === serviceName && item.hostname === hostname + try { + const [currentState, last24State] = await Promise.all( + getPromises.call(this, 'openstackService.networkService') ); - tmp[idx][`${serviceName}24`] = 'down'; - }); - set(this.network_service, { - isLoading: false, - data: tmp, - }); + const { + data: { result: currentStateResult }, + } = currentState; + currentStateResult.forEach((service) => { + const { + metric: { + service: serviceName = '', + adminState = '', + hostname = '', + } = {}, + } = service; + tmp.push({ + serviceName, + hostname, + state: adminState, + }); + }); + const { + data: { result: last24HResult }, + } = last24State; + last24HResult.forEach((service) => { + const { metric: { service: serviceName = '', hostname = '' } = {} } = + service; + const idx = tmp.findIndex( + (item) => + item.serviceName === serviceName && item.hostname === hostname + ); + tmp[idx][`${serviceName}24`] = 'down'; + }); + } finally { + set(this.network_service, { + isLoading: false, + data: tmp, + }); + } }; @action @@ -187,42 +197,46 @@ export class OpenstackServiceStore extends MonitorBase { isLoading: true, data: [], }); - const [currentState, last24State] = await Promise.all( - getPromises.call(this, 'openstackService.cinderService') - ); - const { - data: { result: currentStateResult }, - } = currentState; const tmp = []; - currentStateResult.forEach((service) => { - const { - metric: { - service: serviceName = '', - adminState = '', - hostname = '', - } = {}, - } = service; - tmp.push({ - serviceName, - hostname, - state: adminState === 'enabled' ? 'up' : 'down', - }); - }); - const { - data: { result: last24HResult }, - } = last24State; - last24HResult.forEach((service) => { - const { metric: { service: serviceName = '', hostname = '' } = {} } = - service; - const idx = tmp.findIndex( - (item) => item.serviceName === serviceName && item.hostname === hostname + try { + const [currentState, last24State] = await Promise.all( + getPromises.call(this, 'openstackService.cinderService') ); - tmp[idx][`${serviceName}24`] = 'down'; - }); - set(this.cinder_service, { - isLoading: false, - data: tmp, - }); + const { + data: { result: currentStateResult }, + } = currentState; + currentStateResult.forEach((service) => { + const { + metric: { + service: serviceName = '', + adminState = '', + hostname = '', + } = {}, + } = service; + tmp.push({ + serviceName, + hostname, + state: adminState === 'enabled' ? 'up' : 'down', + }); + }); + const { + data: { result: last24HResult }, + } = last24State; + last24HResult.forEach((service) => { + const { metric: { service: serviceName = '', hostname = '' } = {} } = + service; + const idx = tmp.findIndex( + (item) => + item.serviceName === serviceName && item.hostname === hostname + ); + tmp[idx][`${serviceName}24`] = 'down'; + }); + } finally { + set(this.cinder_service, { + isLoading: false, + data: tmp, + }); + } }; @action @@ -232,80 +246,82 @@ export class OpenstackServiceStore extends MonitorBase { data: [], }); const tmp = []; - let results = await Promise.all( - getPromises.call(this, 'openstackService.otherService') - ); - results.forEach((result) => { - const { - data: { result: data }, - } = result; - data.forEach((d) => { - const { metric, value } = d; - tmp.push({ - serviceName: serviceNameMap[metric.__name__], - hostname: metric.instance, - state: value[1] === '1' ? 'up' : 'down', + try { + let results = await Promise.all( + getPromises.call(this, 'openstackService.otherService') + ); + results.forEach((result) => { + const { + data: { result: data }, + } = result; + data.forEach((d) => { + const { metric, value } = d; + tmp.push({ + serviceName: serviceNameMap[metric.__name__], + hostname: metric.instance, + state: value[1] === '1' ? 'up' : 'down', + }); }); }); - }); - results = await Promise.all( - getPromises.call(this, 'openstackService.otherServiceMinOverTime') - ); - results.forEach((result, index) => { - const { - data: { result: last24HResult }, - } = result; - last24HResult.forEach((service) => { - const { metric: { instance = '' } = {} } = service; - const idx = tmp.findIndex( - (item) => - item.serviceName === indexToServiceName[index] && - item.hostname === instance - ); - tmp[idx][`${indexToServiceName[index]}24`] = 'down'; + results = await Promise.all( + getPromises.call(this, 'openstackService.otherServiceMinOverTime') + ); + results.forEach((result, index) => { + const { + data: { result: last24HResult }, + } = result; + last24HResult.forEach((service) => { + const { metric: { instance = '' } = {} } = service; + const idx = tmp.findIndex( + (item) => + item.serviceName === indexToServiceName[index] && + item.hostname === instance + ); + tmp[idx][`${indexToServiceName[index]}24`] = 'down'; + }); }); - }); - // const [heatResponse, heat24Response] = await Promise.all( - // getPromises.call(this, 'openstackService.heatMinOverTime') - // ); - // const { - // data: { result: heatResults }, - // } = heatResponse; - // heatResults.forEach((item) => { - // const { - // metric: { - // host = '', - // binary = '', - // engine_id = '', - // services_status = '', - // } = {}, - // } = item; - // tmp.push({ - // serviceName: binary, - // host, - // state: services_status, - // engine_id, - // }); - // }); - // const { - // data: { result: heat24Results }, - // } = heat24Response; - // heat24Results.forEach((result) => { - // const { metric: { binary = '', engine_id = '', host = '' } = {} } = - // result; - // const idx = tmp.findIndex( - // (item) => - // item.serviceName === binary && - // item.host === host && - // item.engine_id === engine_id - // ); - // tmp[idx][`${binary}24`] = 'down'; - // }); - - set(this.other_service, { - isLoading: false, - data: tmp, - }); + // const [heatResponse, heat24Response] = await Promise.all( + // getPromises.call(this, 'openstackService.heatMinOverTime') + // ); + // const { + // data: { result: heatResults }, + // } = heatResponse; + // heatResults.forEach((item) => { + // const { + // metric: { + // host = '', + // binary = '', + // engine_id = '', + // services_status = '', + // } = {}, + // } = item; + // tmp.push({ + // serviceName: binary, + // host, + // state: services_status, + // engine_id, + // }); + // }); + // const { + // data: { result: heat24Results }, + // } = heat24Response; + // heat24Results.forEach((result) => { + // const { metric: { binary = '', engine_id = '', host = '' } = {} } = + // result; + // const idx = tmp.findIndex( + // (item) => + // item.serviceName === binary && + // item.host === host && + // item.engine_id === engine_id + // ); + // tmp[idx][`${binary}24`] = 'down'; + // }); + } finally { + set(this.other_service, { + isLoading: false, + data: tmp, + }); + } }; }