skyline/src/pages/base/containers/Overview/components/QuotaOverview.jsx
xusongfu 7ac40b2650 fix: Support no-cinder
1. Update base client to support service disable
2. Remove volume in create instance if no-cinder
3. Remove cinder services in overview page if no-cinder
4. Remove some storage services if no-cinder
5. Remove volume in monitor centers if no-cinder

Change-Id: Ib6f8f3ed86098b4097b0428b48f0b136bf5ee349
Closes-Bug: #1939984
2022-03-25 12:57:28 +08:00

310 lines
8.1 KiB
JavaScript

// 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 { Badge, Card, Col, List, Progress, Row, Spin, Tooltip } from 'antd';
import { inject, observer } from 'mobx-react';
import globalVolumeTypeStore from 'stores/cinder/volume-type';
import globalProjectStore from 'stores/keystone/project';
import globalRootStore from 'stores/root';
import { isNumber } from 'lodash';
import styles from '../style.less';
const colors = {
normal: { color: '#4CC9F0', text: t('Normal') },
danger: { color: '#4361EE', text: t('Danger') },
full: { color: '#E8684A', text: t('Full') },
};
export const quotaCardList = [
{
text: t('Compute'),
type: 'compute',
value: [
{ text: t('Instances'), key: 'instances' },
{ text: t('vCPUs'), key: 'cores' },
{ text: t('Memory'), key: 'ram' },
{ text: t('Key Pair'), key: 'key_pairs' },
{ text: t('Server Group'), key: 'server_groups' },
],
},
{
text: t('Storage'),
type: 'storage',
value: [
{
text: t('volumes'),
key: 'volumes',
},
{
text: t('Gigabytes(GB)'),
key: 'gigabytes',
},
{
text: t('Snapshots'),
key: 'snapshots',
},
{
text: t('backups'),
key: 'backups',
},
{
text: t('backup gigabytes (GiB)'),
key: 'backup_gigabytes',
},
],
},
{
text: t('Network'),
type: 'networks',
value: [
{ text: t('Router'), key: 'router' },
{ text: t('Network'), key: 'network' },
{ text: t('Subnet'), key: 'subnet' },
{ text: t('Floating IP'), key: 'floatingip' },
{ text: t('Port'), key: 'port' },
{ text: t('Security Group'), key: 'security_group' },
{ text: t('Security Group Rule'), key: 'security_group_rule' },
],
},
];
export const getVolumeTypeCards = (data) => {
const value = data.map((item, index) => {
return {
index,
value: [
{
text: t('{name} type', { name: item.name }),
key: `volumes_${item.name}`,
},
{
text: t('{name} type gigabytes(GB)', { name: item.name }),
key: `gigabytes_${item.name}`,
},
{
text: t('{name} type snapshots', { name: item.name }),
key: `snapshots_${item.name}`,
},
],
};
});
return {
text: t('Storage Types'),
type: 'volumeTypes',
value,
};
};
export class QuotaOverview extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
};
const { projectStore, volumeTypeStore } = props;
this.projectStore = projectStore || globalProjectStore;
this.volumeTypeStore = volumeTypeStore || globalVolumeTypeStore;
}
componentDidMount() {
this.getData();
}
async getData() {
const { getData } = this.props;
if (getData) {
await getData();
} else {
const { user } = this.props.rootStore;
const { project: { id: projectId = '' } = {} } = user;
const promiseArr = [
this.projectStore.fetchProjectQuota({ project_id: projectId }),
];
if (this.enableCinder) {
promiseArr.push(this.volumeTypeStore.fetchList());
}
await Promise.all(promiseArr);
}
this.setState({
isLoading: false,
});
}
get enableCinder() {
return globalRootStore.checkEndpoint('cinder');
}
get volumeTypeData() {
const { volumeTypeData } = this.props;
return volumeTypeData || this.volumeTypeStore.list.data;
}
get volumeTypesQuota() {
return getVolumeTypeCards(this.volumeTypeData);
}
get quotaCardList() {
const list = this.props.quotaCardList || quotaCardList;
if (!this.enableCinder) {
return list.filter((it) => it.type !== 'storage');
}
return list;
}
get quotaAction() {
return this.props.quotaAction;
}
getFilteredValue = (value) => value.filter((it) => !it.hidden);
getItemInfo = (data, i) => {
let percent = 0;
if (data[i.key] && isNumber(data[i.key].used) && data[i.key].limit !== -1) {
percent = (data[i.key].used / data[i.key].limit) * 100;
}
let used = '-';
if (data[i.key] && isNumber(data[i.key].used)) {
used = `${data[i.key].used} / ${
data[i.key].limit === -1 ? t('Unlimit') : data[i.key].limit
}`;
}
const strokeColor =
(percent >= 90 && colors.full.color) ||
(percent >= 80 && colors.danger.color) ||
colors.normal.color;
let title = `${i.text} : ${used}`;
const { server_group_members } = data;
if (i.key === 'server_groups' && server_group_members) {
title = `${title} (${t('Member in group')} : ${
server_group_members.limit === -1
? t('Unlimit')
: server_group_members.limit
})`;
}
return (
<>
<Tooltip title={title}>
<div className={styles.progress_title}>{title}</div>
</Tooltip>
<Progress
style={{ marginTop: 13, marginBottom: 13 }}
percent={percent}
showInfo={false}
strokeColor={strokeColor}
/>
</>
);
};
renderQuotaCardList = () => {
const { isLoading } = this.state;
return (
<Row className={styles.content}>
{this.quotaCardList.map((item) => (
<Col className={styles.card} span={12} key={item.type}>
<Card title={item.text} bordered={false} loading={isLoading}>
{this.renderQuotaCardContent(item)}
</Card>
</Col>
))}
{this.enableCinder ? (
<Col
className={styles.card}
span={24}
key={this.volumeTypesQuota.type}
>
<Card
title={this.volumeTypesQuota.text}
bordered={false}
loading={isLoading}
>
{this.renderVolumeTypes()}
</Card>
</Col>
) : null}
</Row>
);
};
renderQuotaCardContent(item) {
const { isLoading } = this.state;
if (isLoading) {
return <Spin />;
}
return this.renderQuotaCart(
this.projectStore.quota,
this.getFilteredValue(item.value)
);
}
renderQuotaCart = (data, item = []) =>
item.map((i) => <div key={i.text}>{this.getItemInfo(data, i)}</div>);
renderVolumeTypes = () => {
const { isLoading } = this.state;
if (isLoading) {
return <Spin />;
}
return (
<List
itemLayout="vertical"
size="large"
pagination={{
hideOnSinglePage: true,
pageSize: 5,
size: 'small',
}}
dataSource={this.volumeTypesQuota.value}
renderItem={(item) => (
<Row key={item.index} gutter={[16]}>
{item.value.map((i) => (
<Col span={8} key={i.text}>
{this.getItemInfo(this.projectStore.quota, i)}
</Col>
))}
</Row>
)}
/>
);
};
render() {
const { isLoading } = this.state;
return (
<Card
className={styles.bottom}
bodyStyle={{ padding: 0 }}
loading={isLoading}
title={
<div className={styles.title}>
<span className={styles.text}>{t('Quota Overview')}</span>
{Object.keys(colors).map((key) => (
<span key={key} className={styles.badge}>
<Badge color={colors[key].color} text={colors[key].text} />
</span>
))}
</div>
}
extra={this.quotaAction}
>
{this.renderQuotaCardList()}
</Card>
);
}
}
export default inject('rootStore')(observer(QuotaOverview));