diff --git a/src/locales/en.json b/src/locales/en.json index ac84bc87..de4c9b22 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2225,6 +2225,7 @@ "The entire inspection process takes 5 to 10 minutes, so you need to be patient. After the registration is completed, the node configuration status will return to the manageable status.": "The entire inspection process takes 5 to 10 minutes, so you need to be patient. After the registration is completed, the node configuration status will return to the manageable status.", "The feasible configuration of cloud-init or cloudbase-init service in the image is not synced to image's properties, so the Login Name is unknown.": "The feasible configuration of cloud-init or cloudbase-init service in the image is not synced to image's properties, so the Login Name is unknown.", "The file with the same name will be overwritten.": "The file with the same name will be overwritten.", + "The floating IP configured with port forwarding rules cannot be bound": "The floating IP configured with port forwarding rules cannot be bound", "The format of the certificate content is: by \"----BEGIN CERTIFICATE-----\" as the beginning,\"-----END CERTIFICATE----\" as the end, 64 characters per line, the last line does not exceed 64 characters, and there cannot be blank lines.": "The format of the certificate content is: by \"----BEGIN CERTIFICATE-----\" as the beginning,\"-----END CERTIFICATE----\" as the end, 64 characters per line, the last line does not exceed 64 characters, and there cannot be blank lines.", "The host name of this container": "The host name of this container", "The http_proxy address to use for nodes in cluster": "The http_proxy address to use for nodes in cluster", diff --git a/src/locales/zh.json b/src/locales/zh.json index 6bb069aa..9afc3ac8 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -2225,6 +2225,7 @@ "The entire inspection process takes 5 to 10 minutes, so you need to be patient. After the registration is completed, the node configuration status will return to the manageable status.": "检查的整个过程需要耗费 5 到 10 分钟时间,您需要耐心等待。在完成注册后,节点配置状态会重新回到可管理状态。", "The feasible configuration of cloud-init or cloudbase-init service in the image is not synced to image's properties, so the Login Name is unknown.": "镜像中的cloud-init或cloudbase-init服务的预制配置未同步至镜像属性, 登录名未知", "The file with the same name will be overwritten.": "对同名文件将会进行文件覆盖操作。", + "The floating IP configured with port forwarding rules cannot be bound": "不允许绑定配置了端口转发规则的浮动IP", "The format of the certificate content is: by \"----BEGIN CERTIFICATE-----\" as the beginning,\"-----END CERTIFICATE----\" as the end, 64 characters per line, the last line does not exceed 64 characters, and there cannot be blank lines.": "证书内容格式为:以”-----BEGIN CERTIFICATE-----”作为开头,以“-----END CERTIFICATE----”作为结尾,每行64字符,最后一行不超过64字符,不能有空行。", "The host name of this container": "容器的主机名", "The http_proxy address to use for nodes in cluster": "用于集群中节点的 http_proxy 地址", diff --git a/src/pages/compute/containers/Instance/actions/AssociateFip.jsx b/src/pages/compute/containers/Instance/actions/AssociateFip.jsx index f1489e14..66dc8f40 100644 --- a/src/pages/compute/containers/Instance/actions/AssociateFip.jsx +++ b/src/pages/compute/containers/Instance/actions/AssociateFip.jsx @@ -21,6 +21,10 @@ import { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/r import { getInterfaceWithReason, handleFixedIPChange, + getFixedIPFormItemForAssociate, + getFIPFormItemForAssociate, + getFIPFormItemExtra, + disableFIPAssociate, } from 'resources/neutron/floatingip'; import { getPortsAndReasons } from 'resources/neutron/port'; @@ -80,8 +84,6 @@ export class AssociateFip extends ModalAction { const { name } = this.item; const value = { instance: name, - snapshot: '', - ipType: 0, }; return value; } @@ -100,12 +102,20 @@ export class AssociateFip extends ModalAction { ); }; - get nameForStateUpdate() { - return ['network', 'ipType']; + getFIPFormItemExtra() { + return getFIPFormItemExtra(); + } + + disableFIPAssociate(record) { + return disableFIPAssociate(record); } get formItems() { - const { canAssociateFloatingIPs, portLoading, fipLoading } = this.state; + const fixedIpFormItem = getFixedIPFormItemForAssociate( + t('Instance IP'), + this + ); + const fipFormItem = getFIPFormItemForAssociate(this); return [ { name: 'instance', @@ -113,71 +123,8 @@ export class AssociateFip extends ModalAction { type: 'label', iconType: 'instance', }, - { - name: 'fixed_ip', - label: t('Instance IP'), - type: 'select-table', - required: true, - data: this.ports, - isLoading: portLoading, - isMulti: false, - filterParams: [ - { - label: t('Ip Address'), - name: 'name', - }, - ], - columns: [ - { - title: t('Ip Address'), - dataIndex: 'name', - }, - { - title: t('Mac Address'), - dataIndex: 'mac_address', - }, - { - title: t('Network'), - dataIndex: 'network_name', - }, - { - title: t('Reason'), - dataIndex: 'reason', - }, - ], - disabledFunc: (record) => !record.available, - onChange: this.handleFixedIPChange, - }, - { - name: 'fip', - label: t('Floating Ip Address'), - type: 'select-table', - required: true, - data: canAssociateFloatingIPs, - isLoading: fipLoading, - isMulti: false, - filterParams: [ - { - label: t('Floating Ip Address'), - name: 'name', - }, - ], - columns: [ - { - title: t('Floating Ip Address'), - dataIndex: 'name', - }, - { - title: t('Network'), - dataIndex: 'network_name', - }, - { - title: t('Created At'), - dataIndex: 'created_at', - valueRender: 'sinceTime', - }, - ], - }, + fixedIpFormItem, + fipFormItem, ]; } diff --git a/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/AssociateFIP.jsx b/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/AssociateFIP.jsx index 1d58e5da..34511ee3 100644 --- a/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/AssociateFIP.jsx +++ b/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/AssociateFIP.jsx @@ -19,6 +19,10 @@ import { getPortsAndReasons } from 'resources/neutron/port'; import { getInterfaceWithReason, handleFixedIPChange, + getFixedIPFormItemForAssociate, + getFIPFormItemForAssociate, + getFIPFormItemExtra, + disableFIPAssociate, } from 'resources/neutron/floatingip'; import { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/router'; @@ -106,8 +110,17 @@ export class AssociateFip extends ModalAction { } }; + getFIPFormItemExtra() { + return getFIPFormItemExtra(); + } + + disableFIPAssociate(record) { + return disableFIPAssociate(record); + } + get formItems() { - const { canAssociateFloatingIPs, portLoading, fipLoading } = this.state; + const fixedIpFormItem = getFixedIPFormItemForAssociate(t('Fixed IP'), this); + const fipFormItem = getFIPFormItemForAssociate(this); return [ { name: 'lb', @@ -115,67 +128,8 @@ export class AssociateFip extends ModalAction { type: 'label', iconType: 'instance', }, - { - name: 'fixed_ip', - label: t('Fixed IP'), - type: 'select-table', - required: true, - data: this.ports, - isLoading: portLoading, - disabledFunc: (record) => !record.available, - onChange: this.handleFixedIPChange, - isMulti: false, - filterParams: [ - { - label: t('Ip Address'), - name: 'name', - }, - ], - columns: [ - { - title: t('Ip Address'), - dataIndex: 'name', - }, - { - title: t('Subnet ID'), - dataIndex: 'subnet_id', - }, - { - title: t('Reason'), - dataIndex: 'reason', - }, - ], - }, - { - name: 'fip', - label: t('Floating Ip Address'), - type: 'select-table', - required: true, - data: canAssociateFloatingIPs, - isLoading: fipLoading, - isMulti: false, - filterParams: [ - { - label: t('Floating Ip Address'), - name: 'name', - }, - ], - columns: [ - { - title: t('Floating Ip Address'), - dataIndex: 'name', - }, - { - title: t('Network'), - dataIndex: 'network_name', - }, - { - title: t('Created At'), - dataIndex: 'created_at', - valueRender: 'sinceTime', - }, - ], - }, + fixedIpFormItem, + fipFormItem, ]; } diff --git a/src/pages/network/containers/VirtualAdapter/actions/AssociateFIP.jsx b/src/pages/network/containers/VirtualAdapter/actions/AssociateFIP.jsx index 338bd81c..3b582dce 100644 --- a/src/pages/network/containers/VirtualAdapter/actions/AssociateFIP.jsx +++ b/src/pages/network/containers/VirtualAdapter/actions/AssociateFIP.jsx @@ -21,6 +21,10 @@ import { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/r import { getInterfaceWithReason, handleFixedIPChange, + getFixedIPFormItemForAssociate, + getFIPFormItemForAssociate, + getFIPFormItemExtra, + disableFIPAssociate, } from 'resources/neutron/floatingip'; export class AssociateFip extends ModalAction { @@ -104,8 +108,17 @@ export class AssociateFip extends ModalAction { }); }; + getFIPFormItemExtra() { + return getFIPFormItemExtra(); + } + + disableFIPAssociate(record) { + return disableFIPAssociate(record); + } + get formItems() { - const { canAssociateFloatingIPs, portLoading, fipLoading } = this.state; + const fixedIpFormItem = getFixedIPFormItemForAssociate(t('Fixed IP'), this); + const fipFormItem = getFIPFormItemForAssociate(this); return [ { name: 'virtualAdapter', @@ -113,67 +126,8 @@ export class AssociateFip extends ModalAction { type: 'label', iconType: 'instance', }, - { - name: 'fixed_ip', - label: t('Fixed IP'), - type: 'select-table', - required: true, - data: this.ports, - isLoading: portLoading, - disabledFunc: (record) => !record.available, - onChange: this.handleFixedIPChange, - isMulti: false, - filterParams: [ - { - label: t('Ip Address'), - name: 'name', - }, - ], - columns: [ - { - title: t('Ip Address'), - dataIndex: 'name', - }, - { - title: t('Subnet ID'), - dataIndex: 'subnet_id', - }, - { - title: t('Reason'), - dataIndex: 'reason', - }, - ], - }, - { - name: 'fip', - label: t('Floating Ip Address'), - type: 'select-table', - required: true, - data: canAssociateFloatingIPs, - isLoading: fipLoading, - isMulti: false, - filterParams: [ - { - label: t('Floating Ip Address'), - name: 'name', - }, - ], - columns: [ - { - title: t('Floating Ip Address'), - dataIndex: 'name', - }, - { - title: t('Network'), - dataIndex: 'network_name', - }, - { - title: t('Created At'), - dataIndex: 'created_at', - valueRender: 'sinceTime', - }, - ], - }, + fixedIpFormItem, + fipFormItem, ]; } } diff --git a/src/resources/neutron/floatingip.js b/src/resources/neutron/floatingip.js index 06abf7dd..b2749186 100644 --- a/src/resources/neutron/floatingip.js +++ b/src/resources/neutron/floatingip.js @@ -16,6 +16,7 @@ import globalPortStore from 'stores/neutron/port'; import globalNetworkStore from 'stores/neutron/network'; import { ipValidate } from 'utils/validate'; import globalFloatingIpsStore from 'stores/neutron/floatingIp'; +import { enablePFW } from 'resources/neutron/neutron'; const { isIPv4 } = ipValidate; @@ -256,3 +257,96 @@ export async function handleFixedIPChange(e) { fipLoading: false, }); } + +export const getFixedIPFormItemForAssociate = (label, self) => { + const { portLoading } = self.state; + return { + name: 'fixed_ip', + label, + type: 'select-table', + required: true, + data: self.ports, + isLoading: portLoading, + isMulti: false, + filterParams: [ + { + label: t('Ip Address'), + name: 'name', + }, + ], + columns: [ + { + title: t('Ip Address'), + dataIndex: 'name', + }, + { + title: t('Mac Address'), + dataIndex: 'mac_address', + }, + { + title: t('Network'), + dataIndex: 'network_name', + }, + { + title: t('Subnet ID'), + dataIndex: 'subnet_id', + }, + { + title: t('Reason'), + dataIndex: 'reason', + }, + ], + disabledFunc: (record) => !record.available, + onChange: self.handleFixedIPChange, + }; +}; + +export const getFIPFormItemExtra = () => { + if (enablePFW()) { + return t( + 'The floating IP configured with port forwarding rules cannot be bound' + ); + } + return ''; +}; + +export const disableFIPAssociate = (record) => { + const pfws = record.port_forwardings || []; + return !!pfws.length; +}; + +export const getFIPFormItemForAssociate = (self) => { + const { canAssociateFloatingIPs, fipLoading } = self.state; + return { + name: 'fip', + label: t('Floating Ip Address'), + type: 'select-table', + required: true, + data: canAssociateFloatingIPs, + isLoading: fipLoading, + isMulti: false, + extra: self.getFIPFormItemExtra(), + disabledFunc: self.disableFIPAssociate, + filterParams: [ + { + label: t('Floating Ip Address'), + name: 'name', + }, + ], + columns: [ + { + title: t('Floating Ip Address'), + dataIndex: 'name', + }, + { + title: t('Network'), + dataIndex: 'network_name', + }, + { + title: t('Created At'), + dataIndex: 'created_at', + valueRender: 'sinceTime', + }, + ], + }; +};