diff --git a/src/locales/en.json b/src/locales/en.json
index e96bf061..6885335c 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -915,7 +915,6 @@
"External IP(V4)": "External IP(V4)",
"External IP(V6)": "External IP(V6)",
"External Network": "External Network",
- "External Network ID": "External Network ID",
"External Network Info": "External Network Info",
"External Networks": "External Networks",
"External Port": "External Port",
@@ -945,9 +944,7 @@
"Fixed IP Address": "Fixed IP Address",
"Fixed IPs": "Fixed IPs",
"Fixed Network": "Fixed Network",
- "Fixed Network ID": "Fixed Network ID",
"Fixed Subnet": "Fixed Subnet",
- "Fixed Subnet ID": "Fixed Subnet ID",
"Flavor": "Flavor",
"Flavor Detail": "Flavor Detail",
"Flavor Info": "Flavor Info",
@@ -1425,7 +1422,7 @@
"Martinique": "Martinique",
"Master Count": "Master Count",
"Master Node Addresses": "Master Node Addresses",
- "Master Node Flavor ID": "Master Node Flavor ID",
+ "Master Node Flavor": "Master Node Flavor",
"Master Node LB Enabled": "Master Node LB Enabled",
"Mauritania": "Mauritania",
"Mauritius": "Mauritius",
@@ -1565,7 +1562,7 @@
"Node Addresses": "Node Addresses",
"Node Count": "Node Count",
"Node Driver": "Node Driver",
- "Node Flavor ID": "Node Flavor ID",
+ "Node Flavor": "Node Flavor",
"Node ID/Name": "Node ID/Name",
"Node Info": "Node Info",
"Node Name": "Node Name",
@@ -2505,7 +2502,6 @@
"Usage Type": "Usage Type",
"Usb Controller": "Usb Controller",
"Use Type": "Use Type",
- "Use an Existing Network": "Use an Existing Network",
"Used": "Used",
"Used IPs": "Used IPs",
"Used by tunnel(s): {names}. ID(s): {ids}": "Used by tunnel(s): {names}. ID(s): {ids}",
diff --git a/src/locales/zh.json b/src/locales/zh.json
index 41e8e15e..31d9cdcc 100644
--- a/src/locales/zh.json
+++ b/src/locales/zh.json
@@ -915,7 +915,6 @@
"External IP(V4)": "外网IP(V4)",
"External IP(V6)": "外网IP(V6)",
"External Network": "外部网络",
- "External Network ID": "外部网络ID",
"External Network Info": "外部网络信息",
"External Networks": "外部网络",
"External Port": "源端口",
@@ -945,9 +944,7 @@
"Fixed IP Address": "内网IP地址",
"Fixed IPs": "内网IP",
"Fixed Network": "内网",
- "Fixed Network ID": "内网ID",
"Fixed Subnet": "内网子网",
- "Fixed Subnet ID": "内网子网ID",
"Flavor": "云主机类型",
"Flavor Detail": "云主机类型详情",
"Flavor Info": "配置信息",
@@ -1425,7 +1422,7 @@
"Martinique": "马提尼克岛",
"Master Count": "主数量",
"Master Node Addresses": "主节点地址",
- "Master Node Flavor ID": "主节点类型ID",
+ "Master Node Flavor": "主节点类型",
"Master Node LB Enabled": "启用主节点负载均衡",
"Mauritania": "毛里塔尼亚",
"Mauritius": "毛里求斯",
@@ -1565,7 +1562,7 @@
"Node Addresses": "节点地址",
"Node Count": "节点数量",
"Node Driver": "节点驱动",
- "Node Flavor ID": "节点类型ID",
+ "Node Flavor": "节点类型",
"Node ID/Name": "节点ID/名称",
"Node Info": "节点信息",
"Node Name": "节点名称",
@@ -2505,7 +2502,6 @@
"Usage Type": "使用类型",
"Usb Controller": "USB控制器",
"Use Type": "使用类型",
- "Use an Existing Network": "使用现有网络",
"Used": "已使用",
"Used IPs": "已用IP",
"Used by tunnel(s): {names}. ID(s): {ids}": "被隧道使用中:{names}。 ID:{ids}",
diff --git a/src/pages/container-infra/containers/ClusterTemplates/Detail/BaseDetail.jsx b/src/pages/container-infra/containers/ClusterTemplates/Detail/BaseDetail.jsx
index 898dfb60..3ec41a66 100644
--- a/src/pages/container-infra/containers/ClusterTemplates/Detail/BaseDetail.jsx
+++ b/src/pages/container-infra/containers/ClusterTemplates/Detail/BaseDetail.jsx
@@ -68,17 +68,35 @@ export class BaseDetail extends Base {
}
get networkCard() {
- const { external_network_id, fixed_network } = this.detailData || {};
+ const {
+ external_network_id,
+ externalNetwork: { name: externalName } = {},
+ fixed_network,
+ fixedNetwork: { name: fixedName } = {},
+ fixed_subnet,
+ fixedSubnet: { name: subName } = {},
+ } = this.detailData || {};
const externalNetworkUrl = external_network_id
- ? this.getLinkRender('networkDetail', external_network_id, {
- id: external_network_id,
- })
+ ? this.getLinkRender(
+ 'networkDetail',
+ externalName || external_network_id,
+ {
+ id: external_network_id,
+ }
+ )
: '-';
const fixedNetworkUrl = fixed_network
- ? this.getLinkRender('networkDetail', fixed_network, {
+ ? this.getLinkRender('networkDetail', fixedName || fixed_network, {
id: fixed_network,
})
: '-';
+ const subnetUrl =
+ fixed_network && fixed_subnet
+ ? this.getLinkRender('subnetDetail', subName || fixed_subnet, {
+ networkId: fixed_network,
+ id: fixed_subnet,
+ })
+ : '-';
const options = [
{
@@ -98,16 +116,16 @@ export class BaseDetail extends Base {
dataIndex: 'no_proxy',
},
{
- label: t('External Network ID'),
+ label: t('External Network'),
content: externalNetworkUrl,
},
{
- label: t('Fixed Network ID'),
+ label: t('Fixed Network'),
content: fixedNetworkUrl,
},
{
- label: t('Fixed Subnet ID'),
- dataIndex: 'fixed_subnet',
+ label: t('Fixed Subnet'),
+ content: subnetUrl,
},
{
label: t('DNS'),
@@ -132,10 +150,18 @@ export class BaseDetail extends Base {
}
get specCard() {
- const { image_id, keypair_id, flavor_id, master_flavor_id, selfKeypair } =
- this.detailData;
+ const {
+ image_id,
+ image: { name: imageName } = {},
+ keypair_id,
+ flavor_id,
+ flavor: { name: flavorName } = {},
+ master_flavor_id,
+ masterFlavor: { name: masterFlavorName } = {},
+ selfKeypair,
+ } = this.detailData;
const imageUrl = image_id
- ? this.getLinkRender('imageDetail', image_id, {
+ ? this.getLinkRender('imageDetail', imageName || image_id, {
id: image_id,
})
: '-';
@@ -148,20 +174,24 @@ export class BaseDetail extends Base {
: keypair_id || '-';
const flavorUrl = flavor_id
- ? this.getLinkRender('flavorDetail', flavor_id, {
+ ? this.getLinkRender('flavorDetail', flavorName || flavor_id, {
id: flavor_id,
})
: '-';
const masterFlavorUrl = master_flavor_id
- ? this.getLinkRender('flavorDetail', master_flavor_id, {
- id: master_flavor_id,
- })
+ ? this.getLinkRender(
+ 'flavorDetail',
+ masterFlavorName || master_flavor_id,
+ {
+ id: master_flavor_id,
+ }
+ )
: '-';
const options = [
{
- label: t('Image ID'),
+ label: t('Image'),
content: imageUrl,
},
{
@@ -170,11 +200,11 @@ export class BaseDetail extends Base {
hidden: this.isAdminPage,
},
{
- label: t('Node Flavor ID'),
+ label: t('Node Flavor'),
content: flavorUrl,
},
{
- label: t('Master Node Flavor ID'),
+ label: t('Master Node Flavor'),
content: masterFlavorUrl,
},
{
diff --git a/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNetwork/index.jsx b/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNetwork/index.jsx
index cb5e4cbe..382e14fa 100644
--- a/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNetwork/index.jsx
+++ b/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNetwork/index.jsx
@@ -18,7 +18,7 @@ import { inject, observer } from 'mobx-react';
import { NetworkStore } from 'src/stores/neutron/network';
import { SubnetStore } from 'src/stores/neutron/subnet';
import { getLinkRender } from 'utils/route-map';
-import { networkColumns } from 'resources/neutron/network';
+import { networkColumns, subnetColumns } from 'resources/neutron/network';
export class StepNetwork extends Base {
async init() {
@@ -87,8 +87,11 @@ export class StepNetwork extends Base {
https_proxy,
no_proxy,
external_network_id,
+ externalNetwork,
fixed_network,
+ fixedNetwork,
fixed_subnet,
+ fixedSubnet,
dns_nameserver,
master_lb_enabled,
floating_ip_enabled,
@@ -101,21 +104,22 @@ export class StepNetwork extends Base {
no_proxy,
externalNetwork: {
selectedRowKeys: [external_network_id],
+ selectedRows: [externalNetwork],
},
- fixed_network,
- fixed_subnet,
dns_nameserver,
master_lb_enabled,
floating_ip_enabled,
};
if (fixed_network) {
- values.fixedNetwork = this.props.context.fixedNetwork || {
+ values.fixedNetwork = {
selectedRowKeys: [fixed_network],
+ selectedRows: [fixedNetwork],
};
}
if (fixed_subnet) {
values.fixedSubnet = {
selectedRowKeys: [fixed_subnet],
+ selectedRows: [fixedSubnet],
};
}
}
@@ -201,7 +205,10 @@ export class StepNetwork extends Base {
this.updateContext({
fixedNetwork: value,
});
- this.updateFormValue('fixedSubnet', null);
+ this.updateFormValue('fixedSubnet', {
+ selectedRowKeys: [],
+ selectedRows: [],
+ });
},
},
{
@@ -215,29 +222,7 @@ export class StepNetwork extends Base {
name: 'name',
},
],
- columns: [
- {
- title: t('Name'),
- dataIndex: 'name',
- },
- {
- title: t('CIDR'),
- dataIndex: 'cidr',
- },
- {
- title: t('Gateway IP'),
- dataIndex: 'gateway_ip',
- },
- {
- title: t('IP Version'),
- dataIndex: 'ip_version',
- },
- {
- title: t('Created At'),
- dataIndex: 'created_at',
- valueRender: 'toLocalTime',
- },
- ],
+ columns: subnetColumns,
},
{
name: 'dns_nameserver',
diff --git a/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNodeSpec/index.jsx b/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNodeSpec/index.jsx
index dc224154..76b08078 100644
--- a/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNodeSpec/index.jsx
+++ b/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/StepNodeSpec/index.jsx
@@ -12,21 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import React from 'react';
import { inject, observer } from 'mobx-react';
+import { toJS } from 'mobx';
import Base from 'components/Form';
import { ImageStore } from 'stores/glance/image';
import globalKeypairStore from 'stores/nova/keypair';
-import FlavorSelectTable from 'pages/compute/containers/Instance/components/FlavorSelectTable';
+import { FlavorStore } from 'src/stores/nova/flavor';
import { getImageColumns } from 'resources/glance/image';
import { getKeyPairHeader } from 'resources/nova/keypair';
+import { getBaseSimpleFlavorColumns } from 'resources/magnum/template';
export class StepNodeSpec extends Base {
init() {
this.imageStore = new ImageStore();
this.keyPairStore = globalKeypairStore;
- this.getImageList();
- this.getKeypairs();
+ this.flavorStore = new FlavorStore();
+ this.masterFlavorStore = new FlavorStore();
+ this.getAllInitFunctions();
}
get title() {
@@ -45,19 +47,44 @@ export class StepNodeSpec extends Base {
return !!this.props.extra;
}
- async getImageList() {
- await this.imageStore.fetchList({ all_projects: this.hasAdminRole });
+ async getAllInitFunctions() {
+ await Promise.all([
+ this.getImageList(),
+ this.getKeypairs(),
+ this.getFlavors(),
+ this.getMasterFlavors(),
+ ]);
this.updateDefaultValue();
}
- async getKeypairs() {
- await this.keyPairStore.fetchList();
+ getImageList() {
+ return this.imageStore.fetchList({ all_projects: this.hasAdminRole });
+ }
+
+ getKeypairs() {
+ return this.keyPairStore.fetchList();
}
get keypairs() {
return this.keyPairStore.list.data || [];
}
+ getFlavors() {
+ return this.flavorStore.fetchList();
+ }
+
+ getMasterFlavors() {
+ return this.masterFlavorStore.fetchList();
+ }
+
+ get flavors() {
+ return toJS(this.flavorStore.list.data) || [];
+ }
+
+ get masterFlavors() {
+ return toJS(this.masterFlavorStore.list.data) || [];
+ }
+
get acceptedImageOs() {
const { context: { coe = '' } = {} } = this.props;
let acceptedOs = [];
@@ -93,26 +120,6 @@ export class StepNodeSpec extends Base {
return acceptedVolumeDriver;
}
- getFlavorComponent() {
- return ;
- }
-
- onFlavorChange = (value) => {
- this.updateContext({
- flavor: value,
- });
- };
-
- getMasterFlavorComponent() {
- return ;
- }
-
- onMasterFlavorChange = (value) => {
- this.updateContext({
- masterFlavor: value,
- });
- };
-
get defaultValue() {
let values = {};
@@ -134,10 +141,18 @@ export class StepNodeSpec extends Base {
docker_volume_size,
};
if (flavor_id) {
- values.flavor = { selectedRowKeys: [flavor_id] };
+ values.flavor = {
+ selectedRowKeys: [flavor_id],
+ selectedRows: this.flavors.filter((it) => it.id === flavor_id),
+ };
}
if (master_flavor_id) {
- values.masterFlavor = { selectedRowKeys: [master_flavor_id] };
+ values.masterFlavor = {
+ selectedRowKeys: [master_flavor_id],
+ selectedRows: this.masterFlavors.filter(
+ (it) => it.id === master_flavor_id
+ ),
+ };
}
if (image_id) {
values.images = { selectedRowKeys: [image_id] };
@@ -209,13 +224,29 @@ export class StepNodeSpec extends Base {
name: 'flavor',
label: t('Flavor of Nodes'),
type: 'select-table',
- component: this.getFlavorComponent(),
+ data: this.flavors,
+ columns: getBaseSimpleFlavorColumns(this),
+ isLoading: this.flavorStore.list.isLoading,
+ filterParams: [
+ {
+ label: t('Name'),
+ name: 'name',
+ },
+ ],
},
{
name: 'masterFlavor',
label: t('Flavor of Master Nodes'),
type: 'select-table',
- component: this.getMasterFlavorComponent(),
+ data: this.masterFlavors,
+ columns: getBaseSimpleFlavorColumns(this),
+ isLoading: this.masterFlavorStore.list.isLoading,
+ filterParams: [
+ {
+ label: t('Name'),
+ name: 'name',
+ },
+ ],
},
{
name: 'volume_driver',
diff --git a/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/index.jsx b/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/index.jsx
index f3d5aff5..65e5964f 100644
--- a/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/index.jsx
+++ b/src/pages/container-infra/containers/ClusterTemplates/actions/StepCreate/index.jsx
@@ -117,21 +117,14 @@ export class StepCreate extends StepAction {
...rest,
labels: requestLabels,
external_network_id: externalNetwork.selectedRowKeys[0],
- fixed_network: fixedNetwork ? fixedNetwork.selectedRowKeys[0] : null,
- fixed_subnet: fixedSubnet ? fixedSubnet.selectedRowKeys[0] : null,
+ fixed_network: (fixedNetwork && fixedNetwork.selectedRowKeys[0]) || null,
+ fixed_subnet: (fixedSubnet && fixedSubnet.selectedRowKeys[0]) || null,
+ flavor_id: (flavor && flavor.selectedRowKeys[0]) || null,
+ master_flavor_id:
+ (masterFlavor && masterFlavor.selectedRowKeys[0]) || null,
+ image_id: (images && images.selectedRowKeys[0]) || null,
+ keypair_id: (keypair && keypair.selectedRowKeys[0]) || null,
};
- if (flavor) {
- body.flavor_id = flavor.selectedRowKeys[0];
- }
- if (masterFlavor) {
- body.master_flavor_id = masterFlavor.selectedRowKeys[0];
- }
- if (images) {
- body.image_id = images.selectedRowKeys[0];
- }
- if (keypair) {
- body.keypair_id = keypair.selectedRowKeys[0];
- }
if (this.isEdit) {
return this.store.update({ id: this.params.id }, body);
}
diff --git a/src/pages/container-infra/containers/ClusterTemplates/index.jsx b/src/pages/container-infra/containers/ClusterTemplates/index.jsx
index 6f6b0b47..1ade66ec 100644
--- a/src/pages/container-infra/containers/ClusterTemplates/index.jsx
+++ b/src/pages/container-infra/containers/ClusterTemplates/index.jsx
@@ -19,7 +19,6 @@ import actionConfigs from './actions';
export class ClusterTemplates extends Base {
init() {
this.store = globalClusterTemplateStore;
- this.downloadStore = globalClusterTemplateStore;
}
get name() {
diff --git a/src/pages/container-infra/containers/Clusters/Detail/BaseDetail.jsx b/src/pages/container-infra/containers/Clusters/Detail/BaseDetail.jsx
index 049b5242..fce0cf63 100644
--- a/src/pages/container-infra/containers/Clusters/Detail/BaseDetail.jsx
+++ b/src/pages/container-infra/containers/Clusters/Detail/BaseDetail.jsx
@@ -19,14 +19,14 @@ import React from 'react';
export class BaseDetail extends Base {
get leftCards() {
- return [this.baseInfoCard, this.miscellaneousCard];
+ return [this.templateCard, this.networkCard, this.miscellaneousCard];
}
get rightCards() {
return [this.nodesCard, this.labelCard, this.stackCard];
}
- get baseInfoCard() {
+ get templateCard() {
const { template = {} } = this.detailData;
const templateUrl = template
? this.getLinkRender(
@@ -65,19 +65,45 @@ export class BaseDetail extends Base {
};
}
- get miscellaneousCard() {
- const { master_flavor_id, flavor_id, keypair } = this.detailData;
- const masterFlavorUrl = master_flavor_id
- ? this.getLinkRender('flavorDetail', master_flavor_id, {
- id: master_flavor_id,
+ get networkCard() {
+ const {
+ fixed_network,
+ fixedNetwork: { name: fixedName } = {},
+ fixed_subnet,
+ fixedSubnet: { name: subName } = {},
+ } = this.detailData || {};
+ const fixedNetworkUrl = fixed_network
+ ? this.getLinkRender('networkDetail', fixedName || fixed_network, {
+ id: fixed_network,
})
: '-';
+ const subnetUrl =
+ fixed_network && fixed_subnet
+ ? this.getLinkRender('subnetDetail', subName || fixed_subnet, {
+ networkId: fixed_network,
+ id: fixed_subnet,
+ })
+ : '-';
- const flavorUrl = flavor_id
- ? this.getLinkRender('flavorDetail', flavor_id, {
- id: flavor_id,
- })
- : '-';
+ const options = [
+ {
+ label: t('Fixed Network'),
+ content: fixedNetworkUrl,
+ },
+ {
+ label: t('Fixed Subnet'),
+ content: subnetUrl,
+ },
+ ];
+
+ return {
+ title: t('Network'),
+ options,
+ };
+ }
+
+ get miscellaneousCard() {
+ const { keypair } = this.detailData;
const keypairUrl = keypair
? this.getLinkRender('keypairDetail', keypair, {
@@ -111,14 +137,6 @@ export class BaseDetail extends Base {
label: t('Docker Volume Size (GiB)'),
dataIndex: 'docker_volume_size',
},
- {
- label: t('Master Node Flavor ID'),
- content: masterFlavorUrl,
- },
- {
- label: t('Node Flavor ID'),
- content: flavorUrl,
- },
{
label: t('COE Version'),
dataIndex: 'coe_version',
@@ -132,15 +150,48 @@ export class BaseDetail extends Base {
return {
title: t('Miscellaneous'),
options,
+ labelCol: 12,
+ contentCol: 12,
};
}
get nodesCard() {
+ const {
+ master_flavor_id,
+ masterFlavor: { name: masterFlavorName } = {},
+ flavor_id,
+ flavor: { name: flavorName } = {},
+ } = this.detailData;
+
+ const masterFlavorUrl = master_flavor_id
+ ? this.getLinkRender(
+ 'flavorDetail',
+ masterFlavorName || master_flavor_id,
+ {
+ id: master_flavor_id,
+ }
+ )
+ : '-';
+
+ const flavorUrl = flavor_id
+ ? this.getLinkRender('flavorDetail', flavorName || flavor_id, {
+ id: flavor_id,
+ })
+ : '-';
+
const options = [
+ {
+ label: t('Master Node Flavor'),
+ content: masterFlavorUrl,
+ },
{
label: t('Master Count'),
dataIndex: 'master_count',
},
+ {
+ label: t('Node Flavor'),
+ content: flavorUrl,
+ },
{
label: t('Node Count'),
dataIndex: 'node_count',
diff --git a/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNetworks/index.jsx b/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNetworks/index.jsx
index 66e0ccaf..3bb5566d 100644
--- a/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNetworks/index.jsx
+++ b/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNetworks/index.jsx
@@ -12,11 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import React from 'react';
import Base from 'components/Form';
+import { toJS } from 'mobx';
import { inject, observer } from 'mobx-react';
import { defaultTip } from 'resources/magnum/cluster';
+import { NetworkStore } from 'stores/neutron/network';
+import { SubnetStore } from 'src/stores/neutron/subnet';
+import { networkColumns, subnetColumns } from 'resources/neutron/network';
+import { getLinkRender } from 'utils/route-map';
export class StepNetworks extends Base {
+ init() {
+ this.networkStore = new NetworkStore();
+ this.subnetStore = new SubnetStore();
+ this.getAllInitFunctions();
+ }
+
get title() {
return t('Cluster Network');
}
@@ -27,9 +39,62 @@ export class StepNetworks extends Base {
allowed = () => Promise.resolve();
+ async getAllInitFunctions() {
+ const {
+ context: { clusterTemplate = {} },
+ } = this.props;
+ const { selectedRows = [] } = clusterTemplate;
+ const { fixed_network, fixed_subnet } = selectedRows[0] || {};
+ await Promise.all([
+ fixed_network
+ ? this.networkStore.fetchDetail({ id: fixed_network })
+ : null,
+ fixed_subnet ? this.subnetStore.fetchDetail({ id: fixed_subnet }) : null,
+ this.subnetStore.fetchList(),
+ ]);
+ this.updateDefaultValue();
+ }
+
+ get network() {
+ return toJS(this.networkStore.detail) || {};
+ }
+
+ get subnet() {
+ return toJS(this.subnetStore.detail) || {};
+ }
+
+ get subnetList() {
+ const {
+ context: {
+ clusterTemplate: { selectedRows: templateRows = [] } = {},
+ fixedNetwork: { selectedRowKeys: contextKeys = [] } = {},
+ },
+ } = this.props;
+ const { fixed_network } = templateRows[0] || {};
+ const key = contextKeys[0] || fixed_network;
+
+ return (this.subnetStore.list.data || []).filter(
+ (it) => key === it.network_id
+ );
+ }
+
get defaultValue() {
+ const {
+ context: { clusterTemplate = {}, fixedNetwork, fixedSubnet } = {},
+ } = this.props;
+ const { selectedRows = [] } = clusterTemplate;
+ const { fixed_network, fixed_subnet } = selectedRows[0] || {};
+
return {
newNetwork: true,
+ fixedNetwork: fixedNetwork || {
+ selectedRowKeys: fixed_network ? [fixed_network] : [],
+ selectedRows: fixed_network ? [this.network] : [],
+ },
+ fixedSubnet: fixedSubnet || {
+ selectedRowKeys: fixed_subnet ? [fixed_subnet] : [],
+ selectedRows: fixed_subnet ? [this.subnet] : [],
+ },
};
}
@@ -40,6 +105,21 @@ export class StepNetworks extends Base {
get formItems() {
const { newNetwork } = this.state;
+ const {
+ context: { clusterTemplate = {}, fixedNetwork, fixedSubnet } = {},
+ } = this.props;
+ const { selectedRows = [] } = clusterTemplate;
+ const { fixed_network, fixed_subnet } = selectedRows[0] || {};
+
+ const initFixedNetwork = fixedNetwork || {
+ selectedRowKeys: fixed_network ? [fixed_network] : [],
+ selectedRows: fixed_network ? [this.network] : [],
+ };
+ const initSubnet = fixedSubnet || {
+ selectedRowKeys: fixed_subnet ? [fixed_subnet] : [],
+ selectedRows: fixed_subnet ? [this.subnet] : [],
+ };
+
return [
{
name: 'master_lb_enabled',
@@ -55,10 +135,59 @@ export class StepNetworks extends Base {
content: t('Create New Network'),
},
{
- name: 'fixed_network',
- label: t('Use an Existing Network'),
- type: 'network-select-table',
+ name: 'fixedNetwork',
+ label: t('Fixed Network'),
+ type: 'select-table',
hidden: newNetwork,
+ backendPageStore: this.networkStore,
+ extraParams: {
+ 'router:external': false,
+ project_id: this.currentProjectId,
+ },
+ loading: this.networkStore.list.isLoading,
+ header: (
+
+ {t(' You can go to the console to ')}
+ {getLinkRender({
+ key: 'network',
+ value: `${t('create a new network/subnet')} > `,
+ })}
+
+ ),
+ filterParams: [
+ {
+ label: t('Name'),
+ name: 'name',
+ },
+ ],
+ columns: networkColumns(this),
+ onChange: (value) => {
+ this.updateContext({
+ fixedNetwork: value,
+ });
+ this.updateContext({
+ fixedSubnet: {
+ selectedRowKeys: [],
+ selectedRows: [],
+ },
+ });
+ },
+ initValue: initFixedNetwork,
+ },
+ {
+ name: 'fixedSubnet',
+ label: t('Fixed Subnet'),
+ type: 'select-table',
+ hidden: newNetwork,
+ data: this.subnetList,
+ filterParams: [
+ {
+ label: t('Name'),
+ name: 'name',
+ },
+ ],
+ columns: subnetColumns,
+ initValue: initSubnet,
},
{
type: 'divider',
diff --git a/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNodeSpec/index.jsx b/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNodeSpec/index.jsx
index 6f189437..aab20223 100644
--- a/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNodeSpec/index.jsx
+++ b/src/pages/container-infra/containers/Clusters/actions/StepCreate/StepNodeSpec/index.jsx
@@ -12,18 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import React from 'react';
import { inject, observer } from 'mobx-react';
+import { toJS } from 'mobx';
import Base from 'components/Form';
-import FlavorSelectTable from 'src/pages/compute/containers/Instance/components/FlavorSelectTable';
import globalKeypairStore from 'stores/nova/keypair';
+import { FlavorStore } from 'src/stores/nova/flavor';
import { defaultTip } from 'resources/magnum/cluster';
import { getKeyPairHeader } from 'resources/nova/keypair';
+import { getBaseSimpleFlavorColumns } from 'resources/magnum/template';
export class StepNodeSpec extends Base {
init() {
this.keyPairStore = globalKeypairStore;
- this.getKeypairs();
+ this.flavorStore = new FlavorStore();
+ this.masterFlavorStore = new FlavorStore();
+ this.getAllInitFunctions();
}
get title() {
@@ -36,58 +39,90 @@ export class StepNodeSpec extends Base {
allowed = () => Promise.resolve();
- async getKeypairs() {
- await this.keyPairStore.fetchList();
+ async getAllInitFunctions() {
+ await Promise.all([
+ this.getKeypairs(),
+ this.getFlavors(),
+ this.getMasterFlavors(),
+ ]);
+ this.updateDefaultValue();
+ }
+
+ getKeypairs() {
+ return this.keyPairStore.fetchList();
}
get keypairs() {
return this.keyPairStore.list.data || [];
}
- getFlavorComponent() {
- return ;
+ getFlavors() {
+ return this.flavorStore.fetchList();
}
- onFlavorChange = (value) => {
- this.updateContext({
- flavor: value,
- });
- };
-
- getMasterFlavorComponent() {
- return ;
+ getMasterFlavors() {
+ return this.masterFlavorStore.fetchList();
}
- onMasterFlavorChange = (value) => {
- this.updateContext({
- masterFlavor: value,
- });
- };
+ get flavors() {
+ return toJS(this.flavorStore.list.data) || [];
+ }
+
+ get masterFlavors() {
+ return toJS(this.masterFlavorStore.list.data) || [];
+ }
get defaultValue() {
- const { context: { clusterTemplate = {} } = {} } = this.props;
+ const {
+ context: { clusterTemplate = {}, keypair, masterFlavor, flavor } = {},
+ } = this.props;
const { selectedRows = [] } = clusterTemplate;
- const { master_flavor_id, flavor_id } = selectedRows[0] || {};
+ const { master_flavor_id, flavor_id, keypair_id, selfKeypair } =
+ selectedRows[0] || {};
return {
master_count: 1,
node_count: 1,
- masterFlavor: {
- selectedRowKeys: [master_flavor_id],
+ masterFlavor: masterFlavor || {
+ selectedRowKeys: master_flavor_id ? [master_flavor_id] : [],
+ selectedRows: this.masterFlavors.filter(
+ (it) => it.id === master_flavor_id
+ ),
+ },
+ flavor: flavor || {
+ selectedRowKeys: flavor_id ? [flavor_id] : [],
+ selectedRows: this.flavors.filter((it) => it.id === flavor_id),
+ },
+ keypair: keypair || {
+ selectedRowKeys: keypair_id && selfKeypair ? [keypair_id] : [],
+ selectedRows: this.keypairs.filter((it) => it.id === keypair_id),
},
- flavor: { selectedRowKeys: [flavor_id] },
};
}
get formItems() {
- const { context: { clusterTemplate = {}, keypair } = {} } = this.props;
+ const {
+ context: { clusterTemplate = {}, keypair, masterFlavor, flavor } = {},
+ } = this.props;
const { selectedRows = [] } = clusterTemplate;
const { master_flavor_id, flavor_id, keypair_id, selfKeypair } =
selectedRows[0] || {};
const { initKeyPair = keypair } = this.state;
const templateHasSelfKeypair = keypair_id && selfKeypair;
const templateInitKeypair = {
- selectedRowKeys: [keypair_id],
+ selectedRowKeys: keypair_id && selfKeypair ? [keypair_id] : [],
+ selectedRows: this.keypairs.filter((it) => it.id === keypair_id),
+ };
+
+ const initFlavor = flavor || {
+ selectedRowKeys: flavor_id ? [flavor_id] : [],
+ selectedRows: this.flavors.filter((it) => it.id === flavor_id),
+ };
+ const initMasterFlavor = masterFlavor || {
+ selectedRowKeys: master_flavor_id ? [master_flavor_id] : [],
+ selectedRows: this.masterFlavors.filter(
+ (it) => it.id === master_flavor_id
+ ),
};
return [
@@ -95,7 +130,7 @@ export class StepNodeSpec extends Base {
name: 'keypair',
label: t('Keypair'),
type: 'select-table',
- required: !templateHasSelfKeypair,
+ required: true,
data: this.keypairs,
initValue:
initKeyPair || (templateHasSelfKeypair && templateInitKeypair),
@@ -137,9 +172,23 @@ export class StepNodeSpec extends Base {
name: 'masterFlavor',
label: t('Flavor of Master Nodes'),
type: 'select-table',
- component: this.getMasterFlavorComponent(),
- required: !master_flavor_id,
+ required: true,
tip: defaultTip,
+ data: this.masterFlavors,
+ initValue: initMasterFlavor,
+ columns: getBaseSimpleFlavorColumns(this),
+ isLoading: this.masterFlavorStore.list.isLoading,
+ filterParams: [
+ {
+ label: t('Name'),
+ name: 'name',
+ },
+ ],
+ onChange: (value) => {
+ this.updateContext({
+ masterFlavor: value,
+ });
+ },
},
{
type: 'divider',
@@ -160,9 +209,23 @@ export class StepNodeSpec extends Base {
name: 'flavor',
label: t('Flavor of Nodes'),
type: 'select-table',
- component: this.getFlavorComponent(),
- required: !flavor_id,
+ required: true,
tip: defaultTip,
+ data: this.flavors,
+ initValue: initFlavor,
+ columns: getBaseSimpleFlavorColumns(this),
+ isLoading: this.flavorStore.list.isLoading,
+ filterParams: [
+ {
+ label: t('Name'),
+ name: 'name',
+ },
+ ],
+ onChange: (value) => {
+ this.updateContext({
+ flavor: value,
+ });
+ },
},
];
}
diff --git a/src/pages/container-infra/containers/Clusters/actions/StepCreate/index.jsx b/src/pages/container-infra/containers/Clusters/actions/StepCreate/index.jsx
index 590e27ea..85543260 100644
--- a/src/pages/container-infra/containers/Clusters/actions/StepCreate/index.jsx
+++ b/src/pages/container-infra/containers/Clusters/actions/StepCreate/index.jsx
@@ -171,6 +171,19 @@ export class StepCreate extends StepAction {
return quotaInfo;
}
+ checkClusterQuota() {
+ const { quotaLoading } = this.state;
+ if (quotaLoading) {
+ return '';
+ }
+ const { magnum_cluster = {} } = toJS(this.projectStore.magnumQuota) || {};
+ const { left = 0 } = magnum_cluster;
+ if (left === 0) {
+ return this.getQuotaMessage(1, magnum_cluster, t('Clusters'));
+ }
+ return '';
+ }
+
checkInstanceQuota() {
const { quotaLoading } = this.state;
if (quotaLoading) {
@@ -235,9 +248,10 @@ export class StepCreate extends StepAction {
}
checkQuotaInput() {
+ const clusterMsg = this.checkClusterQuota();
const instanceMsg = this.checkInstanceQuota();
const flavorMsg = this.checkFlavorQuota();
- const error = instanceMsg || flavorMsg;
+ const error = clusterMsg || instanceMsg || flavorMsg;
if (!error) {
this.status = 'success';
this.errorMsg = '';
@@ -273,7 +287,8 @@ export class StepCreate extends StepAction {
auto_healing_enabled,
auto_scaling_enabled,
newNetwork,
- fixed_network,
+ fixedNetwork,
+ fixedSubnet,
flavor,
masterFlavor,
...rest
@@ -311,11 +326,16 @@ export class StepCreate extends StepAction {
data.flavor_id = flavor.selectedRowKeys[0];
}
- if (!newNetwork && fixed_network) {
- const { selectedRowKeys = [] } = fixed_network;
+ if (!newNetwork && fixedNetwork) {
+ const { selectedRowKeys = [] } = fixedNetwork;
data.fixed_network = selectedRowKeys[0];
}
+ if (!newNetwork && fixedSubnet) {
+ const { selectedRowKeys = [] } = fixedSubnet;
+ data.fixed_subnet = selectedRowKeys[0];
+ }
+
return this.store.create(data);
};
}
diff --git a/src/pages/container-infra/containers/Clusters/index.jsx b/src/pages/container-infra/containers/Clusters/index.jsx
index ef0511f9..aef0f85b 100644
--- a/src/pages/container-infra/containers/Clusters/index.jsx
+++ b/src/pages/container-infra/containers/Clusters/index.jsx
@@ -22,7 +22,6 @@ import actionConfigs from './actions';
export class Clusters extends Base {
init() {
this.store = globalClustersStore;
- this.downloadStore = globalClustersStore;
}
get name() {
diff --git a/src/resources/magnum/template.js b/src/resources/magnum/template.js
index 60788d4d..d63d629c 100644
--- a/src/resources/magnum/template.js
+++ b/src/resources/magnum/template.js
@@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import { flavorArchitectures, flavorCategoryList } from 'resources/nova/flavor';
+import { formatSize } from 'utils';
+
export const getBaseTemplateColumns = (self) => [
{
title: t('ID/Name'),
@@ -41,3 +44,32 @@ export const getBaseTemplateColumns = (self) => [
},
},
];
+
+export const getBaseSimpleFlavorColumns = (self) => [
+ {
+ title: t('ID/Name'),
+ dataIndex: 'name',
+ routeName: self ? self.getRouteName('flavorDetail') : '',
+ },
+ {
+ title: t('Architecture'),
+ dataIndex: 'architecture',
+ valueMap: flavorArchitectures,
+ },
+ {
+ title: t('Category'),
+ dataIndex: 'category',
+ render: (value) => flavorCategoryList[value] || value || '-',
+ },
+ {
+ title: t('CPU'),
+ dataIndex: 'vcpus',
+ isHideable: true,
+ },
+ {
+ title: t('Memory'),
+ dataIndex: 'ram',
+ isHideable: true,
+ render: (ram) => formatSize(ram, 2),
+ },
+];
diff --git a/src/resources/neutron/network.jsx b/src/resources/neutron/network.jsx
index 51b04a37..a85330b8 100644
--- a/src/resources/neutron/network.jsx
+++ b/src/resources/neutron/network.jsx
@@ -111,3 +111,27 @@ export const isExternalNetwork = (network) => !!network['router:external'];
export const subnetIpv6Tip = t(
'Default is slaac, for details, see https://docs.openstack.org/neutron/latest/admin/config-ipv6.html'
);
+
+export const subnetColumns = [
+ {
+ title: t('Name'),
+ dataIndex: 'name',
+ },
+ {
+ title: t('CIDR'),
+ dataIndex: 'cidr',
+ },
+ {
+ title: t('Gateway IP'),
+ dataIndex: 'gateway_ip',
+ },
+ {
+ title: t('IP Version'),
+ dataIndex: 'ip_version',
+ },
+ {
+ title: t('Created At'),
+ dataIndex: 'created_at',
+ valueRender: 'toLocalTime',
+ },
+];
diff --git a/src/stores/magnum/clusterTemplates.js b/src/stores/magnum/clusterTemplates.js
index 700923a8..08487631 100644
--- a/src/stores/magnum/clusterTemplates.js
+++ b/src/stores/magnum/clusterTemplates.js
@@ -22,6 +22,22 @@ export class ClusterTemplatesStore extends Base {
return client.magnum.clusterTemplates;
}
+ get flavorClient() {
+ return client.nova.flavors;
+ }
+
+ get networkClient() {
+ return client.neutron.networks;
+ }
+
+ get subnetClient() {
+ return client.neutron.subnets;
+ }
+
+ get imageClient() {
+ return client.glance.images;
+ }
+
@action
async create(newbody) {
return this.submitting(this.client.create(newbody));
@@ -75,11 +91,48 @@ export class ClusterTemplatesStore extends Base {
}
async detailDidFetch(item) {
- const { keypairs = [] } = (await client.nova.keypairs.list()) || {};
+ const [kp = {}, fr = {}, mfr = {}, ext = {}, fx = {}, sub = {}, img] =
+ await Promise.all([
+ client.nova.keypairs.list(),
+ item.flavor_id ? this.flavorClient.show(item.flavor_id) : {},
+ item.master_flavor_id
+ ? this.flavorClient.show(item.master_flavor_id)
+ : {},
+ item.external_network_id
+ ? this.networkClient.show(item.external_network_id)
+ : {},
+ item.fixed_network ? this.networkClient.show(item.fixed_network) : {},
+ item.fixed_subnet ? this.subnetClient.show(item.fixed_subnet) : {},
+ item.image_id ? this.imageClient.show(item.image_id) : {},
+ ]);
+ const { keypairs = [] } = kp;
+ const { flavor } = fr;
+ const { flavor: masterFlavor } = mfr;
+ const { network } = ext;
+ const { network: fixedNetwork } = fx;
+ const { subnet: fixedSubnet } = sub;
const keypair = keypairs.find((k) => k?.keypair?.name === item.keypair_id);
if (keypair) {
item.selfKeypair = true;
}
+ if (flavor) {
+ item.flavor = flavor;
+ }
+ if (masterFlavor) {
+ item.masterFlavor = masterFlavor;
+ }
+ if (network) {
+ item.externalNetwork = network;
+ }
+ if (fixedNetwork) {
+ item.fixedNetwork = fixedNetwork;
+ }
+ if (fixedSubnet) {
+ item.fixedSubnet = fixedSubnet;
+ }
+ if (img) {
+ item.image = img;
+ }
return item;
}
}
diff --git a/src/stores/magnum/clusters.js b/src/stores/magnum/clusters.js
index aed93580..b3f0838b 100644
--- a/src/stores/magnum/clusters.js
+++ b/src/stores/magnum/clusters.js
@@ -25,6 +25,18 @@ export class ClustersStore extends Base {
return client.magnum.clusterTemplates;
}
+ get flavorClient() {
+ return client.nova.flavors;
+ }
+
+ get networkClient() {
+ return client.neutron.networks;
+ }
+
+ get subnetClient() {
+ return client.neutron.subnets;
+ }
+
get listWithDetail() {
return true;
}
@@ -45,9 +57,41 @@ export class ClustersStore extends Base {
}
async detailDidFetch(item) {
- const { cluster_template_id } = item || {};
- const template = await this.templateClient.show(cluster_template_id);
+ const template =
+ (await this.templateClient.show(item.cluster_template_id)) || {};
item.template = template;
+ const {
+ flavor_id: templateFlavorId,
+ master_flavor_id: templateMasterFlavorId,
+ fixed_network: templateFixedNetworkId,
+ fixed_subnet: templateSubnetId,
+ } = template;
+ const flavorId = item.flavor_id || templateFlavorId;
+ const masterFlavorId = item.master_flavor_id || templateMasterFlavorId;
+ const fixedNetworkId = item.fixed_network || templateFixedNetworkId;
+ const fixedSubnetId = item.fixed_subnet || templateSubnetId;
+ const [fr = {}, mfr = {}, fx = {}, sub = {}] = await Promise.all([
+ flavorId ? this.flavorClient.show(flavorId) : {},
+ masterFlavorId ? this.flavorClient.show(masterFlavorId) : {},
+ fixedNetworkId ? this.networkClient.show(fixedNetworkId) : {},
+ fixedSubnetId ? this.subnetClient.show(fixedSubnetId) : {},
+ ]);
+ const { flavor } = fr;
+ const { flavor: masterFlavor } = mfr;
+ const { network: fixedNetwork } = fx;
+ const { subnet: fixedSubnet } = sub;
+ if (flavor) {
+ item.flavor = flavor;
+ }
+ if (masterFlavor) {
+ item.masterFlavor = masterFlavor;
+ }
+ if (fixedNetwork) {
+ item.fixedNetwork = fixedNetwork;
+ }
+ if (fixedSubnet) {
+ item.fixedSubnet = fixedSubnet;
+ }
return item;
}