Skip to content

Commit 94cd268

Browse files
server: keep collecting VM network stats after a non DirectAttached NIC
collectVmNetworkStatistics used break when a NIC was not on a DirectAttached network, which ended the whole loop. A DirectAttached (shared network) NIC ordered after an isolated one therefore never had its statistics recorded when the VM was stopped. Skip only that NIC.
1 parent b93f603 commit 94cd268

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5019,7 +5019,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
50195019
List<VlanVO> vlan = _vlanDao.listVlansByNetworkId(nic.getNetworkId());
50205020
if (vlan == null || vlan.size() == 0 || vlan.get(0).getVlanType() != VlanType.DirectAttached)
50215021
{
5022-
break; // only get network statistics for DirectAttached network (shared networks in Basic zone and Advanced zone with/without SG)
5022+
continue; // only get network statistics for DirectAttached network (shared networks in Basic zone and Advanced zone with/without SG)
50235023
}
50245024
UserStatisticsVO previousvmNetworkStats = _userStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), userVm.getId(), "UserVm");
50255025
if (previousvmNetworkStats == null) {

server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,19 @@
7777
import org.mockito.junit.MockitoJUnitRunner;
7878
import org.springframework.test.util.ReflectionTestUtils;
7979

80+
import com.cloud.agent.AgentManager;
81+
import com.cloud.agent.api.GetVmNetworkStatsAnswer;
82+
import com.cloud.agent.api.GetVmNetworkStatsCommand;
83+
import com.cloud.agent.api.VmNetworkStatsEntry;
8084
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
8185
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
8286
import com.cloud.configuration.Resource;
8387
import com.cloud.dc.DataCenter;
8488
import com.cloud.dc.DataCenterVO;
89+
import com.cloud.dc.Vlan;
90+
import com.cloud.dc.VlanVO;
8591
import com.cloud.dc.dao.DataCenterDao;
92+
import com.cloud.dc.dao.VlanDao;
8693
import com.cloud.deploy.DataCenterDeployment;
8794
import com.cloud.deploy.DeployDestination;
8895
import com.cloud.deploy.DeploymentPlanner;
@@ -151,13 +158,18 @@
151158
import com.cloud.user.ResourceLimitService;
152159
import com.cloud.user.UserData;
153160
import com.cloud.user.UserDataVO;
161+
import com.cloud.user.UserStatisticsVO;
154162
import com.cloud.user.UserVO;
155163
import com.cloud.user.dao.AccountDao;
156164
import com.cloud.user.dao.UserDao;
157165
import com.cloud.user.dao.UserDataDao;
166+
import com.cloud.user.dao.UserStatisticsDao;
158167
import com.cloud.uservm.UserVm;
159168
import com.cloud.utils.Pair;
160169
import com.cloud.utils.db.EntityManager;
170+
import com.cloud.utils.db.SearchCriteria;
171+
import com.cloud.utils.db.Transaction;
172+
import com.cloud.utils.db.TransactionCallback;
161173
import com.cloud.utils.exception.CloudRuntimeException;
162174
import com.cloud.utils.exception.ExceptionProxyObject;
163175
import com.cloud.vm.dao.NicDao;
@@ -263,6 +275,15 @@ public class UserVmManagerImplTest {
263275
@Mock
264276
HostDao hostDao;
265277

278+
@Mock
279+
AgentManager agentManager;
280+
281+
@Mock
282+
VlanDao vlanDao;
283+
284+
@Mock
285+
UserStatisticsDao userStatsDao;
286+
266287
@Mock
267288
private VolumeVO volumeVOMock;
268289

@@ -3201,4 +3222,50 @@ public void getRootVolumeSizeForVmRestoreAppliesMaxIopsToTheMaxIopsField() {
32013222
Assert.assertEquals(Long.valueOf(500L), volume.getMinIops());
32023223
Assert.assertEquals(Long.valueOf(2000L), volume.getMaxIops());
32033224
}
3225+
3226+
@Test
3227+
public void collectVmNetworkStatisticsSkipsANonDirectAttachedNicAndStillUpdatesTheNextOne() {
3228+
long hostId = 1L;
3229+
String vmName = "i-2-3-VM";
3230+
Mockito.when(userVmVoMock.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
3231+
Mockito.when(userVmVoMock.getHostId()).thenReturn(hostId);
3232+
Mockito.when(userVmVoMock.getInstanceName()).thenReturn(vmName);
3233+
Mockito.when(hostDao.findById(hostId)).thenReturn(Mockito.mock(HostVO.class));
3234+
3235+
HashMap<String, List<VmNetworkStatsEntry>> statsByVm = new HashMap<>();
3236+
statsByVm.put(vmName, List.of(new VmNetworkStatsEntry(vmName, "02:00:00:00:00:01", 100L, 200L),
3237+
new VmNetworkStatsEntry(vmName, "02:00:00:00:00:02", 300L, 400L)));
3238+
GetVmNetworkStatsAnswer answer = Mockito.mock(GetVmNetworkStatsAnswer.class);
3239+
Mockito.when(answer.getResult()).thenReturn(true);
3240+
Mockito.when(answer.getVmNetworkStatsMap()).thenReturn(statsByVm);
3241+
Mockito.when(agentManager.easySend(Mockito.eq(hostId), Mockito.any(GetVmNetworkStatsCommand.class))).thenReturn(answer);
3242+
3243+
NicVO isolatedNic = Mockito.mock(NicVO.class);
3244+
Mockito.when(isolatedNic.getNetworkId()).thenReturn(10L);
3245+
NicVO sharedNic = Mockito.mock(NicVO.class);
3246+
Mockito.when(sharedNic.getNetworkId()).thenReturn(20L);
3247+
SearchCriteria<NicVO> nicSearch = Mockito.mock(SearchCriteria.class);
3248+
Mockito.when(nicDao.createSearchCriteria()).thenReturn(nicSearch);
3249+
Mockito.when(nicDao.search(nicSearch, null)).thenReturn(List.of(isolatedNic), List.of(sharedNic));
3250+
3251+
VlanVO directAttachedVlan = Mockito.mock(VlanVO.class);
3252+
Mockito.when(directAttachedVlan.getVlanType()).thenReturn(Vlan.VlanType.DirectAttached);
3253+
Mockito.when(vlanDao.listVlansByNetworkId(10L)).thenReturn(new ArrayList<>());
3254+
Mockito.when(vlanDao.listVlansByNetworkId(20L)).thenReturn(List.of(directAttachedVlan));
3255+
3256+
UserStatisticsVO sharedNicStatistics = Mockito.mock(UserStatisticsVO.class);
3257+
Mockito.when(userStatsDao.findBy(Mockito.anyLong(), Mockito.anyLong(), Mockito.eq(20L), Mockito.nullable(String.class), Mockito.anyLong(), Mockito.eq("UserVm")))
3258+
.thenReturn(sharedNicStatistics);
3259+
Mockito.when(userStatsDao.lock(Mockito.anyLong(), Mockito.anyLong(), Mockito.eq(20L), Mockito.nullable(String.class), Mockito.anyLong(), Mockito.eq("UserVm")))
3260+
.thenReturn(sharedNicStatistics);
3261+
3262+
try (MockedStatic<Transaction> transaction = Mockito.mockStatic(Transaction.class)) {
3263+
transaction.when(() -> Transaction.execute(Mockito.any(TransactionCallback.class)))
3264+
.thenAnswer(invocation -> ((TransactionCallback<?>) invocation.getArgument(0)).doInTransaction(null));
3265+
userVmManagerImpl.collectVmNetworkStatistics(userVmVoMock);
3266+
}
3267+
3268+
Mockito.verify(sharedNicStatistics).setCurrentBytesSent(300L);
3269+
Mockito.verify(userStatsDao).update(Mockito.anyLong(), Mockito.eq(sharedNicStatistics));
3270+
}
32043271
}

0 commit comments

Comments
 (0)