Merge "feature: Add allocation pools validate rules"

This commit is contained in:
Zuul 2021-09-02 10:39:47 +00:00 committed by Gerrit Code Review
commit 88ac78a8db
5 changed files with 152 additions and 15 deletions

View File

@ -685,6 +685,7 @@
"GRE": "GRE", "GRE": "GRE",
"Gateway IP": "Gateway IP", "Gateway IP": "Gateway IP",
"Gateway Time-out (code: 504) ": "Gateway Time-out (code: 504) ", "Gateway Time-out (code: 504) ": "Gateway Time-out (code: 504) ",
"Gateway ip {gateway_ip} conflicts with allocation pool {pool}": "Gateway ip {gateway_ip} conflicts with allocation pool {pool}",
"General Computing Type": "General Computing Type", "General Computing Type": "General Computing Type",
"General Purpose": "General Purpose", "General Purpose": "General Purpose",
"Get OpenRC file": "Get OpenRC file", "Get OpenRC file": "Get OpenRC file",
@ -1090,6 +1091,7 @@
"Other Protocol": "Other Protocol", "Other Protocol": "Other Protocol",
"Others": "Others", "Others": "Others",
"Outputs": "Outputs", "Outputs": "Outputs",
"Overlapping allocation pools: {pools}": "Overlapping allocation pools: {pools}",
"Owned Network": "Owned Network", "Owned Network": "Owned Network",
"Owned Network ID": "Owned Network ID", "Owned Network ID": "Owned Network ID",
"Owned Project": "Owned Project", "Owned Project": "Owned Project",

View File

@ -685,6 +685,7 @@
"GRE": "", "GRE": "",
"Gateway IP": "网关IP", "Gateway IP": "网关IP",
"Gateway Time-out (code: 504) ": "网关超时错误码504 ", "Gateway Time-out (code: 504) ": "网关超时错误码504 ",
"Gateway ip {gateway_ip} conflicts with allocation pool {pool}": "网关地址 {gateway_ip} 和分配地址池 {pool} 冲突",
"General Computing Type": "通用计算型", "General Computing Type": "通用计算型",
"General Purpose": "通用型", "General Purpose": "通用型",
"Get OpenRC file": "获取Openstack RC 文件", "Get OpenRC file": "获取Openstack RC 文件",
@ -1090,6 +1091,7 @@
"Other Protocol": "其他协议", "Other Protocol": "其他协议",
"Others": "其他", "Others": "其他",
"Outputs": "输出", "Outputs": "输出",
"Overlapping allocation pools: {pools}": "重叠的分配地址池: {pools}",
"Owned Network": "所属网络", "Owned Network": "所属网络",
"Owned Network ID": "所属网络ID", "Owned Network ID": "所属网络ID",
"Owned Project": "所属项目", "Owned Project": "所属项目",

View File

@ -27,8 +27,7 @@ const {
physicalNetworkArray, physicalNetworkArray,
segmentationNetworkArray, segmentationNetworkArray,
segmentationNetworkRequireArray, segmentationNetworkRequireArray,
checkAllocation_pools, validateAllocationPoolsWithGatewayIp,
checkIpv6Allocation_pools,
checkDNS, checkDNS,
checkIpv6DNS, checkIpv6DNS,
checkHostRoutes, checkHostRoutes,
@ -230,6 +229,10 @@ export default class CreateNetwork extends ModalAction {
return true; return true;
}; };
validateAllocationPools = (rule, value) => {
return validateAllocationPoolsWithGatewayIp.call(this, rule, value);
};
get formItems() { get formItems() {
const { const {
more, more,
@ -482,6 +485,11 @@ export default class CreateNetwork extends ModalAction {
name: 'gateway_ip', name: 'gateway_ip',
label: t('Gateway IP'), label: t('Gateway IP'),
type: 'ip-input', type: 'ip-input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t( tip: t(
'If no gateway is specified, the first IP address will be defaulted.' 'If no gateway is specified, the first IP address will be defaulted.'
), ),
@ -491,6 +499,11 @@ export default class CreateNetwork extends ModalAction {
name: 'gateway_ip', name: 'gateway_ip',
label: t('Gateway IP'), label: t('Gateway IP'),
type: 'input', type: 'input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t( tip: t(
'If no gateway is specified, the first IP address will be defaulted.' 'If no gateway is specified, the first IP address will be defaulted.'
), ),
@ -532,7 +545,8 @@ export default class CreateNetwork extends ModalAction {
ip: isIpv4 ? '192.168.1.2,192.168.1.200' : '1001:1001::,1001:1002::', ip: isIpv4 ? '192.168.1.2,192.168.1.200' : '1001:1001::,1001:1002::',
}), }),
hidden: !(create_subnet && more), hidden: !(create_subnet && more),
validator: isIpv4 ? checkAllocation_pools : checkIpv6Allocation_pools, validator: this.validateAllocationPools,
dependencies: ['gateway_ip'],
}, },
{ {
name: 'dns', name: 'dns',

View File

@ -23,8 +23,7 @@ import globalRootStore from 'stores/root';
import networkUtil from './networkUtil'; import networkUtil from './networkUtil';
const { const {
checkAllocation_pools, validateAllocationPoolsWithGatewayIp,
checkIpv6Allocation_pools,
checkDNS, checkDNS,
checkIpv6DNS, checkIpv6DNS,
checkHostRoutes, checkHostRoutes,
@ -125,6 +124,10 @@ export default class CreateSubnet extends ModalAction {
return checkPolicyRule('skyline:system_admin'); return checkPolicyRule('skyline:system_admin');
} }
validateAllocationPools = (rule, value) => {
return validateAllocationPoolsWithGatewayIp.call(this, rule, value);
};
get formItems() { get formItems() {
const { more, ip_version = 'ipv4', disable_gateway = false } = this.state; const { more, ip_version = 'ipv4', disable_gateway = false } = this.state;
const isIpv4 = ip_version === 'ipv4'; const isIpv4 = ip_version === 'ipv4';
@ -230,6 +233,11 @@ export default class CreateSubnet extends ModalAction {
name: 'gateway_ip', name: 'gateway_ip',
label: t('Gateway IP'), label: t('Gateway IP'),
type: 'ip-input', type: 'ip-input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t( tip: t(
'If no gateway is specified, the first IP address will be defaulted.' 'If no gateway is specified, the first IP address will be defaulted.'
), ),
@ -239,6 +247,11 @@ export default class CreateSubnet extends ModalAction {
name: 'gateway_ip', name: 'gateway_ip',
label: t('Gateway IP'), label: t('Gateway IP'),
type: 'input', type: 'input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t( tip: t(
'If no gateway is specified, the first IP address will be defaulted.' 'If no gateway is specified, the first IP address will be defaulted.'
), ),
@ -275,7 +288,7 @@ export default class CreateSubnet extends ModalAction {
ip: isIpv4 ? '192.168.1.2,192.168.1.200' : '1001:1001::,1001:1002::', ip: isIpv4 ? '192.168.1.2,192.168.1.200' : '1001:1001::,1001:1002::',
}), }),
hidden: !more, hidden: !more,
validator: isIpv4 ? checkAllocation_pools : checkIpv6Allocation_pools, validator: this.validateAllocationPools,
}, },
{ {
name: 'dns', name: 'dns',

View File

@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _, { isString } from 'lodash'; import { isString } from 'lodash';
import { ipValidate } from 'utils/validate'; import { ipValidate } from 'utils/validate';
import { Address4, Address6 } from 'ip-address';
const { ipFull, isIpCidr, isIPv6Cidr, isIPv4, isIpv6, compareIpv6 } = const { ipFull, isIpCidr, isIPv6Cidr, isIPv4, isIpv6, compareIpv6 } =
ipValidate; ipValidate;
@ -25,7 +26,7 @@ const segmentationNetworkArray = ['vxlan', 'vlan', 'gre'];
const segmentationNetworkRequireArray = ['vlan', 'gre']; const segmentationNetworkRequireArray = ['vlan', 'gre'];
const checkAllocation_pools = (rule, value) => { const checkAllocation_pools = (rule, value) => {
if (value && _.isString(value)) { if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g); const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError); const flag = !lines.some(hasError);
return flag return flag
@ -53,7 +54,7 @@ const checkAllocation_pools = (rule, value) => {
}; };
const checkIpv6Allocation_pools = (rule, value) => { const checkIpv6Allocation_pools = (rule, value) => {
if (value && _.isString(value)) { if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g); const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError); const flag = !lines.some(hasError);
return flag return flag
@ -81,8 +82,112 @@ const checkIpv6Allocation_pools = (rule, value) => {
} }
}; };
function validateAllocationPoolsWithGatewayIp(rule, value) {
const { ip_version = 'ipv4', gateway_ip } = this.state;
const isIpv4 = ip_version === 'ipv4';
const IPAddressConstructor = isIpv4 ? Address4 : Address6;
let translateIPSuccess = true;
if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const sortedLines = Array.from(lines).sort((a, b) => {
try {
const ip1 = new IPAddressConstructor(a.split(',')[0]);
const ip2 = new IPAddressConstructor(b.split(',')[0]);
return ip1.bigInteger().compareTo(ip2.bigInteger());
} catch (e) {
translateIPSuccess = false;
}
return 0;
});
if (sortedLines.length > 0 && translateIPSuccess) {
if (gateway_ip) {
// check if gateway ip is include
let conflictPool;
let isGatewayIPIn;
try {
const gatewayIP = new IPAddressConstructor(gateway_ip);
conflictPool = '';
isGatewayIPIn = sortedLines.some((l) => {
const ipStart = new IPAddressConstructor(l.split(',')[0]);
const ipEnd = new IPAddressConstructor(l.split(',')[1]);
if (
gatewayIP.bigInteger().compareTo(ipStart.bigInteger()) >= 0 &&
ipEnd.bigInteger().compareTo(gatewayIP.bigInteger()) >= 0
) {
isGatewayIPIn = true;
conflictPool = l;
return true;
}
return false;
});
} catch (e) {
translateIPSuccess = false;
}
if (isGatewayIPIn && translateIPSuccess) {
return Promise.reject(
new Error(
t(
'Gateway ip {gateway_ip} conflicts with allocation pool {pool}',
{
gateway_ip,
pool: conflictPool.replace(',', '-'),
}
)
)
);
}
// check if gateway ip is include
}
// check if is overlapping
let errorIdxStart = 0;
const isOverlapping = sortedLines.some((i, idx) => {
if (idx < sortedLines.length - 1) {
try {
const ipBefore = new IPAddressConstructor(i.split(',')[1]);
const ipAfter = new IPAddressConstructor(
sortedLines[idx + 1].split(',')[0]
);
const f = ipAfter.bigInteger().compareTo(ipBefore.bigInteger());
if (f > 0) {
errorIdxStart = idx;
}
return f < 0;
} catch (e) {
translateIPSuccess = false;
}
}
return false;
});
if (isOverlapping && translateIPSuccess) {
const pools = `${sortedLines[errorIdxStart].replace(
',',
'-'
)}, ${sortedLines[errorIdxStart + 1].replace(',', '-')}`;
return Promise.reject(
new Error(
t('Overlapping allocation pools: {pools}', {
pools,
})
)
);
}
// check if is overlapping
}
}
return isIpv4
? checkAllocation_pools(rule, value)
: checkIpv6Allocation_pools(rule, value);
}
const checkDNS = (rule, value) => { const checkDNS = (rule, value) => {
if (value && _.isString(value)) { if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g); const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError); const flag = !lines.some(hasError);
return flag return flag
@ -98,7 +203,7 @@ const checkDNS = (rule, value) => {
}; };
const checkIpv6DNS = (rule, value) => { const checkIpv6DNS = (rule, value) => {
if (value && _.isString(value)) { if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g); const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError); const flag = !lines.some(hasError);
return flag return flag
@ -114,7 +219,7 @@ const checkIpv6DNS = (rule, value) => {
}; };
const checkHostRoutes = (rule, value) => { const checkHostRoutes = (rule, value) => {
if (value && _.isString(value)) { if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g); const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError); const flag = !lines.some(hasError);
return flag return flag
@ -133,7 +238,7 @@ const checkHostRoutes = (rule, value) => {
}; };
const checkIpv6HostRoutes = (rule, value) => { const checkIpv6HostRoutes = (rule, value) => {
if (value && _.isString(value)) { if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g); const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError); const flag = !lines.some(hasError);
return flag return flag
@ -153,7 +258,7 @@ const checkIpv6HostRoutes = (rule, value) => {
const getAllocationPools = (allocation_pools) => { const getAllocationPools = (allocation_pools) => {
const allocationPools = []; const allocationPools = [];
if (allocation_pools && _.isString(allocation_pools)) { if (allocation_pools && isString(allocation_pools)) {
const lines = allocation_pools.trim().split(/\s*[\r\n]+\s*/g); const lines = allocation_pools.trim().split(/\s*[\r\n]+\s*/g);
lines.forEach((item) => { lines.forEach((item) => {
const [start, end] = item.split(','); const [start, end] = item.split(',');
@ -168,7 +273,7 @@ const getAllocationPools = (allocation_pools) => {
const getHostRouters = (host_routes) => { const getHostRouters = (host_routes) => {
const hostRouters = []; const hostRouters = [];
if (host_routes && _.isString(host_routes)) { if (host_routes && isString(host_routes)) {
const lines = host_routes.trim().split(/\s*[\r\n]+\s*/g); const lines = host_routes.trim().split(/\s*[\r\n]+\s*/g);
lines.forEach((item) => { lines.forEach((item) => {
const [destination, nexthop] = item.split(','); const [destination, nexthop] = item.split(',');
@ -217,6 +322,7 @@ export default {
physicalNetworkArray, physicalNetworkArray,
segmentationNetworkArray, segmentationNetworkArray,
segmentationNetworkRequireArray, segmentationNetworkRequireArray,
validateAllocationPoolsWithGatewayIp,
checkAllocation_pools, checkAllocation_pools,
checkIpv6Allocation_pools, checkIpv6Allocation_pools,
checkDNS, checkDNS,