[NSX] Fix update source NAT IP (#8176)

* [NSX] Fix update source NAT IP

* Fix startup

* Fix API result
This commit is contained in:
Nicolas Vazquez 2023-11-06 08:15:00 -03:00 committed by GitHub
parent 42300aa80e
commit ecd32d5632
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 99 additions and 24 deletions

View File

@ -14,7 +14,7 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network;
package com.cloud.network.nsx;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;

View File

@ -14,9 +14,13 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.service;
package com.cloud.network.nsx;
import com.cloud.network.IpAddress;
import com.cloud.network.vpc.Vpc;
public interface NsxService {
boolean createVpcNetwork(Long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled);
boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
}

View File

@ -16,7 +16,7 @@
// under the License.
package com.cloud.network.element;
import com.cloud.network.NsxProvider;
import com.cloud.network.nsx.NsxProvider;
import com.cloud.utils.db.Encrypt;
import javax.persistence.Column;

View File

@ -16,15 +16,15 @@
// under the License.
package org.apache.cloudstack.agent.api;
public class CreateNsxTier1NatRuleCommand extends NsxCommand {
public class CreateOrUpdateNsxTier1NatRuleCommand extends NsxCommand {
private String tier1GatewayName;
private String action;
private String translatedIpAddress;
private String natRuleId;
public CreateNsxTier1NatRuleCommand(long domainId, long accountId, long zoneId,
String tier1GatewayName, String action, String translatedIpAddress, String natRuleId) {
public CreateOrUpdateNsxTier1NatRuleCommand(long domainId, long accountId, long zoneId,
String tier1GatewayName, String action, String translatedIpAddress, String natRuleId) {
super(domainId, accountId, zoneId);
this.tier1GatewayName = tier1GatewayName;
this.action = action;

View File

@ -16,7 +16,7 @@
// under the License.
package org.apache.cloudstack.api.command;
import com.cloud.network.NsxProvider;
import com.cloud.network.nsx.NsxProvider;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.BaseCmd;

View File

@ -16,7 +16,7 @@
// under the License.
package org.apache.cloudstack.api.response;
import com.cloud.network.NsxProvider;
import com.cloud.network.nsx.NsxProvider;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;

View File

@ -41,7 +41,7 @@ import org.apache.cloudstack.agent.api.CreateNsxPortForwardRuleCommand;
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.CreateNsxTier1NatRuleCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNsxTier1NatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNsxLoadBalancerRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
import org.apache.cloudstack.agent.api.DeleteNsxNatRuleCommand;
@ -111,8 +111,8 @@ public class NsxResource implements ServerResource {
return executeRequest((CreateNsxTier1GatewayCommand) cmd);
} else if (cmd instanceof CreateNsxDhcpRelayConfigCommand) {
return executeRequest((CreateNsxDhcpRelayConfigCommand) cmd);
} else if (cmd instanceof CreateNsxTier1NatRuleCommand) {
return executeRequest((CreateNsxTier1NatRuleCommand) cmd);
} else if (cmd instanceof CreateOrUpdateNsxTier1NatRuleCommand) {
return executeRequest((CreateOrUpdateNsxTier1NatRuleCommand) cmd);
} else if (cmd instanceof CreateNsxStaticNatCommand) {
return executeRequest((CreateNsxStaticNatCommand) cmd);
} else if (cmd instanceof DeleteNsxNatRuleCommand) {
@ -229,7 +229,7 @@ public class NsxResource implements ServerResource {
return true;
}
private Answer executeRequest(CreateNsxTier1NatRuleCommand cmd) {
private Answer executeRequest(CreateOrUpdateNsxTier1NatRuleCommand cmd) {
String tier1GatewayName = cmd.getTier1GatewayName();
String action = cmd.getAction();
String translatedIpAddress = cmd.getTranslatedIpAddress();

View File

@ -16,7 +16,7 @@
// under the License.
package org.apache.cloudstack.service;
import com.cloud.network.NsxProvider;
import com.cloud.network.nsx.NsxProvider;
import com.cloud.utils.component.PluggableService;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.command.AddNsxControllerCmd;

View File

@ -25,7 +25,7 @@ import com.cloud.host.Host;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.Network;
import com.cloud.network.Networks;
import com.cloud.network.NsxProvider;
import com.cloud.network.nsx.NsxProvider;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NsxProviderDao;
import com.cloud.network.dao.PhysicalNetworkDao;

View File

@ -24,6 +24,7 @@ import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
import com.cloud.network.Network;
import com.cloud.network.Networks;
import com.cloud.network.nsx.NsxService;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.guru.PublicNetworkGuru;
@ -36,7 +37,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxTier1NatRuleCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNsxTier1NatRuleCommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.cloudstack.utils.NsxHelper;
@ -142,7 +143,7 @@ public class NsxPublicNetworkGuru extends PublicNetworkGuru {
String translatedIp = ipAddress.getAddress().addr();
s_logger.debug(String.format("Creating NSX Nat Rule for Tier1 GW %s for translated IP %s", tier1GatewayName, translatedIp));
String natRuleId = NsxControllerUtils.getNsxNatRuleId(domainId, accountId, dataCenterId, resourceId, isForVpc);
CreateNsxTier1NatRuleCommand cmd = NsxHelper.createNsxNatRuleCommand(domainId, accountId, dataCenterId, tier1GatewayName, "SNAT", translatedIp, natRuleId);
CreateOrUpdateNsxTier1NatRuleCommand cmd = NsxHelper.createOrUpdateNsxNatRuleCommand(domainId, accountId, dataCenterId, tier1GatewayName, "SNAT", translatedIp, natRuleId);
NsxAnswer nsxAnswer = nsxControllerUtils.sendNsxCommand(cmd, dataCenterId);
if (!nsxAnswer.getResult()) {
String msg = String.format("Could not create NSX Nat Rule on Tier1 Gateway %s for IP %s", tier1GatewayName, translatedIp);

View File

@ -16,9 +16,12 @@
// under the License.
package org.apache.cloudstack.service;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.nsx.NsxService;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.utils.exception.CloudRuntimeException;
@ -27,12 +30,14 @@ import org.apache.cloudstack.agent.api.CreateNsxLoadBalancerRuleCommand;
import org.apache.cloudstack.agent.api.CreateNsxPortForwardRuleCommand;
import org.apache.cloudstack.agent.api.CreateNsxStaticNatCommand;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNsxTier1NatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNsxLoadBalancerRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
import org.apache.cloudstack.agent.api.DeleteNsxNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
import org.apache.cloudstack.resource.NsxNetworkRule;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.cloudstack.utils.NsxHelper;
import org.apache.log4j.Logger;
import javax.inject.Inject;
@ -55,6 +60,28 @@ public class NsxServiceImpl implements NsxService {
return result.getResult();
}
@Override
public boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address) {
if (vpc == null || address == null) {
return false;
}
long accountId = vpc.getAccountId();
long domainId = vpc.getDomainId();
long zoneId = vpc.getZoneId();
long vpcId = vpc.getId();
LOGGER.debug(String.format("Updating the source NAT IP for NSX VPC %s to IP: %s", vpc.getName(), address.getAddress().addr()));
String tier1GatewayName = NsxControllerUtils.getTier1GatewayName(domainId, accountId, zoneId, vpcId, true);
String sourceNatRuleId = NsxControllerUtils.getNsxNatRuleId(domainId, accountId, zoneId, vpcId, true);
CreateOrUpdateNsxTier1NatRuleCommand cmd = NsxHelper.createOrUpdateNsxNatRuleCommand(domainId, accountId, zoneId, tier1GatewayName, "SNAT", address.getAddress().addr(), sourceNatRuleId);
NsxAnswer answer = nsxControllerUtils.sendNsxCommand(cmd, zoneId);
if (!answer.getResult()) {
LOGGER.error(String.format("Could not update the source NAT IP address for VPC %s: %s", vpc.getName(), answer.getDetails()));
return false;
}
return true;
}
public boolean createNetwork(Long zoneId, long accountId, long domainId, Long networkId, String networkName) {
CreateNsxTier1GatewayCommand createNsxTier1GatewayCommand =
new CreateNsxTier1GatewayCommand(domainId, accountId, zoneId, networkId, networkName, false, false);

View File

@ -25,7 +25,7 @@ import com.cloud.user.Account;
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.CreateNsxTier1NatRuleCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNsxTier1NatRuleCommand;
import java.util.List;
@ -48,9 +48,9 @@ public class NsxHelper {
return new CreateNsxTier1GatewayCommand(domain.getId(), account.getId(), zone.getId(), networkResourceId, networkResourceName, isResourceVpc, false);
}
public static CreateNsxTier1NatRuleCommand createNsxNatRuleCommand(long domainId, long accountId, long zoneId,
String tier1Gateway, String action, String ipAddress,
String natRuleId) {
return new CreateNsxTier1NatRuleCommand(domainId, accountId, zoneId, tier1Gateway, action, ipAddress, natRuleId);
public static CreateOrUpdateNsxTier1NatRuleCommand createOrUpdateNsxNatRuleCommand(long domainId, long accountId, long zoneId,
String tier1Gateway, String action, String ipAddress,
String natRuleId) {
return new CreateOrUpdateNsxTier1NatRuleCommand(domainId, accountId, zoneId, tier1Gateway, action, ipAddress, natRuleId);
}
}

View File

@ -0,0 +1,32 @@
<!--
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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="nsxService" class="org.apache.cloudstack.service.NsxServiceImpl"/>
<bean id="nsxControllerUtils" class="org.apache.cloudstack.utils.NsxControllerUtils" />
</beans>

View File

@ -35,7 +35,5 @@
<property name="name" value="NsxPublicNetworkGuru" />
</bean>
<bean id="nsxProviderService" class="org.apache.cloudstack.service.NsxProviderServiceImpl"/>
<bean id="nsxService" class="org.apache.cloudstack.service.NsxServiceImpl"/>
<bean id="nsxControllerUtils" class="org.apache.cloudstack.utils.NsxControllerUtils" />
</beans>

View File

@ -20,7 +20,7 @@ import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.host.Host;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.NsxProvider;
import com.cloud.network.nsx.NsxProvider;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.NsxProviderDao;

View File

@ -40,6 +40,7 @@ import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.nsx.NsxService;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.alert.AlertService;
import org.apache.cloudstack.annotation.AnnotationService;
@ -264,6 +265,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
@Autowired
@Qualifier("networkHelper")
protected NetworkHelper networkHelper;
@Inject
private NsxService nsxService;
@Inject
private VpcPrivateGatewayTransactionCallable vpcTxCallable;
@ -1396,6 +1399,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
}
return vpcDao.findById(vpcId);
} else if (isVpcForNsx(vpcToUpdate)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("no restart needed.");
}
return vpcDao.findById(vpcId);
} else {
s_logger.error(String.format("failed to update vpc %s/%s",vpc.getName(), vpc.getUuid()));
return null;
@ -1410,6 +1418,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
if (! userIps.isEmpty()) {
try {
_ipAddrMgr.updateSourceNatIpAddress(requestedIp, userIps);
if (isVpcForNsx(vpc)) {
nsxService.updateVpcSourceNatIp(vpc, requestedIp);
// The NSX source NAT IP change does not require to update the VPC VR
return false;
}
} catch (Exception e) { // pokemon exception from transaction
String msg = String.format("Update of source NAT ip to %s for network \"%s\"/%s failed due to %s",
requestedIp.getAddress().addr(), vpc.getName(), vpc.getUuid(), e.getLocalizedMessage());