[WIP] NSX: Add support to re-order ACL rules (NSX FW rules)

This commit is contained in:
Pearl Dsilva 2024-02-05 23:32:38 -05:00
parent 80365c8333
commit 8d48e305a5
8 changed files with 86 additions and 13 deletions

View File

@ -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<? extends NetworkACLItem> rules) throws ResourceUnavailableException;
boolean reorderAclRules(Vpc vpc, List<? extends NetworkACLItem> networkACLItems);
}

View File

@ -91,4 +91,6 @@ public interface NetworkACLManager {
boolean revokeACLItemsForPrivateGw(PrivateGateway gateway) throws ResourceUnavailableException;
boolean applyACLToPrivateGw(PrivateGateway gateway) throws ResourceUnavailableException;
boolean reorderAclRules(VpcVO vpc, List<? extends NetworkACLItem> networkACLItems);
}

View File

@ -700,6 +700,11 @@ NetworkACLServiceProvider, FirewallServiceProvider, ResourceStateAdapter {
return true;
}
@Override
public boolean reorderAclRules(Vpc vpc, List<? extends NetworkACLItem> networkACLItems) {
return true;
}
@Override
public boolean applyFWRules(Network network,
List<? extends FirewallRule> rules)

View File

@ -185,6 +185,11 @@ public class ContrailVpcElementImpl extends ContrailElementImpl implements Netwo
return true;
}
@Override
public boolean reorderAclRules(Vpc vpc, List<? extends NetworkACLItem> networkACLItems) {
return true;
}
@Override
public boolean applyACLItemsToPrivateGw(PrivateGateway privateGateway,
List<? extends NetworkACLItem> rules)

View File

@ -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<NsxNetworkRule> 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<? extends NetworkACLItem> networkACLItems) {
List<NsxNetworkRule> 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<? extends FirewallRule> rules) throws ResourceUnavailableException {

View File

@ -531,6 +531,11 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc
return result;
}
@Override
public boolean reorderAclRules(Vpc vpc, List<? extends NetworkACLItem> networkACLItems) {
return true;
}
@Override
protected Type getVirtualRouterProvider() {
return Type.VPCVirtualRouter;

View File

@ -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<? extends NetworkACLItem> networkACLItems) {
List<NetworkACLServiceProvider> 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<? extends NetworkACLItem> rules) throws ResourceUnavailableException {
List<VpcProvider> vpcElements = new ArrayList<VpcProvider>();
vpcElements.add((VpcProvider)_ntwkModel.getElementImplementingProvider(Network.Provider.VPCVirtualRouter.getName()));

View File

@ -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<NetworkACLItem> getAclRulesSortedByNumber(long aclId) {
List<NetworkACLItemVO> 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.