Improve floating ranges validation

Closes-Bug: #1518435

Change-Id: I694b8255cb15db75f292099806974a5f374b7868
This commit is contained in:
Julia Aranovich 2015-12-09 12:56:13 +03:00
parent eb187d0eed
commit 2c90987b8b
3 changed files with 120 additions and 66 deletions

View File

@ -815,7 +815,7 @@ define([
var untaggedNetworks = networks.filter(function(network) { return _.isNull(network.getVlanRange(attrs.networkingParameters)); });
var ns = 'cluster_page.nodes_tab.configure_interfaces.validation.';
// public and floating networks are allowed to be assigned to the same interface
var maxUntaggedNetworksCount = networks.where({name: 'public'}).length && networks.where({name: 'floating'}).length ? 2 : 1;
var maxUntaggedNetworksCount = networks.any({name: 'public'}) && networks.any({name: 'floating'}) ? 2 : 1;
if (untaggedNetworks.length > maxUntaggedNetworksCount) {
errors.push(i18n(ns + 'too_many_untagged_networks'));
}
@ -921,10 +921,11 @@ define([
currentNetworks.each(function(network) {
var networkErrors = {};
if (network.get('meta').configurable) {
_.extend(networkErrors, utils.validateCidr(network.get('cidr')));
var hasInvalidCidr = _.has(networkErrors, 'cidr');
var cidr = network.get('cidr');
_.extend(networkErrors, utils.validateCidr(cidr));
var cidrError = _.has(networkErrors, 'cidr');
if (network.get('meta').notation == 'ip_ranges') {
var ipRangesErrors = utils.validateIpRanges(network.get('ip_ranges'), hasInvalidCidr ? null : network.get('cidr'));
var ipRangesErrors = utils.validateIPRanges(network.get('ip_ranges'), !cidrError && cidr);
if (ipRangesErrors.length) {
networkErrors.ip_ranges = ipRangesErrors;
}
@ -932,7 +933,7 @@ define([
if (network.get('meta').use_gateway) {
if (!utils.validateIP(network.get('gateway'))) {
networkErrors.gateway = i18n(ns + 'invalid_gateway');
} else if (!hasInvalidCidr && !utils.validateIpCorrespondsToCIDR(network.get('cidr'), network.get('gateway'))) {
} else if (!cidrError && !utils.validateIpCorrespondsToCIDR(cidr, network.get('gateway'))) {
networkErrors.gateway = i18n(ns + 'gateway_is_out_of_ip_range');
}
}
@ -948,18 +949,17 @@ define([
nodeNetworkGroupErrors[network.id] = networkErrors;
}
if (network.get('name') == 'baremetal') {
if (!_.has(nodeNetworkGroupErrors[network.id], 'cidr')) {
var baremetalGateway = networkParameters.get('baremetal_gateway');
if (!utils.validateIP(baremetalGateway)) {
networkingParametersErrors.baremetal_gateway = i18n(ns + 'invalid_gateway');
} else if (!utils.validateIpCorrespondsToCIDR(network.get('cidr'), baremetalGateway)) {
networkingParametersErrors.baremetal_gateway = i18n(ns + 'gateway_is_out_of_baremetal_network');
}
var baremetalRangeErrors = utils.validateIpRanges([networkParameters.get('baremetal_range')], network.get('cidr'), true);
if (baremetalRangeErrors.length) {
var [{start, end}] = baremetalRangeErrors;
networkingParametersErrors.baremetal_range = [start, end];
}
var baremetalCidrError = _.has(nodeNetworkGroupErrors[network.id], 'cidr'),
baremetalGateway = networkParameters.get('baremetal_gateway');
if (!utils.validateIP(baremetalGateway)) {
networkingParametersErrors.baremetal_gateway = i18n(ns + 'invalid_gateway');
} else if (!baremetalCidrError && !utils.validateIpCorrespondsToCIDR(cidr, baremetalGateway)) {
networkingParametersErrors.baremetal_gateway = i18n(ns + 'gateway_is_out_of_baremetal_network');
}
var baremetalRangeErrors = utils.validateIPRanges([networkParameters.get('baremetal_range')], !baremetalCidrError && cidr);
if (baremetalRangeErrors.length) {
var [{start, end}] = baremetalRangeErrors;
networkingParametersErrors.baremetal_range = [start, end];
}
}
}
@ -997,7 +997,7 @@ define([
networkingParametersErrors.fixed_networks_vlan_start = i18n(ns + 'vlan_intersection');
}
}
floatingRangesErrors = utils.validateIpRanges(networkParameters.get('floating_ranges'), null, true);
floatingRangesErrors = utils.validateIPRanges(networkParameters.get('floating_ranges'));
if (floatingRangesErrors.length) {
networkingParametersErrors.floating_ranges = floatingRangesErrors;
}
@ -1039,19 +1039,45 @@ define([
var networkNamesRegExp = /^[a-z][\w\-]*$/i;
_.each(['internal_name', 'floating_name'], (paramName) => {
if (!networkParameters.get(paramName).match(networkNamesRegExp)) {
networkingParametersErrors[paramName] = i18n('cluster_page.network_tab.validation.invalid_name');
networkingParametersErrors[paramName] = i18n(ns + 'invalid_name');
}
});
var networkWithFloatingRange = networks.filter(function(network) {
return network.get('meta').floating_range_var;
})[0];
if (networkWithFloatingRange && !_.has(((errors.networks ||
{})[networkWithFloatingRange.get('group_id')] ||
{})[networkWithFloatingRange.id], 'cidr')) {
floatingRangesErrors = utils.validateIpRanges(networkParameters.get('floating_ranges'), networkWithFloatingRange.get('cidr'), true);
if (floatingRangesErrors.length) {
networkingParametersErrors.floating_ranges = floatingRangesErrors;
var defaultNodeNetworkGroupId = _.min(_.compact(networks.pluck('group_id'))),
networkToCheckFloatingRange = networks.find(
(network) => network.get('group_id') == defaultNodeNetworkGroupId && network.get('meta').floating_range_var
),
networkToCheckFloatingRangeCidrError = false;
try {
networkToCheckFloatingRangeCidrError = !!errors.networks[defaultNodeNetworkGroupId][networkToCheckFloatingRange.id].cidr;
} catch (error) {}
var networkToCheckFloatingRangeName = _.capitalize(networkToCheckFloatingRange.get('name')),
cidrToCheckFloatingRange = networkToCheckFloatingRange.get('cidr'),
ipRangesToCheckFloatingRange = _.filter(networkToCheckFloatingRange.get('ip_ranges'), (range, index) => {
var ipRangeError = false;
try {
ipRangeError = !_.all(range) || !!_.find(errors.networks[defaultNodeNetworkGroupId][networkToCheckFloatingRange.id].ip_ranges, {index: index});
} catch (error) {}
return !ipRangeError;
});
floatingRangesErrors = utils.validateIPRanges(
networkParameters.get('floating_ranges'),
!networkToCheckFloatingRangeCidrError && cidrToCheckFloatingRange,
ipRangesToCheckFloatingRange,
{
DOES_NOT_MATCH_CIDR: i18n(ns + 'floating_ip_does_not_match_cidr', {
cidr: cidrToCheckFloatingRange,
network: networkToCheckFloatingRangeName
}),
IP_RANGES_INTERSECTION: i18n(ns + 'floating_and_public_ip_ranges_intersection', {
network: networkToCheckFloatingRangeName
})
}
);
if (floatingRangesErrors.length) {
networkingParametersErrors.floating_ranges = floatingRangesErrors;
}
}
var nameserverErrors = [];

View File

@ -697,28 +697,30 @@
"large_network": "Network is too large",
"small_network": "Network is too small",
"invalid_cidr": "Invalid CIDR",
"invalid_ip_start": "Invalid IP range start",
"invalid_ip_end": "Invalid IP range end",
"invalid_ip_range": "The IP range start value must be less than the IP range end value.",
"invalid_ip_range_equal": "The IP range must include more than 1 IP address.",
"empty_ip_range": "Please specify at least one IP range.",
"invalid_ip": "Invalid IP address",
"invalid_ip_range": "Start IP address must be less than end IP address",
"empty_ip_range": "Please specify at least one IP range",
"ip_does_not_match_cidr": "IP address does not match the network CIDR",
"floating_ip_does_not_match_cidr": "Floating IP range must be contained in the CIDR of the __network__ network (Default node network group): __cidr__",
"ip_ranges_intersection": "The IP range intersects the following IP range: ",
"floating_and_public_ip_ranges_intersection": "Floating IP range must not intersect with IP range of the __network__ network (Default node network group): ",
"invalid_vlan": "Invalid VLAN ID",
"forbidden_vlan": "This VLAN ID is used by other networks. Please select other VLAN ID.",
"forbidden_vlan": "This VLAN ID is used by other networks. Please select other VLAN ID",
"invalid_netmask": "Invalid netmask",
"invalid_gateway": "Invalid gateway",
"invalid_amount": "Invalid amount of networks",
"gateway_is_out_of_ip_range": "The gateway address is out of the network CIDR.",
"gateway_is_out_of_baremetal_network": "The gateway address is out of the baremetal network CIDR.",
"gateway_is_out_of_internal_network": "The gateway address is out of the internal network CIDR.",
"need_more_vlan": "Not enough VLAN IDs are available for the selected number of networks. Verify that the number of networks specified in the VLAN ID Range field is correct.",
"gateway_is_out_of_ip_range": "The gateway address is out of the network CIDR",
"gateway_is_out_of_baremetal_network": "The gateway address is out of the baremetal network CIDR",
"gateway_is_out_of_internal_network": "The gateway address is out of the internal network CIDR",
"need_more_vlan": "Not enough VLAN IDs are available for the selected number of networks. Verify that the number of networks specified in the VLAN ID Range field is correct",
"invalid_nameserver": "Invalid nameserver",
"invalid_id_start": "Invalid ID range start",
"invalid_id_end": "Invalid ID range end",
"invalid_id_range": "The ID range start is greater than ID range end.",
"vlan_intersection": "The VLAN ID range overlaps with the VLAN ID range used in other networks. Please set a different VLAN ID range.",
"invalid_id_range": "The ID range start is greater than ID range end",
"vlan_intersection": "The VLAN ID range overlaps with the VLAN ID range used in other networks. Please set a different VLAN ID range",
"invalid_mac": "Invalid MAC address",
"ip_start_is_out_of_ip_range": "The IP start value is out of the selected IP range.",
"ip_end_is_out_of_ip_range": "The IP end value is out of the selected IP range.",
"ip_start_is_out_of_ip_range": "The IP start value is out of the selected IP range",
"ip_end_is_out_of_ip_range": "The IP end value is out of the selected IP range",
"invalid_name": "Invalid network name",
"invalid_node_network_group_name": "Invalid node network group name"
},
@ -2025,8 +2027,6 @@
"large_network": "ネットワークが大きすぎます",
"small_network": "ネットワークが小さすぎます",
"invalid_cidr": "CIDRが不正です",
"invalid_ip_start": "IPレンジの開始が不正です",
"invalid_ip_end": "IPレンジの終了が不正です",
"invalid_ip_range": "IPレンジの開始がIPレンジの終了より大きいです",
"empty_ip_range": "少なくとも、1つのIPレンジを指定してください",
"invalid_vlan": "VLAN IDが不正です",
@ -2588,8 +2588,6 @@
"large_network": "네트워크가 너무 큽니다",
"small_network": "네트워크가 너무 작습니다",
"invalid_cidr": "잘못된 CIDR",
"invalid_ip_start": "잘못된 IP 범위시작",
"invalid_ip_end": "잘못된 IP 범위끝",
"invalid_ip_range": "IP 범위의 시작이 IP 범위의 끝보다 큽니다",
"empty_ip_range": "적어도 하나의 IP 범위를 지정하십시오",
"invalid_vlan": "잘못된 VLAN ID",

View File

@ -196,34 +196,64 @@ define([
validateIP: function(ip) {
return _.isString(ip) && !!ip.match(utils.regexes.ip);
},
validateIPrange: function(startIP, endIP) {
return IP.toLong(startIP) - IP.toLong(endIP) <= 0;
},
validateIpRanges: function(ranges, cidr, disallowSingleAddress) {
var ipRangesErrors = [];
if (_.filter(ranges, function(range) {return _.compact(range).length;}).length) {
_.each(ranges, function(range, i) {
if (range[0] || range[1]) {
var error = {index: i};
if (!utils.validateIP(range[0]) || !utils.validateIpCorrespondsToCIDR(cidr, range[0])) {
error.start = i18n('cluster_page.network_tab.validation.invalid_ip_start');
} else if (!utils.validateIP(range[1]) || !utils.validateIpCorrespondsToCIDR(cidr, range[1])) {
error.end = i18n('cluster_page.network_tab.validation.invalid_ip_end');
} else if (!utils.validateIPrange(range[0], range[1])) {
error.start = i18n('cluster_page.network_tab.validation.invalid_ip_range');
} else if (disallowSingleAddress && range[0] == range[1]) {
error.start = i18n('cluster_page.network_tab.validation.invalid_ip_range_equal');
validateIPRanges: function(ranges, cidr, existingRanges = [], warnings = {}) {
var ipRangesErrors = [],
ns = 'cluster_page.network_tab.validation.';
_.defaults(warnings, {
INVALID_IP: i18n(ns + 'invalid_ip'),
DOES_NOT_MATCH_CIDR: i18n(ns + 'ip_does_not_match_cidr'),
INVALID_IP_RANGE: i18n(ns + 'invalid_ip_range'),
EMPTY_IP_RANGE: i18n(ns + 'empty_ip_range'),
IP_RANGES_INTERSECTION: i18n(ns + 'ip_ranges_intersection')
});
if (_.any(ranges, (range) => _.compact(range).length)) {
_.each(ranges, (range, index) => {
if (_.any(range)) {
var error = {};
if (!utils.validateIP(range[0])) {
error.start = warnings.INVALID_IP;
} else if (cidr && !utils.validateIpCorrespondsToCIDR(cidr, range[0])) {
error.start = warnings.DOES_NOT_MATCH_CIDR;
}
if (error.start || error.end) {
ipRangesErrors.push(error);
if (!utils.validateIP(range[1])) {
error.end = warnings.INVALID_IP;
} else if (cidr && !utils.validateIpCorrespondsToCIDR(cidr, range[1])) {
error.end = warnings.DOES_NOT_MATCH_CIDR;
}
if (_.isEmpty(error)) {
if (IP.toLong(range[0]) > IP.toLong(range[1])) {
error.start = error.end = warnings.INVALID_IP_RANGE;
} else if (existingRanges.length) {
var intersection = utils.checkIPRangesIntersection(range, existingRanges);
if (intersection) {
error.start = error.end = warnings.IP_RANGES_INTERSECTION + intersection.join(' - ');
}
}
}
if (!_.isEmpty(error)) {
ipRangesErrors.push(_.extend(error, {index: index}));
}
}
});
} else {
ipRangesErrors.push({index: 0, start: i18n('cluster_page.network_tab.validation.empty_ip_range')});
ipRangesErrors.push({
index: 0,
start: warnings.EMPTY_IP_RANGE,
end: warnings.EMPTY_IP_RANGE
});
}
return ipRangesErrors;
},
checkIPRangesIntersection: function([startIP, endIP], existingRanges) {
var startIPInt = IP.toLong(startIP),
endIPInt = IP.toLong(endIP);
return _.find(existingRanges, ([ip1, ip2]) => IP.toLong(ip2) >= startIPInt && IP.toLong(ip1) <= endIPInt);
},
validateIpCorrespondsToCIDR: function(cidr, ip) {
if (!cidr) return true;
var networkData = IP.cidrSubnet(cidr),