Files
skyline-console/src/pages/container-infra/containers/Clusters/actions/StepCreate/index.jsx
xusongfu 228ccff07b fix: Improve quota in magnum service
1.Show quota info by template when create cluster if did not select flavor or master flavor

2.Remove link of keypair if the keypair is not belong to the current user

Change-Id: Ic6faebfa21b92479b982770a00046a54882f21d8
2022-12-07 15:57:15 +08:00

324 lines
7.9 KiB
JavaScript

// 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 { inject, observer } from 'mobx-react';
import { toJS } from 'mobx';
import { StepAction } from 'src/containers/Action';
import globalClustersStore from 'src/stores/magnum/clusters';
import globalProjectStore from 'stores/keystone/project';
import globalFlavorStore from 'stores/nova/flavor';
import { getGiBValue } from 'utils';
import { message as $message } from 'antd';
import StepInfo from './StepInfo';
import StepNodeSpec from './StepNodeSpec';
import StepNetworks from './StepNetworks';
import StepManagement from './StepManagement';
import StepLabel from './StepLabel';
export class StepCreate extends StepAction {
init() {
this.store = globalClustersStore;
this.projectStore = globalProjectStore;
this.state.quotaLoading = true;
this.getQuota();
this.errorMsg = '';
}
static id = 'create-cluster';
static title = t('Create Cluster');
static path = '/container-infra/clusters/create';
static policy = 'cluster:create';
static allowed() {
return Promise.resolve(true);
}
get name() {
return t('Create Cluster');
}
get listUrl() {
return this.getRoutePath('containerInfraClusters');
}
get hasConfirmStep() {
return false;
}
get steps() {
return [
{
title: t('Cluster Info'),
component: StepInfo,
},
{
title: t('Node Spec'),
component: StepNodeSpec,
},
{
title: t('Network Setting'),
component: StepNetworks,
},
{
title: t('Management'),
component: StepManagement,
},
{
title: t('Additional Labels'),
component: StepLabel,
},
];
}
get enableCinder() {
return this.props.rootStore.checkEndpoint('cinder');
}
get flavors() {
return toJS(globalFlavorStore.list.data) || [];
}
get showQuota() {
return true;
}
async getQuota() {
this.setState({
quotaLoading: true,
});
await Promise.all([
this.projectStore.fetchProjectNovaQuota(),
this.projectStore.fetchProjectMagnumQuota(),
this.enableCinder ? this.projectStore.fetchProjectCinderQuota() : null,
]);
this.setState({
quotaLoading: false,
});
}
get disableNext() {
return !!this.errorMsg;
}
get disableSubmit() {
return !!this.errorMsg;
}
get quotaInfo() {
const { quotaLoading } = this.state;
if (quotaLoading) {
return [];
}
const quotaError = this.checkQuotaInput();
const { magnum_cluster = {} } = toJS(this.projectStore.magnumQuota) || {};
const clusterQuotaInfo = {
...magnum_cluster,
add: quotaError ? 0 : 1,
name: 'cluster',
title: t('Clusters'),
};
const {
instances = {},
cores = {},
ram = {},
} = toJS(this.projectStore.novaQuota) || {};
const instanceQuotaInfo = {
...instances,
add: quotaError ? 0 : 1,
name: 'instance',
title: t('Instance'),
type: 'line',
};
const { newCPU, newRam } = this.getFlavorInput();
const cpuQuotaInfo = {
...cores,
add: quotaError ? 0 : newCPU,
name: 'cpu',
title: t('CPU'),
type: 'line',
};
const ramQuotaInfo = {
...ram,
add: quotaError ? 0 : newRam,
name: 'ram',
title: t('Memory (GiB)'),
type: 'line',
};
const quotaInfo = [
clusterQuotaInfo,
instanceQuotaInfo,
cpuQuotaInfo,
ramQuotaInfo,
];
return quotaInfo;
}
checkInstanceQuota() {
const { quotaLoading } = this.state;
if (quotaLoading) {
return '';
}
const { instances = {} } = this.projectStore.novaQuota || {};
const { left = 0 } = instances;
if (left === 0) {
return this.getQuotaMessage(1, instances, t('Instance'));
}
return '';
}
get templateFlavor() {
const { data = {} } = this.state;
const { clusterTemplate: { selectedRows = [] } = {} } = data;
const { master_flavor_id, flavor_id } = selectedRows[0] || {};
const masterTemplateFlavor = this.flavors.find(
(it) => it.id === master_flavor_id
);
const workTemplateFlavor = this.flavors.find((it) => it.id === flavor_id);
return {
masterTemplateFlavor,
workTemplateFlavor,
};
}
getFlavorInput() {
const { data = {} } = this.state;
const {
flavor: { selectedRows = [] } = {},
node_count = 1,
masterFlavor: { selectedRows: selectedRowsMaster = [] } = {},
master_count = 1,
} = data;
const { vcpus = 0, ram = 0 } =
selectedRows[0] || this.templateFlavor.workTemplateFlavor || {};
const ramGiB = getGiBValue(ram);
const { vcpus: vcpusMaster = 0, ram: ramMaster = 0 } =
selectedRowsMaster[0] || this.templateFlavor.masterTemplateFlavor || {};
const ramGiBMaster = getGiBValue(ramMaster);
const newCPU = vcpus * node_count + vcpusMaster * master_count;
const newRam = ramGiB * node_count + ramGiBMaster * master_count;
return {
newCPU,
newRam,
};
}
checkFlavorQuota() {
const { newCPU, newRam } = this.getFlavorInput();
const { cores = {}, ram = {} } = this.projectStore.novaQuota || {};
const { left = 0 } = cores || {};
const { left: leftRam = 0 } = ram || {};
if (left !== -1 && left < newCPU) {
return this.getQuotaMessage(newCPU, cores, t('CPU'));
}
if (leftRam !== -1 && leftRam < newRam) {
return this.getQuotaMessage(newRam, ram, t('Memory'));
}
return '';
}
checkQuotaInput() {
const instanceMsg = this.checkInstanceQuota();
const flavorMsg = this.checkFlavorQuota();
const error = instanceMsg || flavorMsg;
if (!error) {
this.status = 'success';
this.errorMsg = '';
return '';
}
this.status = 'error';
if (this.errorMsg !== error) {
$message.error(error);
}
this.errorMsg = error;
return error;
}
getQuotaMessage(value, quota, name) {
const { left = 0 } = quota || {};
if (left === -1) {
return '';
}
if (value > left) {
return t(
'Insufficient {name} quota to create resources(left { quota }, input { input }).',
{ name, quota: left, input: value }
);
}
return '';
}
onSubmit = (values) => {
const {
additionalLabels,
clusterTemplate,
keypair,
auto_healing_enabled,
auto_scaling_enabled,
newNetwork,
fixed_network,
flavor,
masterFlavor,
...rest
} = values;
const requestLabels = {};
if (additionalLabels) {
additionalLabels.forEach((item) => {
const labelKey = item.value.key;
const labelValue = item.value.value;
requestLabels[labelKey] = labelValue;
});
}
const data = {
name: values.name,
labels: {
...requestLabels,
auto_healing_enabled: `${!!auto_healing_enabled}`,
auto_scaling_enabled: `${!!auto_scaling_enabled}`,
},
cluster_template_id: clusterTemplate.selectedRowKeys[0],
...rest,
};
if (keypair) {
data.keypair = keypair.selectedRowKeys[0];
}
if (masterFlavor) {
data.master_flavor_id = masterFlavor.selectedRowKeys[0];
}
if (flavor) {
data.flavor_id = flavor.selectedRowKeys[0];
}
if (!newNetwork && fixed_network) {
const { selectedRowKeys = [] } = fixed_network;
data.fixed_network = selectedRowKeys[0];
}
return this.store.create(data);
};
}
export default inject('rootStore')(observer(StepCreate));