NSX: Router Public nic to get IP from systemVM Ip range (#8172)

* NSX: Router Public nic to get IP from systemVM Ip range

* Fix VR IP address and setSourceNatIp command

* NSX: hide systemVM reserved IP range SourceNAT

* fix test

---------

Co-authored-by: nvazquez <nicovazquez90@gmail.com>
This commit is contained in:
Pearl Dsilva 2023-11-01 15:14:33 -04:00 committed by GitHub
parent e3a2762235
commit a36f355877
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 107 additions and 8 deletions

View File

@ -97,4 +97,6 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity,
void setRuleState(State ruleState);
boolean isForSystemVms();
}

View File

@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.address;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.log4j.Logger;
@ -106,6 +107,9 @@ public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountC
@Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "list resources by display flag; only ROOT admin is eligible to pass this parameter", since = "4.4", authorized = {RoleType.Admin})
private Boolean display;
@Parameter(name = ApiConstants.FOR_SYSTEM_VMS, type = CommandType.BOOLEAN, description = "true if range is dedicated for system VMs", since = "4.20.0")
private Boolean forSystemVMs;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -177,6 +181,10 @@ public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountC
return state;
}
public boolean getForSystemVMs() {
return !Objects.isNull(forSystemVMs) && forSystemVMs;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -167,6 +167,10 @@ public class IPAddressResponse extends BaseResponseWithAnnotations implements Co
@Param(description="whether the ip address has Firewall/PortForwarding/LoadBalancing rules defined")
private boolean hasRules;
@SerializedName(ApiConstants.FOR_SYSTEM_VMS)
@Param(description="true if range is dedicated for System VMs")
private boolean forSystemVms;
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
@ -316,4 +320,8 @@ public class IPAddressResponse extends BaseResponseWithAnnotations implements Co
public void setHasRules(final boolean hasRules) {
this.hasRules = hasRules;
}
public void setForSystemVms(boolean forSystemVms) {
this.forSystemVms = forSystemVms;
}
}

View File

@ -269,4 +269,11 @@ public class PublicIp implements PublicIpAddress {
public void setRuleState(State ruleState) {
_addr.setRuleState(ruleState);
}
@Override
public boolean isForSystemVms() {
return false;
}
}

View File

@ -41,6 +41,7 @@ import javax.naming.ConfigurationException;
import com.cloud.dc.VlanDetailsVO;
import com.cloud.dc.dao.VlanDetailsDao;
import com.cloud.network.dao.NsxProviderDao;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
@ -347,6 +348,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
private VlanDetailsDao vlanDetailsDao;
List<NetworkGuru> networkGurus;
@Inject
private NsxProviderDao nsxProviderDao;
@Override
public List<NetworkGuru> getNetworkGurus() {
@ -1082,16 +1085,26 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
if (!isVirtualRouter || !isPublicTraffic || requested.getIPv4Address() == null) {
return false;
}
IPAddressVO ip = _ipAddressDao.findByIp(requested.getIPv4Address());
if (ip == null) {
long dataCenterId = vm.getVirtualMachine().getDataCenterId();
if (nsxProviderDao.findByZoneId(dataCenterId) == null) {
return false;
}
Long vpcId = _ipAddressDao.findByIp(requested.getIPv4Address()).getVpcId();
// TODO: Need to fix isolated network
List<IPAddressVO> ips = _ipAddressDao.listByAssociatedVpc(vpcId, true);
if (CollectionUtils.isEmpty(ips)) {
return false;
}
ips = ips.stream().filter(x -> !x.getAddress().addr().equals(requested.getIPv4Address())).collect(Collectors.toList());
IPAddressVO ip = ips.get(0);
VlanDetailsVO vlanDetail = vlanDetailsDao.findDetail(ip.getVlanId(), ApiConstants.NSX_DETAIL_KEY);
if (vlanDetail == null) {
return false;
}
boolean isForNsx = vlanDetail.getValue().equalsIgnoreCase("true");
return isForNsx && ip.isSourceNat() && !ip.isForSystemVms();
return isForNsx && !ip.isForSystemVms();
}
private void setMtuDetailsInVRNic(final Pair<NetworkVO, VpcVO> networks, Network network, NicVO vo) {

View File

@ -40,9 +40,12 @@ import org.apache.cloudstack.agent.api.CreateNsxTier1NatRuleCommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.cloudstack.utils.NsxHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import javax.inject.Inject;
import java.util.List;
import java.util.stream.Collectors;
public class NsxPublicNetworkGuru extends PublicNetworkGuru {
@ -106,6 +109,16 @@ public class NsxPublicNetworkGuru extends PublicNetworkGuru {
throw new CloudRuntimeException(err);
}
// For NSX, use VR Public IP != Source NAT
List<IPAddressVO> ips = _ipAddressDao.listByAssociatedVpc(vpcId, true);
if (CollectionUtils.isEmpty(ips)) {
String err = String.format("Cannot find a source NAT IP for the VPC %s", vpc.getName());
s_logger.error(err);
throw new CloudRuntimeException(err);
}
ips = ips.stream().filter(x -> !x.getAddress().addr().equals(nic.getIPv4Address())).collect(Collectors.toList());
// Use Source NAT IP address from the NSX Public Range. Do not Use the VR Public IP address
ipAddress = ips.get(0);
if (ipAddress.isSourceNat() && !ipAddress.isForSystemVms()) {
VlanDetailsVO detail = vlanDetailsDao.findDetail(ipAddress.getVlanId(), ApiConstants.NSX_DETAIL_KEY);
if (detail != null && detail.getValue().equalsIgnoreCase("true")) {

View File

@ -1097,6 +1097,7 @@ public class ApiResponseHelper implements ResponseGenerator {
ipResponse.setForDisplay(ipAddr.isDisplay());
ipResponse.setPortable(ipAddr.isPortable());
ipResponse.setForSystemVms(ipAddr.isForSystemVms());
//set tag information
List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.PublicIpAddress, ipAddr.getId());

View File

@ -2584,6 +2584,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
final Boolean staticNat = cmd.isStaticNat();
final Boolean forDisplay = cmd.getDisplay();
final String state = cmd.getState();
final Boolean forSystemVms = cmd.getForSystemVMs();
final Map<String, String> tags = cmd.getTags();
sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
@ -2646,6 +2647,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
if (IpAddressManagerImpl.getSystemvmpublicipreservationmodestrictness().value() && IpAddress.State.Free.name().equalsIgnoreCase(state)) {
sc.setParameters("forsystemvms", false);
} else {
sc.setParameters("forsystemvms", forSystemVms);
}
}

View File

@ -19,9 +19,14 @@ package org.apache.cloudstack.network.router.deployment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.cloud.dc.DataCenter;
import com.cloud.dc.Vlan;
import com.cloud.network.dao.NetworkDetailVO;
import com.cloud.network.dao.NetworkDetailsDao;
import com.cloud.network.dao.NsxProviderDao;
import com.cloud.network.element.NsxProviderVO;
import com.cloud.network.router.VirtualRouter;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.dao.DiskOfferingDao;
@ -86,6 +91,7 @@ public class RouterDeploymentDefinition {
protected NetworkDao networkDao;
protected DomainRouterDao routerDao;
protected NsxProviderDao nsxProviderDao;
protected PhysicalNetworkServiceProviderDao physicalProviderDao;
protected NetworkModel networkModel;
protected VirtualRouterProviderDao vrProviderDao;
@ -383,8 +389,19 @@ public class RouterDeploymentDefinition {
protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
sourceNatIp = null;
DataCenter zone = dest.getDataCenter();
Long zoneId = null;
if (Objects.nonNull(zone)) {
zoneId = zone.getId();
}
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
if (isPublicNetwork) {
sourceNatIp = ipAddrMgr.assignSourceNatIpAddressToGuestNetwork(owner, guestNetwork);
if (Objects.isNull(nsxProvider)) {
sourceNatIp = ipAddrMgr.assignSourceNatIpAddressToGuestNetwork(owner, guestNetwork);
} else {
sourceNatIp = ipAddrMgr.assignPublicIpAddress(zoneId, getPodId(), owner, Vlan.VlanType.VirtualNetwork, null, null, false, true);
}
}
}

View File

@ -23,6 +23,7 @@ import java.util.Map;
import javax.inject.Inject;
import com.cloud.network.dao.NetworkDetailsDao;
import com.cloud.network.dao.NsxProviderDao;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@ -63,6 +64,8 @@ public class RouterDeploymentDefinitionBuilder {
@Inject
private DomainRouterDao routerDao;
@Inject
private NsxProviderDao nsxProviderDao;
@Inject
private PhysicalNetworkServiceProviderDao physicalProviderDao;
@Inject
private NetworkModel networkModel;
@ -125,6 +128,7 @@ public class RouterDeploymentDefinitionBuilder {
routerDeploymentDefinition.networkDao = networkDao;
routerDeploymentDefinition.routerDao = routerDao;
routerDeploymentDefinition.nsxProviderDao = nsxProviderDao;
routerDeploymentDefinition.physicalProviderDao = physicalProviderDao;
routerDeploymentDefinition.networkModel = networkModel;
routerDeploymentDefinition.vrProviderDao = vrProviderDao;

View File

@ -19,7 +19,12 @@ package org.apache.cloudstack.network.router.deployment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.cloud.dc.DataCenter;
import com.cloud.dc.Vlan;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.element.NsxProviderVO;
import org.apache.log4j.Logger;
import com.cloud.dc.dao.VlanDao;
@ -120,8 +125,26 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition {
@Override
protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
sourceNatIp = null;
DataCenter zone = dest.getDataCenter();
Long zoneId = null;
if (Objects.nonNull(zone)) {
zoneId = zone.getId();
}
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
if (isPublicNetwork) {
sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(owner, vpc);
if (Objects.isNull(nsxProvider)) {
sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(owner, vpc);
} else {
// NSX deploys VRs with Public NIC != to the source NAT, the source NAT IP is on the NSX Public range
sourceNatIp = ipAddrMgr.assignPublicIpAddress(zoneId, getPodId(), owner, Vlan.VlanType.VirtualNetwork, null, null, false, true);
if (vpc != null) {
IPAddressVO routerPublicIp = ipAddressDao.findByIp(sourceNatIp.getAddress().toString());
routerPublicIp.setVpcId(vpc.getId());
routerPublicIp.setSourceNat(true);
ipAddressDao.persist(routerPublicIp);
}
}
}
}

View File

@ -252,7 +252,7 @@ public class ManagementServerImplTest {
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
Mockito.verify(sc, Mockito.times(1)).setParameters("state", "Free");
Mockito.verify(sc, Mockito.never()).setParameters("forsystemvms", false);
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
}
@Test
@ -274,7 +274,7 @@ public class ManagementServerImplTest {
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
Mockito.verify(sc, Mockito.never()).setParameters("forsystemvms", false);
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
}
@Test
@ -296,7 +296,7 @@ public class ManagementServerImplTest {
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
Mockito.verify(sc, Mockito.never()).setParameters("forsystemvms", false);
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
}
@Test