diff --git a/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java b/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java index 8c3243c99f4..92d3519d596 100644 --- a/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java +++ b/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java @@ -21,6 +21,7 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.Vpc; public interface NetworkACLServiceProvider extends NetworkElement { @@ -32,4 +33,6 @@ public interface NetworkACLServiceProvider extends NetworkElement { */ boolean applyNetworkACLs(Network config, List rules) throws ResourceUnavailableException; + boolean reorderAclRules(Vpc vpc, List networkACLItems); + } diff --git a/engine/components-api/src/main/java/com/cloud/network/vpc/NetworkACLManager.java b/engine/components-api/src/main/java/com/cloud/network/vpc/NetworkACLManager.java index 4200ea8c601..9d1caa1c031 100644 --- a/engine/components-api/src/main/java/com/cloud/network/vpc/NetworkACLManager.java +++ b/engine/components-api/src/main/java/com/cloud/network/vpc/NetworkACLManager.java @@ -91,4 +91,6 @@ public interface NetworkACLManager { boolean revokeACLItemsForPrivateGw(PrivateGateway gateway) throws ResourceUnavailableException; boolean applyACLToPrivateGw(PrivateGateway gateway) throws ResourceUnavailableException; + + boolean reorderAclRules(VpcVO vpc, List networkACLItems); } diff --git a/plugins/network-elements/bigswitch/src/main/java/com/cloud/network/element/BigSwitchBcfElement.java b/plugins/network-elements/bigswitch/src/main/java/com/cloud/network/element/BigSwitchBcfElement.java index 776f76fabca..c4b8de2ed95 100644 --- a/plugins/network-elements/bigswitch/src/main/java/com/cloud/network/element/BigSwitchBcfElement.java +++ b/plugins/network-elements/bigswitch/src/main/java/com/cloud/network/element/BigSwitchBcfElement.java @@ -700,6 +700,11 @@ NetworkACLServiceProvider, FirewallServiceProvider, ResourceStateAdapter { return true; } + @Override + public boolean reorderAclRules(Vpc vpc, List networkACLItems) { + return true; + } + @Override public boolean applyFWRules(Network network, List rules) diff --git a/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailVpcElementImpl.java b/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailVpcElementImpl.java index 689b252b2a7..58169f22d7b 100644 --- a/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailVpcElementImpl.java +++ b/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailVpcElementImpl.java @@ -185,6 +185,11 @@ public class ContrailVpcElementImpl extends ContrailElementImpl implements Netwo return true; } + @Override + public boolean reorderAclRules(Vpc vpc, List networkACLItems) { + return true; + } + @Override public boolean applyACLItemsToPrivateGw(PrivateGateway privateGateway, List rules) diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java index 571e68496d6..e1f921957b5 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java @@ -66,6 +66,7 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.StaticNat; import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.NetworkACLItemVO; import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.StaticRouteProfile; import com.cloud.network.vpc.Vpc; @@ -89,7 +90,13 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.VMInstanceDao; import net.sf.ehcache.config.InvalidConfigurationException; +import org.apache.cloudstack.NsxAnswer; import org.apache.cloudstack.StartupNsxCommand; +import org.apache.cloudstack.agent.api.DeleteNsxDistributedFirewallRulesCommand; +import org.apache.cloudstack.api.command.admin.internallb.ConfigureInternalLoadBalancerElementCmd; +import org.apache.cloudstack.api.command.admin.internallb.CreateInternalLoadBalancerElementCmd; +import org.apache.cloudstack.api.command.admin.internallb.ListInternalLoadBalancerElementsCmd; +import org.apache.cloudstack.network.element.InternalLoadBalancerElementService; import org.apache.cloudstack.resource.NsxLoadBalancerMember; import org.apache.cloudstack.resource.NsxNetworkRule; import org.apache.cloudstack.resource.NsxOpObject; @@ -684,18 +691,7 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns List nsxDelNetworkRules = new ArrayList<>(); for (NetworkACLItem rule : rules) { String privatePort = getPrivatePortRangeForACLRule(rule); - NsxNetworkRule networkRule = new NsxNetworkRule.Builder() - .setRuleId(rule.getId()) - .setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ? transformCidrListValues(rule.getSourceCidrList()) : List.of("ANY")) - .setAclAction(transformActionValue(rule.getAction())) - .setTrafficType(rule.getTrafficType().toString()) - .setProtocol(rule.getProtocol().toUpperCase()) - .setPublicPort(String.valueOf(rule.getSourcePortStart())) - .setPrivatePort(privatePort) - .setIcmpCode(rule.getIcmpCode()) - .setIcmpType(rule.getIcmpType()) - .setService(Network.Service.NetworkACL) - .build(); + NsxNetworkRule networkRule = getNsxNetworkRuleForAcl(rule, privatePort); if (Arrays.asList(NetworkACLItem.State.Active, NetworkACLItem.State.Add).contains(rule.getState())) { nsxAddNetworkRules.add(networkRule); } else if (NetworkACLItem.State.Revoke == rule.getState()) { @@ -712,6 +708,35 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns return success && nsxService.addFirewallRules(network, nsxAddNetworkRules); } + @Override + public boolean reorderAclRules(Vpc vpc, List networkACLItems) { + List aclRulesList = new ArrayList<>(); + for (NetworkACLItem rule : networkACLItems) { + String privatePort = getPrivatePortRangeForACLRule(rule); + aclRulesList.add(getNsxNetworkRuleForAcl(rule, privatePort)); + } + DeleteNsxDistributedFirewallRulesCommand command = new DeleteNsxDistributedFirewallRulesCommand(vpc.getDomainId(), + vpc.getAccountId(), vpc.getZoneId(), vpc.getId(), network.getId(), netRules); + NsxAnswer result = nsxControllerUtils.sendNsxCommand(command, network.getDataCenterId()); + return result.getResult(); + return true; + } + + private NsxNetworkRule getNsxNetworkRuleForAcl(NetworkACLItem rule, String privatePort) { + return new NsxNetworkRule.Builder() + .setRuleId(rule.getId()) + .setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ? transformCidrListValues(rule.getSourceCidrList()) : List.of("ANY")) + .setAclAction(transformActionValue(rule.getAction())) + .setTrafficType(rule.getTrafficType().toString()) + .setProtocol(rule.getProtocol().toUpperCase()) + .setPublicPort(String.valueOf(rule.getSourcePortStart())) + .setPrivatePort(privatePort) + .setIcmpCode(rule.getIcmpCode()) + .setIcmpType(rule.getIcmpType()) + .setService(Network.Service.NetworkACL) + .build(); + } + @Override public boolean applyFWRules(Network network, List rules) throws ResourceUnavailableException { diff --git a/server/src/main/java/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/main/java/com/cloud/network/element/VpcVirtualRouterElement.java index d740f80bd25..6b79950949d 100644 --- a/server/src/main/java/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/main/java/com/cloud/network/element/VpcVirtualRouterElement.java @@ -531,6 +531,11 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc return result; } + @Override + public boolean reorderAclRules(Vpc vpc, List networkACLItems) { + return true; + } + @Override protected Type getVirtualRouterProvider() { return Type.VPCVirtualRouter; diff --git a/server/src/main/java/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/NetworkACLManagerImpl.java index d95cf9ac7af..6e0d8a6162e 100644 --- a/server/src/main/java/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -21,6 +21,7 @@ import java.util.List; import javax.inject.Inject; +import com.cloud.network.nsx.NsxProvider; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.PublishScope; @@ -369,6 +370,20 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana return applyACLToPrivateGw(gateway, rules); } + @Override + public boolean reorderAclRules(VpcVO vpc, List networkACLItems) { + List nsxElements = new ArrayList<>(); + nsxElements.add((NetworkACLServiceProvider) _ntwkModel.getElementImplementingProvider(Network.Provider.Nsx.getName())); + try { + for (final NetworkACLServiceProvider provider : nsxElements) { + return provider.reorderAclRules(networkACLItems); + } + } catch (final Exception ex) { + s_logger.debug("Failed to reorder ACLs on NSX due to: " + ex.getLocalizedMessage()); + } + return false; + } + private boolean applyACLToPrivateGw(final PrivateGateway gateway, final List rules) throws ResourceUnavailableException { List vpcElements = new ArrayList(); vpcElements.add((VpcProvider)_ntwkModel.getElementImplementingProvider(Network.Provider.VPCVirtualRouter.getName())); diff --git a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java index 52d92f16117..4dc62babe1c 100644 --- a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -986,7 +986,15 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ if (nextRule == null) { return moveRuleToTheBottom(ruleBeingMoved, allAclRules); } - return moveRuleBetweenAclRules(ruleBeingMoved, allAclRules, previousRule, nextRule); + NetworkACLItem networkACLItem = moveRuleBetweenAclRules(ruleBeingMoved, allAclRules, previousRule, nextRule); + VpcVO vpc = _vpcDao.findById(lockedAcl.getVpcId()); + final DataCenter dc = _entityMgr.findById(DataCenter.class, vpc.getZoneId()); + final NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(dc.getId()); + if (Objects.nonNull(nsxProvider)) { + allAclRules = getAllAclRulesSortedByNumber(lockedAcl.getId()); + _networkAclMgr.reorderAclRules(vpc, allAclRules); + } + return networkACLItem; } finally { _networkACLDao.releaseFromLockTable(ruleBeingMoved.getAclId()); } @@ -1050,6 +1058,11 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ return allAclRules; } + protected List getAclRulesSortedByNumber(long aclId) { + List allAclRules = getAllAclRulesSortedByNumber(aclId); + return new ArrayList<>(allAclRules); + } + /** * Moves an ACL to the space between to other rules. If there is already enough room to accommodate the ACL rule being moved, we simply get the 'number' field from the previous ACL rule and add one, and then define this new value as the 'number' value for the ACL rule being moved. * Otherwise, we will need to make room. This process is executed via {@link #updateAclRuleToNewPositionAndExecuteShiftIfNecessary(NetworkACLItem, int, List, int)}, which will create the space between ACL rules if necessary. This involves shifting ACL rules to accommodate the rule being moved.