From 6419a17ddd65264d68bc41d0f62876311ff5a205 Mon Sep 17 00:00:00 2001 From: kioie Date: Wed, 24 Apr 2019 12:13:39 +0300 Subject: [PATCH 1/4] #2797 Signed-off-by: kioie --- .../ConfigurationManagerImpl.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 30f2f7cd1e22..7c4e002229dd 100755 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1445,6 +1445,18 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str name = oldPodName; } + final String[] existingPodIPRangeArray = pod.getDescription().split("-"); + final String currentStartIP= existingPodIPRangeArray[0]; + final String currentEndIP = existingPodIPRangeArray [1]; + + if(startIp == null){ + startIp= currentStartIP; + } + + if(endIp == null){ + endIp= currentEndIP; + } + if (allocationStateStr == null) { allocationStateStr = pod.getAllocationState().toString(); } @@ -1487,6 +1499,9 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str final String allocationStateStrFinal = allocationStateStr; final String nameFinal = name; final String gatewayFinal = gateway; + final String newStartIP= startIp; + final String newEndIP= endIp; + Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(final TransactionStatus status) { @@ -1497,6 +1512,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { pod.setGateway(gatewayFinal); pod.setCidrAddress(getCidrAddress(cidr)); pod.setCidrSize(getCidrSize(cidr)); + pod.setDescription(pod.getDescription().replaceAll(currentEndIP, newEndIP).replaceAll(currentStartIP, + newStartIP)); Grouping.AllocationState allocationState = null; if (allocationStateStrFinal != null && !allocationStateStrFinal.isEmpty()) { @@ -1515,6 +1532,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { return pod; } + + @Override public Pod createPod(final long zoneId, final String name, final String startIp, final String endIp, final String gateway, final String netmask, String allocationState) { // Check if the gateway is a valid IP address From e13bbed540e32cbe3ceeb2b48448ba92a2cb5c77 Mon Sep 17 00:00:00 2001 From: kioie Date: Mon, 1 Jul 2019 13:00:09 +0300 Subject: [PATCH 2/4] Added checks for IP overlaps --- .../ConfigurationManagerImpl.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 7c4e002229dd..2c66f3faffd5 100755 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1445,6 +1445,7 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str name = oldPodName; } + final long zoneId = pod.getDataCenterId(); final String[] existingPodIPRangeArray = pod.getDescription().split("-"); final String currentStartIP= existingPodIPRangeArray[0]; final String currentEndIP = existingPodIPRangeArray [1]; @@ -1495,13 +1496,27 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str } } + // Check if the IP range is valid. + checkIpRange(startIp, endIp, cidrAddress, cidrSize); + + // Check if the IP range overlaps with the public ip. + checkOverlapPublicIpRange(zoneId, startIp, endIp); + + // Check if the gateway is in the CIDR subnet + if (!NetUtils.getCidrSubNet(gateway, cidrSize).equalsIgnoreCase(NetUtils.getCidrSubNet(cidrAddress, cidrSize))) { + throw new InvalidParameterValueException("The gateway is not in the CIDR subnet."); + } + + if (NetUtils.ipRangesOverlap(startIp, endIp, gateway, gateway)) { + throw new InvalidParameterValueException("The gateway shouldn't overlap start/end ip addresses"); + } + try { final String allocationStateStrFinal = allocationStateStr; final String nameFinal = name; final String gatewayFinal = gateway; final String newStartIP= startIp; final String newEndIP= endIp; - Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(final TransactionStatus status) { @@ -1512,7 +1527,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { pod.setGateway(gatewayFinal); pod.setCidrAddress(getCidrAddress(cidr)); pod.setCidrSize(getCidrSize(cidr)); - pod.setDescription(pod.getDescription().replaceAll(currentEndIP, newEndIP).replaceAll(currentStartIP, + pod.setDescription(pod.getDescription().replaceFirst(currentEndIP, newEndIP).replaceFirst(currentStartIP, newStartIP)); Grouping.AllocationState allocationState = null; @@ -1753,6 +1768,10 @@ private void checkIpRange(final String startIp, final String endIp, final String throw new InvalidParameterValueException("The start IP address must have a lower value than the end IP address."); } + if (NetUtils.ip2Long(startIp) > NetUtils.ip2Long(endIp)) { + throw new InvalidParameterValueException("The start IP address must have a lower value than the end IP address."); + } + } private void checkOverlapPublicIpRange(final Long zoneId, final String startIp, final String endIp) { From 4a1f43449ed3a724bb55acba6c053ef8f8092244 Mon Sep 17 00:00:00 2001 From: kioie Date: Mon, 1 Jul 2019 13:00:09 +0300 Subject: [PATCH 3/4] Added checks for IP overlaps --- .../ConfigurationManagerImpl.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 7c4e002229dd..bfc1d6dafaa3 100755 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1445,6 +1445,7 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str name = oldPodName; } + final long zoneId = pod.getDataCenterId(); final String[] existingPodIPRangeArray = pod.getDescription().split("-"); final String currentStartIP= existingPodIPRangeArray[0]; final String currentEndIP = existingPodIPRangeArray [1]; @@ -1495,13 +1496,22 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str } } + // Check if the IP range is valid. + checkIpRange(startIp, endIp, cidrAddress, cidrSize); + + // Check if the IP range overlaps with the public ip. + checkOverlapPublicIpRange(zoneId, startIp, endIp); + + if (NetUtils.ipRangesOverlap(startIp, endIp, gateway, gateway)) { + throw new InvalidParameterValueException("The gateway shouldn't overlap start/end ip addresses"); + } + try { final String allocationStateStrFinal = allocationStateStr; final String nameFinal = name; final String gatewayFinal = gateway; final String newStartIP= startIp; final String newEndIP= endIp; - Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(final TransactionStatus status) { @@ -1512,7 +1522,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { pod.setGateway(gatewayFinal); pod.setCidrAddress(getCidrAddress(cidr)); pod.setCidrSize(getCidrSize(cidr)); - pod.setDescription(pod.getDescription().replaceAll(currentEndIP, newEndIP).replaceAll(currentStartIP, + pod.setDescription(pod.getDescription().replaceFirst(currentEndIP, newEndIP).replaceFirst(currentStartIP, newStartIP)); Grouping.AllocationState allocationState = null; @@ -1753,6 +1763,10 @@ private void checkIpRange(final String startIp, final String endIp, final String throw new InvalidParameterValueException("The start IP address must have a lower value than the end IP address."); } + if (NetUtils.ip2Long(startIp) > NetUtils.ip2Long(endIp)) { + throw new InvalidParameterValueException("The start IP address must have a lower value than the end IP address."); + } + } private void checkOverlapPublicIpRange(final Long zoneId, final String startIp, final String endIp) { From 8e55dbf977957cc4054fc373c22d7813a929f9ee Mon Sep 17 00:00:00 2001 From: kioie Date: Mon, 30 Mar 2020 22:19:58 +0300 Subject: [PATCH 4/4] Added additional checks to confirm if IP Range contains taken addresses. Added logic to update op_dc_ip_address_alloc table. Also bried cleanup --- .../cloud/dc/dao/DataCenterIpAddressDao.java | 2 + .../dc/dao/DataCenterIpAddressDaoImpl.java | 14 ++++ .../ConfigurationManagerImpl.java | 66 +++++++++++++++++-- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDao.java b/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDao.java index bb840b5adec4..2c65539dd65b 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDao.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDao.java @@ -41,6 +41,8 @@ public interface DataCenterIpAddressDao extends GenericDao listByPodIdDcId(long podId, long dcId); + List listIpAddressUsage(final long podId, final long dcId, final boolean onlyListAllocated); + int countIPs(long podId, long dcId, boolean onlyCountAllocated); int countIPs(long dcId, boolean onlyCountAllocated); diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java b/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java index 8b0a44bbbf0f..97679bdb10a5 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java @@ -290,6 +290,20 @@ public int countIpAddressUsage(final String ipAddress, final long podId, final l return result.size(); } + @Override + public List listIpAddressUsage(final long podId, final long dcId, final boolean onlyListAllocated) { + SearchCriteria sc = createSearchCriteria(); + + if(onlyListAllocated) { + sc.addAnd("takenAt", SearchCriteria.Op.NNULL); + } + + sc.addAnd("podId", SearchCriteria.Op.EQ, podId); + sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dcId); + + return listBy(sc); + } + public DataCenterIpAddressDaoImpl() { super(); diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 034ffc9eff1c..878ae46fe174 100755 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1404,7 +1404,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { @Override public Pod editPod(final UpdatePodCmd cmd) { - return editPod(cmd.getId(), cmd.getPodName(), null, null, cmd.getGateway(), cmd.getNetmask(), cmd.getAllocationState()); + return editPod(cmd.getId(), cmd.getPodName(), cmd.getStartIp(), cmd.getEndIp(), cmd.getGateway(), cmd.getNetmask(), cmd.getAllocationState()); } @Override @@ -1502,10 +1502,33 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str // Check if the IP range overlaps with the public ip. checkOverlapPublicIpRange(zoneId, startIp, endIp); + // Check if the gateway is in the CIDR subnet + if (!NetUtils.getCidrSubNet(gateway, cidrSize).equalsIgnoreCase(NetUtils.getCidrSubNet(cidrAddress, cidrSize))) { + throw new InvalidParameterValueException("The gateway is not in the CIDR subnet."); + } + if (NetUtils.ipRangesOverlap(startIp, endIp, gateway, gateway)) { throw new InvalidParameterValueException("The gateway shouldn't overlap start/end ip addresses"); } + checkIpRangeContainsTakenAddresses(pod,startIp,endIp); + + long newStartIPLong = NetUtils.ip2Long(startIp); + long newEndIPLong = NetUtils.ip2Long(endIp); + long currentStartIPLong = NetUtils.ip2Long(currentStartIP); + long currentEndIPLong = NetUtils.ip2Long(currentEndIP); + + List currentIPRange = new ArrayList<>(); + List newIPRange = new ArrayList<>(); + while (newStartIPLong<=newEndIPLong){ + newIPRange.add(newStartIPLong); + newStartIPLong++; + } + while (currentStartIPLong<=currentEndIPLong){ + currentIPRange.add(currentStartIPLong); + currentStartIPLong++; + } + try { final String allocationStateStrFinal = allocationStateStr; final String nameFinal = name; @@ -1522,15 +1545,28 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { pod.setGateway(gatewayFinal); pod.setCidrAddress(getCidrAddress(cidr)); pod.setCidrSize(getCidrSize(cidr)); - pod.setDescription(pod.getDescription().replaceFirst(currentEndIP, newEndIP).replaceFirst(currentStartIP, - newStartIP)); + pod.setDescription(pod.getDescription().replace(currentStartIP+"-", newStartIP+"-").replace(currentEndIP, + newEndIP)); Grouping.AllocationState allocationState = null; if (allocationStateStrFinal != null && !allocationStateStrFinal.isEmpty()) { allocationState = Grouping.AllocationState.valueOf(allocationStateStrFinal); pod.setAllocationState(allocationState); } - + List iPAddressesToAdd = new ArrayList(newIPRange); + iPAddressesToAdd.removeAll(currentIPRange); + if (iPAddressesToAdd.size()>0){ + for(Long startIP : iPAddressesToAdd){ + _zoneDao.addPrivateIpAddress(zoneId, pod.getId(), NetUtils.long2Ip(startIP), NetUtils.long2Ip(startIP), false, null); + } + }else { + currentIPRange.removeAll(newIPRange); + if(currentIPRange.size()>0){ + for (Long startIP: currentIPRange){ + _privateIpAddressDao.deleteIpAddressByPodDc(NetUtils.long2Ip(startIP),pod.getId(),zoneId); + } + } + } _podDao.update(id, pod); } }); @@ -1542,6 +1578,28 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { return pod; } + private void checkIpRangeContainsTakenAddresses(final HostPodVO pod,final String startIp, final String endIp ){ + final List takenIps = _privateIpAddressDao.listIpAddressUsage(pod.getId(),pod.getDataCenterId(),true); + List newIPRange = new ArrayList<>(); + List takenIpsList = new ArrayList<>(); + + long newStartIPLong = NetUtils.ip2Long(startIp); + long newEndIPLong = NetUtils.ip2Long(endIp); + + while (newStartIPLong<=newEndIPLong){ + newIPRange.add(newStartIPLong); + newStartIPLong++; + } + for (int i=0;i