package org.ovirt.engine.core.bll.network;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasEntry;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.transaction.TransactionManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.verification.VerificationMode;
import org.ovirt.engine.core.bll.context.NoOpCompensationContext;
import org.ovirt.engine.core.bll.network.macpool.MacPool;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.businessentities.network.VmNic;
import org.ovirt.engine.core.common.osinfo.OsRepository;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.Version;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
import org.ovirt.engine.core.dao.network.VmNetworkStatisticsDao;
import org.ovirt.engine.core.dao.network.VmNicDao;
import org.ovirt.engine.core.di.InjectorRule;
import org.ovirt.engine.core.utils.RandomUtils;
@RunWith(MockitoJUnitRunner.class)
public class VmInterfaceManagerTest {
private static final int OS_ID = 0;
private static final String VM_NAME = "vm name";
@Rule
public InjectorRule injectorRule = new InjectorRule();
@Mock
private MacPool macPool;
@Mock
private VmNetworkStatisticsDao vmNetworkStatisticsDao;
@Mock
private VmNicDao vmNicDao;
@Mock
private AuditLogDirector auditLogDirector;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private TransactionManager transactionManager;
@Captor
private ArgumentCaptor<AuditLogableBase> auditLogableBaseCaptor;
private VmInterfaceManager vmInterfaceManager;
@Mock
private Version version;
@Before
@SuppressWarnings("unchecked")
public void setupMocks() {
vmInterfaceManager = spy(new VmInterfaceManager(macPool));
doReturn(vmNetworkStatisticsDao).when(vmInterfaceManager).getVmNetworkStatisticsDao();
doReturn(vmNicDao).when(vmInterfaceManager).getVmNicDao();
doReturn(auditLogDirector).when(vmInterfaceManager).getAuditLogDirector();
doNothing().when(vmInterfaceManager).removeFromExternalNetworks(anyList());
injectorRule.bind(TransactionManager.class, transactionManager);
}
@Test
public void add() {
runAddAndVerify(createNewInterface(), false, times(0), OS_ID);
}
@Test
public void addWithExistingMacAddressSucceed() {
VmNic iface = createNewInterface();
runAddAndVerify(iface, true, times(1), OS_ID);
}
protected void runAddAndVerify(VmNic iface,
boolean reserveExistingMac,
VerificationMode addMacVerification,
int osId) {
OsRepository osRepository = mock(OsRepository.class);
when(vmInterfaceManager.getOsRepository()).thenReturn(osRepository);
when(osRepository.hasNicHotplugSupport(anyInt(), any(Version.class))).thenReturn(true);
vmInterfaceManager.add(iface, NoOpCompensationContext.getInstance(), reserveExistingMac, false, osId, version);
if (reserveExistingMac) {
verify(macPool, times(1)).forceAddMac(iface.getMacAddress());
} else {
verifyZeroInteractions(macPool);
}
verifyAddDelegatedCorrectly(iface, addMacVerification);
}
@Test
public void removeAll() {
List<VmNic> interfaces = Arrays.asList(createNewInterface(), createNewInterface());
when(vmNicDao.getAllForVm(any(Guid.class))).thenReturn(interfaces);
vmInterfaceManager.removeAll(Guid.newGuid());
for (VmNic iface : interfaces) {
verifyRemoveAllDelegatedCorrectly(iface);
}
}
@Test
public void testAuditLogMacInUse() {
final VmNic iface = createNewInterface();
vmInterfaceManager.auditLogMacInUse(iface);
verifyCommonAuditLogFilledProperly(AuditLogType.MAC_ADDRESS_IS_IN_USE, iface);
}
@Test
public void testAuditLogMacInUseUnplug() {
final VmNic iface = createNewInterface();
vmInterfaceManager.auditLogMacInUseUnplug(iface, VM_NAME);
final Map<String, String> capturedCustomValues =
verifyCommonAuditLogFilledProperly(AuditLogType.MAC_ADDRESS_IS_IN_USE_UNPLUG, iface);
assertThat(capturedCustomValues, hasEntry("vmname", VM_NAME));
}
private Map<String, String> verifyCommonAuditLogFilledProperly(AuditLogType auditLogType, VmNic iface) {
verify(auditLogDirector).log(auditLogableBaseCaptor.capture(), same(auditLogType));
final Map<String, String> capturedCustomValues = auditLogableBaseCaptor.getValue().getCustomValues();
assertThat(capturedCustomValues, allOf(
hasEntry("macaddr", iface.getMacAddress()),
hasEntry("ifacename", iface.getName())));
return capturedCustomValues;
}
/**
* Verify that {@link VmInterfaceManager#add} delegated correctly to {@link MacPool} & Daos.
*
* @param iface
* The interface to check for.
* @param addMacVerification
* Mode to check (times(1), never(), etc) for {@link MacPool#addMac(String)}.
*/
protected void verifyAddDelegatedCorrectly(VmNic iface, VerificationMode addMacVerification) {
verify(macPool, addMacVerification).forceAddMac(iface.getMacAddress());
verify(vmNicDao).save(iface);
verify(vmNetworkStatisticsDao).save(iface.getStatistics());
}
/**
* Verify that {@link VmInterfaceManager#removeAll} delegated correctly to {@link MacPool} & Daos.
*
* @param iface
* The interface to check for.
*/
protected void verifyRemoveAllDelegatedCorrectly(VmNic iface) {
verify(macPool, times(1)).freeMac(iface.getMacAddress());
verify(vmNicDao).remove(iface.getId());
verify(vmNetworkStatisticsDao).remove(iface.getId());
}
/**
* @return A new interface that can be used in tests.
*/
private static VmNic createNewInterface() {
VmNic iface = new VmNic();
iface.setId(Guid.newGuid());
iface.setMacAddress(RandomUtils.instance().nextString(10));
return iface;
}
}