From 4d02dbe6dfbd352bd35d2d981cfa7c7baff0fc8f Mon Sep 17 00:00:00 2001 From: Likitha Shetty Date: Mon, 17 Jun 2013 18:50:56 +0530 Subject: [PATCH] CLOUDSTACK-3062. Dedication of a guest vlan range that extends 2 ranges dedicated to different accounts removes an old dedication --- .../com/cloud/network/NetworkServiceImpl.java | 76 ++++++++++++------- .../network/DedicateGuestVlanRangesTest.java | 4 +- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index aace68d9642..6796adc3dae 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -27,6 +27,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -2949,6 +2951,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { String updatedVlanRange = null; long guestVlanMapId = 0; long guestVlanMapAccountId = 0; + long vlanOwnerId = 0; // Verify account is valid Account vlanOwner = null; @@ -2969,6 +2972,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { throw new InvalidParameterValueException("Unable to find account by name " + accountName); } } + vlanOwnerId = vlanOwner.getAccountId(); // Verify physical network isolation type is VLAN PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); @@ -3024,40 +3028,59 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } List guestVlanMaps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByPhysicalNetwork(physicalNetworkId); + // Verify if vlan range is already dedicated for (AccountGuestVlanMapVO guestVlanMap : guestVlanMaps) { List vlanTokens = getVlanFromRange(guestVlanMap.getGuestVlanRange()); int dedicatedStartVlan = vlanTokens.get(0).intValue(); int dedicatedEndVlan = vlanTokens.get(1).intValue(); - guestVlanMapId = guestVlanMap.getId(); - guestVlanMapAccountId = guestVlanMap.getAccountId(); - - // Verify if range is already dedicated - if (startVlan >= dedicatedStartVlan && endVlan <= dedicatedEndVlan) { - if (guestVlanMap.getAccountId() != vlanOwner.getAccountId()) { - throw new InvalidParameterValueException("Vlan range is already dedicated to another account. Cannot dedicate guest vlan range " + vlan); - } else { - s_logger.debug("Vlan range " + vlan +" is already dedicated to the specified account" + accountName); - return guestVlanMap; - } - } - // Verify if range overlaps with an existing range - if (startVlan < dedicatedStartVlan & endVlan+1 >= dedicatedStartVlan & endVlan <= dedicatedEndVlan) { // extend to the left - updatedVlanRange = startVlan + "-" + dedicatedEndVlan; - break; - } else if (startVlan >= dedicatedStartVlan & startVlan-1 <= dedicatedEndVlan & endVlan > dedicatedEndVlan) { // extend to right - updatedVlanRange = dedicatedStartVlan + "-" + endVlan; - break; - } else if (startVlan < dedicatedStartVlan & endVlan > dedicatedEndVlan){ // extend to the left and right - updatedVlanRange = startVlan + "-" + endVlan; - break; + if ((startVlan < dedicatedStartVlan & endVlan >= dedicatedStartVlan) || + (startVlan >= dedicatedStartVlan & startVlan <= dedicatedEndVlan)) { + throw new InvalidParameterValueException("Vlan range is already dedicated. Cannot" + + " dedicate guest vlan range " + vlan); } } + // Sort the existing dedicated vlan ranges + Collections.sort(guestVlanMaps, new Comparator() { + @Override + public int compare( AccountGuestVlanMapVO obj1 , AccountGuestVlanMapVO obj2) { + List vlanTokens1 = getVlanFromRange(obj1.getGuestVlanRange()); + List vlanTokens2 = getVlanFromRange(obj2.getGuestVlanRange()); + return vlanTokens1.get(0).compareTo(vlanTokens2.get(0)); + } + }); + + // Verify if vlan range extends an already dedicated range + for (int i=0; i < guestVlanMaps.size(); i++) { + guestVlanMapId = guestVlanMaps.get(i).getId(); + guestVlanMapAccountId = guestVlanMaps.get(i).getAccountId(); + List vlanTokens1 = getVlanFromRange(guestVlanMaps.get(i).getGuestVlanRange()); + // Range extends a dedicated vlan range to the left + if (endVlan == (vlanTokens1.get(0).intValue()-1)) { + if(guestVlanMapAccountId == vlanOwnerId) { + updatedVlanRange = startVlan + "-" + vlanTokens1.get(1).intValue(); + } + break; + } + // Range extends a dedicated vlan range to the right + if (startVlan == (vlanTokens1.get(1).intValue()+1) & guestVlanMapAccountId == vlanOwnerId) { + if (i != (guestVlanMaps.size()-1)) { + List vlanTokens2 = getVlanFromRange(guestVlanMaps.get(i+1).getGuestVlanRange()); + // Range extends 2 vlan ranges, both to the right and left + if (endVlan == (vlanTokens2.get(0).intValue()-1) & guestVlanMaps.get(i+1).getAccountId() == vlanOwnerId) { + _datacneter_vnet.releaseDedicatedGuestVlans(guestVlanMaps.get(i+1).getId()); + _accountGuestVlanMapDao.remove(guestVlanMaps.get(i+1).getId()); + updatedVlanRange = vlanTokens1.get(0).intValue() + "-" + vlanTokens2.get(1).intValue(); + break; + } + } + updatedVlanRange = vlanTokens1.get(0).intValue() + "-" + endVlan; + break; + } + } + // Dedicate vlan range AccountGuestVlanMapVO accountGuestVlanMapVO; if (updatedVlanRange != null) { - if (guestVlanMapAccountId != vlanOwner.getAccountId()) { - throw new InvalidParameterValueException("Vlan range is partially dedicated to another account. Cannot dedicate guest vlan range " + vlan); - } accountGuestVlanMapVO = _accountGuestVlanMapDao.findById(guestVlanMapId); accountGuestVlanMapVO.setGuestVlanRange(updatedVlanRange); _accountGuestVlanMapDao.update(guestVlanMapId, accountGuestVlanMapVO); @@ -3070,7 +3093,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { txn.commit(); } // For every guest vlan set the corresponding account guest vlan map id - for (int i = startVlan; i <= endVlan; i++) { + List finaVlanTokens = getVlanFromRange(accountGuestVlanMapVO.getGuestVlanRange()); + for (int i = finaVlanTokens.get(0).intValue(); i <= finaVlanTokens.get(1).intValue(); i++) { List dataCenterVnet = _datacneter_vnet.findVnet(physicalNetwork.getDataCenterId(),((Integer)i).toString()); dataCenterVnet.get(0).setAccountGuestVlanMapId(accountGuestVlanMapVO.getId()); _datacneter_vnet.update(dataCenterVnet.get(0).getId(), dataCenterVnet.get(0)); diff --git a/server/test/com/cloud/network/DedicateGuestVlanRangesTest.java b/server/test/com/cloud/network/DedicateGuestVlanRangesTest.java index e81d7222a60..e5d33296b00 100644 --- a/server/test/com/cloud/network/DedicateGuestVlanRangesTest.java +++ b/server/test/com/cloud/network/DedicateGuestVlanRangesTest.java @@ -291,7 +291,7 @@ public class DedicateGuestVlanRangesTest { try { networkService.dedicateGuestVlanRange(dedicateGuestVlanRangesCmd); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Vlan range is already dedicated to another account")); + Assert.assertTrue(e.getMessage().contains("Vlan range is already dedicated")); } finally { txn.close("runDedicateGuestVlanRangeDedicatedRange"); } @@ -320,7 +320,7 @@ public class DedicateGuestVlanRangesTest { try { networkService.dedicateGuestVlanRange(dedicateGuestVlanRangesCmd); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Vlan range is partially dedicated to another account")); + Assert.assertTrue(e.getMessage().contains("Vlan range is already dedicated")); } finally { txn.close("runDedicateGuestVlanRangePartiallyDedicated"); }