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;
