changes in this commit:

1. stop and start vm operations wont trigger dns sync
2. ip update for nic will refresh dns records
This commit is contained in:
Manoj Kumar 2026-04-24 12:32:58 +05:30
parent 172ac67732
commit 5f627aa70a
No known key found for this signature in database
GPG Key ID: E952B7234D2C6F88
3 changed files with 45 additions and 35 deletions

View File

@ -18,6 +18,7 @@ package com.cloud.vm;
import static com.cloud.event.EventTypes.EVENT_NIC_CREATE;
import static com.cloud.event.EventTypes.EVENT_NIC_DELETE;
import static com.cloud.event.EventTypes.EVENT_NIC_UPDATE;
import static com.cloud.event.EventTypes.EVENT_VM_UPDATE;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality;
import static com.cloud.storage.Volume.IOPS_LIMIT;
@ -1582,7 +1583,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
event.put(ApiConstants.INSTANCE_ID, instanceId);
event.put(ApiConstants.ACCOUNT_ID, accountId);
event.put(ApiConstants.NIC_ID, nicId);
event.put(ApiConstants.EVENT_TYPE, eventType); // NIC_CREATE or NIC_DELETE
event.put(ApiConstants.EVENT_TYPE, eventType); // NIC.CREATE, NIC.DELETE or NIC.UPDATE
event.put(ApiConstants.TIME_STAMP, System.currentTimeMillis());
messageBus.publish(_name, Nic.Topics.NIC_LIFECYCLE, PublishScope.GLOBAL, event);
@ -1965,7 +1966,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
logger.debug("Updating IPv4 address of NIC " + nicVO + " to " + ipaddr + "/" + nicVO.getIPv4Netmask() + " with gateway " + nicVO.getIPv4Gateway());
nicVO.setIPv4Address(ipaddr);
_nicDao.persist(nicVO);
publishNicEventMessageBus(vm.getId(), vm.getAccountId(), nicVO.getId(), EVENT_NIC_UPDATE);
return vm;
}
@ -3506,10 +3507,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (cmd.getConsiderLastHost() != null) {
additonalParams.put(VirtualMachineProfile.Param.ConsiderLastHost, cmd.getConsiderLastHost().toString());
}
UserVmVO vm = _vmDao.findById(cmd.getId());
UserVm userVm = startVirtualMachine(cmd.getId(), cmd.getPodId(), cmd.getClusterId(), cmd.getHostId(), additonalParams, cmd.getDeploymentPlanner()).first();
publishVmLifecycleMessageBus(userVm, vm.getState(), VirtualMachine.State.Running);
return userVm;
return startVirtualMachine(cmd.getId(), cmd.getPodId(), cmd.getClusterId(), cmd.getHostId(), additonalParams, cmd.getDeploymentPlanner()).first();
}
@Override
@ -5785,7 +5784,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
status = vmEntity.stop(Long.toString(userId));
}
if (status) {
publishVmLifecycleMessageBus(vm, vm.getState(), VirtualMachine.State.Stopped);
return _vmDao.findById(vmId);
} else {
return null;

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.dns;
import static com.cloud.event.EventTypes.EVENT_NIC_CREATE;
import static com.cloud.event.EventTypes.EVENT_NIC_DELETE;
import static com.cloud.event.EventTypes.EVENT_NIC_UPDATE;
import static com.cloud.event.EventTypes.EVENT_VM_UPDATE;
import java.util.ArrayList;
@ -804,15 +805,13 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
long instanceId = (long) event.get(ApiConstants.INSTANCE_ID);
switch (newState) {
case Running:
handleVmRunningState(instanceId);
handleVmCreateEvent(instanceId);
break;
case Stopped:
case Destroyed:
handleVmStopAndDestroy(instanceId);
handleVmDestroyEvent(instanceId);
break;
default:
logger.warn("Ignoring lifecycle event for Instance ID: {}, unsupported state={}", instanceId, newState);
break;
}
} catch (Exception ex) {
logger.error("Failed to process Instance lifecycle event", ex);
@ -835,12 +834,19 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
logger.warn("Insufficient data to process NIC lifecycle event: {}", args);
return;
}
if (EVENT_NIC_CREATE.equals(eventType)) {
handleNicPlug(instanceId, nicId);
} else if (EVENT_NIC_DELETE.equals(eventType)) {
handleNicUnplug(instanceId, nicId);
} else {
logger.warn("Ignoring lifecycle event for NIC with ID: {}, unsupported eventType={}", nicId, eventType);
switch (eventType) {
case EVENT_NIC_CREATE:
handleNicPlug(instanceId, nicId);
break;
case EVENT_NIC_DELETE:
handleNicUnplug(instanceId, nicId);
break;
case EVENT_NIC_UPDATE:
handleNicRefresh(instanceId, nicId);
break;
default:
logger.warn("Ignoring lifecycle event for NIC with ID: {}, unsupported eventType={}", nicId, eventType);
}
} catch (Exception ex) {
logger.error("Failed to process NIC lifecycle event", ex);
@ -876,7 +882,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
}
}
void handleVmRunningState(long instanceId) {
void handleVmCreateEvent(long instanceId) {
VirtualMachine instance = vmInstanceDao.findById(instanceId);
if (instance == null) {
logger.debug("Instance is not found for the given ID: {}", instanceId);
@ -926,7 +932,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
}
}
void handleVmStopAndDestroy(long instanceId) {
void handleVmDestroyEvent(long instanceId) {
List<NicDnsJoinVO> historicalNics = nicDnsJoinDao.listIncludingRemovedByVmId(instanceId);
if (CollectionUtils.isEmpty(historicalNics)) {
return;
@ -1109,6 +1115,11 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
}
}
private void handleNicRefresh(long instanceId, long nicId) {
handleNicUnplug(instanceId, nicId);
handleNicPlug(instanceId, nicId);
}
String prepareDnsRecordUrl(String hostName, String subDomain, String dnsZoneName) {
List<String> parts = new ArrayList<>();
parts.add(hostName);

View File

@ -91,6 +91,7 @@ import com.cloud.user.AccountVO;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
@ -891,11 +892,11 @@ public class DnsProviderManagerImplTest {
}
@Test
public void testVmLifecycleSubscriberStopped() {
public void testVmLifecycleSubscriberDestroyed() {
DnsProviderManagerImpl.VmLifecycleSubscriber subscriber = manager.new VmLifecycleSubscriber();
java.util.Map<String, Object> event = new java.util.HashMap<>();
event.put(org.apache.cloudstack.api.ApiConstants.OLD_STATE, com.cloud.vm.VirtualMachine.State.Running);
event.put(org.apache.cloudstack.api.ApiConstants.NEW_STATE, com.cloud.vm.VirtualMachine.State.Stopped);
event.put(org.apache.cloudstack.api.ApiConstants.NEW_STATE, VirtualMachine.State.Destroyed);
event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 15L);
when(nicDnsJoinDao.listIncludingRemovedByVmId(15L)).thenReturn(null);
subscriber.onPublishMessage("sender", "subject", event);
@ -1065,32 +1066,32 @@ public class DnsProviderManagerImplTest {
}
@Test
public void testHandleVmRunningStateFoundButNoActiveNics() throws DnsProviderException {
public void testHandleVmCreateEventFoundButNoActiveNics() throws DnsProviderException {
com.cloud.vm.VMInstanceVO instanceMock = mock(com.cloud.vm.VMInstanceVO.class);
when(vmInstanceDao.findById(30L)).thenReturn(instanceMock);
when(nicDnsJoinDao.listActiveByVmId(30L)).thenReturn(Collections.emptyList());
manager.handleVmRunningState(30L);
manager.handleVmCreateEvent(30L);
verify(dnsProviderMock, never()).addRecord(any(), any(), any());
verify(dnsProviderMock, never()).deleteRecord(any(), any(), any());
}
@Test
public void testHandleVmStopAndDestroyNicWithNullDnsUrlIsSkipped() throws DnsProviderException {
public void testHandleVmDestroyEventNicWithNullDnsUrlIsSkipped() throws DnsProviderException {
NicDnsJoinVO nicMock =
mock(NicDnsJoinVO.class);
when(nicMock.getNicDnsName()).thenReturn(null);
when(nicDnsJoinDao.listIncludingRemovedByVmId(31L))
.thenReturn(Collections.singletonList(nicMock));
manager.handleVmStopAndDestroy(31L);
manager.handleVmDestroyEvent(31L);
verify(dnsProviderMock, never()).deleteRecord(any(), any(), any());
}
@Test
public void testHandleVmStopAndDestroyWithValidDnsUrlTriggersCleanup() throws Exception {
public void testHandleVmDestroyEventWithValidDnsUrlTriggersCleanup() throws Exception {
NicDnsJoinVO nicMock =
mock(NicDnsJoinVO.class);
when(nicMock.getNicDnsName()).thenReturn("myvm.example.com");
@ -1118,7 +1119,7 @@ public class DnsProviderManagerImplTest {
return null;
});
manager.handleVmStopAndDestroy(32L);
manager.handleVmDestroyEvent(32L);
verify(nicDetailsDao).removeDetail(nicMock.getId(), org.apache.cloudstack.api.ApiConstants.NIC_DNS_NAME);
verify(dnsProviderMock, times(2)).deleteRecord(eq(serverVO), eq(zoneVO), any(DnsRecord.class));
@ -1258,7 +1259,7 @@ public class DnsProviderManagerImplTest {
}
@Test
public void testHandleVmRunningStateNonEmptyNicsAllZonesMissingSkipsSync() throws DnsProviderException {
public void testHandleVmCreateEventNonEmptyNicsAllZonesMissingSkipsSync() throws DnsProviderException {
com.cloud.vm.VMInstanceVO instanceMock = mock(com.cloud.vm.VMInstanceVO.class);
when(vmInstanceDao.findById(42L)).thenReturn(instanceMock);
@ -1268,7 +1269,7 @@ public class DnsProviderManagerImplTest {
when(nicDnsJoinDao.listActiveByVmId(42L)).thenReturn(Collections.singletonList(nicMock));
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(null); // zone null NIC skipped empty outer map
manager.handleVmRunningState(42L);
manager.handleVmCreateEvent(42L);
verify(dnsZoneDao, times(1)).findById(ZONE_ID);
verify(dnsProviderMock, never()).addRecord(any(), any(), any());
@ -1299,14 +1300,14 @@ public class DnsProviderManagerImplTest {
// handleVmRunningState
@Test
public void testHandleVmRunningStateInstanceNullExitsEarly() throws DnsProviderException {
public void testHandleVmCreateEventInstanceNullExitsEarly() throws DnsProviderException {
when(vmInstanceDao.findById(50L)).thenReturn(null);
manager.handleVmRunningState(50L);
manager.handleVmCreateEvent(50L);
verify(nicDnsJoinDao, never()).listActiveByVmId(anyLong());
}
@Test
public void testHandleVmRunningStateFullSyncNoCollision() throws Exception {
public void testHandleVmCreateEventFullSyncNoCollision() throws Exception {
com.cloud.vm.VMInstanceVO instanceMock = mock(com.cloud.vm.VMInstanceVO.class);
when(instanceMock.getHostName()).thenReturn("myvm");
when(vmInstanceDao.findById(51L)).thenReturn(instanceMock);
@ -1337,7 +1338,7 @@ public class DnsProviderManagerImplTest {
return null;
});
manager.handleVmRunningState(51L);
manager.handleVmCreateEvent(51L);
verify(nicDetailsDao).addDetail(anyLong(),
eq(org.apache.cloudstack.api.ApiConstants.NIC_DNS_NAME), anyString(), eq(true));
@ -1346,7 +1347,7 @@ public class DnsProviderManagerImplTest {
}
@Test
public void testHandleVmRunningStateCollisionSkipsAddDetail() throws Exception {
public void testHandleVmCreateEventCollisionSkipsAddDetail() throws Exception {
com.cloud.vm.VMInstanceVO instanceMock = mock(com.cloud.vm.VMInstanceVO.class);
when(instanceMock.getHostName()).thenReturn("myvm");
when(vmInstanceDao.findById(52L)).thenReturn(instanceMock);
@ -1381,7 +1382,7 @@ public class DnsProviderManagerImplTest {
return null;
});
manager.handleVmRunningState(52L);
manager.handleVmCreateEvent(52L);
verify(nicDetailsDao, never()).addDetail(anyLong(), anyString(), anyString(), eq(true));
verify(dnsProviderMock, never()).addRecord(any(), any(), any());