network: update ip in lb/pf/dnat tables when update vm nic ip (#5757)

* network: update ip in lb/pf/dnat tables when update vm nic ip

* Update: create 3 separated methods for DNAT/LB/PF update

* Update: invert if condition to reduce code indentation
This commit is contained in:
Wei Zhou 2021-12-27 21:05:29 +01:00 committed by GitHub
parent 19325d0286
commit 7823868746
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 34 deletions

View File

@ -341,6 +341,7 @@ import com.cloud.utils.db.UUIDManager;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.DomainRouterDao;
@ -1747,38 +1748,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("Allocating ip to guest nic " + nicVO.getUuid() + " failed, please choose another ip");
}
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.StaticNat)) {
IPAddressVO oldIP = _ipAddressDao.findByAssociatedVmId(vm.getId());
if (oldIP != null) {
oldIP.setVmIp(ipaddr);
_ipAddressDao.persist(oldIP);
}
if (nicVO.getIPv4Address() != null) {
updatePublicIpDnatVmIp(vm.getId(), network.getId(), nicVO.getIPv4Address(), ipaddr);
updateLoadBalancerRulesVmIp(vm.getId(), network.getId(), nicVO.getIPv4Address(), ipaddr);
updatePortForwardingRulesVmIp(vm.getId(), network.getId(), nicVO.getIPv4Address(), ipaddr);
}
// implementing the network elements and resources as a part of vm nic ip update if network has services and it is in Implemented state
if (!_networkModel.listNetworkOfferingServices(offering.getId()).isEmpty() && network.getState() == Network.State.Implemented) {
User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId());
ReservationContext context = new ReservationContextImpl(null, null, callerUser, caller);
DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
s_logger.debug("Implementing the network " + network + " elements and resources as a part of vm nic ip update");
try {
// implement the network elements and rules again
_networkMgr.implementNetworkElementsAndResources(dest, context, network, offering);
} catch (Exception ex) {
s_logger.warn("Failed to implement network " + network + " elements and resources as a part of vm nic ip update due to ", ex);
CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id) elements and resources as a part of vm nic ip update");
e.addProxyObject(network.getUuid(), "networkId");
// restore to old ip address
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.StaticNat)) {
IPAddressVO oldIP = _ipAddressDao.findByAssociatedVmId(vm.getId());
if (oldIP != null) {
oldIP.setVmIp(nicVO.getIPv4Address());
_ipAddressDao.persist(oldIP);
}
}
throw e;
}
}
} else if (dc.getNetworkType() == NetworkType.Basic || network.getGuestType() == Network.GuestType.Shared) {
//handle the basic networks here
//for basic zone, need to provide the podId to ensure proper ip alloation
@ -1826,6 +1801,48 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return vm;
}
private void updatePublicIpDnatVmIp(long vmId, long networkId, String oldIp, String newIp) {
if (!_networkModel.areServicesSupportedInNetwork(networkId, Service.StaticNat)) {
return;
}
List<IPAddressVO> publicIps = _ipAddressDao.listByAssociatedVmId(vmId);
for (IPAddressVO publicIp : publicIps) {
if (oldIp.equals(publicIp.getVmIp()) && publicIp.getAssociatedWithNetworkId() == networkId) {
publicIp.setVmIp(newIp);
_ipAddressDao.persist(publicIp);
}
}
}
private void updateLoadBalancerRulesVmIp(long vmId, long networkId, String oldIp, String newIp) {
if (!_networkModel.areServicesSupportedInNetwork(networkId, Service.Lb)) {
return;
}
List<LoadBalancerVMMapVO> loadBalancerVMMaps = _loadBalancerVMMapDao.listByInstanceId(vmId);
for (LoadBalancerVMMapVO map : loadBalancerVMMaps) {
long lbId = map.getLoadBalancerId();
FirewallRuleVO rule = _rulesDao.findById(lbId);
if (oldIp.equals(map.getInstanceIp()) && networkId == rule.getNetworkId()) {
map.setInstanceIp(newIp);
_loadBalancerVMMapDao.persist(map);
}
}
}
private void updatePortForwardingRulesVmIp(long vmId, long networkId, String oldIp, String newIp) {
if (!_networkModel.areServicesSupportedInNetwork(networkId, Service.PortForwarding)) {
return;
}
List<PortForwardingRuleVO> firewallRules = _portForwardingDao.listByVm(vmId);
for (PortForwardingRuleVO firewallRule : firewallRules) {
FirewallRuleVO rule = _rulesDao.findById(firewallRule.getId());
if (oldIp.equals(firewallRule.getDestinationIpAddress().toString()) && networkId == rule.getNetworkId()) {
firewallRule.setDestinationIpAddress(new Ip(newIp));
_portForwardingDao.persist(firewallRule);
}
}
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_UPGRADE, eventDescription = "Upgrading VM", async = true)
public UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,

View File

@ -30,7 +30,6 @@ import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.lenient;
@ -78,7 +77,6 @@ import com.cloud.dc.DataCenterVO;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
@ -575,8 +573,6 @@ public class UserVmManagerTest {
when(_dcMock.getNetworkType()).thenReturn(NetworkType.Advanced);
when(_ipAddrMgr.allocateGuestIP(Mockito.eq(_networkMock), anyString())).thenReturn("10.10.10.10");
doNothing().when(_networkMgr).implementNetworkElementsAndResources(Mockito.any(DeployDestination.class), Mockito.any(ReservationContext.class), Mockito.eq(_networkMock),
Mockito.eq(_networkOfferingMock));
when(_nicDao.persist(any(NicVO.class))).thenReturn(nic);
Account caller = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());