This is an automated email from the ASF dual-hosted git repository.

pearl11594 pushed a commit to branch netris-integration-upstream
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit c1b7dee52ad7571bc5b6c9cec7e33f6bf22fd6b4
Author: Pearl Dsilva <[email protected]>
AuthorDate: Mon Feb 3 21:43:45 2025 -0500

    Phase5 - Support for ACLs in Netris (#31)
    
    * Add support for Netris ACLs
    
    * acl support
    
    * Make acl api call to netris to create the rule
    
    * refactor add acl rule to populate the right fields
    
    * support icmp type acl rule
    
    * acl rule creation - move netrisnetworkRule
    
    * Update ACL naming on Netris
    
    * Add support for Deletion of netris acls
    
    * Add support to delete and re-order ACL rules
    
    * support creation of default acl rules and replacing acl rules
    
    * fix NSXNetworkRule
---
 .../com/cloud/network/SDNProviderNetworkRule.java  | 196 ++++++++++++++++++---
 .../cloud/network/netris/NetrisNetworkRule.java    |  74 ++++++++
 .../com/cloud/network/netris/NetrisService.java    |   6 +
 .../agent/api/CreateNetrisACLCommand.java          | 120 +++++++++++++
 .../agent/api/DeleteNetrisACLCommand.java}         |  35 ++--
 ...NetrisNetworkRule.java => NetrisPortGroup.java} |   9 +-
 .../apache/cloudstack/resource/NetrisResource.java |  24 ++-
 .../resource/NetrisResourceObjectUtils.java        |   3 +-
 .../apache/cloudstack/service/NetrisApiClient.java |   4 +
 .../cloudstack/service/NetrisApiClientImpl.java    | 186 ++++++++++++++++---
 .../apache/cloudstack/service/NetrisElement.java   | 131 +++++++++++---
 .../cloudstack/service/NetrisServiceImpl.java      |  94 +++++++++-
 .../apache/cloudstack/resource/NsxNetworkRule.java |  11 +-
 .../apache/cloudstack/service/NsxApiClient.java    |  13 +-
 .../org/apache/cloudstack/service/NsxElement.java  | 110 ++++++------
 .../apache/cloudstack/service/NsxServiceImpl.java  |  17 +-
 .../cloudstack/service/NsxApiClientTest.java       |   6 +-
 .../cloudstack/service/NetrisServiceMockTest.java  |  14 ++
 18 files changed, 894 insertions(+), 159 deletions(-)

diff --git a/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java 
b/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java
index 15238f85bb6..a22db4287dc 100644
--- a/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java
+++ b/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java
@@ -20,27 +20,27 @@ import java.util.List;
 
 public class SDNProviderNetworkRule {
 
-    private long domainId;
-    private long accountId;
-    private long zoneId;
-    private Long networkResourceId;
-    private String networkResourceName;
-    private boolean isVpcResource;
-    private long vmId;
-    private long ruleId;
-    private String publicIp;
-    private String vmIp;
-    private String publicPort;
-    private String privatePort;
-    private String protocol;
-    private String algorithm;
-    private List<String> sourceCidrList;
-    private List<String> destinationCidrList;
-    private Integer icmpCode;
-
-    private Integer icmpType;
-    private String trafficType;
-    private Network.Service service;
+    protected long domainId;
+    protected long accountId;
+    protected long zoneId;
+    protected Long networkResourceId;
+    protected String networkResourceName;
+    protected boolean isVpcResource;
+    protected long vmId;
+    protected long ruleId;
+    protected String publicIp;
+    protected String vmIp;
+    protected String publicPort;
+    protected String privatePort;
+    protected String protocol;
+    protected String algorithm;
+    protected List<String> sourceCidrList;
+    protected List<String> destinationCidrList;
+    protected Integer icmpCode;
+
+    protected Integer icmpType;
+    protected String trafficType;
+    protected Network.Service service;
 
     public long getDomainId() {
         return domainId;
@@ -201,4 +201,158 @@ public class SDNProviderNetworkRule {
     public void setTrafficType(String trafficType) {
         this.trafficType = trafficType;
     }
+
+    public static class Builder {
+        public long domainId;
+        public long accountId;
+        public long zoneId;
+        public Long networkResourceId;
+        public String networkResourceName;
+        public boolean isVpcResource;
+        public long vmId;
+
+        public long ruleId;
+        public String publicIp;
+        public String vmIp;
+        public String publicPort;
+        public String privatePort;
+        public String protocol;
+        public String algorithm;
+        public List<String> sourceCidrList;
+        public List<String> destinationCidrList;
+        public String trafficType;
+        public Integer icmpType;
+        public Integer icmpCode;
+        public Network.Service service;
+
+        public Builder() {
+            // Default constructor
+        }
+
+        public Builder setDomainId(long domainId) {
+            this.domainId = domainId;
+            return this;
+        }
+
+        public Builder setAccountId(long accountId) {
+            this.accountId = accountId;
+            return this;
+        }
+
+        public Builder setZoneId(long zoneId) {
+            this.zoneId = zoneId;
+            return this;
+        }
+
+        public Builder setNetworkResourceId(Long networkResourceId) {
+            this.networkResourceId = networkResourceId;
+            return this;
+        }
+
+        public Builder setNetworkResourceName(String networkResourceName) {
+            this.networkResourceName = networkResourceName;
+            return this;
+        }
+
+        public Builder setVpcResource(boolean isVpcResource) {
+            this.isVpcResource = isVpcResource;
+            return this;
+        }
+
+
+        public Builder setVmId(long vmId) {
+            this.vmId = vmId;
+            return this;
+        }
+
+        public Builder setRuleId(long ruleId) {
+            this.ruleId = ruleId;
+            return this;
+        }
+
+        public Builder setPublicIp(String publicIp) {
+            this.publicIp = publicIp;
+            return this;
+        }
+
+        public Builder setVmIp(String vmIp) {
+            this.vmIp = vmIp;
+            return this;
+        }
+
+        public Builder setPublicPort(String publicPort) {
+            this.publicPort = publicPort;
+            return this;
+        }
+
+        public Builder setPrivatePort(String privatePort) {
+            this.privatePort = privatePort;
+            return this;
+        }
+
+        public Builder setProtocol(String protocol) {
+            this.protocol = protocol;
+            return this;
+        }
+
+        public Builder setAlgorithm(String algorithm) {
+            this.algorithm = algorithm;
+            return this;
+        }
+
+        public Builder setTrafficType(String trafficType) {
+            this.trafficType = trafficType;
+            return this;
+        }
+
+        public Builder setIcmpType(Integer icmpType) {
+            this.icmpType = icmpType;
+            return this;
+        }
+
+        public Builder setIcmpCode(Integer icmpCode) {
+            this.icmpCode = icmpCode;
+            return this;
+        }
+
+        public Builder setSourceCidrList(List<String> sourceCidrList) {
+            this.sourceCidrList = sourceCidrList;
+            return this;
+        }
+
+        public Builder setDestinationCidrList(List<String> 
destinationCidrList) {
+            this.destinationCidrList = destinationCidrList;
+            return this;
+        }
+
+        public Builder setService(Network.Service service) {
+            this.service = service;
+            return this;
+        }
+
+        public SDNProviderNetworkRule build() {
+            SDNProviderNetworkRule rule = new SDNProviderNetworkRule();
+            rule.setDomainId(this.domainId);
+            rule.setAccountId(this.accountId);
+            rule.setZoneId(this.zoneId);
+            rule.setNetworkResourceId(this.networkResourceId);
+            rule.setNetworkResourceName(this.networkResourceName);
+            rule.setVpcResource(this.isVpcResource);
+            rule.setVmId(this.vmId);
+            rule.setVmIp(this.vmIp);
+            rule.setPublicIp(this.publicIp);
+            rule.setPublicPort(this.publicPort);
+            rule.setPrivatePort(this.privatePort);
+            rule.setProtocol(this.protocol);
+            rule.setRuleId(this.ruleId);
+            rule.setAlgorithm(this.algorithm);
+            rule.setIcmpType(this.icmpType);
+            rule.setIcmpCode(this.icmpCode);
+            rule.setSourceCidrList(this.sourceCidrList);
+            rule.setDestinationCidrList(this.destinationCidrList);
+            rule.setTrafficType(this.trafficType);
+            rule.setService(service);
+            return rule;
+        }
+    }
 }
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java 
b/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java
new file mode 100644
index 00000000000..67612141f65
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with 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.
+package com.cloud.network.netris;
+
+import com.cloud.network.SDNProviderNetworkRule;
+
+
+public class NetrisNetworkRule {
+    public enum NetrisRuleAction {
+        PERMIT, DENY
+    }
+
+    private SDNProviderNetworkRule baseRule;
+    private NetrisRuleAction aclAction;
+    private String reason;
+
+    public NetrisNetworkRule(Builder builder) {
+        this.baseRule = builder.baseRule;
+        this.aclAction = builder.aclAction;
+        this.reason = builder.reason;
+    }
+
+    public NetrisRuleAction getAclAction() {
+        return aclAction;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+
+    public SDNProviderNetworkRule getBaseRule() {
+        return baseRule;
+    }
+
+    // Builder class extending the parent builder
+    public static class Builder {
+        private SDNProviderNetworkRule baseRule;
+        private NetrisRuleAction aclAction;
+        private String reason;
+
+        public Builder baseRule(SDNProviderNetworkRule baseRule) {
+            this.baseRule = baseRule;
+            return this;
+        }
+
+        public Builder aclAction(NetrisRuleAction aclAction) {
+            this.aclAction = aclAction;
+            return this;
+        }
+
+        public Builder reason(String reason) {
+            this.reason = reason;
+            return this;
+        }
+
+        public NetrisNetworkRule build() {
+            return new NetrisNetworkRule(this);
+        }
+    }
+}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisService.java 
b/api/src/main/java/com/cloud/network/netris/NetrisService.java
index 6fd860f26be..750a82ffe70 100644
--- a/api/src/main/java/com/cloud/network/netris/NetrisService.java
+++ b/api/src/main/java/com/cloud/network/netris/NetrisService.java
@@ -17,9 +17,12 @@
 package com.cloud.network.netris;
 
 import com.cloud.network.IpAddress;
+import com.cloud.network.Network;
 import com.cloud.network.SDNProviderNetworkRule;
 import com.cloud.network.vpc.Vpc;
 
+import java.util.List;
+
 public interface NetrisService {
     boolean createIPAMAllocationsForZoneLevelPublicRanges(long zoneId);
 
@@ -43,6 +46,9 @@ public interface NetrisService {
 
     boolean deleteStaticNatRule(long zoneId, long accountId, long domainId, 
String networkResourceName, Long networkResourceId, boolean isForVpc, String 
staticNatIp);
 
+    boolean addFirewallRules(Network network, List<NetrisNetworkRule> 
firewallRules);
+    boolean deleteFirewallRules(Network network, List<NetrisNetworkRule> 
firewallRules);
+
     boolean addOrUpdateStaticRoute(long zoneId, long accountId, long domainId, 
String networkResourceName, Long networkResourceId, boolean isForVpc, String 
prefix, String nextHop, Long routeId, boolean updateRoute);
 
     boolean deleteStaticRoute(long zoneId, long accountId, long domainId, 
String networkResourceName, Long networkResourceId, boolean isForVpc, String 
prefix, String nextHop, Long routeId);
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/agent/api/CreateNetrisACLCommand.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/agent/api/CreateNetrisACLCommand.java
new file mode 100644
index 00000000000..ea39cd7f366
--- /dev/null
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/agent/api/CreateNetrisACLCommand.java
@@ -0,0 +1,120 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with 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.
+package org.apache.cloudstack.agent.api;
+
+import org.apache.cloudstack.resource.NetrisPortGroup;
+
+public class CreateNetrisACLCommand extends NetrisCommand {
+    private String vpcName;
+    private Long vpcId;
+    private String action;
+    private String destPrefix;
+    private String sourcePrefix;
+    private Integer destPortStart;
+    private Integer destPortEnd;
+    private Integer icmpType;
+    private String protocol;
+    private NetrisPortGroup portGroup;
+    private String netrisAclName;
+    private String reason;
+
+
+    public CreateNetrisACLCommand(long zoneId, Long accountId, Long domainId, 
String name, Long id, String vpcName, Long vpcId, boolean isVpc, String action,
+                                  String sourcePrefix, String destPrefix, 
Integer destPortStart, Integer destPortEnd, String protocol) {
+        super(zoneId, accountId, domainId, name, id, isVpc);
+        this.vpcName = vpcName;
+        this.vpcId = vpcId;
+        this.action = action;
+        this.sourcePrefix = sourcePrefix;
+        this.destPrefix = destPrefix;
+        this.destPortStart = destPortStart;
+        this.destPortEnd = destPortEnd;
+        this.protocol = protocol;
+    }
+
+    public String getVpcName() {
+        return vpcName;
+    }
+
+    public void setVpcName(String vpcName) {
+        this.vpcName = vpcName;
+    }
+
+    public Long getVpcId() {
+        return vpcId;
+    }
+
+    public void setVpcId(Long vpcId) {
+        this.vpcId = vpcId;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public String getDestPrefix() {
+        return destPrefix;
+    }
+
+    public String getSourcePrefix() {
+        return sourcePrefix;
+    }
+
+    public Integer getDestPortStart() {
+        return destPortStart;
+    }
+
+    public Integer getDestPortEnd() {
+        return destPortEnd;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public NetrisPortGroup getPortGroup() {
+        return portGroup;
+    }
+
+    public void setPortGroup(NetrisPortGroup portGroup) {
+        this.portGroup = portGroup;
+    }
+
+    public Integer getIcmpType() {
+        return icmpType;
+    }
+
+    public void setIcmpType(Integer icmpType) {
+        this.icmpType = icmpType;
+    }
+
+    public String getNetrisAclName() {
+        return netrisAclName;
+    }
+
+    public void setNetrisAclName(String netrisAclName) {
+        this.netrisAclName = netrisAclName;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+
+    public void setReason(String reason) {
+        this.reason = reason;
+    }
+}
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/agent/api/DeleteNetrisACLCommand.java
similarity index 54%
copy from 
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
copy to 
plugins/network-elements/netris/src/main/java/org/apache/cloudstack/agent/api/DeleteNetrisACLCommand.java
index 153143b6d18..e4a4993a257 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/agent/api/DeleteNetrisACLCommand.java
@@ -14,34 +14,33 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
-package org.apache.cloudstack.resource;
-
-import com.cloud.network.SDNProviderNetworkRule;
+package org.apache.cloudstack.agent.api;
 
 import java.util.List;
 
-public class NsxNetworkRule extends SDNProviderNetworkRule {
-
-    public enum NsxRuleAction {
-        ALLOW, DROP
+public class DeleteNetrisACLCommand extends NetrisCommand {
+    Long vpcId;
+    String vpcName;
+    List<String> aclRuleNames;
+    public DeleteNetrisACLCommand(long zoneId, Long accountId, Long domainId, 
String name, Long id, boolean isVpc, Long vpcId, String vpcName) {
+        super(zoneId, accountId, domainId, name, id, isVpc);
+        this.vpcId = vpcId;
+        this.vpcName = vpcName;
     }
 
-    private List<NsxLoadBalancerMember> memberList;
-    private NsxRuleAction aclAction;
-
-    public List<NsxLoadBalancerMember> getMemberList() {
-        return memberList;
+    public Long getVpcId() {
+        return vpcId;
     }
 
-    public void setMemberList(List<NsxLoadBalancerMember> memberList) {
-        this.memberList = memberList;
+    public String getVpcName() {
+        return vpcName;
     }
 
-    public NsxRuleAction getAclAction() {
-        return aclAction;
+    public List<String> getAclRuleNames() {
+        return aclRuleNames;
     }
 
-    public void setAclAction(NsxRuleAction aclAction) {
-        this.aclAction = aclAction;
+    public void setAclRuleNames(List<String> aclRuleNames) {
+        this.aclRuleNames = aclRuleNames;
     }
 }
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisNetworkRule.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisPortGroup.java
similarity index 82%
rename from 
plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisNetworkRule.java
rename to 
plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisPortGroup.java
index 2f4eadd443d..13c4c90cf3f 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisNetworkRule.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisPortGroup.java
@@ -16,7 +16,12 @@
 // under the License.
 package org.apache.cloudstack.resource;
 
-import com.cloud.network.SDNProviderNetworkRule;
+public class NetrisPortGroup {
+    private String ports;
 
-public class NetrisNetworkRule extends SDNProviderNetworkRule {
+    public NetrisPortGroup(String ports) {
+        this.ports = ports;
+    }
+
+    public String getPorts() { return ports; }
 }
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResource.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResource.java
index 349b83132c7..989987b9a41 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResource.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResource.java
@@ -28,10 +28,12 @@ import com.cloud.agent.api.StartupCommand;
 import com.cloud.host.Host;
 import com.cloud.resource.ServerResource;
 import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.cloudstack.agent.api.CreateNetrisACLCommand;
 import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
 import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
+import org.apache.cloudstack.agent.api.DeleteNetrisACLCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
@@ -105,7 +107,11 @@ public class NetrisResource implements ServerResource {
         } else if (cmd instanceof DeleteNetrisNatRuleCommand) {
             return executeRequest((DeleteNetrisNatRuleCommand) cmd);
         } else if (cmd instanceof CreateOrUpdateNetrisNatCommand) {
-            return executeRequest((CreateOrUpdateNetrisNatCommand) cmd);
+          return executeRequest((CreateOrUpdateNetrisNatCommand) cmd);
+        } else if (cmd instanceof CreateNetrisACLCommand) {
+            return executeRequest((CreateNetrisACLCommand) cmd);
+        } else if (cmd instanceof DeleteNetrisACLCommand) {
+            return executeRequest((DeleteNetrisACLCommand) cmd);
         } else if (cmd instanceof DeleteNetrisStaticRouteCommand) {
             return executeRequest((DeleteNetrisStaticRouteCommand) cmd);
         } else if (cmd instanceof AddOrUpdateNetrisStaticRouteCommand) {
@@ -306,6 +312,22 @@ public class NetrisResource implements ServerResource {
         return new NetrisAnswer(cmd, true, "OK");
     }
 
+    private Answer executeRequest(CreateNetrisACLCommand cmd) {
+        boolean result = netrisApiClient.addAclRule(cmd);
+        if (!result) {
+            return new NetrisAnswer(cmd, false, String.format("Creation of 
Netris ACL rule: %s failed", cmd.getNetrisAclName()));
+        }
+        return new NetrisAnswer(cmd, true, "OK");
+    }
+
+    private Answer executeRequest(DeleteNetrisACLCommand cmd) {
+        boolean result = netrisApiClient.deleteAclRule(cmd);
+        if (!result) {
+            return new NetrisAnswer(cmd, false, String.format("Failed to 
delete Netris ACLs: %s", String.join("'", cmd.getAclRuleNames())));
+        }
+        return new NetrisAnswer(cmd, true, "OK");
+    }
+
     private Answer executeRequest(AddOrUpdateNetrisStaticRouteCommand cmd) {
         boolean result = netrisApiClient.addOrUpdateStaticRoute(cmd);
         if (!result) {
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
index f5f6072b604..32225fdd199 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
@@ -22,7 +22,7 @@ import org.apache.commons.lang3.ArrayUtils;
 public class NetrisResourceObjectUtils {
 
     public enum NetrisObjectType {
-        VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET, SNAT, STATICNAT, DNAT, 
STATICROUTE
+        VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET, SNAT, STATICNAT, DNAT, 
STATICROUTE, ACL
     }
 
     public static String retrieveNetrisResourceObjectName(NetrisCommand cmd, 
NetrisObjectType netrisObjectType, String... suffixes) {
@@ -77,6 +77,7 @@ public class NetrisResourceObjectUtils {
                 suffixes = new String[0];
                 break;
             case VNET:
+            case ACL:
                break;
             default:
                 stringBuilder.append(String.format("-%s", objectName));
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClient.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClient.java
index 83e8b5fe0a3..f5efb4b55ea 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClient.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClient.java
@@ -20,10 +20,12 @@ import io.netris.ApiException;
 import io.netris.model.GetSiteBody;
 import io.netris.model.VPCListing;
 import io.netris.model.response.TenantResponse;
+import org.apache.cloudstack.agent.api.CreateNetrisACLCommand;
 import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
 import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
+import org.apache.cloudstack.agent.api.DeleteNetrisACLCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
@@ -77,6 +79,8 @@ public interface NetrisApiClient {
     boolean createOrUpdateDNATRule(CreateOrUpdateNetrisNatCommand cmd);
     boolean createStaticNatRule(CreateOrUpdateNetrisNatCommand cmd);
     boolean deleteNatRule(DeleteNetrisNatRuleCommand cmd);
+    boolean addAclRule(CreateNetrisACLCommand cmd);
+    boolean deleteAclRule(DeleteNetrisACLCommand cmd);
     boolean addOrUpdateStaticRoute(AddOrUpdateNetrisStaticRouteCommand cmd);
     boolean deleteStaticRoute(DeleteNetrisStaticRouteCommand cmd);
     boolean releaseNatIp(ReleaseNatIpCommand cmd);
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
index bfed67a915a..77d5aa40591 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
@@ -21,6 +21,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
 import io.netris.ApiClient;
 import io.netris.ApiException;
 import io.netris.ApiResponse;
+import io.netris.api.v1.AclApi;
 import io.netris.api.v1.AuthenticationApi;
 import io.netris.api.v1.RoutesApi;
 import io.netris.api.v1.SitesApi;
@@ -29,6 +30,11 @@ import io.netris.api.v2.IpamApi;
 import io.netris.api.v2.NatApi;
 import io.netris.api.v2.VNetApi;
 import io.netris.api.v2.VpcApi;
+import io.netris.model.AclAddItem;
+import io.netris.model.AclBodyVpc;
+import io.netris.model.AclDeleteItem;
+import io.netris.model.AclGetBody;
+import io.netris.model.AclResponseGetOk;
 import io.netris.model.AllocationBody;
 import io.netris.model.AllocationBodyVpc;
 import io.netris.model.FilterBySites;
@@ -80,14 +86,17 @@ import io.netris.model.VnetsBody;
 import io.netris.model.response.AuthResponse;
 import io.netris.model.response.TenantResponse;
 import io.netris.model.response.TenantsResponse;
+import org.apache.cloudstack.agent.api.CreateNetrisACLCommand;
 import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
+import org.apache.cloudstack.agent.api.DeleteNetrisACLCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
+import org.apache.cloudstack.agent.api.NetrisCommand;
 import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
 import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
 import org.apache.cloudstack.resource.NetrisResourceObjectUtils;
@@ -98,14 +107,18 @@ import org.apache.logging.log4j.Logger;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
 public class NetrisApiClientImpl implements NetrisApiClient {
 
     private final Logger logger = LogManager.getLogger(getClass());
+    private static final String ANY_IP = "0.0.0.0/0";
+    private static final String[] PROTOCOL_LIST = new String[]{"TCP", "UDP", 
"ICMP", "ALL"};
 
     private static ApiClient apiClient;
 
@@ -296,6 +309,120 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
     }
 
     @Override
+    public boolean addAclRule(CreateNetrisACLCommand cmd) {
+        String aclName = cmd.getNetrisAclName();
+        try {
+            AclApi aclApi = apiClient.getApiStubForMethod(AclApi.class);
+            AclAddItem aclAddItem = new AclAddItem();
+            aclAddItem.setAction(cmd.getAction());
+            aclAddItem.setComment(String.format("ACL rule: %s. %s", 
cmd.getNetrisAclName(), cmd.getReason()));
+            aclAddItem.setName(aclName);
+            String protocol = cmd.getProtocol();
+            if ("TCP".equals(protocol)) {
+                aclAddItem.setEstablished(new BigDecimal(1));
+            } else {
+                aclAddItem.setReverse("yes");
+            }
+            if (!Arrays.asList(PROTOCOL_LIST).contains(protocol)) {
+                aclAddItem.setProto("ip");
+                aclAddItem.setSrcPortTo(cmd.getIcmpType());
+                // TODO: set proto number: where should the protocol number be 
set - API sets the protocol number to Src-from & to and Dest-from & to fields
+            } else if ("ICMP".equals(protocol)) {
+                aclAddItem.setProto("icmp");
+                if (cmd.getIcmpType() != -1) {
+                    aclAddItem.setIcmpType(cmd.getIcmpType());
+                }
+            } else {
+                aclAddItem.setProto(protocol.toLowerCase(Locale.ROOT));
+            }
+
+            aclAddItem.setDstPortFrom(cmd.getDestPortStart());
+            aclAddItem.setDstPortTo(cmd.getDestPortEnd());
+            aclAddItem.setDstPrefix(cmd.getDestPrefix());
+            aclAddItem.setSrcPrefix(cmd.getSourcePrefix());
+            aclAddItem.setSrcPortFrom(1);
+            aclAddItem.setSrcPortTo(65535);
+            if 
(NatPutBody.ProtocolEnum.ICMP.name().equalsIgnoreCase(protocol)) {
+                aclAddItem.setIcmpType(cmd.getIcmpType());
+            }
+            String netrisVpcName = getNetrisVpcName(cmd, cmd.getVpcId(), 
cmd.getVpcName());
+            VPCListing vpcResource = getNetrisVpcResource(netrisVpcName);
+            if (Objects.isNull(vpcResource)) {
+                return false;
+            }
+            AclBodyVpc vpc = new AclBodyVpc().id(vpcResource.getId());
+            aclAddItem.setVpc(vpc);
+            List<String> aclNames = List.of(aclName);
+            Pair<Boolean, List<BigDecimal>> resultAndMatchingAclIds = 
getMatchingAclIds(aclNames, netrisVpcName);
+            if (!resultAndMatchingAclIds.second().isEmpty()) {
+                logger.debug("Netris ACL rule: {} already exists", aclName);
+                return true;
+            }
+            aclApi.apiAclPost(aclAddItem);
+        } catch (ApiException e) {
+            logAndThrowException(String.format("Failed to create Netris ACL: 
%s", cmd.getNetrisAclName()), e);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean deleteAclRule(DeleteNetrisACLCommand cmd) {
+        List<String> aclNames = cmd.getAclRuleNames();
+        try {
+            AclApi aclApi = apiClient.getApiStubForMethod(AclApi.class);
+
+            String suffix = getNetrisVpcNameSuffix(cmd.getVpcId(), 
cmd.getVpcName(), cmd.getId(), cmd.getName(), cmd.isVpc());
+            String vpcName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VPC, suffix);
+            Pair<Boolean, List<BigDecimal>> resultAndMatchingAclIds = 
getMatchingAclIds(aclNames, vpcName);
+            Boolean result = resultAndMatchingAclIds.first();
+            List<BigDecimal> matchingAclIds = resultAndMatchingAclIds.second();
+            if (!result) {
+                logger.error("Could not find the Netris VPC resource with name 
{} and tenant ID {}", vpcName, tenantId);
+                return false;
+            }
+            if (matchingAclIds.isEmpty()) {
+                logger.warn("There doesn't seem to be any ACLs on Netris 
matching {}", aclNames.size() > 1 ? String.join(",", aclNames) : aclNames);
+                return true;
+            }
+            AclDeleteItem aclDeleteItem = new AclDeleteItem();
+            aclDeleteItem.setId(matchingAclIds);
+            aclDeleteItem.setTenantsID(String.valueOf(tenantId));
+            aclApi.apiAclDelete(aclDeleteItem);
+        } catch (ApiException e) {
+            logAndThrowException(String.format("Failed to delete Netris ACLs: 
%s", String.join(",", cmd.getAclRuleNames())), e);
+        }
+        return true;
+    }
+
+    Pair<Boolean, List<BigDecimal>> getMatchingAclIds(List<String> aclNames, 
String vpcName) {
+        try {
+            AclApi aclApi = apiClient.getApiStubForMethod(AclApi.class);
+            VPCListing vpcResource = getVpcByNameAndTenant(vpcName);
+            if (vpcResource == null) {
+                logger.error("Could not find the Netris VPC resource with name 
{} and tenant ID {}", vpcName, tenantId);
+                return new Pair<>(false, Collections.emptyList());
+            }
+            FilterByVpc vpcFilter = new FilterByVpc();
+            vpcFilter.add(vpcResource.getId());
+            FilterBySites siteFilter = new FilterBySites();
+            siteFilter.add(siteId);
+            AclResponseGetOk aclGetResponse = aclApi.apiAclGet(siteFilter, 
vpcFilter);
+            if (aclGetResponse == null || !aclGetResponse.isIsSuccess()) {
+                logger.warn("No ACLs were found to be present for the specific 
Netris VPC resource {}." +
+                        " Netris ACLs may have been deleted out of band.", 
vpcName);
+                return new Pair<>(true, Collections.emptyList());
+            }
+            List<AclGetBody> aclList = aclGetResponse.getData();
+            return new Pair<>(true, aclList.stream()
+                    .filter(acl -> aclNames.contains(acl.getName()))
+                    .map(acl -> BigDecimal.valueOf(acl.getId()))
+                    .collect(Collectors.toList()));
+        } catch (ApiException e) {
+            logAndThrowException("Failed to retrieve Netris ACLs", e);
+        }
+        return new Pair<>(true, Collections.emptyList());
+    }
+
     public boolean addOrUpdateStaticRoute(AddOrUpdateNetrisStaticRouteCommand 
cmd) {
         String prefix = cmd.getPrefix();
         String nextHop = cmd.getNextHop();
@@ -491,13 +618,6 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
         return new Pair<>(false, null);
     }
 
-    private void deleteNatSubnet(Integer netrisVpcId, String natIp) {
-        FilterByVpc vpcFilter = new FilterByVpc();
-        vpcFilter.add(netrisVpcId);
-        String netrisSubnetName = natIp + "/32";
-        deleteSubnetInternal(vpcFilter, null, netrisSubnetName);
-    }
-
     public void deleteNatRule(String natRuleName, Integer snatRuleId, String 
netrisVpcName) {
         logger.debug("Deleting NAT rule on Netris: {} for VPC {}", 
natRuleName, netrisVpcName);
         try {
@@ -597,9 +717,8 @@ public class NetrisApiClientImpl implements NetrisApiClient 
{
         String netrisV6Cidr = cmd.getIpv6Cidr();
         boolean isVpc = cmd.isVpc();
 
-        String suffix = getNetrisVpcNameSuffix(vpcId, vpcName, networkId, 
networkName, isVpc);
-        String netrisVpcName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VPC, suffix);
-        VPCListing associatedVpc = getVpcByNameAndTenant(netrisVpcName);
+        String netrisVpcName = getNetrisVpcName(cmd, vpcId, vpcName);
+        VPCListing associatedVpc = getNetrisVpcResource(netrisVpcName);
         if (associatedVpc == null) {
             logger.error("Failed to find Netris VPC with name: {}, to create 
the corresponding vNet for network {}", netrisVpcName, networkName);
             return false;
@@ -644,9 +763,8 @@ public class NetrisApiClientImpl implements NetrisApiClient 
{
         boolean isVpc = cmd.isVpc();
         String vnetCidr = cmd.getVNetCidr();
         try {
-            String suffix = getNetrisVpcNameSuffix(vpcId, vpcName, networkId, 
networkName, isVpc);
-            String netrisVpcName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VPC, suffix);
-            VPCListing associatedVpc = getVpcByNameAndTenant(netrisVpcName);
+            String netrisVpcName = getNetrisVpcName(cmd, vpcId, vpcName);
+            VPCListing associatedVpc = getNetrisVpcResource(netrisVpcName);
             if (associatedVpc == null) {
                 logger.error("Failed to find Netris VPC with name: {}, to 
create the corresponding vNet for network {}", netrisVpcName, networkName);
                 return false;
@@ -758,9 +876,8 @@ public class NetrisApiClientImpl implements NetrisApiClient 
{
         String vNetName = isVpc ?
                 String.format("V%s-N%s-%s", vpcId, networkId, networkName) :
                 String.format("N%s-%s", networkId, networkName);
-        String vpcSuffix = getNetrisVpcNameSuffix(vpcId, vpcName, networkId, 
networkName, isVpc);
-        String netrisVpcName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VPC, vpcSuffix);
-        VPCListing vpcResource = getVpcByNameAndTenant(netrisVpcName);
+        String netrisVpcName = getNetrisVpcName(cmd, vpcId, vpcName);
+        VPCListing vpcResource = getNetrisVpcResource(netrisVpcName);
         if (vpcResource == null) {
             logger.error("Could not find the Netris VPC resource with name {} 
and tenant ID {}", netrisVpcName, tenantId);
             return false;
@@ -781,9 +898,9 @@ public class NetrisApiClientImpl implements NetrisApiClient 
{
         NatGetBody existingNatRule = netrisNatRuleExists(ruleName);
         boolean ruleExists = Objects.nonNull(existingNatRule);
         if (!ruleExists) {
-            String destinationAddress = action == NatPostBody.ActionEnum.SNAT 
? "0.0.0.0/0" : cmd.getDestinationAddress() + "/32";
+            String destinationAddress = action == NatPostBody.ActionEnum.SNAT 
? ANY_IP : cmd.getDestinationAddress() + "/32";
             String destinationPort = cmd.getDestinationPort();
-            String sourceAddress = action == NatPostBody.ActionEnum.SNAT ? 
vpcCidr : "0.0.0.0/0";
+            String sourceAddress = action == NatPostBody.ActionEnum.SNAT ? 
vpcCidr : ANY_IP;
             String sourcePort = "1-65535";
             String snatToIp = action == NatPostBody.ActionEnum.SNAT ? 
targetIpSubnet : null;
             String dnatToIp = action == NatPostBody.ActionEnum.DNAT ? 
cmd.getSourceAddress() + "/32" : null;
@@ -834,9 +951,8 @@ public class NetrisApiClientImpl implements NetrisApiClient 
{
         boolean isVpc = cmd.isVpc();
 
         try {
-            String vpcSuffix = getNetrisVpcNameSuffix(vpcId, vpcName, 
networkId, networkName, isVpc);
-            String netrisVpcName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VPC, vpcSuffix);
-            VPCListing vpcResource = getVpcByNameAndTenant(netrisVpcName);
+            String netrisVpcName = getNetrisVpcName(cmd, vpcId, vpcName);
+            VPCListing vpcResource = getNetrisVpcResource(netrisVpcName);
             if (vpcResource == null) {
                 logger.error("Could not find the Netris VPC resource with name 
{} and tenant ID {}", netrisVpcName, tenantId);
                 return false;
@@ -856,7 +972,7 @@ public class NetrisApiClientImpl implements NetrisApiClient 
{
             site.setId(siteId);
             site.setName(siteName);
             natBody.setSite(site);
-            natBody.setSourceAddress("0.0.0.0/0");
+            natBody.setSourceAddress(ANY_IP);
             natBody.setDnatToIP(vmIp);
 
             NatBodyVpcVpc vpc = new NatBodyVpcVpc();
@@ -981,17 +1097,13 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
         return true;
     }
 
-    private void updateNatRequest(NatPostBody natBody) {
-
-    }
-
     private boolean updateSnatRuleInternal(String snatRuleName, String snatIP, 
String netrisVpcName, String networkName,
                                            String vNetName, Integer 
netisSnatId, String vpcCidr) {
         try {
             NatApi natApi = apiClient.getApiStubForMethod(NatApi.class);
             NatPutBody natBody = new NatPutBody();
             natBody.setAction(NatPutBody.ActionEnum.SNAT);
-            natBody.setDestinationAddress("0.0.0.0/0");
+            natBody.setDestinationAddress(ANY_IP);
             natBody.setName(snatRuleName);
             natBody.setProtocol(NatPutBody.ProtocolEnum.ALL);
 
@@ -1214,4 +1326,24 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
             throw new CloudRuntimeException("Failed to list Netris NAT rules");
         }
     }
+
+    private VPCListing getNetrisVpcResource(String netrisVpcName) {
+        VPCListing vpcResource = getVpcByNameAndTenant(netrisVpcName);
+        if (vpcResource == null) {
+            logger.error("Could not find the Netris VPC resource with name {} 
and tenant ID {}", netrisVpcName, tenantId);
+        }
+        return vpcResource;
+    }
+
+    private String getNetrisVpcName(NetrisCommand cmd, Long vpcId, String 
vpcName) {
+        String suffix = getNetrisVpcNameSuffix(vpcId, vpcName, cmd.getId(), 
cmd.getName(), cmd.isVpc());
+        return NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VPC, suffix);
+    }
+
+    private void deleteNatSubnet(Integer netrisVpcId, String natIp) {
+        FilterByVpc vpcFilter = new FilterByVpc();
+        vpcFilter.add(netrisVpcId);
+        String netrisSubnetName = natIp + "/32";
+        deleteSubnetInternal(vpcFilter, null, netrisSubnetName);
+    }
 }
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisElement.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisElement.java
index 96b7379d285..7ffa3363046 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisElement.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisElement.java
@@ -41,6 +41,7 @@ import com.cloud.network.Network;
 import com.cloud.network.NetworkModel;
 import com.cloud.network.PhysicalNetworkServiceProvider;
 import com.cloud.network.PublicIpAddress;
+import com.cloud.network.SDNProviderNetworkRule;
 import com.cloud.network.SDNProviderOpObject;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.network.dao.IPAddressVO;
@@ -86,7 +87,7 @@ import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.VMInstanceDao;
 import org.apache.cloudstack.StartupNetrisCommand;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.resource.NetrisNetworkRule;
+import com.cloud.network.netris.NetrisNetworkRule;
 import org.apache.cloudstack.resourcedetail.FirewallRuleDetailVO;
 import org.apache.cloudstack.resourcedetail.dao.FirewallRuleDetailsDao;
 import org.apache.logging.log4j.LogManager;
@@ -95,6 +96,7 @@ import org.springframework.stereotype.Component;
 
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -440,13 +442,93 @@ public class NetrisElement extends AdapterBase implements 
DhcpServiceProvider, D
     }
 
     @Override
-    public boolean applyNetworkACLs(Network config, List<? extends 
NetworkACLItem> rules) throws ResourceUnavailableException {
-        return true;
+    public boolean applyNetworkACLs(Network network, List<? extends 
NetworkACLItem> rules) throws ResourceUnavailableException {
+        if (!canHandle(network, Network.Service.NetworkACL)) {
+            return false;
+        }
+
+        List<NetrisNetworkRule> nsxDelNetworkRules = new ArrayList<>();
+        boolean success = true;
+        for (NetworkACLItem rule : rules) {
+            String privatePort = 
PortForwardingServiceProvider.getPrivatePortRangeForACLRule(rule);
+            NetrisNetworkRule networkRule = getNetrisNetworkRuleForAcl(rule, 
privatePort);
+            if (Arrays.asList(NetworkACLItem.State.Active, 
NetworkACLItem.State.Add).contains(rule.getState())) {
+                success = success && netrisService.addFirewallRules(network, 
List.of(networkRule));
+            } else if (NetworkACLItem.State.Revoke == rule.getState()) {
+                nsxDelNetworkRules.add(networkRule);
+            }
+        }
+
+        if (!nsxDelNetworkRules.isEmpty()) {
+            success = netrisService.deleteFirewallRules(network, 
nsxDelNetworkRules);
+            if (!success) {
+                logger.warn("Not all firewall rules were successfully 
deleted");
+            }
+        }
+        return success;
+    }
+
+    private NetrisNetworkRule getNetrisNetworkRuleForAcl(NetworkACLItem rule, 
String privatePort) {
+        SDNProviderNetworkRule baseNetworkRule = new 
SDNProviderNetworkRule.Builder()
+                .setRuleId(rule.getId())
+                .setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ? 
transformCidrListValues(rule.getSourceCidrList()) : List.of("ANY"))
+                .setTrafficType(rule.getTrafficType().toString())
+                .setProtocol(rule.getProtocol().toUpperCase())
+                .setPublicPort(String.valueOf(rule.getSourcePortStart()))
+                .setPrivatePort(String.valueOf(privatePort))
+                .setIcmpCode(rule.getIcmpCode())
+                .setIcmpType(rule.getIcmpType())
+                .setService(Network.Service.NetworkACL)
+                .build();
+        return new NetrisNetworkRule.Builder()
+                .baseRule(baseNetworkRule)
+                .aclAction(transformActionValue(rule.getAction()))
+                        .reason(rule.getReason())
+                .build();
+    }
+
+    protected List<String> transformCidrListValues(List<String> 
sourceCidrList) {
+        List<String> list = new ArrayList<>();
+        if 
(org.apache.commons.collections.CollectionUtils.isNotEmpty(sourceCidrList)) {
+            for (String cidr : sourceCidrList) {
+                if (cidr.equals("0.0.0.0/0")) {
+                    list.add("ANY");
+                } else {
+                    list.add(cidr);
+                }
+            }
+        }
+        return list;
+    }
+
+    protected NetrisNetworkRule.NetrisRuleAction 
transformActionValue(NetworkACLItem.Action action) {
+        if (action == NetworkACLItem.Action.Allow) {
+            return NetrisNetworkRule.NetrisRuleAction.PERMIT;
+        } else if (action == NetworkACLItem.Action.Deny) {
+            return NetrisNetworkRule.NetrisRuleAction.DENY;
+        }
+        String err = String.format("Unsupported action %s", action.toString());
+        logger.error(err);
+        throw new CloudRuntimeException(err);
     }
 
     @Override
     public boolean reorderAclRules(Vpc vpc, List<? extends Network> networks, 
List<? extends NetworkACLItem> networkACLItems) {
-        return false;
+        List<NetrisNetworkRule> aclRulesList = new ArrayList<>();
+        for (NetworkACLItem rule : networkACLItems) {
+            String privatePort = 
PortForwardingServiceProvider.getPrivatePortRangeForACLRule(rule);
+            aclRulesList.add(getNetrisNetworkRuleForAcl(rule, privatePort));
+        }
+        for (Network network: networks) {
+            netrisService.deleteFirewallRules(network, aclRulesList);
+        }
+        boolean success = true;
+        for (Network network : networks) {
+            for (NetrisNetworkRule aclRule : aclRulesList) {
+                success = success && netrisService.addFirewallRules(network, 
List.of(aclRule));
+            }
+        }
+        return success;
     }
 
     @Override
@@ -470,12 +552,12 @@ public class NetrisElement extends AdapterBase implements 
DhcpServiceProvider, D
         Long networkId = netrisObject.getNetworkVO() != null ? 
netrisObject.getNetworkVO().getId() : null;
         String networkName = netrisObject.getNetworkVO() != null ? 
netrisObject.getNetworkVO().getName() : null;
         String vpcCidr = netrisObject.getVpcVO() != null ? 
netrisObject.getVpcVO().getCidr() : null;
-
+        SDNProviderNetworkRule baseNetRule = networkRule.getBaseRule();
         return create ?
-                
netrisService.createPortForwardingRule(networkRule.getZoneId(), 
networkRule.getAccountId(), networkRule.getDomainId(),
-                        vpcName, vpcId, networkName, networkId, 
netrisObject.isVpcResource(), vpcCidr, networkRule) :
-                
netrisService.deletePortForwardingRule(networkRule.getZoneId(), 
networkRule.getAccountId(), networkRule.getDomainId(),
-                        vpcName, vpcId, networkName, networkId, 
netrisObject.isVpcResource(), vpcCidr, networkRule);
+                
netrisService.createPortForwardingRule(baseNetRule.getZoneId(), 
baseNetRule.getAccountId(), baseNetRule.getDomainId(),
+                        vpcName, vpcId, networkName, networkId, 
netrisObject.isVpcResource(), vpcCidr, baseNetRule) :
+                
netrisService.deletePortForwardingRule(baseNetRule.getZoneId(), 
baseNetRule.getAccountId(), baseNetRule.getDomainId(),
+                        vpcName, vpcId, networkName, networkId, 
netrisObject.isVpcResource(), vpcCidr, baseNetRule);
     }
 
     private boolean applyPFRulesInternal(Network network, 
List<PortForwardingRule> rules) {
@@ -492,20 +574,23 @@ public class NetrisElement extends AdapterBase implements 
DhcpServiceProvider, D
                 String privatePort = 
PortForwardingServiceProvider.getPrivatePFPortRange(rule);
                 FirewallRuleDetailVO ruleDetail = 
firewallRuleDetailsDao.findDetail(rule.getId(), ApiConstants.NETRIS_DETAIL_KEY);
 
-                NetrisNetworkRule networkRule = new NetrisNetworkRule();
-                networkRule.setDomainId(netrisObject.getDomainId());
-                networkRule.setAccountId(netrisObject.getAccountId());
-                networkRule.setZoneId(netrisObject.getZoneId());
-                
networkRule.setNetworkResourceId(netrisObject.getNetworkResourceId());
-                
networkRule.setNetworkResourceName(netrisObject.getNetworkResourceName());
-                networkRule.setVpcResource(netrisObject.isVpcResource());
-                networkRule.setVmId(Objects.nonNull(vm) ? vm.getId() : 0);
-                networkRule.setVmIp(Objects.nonNull(vm) ? 
vm.getPrivateIpAddress() : null);
-                networkRule.setPublicIp(publicIp.getAddress().addr());
-                networkRule.setPrivatePort(privatePort);
-                networkRule.setPublicPort(publicPort);
-                networkRule.setRuleId(rule.getId());
-                
networkRule.setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT));
+                SDNProviderNetworkRule baseNetworkRule = new 
SDNProviderNetworkRule.Builder()
+                        .setDomainId(netrisObject.getDomainId())
+                .setAccountId(netrisObject.getAccountId())
+                .setZoneId(netrisObject.getZoneId())
+                .setNetworkResourceId(netrisObject.getNetworkResourceId())
+                .setNetworkResourceName(netrisObject.getNetworkResourceName())
+                .setVpcResource(netrisObject.isVpcResource())
+                .setVmId(Objects.nonNull(vm) ? vm.getId() : 0)
+                .setVmIp(Objects.nonNull(vm) ? vm.getPrivateIpAddress() : null)
+                .setPublicIp(publicIp.getAddress().addr())
+                .setPrivatePort(privatePort)
+                .setPublicPort(publicPort)
+                .setRuleId(rule.getId())
+                .setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT))
+                        .build();
+
+                NetrisNetworkRule networkRule = new 
NetrisNetworkRule.Builder().baseRule(baseNetworkRule).build();
 
                 if (Arrays.asList(FirewallRule.State.Add, 
FirewallRule.State.Active).contains(rule.getState())) {
                     boolean pfRuleResult = addOrRemovePFRuleOnNetris(vm, rule, 
networkRule, netrisObject, true);
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisServiceImpl.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisServiceImpl.java
index 0a9fe4ac239..a615090c429 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisServiceImpl.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisServiceImpl.java
@@ -35,16 +35,19 @@ import com.cloud.network.dao.PhysicalNetworkVO;
 import com.cloud.network.element.NetrisProviderVO;
 import com.cloud.network.netris.NetrisService;
 import com.cloud.network.vpc.Vpc;
+import com.cloud.network.vpc.dao.VpcDao;
+import io.netris.model.NatPostBody;
+import org.apache.cloudstack.agent.api.CreateNetrisACLCommand;
 import com.cloud.utils.Pair;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
 import inet.ipaddr.IPAddress;
 import inet.ipaddr.IPAddressString;
-import io.netris.model.NatPostBody;
 import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
 import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
 import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
+import org.apache.cloudstack.agent.api.DeleteNetrisACLCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
 import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
@@ -56,6 +59,7 @@ import 
org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
+import com.cloud.network.netris.NetrisNetworkRule;
 import org.apache.cloudstack.resource.NetrisResourceObjectUtils;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -77,6 +81,8 @@ public class NetrisServiceImpl implements NetrisService, 
Configurable {
     @Inject
     private NetworkDao networkDao;
     @Inject
+    private VpcDao vpcDao;
+    @Inject
     private AgentManager agentMgr;
     @Inject
     private PhysicalNetworkDao physicalNetworkDao;
@@ -207,7 +213,9 @@ public class NetrisServiceImpl implements NetrisService, 
Configurable {
         cmd.setNetrisTag(netrisProvider.getNetrisTag());
         if (Objects.nonNull(networkId)) {
             Ipv6GuestPrefixSubnetNetworkMapVO ipv6PrefixNetworkMapVO = 
ipv6PrefixNetworkMapDao.findByNetworkId(networkId);
-            cmd.setIpv6Cidr(ipv6PrefixNetworkMapVO.getSubnet());
+            if (Objects.nonNull(ipv6PrefixNetworkMapVO)) {
+                cmd.setIpv6Cidr(ipv6PrefixNetworkMapVO.getSubnet());
+            }
         }
         NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
         return answer.getResult();
@@ -343,6 +351,88 @@ public class NetrisServiceImpl implements NetrisService, 
Configurable {
     }
 
     @Override
+    public boolean addFirewallRules(Network network, List<NetrisNetworkRule> 
firewallRules) {
+        Long zoneId = network.getDataCenterId();
+        Long accountId = network.getAccountId();
+        Long domainId = network.getDomainId();
+        Long vpcId = network.getVpcId();
+        Long networkId = network.getId();
+        String vpcName = null;
+        Vpc vpc = null;
+        if (Objects.nonNull(vpcId)) {
+            vpc = vpcDao.findById(vpcId);
+            if (Objects.nonNull(vpc)) {
+                vpcName = vpc.getName();
+            }
+        }
+        String networkName = network.getName();
+        NetrisNetworkRule rule = firewallRules.get(0);
+        SDNProviderNetworkRule baseNetworkRule = rule.getBaseRule();
+        String trafficType = 
baseNetworkRule.getTrafficType().toUpperCase(Locale.ROOT);
+        String sourcePrefix;
+        String destinationPrefix;
+        if ("INGRESS".equals(trafficType)) {
+            sourcePrefix = baseNetworkRule.getSourceCidrList().get(0);
+            destinationPrefix = network.getCidr();
+        } else {
+            sourcePrefix = network.getCidr();
+            destinationPrefix = baseNetworkRule.getSourceCidrList().get(0);
+        }
+        String srcPort;
+        String dstPort;
+        if (baseNetworkRule.getPrivatePort().contains("-")) {
+            srcPort = baseNetworkRule.getPrivatePort().split("-")[0];
+            dstPort = baseNetworkRule.getPrivatePort().split("-")[1];
+        } else {
+            srcPort = dstPort = baseNetworkRule.getPrivatePort();
+        }
+        CreateNetrisACLCommand cmd = new CreateNetrisACLCommand(zoneId, 
accountId, domainId, networkName, networkId,
+                vpcName, vpcId, Objects.nonNull(vpcId), 
rule.getAclAction().name().toLowerCase(Locale.ROOT), getPrefix(sourcePrefix), 
getPrefix(destinationPrefix),
+                "null".equals(srcPort) ? 1 : Integer.parseInt(srcPort),
+                "null".equals(dstPort) ? 65535 : Integer.parseInt(dstPort), 
baseNetworkRule.getProtocol());
+        String aclName = String.format("V%s-N%s-ACL%s", vpcId, networkId, 
rule.getBaseRule().getRuleId());
+        String netrisAclName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.ACL, aclName);
+        cmd.setNetrisAclName(netrisAclName);
+        cmd.setReason(rule.getReason());
+        if ("ICMP".equals(baseNetworkRule.getProtocol())) {
+            cmd.setIcmpType(baseNetworkRule.getIcmpType());
+        }
+        NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
+        return answer.getResult();
+    }
+
+    private String getPrefix(String prefix) {
+        if ("ANY".equals(prefix)) {
+            return NetUtils.ALL_IP4_CIDRS;
+        }
+        return prefix;
+    }
+
+    @Override
+    public boolean deleteFirewallRules(Network network, 
List<NetrisNetworkRule> firewallRules) {
+        long zoneId = network.getDataCenterId();
+        Long accountId = network.getAccountId();
+        Long domainId = network.getDomainId();
+        String networkName = network.getName();
+        Long networkId = network.getId();
+        String vpcName = null;
+        Long vpcId = network.getVpcId();
+        if (Objects.nonNull(vpcId)) {
+            vpcName = vpcDao.findById(vpcId).getName();
+        }
+        DeleteNetrisACLCommand cmd = new DeleteNetrisACLCommand(zoneId, 
accountId, domainId, networkName, networkId, 
Objects.nonNull(network.getVpcId()), vpcId, vpcName);
+        List<String> aclRuleNames = firewallRules.stream()
+                .map(rule -> {
+                    String aclName = String.format("V%s-N%s-ACL%s", vpcId, 
networkId, rule.getBaseRule().getRuleId());
+                    return 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.ACL, aclName);
+                })
+                .collect(Collectors.toList());
+        cmd.setAclRuleNames(aclRuleNames);
+
+        NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
+        return answer.getResult();
+    }
+
     public boolean addOrUpdateStaticRoute(long zoneId, long accountId, long 
domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, 
String prefix, String nextHop, Long routeId, boolean updateRoute) {
         AddOrUpdateNetrisStaticRouteCommand cmd = new 
AddOrUpdateNetrisStaticRouteCommand(zoneId, accountId, domainId, 
networkResourceName, networkResourceId, isForVpc, prefix, nextHop, routeId, 
updateRoute);
         NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
index 153143b6d18..9c85c49adde 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
@@ -20,15 +20,24 @@ import com.cloud.network.SDNProviderNetworkRule;
 
 import java.util.List;
 
-public class NsxNetworkRule extends SDNProviderNetworkRule {
+public class NsxNetworkRule {
 
     public enum NsxRuleAction {
         ALLOW, DROP
     }
 
+    private SDNProviderNetworkRule baseRule;
     private List<NsxLoadBalancerMember> memberList;
     private NsxRuleAction aclAction;
 
+    public SDNProviderNetworkRule getBaseRule() {
+        return baseRule;
+    }
+
+    public void setBaseRule(SDNProviderNetworkRule baseRule) {
+        this.baseRule = baseRule;
+    }
+
     public List<NsxLoadBalancerMember> getMemberList() {
         return memberList;
     }
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
index 1ba1cc0fcc3..86559f7e945 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
@@ -17,6 +17,7 @@
 package org.apache.cloudstack.service;
 
 import com.cloud.network.Network;
+import com.cloud.network.SDNProviderNetworkRule;
 import com.cloud.network.nsx.NsxService;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.vmware.nsx.cluster.Status;
@@ -1025,7 +1026,8 @@ public class NsxApiClient {
     }
 
     public void deleteDistributedFirewallRules(String segmentName, 
List<NsxNetworkRule> nsxRules) {
-        for(NsxNetworkRule rule : nsxRules) {
+        for(NsxNetworkRule nsxRule : nsxRules) {
+            SDNProviderNetworkRule rule = nsxRule.getBaseRule();
             String ruleId = 
NsxControllerUtils.getNsxDistributedFirewallPolicyRuleId(segmentName, 
rule.getRuleId());
            String svcName = getServiceName(ruleId, rule.getPrivatePort(), 
rule.getProtocol(), rule.getIcmpType(), rule.getIcmpCode());
             // delete rules
@@ -1043,10 +1045,11 @@ public class NsxApiClient {
         if (Objects.isNull(groupPath)) {
             throw new CloudRuntimeException(String.format("Failed to find 
group for segment %s", segmentName));
         }
-        for (NsxNetworkRule rule : nsxRules) {
+        for (NsxNetworkRule nsxRule : nsxRules) {
+            SDNProviderNetworkRule rule = nsxRule.getBaseRule();
             String ruleId = 
NsxControllerUtils.getNsxDistributedFirewallPolicyRuleId(segmentName, 
rule.getRuleId());
             Rule ruleToAdd = new Rule.Builder()
-                    .setAction(rule.getAclAction().toString())
+                    .setAction(nsxRule.getAclAction().toString())
                     .setId(ruleId)
                     .setDisplayName(ruleId)
                     .setResourceType("SecurityPolicy")
@@ -1060,7 +1063,7 @@ public class NsxApiClient {
         return rules;
     }
 
-    private List<String> 
getServicesListForDistributedFirewallRule(NsxNetworkRule rule, String 
segmentName) {
+    private List<String> 
getServicesListForDistributedFirewallRule(SDNProviderNetworkRule rule, String 
segmentName) {
         List<String> services = List.of("ANY");
         if (!rule.getProtocol().equalsIgnoreCase("all")) {
             String ruleName = String.format("%s-R%s", segmentName, 
rule.getRuleId());
@@ -1071,7 +1074,7 @@ public class NsxApiClient {
         return services;
     }
 
-    protected List<String> getGroupsForTraffic(NsxNetworkRule rule,
+    protected List<String> getGroupsForTraffic(SDNProviderNetworkRule rule,
                                              String segmentName, boolean 
source) {
         List<String> segmentGroup = List.of(String.format("%s/%s", 
GROUPS_PATH_PREFIX, segmentName));
         List<String> sourceCidrList = rule.getSourceCidrList();
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 4a9c4dddd22..f4cfefdac0c 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
@@ -45,6 +45,7 @@ import com.cloud.network.NetworkModel;
 import com.cloud.network.Networks;
 import com.cloud.network.PhysicalNetworkServiceProvider;
 import com.cloud.network.PublicIpAddress;
+import com.cloud.network.SDNProviderNetworkRule;
 import com.cloud.network.VirtualRouterProvider;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.network.dao.IPAddressVO;
@@ -562,27 +563,31 @@ public class NsxElement extends AdapterBase implements  
DhcpServiceProvider, Dns
 
                 String privatePort = 
PortForwardingServiceProvider.getPrivatePFPortRange(rule);
 
-                NsxNetworkRule networkRule = new NsxNetworkRule();
-                networkRule.setDomainId(nsxObject.getDomainId());
-                networkRule.setAccountId(nsxObject.getAccountId());
-                networkRule.setZoneId(nsxObject.getZoneId());
-                
networkRule.setNetworkResourceId(nsxObject.getNetworkResourceId());
-                
networkRule.setNetworkResourceName(nsxObject.getNetworkResourceName());
-                networkRule.setVpcResource(nsxObject.isVpcResource());
-                networkRule.setVmId(Objects.nonNull(vm) ? vm.getId() : 0);
-                networkRule.setVmIp(Objects.nonNull(vm) ? 
vm.getPrivateIpAddress() : null);
-                networkRule.setPublicIp(publicIp.getAddress().addr());
-                networkRule.setPrivatePort(privatePort);
-                networkRule.setPublicPort(publicPort);
-                networkRule.setRuleId(rule.getId());
-                
networkRule.setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT));
+                SDNProviderNetworkRule networkRule = new 
SDNProviderNetworkRule.Builder()
+                        .setDomainId(nsxObject.getDomainId())
+                        .setAccountId(nsxObject.getAccountId())
+                        .setZoneId(nsxObject.getZoneId())
+                        .setNetworkResourceId(nsxObject.getNetworkResourceId())
+                        
.setNetworkResourceName(nsxObject.getNetworkResourceName())
+                        .setVpcResource(nsxObject.isVpcResource())
+                        .setVmId(Objects.nonNull(vm) ? vm.getId() : 0)
+                        .setVmIp(Objects.nonNull(vm) ? 
vm.getPrivateIpAddress() : null)
+                        .setPublicIp(publicIp.getAddress().addr())
+                        .setPrivatePort(privatePort)
+                        .setPublicPort(publicPort)
+                        .setRuleId(rule.getId())
+                        
.setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT))
+                        .build();
+
+                NsxNetworkRule nsxNetworkRule = new NsxNetworkRule();
+                nsxNetworkRule.setBaseRule(networkRule);
 
                 FirewallRuleDetailVO ruleDetail = 
firewallRuleDetailsDao.findDetail(rule.getId(), ApiConstants.FOR_NSX);
                 if (Arrays.asList(FirewallRule.State.Add, 
FirewallRule.State.Active).contains(rule.getState())) {
                     if ((ruleDetail == null && FirewallRule.State.Add == 
rule.getState()) || (ruleDetail != null && 
!ruleDetail.getValue().equalsIgnoreCase("true"))) {
                         logger.debug("Creating port forwarding rule on NSX for 
VM {} to ports {} - {}",
                                 vm, rule.getDestinationPortStart(), 
rule.getDestinationPortEnd());
-                        NsxAnswer answer = 
nsxService.createPortForwardRule(networkRule);
+                        NsxAnswer answer = 
nsxService.createPortForwardRule(nsxNetworkRule);
                         boolean pfRuleResult = answer.getResult();
                         if (pfRuleResult && !answer.isObjectExistent()) {
                             logger.debug("Port forwarding rule {} created on 
NSX, adding detail on firewall rules details", rule);
@@ -599,7 +604,7 @@ public class NsxElement extends AdapterBase implements  
DhcpServiceProvider, Dns
                     }
                 } else if (rule.getState() == FirewallRule.State.Revoke) {
                     if (ruleDetail == null || (ruleDetail != null && 
ruleDetail.getValue().equalsIgnoreCase("true"))) {
-                        boolean pfRuleResult = 
nsxService.deletePortForwardRule(networkRule);
+                        boolean pfRuleResult = 
nsxService.deletePortForwardRule(nsxNetworkRule);
                         if (pfRuleResult && ruleDetail != null) {
                             logger.debug("Updating firewall rule detail {} () 
for rule {}, set to false", ruleDetail.getId(), ruleDetail.getName(), rule);
                             ruleDetail.setValue("false");
@@ -677,20 +682,23 @@ public class NsxElement extends AdapterBase implements  
DhcpServiceProvider, Dns
             SDNProviderOpObject nsxObject = getNsxOpObject(network);
 
             List<NsxLoadBalancerMember> lbMembers = 
getLoadBalancerMembers(loadBalancingRule);
+            SDNProviderNetworkRule baseNetRule = new 
SDNProviderNetworkRule.Builder()
+            .setDomainId(nsxObject.getDomainId())
+            .setAccountId(nsxObject.getAccountId())
+            .setZoneId(nsxObject.getZoneId())
+            .setNetworkResourceId(nsxObject.getNetworkResourceId())
+            .setNetworkResourceName(nsxObject.getNetworkResourceName())
+            .setVpcResource(nsxObject.isVpcResource())
+            .setPublicIp(LoadBalancerContainer.Scheme.Public == 
loadBalancingRule.getScheme() ?
+                            publicIp.getAddress().addr() : 
loadBalancingRule.getSourceIp().addr())
+            
.setPublicPort(String.valueOf(loadBalancingRule.getSourcePortStart()))
+            
.setPrivatePort(String.valueOf(loadBalancingRule.getDefaultPortStart()))
+            .setRuleId(loadBalancingRule.getId())
+            
.setProtocol(loadBalancingRule.getLbProtocol().toUpperCase(Locale.ROOT))
+            .setAlgorithm(loadBalancingRule.getAlgorithm())
+                    .build();
             NsxNetworkRule networkRule = new NsxNetworkRule();
-            networkRule.setDomainId(nsxObject.getDomainId());
-            networkRule.setAccountId(nsxObject.getAccountId());
-            networkRule.setZoneId(nsxObject.getZoneId());
-            networkRule.setNetworkResourceId(nsxObject.getNetworkResourceId());
-            
networkRule.setNetworkResourceName(nsxObject.getNetworkResourceName());
-            networkRule.setVpcResource(nsxObject.isVpcResource());
-            networkRule.setPublicIp(LoadBalancerContainer.Scheme.Public == 
loadBalancingRule.getScheme() ?
-                            publicIp.getAddress().addr() : 
loadBalancingRule.getSourceIp().addr());
-            
networkRule.setPublicPort(String.valueOf(loadBalancingRule.getSourcePortStart()));
-            
networkRule.setPrivatePort(String.valueOf(loadBalancingRule.getDefaultPortStart()));
-            networkRule.setRuleId(loadBalancingRule.getId());
-            
networkRule.setProtocol(loadBalancingRule.getLbProtocol().toUpperCase(Locale.ROOT));
-            networkRule.setAlgorithm(loadBalancingRule.getAlgorithm());
+            networkRule.setBaseRule(baseNetRule);
             networkRule.setMemberList(lbMembers);
             if (Arrays.asList(FirewallRule.State.Add, 
FirewallRule.State.Active).contains(loadBalancingRule.getState())) {
                 result &= nsxService.createLbRule(networkRule);
@@ -775,15 +783,17 @@ public class NsxElement extends AdapterBase implements  
DhcpServiceProvider, Dns
 
     private NsxNetworkRule getNsxNetworkRuleForAcl(NetworkACLItem rule, String 
privatePort) {
         NsxNetworkRule nsxNetworkRule = new NsxNetworkRule();
-        nsxNetworkRule.setRuleId(rule.getId());
-        
nsxNetworkRule.setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ? 
transformCidrListValues(rule.getSourceCidrList()) : List.of("ANY"));
-        nsxNetworkRule.setTrafficType(rule.getTrafficType().toString());
-        nsxNetworkRule.setProtocol(rule.getProtocol().toUpperCase());
-        
nsxNetworkRule.setPublicPort(String.valueOf(rule.getSourcePortStart()));
-        nsxNetworkRule.setPrivatePort(privatePort);
-        nsxNetworkRule.setIcmpCode(rule.getIcmpCode());
-        nsxNetworkRule.setIcmpType(rule.getIcmpType());
-        nsxNetworkRule.setService(Network.Service.NetworkACL);
+        SDNProviderNetworkRule networkRule = new 
SDNProviderNetworkRule.Builder()
+        .setRuleId(rule.getId())
+        .setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ? 
transformCidrListValues(rule.getSourceCidrList()) : List.of("ANY"))
+        .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.setBaseRule(networkRule);
         nsxNetworkRule.setAclAction(transformActionValue(rule.getAction()));
         return nsxNetworkRule;
     }
@@ -797,17 +807,19 @@ public class NsxElement extends AdapterBase implements  
DhcpServiceProvider, Dns
         List<NsxNetworkRule> nsxDelNetworkRules = new ArrayList<>();
         for (FirewallRule rule : rules) {
             NsxNetworkRule networkRule = new NsxNetworkRule();
-            networkRule.setRuleId(rule.getId());
-            
networkRule.setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ?
-                        transformCidrListValues(rule.getSourceCidrList()) : 
List.of("ANY"));
-            
networkRule.setDestinationCidrList(Objects.nonNull(rule.getDestinationCidrList())
 ?
-                        transformCidrListValues(rule.getDestinationCidrList()) 
: List.of("ANY"));
-            networkRule.setIcmpCode(rule.getIcmpCode());
-            networkRule.setIcmpType(rule.getIcmpType());
-            
networkRule.setPrivatePort(PortForwardingServiceProvider.getPrivatePortRange(rule));
-            networkRule.setTrafficType(rule.getTrafficType().toString());
-            networkRule.setService(Network.Service.Firewall);
-            
networkRule.setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT));
+            SDNProviderNetworkRule baseNetRule = new 
SDNProviderNetworkRule.Builder()
+            .setRuleId(rule.getId())
+            .setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ?
+                        transformCidrListValues(rule.getSourceCidrList()) : 
List.of("ANY"))
+            
.setDestinationCidrList(Objects.nonNull(rule.getDestinationCidrList()) ?
+                        transformCidrListValues(rule.getDestinationCidrList()) 
: List.of("ANY"))
+            .setIcmpCode(rule.getIcmpCode())
+            .setIcmpType(rule.getIcmpType())
+            
.setPrivatePort(PortForwardingServiceProvider.getPrivatePortRange(rule))
+            .setTrafficType(rule.getTrafficType().toString())
+            .setService(Network.Service.Firewall)
+            .setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT)).build();
+            networkRule.setBaseRule(baseNetRule);
             networkRule.setAclAction(NsxNetworkRule.NsxRuleAction.ALLOW);
             if (rule.getState() == FirewallRule.State.Add) {
                 nsxAddNetworkRules.add(networkRule);
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
index 64a2514fc51..427ad4cbfed 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
@@ -18,6 +18,7 @@ package org.apache.cloudstack.service;
 
 import com.cloud.network.IpAddress;
 import com.cloud.network.Network;
+import com.cloud.network.SDNProviderNetworkRule;
 import com.cloud.network.nsx.NsxService;
 import com.cloud.network.dao.NetworkVO;
 import com.cloud.network.vpc.Vpc;
@@ -138,7 +139,8 @@ public class NsxServiceImpl implements NsxService, 
Configurable {
         return result.getResult();
     }
 
-    public NsxAnswer createPortForwardRule(NsxNetworkRule netRule) {
+    public NsxAnswer createPortForwardRule(NsxNetworkRule nsxNetRule) {
+        SDNProviderNetworkRule netRule = nsxNetRule.getBaseRule();
         // TODO: if port doesn't exist in default list of services, create a 
service entry
         CreateNsxPortForwardRuleCommand createPortForwardCmd = new 
CreateNsxPortForwardRuleCommand(netRule.getDomainId(),
                 netRule.getAccountId(), netRule.getZoneId(), 
netRule.getNetworkResourceId(),
@@ -147,7 +149,8 @@ public class NsxServiceImpl implements NsxService, 
Configurable {
         return nsxControllerUtils.sendNsxCommand(createPortForwardCmd, 
netRule.getZoneId());
     }
 
-    public boolean deletePortForwardRule(NsxNetworkRule netRule) {
+    public boolean deletePortForwardRule(NsxNetworkRule nsxNetRule) {
+        SDNProviderNetworkRule netRule = nsxNetRule.getBaseRule();
         DeleteNsxNatRuleCommand deleteCmd = new 
DeleteNsxNatRuleCommand(netRule.getDomainId(),
                 netRule.getAccountId(), netRule.getZoneId(), 
netRule.getNetworkResourceId(),
                 netRule.getNetworkResourceName(), netRule.isVpcResource(),  
netRule.getVmId(), netRule.getRuleId(), netRule.getPrivatePort(), 
netRule.getProtocol());
@@ -156,20 +159,22 @@ public class NsxServiceImpl implements NsxService, 
Configurable {
         return result.getResult();
     }
 
-    public boolean createLbRule(NsxNetworkRule netRule) {
+    public boolean createLbRule(NsxNetworkRule nsxNetRule) {
+        SDNProviderNetworkRule netRule = nsxNetRule.getBaseRule();
         CreateNsxLoadBalancerRuleCommand command = new 
CreateNsxLoadBalancerRuleCommand(netRule.getDomainId(),
                 netRule.getAccountId(), netRule.getZoneId(), 
netRule.getNetworkResourceId(),
-                netRule.getNetworkResourceName(), netRule.isVpcResource(),  
netRule.getMemberList(), netRule.getRuleId(),
+                netRule.getNetworkResourceName(), netRule.isVpcResource(),  
nsxNetRule.getMemberList(), netRule.getRuleId(),
                 netRule.getPublicPort(), netRule.getPrivatePort(), 
netRule.getAlgorithm(), netRule.getProtocol());
         command.setPublicIp(netRule.getPublicIp());
         NsxAnswer result = nsxControllerUtils.sendNsxCommand(command, 
netRule.getZoneId());
         return result.getResult();
     }
 
-    public boolean deleteLbRule(NsxNetworkRule netRule) {
+    public boolean deleteLbRule(NsxNetworkRule nsxNetRule) {
+        SDNProviderNetworkRule netRule = nsxNetRule.getBaseRule();
         DeleteNsxLoadBalancerRuleCommand command = new 
DeleteNsxLoadBalancerRuleCommand(netRule.getDomainId(),
                 netRule.getAccountId(), netRule.getZoneId(), 
netRule.getNetworkResourceId(),
-                netRule.getNetworkResourceName(), netRule.isVpcResource(),  
netRule.getMemberList(), netRule.getRuleId(),
+                netRule.getNetworkResourceName(), netRule.isVpcResource(),  
nsxNetRule.getMemberList(), netRule.getRuleId(),
                 netRule.getVmId());
         NsxAnswer result = nsxControllerUtils.sendNsxCommand(command, 
netRule.getZoneId());
         return result.getResult();
diff --git 
a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
 
b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
index fbcca86a28b..f9ee8daea4b 100644
--- 
a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
+++ 
b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
@@ -17,6 +17,7 @@
 package org.apache.cloudstack.service;
 
 import com.cloud.network.Network;
+import com.cloud.network.SDNProviderNetworkRule;
 import com.vmware.nsx.cluster.Status;
 import com.vmware.nsx.model.ClusterStatus;
 import com.vmware.nsx.model.ControllerClusterStatus;
@@ -24,7 +25,6 @@ import com.vmware.nsx_policy.infra.domains.Groups;
 import com.vmware.nsx_policy.model.Group;
 import com.vmware.nsx_policy.model.PathExpression;
 import com.vmware.vapi.bindings.Service;
-import org.apache.cloudstack.resource.NsxNetworkRule;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -73,7 +73,7 @@ public class NsxApiClientTest {
 
     @Test
     public void testGetGroupsForTrafficIngress() {
-        NsxNetworkRule rule = Mockito.mock(NsxNetworkRule.class);
+        SDNProviderNetworkRule rule = 
Mockito.mock(SDNProviderNetworkRule.class);
         Mockito.when(rule.getSourceCidrList()).thenReturn(List.of("ANY"));
         Mockito.when(rule.getTrafficType()).thenReturn("Ingress");
         Mockito.when(rule.getService()).thenReturn(Network.Service.NetworkACL);
@@ -86,7 +86,7 @@ public class NsxApiClientTest {
 
     @Test
     public void testGetGroupsForTrafficEgress() {
-        NsxNetworkRule rule = Mockito.mock(NsxNetworkRule.class);
+        SDNProviderNetworkRule rule = 
Mockito.mock(SDNProviderNetworkRule.class);
         Mockito.when(rule.getSourceCidrList()).thenReturn(List.of("ANY"));
         Mockito.when(rule.getTrafficType()).thenReturn("Egress");
         Mockito.when(rule.getService()).thenReturn(Network.Service.NetworkACL);
diff --git 
a/server/src/test/java/org/apache/cloudstack/service/NetrisServiceMockTest.java 
b/server/src/test/java/org/apache/cloudstack/service/NetrisServiceMockTest.java
index 05a6cd20213..ff715db4027 100644
--- 
a/server/src/test/java/org/apache/cloudstack/service/NetrisServiceMockTest.java
+++ 
b/server/src/test/java/org/apache/cloudstack/service/NetrisServiceMockTest.java
@@ -17,10 +17,14 @@
 package org.apache.cloudstack.service;
 
 import com.cloud.network.IpAddress;
+import com.cloud.network.Network;
 import com.cloud.network.SDNProviderNetworkRule;
+import com.cloud.network.netris.NetrisNetworkRule;
 import com.cloud.network.netris.NetrisService;
 import com.cloud.network.vpc.Vpc;
 
+import java.util.List;
+
 public class NetrisServiceMockTest implements NetrisService {
     @Override
     public boolean createIPAMAllocationsForZoneLevelPublicRanges(long zoneId) {
@@ -77,6 +81,16 @@ public class NetrisServiceMockTest implements NetrisService {
         return true;
     }
 
+    @Override
+    public boolean addFirewallRules(Network network, List<NetrisNetworkRule> 
firewallRules) {
+        return true;
+    }
+
+    @Override
+    public boolean deleteFirewallRules(Network network, 
List<NetrisNetworkRule> firewallRules) {
+        return true;
+    }
+
     @Override
     public boolean addOrUpdateStaticRoute(long zoneId, long accountId, long 
domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, 
String prefix, String nextHop, Long routeId, boolean updateRoute) {
         return true;

Reply via email to