mirror of https://github.com/apache/cloudstack.git
Phase5 - Support for LB - create, delete and Update operations (#49)
* 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 * Fix naming convention for NAT subnets to follow other resources * Use vpc ID for nat subnets * Phase5 - Support for LB - create, delete and Update operations * Use new nat subnet name for deletion of static nat rule * add support to add netris lb rule * support deletion of LB rule on Netris * add checks when editing unsupported fields of LB rule for Netris and hide columns on the UI * fix test failure * fix imports * add license * address comments
This commit is contained in:
parent
7f31803232
commit
ca4c13c4a0
|
|
@ -0,0 +1,41 @@
|
|||
// 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;
|
||||
|
||||
public class NetrisLbBackend {
|
||||
private long vmId;
|
||||
private String vmIp;
|
||||
private int port;
|
||||
|
||||
public NetrisLbBackend(long vmId, String vmIp, int port) {
|
||||
this.vmId = vmId;
|
||||
this.vmIp = vmIp;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public String getVmIp() {
|
||||
return vmIp;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,8 @@ package com.cloud.network.netris;
|
|||
import com.cloud.network.SDNProviderNetworkRule;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NetrisNetworkRule {
|
||||
public enum NetrisRuleAction {
|
||||
PERMIT, DENY
|
||||
|
|
@ -26,11 +28,13 @@ public class NetrisNetworkRule {
|
|||
|
||||
private SDNProviderNetworkRule baseRule;
|
||||
private NetrisRuleAction aclAction;
|
||||
private List<NetrisLbBackend> lbBackends;
|
||||
private String reason;
|
||||
|
||||
public NetrisNetworkRule(Builder builder) {
|
||||
this.baseRule = builder.baseRule;
|
||||
this.aclAction = builder.aclAction;
|
||||
this.lbBackends = builder.lbBackends;
|
||||
this.reason = builder.reason;
|
||||
}
|
||||
|
||||
|
|
@ -38,6 +42,10 @@ public class NetrisNetworkRule {
|
|||
return aclAction;
|
||||
}
|
||||
|
||||
public List<NetrisLbBackend> getLbBackends() {
|
||||
return lbBackends;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
|
@ -50,6 +58,7 @@ public class NetrisNetworkRule {
|
|||
public static class Builder {
|
||||
private SDNProviderNetworkRule baseRule;
|
||||
private NetrisRuleAction aclAction;
|
||||
private List<NetrisLbBackend> lbBackends;
|
||||
private String reason;
|
||||
|
||||
public Builder baseRule(SDNProviderNetworkRule baseRule) {
|
||||
|
|
@ -62,6 +71,11 @@ public class NetrisNetworkRule {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder lbBackends(List<NetrisLbBackend> lbBackends) {
|
||||
this.lbBackends = lbBackends;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder reason(String reason) {
|
||||
this.reason = reason;
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -54,4 +54,7 @@ public interface NetrisService {
|
|||
boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId);
|
||||
|
||||
boolean releaseNatIp(long zoneId, String publicIp);
|
||||
|
||||
boolean createLbRule(NetrisNetworkRule rule);
|
||||
boolean deleteLbRule(NetrisNetworkRule rule);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
// 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 com.cloud.network.netris.NetrisLbBackend;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CreateOrUpdateNetrisLoadBalancerRuleCommand extends NetrisCommand {
|
||||
private final String publicPort;
|
||||
private final String privatePort;
|
||||
private final String algorithm;
|
||||
private final String protocol;
|
||||
List<NetrisLbBackend> lbBackends;
|
||||
private String publicIp;
|
||||
private final Long lbId;
|
||||
|
||||
public CreateOrUpdateNetrisLoadBalancerRuleCommand(long zoneId, Long accountId, Long domainId, String name, Long id, boolean isVpc,
|
||||
List<NetrisLbBackend> lbBackends, long lbId, String publicIp, String publicPort,
|
||||
String privatePort, String algorithm, String protocol) {
|
||||
super(zoneId, accountId, domainId, name, id, isVpc);
|
||||
this.lbId = lbId;
|
||||
this.publicIp = publicIp;
|
||||
this.publicPort = publicPort;
|
||||
this.privatePort = privatePort;
|
||||
this.algorithm = algorithm;
|
||||
this.protocol = protocol;
|
||||
this.lbBackends = lbBackends;
|
||||
}
|
||||
|
||||
public String getPublicPort() {
|
||||
return publicPort;
|
||||
}
|
||||
|
||||
public String getPrivatePort() {
|
||||
return privatePort;
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public List<NetrisLbBackend> getLbBackends() {
|
||||
return lbBackends;
|
||||
}
|
||||
|
||||
public Long getLbId() {
|
||||
return lbId;
|
||||
}
|
||||
|
||||
public String getPublicIp() {
|
||||
return publicIp;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// 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;
|
||||
|
||||
public class DeleteNetrisLoadBalancerRuleCommand extends NetrisCommand {
|
||||
private Long lbId;
|
||||
|
||||
public DeleteNetrisLoadBalancerRuleCommand(long zoneId, Long accountId, Long domainId, String name, Long id, boolean isVpc, Long lbId) {
|
||||
super(zoneId, accountId, domainId, name, id, isVpc);
|
||||
this.lbId = lbId;
|
||||
}
|
||||
|
||||
public Long getLbId() {
|
||||
return lbId;
|
||||
}
|
||||
|
||||
public void setLbId(Long lbId) {
|
||||
this.lbId = lbId;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,8 +32,10 @@ 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.CreateOrUpdateNetrisLoadBalancerRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisACLCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisLoadBalancerRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
|
||||
|
|
@ -118,6 +120,10 @@ public class NetrisResource implements ServerResource {
|
|||
return executeRequest((AddOrUpdateNetrisStaticRouteCommand) cmd);
|
||||
} else if (cmd instanceof ReleaseNatIpCommand) {
|
||||
return executeRequest((ReleaseNatIpCommand) cmd);
|
||||
} else if (cmd instanceof CreateOrUpdateNetrisLoadBalancerRuleCommand) {
|
||||
return executeRequest((CreateOrUpdateNetrisLoadBalancerRuleCommand) cmd);
|
||||
} else if (cmd instanceof DeleteNetrisLoadBalancerRuleCommand) {
|
||||
return executeRequest((DeleteNetrisLoadBalancerRuleCommand) cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
|
|
@ -352,6 +358,31 @@ public class NetrisResource implements ServerResource {
|
|||
return new NetrisAnswer(cmd, true, "OK");
|
||||
}
|
||||
|
||||
private Answer executeRequest(CreateOrUpdateNetrisLoadBalancerRuleCommand cmd) {
|
||||
boolean result = netrisApiClient.createLbRule(cmd);
|
||||
if (!result) {
|
||||
return new NetrisAnswer(cmd, false, String.format("Failed to create Netris LB rule for %s: %s, " +
|
||||
"for private port: %s and public port: %s", getNetworkType(cmd.isVpc()), cmd.getName(), cmd.getPrivatePort(), cmd.getPublicPort(), cmd.getPublicPort()));
|
||||
}
|
||||
return new NetrisAnswer(cmd, true, "OK");
|
||||
}
|
||||
|
||||
private Answer executeRequest(DeleteNetrisLoadBalancerRuleCommand cmd) {
|
||||
boolean result = netrisApiClient.deleteLbRule(cmd);
|
||||
if (!result) {
|
||||
return new NetrisAnswer(cmd, false, String.format("Failed to delete Netris LB rule for %s: %s, " +
|
||||
"for private port: %s and public port: %s", getNetworkType(cmd.isVpc()), cmd.getName()));
|
||||
}
|
||||
return new NetrisAnswer(cmd, true, "OK");
|
||||
}
|
||||
|
||||
private String getNetworkType(Boolean isVpc) {
|
||||
if (isVpc) {
|
||||
return "VPC";
|
||||
}
|
||||
return "Network";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import java.util.Objects;
|
|||
public class NetrisResourceObjectUtils {
|
||||
|
||||
public enum NetrisObjectType {
|
||||
VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET, SNAT, STATICNAT, DNAT, STATICROUTE, ACL
|
||||
VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET, SNAT, STATICNAT, DNAT, STATICROUTE, ACL, LB
|
||||
}
|
||||
|
||||
public static String retrieveNetrisResourceObjectName(NetrisCommand cmd, NetrisObjectType netrisObjectType, String... suffixes) {
|
||||
|
|
@ -59,7 +59,7 @@ public class NetrisResourceObjectUtils {
|
|||
break;
|
||||
case IPAM_SUBNET:
|
||||
if (!isZoneLevel) {
|
||||
if (Objects.nonNull(objectId) && Objects.nonNull(objectName)) {
|
||||
if (Objects.nonNull(objectId) && Objects.nonNull(objectName) && !isVpc) {
|
||||
stringBuilder.append(String.format("-N%s", objectId));
|
||||
} else {
|
||||
stringBuilder.append(String.format("-V%s-%s", suffixes[0], suffixes[1]));
|
||||
|
|
@ -86,6 +86,9 @@ public class NetrisResourceObjectUtils {
|
|||
case VNET:
|
||||
case ACL:
|
||||
break;
|
||||
case LB:
|
||||
stringBuilder.append(String.format("%s%s", prefix, objectId));
|
||||
break;
|
||||
default:
|
||||
stringBuilder.append(String.format("-%s", objectName));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ 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.CreateOrUpdateNetrisLoadBalancerRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisACLCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisLoadBalancerRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
|
||||
|
|
@ -84,4 +86,6 @@ public interface NetrisApiClient {
|
|||
boolean addOrUpdateStaticRoute(AddOrUpdateNetrisStaticRouteCommand cmd);
|
||||
boolean deleteStaticRoute(DeleteNetrisStaticRouteCommand cmd);
|
||||
boolean releaseNatIp(ReleaseNatIpCommand cmd);
|
||||
boolean createLbRule(CreateOrUpdateNetrisLoadBalancerRuleCommand cmd);
|
||||
boolean deleteLbRule(DeleteNetrisLoadBalancerRuleCommand cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,10 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.service;
|
||||
|
||||
import com.cloud.network.netris.NetrisLbBackend;
|
||||
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.ApiClient;
|
||||
|
|
@ -29,6 +31,7 @@ import io.netris.api.v1.RoutesApi;
|
|||
import io.netris.api.v1.SitesApi;
|
||||
import io.netris.api.v1.TenantsApi;
|
||||
import io.netris.api.v2.IpamApi;
|
||||
import io.netris.api.v2.L4LoadBalancerApi;
|
||||
import io.netris.api.v2.NatApi;
|
||||
import io.netris.api.v2.VNetApi;
|
||||
import io.netris.api.v2.VpcApi;
|
||||
|
|
@ -52,12 +55,20 @@ import io.netris.model.IpTreeAllocation;
|
|||
import io.netris.model.IpTreeAllocationTenant;
|
||||
import io.netris.model.IpTreeSubnet;
|
||||
import io.netris.model.IpTreeSubnetSites;
|
||||
import io.netris.model.L4LBSite;
|
||||
import io.netris.model.L4LbTenant;
|
||||
import io.netris.model.L4LbVpc;
|
||||
import io.netris.model.L4LoadBalancerBackendItem;
|
||||
import io.netris.model.L4LoadBalancerItem;
|
||||
import io.netris.model.L4lbAddItem;
|
||||
import io.netris.model.L4lbresBody;
|
||||
import io.netris.model.NatBodySiteSite;
|
||||
import io.netris.model.NatBodyVpcVpc;
|
||||
import io.netris.model.NatGetBody;
|
||||
import io.netris.model.NatPostBody;
|
||||
import io.netris.model.NatPutBody;
|
||||
import io.netris.model.NatResponseGetOk;
|
||||
import io.netris.model.ResAddEditBody;
|
||||
import io.netris.model.RoutesBody;
|
||||
import io.netris.model.RoutesBodyId;
|
||||
import io.netris.model.RoutesBodyVpcVpc;
|
||||
|
|
@ -90,10 +101,12 @@ 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.CreateOrUpdateNetrisLoadBalancerRuleCommand;
|
||||
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.DeleteNetrisLoadBalancerRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
|
||||
|
|
@ -598,6 +611,169 @@ public class NetrisApiClientImpl implements NetrisApiClient {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createLbRule(CreateOrUpdateNetrisLoadBalancerRuleCommand cmd) {
|
||||
boolean isVpc = cmd.isVpc();
|
||||
Long networkResourceId = cmd.getId();
|
||||
String networkResourceName = cmd.getName();
|
||||
Long domainId = cmd.getDomainId();
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long zoneId = cmd.getZoneId();
|
||||
Long lbId = cmd.getLbId();
|
||||
String publicIp = cmd.getPublicIp();
|
||||
List<NetrisLbBackend> lbBackends = cmd.getLbBackends();
|
||||
|
||||
try {
|
||||
String resourcePrefix = isVpc ? "V" : "N";
|
||||
String netrisResourceName = String.format("D%s-A%s-Z%s-%s%s-%s", domainId, accountId, zoneId, resourcePrefix, networkResourceId, networkResourceName);
|
||||
VPCListing vpcResource = getNetrisVpcResource(netrisResourceName);
|
||||
if (vpcResource == null) {
|
||||
logger.error("Could not find the Netris VPC resource with name {} and tenant ID {}", netrisResourceName, tenantId);
|
||||
return false;
|
||||
}
|
||||
createLBSubnet(cmd, publicIp + "/32", vpcResource.getId());
|
||||
|
||||
String suffix = String.format("LB%s", lbId);
|
||||
String lbName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.LB, suffix);
|
||||
Pair<Boolean, List<BigDecimal>> resultAndMatchingLbId = getMatchingLbRule(lbName, vpcResource.getName());
|
||||
Boolean result = resultAndMatchingLbId.first();
|
||||
List<BigDecimal> matchingLbId = resultAndMatchingLbId.second();
|
||||
if (Boolean.FALSE.equals(result)) {
|
||||
logger.warn("Could not find the Netris LB rule with name {}", lbName);
|
||||
}
|
||||
if (!matchingLbId.isEmpty()) {
|
||||
logger.warn("LB rule by name: {} already exists", lbName);
|
||||
return true;
|
||||
}
|
||||
|
||||
L4lbAddItem l4lbAddItem = getL4LbRule(cmd, vpcResource, lbName, publicIp, lbBackends);
|
||||
L4LoadBalancerApi loadBalancerApi = apiClient.getApiStubForMethod(L4LoadBalancerApi.class);
|
||||
ResAddEditBody response = loadBalancerApi.apiV2L4lbPost(l4lbAddItem);
|
||||
if (Objects.isNull(response) || Boolean.FALSE.equals(response.isIsSuccess())) {
|
||||
throw new CloudRuntimeException("Failed to create Netris LB rule");
|
||||
}
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException("Failed to create Netris load balancer rule", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private L4lbAddItem getL4LbRule(CreateOrUpdateNetrisLoadBalancerRuleCommand cmd, VPCListing vpcResource, String lbName,
|
||||
String publicIp, List<NetrisLbBackend> lbBackends) {
|
||||
L4lbAddItem l4lbAddItem = new L4lbAddItem();
|
||||
try {
|
||||
l4lbAddItem.setName(lbName);
|
||||
|
||||
String protocol = cmd.getProtocol().toUpperCase(Locale.ROOT);
|
||||
if (!Arrays.asList("TCP", "UDP").contains(protocol)) {
|
||||
throw new CloudRuntimeException("Invalid protocol " + protocol);
|
||||
}
|
||||
l4lbAddItem.setProtocol(cmd.getProtocol().toUpperCase(Locale.ROOT));
|
||||
L4LBSite site = new L4LBSite();
|
||||
site.setId(siteId);
|
||||
site.setName(siteName);
|
||||
l4lbAddItem.setSite(site);
|
||||
l4lbAddItem.setSiteID(new BigDecimal(siteId));
|
||||
|
||||
L4LbTenant tenant = new L4LbTenant();
|
||||
tenant.setId(tenantId);
|
||||
tenant.setName(tenantName);
|
||||
l4lbAddItem.setTenant(tenant);
|
||||
|
||||
L4LbVpc vpc = new L4LbVpc();
|
||||
vpc.setId(vpcResource.getId());
|
||||
l4lbAddItem.setVpc(vpc);
|
||||
|
||||
l4lbAddItem.setAutomatic(false);
|
||||
l4lbAddItem.setIpFamily(NetUtils.isIpv4(publicIp) ? L4lbAddItem.IpFamilyEnum.IPv4 : L4lbAddItem.IpFamilyEnum.IPv6);
|
||||
l4lbAddItem.setIp(publicIp);
|
||||
l4lbAddItem.setStatus("enable");
|
||||
|
||||
List<L4LoadBalancerBackendItem> backends = new ArrayList<>();
|
||||
for (NetrisLbBackend backend : lbBackends) {
|
||||
L4LoadBalancerBackendItem backendItem = new L4LoadBalancerBackendItem();
|
||||
backendItem.setIp(backend.getVmIp());
|
||||
backendItem.setPort(backend.getPort());
|
||||
backends.add(backendItem);
|
||||
}
|
||||
l4lbAddItem.setBackend(backends);
|
||||
l4lbAddItem.setPort(Integer.valueOf(cmd.getPublicPort()));
|
||||
l4lbAddItem.setHealthCheck(L4lbAddItem.HealthCheckEnum.NONE);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Failed to create Netris load balancer rule", e);
|
||||
}
|
||||
return l4lbAddItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteLbRule(DeleteNetrisLoadBalancerRuleCommand cmd) {
|
||||
boolean isVpc = cmd.isVpc();
|
||||
String vpcName = null;
|
||||
String networkName = null;
|
||||
Long vpcId = null;
|
||||
Long networkId = null;
|
||||
if (isVpc) {
|
||||
vpcName = cmd.getName();
|
||||
vpcId = cmd.getId();
|
||||
} else {
|
||||
networkName = cmd.getName();
|
||||
networkId = cmd.getId();
|
||||
}
|
||||
Long lbId = cmd.getLbId();
|
||||
try {
|
||||
String suffix = getNetrisVpcNameSuffix(vpcId, vpcName, networkId, networkName, isVpc);
|
||||
String netrisVpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC, suffix);
|
||||
suffix = String.format("LB%s", lbId);
|
||||
String lbName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.LB, suffix);
|
||||
Pair<Boolean, List<BigDecimal>> resultAndMatchingLbId = getMatchingLbRule(lbName, netrisVpcName);
|
||||
Boolean result = resultAndMatchingLbId.first();
|
||||
List<BigDecimal> matchingLbId = resultAndMatchingLbId.second();
|
||||
if (!result) {
|
||||
logger.error("Could not find the Netris LB rule with name {}", lbName);
|
||||
return false;
|
||||
}
|
||||
if (matchingLbId.isEmpty()) {
|
||||
logger.warn("There doesn't seem to be any LB rule on Netris matching {}", lbName);
|
||||
return true;
|
||||
}
|
||||
|
||||
L4LoadBalancerApi lbApi = apiClient.getApiStubForMethod(L4LoadBalancerApi.class);
|
||||
lbApi.apiV2L4lbIdDelete(matchingLbId.get(0).intValue());
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException("Failed to delete Netris load balancer rule", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Pair<Boolean, List<BigDecimal>> getMatchingLbRule(String lbName, String vpcName) {
|
||||
try {
|
||||
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);
|
||||
L4LoadBalancerApi lbApi = apiClient.getApiStubForMethod(L4LoadBalancerApi.class);
|
||||
L4lbresBody lbGetResponse = lbApi.apiV2L4lbGet(siteFilter, vpcFilter);
|
||||
if (lbGetResponse == null || !lbGetResponse.isIsSuccess()) {
|
||||
logger.warn("No LB rules were found to be present for the specific Netris VPC resource {}." +
|
||||
" Netris LB rules may have been deleted out of band.", vpcName);
|
||||
return new Pair<>(true, Collections.emptyList());
|
||||
}
|
||||
List<L4LoadBalancerItem> lbList = lbGetResponse.getData();
|
||||
return new Pair<>(true, lbList.stream()
|
||||
.filter(lb -> lbName.equals(lb.getName()))
|
||||
.map(acl -> BigDecimal.valueOf(acl.getId()))
|
||||
.collect(Collectors.toList()));
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException("Failed to retrieve Netris LB rules", e);
|
||||
}
|
||||
return new Pair<>(true, Collections.emptyList());
|
||||
}
|
||||
|
||||
private Pair<Boolean, RoutesGetBody> staticRouteExists(Integer netrisVpcId, String prefix, String nextHop, String description) {
|
||||
try {
|
||||
FilterByVpc vpcFilter = new FilterByVpc();
|
||||
|
|
@ -904,7 +1080,7 @@ public class NetrisApiClientImpl implements NetrisApiClient {
|
|||
}
|
||||
|
||||
if (StringUtils.isNotBlank(targetIpSubnet) && existsDestinationSubnet(targetIpSubnet)) {
|
||||
logger.debug(String.format("Creating subnet with NAT purpose for %s", targetIpSubnet));
|
||||
logger.debug("Creating subnet with NAT purpose for {}}", targetIpSubnet);
|
||||
createNatSubnet(cmd, targetIpSubnet, vpcResource.getId());
|
||||
}
|
||||
|
||||
|
|
@ -1022,6 +1198,27 @@ public class NetrisApiClientImpl implements NetrisApiClient {
|
|||
}
|
||||
}
|
||||
|
||||
private void createLBSubnet(NetrisCommand cmd, String lbIp, Integer netrisVpcId) {
|
||||
try {
|
||||
FilterByVpc vpcFilter = new FilterByVpc();
|
||||
vpcFilter.add(netrisVpcId);
|
||||
String netrisSubnetName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd,
|
||||
NetrisResourceObjectUtils.NetrisObjectType.IPAM_SUBNET,
|
||||
String.valueOf(cmd.getId()), lbIp);
|
||||
List<IpTreeSubnet> matchedSubnets = getSubnet(vpcFilter, netrisSubnetName);
|
||||
VPCListing systemVpc = getSystemVpc();
|
||||
if (matchedSubnets.isEmpty()) {
|
||||
createIpamSubnetInternal(netrisSubnetName, lbIp, SubnetBody.PurposeEnum.LOAD_BALANCER, systemVpc, null);
|
||||
} else if (IpTreeSubnet.PurposeEnum.LOAD_BALANCER != matchedSubnets.get(0).getPurpose()){
|
||||
logger.debug("Updating existing NAT subnet {} to have load balancer purpose", netrisSubnetName);
|
||||
updateIpamSubnetInternal(matchedSubnets.get(0).getId().intValue(), netrisSubnetName, lbIp, SubnetBody.PurposeEnum.LOAD_BALANCER, systemVpc, null);
|
||||
}
|
||||
logger.debug("LB subnet: {} already exists", netrisSubnetName);
|
||||
} catch (ApiException e) {
|
||||
throw new CloudRuntimeException(String.format("Failed to create subnet for %s with LB purpose", lbIp));
|
||||
}
|
||||
}
|
||||
|
||||
private NatPostBody.ProtocolEnum getProtocolFromString(String protocol) {
|
||||
return NatPostBody.ProtocolEnum.fromValue(protocol);
|
||||
}
|
||||
|
|
@ -1204,33 +1401,38 @@ public class NetrisApiClientImpl implements NetrisApiClient {
|
|||
}
|
||||
}
|
||||
|
||||
private SubnetBody getIpamSubnetBody(VPCListing vpc, SubnetBody.PurposeEnum purpose, String subnetName, String subnetPrefix, Boolean isGlobalRouting) {
|
||||
SubnetBody subnetBody = new SubnetBody();
|
||||
subnetBody.setName(subnetName);
|
||||
|
||||
AllocationBodyVpc vpcAllocationBody = new AllocationBodyVpc();
|
||||
vpcAllocationBody.setName(vpc.getName());
|
||||
vpcAllocationBody.setId(vpc.getId());
|
||||
subnetBody.setVpc(vpcAllocationBody);
|
||||
|
||||
IpTreeAllocationTenant allocationTenant = new IpTreeAllocationTenant();
|
||||
allocationTenant.setId(new BigDecimal(tenantId));
|
||||
allocationTenant.setName(tenantName);
|
||||
subnetBody.setTenant(allocationTenant);
|
||||
|
||||
IpTreeSubnetSites subnetSites = new IpTreeSubnetSites();
|
||||
subnetSites.setId(new BigDecimal(siteId));
|
||||
subnetSites.setName(siteName);
|
||||
subnetBody.setSites(List.of(subnetSites));
|
||||
|
||||
subnetBody.setPurpose(purpose);
|
||||
subnetBody.setPrefix(subnetPrefix);
|
||||
if (isGlobalRouting != null) {
|
||||
subnetBody.setGlobalRouting(isGlobalRouting);
|
||||
}
|
||||
return subnetBody;
|
||||
}
|
||||
|
||||
private InlineResponse2004Data createIpamSubnetInternal(String subnetName, String subnetPrefix, SubnetBody.PurposeEnum purpose, VPCListing vpc, Boolean isGlobalRouting) {
|
||||
logger.debug("Creating Netris IPAM Subnet {} for VPC {}", subnetPrefix, vpc.getName());
|
||||
try {
|
||||
|
||||
SubnetBody subnetBody = new SubnetBody();
|
||||
subnetBody.setName(subnetName);
|
||||
|
||||
AllocationBodyVpc vpcAllocationBody = new AllocationBodyVpc();
|
||||
vpcAllocationBody.setName(vpc.getName());
|
||||
vpcAllocationBody.setId(vpc.getId());
|
||||
subnetBody.setVpc(vpcAllocationBody);
|
||||
|
||||
IpTreeAllocationTenant allocationTenant = new IpTreeAllocationTenant();
|
||||
allocationTenant.setId(new BigDecimal(tenantId));
|
||||
allocationTenant.setName(tenantName);
|
||||
subnetBody.setTenant(allocationTenant);
|
||||
|
||||
IpTreeSubnetSites subnetSites = new IpTreeSubnetSites();
|
||||
subnetSites.setId(new BigDecimal(siteId));
|
||||
subnetSites.setName(siteName);
|
||||
subnetBody.setSites(List.of(subnetSites));
|
||||
|
||||
subnetBody.setPurpose(purpose);
|
||||
subnetBody.setPrefix(subnetPrefix);
|
||||
if (isGlobalRouting != null) {
|
||||
subnetBody.setGlobalRouting(isGlobalRouting);
|
||||
}
|
||||
SubnetBody subnetBody = getIpamSubnetBody(vpc, purpose, subnetName, subnetPrefix, isGlobalRouting);
|
||||
IpamApi ipamApi = apiClient.getApiStubForMethod(IpamApi.class);
|
||||
InlineResponse2004 subnetResponse = ipamApi.apiV2IpamSubnetPost(subnetBody);
|
||||
if (subnetResponse == null || !subnetResponse.isIsSuccess()) {
|
||||
|
|
@ -1245,6 +1447,25 @@ public class NetrisApiClientImpl implements NetrisApiClient {
|
|||
}
|
||||
}
|
||||
|
||||
private InlineResponse2004Data updateIpamSubnetInternal(Integer netrisSubnetId, String subnetName, String subnetPrefix, SubnetBody.PurposeEnum purpose, VPCListing vpc, Boolean isGlobalRouting) {
|
||||
logger.debug("Updating Netris IPAM Subnet {} for VPC {}", subnetPrefix, vpc.getName());
|
||||
try {
|
||||
|
||||
SubnetBody subnetBody = getIpamSubnetBody(vpc, purpose, subnetName, subnetPrefix, isGlobalRouting);
|
||||
IpamApi ipamApi = apiClient.getApiStubForMethod(IpamApi.class);
|
||||
InlineResponse2004 subnetResponse = ipamApi.apiV2IpamSubnetIdPut(subnetBody, netrisSubnetId);
|
||||
if (subnetResponse == null || !subnetResponse.isIsSuccess()) {
|
||||
String reason = subnetResponse == null ? "Empty response" : "Operation failed on Netris";
|
||||
logger.debug("The Netris IPAM Subnet {} update failed: {}", subnetName, reason);
|
||||
throw new CloudRuntimeException(reason);
|
||||
}
|
||||
return subnetResponse.getData();
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException(String.format("Error Updating Netris IPAM Subnet %s for VPC %s", subnetPrefix, vpc.getName()), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
VnetResAddBody createVnetInternal(VPCListing associatedVpc, String netrisVnetName, String netrisGateway, String netrisV6Gateway, Integer vxlanId, String netrisTag) {
|
||||
logger.debug("Creating Netris VPC vNet {} for CIDR {}", netrisVnetName, netrisGateway);
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.cloud.agent.api.AgentControlCommand;
|
|||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.to.LoadBalancerTO;
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
|
|
@ -45,16 +46,21 @@ import com.cloud.network.SDNProviderNetworkRule;
|
|||
import com.cloud.network.SDNProviderOpObject;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.LoadBalancerVMMapDao;
|
||||
import com.cloud.network.dao.LoadBalancerVMMapVO;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.element.DhcpServiceProvider;
|
||||
import com.cloud.network.element.DnsServiceProvider;
|
||||
import com.cloud.network.element.IpDeployer;
|
||||
import com.cloud.network.element.LoadBalancingServiceProvider;
|
||||
import com.cloud.network.element.NetworkACLServiceProvider;
|
||||
import com.cloud.network.element.PortForwardingServiceProvider;
|
||||
import com.cloud.network.element.StaticNatServiceProvider;
|
||||
import com.cloud.network.element.VirtualRouterElement;
|
||||
import com.cloud.network.element.VpcProvider;
|
||||
import com.cloud.network.lb.LoadBalancingRule;
|
||||
import com.cloud.network.netris.NetrisLbBackend;
|
||||
import com.cloud.network.netris.NetrisService;
|
||||
import com.cloud.network.rules.FirewallRule;
|
||||
import com.cloud.network.rules.LoadBalancerContainer;
|
||||
|
|
@ -107,7 +113,8 @@ import java.util.Set;
|
|||
|
||||
@Component
|
||||
public class NetrisElement extends AdapterBase implements DhcpServiceProvider, DnsServiceProvider, VpcProvider,
|
||||
StaticNatServiceProvider, IpDeployer, PortForwardingServiceProvider, NetworkACLServiceProvider, ResourceStateAdapter, Listener {
|
||||
StaticNatServiceProvider, IpDeployer, PortForwardingServiceProvider, NetworkACLServiceProvider,
|
||||
LoadBalancingServiceProvider, ResourceStateAdapter, Listener {
|
||||
|
||||
@Inject
|
||||
NetworkModel networkModel;
|
||||
|
|
@ -133,6 +140,8 @@ public class NetrisElement extends AdapterBase implements DhcpServiceProvider, D
|
|||
private IPAddressDao ipAddressDao;
|
||||
@Inject
|
||||
private VMInstanceDao vmInstanceDao;
|
||||
@Inject
|
||||
LoadBalancerVMMapDao lbVmMapDao;
|
||||
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
|
|
@ -693,4 +702,85 @@ public class NetrisElement extends AdapterBase implements DhcpServiceProvider, D
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private SDNProviderOpObject getNetrisObject(Network network) {
|
||||
Pair<VpcVO, NetworkVO> vpcOrNetwork = getVpcOrNetwork(network.getVpcId(), network.getId());
|
||||
VpcVO vpc = vpcOrNetwork.first();
|
||||
NetworkVO networkVO = vpcOrNetwork.second();
|
||||
long domainId = getResourceId("domain", vpc, networkVO);
|
||||
long accountId = getResourceId("account", vpc, networkVO);
|
||||
long zoneId = getResourceId("zone", vpc, networkVO);
|
||||
|
||||
return new SDNProviderOpObject.Builder()
|
||||
.vpcVO(vpc)
|
||||
.networkVO(networkVO)
|
||||
.domainId(domainId)
|
||||
.accountId(accountId)
|
||||
.zoneId(zoneId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyLBRules(Network network, List<LoadBalancingRule> rules) throws ResourceUnavailableException {
|
||||
boolean result = true;
|
||||
for (LoadBalancingRule loadBalancingRule : rules) {
|
||||
IPAddressVO publicIp = ipAddressDao.findByIpAndDcId(network.getDataCenterId(),
|
||||
loadBalancingRule.getSourceIp().addr());
|
||||
|
||||
List<NetrisLbBackend> lbBackends = getLoadBalancerBackends(loadBalancingRule);
|
||||
SDNProviderOpObject netrisObject = getNetrisObject(network);
|
||||
SDNProviderNetworkRule baseNetworkRule = new SDNProviderNetworkRule.Builder()
|
||||
.setDomainId(netrisObject.getDomainId())
|
||||
.setAccountId(netrisObject.getAccountId())
|
||||
.setZoneId(netrisObject.getZoneId())
|
||||
.setNetworkResourceId(netrisObject.getNetworkResourceId())
|
||||
.setNetworkResourceName(netrisObject.getNetworkResourceName())
|
||||
.setVpcResource(netrisObject.isVpcResource())
|
||||
.setPublicIp(LoadBalancerContainer.Scheme.Public == loadBalancingRule.getScheme() ?
|
||||
publicIp.getAddress().addr() : loadBalancingRule.getSourceIp().addr())
|
||||
.setPrivatePort(String.valueOf(loadBalancingRule.getDefaultPortStart()))
|
||||
.setPublicPort(String.valueOf(loadBalancingRule.getSourcePortStart()))
|
||||
.setRuleId(loadBalancingRule.getId())
|
||||
.setProtocol(loadBalancingRule.getProtocol().toUpperCase(Locale.ROOT))
|
||||
.setAlgorithm(loadBalancingRule.getAlgorithm())
|
||||
.build();
|
||||
|
||||
NetrisNetworkRule networkRule = new NetrisNetworkRule.Builder()
|
||||
.baseRule(baseNetworkRule)
|
||||
.lbBackends(lbBackends)
|
||||
.build();
|
||||
if (Arrays.asList(FirewallRule.State.Add, FirewallRule.State.Active).contains(loadBalancingRule.getState())) {
|
||||
result &= netrisService.createLbRule(networkRule);
|
||||
} else if (loadBalancingRule.getState() == FirewallRule.State.Revoke) {
|
||||
result &= netrisService.deleteLbRule(networkRule);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<NetrisLbBackend> getLoadBalancerBackends(LoadBalancingRule lbRule) {
|
||||
List<LoadBalancerVMMapVO> lbVms = lbVmMapDao.listByLoadBalancerId(lbRule.getId(), false);
|
||||
List<NetrisLbBackend> lbMembers = new ArrayList<>();
|
||||
|
||||
for (LoadBalancerVMMapVO lbVm : lbVms) {
|
||||
NetrisLbBackend member = new NetrisLbBackend(lbVm.getInstanceId(), lbVm.getInstanceIp(), lbRule.getDefaultPortStart());
|
||||
lbMembers.add(member);
|
||||
}
|
||||
return lbMembers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateLBRule(Network network, LoadBalancingRule rule) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LoadBalancerTO> updateHealthChecks(Network network, List<LoadBalancingRule> lbrules) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlesOnlyRulesInTransitionState() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@ import com.cloud.utils.net.NetUtils;
|
|||
import inet.ipaddr.IPAddress;
|
||||
import inet.ipaddr.IPAddressString;
|
||||
import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisLoadBalancerRuleCommand;
|
||||
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.DeleteNetrisLoadBalancerRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
|
||||
|
|
@ -455,6 +457,27 @@ public class NetrisServiceImpl implements NetrisService, Configurable {
|
|||
return answer.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createLbRule(NetrisNetworkRule rule) {
|
||||
SDNProviderNetworkRule baseRule = rule.getBaseRule();
|
||||
CreateOrUpdateNetrisLoadBalancerRuleCommand cmd = new CreateOrUpdateNetrisLoadBalancerRuleCommand(baseRule.getZoneId(), baseRule.getAccountId(),
|
||||
baseRule.getDomainId(), baseRule.getNetworkResourceName(), baseRule.getNetworkResourceId(), baseRule.isVpcResource(),
|
||||
rule.getLbBackends(), baseRule.getRuleId(), baseRule.getPublicIp(), baseRule.getPublicPort(),
|
||||
baseRule.getPrivatePort(), baseRule.getAlgorithm(), baseRule.getProtocol());
|
||||
NetrisAnswer answer = sendNetrisCommand(cmd, baseRule.getZoneId());
|
||||
return answer.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteLbRule(NetrisNetworkRule rule) {
|
||||
SDNProviderNetworkRule baseRule = rule.getBaseRule();
|
||||
DeleteNetrisLoadBalancerRuleCommand cmd = new DeleteNetrisLoadBalancerRuleCommand(baseRule.getZoneId(), baseRule.getAccountId(),
|
||||
baseRule.getDomainId(), baseRule.getNetworkResourceName(), baseRule.getNetworkResourceId(), baseRule.isVpcResource(),
|
||||
baseRule.getRuleId());
|
||||
NetrisAnswer answer = sendNetrisCommand(cmd, baseRule.getZoneId());
|
||||
return answer.getResult();
|
||||
}
|
||||
|
||||
private String getResourceSuffix(Long vpcId, Long networkId, boolean isForVpc) {
|
||||
String suffix;
|
||||
if (isForVpc) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
|
@ -2248,6 +2249,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
|
|||
lb.setLbProtocol(lbProtocol);
|
||||
}
|
||||
|
||||
validateInputsForExternalNetworkProvider(lb, algorithm, lbProtocol);
|
||||
// Validate rule in LB provider
|
||||
LoadBalancingRule rule = getLoadBalancerRuleToApply(lb);
|
||||
if (!validateLbRule(rule)) {
|
||||
|
|
@ -2297,6 +2299,18 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
|
|||
return lb;
|
||||
}
|
||||
|
||||
private void validateInputsForExternalNetworkProvider(LoadBalancerVO lb, String algorithm, String protocol) {
|
||||
Network network = _networkDao.findById(lb.getNetworkId());
|
||||
if (_networkOfferingServiceDao.canProviderSupportServiceInNetworkOffering(network.getNetworkOfferingId(), Service.Lb, Provider.Netris)) {
|
||||
if (Objects.nonNull(algorithm)) {
|
||||
throw new InvalidParameterValueException(String.format("Algorithm: %s specified for Netris Provider is not supported.", algorithm));
|
||||
}
|
||||
if (Objects.nonNull(protocol) && "tcp-proxy".equalsIgnoreCase(protocol)) {
|
||||
throw new InvalidParameterValueException("TCP Proxy protocol is not supported for Netris Provider.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<? extends UserVm>, List<String>> listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import com.cloud.network.dao.LoadBalancerVO;
|
|||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.element.LoadBalancingServiceProvider;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.MockAccountManagerImpl;
|
||||
|
|
@ -52,6 +53,7 @@ import java.util.UUID;
|
|||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
|
@ -63,6 +65,7 @@ public class UpdateLoadBalancerTest {
|
|||
private LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class);
|
||||
private NetworkDao netDao = Mockito.mock(NetworkDao.class);
|
||||
private NetworkModel netModel = Mockito.mock(NetworkModel.class);
|
||||
private NetworkOfferingServiceMapDao ntwkOffServiceMapDao = Mockito.mock(NetworkOfferingServiceMapDao.class);
|
||||
private LoadBalancingServiceProvider lbServiceProvider= Mockito.mock(LoadBalancingServiceProvider.class);
|
||||
|
||||
private static long domainId = 5L;
|
||||
|
|
@ -73,6 +76,7 @@ public class UpdateLoadBalancerTest {
|
|||
_lbMgr._accountMgr = new MockAccountManagerImpl();
|
||||
_lbMgr._autoScaleVmGroupDao = Mockito.mock(AutoScaleVmGroupDao.class);
|
||||
_lbMgr._networkDao = netDao;
|
||||
_lbMgr._networkOfferingServiceDao = ntwkOffServiceMapDao;
|
||||
_lbMgr._networkModel = netModel;
|
||||
_lbMgr._lb2healthcheckDao = Mockito.mock(LBHealthCheckPolicyDao.class);
|
||||
_lbMgr._lb2stickinesspoliciesDao = Mockito.mock(LBStickinessPolicyDao.class);
|
||||
|
|
@ -99,7 +103,8 @@ public class UpdateLoadBalancerTest {
|
|||
when(netDao.findById(anyLong())).thenReturn(Mockito.mock(NetworkVO.class));
|
||||
when(lbServiceProvider.validateLBRule(any(Network.class), any(LoadBalancingRule.class))).thenReturn(true);
|
||||
when(lbDao.update(isNull(), eq(lb))).thenReturn(true);
|
||||
|
||||
when(netDao.findById(nullable(Long.class))).thenReturn(Mockito.mock(NetworkVO.class));
|
||||
when(ntwkOffServiceMapDao.canProviderSupportServiceInNetworkOffering(nullable(Long.class), any(Network.Service.class), any(Network.Provider.class))).thenReturn(false);
|
||||
_lbMgr.updateLoadBalancerRule(updateLbRuleCmd);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(lbServiceProvider, lbDao);
|
||||
|
|
|
|||
|
|
@ -105,4 +105,14 @@ public class NetrisServiceMockTest implements NetrisService {
|
|||
public boolean releaseNatIp(long zoneId, String publicIp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createLbRule(NetrisNetworkRule rule) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteLbRule(NetrisNetworkRule rule) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
<tooltip-label :title="$t('label.cidrlist')" bold :tooltip="createLoadBalancerRuleParams.cidrlist.description" :tooltip-placement="'right'"/>
|
||||
<a-input v-model:value="newRule.cidrlist"></a-input>
|
||||
</div>
|
||||
<div class="form__item">
|
||||
<div class="form__item" v-if="lbProvider !== 'Netris'">
|
||||
<div class="form__label">{{ $t('label.algorithm') }}</div>
|
||||
<a-select
|
||||
v-model:value="newRule.algorithm"
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
:filterOption="(input, option) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}" >
|
||||
<a-select-option value="tcp-proxy" :label="$t('label.tcp.proxy')">{{ $t('label.tcp.proxy') }}</a-select-option>
|
||||
<a-select-option v-if="lbProvider !== 'Netris'" value="tcp-proxy" :label="$t('label.tcp.proxy')">{{ $t('label.tcp.proxy') }}</a-select-option>
|
||||
<a-select-option value="tcp" :label="$t('label.tcp')">{{ $t('label.tcp') }}</a-select-option>
|
||||
<a-select-option value="udp" :label="$t('label.udp')">{{ $t('label.udp') }}</a-select-option>
|
||||
</a-select>
|
||||
|
|
@ -409,7 +409,7 @@
|
|||
<p class="edit-rule__label">{{ $t('label.name') }}</p>
|
||||
<a-input v-focus="true" v-model:value="editRuleDetails.name" />
|
||||
</div>
|
||||
<div class="edit-rule__item">
|
||||
<div v-if="lbProvider !== 'Netris'" class="edit-rule__item">
|
||||
<p class="edit-rule__label">{{ $t('label.algorithm') }}</p>
|
||||
<a-select
|
||||
v-model:value="editRuleDetails.algorithm"
|
||||
|
|
@ -423,7 +423,7 @@
|
|||
<a-select-option value="source" :label="$t('label.lb.algorithm.source')">{{ $t('label.lb.algorithm.source') }}</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<div class="edit-rule__item">
|
||||
<div v-if="lbProvider !== 'Netris'" class="edit-rule__item">
|
||||
<p class="edit-rule__label">{{ $t('label.protocol') }}</p>
|
||||
<a-select
|
||||
v-model:value="editRuleDetails.protocol"
|
||||
|
|
@ -781,9 +781,11 @@ export default {
|
|||
vmguestip: [],
|
||||
cidrlist: ''
|
||||
},
|
||||
lbProvider: null,
|
||||
addVmModalVisible: false,
|
||||
addVmModalLoading: false,
|
||||
addVmModalNicLoading: false,
|
||||
zoneloading: false,
|
||||
vms: [],
|
||||
nics: [],
|
||||
totalCount: 0,
|
||||
|
|
@ -802,10 +804,6 @@ export default {
|
|||
title: this.$t('label.privateport'),
|
||||
dataIndex: 'privateport'
|
||||
},
|
||||
{
|
||||
key: 'algorithm',
|
||||
title: this.$t('label.algorithm')
|
||||
},
|
||||
{
|
||||
key: 'cidrlist',
|
||||
title: this.$t('label.cidrlist')
|
||||
|
|
@ -979,6 +977,7 @@ export default {
|
|||
fetchData () {
|
||||
this.fetchListTiers()
|
||||
this.fetchLBRules()
|
||||
this.fetchZone()
|
||||
},
|
||||
fetchListTiers () {
|
||||
this.tiers.loading = true
|
||||
|
|
@ -1073,6 +1072,22 @@ export default {
|
|||
})
|
||||
})
|
||||
},
|
||||
fetchZone () {
|
||||
this.zoneloading = true
|
||||
api('listZones', {
|
||||
id: this.resource.zoneid
|
||||
}).then(response => {
|
||||
this.lbProvider = response?.listzonesresponse?.zone?.[0]?.provider || null
|
||||
}).finally(() => {
|
||||
this.zoneloading = false
|
||||
if (this.lbProvider !== 'Netris') {
|
||||
this.column.push({
|
||||
key: 'algorithm',
|
||||
title: this.$t('label.algorithm')
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
returnAlgorithmName (name) {
|
||||
switch (name) {
|
||||
case 'leastconn':
|
||||
|
|
@ -1377,7 +1392,7 @@ export default {
|
|||
this.selectedRule = rule
|
||||
this.editRuleModalVisible = true
|
||||
this.editRuleDetails.name = this.selectedRule.name
|
||||
this.editRuleDetails.algorithm = this.selectedRule.algorithm
|
||||
this.editRuleDetails.algorithm = this.lbProvider !== 'Netris' ? this.selectedRule.algorithm : undefined
|
||||
this.editRuleDetails.protocol = this.selectedRule.protocol
|
||||
},
|
||||
handleSubmitEditForm () {
|
||||
|
|
|
|||
Loading…
Reference in New Issue