Cloudstack-701 Support for non contiguous vlan ranges. Signed-off-by: Abhinandan Prateek <aprat...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8b40e393 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8b40e393 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8b40e393 Branch: refs/heads/internallb Commit: 8b40e393b845c4c3d7ca23c8e297dc43288f6863 Parents: 2057221 Author: Bharat Kumar <bharat.ku...@citrix.com> Authored: Tue Apr 16 20:04:46 2013 +0530 Committer: Abhinandan Prateek <aprat...@apache.org> Committed: Wed Apr 17 10:14:42 2013 +0530 ---------------------------------------------------------------------- api/src/com/cloud/network/NetworkService.java | 2 +- api/src/com/cloud/network/PhysicalNetwork.java | 5 +- .../org/apache/cloudstack/api/ApiConstants.java | 1 + .../admin/network/UpdatePhysicalNetworkCmd.java | 8 +- server/src/com/cloud/api/ApiResponseHelper.java | 2 +- .../configuration/ConfigurationManagerImpl.java | 2 +- server/src/com/cloud/dc/dao/DataCenterVnetDao.java | 6 + .../com/cloud/dc/dao/DataCenterVnetDaoImpl.java | 50 +++- .../network/ExternalFirewallDeviceManagerImpl.java | 14 +- .../src/com/cloud/network/NetworkServiceImpl.java | 289 +++++++++++---- .../com/cloud/network/dao/PhysicalNetworkVO.java | 20 +- .../com/cloud/network/guru/GuestNetworkGuru.java | 14 +- .../com/cloud/network/MockNetworkManagerImpl.java | 2 +- .../cloud/network/UpdatePhysicalNetworkTest.java | 68 ++++ .../test/com/cloud/vpc/MockNetworkManagerImpl.java | 2 +- test/integration/smoke/test_non_contigiousvlan.py | 125 +++++++ 16 files changed, 512 insertions(+), 98 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/api/src/com/cloud/network/NetworkService.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 066009b..5a6054d 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -79,7 +79,7 @@ public interface NetworkService { Long startIndex, Long pageSize, String name); PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List<String> tags, - String newVnetRangeString, String state); + String newVnetRangeString, String state, String removeVlan); boolean deletePhysicalNetwork(Long id); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/api/src/com/cloud/network/PhysicalNetwork.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/PhysicalNetwork.java b/api/src/com/cloud/network/PhysicalNetwork.java index a2044a6..c521dc4 100644 --- a/api/src/com/cloud/network/PhysicalNetwork.java +++ b/api/src/com/cloud/network/PhysicalNetwork.java @@ -18,6 +18,7 @@ package com.cloud.network; import java.util.List; +import com.cloud.utils.Pair; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -59,7 +60,9 @@ public interface PhysicalNetwork extends Identity, InternalIdentity { Long getDomainId(); - String getVnet(); + List<Pair<Integer,Integer>> getVnet(); + + String getVnetString(); String getSpeed(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/api/src/org/apache/cloudstack/api/ApiConstants.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index cb4d43e..8c32bb3 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -221,6 +221,7 @@ public class ApiConstants { public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; public static final String VLAN = "vlan"; + public static final String REMOVE_VLAN="removevlan"; public static final String VLAN_ID = "vlanid"; public static final String VM_AVAILABLE = "vmavailable"; public static final String VM_LIMIT = "vmlimit"; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java index 06cf38d..6d37dd8 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java @@ -54,6 +54,8 @@ public class UpdatePhysicalNetworkCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the VLAN for the physical network") private String vlan; + @Parameter(name=ApiConstants.REMOVE_VLAN, type = CommandType.STRING, description ="The vlan range we want to remove") + private String removevlan; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -79,6 +81,10 @@ public class UpdatePhysicalNetworkCmd extends BaseAsyncCmd { return vlan; } + public String getRemoveVlan(){ + return removevlan; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -95,7 +101,7 @@ public class UpdatePhysicalNetworkCmd extends BaseAsyncCmd { @Override public void execute(){ - PhysicalNetwork result = _networkService.updatePhysicalNetwork(getId(),getNetworkSpeed(), getTags(), getVlan(), getState()); + PhysicalNetwork result = _networkService.updatePhysicalNetwork(getId(),getNetworkSpeed(), getTags(), getVlan(), getState(), getRemoveVlan()); PhysicalNetworkResponse response = _responseGenerator.createPhysicalNetworkResponse(result); response.setResponseName(getCommandName()); this.setResponseObject(response); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/api/ApiResponseHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index cfe0e00..b899fa1 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2667,7 +2667,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setZoneId(zone.getUuid()); } response.setNetworkSpeed(result.getSpeed()); - response.setVlan(result.getVnet()); + response.setVlan(result.getVnetString()); if (result.getDomainId() != null) { Domain domain = ApiDBUtils.findDomainById(result.getDomainId()); if (domain != null) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/configuration/ConfigurationManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 3551295..4fc2db7 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2633,7 +2633,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (vlan == null) { throw new CloudRuntimeException("Unable to acquire vlan configuration: " + vlanDbId); } - + if (s_logger.isDebugEnabled()) { s_logger.debug("lock vlan " + vlanDbId + " is acquired"); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/dc/dao/DataCenterVnetDao.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/dc/dao/DataCenterVnetDao.java b/server/src/com/cloud/dc/dao/DataCenterVnetDao.java index 79e91c4..7fb68dc 100644 --- a/server/src/com/cloud/dc/dao/DataCenterVnetDao.java +++ b/server/src/com/cloud/dc/dao/DataCenterVnetDao.java @@ -20,9 +20,11 @@ import java.util.List; import com.cloud.dc.DataCenterVnetVO; import com.cloud.utils.db.GenericDao; +import com.cloud.utils.db.Transaction; public interface DataCenterVnetDao extends GenericDao<DataCenterVnetVO, Long> { public List<DataCenterVnetVO> listAllocatedVnets(long physicalNetworkId); + public List<DataCenterVnetVO> listAllocatedVnetsInRange(long dcId, long physicalNetworkId, Integer start, Integer end); public List<DataCenterVnetVO> findVnet(long dcId, String vnet); public int countZoneVlans(long dcId, boolean onlyCountAllocated); public List<DataCenterVnetVO> findVnet(long dcId, long physicalNetworkId, String vnet); @@ -31,6 +33,10 @@ public interface DataCenterVnetDao extends GenericDao<DataCenterVnetVO, Long> { public void delete(long physicalNetworkId); + public void deleteRange(Transaction txn, long dcId, long physicalNetworkId, int start, int end); + + public void lockRange(long dcId, long physicalNetworkId, Integer start, Integer end); + public DataCenterVnetVO take(long physicalNetworkId, long accountId, String reservationId); public void release(String vnet, long physicalNetworkId, long accountId, String reservationId); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java b/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java index 5ded0f4..2e04439 100755 --- a/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java +++ b/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java @@ -21,6 +21,7 @@ import java.sql.SQLException; import java.util.Date; import java.util.List; +import com.cloud.exception.InvalidParameterValueException; import org.springframework.stereotype.Component; import com.cloud.dc.DataCenterVnetVO; @@ -46,8 +47,10 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase<DataCenterVnetVO, Long private final SearchBuilder<DataCenterVnetVO> VnetDcSearch; private final SearchBuilder<DataCenterVnetVO> VnetDcSearchAllocated; private final SearchBuilder<DataCenterVnetVO> DcSearchAllocated; + private final SearchBuilder<DataCenterVnetVO> DcSearchAllocatedInRange; private final GenericSearchBuilder<DataCenterVnetVO, Integer> countZoneVlans; private final GenericSearchBuilder<DataCenterVnetVO, Integer> countAllocatedZoneVlans; + private final SearchBuilder<DataCenterVnetVO> SearchRange; public List<DataCenterVnetVO> listAllocatedVnets(long physicalNetworkId) { SearchCriteria<DataCenterVnetVO> sc = DcSearchAllocated.create(); @@ -55,6 +58,22 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase<DataCenterVnetVO, Long return listBy(sc); } + public List<DataCenterVnetVO> listAllocatedVnetsInRange(long dcId, long physicalNetworkId, Integer start, Integer end) { + SearchCriteria<DataCenterVnetVO> sc = DcSearchAllocatedInRange.create(); + sc.setParameters("dc",dcId); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("vnetRange", start.toString(), end.toString()); + return listBy(sc); + } + + public void lockRange(long dcId, long physicalNetworkId, Integer start, Integer end) { + SearchCriteria<DataCenterVnetVO> sc = SearchRange.create(); + sc.setParameters("dc",dcId); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("vnetRange", start.toString(), end.toString()); + lockRows(sc,null,true); + } + public List<DataCenterVnetVO> findVnet(long dcId, String vnet) { SearchCriteria<DataCenterVnetVO> sc = VnetDcSearch.create();; sc.setParameters("dc", dcId); @@ -94,10 +113,27 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase<DataCenterVnetVO, Long stmt.executeBatch(); txn.commit(); } catch (SQLException e) { + if (!e.getMessage().contains("Duplicate")){ + txn.rollback(); + txn.close(); + throw new CloudRuntimeException("Exception caught adding vnet ", e); + } + } + } + + public void deleteRange(Transaction txn, long dcId, long physicalNetworkId, int start, int end) { + String deleteVnet = "DELETE FROM `cloud`.`op_dc_vnet_alloc` WHERE data_center_id=? AND physical_network_id=? AND taken IS NULL AND vnet BETWEEN ? AND ?"; + try { + PreparedStatement stmt = txn.prepareAutoCloseStatement(deleteVnet); + stmt.setLong(1,dcId); + stmt.setLong(2,physicalNetworkId); + stmt.setString(3,((Integer)start).toString()); + stmt.setString(4,((Integer)end).toString()); + stmt.execute(); + } catch (SQLException e) { throw new CloudRuntimeException("Exception caught adding vnet ", e); } } - public void delete(long physicalNetworkId) { SearchCriteria<DataCenterVnetVO> sc = VnetDcSearch.create(); sc.setParameters("physicalNetworkId", physicalNetworkId); @@ -149,6 +185,18 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase<DataCenterVnetVO, Long DcSearchAllocated.and("physicalNetworkId", DcSearchAllocated.entity().getPhysicalNetworkId(), SearchCriteria.Op.EQ); DcSearchAllocated.and("allocated", DcSearchAllocated.entity().getTakenAt(), SearchCriteria.Op.NNULL); DcSearchAllocated.done(); + + DcSearchAllocatedInRange = createSearchBuilder(); + DcSearchAllocatedInRange.and("dc",DcSearchAllocatedInRange.entity().getDataCenterId(), Op.EQ); + DcSearchAllocatedInRange.and("physicalNetworkId", DcSearchAllocatedInRange.entity().getPhysicalNetworkId(), Op.EQ); + DcSearchAllocatedInRange.and("allocated", DcSearchAllocatedInRange.entity().getTakenAt(), Op.NNULL); + DcSearchAllocatedInRange.and("vnetRange", DcSearchAllocatedInRange.entity().getVnet(), Op.BETWEEN); + DcSearchAllocatedInRange.done(); + + SearchRange = createSearchBuilder(); + SearchRange.and("dc", SearchRange.entity().getDataCenterId(), Op.EQ); + SearchRange.and("physicalNetworkId", SearchRange.entity().getPhysicalNetworkId(), Op.EQ); + SearchRange.and("vnetRange", SearchRange.entity().getVnet(), Op.BETWEEN); FreeVnetSearch = createSearchBuilder(); FreeVnetSearch.and("dc", FreeVnetSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java index c2038e5..ac00bc1 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java @@ -29,6 +29,7 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.response.ExternalFirewallResponse; import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; +import com.cloud.utils.Pair; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -715,8 +716,17 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl if (pNetwork.getVnet() == null) { throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + "."); } - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); + Integer lowestVlanTag = null; + List<Pair<Integer, Integer>> vnetList = pNetwork.getVnet(); + //finding the vlanrange in which the vlanTag lies. + for (Pair <Integer,Integer> vnet : vnetList){ + if (vlanTag >= vnet.first() && vlanTag <= vnet.second()){ + lowestVlanTag = vnet.first(); + } + } + if (lowestVlanTag == null) { + throw new InvalidParameterValueException ("The vlan tag dose not belong to any of the existing vlan ranges"); + } return vlanTag - lowestVlanTag; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/network/NetworkServiceImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 70d1d0d..12c6068 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -19,16 +19,10 @@ package com.cloud.network; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.DataCenter; +import com.cloud.dc.*; import com.cloud.dc.DataCenter.NetworkType; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.Pod; import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; -import com.cloud.dc.dao.AccountVlanMapDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.HostPodDao; -import com.cloud.dc.dao.VlanDao; +import com.cloud.dc.dao.*; import com.cloud.deploy.DeployDestination; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; @@ -89,6 +83,7 @@ import com.cloud.utils.net.NetUtils; import com.cloud.vm.*; import com.cloud.vm.dao.*; import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; @@ -206,6 +201,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { HostDao _hostDao; @Inject HostPodDao _hostPodDao; + @Inject + DataCenterVnetDao _datacneter_vnet; int _cidrLimit; boolean _allowSubdomainNetworkAccess; @@ -538,7 +535,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) { Account caller = UserContext.current().getCaller(); long callerUserId = UserContext.current().getCallerUserId(); - _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseNetwork, false, network); //handle the basic networks here VirtualMachine vm = _userVmDao.findById(nicVO.getInstanceId()); if (vm == null) { @@ -758,18 +755,20 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // in the zone when using external networking PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); if (pNetwork.getVnet() != null) { - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); - int highestVlanTag = Integer.valueOf(vlanRange[1]); - for (int vlan=lowestVlanTag; vlan <= highestVlanTag; ++vlan) { - int offset = vlan - lowestVlanTag; - String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); - int cidrSize = 8 + Integer.parseInt(globalVlanBits); - String guestNetworkCidr = zone.getGuestNetworkCidr(); - String[] cidrTuple = guestNetworkCidr.split("\\/"); - long newCidrAddress = (NetUtils.ip2Long(cidrTuple[0]) & 0xff000000) | (offset << (32 - cidrSize)); - if (NetUtils.isNetworksOverlap(NetUtils.long2Ip(newCidrAddress), cidr)) { - throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR that is reserved for zone vlan " + vlan); + List <Pair<Integer,Integer>> vlanList = pNetwork.getVnet(); + for (Pair<Integer,Integer> vlanRange : vlanList){ + Integer lowestVlanTag = vlanRange.first(); + Integer highestVlanTag = vlanRange.second(); + for (int vlan=lowestVlanTag; vlan <= highestVlanTag; ++vlan) { + int offset = vlan - lowestVlanTag; + String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); + int cidrSize = 8 + Integer.parseInt(globalVlanBits); + String guestNetworkCidr = zone.getGuestNetworkCidr(); + String[] cidrTuple = guestNetworkCidr.split("\\/"); + long newCidrAddress = (NetUtils.ip2Long(cidrTuple[0]) & 0xff000000) | (offset << (32 - cidrSize)); + if (NetUtils.isNetworksOverlap(NetUtils.long2Ip(newCidrAddress), cidr)) { + throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR that is reserved for zone vlan " + vlan); + } } } } @@ -2198,7 +2197,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } catch (NumberFormatException e) { throw new InvalidParameterValueException("Please specify valid integers for the vlan range."); } - if ((vnetStart > vnetEnd) || (vnetStart < 0) || (vnetEnd > 4096)) { s_logger.warn("Invalid vnet range: start range:" + vnetStart + " end range:" + vnetEnd); throw new InvalidParameterValueException("Vnet range should be between 0-4096 and start range should be lesser than or equal to end range"); @@ -2289,7 +2287,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { @Override @DB @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_UPDATE, eventDescription = "updating physical network", async = true) - public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List<String> tags, String newVnetRangeString, String state) { + public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List<String> tags, String newVnetRangeString, String state, String removeVlan) { // verify input parameters PhysicalNetworkVO network = _physicalNetworkDao.findById(id); @@ -2314,6 +2312,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } } + if (removeVlan != null){ + List<Integer> tokens = processVlanRange(network,removeVlan); + boolean result = removeVlanRange(network, tokens.get(0), tokens.get(1)); + + } + if (tags != null && tags.size() > 1) { throw new InvalidParameterException("Unable to support more than one tag on network yet"); } @@ -2340,88 +2344,209 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } // Vnet range can be extended only - boolean replaceVnet = false; - ArrayList<Pair<Integer, Integer>> vnetsToAdd = new ArrayList<Pair<Integer, Integer>>(2); + boolean AddVnet = true; + List<Pair<Integer, Integer>> vnetsToAdd = new ArrayList<Pair<Integer, Integer>>(); if (newVnetRangeString != null) { Integer newStartVnet = 0; Integer newEndVnet = 0; - String[] newVnetRange = newVnetRangeString.split("-"); - int maxVnet = 4096; - // for GRE phynets allow up to 32bits - // TODO: Not happy about this test. - // What about guru-like objects for physical networs? - s_logger.debug("ISOLATION METHODS:" + network.getIsolationMethods()); - // Java does not have unsigned types... - if (network.getIsolationMethods().contains("GRE")) { - maxVnet = (int)(Math.pow(2, 32)-1); - } - String rangeMessage = " between 0 and " + maxVnet; - if (newVnetRange.length < 2) { - throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); - } + List<Integer> tokens = processVlanRange(network, newVnetRangeString); + newStartVnet = tokens.get(0); + newEndVnet = tokens.get(1); + Integer j=0; + List <Pair <Integer,Integer>> existingRanges = network.getVnet(); + if (!existingRanges.isEmpty()) { + for (; j < existingRanges.size(); j++){ + int existingStartVnet = existingRanges.get(j).first(); + int existingEndVnet = existingRanges.get(j).second(); + + // check if vnet is being extended + if (newStartVnet.intValue() >= existingStartVnet & newEndVnet.intValue() <= existingEndVnet) { + throw new InvalidParameterValueException("The vlan range you trying to add already exists."); + } - if (newVnetRange[0] == null || newVnetRange[1] == null) { - throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); - } + if (newStartVnet < existingStartVnet & newEndVnet+1 >= existingStartVnet & newEndVnet <= existingEndVnet) { + vnetsToAdd.add(new Pair<Integer, Integer>(newStartVnet, existingStartVnet - 1)); + existingRanges.get(j).first(newStartVnet); + AddVnet = false; + break; + } + + else if (newStartVnet > existingStartVnet & newStartVnet-1 <= existingEndVnet & newEndVnet >= existingEndVnet) { + vnetsToAdd.add(new Pair<Integer, Integer>(existingEndVnet + 1, newEndVnet)); + existingRanges.get(j).second(newEndVnet); + AddVnet = false; + break; + } + + else if (newStartVnet< existingStartVnet & newEndVnet > existingEndVnet){ + vnetsToAdd.add(new Pair<Integer, Integer>(newStartVnet,existingStartVnet-1)); + vnetsToAdd.add(new Pair<Integer, Integer>(existingEndVnet+1,newEndVnet)); + existingRanges.get(j).first(newStartVnet); + existingRanges.get(j).second(newEndVnet); + break; + } + } - try { - newStartVnet = Integer.parseInt(newVnetRange[0]); - newEndVnet = Integer.parseInt(newVnetRange[1]); - } catch (NumberFormatException e) { - s_logger.warn("Unable to parse vnet range:", e); - throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); } - if (newStartVnet < 0 || newEndVnet > maxVnet) { - throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage); + if (AddVnet){ + vnetsToAdd.add(new Pair<Integer, Integer>(newStartVnet, newEndVnet)); + existingRanges.add(new Pair<Integer, Integer>(newStartVnet,newEndVnet)); + } + + Map <Integer,Integer> vnetMap = new HashMap<Integer, Integer>(existingRanges.size()); + Map <Integer, Integer> IndexMap = new HashMap<Integer, Integer>(existingRanges.size()); + for (int i=0; i< existingRanges.size(); i++){ + vnetMap.put(existingRanges.get(i).first(),existingRanges.get(i).second()); + IndexMap.put(existingRanges.get(i).first(),i); + } + + Integer value; + Integer index; + String vnetString = ""; + for (int i=0; i < existingRanges.size(); i++){ + value = vnetMap.get((existingRanges.get(i).second()+1)); + if (value != null) { + vnetMap.remove((existingRanges.get(i).second()+1)); + vnetMap.remove(existingRanges.get(i).first()); + vnetMap.put(existingRanges.get(i).first(),value); + existingRanges.add(new Pair<Integer,Integer>(existingRanges.get(i).first(),value)); + index = IndexMap.get(existingRanges.get(i).second()+1); + existingRanges.get(index).first(-1); + existingRanges.get(index).second(-1); + existingRanges.get(i).first(-1); + existingRanges.get(i).second(-1); + } + value = vnetMap.get((existingRanges.get(i).second())); + if (value != null) { + vnetMap.remove((existingRanges.get(i).second())); + vnetMap.remove(existingRanges.get(i).first()); + vnetMap.put(existingRanges.get(i).first(),value); + existingRanges.add(new Pair<Integer,Integer>(existingRanges.get(i).first(),value)); + index = IndexMap.get(existingRanges.get(i).second()); + existingRanges.get(index).first(-1); + existingRanges.get(index).second(-1); + existingRanges.get(i).first(-1); + existingRanges.get(i).second(-1); + } } - if (newStartVnet > newEndVnet) { - throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage + " and start range should be lesser than or equal to stop range"); + + + if (newVnetRangeString != null) { + for (Pair<Integer,Integer> vnetRange : existingRanges ){ + value=vnetMap.get(vnetRange.first()); + if (value != null){ + vnetString = vnetString+vnetRange.first().toString()+"-"+value.toString()+";"; + } + } + vnetString = vnetString+"*"; + vnetString = vnetString.replace(";*",""); + network.setVnet(vnetString); } - - if (physicalNetworkHasAllocatedVnets(network.getDataCenterId(), network.getId())) { - String[] existingRange = network.getVnet().split("-"); - int existingStartVnet = Integer.parseInt(existingRange[0]); - int existingEndVnet = Integer.parseInt(existingRange[1]); - - // check if vnet is being extended - if (newStartVnet.intValue() > existingStartVnet || newEndVnet.intValue() < existingEndVnet) { - throw new InvalidParameterValueException("Can't shrink existing vnet range as it the range has vnets allocated. Only extending existing vnet is supported"); - } - if (newStartVnet < existingStartVnet) { - vnetsToAdd.add(new Pair<Integer, Integer>(newStartVnet, existingStartVnet - 1)); - } - if (newEndVnet > existingEndVnet) { - vnetsToAdd.add(new Pair<Integer, Integer>(existingEndVnet + 1, newEndVnet)); - } - } else { - vnetsToAdd.add(new Pair<Integer, Integer>(newStartVnet, newEndVnet)); - replaceVnet = true; + _physicalNetworkDao.update(id, network); + + for (Pair<Integer, Integer> vnetToAdd : vnetsToAdd) { + s_logger.debug("Adding vnet range " + vnetToAdd.first() + "-" + vnetToAdd.second() + " for the physicalNetwork id= " + id + " and zone id=" + network.getDataCenterId() + + " as a part of updatePhysicalNetwork call"); + _dcDao.addVnet(network.getDataCenterId(), network.getId(), vnetToAdd.first(), vnetToAdd.second()); } } - if (newVnetRangeString != null) { - network.setVnet(newVnetRangeString); + return network; + } + + private List<Integer> processVlanRange(PhysicalNetworkVO network, String removeVlan) { + Integer StartVnet; + Integer EndVnet; + String[] VnetRange = removeVlan.split("-"); + int maxVnet = 4096; + // for GRE phynets allow up to 32bits + // TODO: Not happy about this test. + // What about guru-like objects for physical networs? + s_logger.debug("ISOLATION METHODS:" + network.getIsolationMethods()); + // Java does not have unsigned types... + if (network.getIsolationMethods().contains("GRE")) { + maxVnet = (int)(Math.pow(2, 32)-1); + } + String rangeMessage = " between 0 and " + maxVnet; + if (VnetRange.length < 2) { + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); } - _physicalNetworkDao.update(id, network); + if (VnetRange[0] == null || VnetRange[1] == null) { + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); + } - if (replaceVnet) { - s_logger.debug("Deleting existing vnet range for the physicalNetwork id= " + id + " and zone id=" + network.getDataCenterId() + " as a part of updatePhysicalNetwork call"); - _dcDao.deleteVnet(network.getId()); + try { + StartVnet = Integer.parseInt(VnetRange[0]); + EndVnet = Integer.parseInt(VnetRange[1]); + } catch (NumberFormatException e) { + s_logger.warn("Unable to parse vnet range:", e); + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); + } + if (StartVnet < 0 || EndVnet > maxVnet) { + throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage); } - for (Pair<Integer, Integer> vnetToAdd : vnetsToAdd) { - s_logger.debug("Adding vnet range " + vnetToAdd.first() + "-" + vnetToAdd.second() + " for the physicalNetwork id= " + id + " and zone id=" + network.getDataCenterId() - + " as a part of updatePhysicalNetwork call"); - _dcDao.addVnet(network.getDataCenterId(), network.getId(), vnetToAdd.first(), vnetToAdd.second()); + if (StartVnet > EndVnet) { + throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage + " and start range should be lesser than or equal to stop range"); } + List<Integer> tokens = new ArrayList<Integer>(); + tokens.add(StartVnet); + tokens.add(EndVnet); + return tokens; - return network; + } + + + private boolean removeVlanRange( PhysicalNetworkVO network, Integer start, Integer end) { + Integer temp=0; + int i; + List <Pair <Integer,Integer>> existingRanges = network.getVnet(); + Transaction txn = Transaction.currentTxn(); + txn.start(); + _physicalNetworkDao.acquireInLockTable(network.getId(),10); + _datacneter_vnet.lockRange(network.getDataCenterId(), network.getId(), start, end); + List<DataCenterVnetVO> result = _datacneter_vnet.listAllocatedVnetsInRange(network.getDataCenterId(), network.getId(), start, end); + if (!result.isEmpty()){ + txn.close(); + throw new InvalidParameterValueException("Some of the vnets from this range are allocated, can only remove a range which has no allocated vnets"); + } + for (i=0; i<existingRanges.size(); i++){ + if (existingRanges.get(i).first()<= start & existingRanges.get(i).second()>= end){ + temp = existingRanges.get(i).second(); + existingRanges.get(i).second(start - 1); + existingRanges.add(new Pair<Integer, Integer>((end+1),temp)); + break; + } + } + + if (temp == 0){ + throw new InvalidParameterValueException("The vlan range you are trying to delete dose not exist."); + } + if(existingRanges.get(i).first() > existingRanges.get(i).second()){ + existingRanges.remove(i); + } + if(existingRanges.get(existingRanges.size()-1).first() > existingRanges.get(existingRanges.size()-1).second()){ + existingRanges.remove(existingRanges.size()-1); + } + _datacneter_vnet.deleteRange(txn, network.getDataCenterId(), network.getId(), start, end); + + String vnetString=""; + for (Pair<Integer,Integer> vnetRange : existingRanges ){ + vnetString=vnetString+vnetRange.first().toString()+"-"+vnetRange.second().toString()+";"; + } + vnetString = vnetString+"*"; + vnetString = vnetString.replace(";*",""); + network.setVnet(vnetString); + _physicalNetworkDao.update(network.getId(), network); + txn.commit(); + _physicalNetworkDao.releaseFromLockTable(network.getId()); + return true; } private boolean physicalNetworkHasAllocatedVnets(long zoneId, long physicalNetworkId) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/network/dao/PhysicalNetworkVO.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/dao/PhysicalNetworkVO.java b/server/src/com/cloud/network/dao/PhysicalNetworkVO.java index e5ffcfb..f68eee1 100644 --- a/server/src/com/cloud/network/dao/PhysicalNetworkVO.java +++ b/server/src/com/cloud/network/dao/PhysicalNetworkVO.java @@ -34,11 +34,9 @@ import javax.persistence.Table; import javax.persistence.TableGenerator; import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetwork.BroadcastDomainRange; -import com.cloud.network.PhysicalNetwork.State; import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; -import org.apache.cloudstack.api.InternalIdentity; /** * NetworkConfigurationVO contains information about a specific physical network. @@ -205,7 +203,21 @@ public class PhysicalNetworkVO implements PhysicalNetwork { } @Override - public String getVnet() { + public List<Pair<Integer, Integer>> getVnet() { + List <Pair<Integer,Integer>> vnetList = new ArrayList<Pair<Integer, Integer>>(); + if (vnet != null) { + String [] Temp = vnet.split(";"); + String [] vnetSplit = null; + for (String vnetRange : Temp){ + vnetSplit = vnetRange.split("-"); + vnetList.add(new Pair<Integer,Integer>(Integer.parseInt(vnetSplit[0]),Integer.parseInt(vnetSplit[1]))); + } + } + return vnetList; + } + + @Override + public String getVnetString() { return vnet; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/src/com/cloud/network/guru/GuestNetworkGuru.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java index 9c0205a..92607e2 100755 --- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java @@ -26,6 +26,7 @@ import javax.ejb.Local; import javax.inject.Inject; import com.cloud.event.ActionEventUtils; +import com.cloud.utils.Pair; import org.apache.log4j.Logger; import com.cloud.configuration.Config; @@ -274,8 +275,17 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur if (pNetwork.getVnet() == null) { throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + "."); } - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); + Integer lowestVlanTag = null; + List<Pair<Integer, Integer>> vnetList = pNetwork.getVnet(); + //finding the vlanrange in which the vlanTag lies. + for (Pair <Integer,Integer> vnet : vnetList){ + if (vlanTag >= vnet.first() && vlanTag <= vnet.second()){ + lowestVlanTag = vnet.first(); + } + } + if (lowestVlanTag == null) { + throw new InvalidParameterValueException ("The vlan tag dose not belong to any of the existing vlan ranges"); + } return vlanTag - lowestVlanTag; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/test/com/cloud/network/MockNetworkManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index 9042f03..6a0263e 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -322,7 +322,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } @Override - public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List<String> tags, String newVnetRangeString, String state) { + public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List<String> tags, String newVnetRangeString, String state, String removeVlan) { // TODO Auto-generated method stub return null; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/test/com/cloud/network/UpdatePhysicalNetworkTest.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/network/UpdatePhysicalNetworkTest.java b/server/test/com/cloud/network/UpdatePhysicalNetworkTest.java new file mode 100644 index 0000000..ca9d149 --- /dev/null +++ b/server/test/com/cloud/network/UpdatePhysicalNetworkTest.java @@ -0,0 +1,68 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network; +import com.cloud.capacity.CapacityManagerImpl; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.network.NetworkServiceImpl; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.utils.Pair; +import org.junit.Test; +import org.junit.*; +import org.mockito.ArgumentCaptor; +import org.mockito.MockitoAnnotations.*; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +public class UpdatePhysicalNetworkTest { + private PhysicalNetworkDao _physicalNetworkDao = mock(PhysicalNetworkDao.class); + private DataCenterDao _datacenterDao = mock(DataCenterDao.class); + private DataCenterVO datacentervo = mock(DataCenterVO.class); + private PhysicalNetworkVO physicalNetworkVO = mock(PhysicalNetworkVO.class); + List<Pair<Integer,Integer>> existingRange = new ArrayList<Pair<Integer, Integer>>(); + ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class); + + public NetworkServiceImpl setUp() { + NetworkServiceImpl networkService = new NetworkServiceImpl(); + ((NetworkServiceImpl)networkService)._dcDao= _datacenterDao; + networkService._physicalNetworkDao = _physicalNetworkDao; + return networkService; + } + + @Test + public void updatePhysicalNetworkTest(){ + NetworkServiceImpl networkService = setUp(); + existingRange.add(new Pair<Integer, Integer>(520, 524)); + when(_physicalNetworkDao.findById(anyLong())).thenReturn(physicalNetworkVO); + when(_datacenterDao.findById(anyLong())).thenReturn(datacentervo); + when(_physicalNetworkDao.update(anyLong(), any(physicalNetworkVO.getClass()))).thenReturn(true); + when(physicalNetworkVO.getVnet()).thenReturn(existingRange); + networkService.updatePhysicalNetwork(1l, null, null, "525-530", null, null); + verify(physicalNetworkVO).setVnet(argumentCaptor.capture()); + assertEquals("520-530", argumentCaptor.getValue()); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/server/test/com/cloud/vpc/MockNetworkManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 3a585ce..bfcccf5 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -328,7 +328,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage */ @Override public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List<String> tags, - String newVnetRangeString, String state) { + String newVnetRangeString, String state, String removeVlan) { // TODO Auto-generated method stub return null; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8b40e393/test/integration/smoke/test_non_contigiousvlan.py ---------------------------------------------------------------------- diff --git a/test/integration/smoke/test_non_contigiousvlan.py b/test/integration/smoke/test_non_contigiousvlan.py new file mode 100644 index 0000000..fe70f87 --- /dev/null +++ b/test/integration/smoke/test_non_contigiousvlan.py @@ -0,0 +1,125 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" BVT tests for Primary Storage +""" +import marvin +from marvin import cloudstackTestCase +from marvin.cloudstackTestCase import * + +import unittest +import hashlib +import random + + +class TestUpdatePhysicalNetwork(cloudstackTestCase): + """ + This test updates the existing physicalnetwork with a new vlan range. + """ + def setUp(self): + """ + CloudStack internally saves its passwords in md5 form and that is how we + specify it in the API. Python's hashlib library helps us to quickly hash + strings as follows + """ + mdf = hashlib.md5() + mdf.update('password') + mdf_pass = mdf.hexdigest() + + self.apiClient = self.testClient.getApiClient() #Get ourselves an API client + + self.acct = createAccount.createAccountCmd() #The createAccount command + self.acct.accounttype = 0 #We need a regular user. admins have accounttype=1 + self.acct.firstname = 'bharat' + self.acct.lastname = 'kumar' #What's up doc? + self.acct.password = mdf_pass #The md5 hashed password string + self.acct.username = 'bharat' + self.acct.email = 'bha...@kumar.com' + self.acct.account = 'bharat' + self.acct.domainid = 1 #The default ROOT domain + self.acctResponse = self.apiClient.createAccount(self.acct) + # using the default debug logger of the test framework + self.debug("successfully created account: %s, user: %s, id: \ + %s"%(self.acctResponse.account.account, \ + self.acctResponse.account.username, \ + self.acctResponse.account.id)) + + def test_UpdatePhysicalNetwork(self): + """ + Let's start by defining the attributes of our VM that we will be + deploying on CloudStack. We will be assuming a single zone is available + and is configured and all templates are Ready + + The hardcoded values are used only for brevity. + """ + listPhysicalNetworksCmd = listPhysicalNetworks.listPhysicalNetworksCmd() + listPhysicalNetworksResponse = self.apiClient.listPhysicalNetworks(listPhysicalNetworksCmd) + + self.assertNotEqual(len(listPhysicalNetworksResponse), 0, "Check if the list API \ + returns a non-empty response") + + networkid = listPhysicalNetworksResponse[0].id + updatePhysicalNetworkCmd = updatePhysicalNetwork.updatePhysicalNetworkCmd() + updatePhysicalNetworkCmd.id = networkid + updatePhysicalNetworkCmd.vlan = "4090-4091" + updatePhysicalNetworkResponse = self.apiClient.updatePhysicalNetwork(updatePhysicalNetworkCmd) + self.assertNotEqual((updatePhysicalNetworkResponse.len), 0, "Check if the list API \ + returns a non-empty response") + + updatePhysicalNetworkCmd = updatePhysicalNetwork.updatePhysicalNetworkCmd() + updatePhysicalNetworkCmd.id = networkid + updatePhysicalNetworkCmd.vlan = "4092-4096" + updatePhysicalNetworkResponse = self.apiClient.updatePhysicalNetwork(updatePhysicalNetworkCmd) + self.assertNotEqual((updatePhysicalNetworkResponse.len), 0, "Check if the list API \ + returns a non-empty response") + + vlanranges= updatePhysicalNetworkResponse.vlan + range = "" + vlanranges = vlanranges.split(";") + for vlan in vlanranges: + if (vlan == "4090-4096"): + range = vlan + + self.assertEqual(range, "4090-4096", "check if adding the range is successful") + + updatePhysicalNetworkCmd = updatePhysicalNetwork.updatePhysicalNetworkCmd() + updatePhysicalNetworkCmd.id = networkid + updatePhysicalNetworkCmd.removevlan = "4090-4096" + updatePhysicalNetworkResponse = self.apiClient.updatePhysicalNetwork(updatePhysicalNetworkCmd) + self.assertNotEqual((updatePhysicalNetworkResponse.len), 0, "Check if the list API \ + returns a non-empty response") + + vlanranges= updatePhysicalNetworkResponse.vlan + range = "" + vlanranges = vlanranges.split(";") + + for vlan in vlanranges: + if (vlan == "4090-4096"): + range = vlan + + + self.assertEqual(range, "", "check if removing the range is successful") + + + def tearDown(self): # Teardown will delete the Account as well as the VM once the VM reaches "Running" state + """ + And finally let us cleanup the resources we created by deleting the + account. All good unittests are atomic and rerunnable this way + """ + deleteAcct = deleteAccount.deleteAccountCmd() + deleteAcct.id = self.acctResponse.account.id + self.apiClient.deleteAccount(deleteAcct) +