mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
NSX: Create and delete NSX Static Nat rules
This commit is contained in:
parent
116d6c3c86
commit
9e51bdfaa9
@ -0,0 +1,76 @@
|
||||
package org.apache.cloudstack.agent.api;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class CreateNsxStaticNatCommand extends NsxCommand {
|
||||
|
||||
private long vpcId;
|
||||
private String vpcName;
|
||||
private long vmId;
|
||||
private String publicIp;
|
||||
private String vmIp;
|
||||
|
||||
public CreateNsxStaticNatCommand(long domainId, long accountId, long zoneId, long vpcId, String vpcName,
|
||||
long vmId, String publicIp, String vmIp) {
|
||||
super(domainId, accountId, zoneId);
|
||||
this.vpcId = vpcId;
|
||||
this.vpcName = vpcName;
|
||||
this.vmId = vmId;
|
||||
this.publicIp = publicIp;
|
||||
this.vmIp = vmIp;
|
||||
}
|
||||
|
||||
public long getVpcId() {
|
||||
return vpcId;
|
||||
}
|
||||
|
||||
public void setVpcId(long vpcId) {
|
||||
this.vpcId = vpcId;
|
||||
}
|
||||
|
||||
public String getVpcName() {
|
||||
return vpcName;
|
||||
}
|
||||
|
||||
public void setVpcName(String vpcName) {
|
||||
this.vpcName = vpcName;
|
||||
}
|
||||
|
||||
public long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public void setVmId(long vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
|
||||
public String getPublicIp() {
|
||||
return publicIp;
|
||||
}
|
||||
|
||||
public void setPublicIp(String publicIp) {
|
||||
this.publicIp = publicIp;
|
||||
}
|
||||
|
||||
public String getVmIp() {
|
||||
return vmIp;
|
||||
}
|
||||
|
||||
public void setVmIp(String vmIp) {
|
||||
this.vmIp = vmIp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
CreateNsxStaticNatCommand that = (CreateNsxStaticNatCommand) o;
|
||||
return vpcId == that.vpcId && Objects.equals(publicIp, that.publicIp) && Objects.equals(vmIp, that.vmIp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), vpcId, publicIp, vmIp);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package org.apache.cloudstack.agent.api;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class DeleteNsxStaticNatCommand extends NsxCommand {
|
||||
private long vpcId;
|
||||
private String vpcName;
|
||||
public DeleteNsxStaticNatCommand(long domainId, long accountId, long zoneId, long vpcId, String vpcName) {
|
||||
super(domainId, accountId, zoneId);
|
||||
this.vpcId = vpcId;
|
||||
this.vpcName = vpcName;
|
||||
}
|
||||
|
||||
public long getVpcId() {
|
||||
return vpcId;
|
||||
}
|
||||
|
||||
public void setVpcId(long vpcId) {
|
||||
this.vpcId = vpcId;
|
||||
}
|
||||
|
||||
public String getVpcName() {
|
||||
return vpcName;
|
||||
}
|
||||
|
||||
public void setVpcName(String vpcName) {
|
||||
this.vpcName = vpcName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
DeleteNsxStaticNatCommand that = (DeleteNsxStaticNatCommand) o;
|
||||
return vpcId == that.vpcId && Objects.equals(vpcName, that.vpcName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), vpcId, vpcName);
|
||||
}
|
||||
}
|
||||
@ -36,8 +36,10 @@ import org.apache.cloudstack.NsxAnswer;
|
||||
import org.apache.cloudstack.StartupNsxCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNsxStaticNatCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNsxStaticNatCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
|
||||
import org.apache.cloudstack.service.NsxApiClient;
|
||||
import org.apache.cloudstack.utils.NsxControllerUtils;
|
||||
@ -103,6 +105,10 @@ public class NsxResource implements ServerResource {
|
||||
return executeRequest((CreateNsxTier1GatewayCommand) cmd);
|
||||
} else if (cmd instanceof CreateNsxDhcpRelayConfigCommand) {
|
||||
return executeRequest((CreateNsxDhcpRelayConfigCommand) cmd);
|
||||
} else if (cmd instanceof CreateNsxStaticNatCommand) {
|
||||
return executeRequest((CreateNsxStaticNatCommand) cmd);
|
||||
} else if (cmd instanceof DeleteNsxStaticNatCommand) {
|
||||
return executeRequest((DeleteNsxStaticNatCommand) cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
@ -331,6 +337,34 @@ public class NsxResource implements ServerResource {
|
||||
return new NsxAnswer(cmd, true, null);
|
||||
}
|
||||
|
||||
private NsxAnswer executeRequest(CreateNsxStaticNatCommand cmd) {
|
||||
String staticNatRuleName = NsxControllerUtils.getStaticNatRuleName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(),
|
||||
cmd.getVpcId());
|
||||
String tier1GatewayName = NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(),
|
||||
cmd.getVpcId());
|
||||
try {
|
||||
nsxApiClient.createStaticNatRule(cmd.getVpcName(), tier1GatewayName, staticNatRuleName, cmd.getPublicIp(), cmd.getVmIp());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(String.format("Failed to add NSX static NAT rule %s for network: %s", staticNatRuleName, cmd.getVpcName()));
|
||||
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
|
||||
}
|
||||
return new NsxAnswer(cmd, true, null);
|
||||
}
|
||||
|
||||
private NsxAnswer executeRequest(DeleteNsxStaticNatCommand cmd) {
|
||||
String staticNatRuleName = NsxControllerUtils.getStaticNatRuleName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(),
|
||||
cmd.getVpcId());
|
||||
String tier1GatewayName = NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(),
|
||||
cmd.getVpcId());
|
||||
try {
|
||||
nsxApiClient.deleteStaticNatRule(cmd.getVpcName(), tier1GatewayName, staticNatRuleName);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(String.format("Failed to add NSX static NAT rule %s for network: %s", staticNatRuleName, cmd.getVpcName()));
|
||||
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
|
||||
}
|
||||
return new NsxAnswer(cmd, true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
|
||||
@ -26,10 +26,14 @@ import com.vmware.nsx_policy.infra.Sites;
|
||||
import com.vmware.nsx_policy.infra.Tier1s;
|
||||
import com.vmware.nsx_policy.infra.sites.EnforcementPoints;
|
||||
import com.vmware.nsx_policy.infra.tier_0s.LocaleServices;
|
||||
import com.vmware.nsx_policy.infra.tier_1s.Nat;
|
||||
import com.vmware.nsx_policy.infra.tier_1s.nat.NatRules;
|
||||
import com.vmware.nsx_policy.model.ApiError;
|
||||
import com.vmware.nsx_policy.model.DhcpRelayConfig;
|
||||
import com.vmware.nsx_policy.model.EnforcementPointListResult;
|
||||
import com.vmware.nsx_policy.model.LocaleServicesListResult;
|
||||
import com.vmware.nsx_policy.model.PolicyNat;
|
||||
import com.vmware.nsx_policy.model.PolicyNatRule;
|
||||
import com.vmware.nsx_policy.model.Segment;
|
||||
import com.vmware.nsx_policy.model.SegmentSubnet;
|
||||
import com.vmware.nsx_policy.model.SiteListResult;
|
||||
@ -79,6 +83,16 @@ public class NsxApiClient {
|
||||
|
||||
private enum TransportType { OVERLAY, VLAN }
|
||||
|
||||
private enum NatId { USER, INTERNAL, DEFAULT }
|
||||
|
||||
private enum NatAction {SNAT, DNAT, REFLEXIVE}
|
||||
|
||||
private enum FirewallMatch {
|
||||
MATCH_INTERNAL_ADDRESS,
|
||||
MATCH_EXTERNAL_ADDRESS,
|
||||
BYPASS
|
||||
}
|
||||
|
||||
public enum RouteAdvertisementType { TIER1_STATIC_ROUTES, TIER1_CONNECTED, TIER1_NAT,
|
||||
TIER1_LB_VIP, TIER1_LB_SNAT, TIER1_DNS_FORWARDER_IP, TIER1_IPSEC_LOCAL_ENDPOINT
|
||||
}
|
||||
@ -290,4 +304,43 @@ public class NsxApiClient {
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void createStaticNatRule(String vpcName, String tier1GatewayName,
|
||||
String ruleName, String publicIp, String vmIp) {
|
||||
try {
|
||||
NatRules natService = (NatRules) nsxService.apply(NatRules.class);
|
||||
PolicyNatRule rule = new PolicyNatRule.Builder()
|
||||
.setId(ruleName)
|
||||
.setDisplayName(ruleName)
|
||||
.setAction(NatAction.DNAT.name())
|
||||
.setFirewallMatch(FirewallMatch.MATCH_INTERNAL_ADDRESS.name())
|
||||
.setDestinationNetwork(publicIp)
|
||||
.setTranslatedNetwork(vmIp)
|
||||
.setEnabled(true)
|
||||
.build();
|
||||
|
||||
LOGGER.debug(String.format("Creating NSX static NAT rule %s for tier-1 gateway %s (VPC: %s)", ruleName, tier1GatewayName, vpcName));
|
||||
natService.patch(tier1GatewayName, NatId.USER.name(), ruleName, rule);
|
||||
} catch (Error error) {
|
||||
ApiError ae = error.getData()._convertTo(ApiError.class);
|
||||
String msg = String.format("Error creating NSX Static NAT rule %s for tier-1 gateway %s (VPC: %s), due to %s",
|
||||
ruleName, tier1GatewayName, vpcName, ae.getErrorMessage());
|
||||
LOGGER.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteStaticNatRule(String vpcName, String tier1GatewayName, String ruleName) {
|
||||
try {
|
||||
NatRules natService = (NatRules) nsxService.apply(NatRules.class);
|
||||
LOGGER.debug(String.format("Deleting NSX static NAT rule %s for tier-1 gateway %s (VPC: %s)", ruleName, tier1GatewayName, vpcName));
|
||||
natService.delete(tier1GatewayName, NatId.USER.name(), ruleName);
|
||||
} catch (Error error) {
|
||||
ApiError ae = error.getData()._convertTo(ApiError.class);
|
||||
String msg = String.format("Failed to delete NSX Static NAT rule %s for tier-1 gateway %s (VPC: %s), due to %s",
|
||||
ruleName, tier1GatewayName, vpcName, ae.getErrorMessage());
|
||||
LOGGER.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,13 +41,19 @@ import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||
import com.cloud.network.PublicIpAddress;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.dao.PhysicalNetworkDao;
|
||||
import com.cloud.network.dao.PhysicalNetworkVO;
|
||||
import com.cloud.network.element.DhcpServiceProvider;
|
||||
import com.cloud.network.element.DnsServiceProvider;
|
||||
import com.cloud.network.element.IpDeployer;
|
||||
import com.cloud.network.element.StaticNatServiceProvider;
|
||||
import com.cloud.network.element.VpcProvider;
|
||||
import com.cloud.network.rules.StaticNat;
|
||||
import com.cloud.network.vpc.NetworkACLItem;
|
||||
import com.cloud.network.vpc.PrivateGateway;
|
||||
import com.cloud.network.vpc.StaticRouteProfile;
|
||||
@ -62,9 +68,12 @@ import com.cloud.user.AccountManager;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.Nic;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.ReservationContext;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
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.log4j.Logger;
|
||||
@ -81,7 +90,7 @@ import java.util.function.LongFunction;
|
||||
|
||||
@Component
|
||||
public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsServiceProvider, VpcProvider,
|
||||
ResourceStateAdapter, Listener {
|
||||
StaticNatServiceProvider, IpDeployer, ResourceStateAdapter, Listener {
|
||||
|
||||
@Inject
|
||||
AccountManager accountMgr;
|
||||
@ -101,6 +110,10 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
|
||||
NetworkModel networkModel;
|
||||
@Inject
|
||||
DomainDao domainDao;
|
||||
@Inject
|
||||
IPAddressDao ipAddressDao;
|
||||
@Inject
|
||||
VMInstanceDao vmInstanceDao;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(NsxElement.class);
|
||||
|
||||
@ -172,6 +185,11 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Network.Service> services) throws ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Network.Provider getProvider() {
|
||||
return Network.Provider.Nsx;
|
||||
@ -412,4 +430,32 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
|
||||
}
|
||||
|
||||
private final LongFunction<DataCenterVO> zoneFunction = zoneId -> dataCenterDao.findById(zoneId);
|
||||
|
||||
@Override
|
||||
public IpDeployer getIpDeployer(Network network) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
|
||||
for(StaticNat staticNat : rules) {
|
||||
long sourceIpAddressId = staticNat.getSourceIpAddressId();
|
||||
IPAddressVO ipAddressVO = ipAddressDao.findByIdIncludingRemoved(sourceIpAddressId);
|
||||
VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(ipAddressVO.getAssociatedWithVmId());
|
||||
// floating ip is released when nic was deleted
|
||||
if (vm == null || networkModel.getNicInNetworkIncludingRemoved(vm.getId(), config.getId()) == null) {
|
||||
continue;
|
||||
}
|
||||
Nic nic = networkModel.getNicInNetworkIncludingRemoved(vm.getId(), config.getId());
|
||||
Network publicNetwork = networkModel.getSystemNetworkByZoneAndTrafficType(config.getDataCenterId(), Networks.TrafficType.Public);
|
||||
if (!staticNat.isForRevoke()) {
|
||||
return nsxService.createStaticNatRule(config.getDataCenterId(), config.getDomainId(), config.getAccountId(),
|
||||
config.getVpcId(), vm.getId(), ipAddressVO.getAddress().addr(), staticNat.getDestIpAddress());
|
||||
} else {
|
||||
return nsxService.deleteStaticNatRule(config.getDataCenterId(), config.getDomainId(), config.getAccountId(),
|
||||
config.getVpcId());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,9 +19,12 @@ package org.apache.cloudstack.service;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.NsxAnswer;
|
||||
import org.apache.cloudstack.agent.api.CreateNsxStaticNatCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNsxStaticNatCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
|
||||
import org.apache.cloudstack.utils.NsxControllerUtils;
|
||||
|
||||
@ -59,4 +62,27 @@ public class NsxServiceImpl implements NsxService {
|
||||
NsxAnswer result = nsxControllerUtils.sendNsxCommand(deleteNsxSegmentCommand, network.getDataCenterId());
|
||||
return result.getResult();
|
||||
}
|
||||
|
||||
public boolean createStaticNatRule(long zoneId, long accountId, long domainId, long vpcId,
|
||||
long vmId, String publicIp, String vmIp) {
|
||||
VpcVO vpc = vpcDao.findById(vpcId);
|
||||
if (Objects.isNull(vpc)) {
|
||||
throw new CloudRuntimeException(String.format("Failed to find VPC with id: %s", vpcId));
|
||||
}
|
||||
CreateNsxStaticNatCommand createNsxStaticNatCommand = new CreateNsxStaticNatCommand(domainId, accountId, zoneId,
|
||||
vpcId, vpc.getName(), vmId, publicIp, vmIp);
|
||||
NsxAnswer result = nsxControllerUtils.sendNsxCommand(createNsxStaticNatCommand, zoneId);
|
||||
return result.getResult();
|
||||
}
|
||||
|
||||
public boolean deleteStaticNatRule(long zoneId, long accountId, long domainId, long vpcId) {
|
||||
VpcVO vpc = vpcDao.findById(vpcId);
|
||||
if (Objects.isNull(vpc)) {
|
||||
throw new CloudRuntimeException(String.format("Failed to find VPC with id: %s", vpcId));
|
||||
}
|
||||
DeleteNsxStaticNatCommand deleteNsxStaticNatCommand = new DeleteNsxStaticNatCommand(domainId, accountId, zoneId,
|
||||
vpcId, vpc.getName());
|
||||
NsxAnswer result = nsxControllerUtils.sendNsxCommand(deleteNsxStaticNatCommand, zoneId);
|
||||
return result.getResult();
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,4 +75,9 @@ public class NsxControllerUtils {
|
||||
}
|
||||
return String.format("D%s-A%s-Z%s-V%s-S%s-%s", domainId, accountId, zoneId, vpcId, networkId, suffix);
|
||||
}
|
||||
|
||||
public static String getStaticNatRuleName(long zoneId, long domainId, long accountId, Long vpcId) {
|
||||
String suffix = "-STATICNAT";
|
||||
return getTier1GatewayName(domainId, accountId, zoneId, vpcId) + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user