feat: support quota info when create security group

1. Add security group quota and security group rule quota when create security group
2. Check security group left quota and security group rule left quota to determine if a security group can be created: one security need 2 new rules
3. Add rule tip
4. Update form tip position

Change-Id: I8d7565763c8c325cf89630039e479ed00a70e7c3
This commit is contained in:
Jingwei.Zhang 2022-06-23 14:24:31 +08:00
parent bf6c765fb1
commit 919840a1e0
4 changed files with 81 additions and 1 deletions

View File

@ -696,7 +696,6 @@ export default class BaseForm extends React.Component {
const formDiv = ( const formDiv = (
<Spin spinning={this.isSubmitting} tip={this.renderSubmittingTip()}> <Spin spinning={this.isSubmitting} tip={this.renderSubmittingTip()}>
{tips}
{this.renderRightTopExtra()} {this.renderRightTopExtra()}
<div className={classnames(styles.form, 'sl-form')} style={formStyle}> <div className={classnames(styles.form, 'sl-form')} style={formStyle}>
{this.renderForms()} {this.renderForms()}
@ -716,6 +715,7 @@ export default class BaseForm extends React.Component {
<div <div
className={classnames(styles.wrapper, wrapperPadding, this.className)} className={classnames(styles.wrapper, wrapperPadding, this.className)}
> >
{tips}
{onlyForm && formDiv} {onlyForm && formDiv}
{modalInner} {modalInner}
</div> </div>

View File

@ -2279,6 +2279,7 @@
"There are resources that cannot {action} in the selected resources.": "There are resources that cannot {action} in the selected resources.", "There are resources that cannot {action} in the selected resources.": "There are resources that cannot {action} in the selected resources.",
"There are resources under the project and cannot be deleted.": "There are resources under the project and cannot be deleted.", "There are resources under the project and cannot be deleted.": "There are resources under the project and cannot be deleted.",
"There is currently no file to paste.": "There is currently no file to paste.", "There is currently no file to paste.": "There is currently no file to paste.",
"This operation creates a security group with default security group rules for the IPv4 and IPv6 ether types.": "This operation creates a security group with default security group rules for the IPv4 and IPv6 ether types.",
"This service will automatically query the configuration (CPU, memory, etc.) and mac address of the physical machine, and the ironic-inspector service will automatically register this information in the node information.": "This service will automatically query the configuration (CPU, memory, etc.) and mac address of the physical machine, and the ironic-inspector service will automatically register this information in the node information.", "This service will automatically query the configuration (CPU, memory, etc.) and mac address of the physical machine, and the ironic-inspector service will automatically register this information in the node information.": "This service will automatically query the configuration (CPU, memory, etc.) and mac address of the physical machine, and the ironic-inspector service will automatically register this information in the node information.",
"This will delete all child objects of the load balancer.": "This will delete all child objects of the load balancer.", "This will delete all child objects of the load balancer.": "This will delete all child objects of the load balancer.",
"Threads Activity Trends": "Threads Activity Trends", "Threads Activity Trends": "Threads Activity Trends",

View File

@ -2279,6 +2279,7 @@
"There are resources that cannot {action} in the selected resources.": "您选中的资源中有无法{action}的资源。", "There are resources that cannot {action} in the selected resources.": "您选中的资源中有无法{action}的资源。",
"There are resources under the project and cannot be deleted.": "项目下存在资源,无法执行删除操作。", "There are resources under the project and cannot be deleted.": "项目下存在资源,无法执行删除操作。",
"There is currently no file to paste.": "当前没有需要粘贴的文件。", "There is currently no file to paste.": "当前没有需要粘贴的文件。",
"This operation creates a security group with default security group rules for the IPv4 and IPv6 ether types.": "此操作会创建带有 IPv4 和 IPv6 的默认安全组规则的安全组。",
"This service will automatically query the configuration (CPU, memory, etc.) and mac address of the physical machine, and the ironic-inspector service will automatically register this information in the node information.": "此服务将对在对物理机的配置CPU、内存等和 mac 地址进行自动查询, 并且 ironic-inspector 服务会将这些信息自动注册入节点信息中。", "This service will automatically query the configuration (CPU, memory, etc.) and mac address of the physical machine, and the ironic-inspector service will automatically register this information in the node information.": "此服务将对在对物理机的配置CPU、内存等和 mac 地址进行自动查询, 并且 ironic-inspector 服务会将这些信息自动注册入节点信息中。",
"This will delete all child objects of the load balancer.": "这会删除所有LB下的资源", "This will delete all child objects of the load balancer.": "这会删除所有LB下的资源",
"Threads Activity Trends": "", "Threads Activity Trends": "",

View File

@ -15,6 +15,19 @@
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { ModalAction } from 'containers/Action'; import { ModalAction } from 'containers/Action';
import globalSecurityGroupStore from 'stores/neutron/security-group'; import globalSecurityGroupStore from 'stores/neutron/security-group';
import globalProjectStore from 'stores/keystone/project';
const defaultRuleCount = 2;
const getAdd = (groupQuota, ruleQuota) => {
const { left: groupLeft = 0 } = groupQuota || {};
const { left: ruleLeft = 0 } = ruleQuota || {};
const add =
groupLeft !== 0 && (ruleLeft >= defaultRuleCount || ruleLeft === -1)
? 1
: 0;
return add;
};
export class CreateAction extends ModalAction { export class CreateAction extends ModalAction {
static id = 'create'; static id = 'create';
@ -29,6 +42,71 @@ export class CreateAction extends ModalAction {
static allowed = () => Promise.resolve(true); static allowed = () => Promise.resolve(true);
init() {
this.state.groupQuota = {};
this.state.ruleQuota = {};
this.state.quotaLoading = true;
this.projectStore = globalProjectStore;
this.getQuota();
}
static get disableSubmit() {
const {
neutronQuota: { security_group = {}, security_group_rule = {} } = {},
} = globalProjectStore;
const add = getAdd(security_group, security_group_rule);
return add === 0;
}
static get showQuota() {
return true;
}
get showQuota() {
return true;
}
async getQuota() {
const result = await this.projectStore.fetchProjectNeutronQuota();
const {
security_group: groupQuota = {},
security_group_rule: ruleQuota = {},
} = result || {};
this.setState({
groupQuota,
ruleQuota,
quotaLoading: false,
});
}
get tips() {
return t(
'This operation creates a security group with default security group rules for the IPv4 and IPv6 ether types.'
);
}
get quotaInfo() {
const { groupQuota = {}, ruleQuota = {}, quotaLoading } = this.state;
if (quotaLoading) {
return [];
}
const add = getAdd(groupQuota, ruleQuota);
const groupQuotaData = {
...groupQuota,
add,
name: 'security_group',
title: t('Security Group'),
};
const ruleQuotaData = {
...ruleQuota,
add: add * defaultRuleCount,
name: 'security_group_rule',
title: t('Security Group Rule'),
type: 'line',
};
return [groupQuotaData, ruleQuotaData];
}
get defaultValue() { get defaultValue() {
const value = {}; const value = {};
return value; return value;