VPC: implemented vpc cleanup thread that cleans up Inactive VPCs (that were failed to delete)
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/b03265bc Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/b03265bc Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/b03265bc Branch: refs/heads/vpc Commit: b03265bc7675e8611ee153c0ea52142b7737987b Parents: cec5012 Author: Alena Prokharchyk <[email protected]> Authored: Wed Jun 27 14:38:21 2012 -0700 Committer: Alena Prokharchyk <[email protected]> Committed: Thu Jun 28 10:18:14 2012 -0700 ---------------------------------------------------------------------- .../cloud/network/firewall/NetworkACLService.java | 2 - api/src/com/cloud/network/vpc/Vpc.java | 2 +- server/src/com/cloud/configuration/Config.java | 3 +- .../src/com/cloud/network/NetworkManagerImpl.java | 15 +- .../network/firewall/FirewallManagerImpl.java | 2 +- .../network/lb/LoadBalancingRulesManagerImpl.java | 27 ++- .../VpcVirtualNetworkApplianceManagerImpl.java | 14 +- .../com/cloud/network/vpc/Dao/StaticRouteDao.java | 2 +- .../cloud/network/vpc/Dao/StaticRouteDaoImpl.java | 2 +- server/src/com/cloud/network/vpc/Dao/VpcDao.java | 2 + .../src/com/cloud/network/vpc/Dao/VpcDaoImpl.java | 10 +- .../com/cloud/network/vpc/NetworkACLManager.java | 38 +++ .../cloud/network/vpc/NetworkACLManagerImpl.java | 34 +++- .../src/com/cloud/network/vpc/VpcManagerImpl.java | 194 ++++++++++++--- .../src/com/cloud/projects/ProjectManagerImpl.java | 1 - server/src/com/cloud/user/AccountManagerImpl.java | 2 +- 16 files changed, 275 insertions(+), 75 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/api/src/com/cloud/network/firewall/NetworkACLService.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/firewall/NetworkACLService.java index d556844..3cdb058 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/firewall/NetworkACLService.java @@ -44,6 +44,4 @@ public interface NetworkACLService { */ List<? extends NetworkACL> listNetworkACLs(ListNetworkACLsCmd cmd); - List<? extends NetworkACL> listNetworkACLs(long guestNtwkId); - } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/api/src/com/cloud/network/vpc/Vpc.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/vpc/Vpc.java b/api/src/com/cloud/network/vpc/Vpc.java index 5e15bab..5efd2e8 100644 --- a/api/src/com/cloud/network/vpc/Vpc.java +++ b/api/src/com/cloud/network/vpc/Vpc.java @@ -22,7 +22,7 @@ import com.cloud.network.Network; public interface Vpc extends ControlledEntity{ public enum State { Enabled, - Disabled + Inactive } public static final String _supportedProviders = Network.Provider.VPCVirtualRouter.getName(); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/configuration/Config.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 8936544..f1239d1 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -336,7 +336,8 @@ public enum Config { CustomDiskOfferingMaxSize("Advanced", ManagementServer.class, Long.class, "custom.diskoffering.size.max", "1024", "Maximum size in GB for custom disk offering", null), ConsoleProxyServiceOffering("Advanced", ManagementServer.class, Long.class, "consoleproxy.service.offering", null, "Service offering used by console proxy; if NULL - system offering will be used", null), SecondaryStorageServiceOffering("Advanced", ManagementServer.class, Long.class, "secstorage.service.offering", null, "Service offering used by secondary storage; if NULL - system offering will be used", null), - HaTag("Advanced", ManagementServer.class, String.class, "ha.tag", null, "HA tag defining that the host marked with this tag can be used for HA purposes only", null); + HaTag("Advanced", ManagementServer.class, String.class, "ha.tag", null, "HA tag defining that the host marked with this tag can be used for HA purposes only", null), + VpcCleanupInterval("Advanced", ManagementServer.class, Integer.class, "vpc.cleanup.interval", "3600", "The interval (in seconds) between cleanup for Inactive VPCs", null); private final String _category; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/NetworkManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 67cb28a..9b70225 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1262,6 +1262,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag ip.setVpcId(vpcId); ip.setSourceNat(isSourceNat); _ipAddressDao.update(ipId, ip); + + //mark ip as allocated + markPublicIpAsAllocated(ip); txn.commit(); s_logger.debug("Successfully assigned ip " + ipToAssoc + " to vpc " + vpc); @@ -2603,7 +2606,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (vpcId != null) { Vpc vpc = _vpcMgr.getActiveVpc(vpcId); if (vpc == null) { - throw new InvalidParameterValueException("Unable to find enabled vpc by id " + vpcId); + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC "); + ex.addProxyObject("vpc", vpcId, "VPC"); + throw ex; } _accountMgr.checkAccess(caller, null, false, vpc); } @@ -5877,7 +5882,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag boolean success = true; Network network = getNetwork(networkId); - // remove all PF/Static Nat rules for the network + //remove all PF/Static Nat rules for the network try { if (_rulesMgr.revokeAllPFStaticNatRulesForNetwork(networkId, callerUserId, caller)) { s_logger.debug("Successfully cleaned up portForwarding/staticNat rules for network id=" + networkId); @@ -5891,7 +5896,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.warn("Failed to release portForwarding/StaticNat rules as a part of network id=" + networkId + " cleanup due to resourceUnavailable ", ex); } - // remove all LB rules for the network + //remove all LB rules for the network if (_lbMgr.removeAllLoadBalanacersForNetwork(networkId, caller, callerUserId)) { s_logger.debug("Successfully cleaned up load balancing rules for network id=" + networkId); } else { @@ -5900,7 +5905,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.warn("Failed to cleanup LB rules as a part of network id=" + networkId + " cleanup"); } - // revoke all firewall rules for the network + //revoke all firewall rules for the network try { if (_firewallMgr.revokeAllFirewallRulesForNetwork(networkId, callerUserId, caller)) { s_logger.debug("Successfully cleaned up firewallRules rules for network id=" + networkId); @@ -5914,7 +5919,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.warn("Failed to cleanup Firewall rules as a part of network id=" + networkId + " cleanup due to resourceUnavailable ", ex); } - // release all ip addresses + //release all ip addresses List<IPAddressVO> ipsToRelease = _ipAddressDao.listByAssociatedNetwork(networkId, null); for (IPAddressVO ipToRelease : ipsToRelease) { if (ipToRelease.getVpcId() != null) { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/firewall/FirewallManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index a364dbc..1c1c882 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -606,7 +606,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma for (FirewallRuleVO rule : fwRules) { // Mark all Firewall rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no -// need to send them one by one + // need to send them one by one revokeFirewallRule(rule.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 4afdacb..a777d9a 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -706,16 +706,16 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa } Long ipAddrId = lb.getSourceIpAddressId(); - IPAddressVO ipAddressVo = null; + IPAddressVO ipAddressVO = null; if (ipAddrId != null) { - ipAddressVo = _ipAddressDao.findById(ipAddrId); + ipAddressVO = _ipAddressDao.findById(ipAddrId); // Validate ip address - if (ipAddressVo == null) { + if (ipAddressVO == null) { throw new InvalidParameterValueException("Unable to create load balance rule; ip id=" + ipAddrId + "" + " doesn't exist in the system"); - } else if (ipAddressVo.isOneToOneNat()) { - throw new NetworkRuleConflictException("Can't do load balance on ip address: " + ipAddressVo.getAddress()); + } else if (ipAddressVO.isOneToOneNat()) { + throw new NetworkRuleConflictException("Can't do load balance on ip address: " + ipAddressVO.getAddress()); } } @@ -724,18 +724,23 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa IpAddress ip = null; Network guestNetwork = _networkMgr.getNetwork(lb.getNetworkId()); NetworkOffering off = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); - if (off.getElasticLb() && ipAddressVo == null) { + if (off.getElasticLb() && ipAddressVO == null) { ip = _networkMgr.assignSystemIp(lb.getNetworkId(), lbOwner, true, false); lb.setSourceIpAddressId(ip.getId()); } try { - if (ip.getAssociatedWithNetworkId() == null) { - s_logger.debug("The ip is not associated with the network id="+ lb.getNetworkId() + " so assigning"); - ip = _networkMgr.associateIPToGuestNetwork(ipAddrId, lb.getNetworkId()); + if (ipAddressVO != null) { + if (ipAddressVO.getAssociatedWithNetworkId() == null) { + s_logger.debug("The ip is not associated with the network id="+ lb.getNetworkId() + " so assigning"); + ipAddressVO = _networkMgr.associateIPToGuestNetwork(ipAddrId, lb.getNetworkId()); + } + _networkMgr.checkIpForService(ipAddressVO, Service.Lb); + } + + if (lb.getSourceIpAddressId() == null) { + throw new CloudRuntimeException("No ip address is defined to assign the LB to"); } - ipAddressVo = _ipAddressDao.findById(ipAddrId); - _networkMgr.checkIpForService(ipAddressVo, Service.Lb); result = createLoadBalancer(lb, openFirewall); } catch (Exception ex) { s_logger.warn("Failed to create load balancer due to ", ex); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index f3ae3c9..76ff190 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -70,8 +70,8 @@ import com.cloud.network.VirtualRouterProvider.VirtualRouterProviderType; import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.PhysicalNetworkDao; -import com.cloud.network.firewall.NetworkACLService; import com.cloud.network.rules.NetworkACL; +import com.cloud.network.vpc.NetworkACLManager; import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.StaticRoute; import com.cloud.network.vpc.StaticRouteProfile; @@ -104,15 +104,15 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian private static final Logger s_logger = Logger.getLogger(VpcVirtualNetworkApplianceManagerImpl.class); @Inject - VpcDao _vpcDao = null; + VpcDao _vpcDao; @Inject - VpcOfferingDao _vpcOffDao = null; + VpcOfferingDao _vpcOffDao; @Inject - PhysicalNetworkDao _pNtwkDao = null; + PhysicalNetworkDao _pNtwkDao; @Inject - NetworkService _ntwkService = null; + NetworkService _ntwkService; @Inject - NetworkACLService _networkACLService = null; + NetworkACLManager _networkACLMgr; @Inject VMInstanceDao _vmDao; @Inject @@ -850,7 +850,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian super.finalizeNetworkRulesForNetwork(cmds, router, provider, guestNetworkId); if (_networkMgr.isProviderSupportServiceInNetwork(guestNetworkId, Service.Firewall, Provider.VPCVirtualRouter)) { - List<? extends NetworkACL> networkACLs = _networkACLService.listNetworkACLs(guestNetworkId); + List<? extends NetworkACL> networkACLs = _networkACLMgr.listNetworkACLs(guestNetworkId); s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + router + " start for guest network id=" + guestNetworkId); if (!networkACLs.isEmpty()) { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/vpc/Dao/StaticRouteDao.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpc/Dao/StaticRouteDao.java b/server/src/com/cloud/network/vpc/Dao/StaticRouteDao.java index d5a7d35..a9515e8 100644 --- a/server/src/com/cloud/network/vpc/Dao/StaticRouteDao.java +++ b/server/src/com/cloud/network/vpc/Dao/StaticRouteDao.java @@ -27,7 +27,7 @@ public interface StaticRouteDao extends GenericDao<StaticRouteVO, Long>{ List<? extends StaticRoute> listByGatewayIdAndNotRevoked(long gatewayId); - List<? extends StaticRoute> listByVpcId(long vpcId); + List<StaticRouteVO> listByVpcId(long vpcId); long countRoutesByGateway(long gatewayId); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/vpc/Dao/StaticRouteDaoImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpc/Dao/StaticRouteDaoImpl.java b/server/src/com/cloud/network/vpc/Dao/StaticRouteDaoImpl.java index d88b89f..d4b195b 100644 --- a/server/src/com/cloud/network/vpc/Dao/StaticRouteDaoImpl.java +++ b/server/src/com/cloud/network/vpc/Dao/StaticRouteDaoImpl.java @@ -80,7 +80,7 @@ public class StaticRouteDaoImpl extends GenericDaoBase<StaticRouteVO, Long> impl } @Override - public List<? extends StaticRoute> listByVpcId(long vpcId) { + public List<StaticRouteVO> listByVpcId(long vpcId) { SearchCriteria<StaticRouteVO> sc = AllFieldsSearch.create(); sc.setParameters("vpcId", vpcId); return listBy(sc); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/vpc/Dao/VpcDao.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpc/Dao/VpcDao.java b/server/src/com/cloud/network/vpc/Dao/VpcDao.java index 75fd56e..ac8b0d4 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcDao.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcDao.java @@ -32,5 +32,7 @@ public interface VpcDao extends GenericDao<VpcVO, Long>{ Vpc getActiveVpcById(long vpcId); List<? extends Vpc> listByAccountId(long accountId); + + List<VpcVO> listInactiveVpcs(); } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java b/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java index 6d6b03c..e0ea5d9 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java @@ -16,7 +16,6 @@ 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; @@ -66,7 +65,7 @@ public class VpcDaoImpl extends GenericDaoBase<VpcVO, Long> implements VpcDao{ public Vpc getActiveVpcById(long vpcId) { SearchCriteria<VpcVO> sc = AllFieldsSearch.create(); sc.setParameters("id", vpcId); - sc.setParameters("state", State.Active); + sc.setParameters("state", Vpc.State.Enabled); return findOneBy(sc); } @@ -76,5 +75,12 @@ public class VpcDaoImpl extends GenericDaoBase<VpcVO, Long> implements VpcDao{ sc.setParameters("accountId", accountId); return listBy(sc, null); } + + @Override + public List<VpcVO> listInactiveVpcs() { + SearchCriteria<VpcVO> sc = AllFieldsSearch.create(); + sc.setParameters("state", Vpc.State.Inactive); + return listBy(sc, null); + } } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/vpc/NetworkACLManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java new file mode 100644 index 0000000..01f54f0 --- /dev/null +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -0,0 +1,38 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.network.vpc; + +import java.util.List; + +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.firewall.NetworkACLService; +import com.cloud.network.rules.NetworkACL; +import com.cloud.user.Account; + +/** + * @author Alena Prokharchyk + */ +public interface NetworkACLManager extends NetworkACLService{ + + /** + * @param networkId + * @param userId + * @param caller + * @return + * @throws ResourceUnavailableException + */ + boolean revokeAllNetworkACLsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException; + + List<? extends NetworkACL> listNetworkACLs(long guestNtwkId); + +} http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index be30e8c..e546565 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -63,8 +63,8 @@ import com.cloud.utils.net.NetUtils; * @author Alena Prokharchyk */ -@Local(value = { NetworkACLService.class}) -public class NetworkACLManagerImpl implements Manager,NetworkACLService{ +@Local(value = { NetworkACLService.class, NetworkACLManager.class}) +public class NetworkACLManagerImpl implements Manager,NetworkACLManager{ String _name; private static final Logger s_logger = Logger.getLogger(NetworkACLManagerImpl.class); @@ -289,7 +289,7 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLService{ if (rule == null || rule.getPurpose() != Purpose.NetworkACL) { throw new InvalidParameterValueException("Unable to find " + ruleId + " having purpose " + Purpose.NetworkACL); } - + _accountMgr.checkAccess(caller, null, true, rule); _firewallMgr.revokeRule(rule, caller, userId, false); @@ -298,7 +298,7 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLService{ if (apply) { List<FirewallRuleVO> rules = _firewallDao.listByNetworkAndPurpose(rule.getNetworkId(), Purpose.NetworkACL); - return _firewallMgr.applyFirewallRules(rules, false, caller); + success = _firewallMgr.applyFirewallRules(rules, false, caller); } else { success = true; } @@ -367,4 +367,30 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLService{ return _firewallDao.listByNetworkAndPurpose(guestNtwkId, Purpose.NetworkACL); } + @Override + public boolean revokeAllNetworkACLsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException { + + List<FirewallRuleVO> ACLs = _firewallDao.listByNetworkAndPurposeAndNotRevoked(networkId, Purpose.NetworkACL); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Releasing " + ACLs.size() + " Network ACLs for network id=" + networkId); + } + + for (FirewallRuleVO ACL : ACLs) { + // Mark all Firewall rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no + // need to send them one by one + revokeNetworkACL(ACL.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); + } + + // now send everything to the backend + boolean success = _firewallMgr.applyFirewallRules(ACLs, false, caller); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully released Network ACLs for network id=" + networkId + " and # of rules now = " + ACLs.size()); + } + + // Now we check again in case more rules have been inserted. + ACLs.addAll(_firewallDao.listByNetworkAndPurposeAndNotRevoked(networkId, Purpose.Firewall)); + return success && ACLs.size() == 0; + } + } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/network/vpc/VpcManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 93f17b8..f3b30e9 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -18,6 +18,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.naming.ConfigurationException; @@ -26,6 +29,7 @@ import org.apache.log4j.Logger; import com.cloud.api.commands.ListPrivateGatewaysCmd; import com.cloud.api.commands.ListStaticRoutesCmd; +import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter; @@ -67,11 +71,15 @@ import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.User; import com.cloud.user.UserContext; +import com.cloud.utils.NumbersUtil; import com.cloud.utils.Ternary; +import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; +import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -84,6 +92,7 @@ import com.cloud.vm.ReservationContext; import com.cloud.vm.ReservationContextImpl; import com.cloud.vm.dao.DomainRouterDao; + /** * @author Alena Prokharchyk */ @@ -118,9 +127,12 @@ public class VpcManagerImpl implements VpcManager, Manager{ @Inject StaticRouteDao _staticRouteDao; + private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker")); + private VpcProvider vpcElement = null; String _name; + int _cleanupInterval; @Override @DB @@ -146,11 +158,18 @@ public class VpcManagerImpl implements VpcManager, Manager{ txn.commit(); + ComponentLocator locator = ComponentLocator.getCurrentLocator(); + ConfigurationDao configDao = locator.getDao(ConfigurationDao.class); + Map<String, String> configs = configDao.getConfiguration(params); + String value = configs.get(Config.VpcCleanupInterval.key()); + _cleanupInterval = NumbersUtil.parseInt(value, 60 * 60); // 1 hour + return true; } @Override public boolean start() { + _executor.scheduleAtFixedRate(new VpcCleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS); return true; } @@ -256,7 +275,7 @@ public class VpcManagerImpl implements VpcManager, Manager{ @Override public Vpc getActiveVpc(long vpcId) { - return _vpcDao.findById(vpcId); + return _vpcDao.getActiveVpcById(vpcId); } @Override @@ -528,9 +547,9 @@ public class VpcManagerImpl implements VpcManager, Manager{ } //mark VPC as disabled - s_logger.debug("Updating VPC " + vpc + " with state " + Vpc.State.Disabled + " as a part of vpc delete"); + s_logger.debug("Updating VPC " + vpc + " with state " + Vpc.State.Inactive + " as a part of vpc delete"); VpcVO vpcVO = _vpcDao.findById(vpc.getId()); - vpcVO.setState(Vpc.State.Disabled); + vpcVO.setState(Vpc.State.Inactive); _vpcDao.update(vpc.getId(), vpcVO); //shutdown VPC @@ -545,7 +564,9 @@ public class VpcManagerImpl implements VpcManager, Manager{ return false; } + //update the instance with removed flag only when the cleanup is executed successfully if (_vpcDao.remove(vpc.getId())) { + s_logger.debug("Vpc " + vpc + " is removed succesfully"); return true; } else { return false; @@ -712,7 +733,9 @@ public class VpcManagerImpl implements VpcManager, Manager{ //check if vpc exists Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { - throw new InvalidParameterValueException("Unable to find Enabled vpc by id " + vpcId); + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); + ex.addProxyObject("vpc", vpcId, "VPC"); + throw ex; } //permission check @@ -872,10 +895,12 @@ public class VpcManagerImpl implements VpcManager, Manager{ return _vpcDao.listByAccountId(accountId); } - public boolean cleanupVpcResources(long vpcId, Account caller, long callerUserId) { + public boolean cleanupVpcResources(long vpcId, Account caller, long callerUserId) + throws ResourceUnavailableException, ConcurrentOperationException { s_logger.debug("Cleaning up resources for vpc id=" + vpcId); boolean success = true; - // release all ip addresses + + //1) release all ip addresses List<IPAddressVO> ipsToRelease = _ipAddressDao.listByAssociatedVpc(vpcId, null); s_logger.debug("Releasing ips for vpc id=" + vpcId + " as a part of vpc cleanup"); for (IPAddressVO ipToRelease : ipsToRelease) { @@ -883,6 +908,31 @@ public class VpcManagerImpl implements VpcManager, Manager{ if (!success) { s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " cleanup"); } + } + + if (success) { + s_logger.debug("Released ip addresses for vpc id=" + vpcId + " as a part of cleanup vpc process"); + } else { + s_logger.warn("Failed to release ip addresses for vpc id=" + vpcId + " as a part of cleanup vpc process"); + //although it failed, proceed to the next cleanup step as it doesn't depend on the public ip release + } + + //2) Delete all static route rules + if (!revokeStaticRoutesForVpc(vpcId, caller)) { + s_logger.warn("Failed to revoke static routes for vpc " + vpcId + " as a part of cleanup vpc process"); + return false; + } + + //3) Delete private gateway + PrivateGateway gateway = getVpcPrivateGateway(vpcId); + if (gateway != null) { + s_logger.debug("Deleting private gateway " + gateway + " as a part of vpc " + vpcId + " resources cleanup"); + if (!deleteVpcPrivateGateway(gateway.getId())) { + success = false; + s_logger.debug("Failed to delete private gateway " + gateway + " as a part of vpc " + vpcId + " resources cleanup"); + } else { + s_logger.debug("Deleted private gateway " + gateway + " as a part of vpc " + vpcId + " resources cleanup"); + } } return success; @@ -896,9 +946,11 @@ public class VpcManagerImpl implements VpcManager, Manager{ Account caller = UserContext.current().getCaller(); // Verify input parameters - VpcVO vpc = _vpcDao.findById(vpcId); + Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { - throw new InvalidParameterValueException("Unable to find vpc offering " + vpcId); + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); + ex.addProxyObject("vpc", vpcId, "VPC"); + throw ex; } _accountMgr.checkAccess(caller, null, false, vpc); @@ -906,7 +958,7 @@ public class VpcManagerImpl implements VpcManager, Manager{ s_logger.debug("Restarting VPC " + vpc); boolean restartRequired = false; try { - s_logger.debug("Shuttign down VPC " + vpc + " as a part of VPC restart process"); + s_logger.debug("Shutting down VPC " + vpc + " as a part of VPC restart process"); if (!shutdownVpc(vpcId)) { s_logger.warn("Failed to shutdown vpc as a part of VPC " + vpc + " restart process"); restartRequired = true; @@ -923,8 +975,9 @@ public class VpcManagerImpl implements VpcManager, Manager{ return true; } finally { s_logger.debug("Updating VPC " + vpc + " with restartRequired=" + restartRequired); - vpc.setRestartRequired(restartRequired); - _vpcDao.update(vpc.getId(), vpc); + VpcVO vo = _vpcDao.findById(vpcId); + vo.setRestartRequired(restartRequired); + _vpcDao.update(vpc.getId(), vo); } } @@ -958,9 +1011,11 @@ public class VpcManagerImpl implements VpcManager, Manager{ ConcurrentOperationException, InsufficientCapacityException { //Validate parameters - Vpc vpc = getVpc(vpcId); + Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { - throw new InvalidParameterValueException("Unable to find VPC by id given"); + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); + ex.addProxyObject("vpc", vpcId, "VPC"); + throw ex; } //allow only one private gateway per vpc @@ -1018,8 +1073,15 @@ public class VpcManagerImpl implements VpcManager, Manager{ if (gatewayVO == null || gatewayVO.getType() != VpcGateway.Type.Private) { throw new InvalidParameterValueException("Can't find private gateway by id specified"); } + + //don't allow to remove gateway when there are static routes associated with it + long routeCount = _staticRouteDao.countRoutesByGateway(gatewayVO.getId()); + if (routeCount > 0) { + throw new CloudRuntimeException("Can't delete private gateway " + gatewayVO + " as it has " + routeCount + + " static routes applied. Remove the routes first"); + } - //1) delete the gateaway on the backend + //1) delete the gateway on the backend PrivateGateway gateway = getVpcPrivateGateway(gatewayId); if (getVpcElement().deletePrivateGateway(gateway)) { s_logger.debug("Private gateway " + gateway + " was applied succesfully on the backend"); @@ -1028,22 +1090,15 @@ public class VpcManagerImpl implements VpcManager, Manager{ return false; } - //2) Delete private gateway - return deletePrivateGateway(gateway); + //2) Delete private gateway from the DB + return deletePrivateGatewayFromTheDB(gateway); } @DB - public boolean deletePrivateGateway(PrivateGateway gateway) { + protected boolean deletePrivateGatewayFromTheDB(PrivateGateway gateway) { //check if there are ips allocted in the network long networkId = gateway.getNetworkId(); - //don't allow to remove gateway when there are static routes associated with it - long routeCount = _staticRouteDao.countRoutesByGateway(gateway.getId()); - if (routeCount > 0) { - throw new CloudRuntimeException("Can't delete private gateway " + gateway + " as it has " + routeCount + - " static routes applied. Remove the routes first"); - } - boolean deleteNetwork = true; List<PrivateIpVO> privateIps = _privateIpDao.listByNetworkId(networkId); if (privateIps.size() > 1 || !privateIps.get(0).getIpAddress().equalsIgnoreCase(gateway.getIp4Address())) { @@ -1123,10 +1178,10 @@ public class VpcManagerImpl implements VpcManager, Manager{ public boolean applyStaticRoutes(long vpcId) throws ResourceUnavailableException { Account caller = UserContext.current().getCaller(); List<? extends StaticRoute> routes = _staticRouteDao.listByVpcId(vpcId); - return applyStaticRoutes(routes, caller); + return applyStaticRoutes(routes, caller, true); } - protected boolean applyStaticRoutes(List<? extends StaticRoute> routes, Account caller) throws ResourceUnavailableException { + protected boolean applyStaticRoutes(List<? extends StaticRoute> routes, Account caller, boolean updateRoutesInDB) throws ResourceUnavailableException { boolean success = true; List<StaticRouteProfile> staticRouteProfiles = new ArrayList<StaticRouteProfile>(routes.size()); Map<Long, PrivateGateway> gatewayMap = new HashMap<Long, PrivateGateway>(); @@ -1142,15 +1197,19 @@ public class VpcManagerImpl implements VpcManager, Manager{ s_logger.warn("Routes are not completely applied"); return false; } else { - for (StaticRoute route : routes) { - if (route.getState() == StaticRoute.State.Revoke) { - _staticRouteDao.remove(route.getId()); - } else if (route.getState() == StaticRoute.State.Add) { - StaticRouteVO ruleVO = _staticRouteDao.findById(route.getId()); - ruleVO.setState(StaticRoute.State.Active); - _staticRouteDao.update(ruleVO.getId(), ruleVO); + if (updateRoutesInDB) { + for (StaticRoute route : routes) { + if (route.getState() == StaticRoute.State.Revoke) { + _staticRouteDao.remove(route.getId()); + s_logger.debug("Removed route " + route + " from the DB"); + } else if (route.getState() == StaticRoute.State.Add) { + StaticRouteVO ruleVO = _staticRouteDao.findById(route.getId()); + ruleVO.setState(StaticRoute.State.Active); + _staticRouteDao.update(ruleVO.getId(), ruleVO); + s_logger.debug("Marked route " + route + " with state " + StaticRoute.State.Active); + } } - } + } } return success; @@ -1186,10 +1245,28 @@ public class VpcManagerImpl implements VpcManager, Manager{ _accountMgr.checkAccess(caller, null, false, route); - revokeStaticRoute(route, caller); + markStaticRouteForRevoke(route, caller); return applyStaticRoutes(route.getVpcId()); + } + + @DB + protected boolean revokeStaticRoutesForVpc(long vpcId, Account caller) throws ResourceUnavailableException { + //get all static routes for the vpc + List<StaticRouteVO> routes = _staticRouteDao.listByVpcId(vpcId); + s_logger.debug("Found " + routes.size() + " to revoke for the vpc " + vpcId); + if (!routes.isEmpty()) { + //mark all of them as revoke + Transaction txn = Transaction.currentTxn(); + txn.start(); + for (StaticRouteVO route : routes) { + markStaticRouteForRevoke(route, caller); + } + txn.commit(); + return applyStaticRoutes(vpcId); + } + return true; } @Override @@ -1204,7 +1281,10 @@ public class VpcManagerImpl implements VpcManager, Manager{ throw new InvalidParameterValueException("Invalid gateway id is given"); } - Vpc vpc = getVpc(gateway.getVpcId()); + Vpc vpc = getActiveVpc(gateway.getVpcId()); + if (vpc == null) { + throw new InvalidParameterValueException("Can't add static route to VPC that is being deleted"); + } _accountMgr.checkAccess(caller, null, false, vpc); if (!NetUtils.isValidCIDR(cidr)){ @@ -1294,7 +1374,7 @@ public class VpcManagerImpl implements VpcManager, Manager{ } } - protected void revokeStaticRoute(StaticRouteVO route, Account caller) { + protected void markStaticRouteForRevoke(StaticRouteVO route, Account caller) { s_logger.debug("Revoking static route " + route); if (caller != null) { _accountMgr.checkAccess(caller, null, false, route); @@ -1308,7 +1388,47 @@ public class VpcManagerImpl implements VpcManager, Manager{ } else if (route.getState() == StaticRoute.State.Add || route.getState() == StaticRoute.State.Active) { route.setState(StaticRoute.State.Revoke); _staticRouteDao.update(route.getId(), route); + s_logger.debug("Marked static route " + route + " with state " + StaticRoute.State.Revoke); } + } + + protected class VpcCleanupTask implements Runnable { + @Override + public void run() { + try { + GlobalLock lock = GlobalLock.getInternLock("VpcCleanup"); + if (lock == null) { + s_logger.debug("Couldn't get the global lock"); + return; + } + + if (!lock.lock(30)) { + s_logger.debug("Couldn't lock the db"); + return; + } + Transaction txn = null; + try { + txn = Transaction.open(Transaction.CLOUD_DB); + + // Cleanup inactive VPCs + List<VpcVO> inactiveVpcs = _vpcDao.listInactiveVpcs(); + s_logger.info("Found " + inactiveVpcs.size() + " removed VPCs to cleanup"); + for (VpcVO vpc : inactiveVpcs) { + s_logger.debug("Cleaning up " + vpc); + destroyVpc(vpc); + } + } catch (Exception e) { + s_logger.error("Exception ", e); + } finally { + if (txn != null) { + txn.close(); + } + lock.unlock(); + } + } catch (Exception e) { + s_logger.error("Exception ", e); + } + } } } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/projects/ProjectManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index 01fdeda..9b06e49 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -69,7 +69,6 @@ import com.cloud.utils.Ternary; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.concurrency.NamedThreadFactory; -import com.cloud.utils.AnnotationHelper; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; import com.cloud.utils.db.JoinBuilder; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b03265bc/server/src/com/cloud/user/AccountManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 6c7aa95..34e272d 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -233,7 +233,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag Map<String, String> configs = configDao.getConfiguration(params); String value = configs.get(Config.AccountCleanupInterval.key()); - _cleanupInterval = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour. + _cleanupInterval = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 day. _userAuthenticators = locator.getAdapters(UserAuthenticator.class); if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
