NSX: Support internal LB service in NSX

This commit is contained in:
Pearl Dsilva 2024-01-23 14:44:10 -05:00
parent 5a4f38c2fc
commit 829d50c58c
12 changed files with 156 additions and 15 deletions

View File

@ -21,7 +21,7 @@ import org.apache.cloudstack.api.InternalIdentity;
public interface VirtualRouterProvider extends InternalIdentity, Identity {
public enum Type {
VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm, NetScalerVm
VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm, NetScalerVm, Nsx
}
public Type getType();

View File

@ -58,6 +58,7 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService";
public static final String DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE = "DefaultTungstenSharedNetworkOfferingWithSGService";
public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC = "DefaultNATNSXNetworkOfferingForVpc";
public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC_WITH_ILB = "DefaultNATNSXNetworkOfferingForVpcWithInternalLB";
public static final String DEFAULT_ROUTED_NSX_OFFERING_FOR_VPC = "DefaultRoutedNSXNetworkOfferingForVpc";
public static final String DEFAULT_NAT_NSX_OFFERING = "DefaultNATNSXNetworkOffering";
public static final String DEFAULT_ROUTED_NSX_OFFERING = "DefaultRoutedNSXNetworkOffering";

View File

@ -825,6 +825,7 @@ public class ApiConstants {
public static final String FOR_VPC = "forvpc";
public static final String FOR_NSX = "fornsx";
public static final String NSX_SUPPORT_LB = "nsxsupportlb";
public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb";
public static final String FOR_TUNGSTEN = "fortungsten";
public static final String SHRINK_OK = "shrinkok";
public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid";
@ -963,6 +964,7 @@ public class ApiConstants {
public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc";
public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet";
public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess";
public static final String SUPPORTS_INTERNAL_LB = "supportsinternallb";
public static final String SUPPORTS_VM_AUTOSCALING = "supportsvmautoscaling";
public static final String REGION_LEVEL_VPC = "regionlevelvpc";
public static final String STRECHED_L2_SUBNET = "strechedl2subnet";

View File

@ -160,6 +160,12 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
since = "4.20.0")
private Boolean nsxSupportsLbService;
@Parameter(name = ApiConstants.NSX_SUPPORTS_INTERNAL_LB,
type = CommandType.BOOLEAN,
description = "true if network offering for NSX network offering supports Internal Load balancer service.",
since = "4.20.0")
private Boolean nsxSupportsInternalLbService;
@Parameter(name = ApiConstants.FOR_TUNGSTEN,
type = CommandType.BOOLEAN,
description = "true if network offering is meant to be used for Tungsten-Fabric, false otherwise.")
@ -306,6 +312,10 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
return BooleanUtils.isTrue(nsxSupportsLbService);
}
public boolean getNsxSupportsInternalLbService() {
return BooleanUtils.isTrue(nsxSupportsInternalLbService);
}
public Boolean getForTungsten() {
return forTungsten;
}

View File

@ -135,6 +135,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations {
@Param(description = "true if network offering supports public access for guest networks", since = "4.10.0")
private Boolean supportsPublicAccess;
@SerializedName(ApiConstants.SUPPORTS_INTERNAL_LB)
@Param(description = "true if network offering supports public access for guest networks", since = "4.20.0")
private Boolean supportsInternalLb;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the domain ID(s) this disk offering belongs to. Ignore this information as it is not currently applicable.")
private String domainId;
@ -259,6 +263,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations {
this.supportsPublicAccess = supportsPublicAccess;
}
public void setSupportsInternalLb(Boolean supportsInternalLb) {
this.supportsInternalLb = supportsInternalLb;
}
public String getDomainId() {
return domainId;
}

View File

@ -44,6 +44,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.VirtualRouterProvider;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.LoadBalancerVMMapDao;
@ -51,7 +52,9 @@ import com.cloud.network.dao.LoadBalancerVMMapVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.element.DhcpServiceProvider;
import com.cloud.network.element.DnsServiceProvider;
import com.cloud.network.element.FirewallServiceProvider;
@ -60,9 +63,12 @@ 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.VirtualRouterProviderVO;
import com.cloud.network.element.VpcProvider;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.LoadBalancerContainer;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpc.NetworkACLItem;
@ -82,6 +88,8 @@ import com.cloud.user.AccountManager;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
@ -90,6 +98,10 @@ import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.VMInstanceDao;
import net.sf.ehcache.config.InvalidConfigurationException;
import org.apache.cloudstack.StartupNsxCommand;
import org.apache.cloudstack.api.command.admin.internallb.ConfigureInternalLoadBalancerElementCmd;
import org.apache.cloudstack.api.command.admin.internallb.CreateInternalLoadBalancerElementCmd;
import org.apache.cloudstack.api.command.admin.internallb.ListInternalLoadBalancerElementsCmd;
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
import org.apache.cloudstack.resource.NsxLoadBalancerMember;
import org.apache.cloudstack.resource.NsxNetworkRule;
import org.apache.cloudstack.resource.NsxOpObject;
@ -111,7 +123,7 @@ import java.util.function.LongFunction;
@Component
public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsServiceProvider, VpcProvider,
StaticNatServiceProvider, IpDeployer, PortForwardingServiceProvider, NetworkACLServiceProvider,
LoadBalancingServiceProvider, FirewallServiceProvider, ResourceStateAdapter, Listener {
LoadBalancingServiceProvider, FirewallServiceProvider, InternalLoadBalancerElementService, ResourceStateAdapter, Listener {
@Inject
@ -142,6 +154,10 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns
VpcDao vpcDao;
@Inject
LoadBalancerVMMapDao lbVmMapDao;
@Inject
VirtualRouterProviderDao vrProviderDao;
@Inject
PhysicalNetworkServiceProviderDao pNtwkSvcProviderDao;
private static final Logger LOGGER = Logger.getLogger(NsxElement.class);
@ -159,7 +175,16 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns
capabilities.put(Network.Service.Dns, dnsCapabilities);
capabilities.put(Network.Service.StaticNat, null);
capabilities.put(Network.Service.Lb, null);
// Set capabilities for LB service
Map<Network.Capability, String> lbCapabilities = new HashMap<Network.Capability, String>();
lbCapabilities.put(Network.Capability.SupportedLBAlgorithms, "roundrobin,leastconn");
lbCapabilities.put(Network.Capability.SupportedLBIsolation, "dedicated");
lbCapabilities.put(Network.Capability.SupportedProtocols, "tcp, udp");
lbCapabilities.put(Network.Capability.SupportedStickinessMethods, VirtualRouterElement.getHAProxyStickinessCapability());
lbCapabilities.put(Network.Capability.LbSchemes, String.join(",", LoadBalancerContainer.Scheme.Internal.name(), LoadBalancerContainer.Scheme.Public.name()));
capabilities.put(Network.Service.Lb, lbCapabilities);
capabilities.put(Network.Service.PortForwarding, null);
capabilities.put(Network.Service.NetworkACL, null);
@ -633,7 +658,8 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns
.setNetworkResourceName(nsxObject.getNetworkResourceName())
.setVpcResource(nsxObject.isVpcResource())
.setMemberList(lbMembers)
.setPublicIp(publicIp.getAddress().addr())
.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())
@ -778,4 +804,74 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns
}
return list;
}
@Override
public VirtualRouterProvider configureInternalLoadBalancerElement(long id, boolean enable) {
VirtualRouterProviderVO element = vrProviderDao.findById(id);
if (element == null || element.getType() != VirtualRouterProvider.Type.Nsx) {
throw new InvalidParameterValueException("Can't find " + getName() + " " +
"element with network service provider id " + id + " to be used as a provider for " +
getName());
}
element.setEnabled(enable);
element = vrProviderDao.persist(element);
return element;
}
@Override
public VirtualRouterProvider addInternalLoadBalancerElement(long ntwkSvcProviderId) {
VirtualRouterProviderVO element = vrProviderDao.findByNspIdAndType(ntwkSvcProviderId, VirtualRouterProvider.Type.Nsx);
if (element != null) {
LOGGER.debug("There is already an " + getName() + " with service provider id " + ntwkSvcProviderId);
return null;
}
PhysicalNetworkServiceProvider provider = pNtwkSvcProviderDao.findById(ntwkSvcProviderId);
if (provider == null || !provider.getProviderName().equalsIgnoreCase(getName())) {
throw new InvalidParameterValueException("Invalid network service provider is specified");
}
element = new VirtualRouterProviderVO(ntwkSvcProviderId, VirtualRouterProvider.Type.Nsx);
element = vrProviderDao.persist(element);
return element;
}
@Override
public VirtualRouterProvider getInternalLoadBalancerElement(long id) {
VirtualRouterProvider provider = vrProviderDao.findById(id);
if (provider == null || provider.getType() != VirtualRouterProvider.Type.Nsx) {
throw new InvalidParameterValueException("Unable to find " + getName() + " by id");
}
return provider;
}
@Override
public List<? extends VirtualRouterProvider> searchForInternalLoadBalancerElements(Long id, Long ntwkSvsProviderId, Boolean enabled) {
QueryBuilder<VirtualRouterProviderVO> sc = QueryBuilder.create(VirtualRouterProviderVO.class);
if (id != null) {
sc.and(sc.entity().getId(), SearchCriteria.Op.EQ, id);
}
if (ntwkSvsProviderId != null) {
sc.and(sc.entity().getNspId(), SearchCriteria.Op.EQ, ntwkSvsProviderId);
}
if (enabled != null) {
sc.and(sc.entity().isEnabled(), SearchCriteria.Op.EQ, enabled);
}
//return only Internal LB elements
sc.and(sc.entity().getType(), SearchCriteria.Op.EQ, VirtualRouterProvider.Type.Nsx);
return sc.list();
}
@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>();
cmdList.add(CreateInternalLoadBalancerElementCmd.class);
cmdList.add(ConfigureInternalLoadBalancerElementCmd.class);
cmdList.add(ListInternalLoadBalancerElementsCmd.class);
return cmdList;
}
}

View File

@ -108,6 +108,7 @@ public class NetworkOfferingJoinDaoImpl extends GenericDaoBase<NetworkOfferingJo
networkOfferingResponse.setConcurrentConnections(offering.getConcurrentConnections());
networkOfferingResponse.setSupportsStrechedL2Subnet(offering.isSupportingStrechedL2());
networkOfferingResponse.setSupportsPublicAccess(offering.isSupportingPublicAccess());
networkOfferingResponse.setSupportsInternalLb(offering.isInternalLb());
networkOfferingResponse.setCreated(offering.getCreated());
if (offering.getGuestType() != null) {
networkOfferingResponse.setGuestIpType(offering.getGuestType().toString());

View File

@ -5956,6 +5956,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
Boolean forNsx = cmd.isForNsx();
Boolean forTungsten = cmd.getForTungsten();
String nsxMode = cmd.getNsxMode();
boolean nsxSupportInternalLbSvc = cmd.getNsxSupportsInternalLbService();
Integer maxconn = null;
boolean enableKeepAlive = false;
String servicePackageuuid = cmd.getServicePackageId();
@ -6274,6 +6275,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
final NetworkOfferingVO offering = createNetworkOffering(name, displayText, trafficType, tags, specifyVlan, availability, networkRate, serviceProviderMap, false, guestType, false,
serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges, isPersistent, details, egressDefaultPolicy, maxconn, enableKeepAlive, forVpc, forTungsten, forNsx, nsxMode, domainIds, zoneIds, enable, internetProtocol);
if (Boolean.TRUE.equals(forNsx) && nsxSupportInternalLbSvc) {
offering.setInternalLb(true);
offering.setPublicLb(false);
_networkOfferingDao.update(offering.getId(), offering);
}
CallContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name);
CallContext.current().putContextParameter(NetworkOffering.class, offering.getId());
return offering;

View File

@ -1203,35 +1203,41 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
// Offering #9 - network offering for NSX provider - NATTED mode
createAndPersistDefaultNsxOffering(NetworkOffering.DEFAULT_NAT_NSX_OFFERING, "Offering for NSX enabled networks - NAT mode",
NetworkOffering.NsxMode.NATTED, false);
NetworkOffering.NsxMode.NATTED, false, true);
// Offering #10 - network offering for NSX provider - ROUTED mode
createAndPersistDefaultNsxOffering(NetworkOffering.DEFAULT_ROUTED_NSX_OFFERING, "Offering for NSX enabled networks - ROUTED mode",
NetworkOffering.NsxMode.ROUTED, false);
NetworkOffering.NsxMode.ROUTED, false, true);
// Offering #11 - network offering for NSX provider for VPCs - NATTED mode
createAndPersistDefaultNsxOffering(NetworkOffering.DEFAULT_NAT_NSX_OFFERING_FOR_VPC, "Offering for NSX enabled networks on VPCs - NAT mode",
NetworkOffering.NsxMode.NATTED, true);
NetworkOffering.NsxMode.NATTED, true, true);
// Offering #12 - network offering for NSX provider for VPCs - ROUTED mode
createAndPersistDefaultNsxOffering(NetworkOffering.DEFAULT_ROUTED_NSX_OFFERING_FOR_VPC, "Offering for NSX enabled networks on VPCs - ROUTED mode",
NetworkOffering.NsxMode.ROUTED, true);
NetworkOffering.NsxMode.ROUTED, true, true);
// Offering #13 - network offering for NSX provider for VPCs with Internal LB - NATTED mode
createAndPersistDefaultNsxOffering(NetworkOffering.DEFAULT_NAT_NSX_OFFERING_FOR_VPC_WITH_ILB, "Offering for NSX enabled networks on VPCs with internal LB - NAT mode",
NetworkOffering.NsxMode.NATTED, true, false);
}
});
}
private void createAndPersistDefaultNsxOffering(String name, String displayText, NetworkOffering.NsxMode nsxMode, boolean forVpc) {
private void createAndPersistDefaultNsxOffering(String name, String displayText, NetworkOffering.NsxMode nsxMode,
boolean forVpc, boolean publicLB) {
NetworkOfferingVO defaultNatNSXNetworkOffering =
new NetworkOfferingVO(name, displayText, TrafficType.Guest, false, false, null,
null, true, Availability.Optional, null, GuestType.Isolated, false,
false, false, false, false, forVpc);
defaultNatNSXNetworkOffering.setPublicLb(true);
defaultNatNSXNetworkOffering.setPublicLb(publicLB);
defaultNatNSXNetworkOffering.setInternalLb(!publicLB);
defaultNatNSXNetworkOffering.setForNsx(true);
defaultNatNSXNetworkOffering.setNsxMode(nsxMode.name());
defaultNatNSXNetworkOffering.setState(NetworkOffering.State.Enabled);
defaultNatNSXNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNatNSXNetworkOffering);
Map<Service, Provider> serviceProviderMap = getServicesAndProvidersForNSXNetwork(nsxMode, forVpc);
Map<Service, Provider> serviceProviderMap = getServicesAndProvidersForNSXNetwork(nsxMode, forVpc, publicLB);
for (Map.Entry<Network.Service, Network.Provider> service : serviceProviderMap.entrySet()) {
NetworkOfferingServiceMapVO offService =
new NetworkOfferingServiceMapVO(defaultNatNSXNetworkOffering.getId(), service.getKey(), service.getValue());
@ -1240,7 +1246,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
}
}
private Map<Service, Provider> getServicesAndProvidersForNSXNetwork(NetworkOffering.NsxMode nsxMode, boolean forVpc) {
private Map<Service, Provider> getServicesAndProvidersForNSXNetwork(NetworkOffering.NsxMode nsxMode, boolean forVpc, boolean publicLB) {
final Map<Network.Service, Network.Provider> serviceProviderMap = new HashMap<>();
Provider routerProvider = forVpc ? Provider.VPCVirtualRouter : Provider.VirtualRouter;
serviceProviderMap.put(Service.Dhcp, routerProvider);

View File

@ -1444,6 +1444,7 @@
"label.nsx.provider.edgecluster": "NSX provider edge cluster",
"label.nsx.provider.tier0gateway": "NSX provider tier-0 gateway",
"label.nsx.provider.transportzone": "NSX provider transport zone",
"label.nsx.supports.internal.lb": "Enable NSX internal LB service",
"label.nsx.supports.lb": "Enable NSX LB service",
"label.num.cpu.cores": "# of CPU cores",
"label.number": "#Rule",

View File

@ -112,7 +112,7 @@
</template>
</a-pagination>
</a-collapse-panel>
<a-collapse-panel :header="$t('label.internal.lb')" key="ilb" :style="customStyle" :collapsible="!showIlb(network) ? 'disabled' : null" >
<a-collapse-panel :header="$t('label.internal.lb')" key="ilb" :style="customStyle" :collapsible="showIlb(network) ? null: 'disabled'" >
<a-button
type="dashed"
style="margin-bottom: 15px; width: 100%"
@ -461,8 +461,9 @@ export default {
this.form = reactive({})
this.rules = reactive({})
},
showIlb (network) {
return network.service.filter(s => (s.name === 'Lb') && (s.capability.filter(c => c.name === 'LbSchemes' && c.value === 'Internal').length > 0)).length > 0 || false
async showIlb (network) {
const networkOffering = await this.getNetworkOffering(network.networkofferingid)
return ((networkOffering.supportsinternallb && network.service.filter(s => (s.name === 'Lb') && (s.capability.filter(c => c.name === 'LbSchemes' && c.value.split(',').includes('Internal')).length > 0)).length > 0))
},
updateMtu () {
if (this.form.privatemtu > this.privateMtuMax) {

View File

@ -138,6 +138,14 @@
<a-switch v-model:checked="form.nsxsupportlb" @change="val => { handleNsxLbService(val) }" />
</a-form-item>
</a-col>
<a-col :md="12" :lg="12" v-if="form.nsxsupportlb && form.forvpc">
<a-form-item name="nsxsupportsinternallb" ref="nsxsupportsinternallb" v-if="guestType === 'isolated'">
<template #label>
<tooltip-label :title="$t('label.nsx.supports.internal.lb')" :tooltip="apiParams.nsxsupportsinternallb.description"/>
</template>
<a-switch v-model:checked="form.nsxsupportsinternallb"/>
</a-form-item>
</a-col>
</a-row>
<a-form-item name="nsxmode" ref="nsxmode" v-if="forNsx">
<template #label>
@ -1025,6 +1033,7 @@ export default {
params.fornsx = true
params.nsxmode = values.nsxmode
params.nsxsupportlb = values.nsxsupportlb
params.nsxsupportsinternallb = values.nsxsupportsinternallb
}
if (values.guestiptype === 'shared' || values.guestiptype === 'isolated') {
if (values.conservemode !== true) {