diff --git a/api/src/com/cloud/api/commands/ListNetworksCmd.java b/api/src/com/cloud/api/commands/ListNetworksCmd.java index e7bea4d2d2f..9197c548d78 100644 --- a/api/src/com/cloud/api/commands/ListNetworksCmd.java +++ b/api/src/com/cloud/api/commands/ListNetworksCmd.java @@ -67,6 +67,10 @@ public class ListNetworksCmd extends BaseListProjectAndAccountResourcesCmd { @Parameter(name=ApiConstants.SPECIFY_IP_RANGES, type=CommandType.BOOLEAN, description="true if need to list only networks which support specifying ip ranges") private Boolean specifyIpRanges; + + @IdentityMapper(entityTableName="vpc") + @Parameter(name=ApiConstants.VPC_ID, type=CommandType.LONG, description="List networks by VPC") + private Long vpcId; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -112,7 +116,11 @@ public class ListNetworksCmd extends BaseListProjectAndAccountResourcesCmd { return specifyIpRanges; } - ///////////////////////////////////////////////////// + public Long getVpcId() { + return vpcId; + } + + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @Override diff --git a/api/src/com/cloud/api/commands/ListRoutersCmd.java b/api/src/com/cloud/api/commands/ListRoutersCmd.java index 2e713e66988..0fb4dcc65c9 100644 --- a/api/src/com/cloud/api/commands/ListRoutersCmd.java +++ b/api/src/com/cloud/api/commands/ListRoutersCmd.java @@ -18,7 +18,6 @@ import java.util.List; import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; -import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.BaseListProjectAndAccountResourcesCmd; import com.cloud.api.IdentityMapper; import com.cloud.api.Implementation; @@ -63,6 +62,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { @IdentityMapper(entityTableName="networks") @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, description="list by network id") private Long networkId; + + @IdentityMapper(entityTableName="vpc") + @Parameter(name=ApiConstants.VPC_ID, type=CommandType.LONG, description="List networks by VPC") + private Long vpcId; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -95,6 +98,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { public Long getNetworkId() { return networkId; } + + public Long getVpcId() { + return vpcId; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/com/cloud/api/commands/UpdateVPCOfferingCmd.java b/api/src/com/cloud/api/commands/UpdateVPCOfferingCmd.java index a31a8acb29b..38a519b52f2 100644 --- a/api/src/com/cloud/api/commands/UpdateVPCOfferingCmd.java +++ b/api/src/com/cloud/api/commands/UpdateVPCOfferingCmd.java @@ -46,7 +46,8 @@ public class UpdateVPCOfferingCmd extends BaseAsyncCmd{ @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, description="the display text of the VPC offering") private String displayText; - @Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="update state for the VPC offering") + @Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="update state for the VPC offering; " + + "supported states - Enabled/Disabled") private String state; ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/response/DomainRouterResponse.java b/api/src/com/cloud/api/response/DomainRouterResponse.java index 10c50f5eeec..bd7e7d07d6f 100644 --- a/api/src/com/cloud/api/response/DomainRouterResponse.java +++ b/api/src/com/cloud/api/response/DomainRouterResponse.java @@ -15,8 +15,8 @@ package com.cloud.api.response; import java.util.Date; import com.cloud.api.ApiConstants; -import com.cloud.utils.IdentityProxy; import com.cloud.serializer.Param; +import com.cloud.utils.IdentityProxy; import com.cloud.vm.VirtualMachine.State; import com.google.gson.annotations.SerializedName; @@ -133,6 +133,9 @@ public class DomainRouterResponse extends BaseResponse implements ControlledEnti @SerializedName("scriptsversion") @Param(description="the version of scripts") private String scriptsVersion; + @SerializedName(ApiConstants.VPC_ID) @Param(description="VPC the network belongs to") + private IdentityProxy vpcId = new IdentityProxy("vpc"); + @Override public Long getObjectId() { return getId(); @@ -301,4 +304,8 @@ public class DomainRouterResponse extends BaseResponse implements ControlledEnti public void setProjectName(String projectName) { this.projectName = projectName; } + + public void setVpcId(Long vpcId) { + this.vpcId.setValue(vpcId); + } } diff --git a/api/src/com/cloud/api/response/NetworkResponse.java b/api/src/com/cloud/api/response/NetworkResponse.java index 834248b8670..5cb2cb47a86 100644 --- a/api/src/com/cloud/api/response/NetworkResponse.java +++ b/api/src/com/cloud/api/response/NetworkResponse.java @@ -127,6 +127,9 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes @SerializedName(ApiConstants.SPECIFY_IP_RANGES) @Param(description="true if network supports specifying ip ranges, false otherwise") private Boolean specifyIpRanges; + @SerializedName(ApiConstants.VPC_ID) @Param(description="VPC the network belongs to") + private IdentityProxy vpcId = new IdentityProxy("vpc"); + public void setId(Long id) { this.id.setValue(id); } @@ -268,4 +271,8 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes public void setSpecifyIpRanges(Boolean specifyIpRanges) { this.specifyIpRanges = specifyIpRanges; } + + public void setVpcId(Long vpcId) { + this.vpcId.setValue(vpcId); + } } diff --git a/api/src/com/cloud/network/element/VpcProvider.java b/api/src/com/cloud/network/element/VpcProvider.java index e40d188f5e1..63d0ce5af2b 100644 --- a/api/src/com/cloud/network/element/VpcProvider.java +++ b/api/src/com/cloud/network/element/VpcProvider.java @@ -17,12 +17,8 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientNetworkCapacityException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.network.Network; import com.cloud.network.vpc.Vpc; -import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachineProfile; /** * @author Alena Prokharchyk diff --git a/api/src/com/cloud/network/vpc/VpcService.java b/api/src/com/cloud/network/vpc/VpcService.java index 5c1ebb3ad4c..e60a5a4224e 100644 --- a/api/src/com/cloud/network/vpc/VpcService.java +++ b/api/src/com/cloud/network/vpc/VpcService.java @@ -33,8 +33,10 @@ public interface VpcService { public VpcOffering createVpcOffering(String name, String displayText, List supportedServices); public Vpc getVpc(long vpcId); + + public Vpc getActiveVpc(long vpcId); - public List getVpcNetworks(long vpcId); + public List getVpcNetworks(long vpcId); Map> getVpcOffSvcProvidersMap(long vpcOffId); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 079aa039d2a..187843c5720 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -1650,6 +1650,8 @@ public class ApiResponseHelper implements ResponseGenerator { routerResponse.setDns1(zone.getDns1()); routerResponse.setDns2(zone.getDns2()); } + + routerResponse.setVpcId(router.getVpcId()); routerResponse.setObjectName("domainrouter"); return routerResponse; @@ -2884,6 +2886,7 @@ public class ApiResponseHelper implements ResponseGenerator { } response.setSpecifyIpRanges(network.getSpecifyIpRanges()); + response.setVpcId(network.getVpcId()); response.setObjectName("network"); return response; diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 23a50dc5b61..21e1d54e984 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -187,7 +187,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; -import com.cloud.vm.DomainRouterVO; import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; @@ -1168,8 +1167,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag _ipAddressDao.markAsUnavailable(ip.getId()); if (!applyIpAssociations(network, true)) { // if fail to apply ip assciations again, unassign ip address without updating resource -// count and - // generating usage event as there is no need to keep it in the db + // count and generating usage event as there is no need to keep it in the db _ipAddressDao.unassignIpAddress(ip.getId()); } } catch (Exception e) { @@ -1185,7 +1183,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag public boolean releasePublicIpAddress(long addrId, long userId, Account caller) { boolean success = true; - // Cleanup all ip address resources - PF/LB/Static nat rules if (!cleanupIpResources(addrId, userId, caller)) { success = false; @@ -1213,10 +1210,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } catch (ResourceUnavailableException e) { throw new CloudRuntimeException("We should never get to here because we used true when applyIpAssociations", e); } + } else { + if (ip.getState() == IpAddress.State.Releasing) { + _ipAddressDao.unassignIpAddress(ip.getId()); + } } if (success) { - s_logger.debug("released a public ip id=" + addrId); + s_logger.debug("Released a public ip id=" + addrId); } return success; @@ -2428,9 +2429,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag //validate vpc if (vpcId != null) { - Vpc vpc = _vpcMgr.getVpc(vpcId); + Vpc vpc = _vpcMgr.getActiveVpc(vpcId); if (vpc == null) { - throw new InvalidParameterValueException("Unable to find vpc by id " + vpcId); + throw new InvalidParameterValueException("Unable to find enabled vpc by id " + vpcId); } _accountMgr.checkAccess(caller, null, false, vpc); } @@ -2631,7 +2632,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { - Vpc vpc = _vpcMgr.getVpc(vpcId); + Vpc vpc = _vpcMgr.getActiveVpc(vpcId); //1) Validate if network can be created for VPC _vpcMgr.validateGuestNtkwForVpc(_configMgr.getNetworkOffering(ntwkOffId), cidr, networkDomain, owner, vpc); @@ -2895,6 +2896,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag boolean listAll = cmd.listAll(); boolean isRecursive = cmd.isRecursive(); Boolean specifyIpRanges = cmd.getSpecifyIpRanges(); + Long vpcId = cmd.getVpcId(); // 1) default is system to false if not specified // 2) reset parameter to false if it's specified by the regular user @@ -3005,21 +3007,25 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (domainId != null) { networksToReturn .addAll(listDomainLevelNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges), searchFilter, + buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, + physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId), searchFilter, domainId)); } if (!permittedAccounts.isEmpty()) { networksToReturn.addAll(listAccountSpecificNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges), searchFilter, + buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, + physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId), searchFilter, permittedAccounts)); } else if (domainId == null || listAll) { networksToReturn.addAll(listAccountSpecificNetworksByDomainPath( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges), searchFilter, path, + buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, + physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId), searchFilter, path, isRecursive)); } } else { - networksToReturn = _networksDao.search(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, null, skipProjectNetworks, restartRequired, specifyIpRanges), + networksToReturn = _networksDao.search(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, + guestIpType, trafficType, physicalNetworkId, null, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId), searchFilter); } @@ -3049,8 +3055,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - private SearchCriteria buildNetworkSearchCriteria(SearchBuilder sb, String keyword, Long id, Boolean isSystem, Long zoneId, String guestIpType, String trafficType, Long physicalNetworkId, - String aclType, boolean skipProjectNetworks, Boolean restartRequired, Boolean specifyIpRanges) { + private SearchCriteria buildNetworkSearchCriteria(SearchBuilder sb, String keyword, Long id, + Boolean isSystem, Long zoneId, String guestIpType, String trafficType, Long physicalNetworkId, + String aclType, boolean skipProjectNetworks, Boolean restartRequired, Boolean specifyIpRanges, Long vpcId) { SearchCriteria sc = sb.create(); if (isSystem != null) { @@ -3098,6 +3105,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (specifyIpRanges != null) { sc.addAnd("specifyIpRanges", SearchCriteria.Op.EQ, specifyIpRanges); } + + if (vpcId != null) { + sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId); + } return sc; } diff --git a/server/src/com/cloud/network/dao/IPAddressDao.java b/server/src/com/cloud/network/dao/IPAddressDao.java index 1b44b16ba9e..54867703f36 100755 --- a/server/src/com/cloud/network/dao/IPAddressDao.java +++ b/server/src/com/cloud/network/dao/IPAddressDao.java @@ -56,4 +56,7 @@ public interface IPAddressDao extends GenericDao { List listByPhysicalNetworkId(long physicalNetworkId); long countFreeIPs(); + + List listByAssociatedVpc(long vpcId, Boolean isSourceNat); + } diff --git a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java index 425c215c430..daa8c18b85b 100755 --- a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java +++ b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java @@ -67,6 +67,7 @@ public class IPAddressDaoImpl extends GenericDaoBase implemen AllFieldsSearch.and("oneToOneNat", AllFieldsSearch.entity().isOneToOneNat(), Op.EQ); AllFieldsSearch.and("sourcenetwork", AllFieldsSearch.entity().getSourceNetworkId(), Op.EQ); AllFieldsSearch.and("physicalNetworkId", AllFieldsSearch.entity().getPhysicalNetworkId(), Op.EQ); + AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), Op.EQ); AllFieldsSearch.done(); VlanDbIdSearchUnallocated = createSearchBuilder(); @@ -299,4 +300,16 @@ public class IPAddressDaoImpl extends GenericDaoBase implemen sc.setJoinParameters("vlans", "vlanType", VlanType.VirtualNetwork); return customSearch(sc, null).get(0); } + + @Override + public List listByAssociatedVpc(long vpcId, Boolean isSourceNat) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("vpcId", vpcId); + + if (isSourceNat != null) { + sc.setParameters("sourceNat", isSourceNat); + } + + return listBy(sc); + } } diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index 89a297e0754..4f352c86cd7 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -99,7 +99,11 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc return false; } - Vpc vpc = _vpcService.getVpc(vpcId); + Vpc vpc = _vpcService.getActiveVpc(vpcId); + if (vpc == null) { + s_logger.warn("Unable to find Enabled VPC by id " + vpcId); + return false; + } Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); @@ -142,7 +146,11 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc return false; } - Vpc vpc = _vpcService.getVpc(vpcId); + Vpc vpc = _vpcService.getActiveVpc(vpcId); + if (vpc == null) { + s_logger.warn("Unable to find Enabled VPC by id " + vpcId); + return false; + } Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); diff --git a/server/src/com/cloud/network/vpc/Dao/VpcDao.java b/server/src/com/cloud/network/vpc/Dao/VpcDao.java index e95b6674de1..75fd56e88b7 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcDao.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcDao.java @@ -12,6 +12,9 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.network.vpc.Dao; +import java.util.List; + +import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcVO; import com.cloud.utils.db.GenericDao; @@ -25,5 +28,9 @@ public interface VpcDao extends GenericDao{ * @return */ int getVpcCountByOfferingId(long offId); + + Vpc getActiveVpcById(long vpcId); + + List listByAccountId(long accountId); } diff --git a/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java b/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java index 4e32541e39f..6d6b03c220b 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java @@ -16,10 +16,13 @@ import java.util.List; import javax.ejb.Local; +import com.cloud.domain.Domain.State; +import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcVO; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; @@ -32,8 +35,8 @@ import com.cloud.utils.db.SearchCriteria.Op; @DB(txn = false) public class VpcDaoImpl extends GenericDaoBase implements VpcDao{ final GenericSearchBuilder CountByOfferingId; + final SearchBuilder AllFieldsSearch; - protected VpcDaoImpl() { super(); @@ -42,6 +45,12 @@ public class VpcDaoImpl extends GenericDaoBase implements VpcDao{ CountByOfferingId.and("offeringId", CountByOfferingId.entity().getVpcOfferingId(), Op.EQ); CountByOfferingId.and("removed", CountByOfferingId.entity().getRemoved(), Op.NULL); CountByOfferingId.done(); + + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ); + AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); + AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ); + AllFieldsSearch.done(); } @@ -52,5 +61,20 @@ public class VpcDaoImpl extends GenericDaoBase implements VpcDao{ List results = customSearch(sc, null); return results.get(0); } + + @Override + public Vpc getActiveVpcById(long vpcId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("id", vpcId); + sc.setParameters("state", State.Active); + return findOneBy(sc); + } + + @Override + public List listByAccountId(long accountId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("accountId", accountId); + return listBy(sc, null); + } } diff --git a/server/src/com/cloud/network/vpc/VpcManager.java b/server/src/com/cloud/network/vpc/VpcManager.java index e6f025024de..fe8105876b5 100644 --- a/server/src/com/cloud/network/vpc/VpcManager.java +++ b/server/src/com/cloud/network/vpc/VpcManager.java @@ -17,6 +17,8 @@ import java.util.Map; import java.util.Set; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.element.VpcProvider; @@ -78,4 +80,15 @@ public interface VpcManager extends VpcService{ * @return */ VpcProvider getVpcElement(); + + List getVpcsForAccount(long accountId); + + /** + * @param vpc + * @return + * @throws ConcurrentOperationException + * @throws ResourceUnavailableException + * @throws InsufficientCapacityException + */ + boolean destroyVpc(Vpc vpc) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 70c36ac2dac..b8e5dd54049 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -36,11 +36,13 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.UnsupportedServiceException; +import com.cloud.network.IPAddressVO; import com.cloud.network.Network; import com.cloud.network.Network.GuestType; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; +import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.element.VpcProvider; import com.cloud.network.vpc.VpcOffering.State; @@ -90,6 +92,8 @@ public class VpcManagerImpl implements VpcManager, Manager{ NetworkDao _ntwkDao; @Inject NetworkManager _ntwkMgr; + @Inject + IPAddressDao _ipAddressDao; private VpcProvider vpcElement = null; @@ -138,9 +142,8 @@ public class VpcManagerImpl implements VpcManager, Manager{ } @Override - public List getVpcNetworks(long vpcId) { - // TODO Auto-generated method stub - return null; + public List getVpcNetworks(long vpcId) { + return _ntwkDao.listByVpc(vpcId); } @Override @@ -226,12 +229,15 @@ public class VpcManagerImpl implements VpcManager, Manager{ return offering; } - - @Override public Vpc getVpc(long vpcId) { return _vpcDao.findById(vpcId); } + + @Override + public Vpc getActiveVpc(long vpcId) { + return _vpcDao.findById(vpcId); + } @Override public Map> getVpcOffSvcProvidersMap(long vpcOffId) { @@ -478,23 +484,47 @@ public class VpcManagerImpl implements VpcManager, Manager{ @ActionEvent(eventType = EventTypes.EVENT_VPC_DELETE, eventDescription = "deleting VPC") public boolean deleteVpc(long vpcId) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { UserContext.current().setEventDetails(" Id: " + vpcId); + Account caller = UserContext.current().getCaller(); // Verify vpc id - VpcVO vpc = _vpcDao.findById(vpcId); + Vpc vpc = getVpc(vpcId); if (vpc == null) { throw new InvalidParameterValueException("unable to find VPC id=" + vpcId); } + + //verify permissions + _accountMgr.checkAccess(caller, null, false, vpc); - // don't allow to delete vpc if it's in use by existing networks - int networksCount = _ntwkDao.getNetworkCountByVpcId(vpcId); + return destroyVpc(vpc); + } + + @Override + public boolean destroyVpc(Vpc vpc) throws ConcurrentOperationException, ResourceUnavailableException, + InsufficientCapacityException { + UserContext ctx = UserContext.current(); + + //don't allow to delete vpc if it's in use by existing networks + int networksCount = _ntwkDao.getNetworkCountByVpcId(vpc.getId()); if (networksCount > 0) { - throw new InvalidParameterValueException("Can't delete VPC " + vpcId + " as its used by " + networksCount + " networks"); + throw new InvalidParameterValueException("Can't delete VPC " + vpc + " as its used by " + networksCount + " networks"); } - //shutdown VPC - shutdownVpc(vpcId); + //mark VPC as disabled + s_logger.debug("Updating VPC " + vpc + " with state " + Vpc.State.Disabled + " as a part of vpc delete"); + VpcVO vpcVO = _vpcDao.findById(vpc.getId()); + vpcVO.setState(Vpc.State.Disabled); + _vpcDao.update(vpc.getId(), vpcVO); - if (_vpcDao.remove(vpcId)) { + //shutdown VPC + shutdownVpc(vpc.getId()); + + //cleanup vpc resources + if (!cleanupVpcResources(vpc.getId(), ctx.getCaller(), ctx.getCallerUserId())) { + s_logger.warn("Failed to cleanup resources for vpc " + vpc); + return false; + } + + if (_vpcDao.remove(vpc.getId())) { return true; } else { return false; @@ -652,9 +682,9 @@ public class VpcManagerImpl implements VpcManager, Manager{ User callerUser = _accountMgr.getActiveUser(ctx.getCallerUserId()); //check if vpc exists - Vpc vpc = getVpc(vpcId); + Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { - throw new InvalidParameterValueException("Unable to find vpc by id " + vpcId); + throw new InvalidParameterValueException("Unable to find Enabled vpc by id " + vpcId); } //permission check @@ -778,4 +808,26 @@ public class VpcManagerImpl implements VpcManager, Manager{ return vpcElement; } + + @Override + public List getVpcsForAccount(long accountId) { + return _vpcDao.listByAccountId(accountId); + } + + public boolean cleanupVpcResources(long vpcId, Account caller, long callerUserId) { + s_logger.debug("Cleaning up resources for vpc id=" + vpcId); + boolean success = true; + // release all ip addresses + List ipsToRelease = _ipAddressDao.listByAssociatedVpc(vpcId, null); + s_logger.debug("Releasing ips for vpc id=" + vpcId + " as a part of vpc cleanup"); + for (IPAddressVO ipToRelease : ipsToRelease) { + success = success && _ntwkMgr.releasePublicIpAddress(ipToRelease.getId(), callerUserId, caller); + if (!success) { + s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " cleanup"); + } + } + + return success; + + } } diff --git a/server/src/com/cloud/network/vpc/VpcVO.java b/server/src/com/cloud/network/vpc/VpcVO.java index ad12cc014d5..3d90f3ca8e7 100644 --- a/server/src/com/cloud/network/vpc/VpcVO.java +++ b/server/src/com/cloud/network/vpc/VpcVO.java @@ -12,9 +12,7 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.network.vpc; -import java.util.ArrayList; import java.util.Date; -import java.util.List; import java.util.UUID; import javax.persistence.Column; @@ -25,8 +23,6 @@ import javax.persistence.Id; import javax.persistence.Table; import com.cloud.api.Identity; -import com.cloud.network.Network; -import com.cloud.network.Network.Service; import com.cloud.utils.db.GenericDao; /** diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index c98a2977db5..3d2a57571f2 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -160,7 +160,6 @@ import com.cloud.network.NetworkVO; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.NetworkDao; -import com.cloud.offering.ServiceOffering; import com.cloud.org.Grouping.AllocationState; import com.cloud.projects.Project; import com.cloud.projects.Project.ListProjectResourcesCriteria; @@ -1552,6 +1551,7 @@ public class ManagementServerImpl implements ManagementServer { Long hostId = cmd.getHostId(); String keyword = cmd.getKeyword(); Long networkId = cmd.getNetworkId(); + Long vpcId = cmd.getVpcId(); Account caller = UserContext.current().getCaller(); List permittedAccounts = new ArrayList(); @@ -1572,6 +1572,7 @@ public class ManagementServerImpl implements ManagementServer { sb.and("dataCenterId", sb.entity().getDataCenterIdToDeployIn(), SearchCriteria.Op.EQ); sb.and("podId", sb.entity().getPodIdToDeployIn(), SearchCriteria.Op.EQ); sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ); + sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ); if (networkId != null) { SearchBuilder nicSearch = _nicDao.createSearchBuilder(); @@ -1598,24 +1599,34 @@ public class ManagementServerImpl implements ManagementServer { if (name != null) { sc.setParameters("name", "%" + name + "%"); } + if (id != null) { sc.setParameters("id", id); } + if (state != null) { sc.setParameters("state", state); } + if (zone != null) { sc.setParameters("dataCenterId", zone); } + if (pod != null) { sc.setParameters("podId", pod); } + if (hostId != null) { sc.setParameters("hostId", hostId); } + if (networkId != null) { sc.setJoinParameters("nicSearch", "networkId", networkId); } + + if (vpcId != null) { + sc.setParameters("vpcId", vpcId); + } return _routerDao.search(sc, searchFilter); } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index fd9c9c2099e..3503d3f475d 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -77,6 +77,8 @@ import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.VpnUserDao; import com.cloud.network.security.SecurityGroupManager; import com.cloud.network.security.dao.SecurityGroupDao; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcManager; import com.cloud.network.vpn.RemoteAccessVpnService; import com.cloud.projects.Project; import com.cloud.projects.Project.ListProjectResourcesCriteria; @@ -199,6 +201,8 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag private ProjectAccountDao _projectAccountDao; @Inject private IPAddressDao _ipAddressDao; + @Inject + private VpcManager _vpcMgr; private Adapters _userAuthenticators; @@ -572,20 +576,36 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } } } + + //Delete all VPCs + boolean vpcsDeleted = true; + s_logger.debug("Deleting vpcs for account " + account.getId()); + List vpcs = _vpcMgr.getVpcsForAccount(account.getId()); + for (Vpc vpc : vpcs) { - // release ip addresses belonging to the account - List ipsToRelease = _ipAddressDao.listByAccount(accountId); - for (IpAddress ip : ipsToRelease) { - s_logger.debug("Releasing ip " + ip + " as a part of account id=" + accountId + " cleanup"); - if (!_networkMgr.releasePublicIpAddress(ip.getId(), callerUserId, caller)) { - s_logger.warn("Failed to release ip address " + ip + " as a part of account id=" + accountId + " clenaup"); + if (!_vpcMgr.destroyVpc(vpc)) { + s_logger.warn("Unable to destroy VPC " + vpc + " as a part of account id=" + accountId + " cleanup."); accountCleanupNeeded = true; + vpcsDeleted = false; + } else { + s_logger.debug("VPC " + vpc.getId() + " successfully deleted as a part of account id=" + accountId + " cleanup."); + } + } + + if (vpcsDeleted) { + // release ip addresses belonging to the account + List ipsToRelease = _ipAddressDao.listByAccount(accountId); + for (IpAddress ip : ipsToRelease) { + s_logger.debug("Releasing ip " + ip + " as a part of account id=" + accountId + " cleanup"); + if (!_networkMgr.releasePublicIpAddress(ip.getId(), callerUserId, caller)) { + s_logger.warn("Failed to release ip address " + ip + " as a part of account id=" + accountId + " clenaup"); + accountCleanupNeeded = true; + } } } // delete account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned - // up - // successfully + // up successfully if (networksDeleted) { if (!_configMgr.deleteAccountSpecificVirtualRanges(accountId)) { accountCleanupNeeded = true; diff --git a/wscript b/wscript index 1f58c524567..05a9a1061b6 100644 --- a/wscript +++ b/wscript @@ -3,7 +3,7 @@ # the following two variables are used by the target "waf dist" # if you change 'em here, you need to change it also in cloud.spec, add a %changelog entry there, and add an entry in debian/changelog -VERSION = '3.0.3.2012-05-24T22:43:32Z' +VERSION = '3.0.3.2012-05-25T21:12:57Z' APPNAME = 'cloud' import shutil,os