feature: Add allocation pools validate rules

add allocation pools validate rules

Change-Id: I285c8f2a4f0ec8581e88425306744f1f3a53572c
This commit is contained in:
zhuyue 2021-09-02 17:49:13 +08:00
parent 101025eaac
commit 2a3018a52d
5 changed files with 152 additions and 15 deletions

View File

@ -685,6 +685,7 @@
"GRE": "GRE",
"Gateway IP": "Gateway IP",
"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 Purpose": "General Purpose",
"Get OpenRC file": "Get OpenRC file",
@ -1090,6 +1091,7 @@
"Other Protocol": "Other Protocol",
"Others": "Others",
"Outputs": "Outputs",
"Overlapping allocation pools: {pools}": "Overlapping allocation pools: {pools}",
"Owned Network": "Owned Network",
"Owned Network ID": "Owned Network ID",
"Owned Project": "Owned Project",

View File

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

View File

@ -27,8 +27,7 @@ const {
physicalNetworkArray,
segmentationNetworkArray,
segmentationNetworkRequireArray,
checkAllocation_pools,
checkIpv6Allocation_pools,
validateAllocationPoolsWithGatewayIp,
checkDNS,
checkIpv6DNS,
checkHostRoutes,
@ -230,6 +229,10 @@ export default class CreateNetwork extends ModalAction {
return true;
};
validateAllocationPools = (rule, value) => {
return validateAllocationPoolsWithGatewayIp.call(this, rule, value);
};
get formItems() {
const {
more,
@ -482,6 +485,11 @@ export default class CreateNetwork extends ModalAction {
name: 'gateway_ip',
label: t('Gateway IP'),
type: 'ip-input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t(
'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',
label: t('Gateway IP'),
type: 'input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t(
'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::',
}),
hidden: !(create_subnet && more),
validator: isIpv4 ? checkAllocation_pools : checkIpv6Allocation_pools,
validator: this.validateAllocationPools,
dependencies: ['gateway_ip'],
},
{
name: 'dns',

View File

@ -23,8 +23,7 @@ import globalRootStore from 'stores/root';
import networkUtil from './networkUtil';
const {
checkAllocation_pools,
checkIpv6Allocation_pools,
validateAllocationPoolsWithGatewayIp,
checkDNS,
checkIpv6DNS,
checkHostRoutes,
@ -125,6 +124,10 @@ export default class CreateSubnet extends ModalAction {
return checkPolicyRule('skyline:system_admin');
}
validateAllocationPools = (rule, value) => {
return validateAllocationPoolsWithGatewayIp.call(this, rule, value);
};
get formItems() {
const { more, ip_version = 'ipv4', disable_gateway = false } = this.state;
const isIpv4 = ip_version === 'ipv4';
@ -230,6 +233,11 @@ export default class CreateSubnet extends ModalAction {
name: 'gateway_ip',
label: t('Gateway IP'),
type: 'ip-input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t(
'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',
label: t('Gateway IP'),
type: 'input',
onChange: (e) => {
this.setState({
gateway_ip: e.target.value,
});
},
tip: t(
'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::',
}),
hidden: !more,
validator: isIpv4 ? checkAllocation_pools : checkIpv6Allocation_pools,
validator: this.validateAllocationPools,
},
{
name: 'dns',

View File

@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import _, { isString } from 'lodash';
import { isString } from 'lodash';
import { ipValidate } from 'utils/validate';
import { Address4, Address6 } from 'ip-address';
const { ipFull, isIpCidr, isIPv6Cidr, isIPv4, isIpv6, compareIpv6 } =
ipValidate;
@ -25,7 +26,7 @@ const segmentationNetworkArray = ['vxlan', 'vlan', 'gre'];
const segmentationNetworkRequireArray = ['vlan', 'gre'];
const checkAllocation_pools = (rule, value) => {
if (value && _.isString(value)) {
if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError);
return flag
@ -53,7 +54,7 @@ const checkAllocation_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 flag = !lines.some(hasError);
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) => {
if (value && _.isString(value)) {
if (value && isString(value)) {
const lines = value.trim().split(/\s*[\r\n]+\s*/g);
const flag = !lines.some(hasError);
return flag
@ -98,7 +203,7 @@ const checkDNS = (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 flag = !lines.some(hasError);
return flag
@ -114,7 +219,7 @@ const checkIpv6DNS = (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 flag = !lines.some(hasError);
return flag
@ -133,7 +238,7 @@ const checkHostRoutes = (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 flag = !lines.some(hasError);
return flag
@ -153,7 +258,7 @@ const checkIpv6HostRoutes = (rule, value) => {
const getAllocationPools = (allocation_pools) => {
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);
lines.forEach((item) => {
const [start, end] = item.split(',');
@ -168,7 +273,7 @@ const getAllocationPools = (allocation_pools) => {
const getHostRouters = (host_routes) => {
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);
lines.forEach((item) => {
const [destination, nexthop] = item.split(',');
@ -217,6 +322,7 @@ export default {
physicalNetworkArray,
segmentationNetworkArray,
segmentationNetworkRequireArray,
validateAllocationPoolsWithGatewayIp,
checkAllocation_pools,
checkIpv6Allocation_pools,
checkDNS,