From 6e2cb083758c4e7f2cbe65d07b41bdedfe0a5d85 Mon Sep 17 00:00:00 2001 From: Wilder Rodrigues Date: Fri, 18 Jul 2014 16:50:47 +0200 Subject: [PATCH] fixing VPC IP Association and ACL rules. Have to rewrite in a better why the apply rules method in the Advanced Topology --- ...VpcVirtualNetworkApplianceManagerImpl.java | 7 -- .../network/rules/NicPlugInOutRules.java | 2 +- .../rules/VirtualNetworkApplianceFactory.java | 4 +- .../network/rules/VpcIpAssociationRules.java | 9 +- .../topology/AdvancedNetworkTopology.java | 110 +++++++++++++++++- .../topology/AdvancedNetworkVisitor.java | 5 +- 6 files changed, 116 insertions(+), 21 deletions(-) diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 9d11d12af4d..6a4376cf02b 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -397,13 +397,6 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return super.finalizeVirtualMachineProfile(profile, dest, context); } - protected boolean sendNetworkACLs(final VirtualRouter router, final List rules, final long guestNetworkId, final boolean isPrivateGateway) - throws ResourceUnavailableException { - Commands cmds = new Commands(Command.OnError.Continue); - createNetworkACLsCommands(rules, router, cmds, guestNetworkId, isPrivateGateway); - return sendCommandsToRouter(router, cmds); - } - private void createNetworkACLsCommands(final List rules, final VirtualRouter router, final Commands cmds, final long guestNetworkId, final boolean privateGateway) { List rulesTO = new ArrayList(); String guestVlan = null; diff --git a/server/src/com/cloud/network/rules/NicPlugInOutRules.java b/server/src/com/cloud/network/rules/NicPlugInOutRules.java index f4be96f6f68..b96e2b1c60d 100644 --- a/server/src/com/cloud/network/rules/NicPlugInOutRules.java +++ b/server/src/com/cloud/network/rules/NicPlugInOutRules.java @@ -127,7 +127,7 @@ public class NicPlugInOutRules extends RuleApplier { } } - // Let the IpAssociationRule call the visitor fot the NicPlugInOutRule + // The visit will be done from the AdvancedNetworkTopology, after the VpcIpAssociation is done. return true; } diff --git a/server/src/com/cloud/network/rules/VirtualNetworkApplianceFactory.java b/server/src/com/cloud/network/rules/VirtualNetworkApplianceFactory.java index 32f61ce1dc1..356f3bbe657 100644 --- a/server/src/com/cloud/network/rules/VirtualNetworkApplianceFactory.java +++ b/server/src/com/cloud/network/rules/VirtualNetworkApplianceFactory.java @@ -158,8 +158,8 @@ public class VirtualNetworkApplianceFactory { return ipAssociationRules; } - public VpcIpAssociationRules createVpcIpAssociationRules(final Network network, final List ipAddresses, final NicPlugInOutRules nicPlugInOutRules) { - VpcIpAssociationRules ipAssociationRules = new VpcIpAssociationRules(network, ipAddresses, nicPlugInOutRules); + public VpcIpAssociationRules createVpcIpAssociationRules(final Network network, final List ipAddresses) { + VpcIpAssociationRules ipAssociationRules = new VpcIpAssociationRules(network, ipAddresses); initBeans(ipAssociationRules); diff --git a/server/src/com/cloud/network/rules/VpcIpAssociationRules.java b/server/src/com/cloud/network/rules/VpcIpAssociationRules.java index bcda3603bb4..e3c9bedb3ac 100644 --- a/server/src/com/cloud/network/rules/VpcIpAssociationRules.java +++ b/server/src/com/cloud/network/rules/VpcIpAssociationRules.java @@ -47,16 +47,13 @@ public class VpcIpAssociationRules extends RuleApplier { private final List _ipAddresses; - private final NicPlugInOutRules _nicPlugInOutRules; - private Map _vlanMacAddress; private List _ipsToSend; - public VpcIpAssociationRules(final Network network, final List ipAddresses, final NicPlugInOutRules nicPlugInOutRules) { + public VpcIpAssociationRules(final Network network, final List ipAddresses) { super(network); _ipAddresses = ipAddresses; - _nicPlugInOutRules = nicPlugInOutRules; } @Override @@ -90,10 +87,6 @@ public class VpcIpAssociationRules extends RuleApplier { return _ipAddresses; } - public NicPlugInOutRules getNicPlugInOutRules() { - return _nicPlugInOutRules; - } - public Map getVlanMacAddress() { return _vlanMacAddress; } diff --git a/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java b/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java index 05ad17ffbc1..a39fed6196c 100644 --- a/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java +++ b/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java @@ -17,6 +17,7 @@ package org.apache.cloudstack.network.topology; +import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; @@ -24,8 +25,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.Pod; import com.cloud.deploy.DeployDestination; +import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.Status; import com.cloud.network.Network; import com.cloud.network.PublicIpAddress; import com.cloud.network.router.VirtualRouter; @@ -39,6 +45,7 @@ import com.cloud.network.rules.VpcIpAssociationRules; import com.cloud.network.vpc.NetworkACLItem; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; +import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineProfile; @Component @@ -105,14 +112,25 @@ public class AdvancedNetworkTopology extends BasicNetworkTopology { final Long podId = null; NicPlugInOutRules nicPlugInOutRules = _virtualNetworkApplianceFactory.createNicPluInOutRules(network, ipAddresses); - VpcIpAssociationRules ipAssociationRules = _virtualNetworkApplianceFactory.createVpcIpAssociationRules(network, ipAddresses, nicPlugInOutRules); + nicPlugInOutRules.accept(_advancedVisitor, router); - return applyRules(network, routers, typeString, isPodLevelException, podId, failWhenDisconnect, new RuleApplierWrapper(ipAssociationRules)); + VpcIpAssociationRules ipAssociationRules = _virtualNetworkApplianceFactory.createVpcIpAssociationRules(network, ipAddresses); + boolean result = applyRules(network, routers, typeString, isPodLevelException, podId, failWhenDisconnect, new RuleApplierWrapper(ipAssociationRules)); + + if (result) { + _advancedVisitor.visit(nicPlugInOutRules); + } + + return result; } @Override public boolean applyNetworkACLs(final Network network, final List rules, final List routers, final boolean isPrivateGateway) throws ResourceUnavailableException { + if (rules == null || rules.isEmpty()) { + s_logger.debug("No network ACLs to be applied for network " + network.getId()); + return true; + } s_logger.debug("APPLYING NETWORK ACLs RULES"); @@ -125,4 +143,92 @@ public class AdvancedNetworkTopology extends BasicNetworkTopology { return applyRules(network, routers, typeString, isPodLevelException, podId, failWhenDisconnect, new RuleApplierWrapper(aclsRules)); } + + @Override + public boolean applyRules(final Network network, final List routers, final String typeString, final boolean isPodLevelException, final Long podId, final boolean failWhenDisconnect, + final RuleApplierWrapper ruleApplierWrapper) + throws ResourceUnavailableException { + + if (routers == null || routers.isEmpty()) { + s_logger.warn("Unable to apply " + typeString + ", virtual router doesn't exist in the network " + network.getId()); + throw new ResourceUnavailableException("Unable to apply " + typeString, DataCenter.class, network.getDataCenterId()); + } + + RuleApplier ruleApplier = ruleApplierWrapper.getRuleType(); + + final DataCenter dc = _dcDao.findById(network.getDataCenterId()); + final boolean isZoneBasic = (dc.getNetworkType() == NetworkType.Basic); + + // isPodLevelException and podId is only used for basic zone + assert !((!isZoneBasic && isPodLevelException) || (isZoneBasic && isPodLevelException && podId == null)); + + final List connectedRouters = new ArrayList(); + final List disconnectedRouters = new ArrayList(); + boolean result = true; + final String msg = "Unable to apply " + typeString + " on disconnected router "; + for (final VirtualRouter router : routers) { + if (router.getState() == State.Running) { + s_logger.debug("Applying " + typeString + " in network " + network); + + if (router.isStopPending()) { + if (_hostDao.findById(router.getHostId()).getState() == Status.Up) { + throw new ResourceUnavailableException("Unable to process due to the stop pending router " + router.getInstanceName() + + " haven't been stopped after it's host coming back!", DataCenter.class, router.getDataCenterId()); + } + s_logger.debug("Router " + router.getInstanceName() + " is stop pending, so not sending apply " + typeString + " commands to the backend"); + continue; + } + + try { + ruleApplier.accept(_advancedVisitor, router); + + connectedRouters.add(router); + } catch (final AgentUnavailableException e) { + s_logger.warn(msg + router.getInstanceName(), e); + disconnectedRouters.add(router); + } + + //If rules fail to apply on one domR and not due to disconnection, no need to proceed with the rest + if (!result) { + if (isZoneBasic && isPodLevelException) { + throw new ResourceUnavailableException("Unable to apply " + typeString + " on router ", Pod.class, podId); + } + throw new ResourceUnavailableException("Unable to apply " + typeString + " on router ", DataCenter.class, router.getDataCenterId()); + } + + } else if (router.getState() == State.Stopped || router.getState() == State.Stopping) { + s_logger.debug("Router " + router.getInstanceName() + " is in " + router.getState() + ", so not sending apply " + typeString + " commands to the backend"); + } else { + s_logger.warn("Unable to apply " + typeString + ", virtual router is not in the right state " + router.getState()); + if (isZoneBasic && isPodLevelException) { + throw new ResourceUnavailableException("Unable to apply " + typeString + ", virtual router is not in the right state", Pod.class, podId); + } + throw new ResourceUnavailableException("Unable to apply " + typeString + ", virtual router is not in the right state", DataCenter.class, + router.getDataCenterId()); + } + } + + if (!connectedRouters.isEmpty()) { + if (!isZoneBasic && !disconnectedRouters.isEmpty() && disconnectedRouters.get(0).getIsRedundantRouter()) { + // These disconnected redundant virtual routers are out of sync now, stop them for synchronization + //[FIXME] handleSingleWorkingRedundantRouter(connectedRouters, disconnectedRouters, msg); + } + } else if (!disconnectedRouters.isEmpty()) { + for (final VirtualRouter router : disconnectedRouters) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(msg + router.getInstanceName() + "(" + router.getId() + ")"); + } + } + if (isZoneBasic && isPodLevelException) { + throw new ResourceUnavailableException(msg, Pod.class, podId); + } + throw new ResourceUnavailableException(msg, DataCenter.class, disconnectedRouters.get(0).getDataCenterId()); + } + + result = true; + if (failWhenDisconnect) { + result = !connectedRouters.isEmpty(); + } + return result; + } } \ No newline at end of file diff --git a/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java b/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java index 35c1755b98f..cdd9ba03314 100644 --- a/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java +++ b/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java @@ -77,7 +77,10 @@ public class AdvancedNetworkVisitor extends BasicNetworkVisitor { final Commands commands = nicPlugInOutRules.getNetUsageCommands(); - return _applianceManager.sendCommandsToRouter(router, commands); + if (commands.size() > 0) { + return _applianceManager.sendCommandsToRouter(router, commands); + } + return true; } @Override