package org.ovirt.engine.core.bll.validator;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.ovirt.engine.core.bll.validator.ValidationResultMatchers.failsWith;
import static org.ovirt.engine.core.bll.validator.ValidationResultMatchers.isValid;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.ovirt.engine.core.bll.ValidationResult;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VmTemplate;
import org.ovirt.engine.core.common.businessentities.network.Network;
import org.ovirt.engine.core.common.businessentities.network.NetworkFilter;
import org.ovirt.engine.core.common.businessentities.network.NetworkQoS;
import org.ovirt.engine.core.common.businessentities.network.VnicProfile;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dao.StoragePoolDao;
import org.ovirt.engine.core.dao.VmDao;
import org.ovirt.engine.core.dao.VmTemplateDao;
import org.ovirt.engine.core.dao.network.NetworkDao;
import org.ovirt.engine.core.dao.network.NetworkFilterDao;
import org.ovirt.engine.core.dao.network.NetworkQoSDao;
import org.ovirt.engine.core.dao.network.VnicProfileDao;
import org.ovirt.engine.core.utils.ReplacementUtils;
@RunWith(MockitoJUnitRunner.class)
public class VnicProfileValidatorTest {
private static final String NAMEABLE_NAME = "nameable";
private static final String DEFAULT_VNIC_PROFILE_NAME = "myvnicprofile";
private static final String OTHER_VNIC_PROFILE_NAME = "myothervnicprofile";
private static final Guid DEFAULT_GUID = Guid.newGuid();
private static final Guid OTHER_GUID = Guid.newGuid();
private static final Guid VALID_NETWORK_FILTER_ID = Guid.newGuid();
private static final Guid INVALID_NETWORK_FILTER_ID = Guid.newGuid();
@Mock
private DbFacade dbFacade;
@Mock
private VnicProfileDao vnicProfileDao;
@Mock
private NetworkDao networkDao;
@Mock
private NetworkQoSDao networkQosDao;
@Mock
private VmDao vmDao;
@Mock
private StoragePoolDao dcDao;
@Mock
private NetworkFilterDao networkFilterDao;
@Mock
private VnicProfile vnicProfile;
@Mock
private Network network;
@Mock
private NetworkQoS networkQos;
private List<VnicProfile> vnicProfiles = new ArrayList<>();
private VnicProfileValidator validator;
@Before
public void setup() {
// spy on attempts to access the database
validator = spy(new VnicProfileValidator(vnicProfile, vmDao, dcDao, networkFilterDao));
doReturn(dbFacade).when(validator).getDbFacade();
// mock some commonly used Daos
when(dbFacade.getVnicProfileDao()).thenReturn(vnicProfileDao);
when(dbFacade.getNetworkDao()).thenReturn(networkDao);
when(dbFacade.getNetworkQosDao()).thenReturn(networkQosDao);
when(dbFacade.getVmDao()).thenReturn(vmDao);
initNetworkFilterDao();
// mock their getters
when(vnicProfileDao.get(any())).thenReturn(vnicProfile);
when(vnicProfileDao.getAllForNetwork(any())).thenReturn(vnicProfiles);
}
private void initNetworkFilterDao() {
when(networkFilterDao.getNetworkFilterById(INVALID_NETWORK_FILTER_ID)).thenReturn(null);
when(networkFilterDao.getNetworkFilterById(VALID_NETWORK_FILTER_ID))
.thenReturn(new NetworkFilter(VALID_NETWORK_FILTER_ID));
}
@Test
public void vnicProfileSet() throws Exception {
assertThat(validator.vnicProfileIsSet(), isValid());
}
@Test
public void vnicProfileNull() throws Exception {
validator = new VnicProfileValidator(null, vmDao, dcDao, networkFilterDao);
assertThat(validator.vnicProfileIsSet(), failsWith(EngineMessage.ACTION_TYPE_FAILED_VNIC_PROFILE_NOT_EXISTS));
}
@Test
public void vnicProfileExists() throws Exception {
assertThat(validator.vnicProfileExists(), isValid());
}
@Test
public void vnicProfileDoesNotExist() throws Exception {
when(vnicProfileDao.get(any())).thenReturn(null);
assertThat(validator.vnicProfileExists(), failsWith(EngineMessage.ACTION_TYPE_FAILED_VNIC_PROFILE_NOT_EXISTS));
}
@Test
public void networkExists() throws Exception {
when(networkDao.get(any())).thenReturn(network);
assertThat(validator.networkExists(), isValid());
}
@Test
public void networkDoesntExist() throws Exception {
when(networkDao.get(any())).thenReturn(null);
assertThat(validator.networkExists(), failsWith(EngineMessage.NETWORK_HAVING_ID_NOT_EXISTS));
}
@Test
public void networkQosExists() throws Exception {
when(vnicProfile.getNetworkQosId()).thenReturn(DEFAULT_GUID);
when(networkQosDao.get(DEFAULT_GUID)).thenReturn(networkQos);
assertThat(validator.networkQosExistsOrNull(), isValid());
}
@Test
public void networkQosNull() throws Exception {
when(vnicProfile.getNetworkQosId()).thenReturn(null);
assertThat(validator.networkQosExistsOrNull(), isValid());
}
@Test
public void networkQosDoesntExist() throws Exception {
when(vnicProfile.getNetworkQosId()).thenReturn(DEFAULT_GUID);
when(networkQosDao.get(any())).thenReturn(null);
assertThat(validator.networkQosExistsOrNull(), failsWith(EngineMessage.ACTION_TYPE_FAILED_NETWORK_QOS_NOT_EXISTS));
}
private void vnicProfileAvailableTest(Matcher<ValidationResult> matcher, List<VnicProfile> vnicProfiles) {
this.vnicProfiles.addAll(vnicProfiles);
when(vnicProfile.getName()).thenReturn(DEFAULT_VNIC_PROFILE_NAME);
when(vnicProfile.getId()).thenReturn(DEFAULT_GUID);
assertThat(validator.vnicProfileNameNotUsed(), matcher);
}
private static List<VnicProfile> getSingletonNamedVnicProfileList(String vnicProfileName, Guid vnicProfileId) {
VnicProfile vnicProfile = mock(VnicProfile.class);
when(vnicProfile.getName()).thenReturn(vnicProfileName);
when(vnicProfile.getId()).thenReturn(vnicProfileId);
return Collections.singletonList(vnicProfile);
}
@Test
public void vnicProfileNameNoVnicProfiles() throws Exception {
vnicProfileAvailableTest(isValid(), Collections.emptyList());
}
@Test
public void vnicProfileNameAvailable() throws Exception {
vnicProfileAvailableTest(isValid(), getSingletonNamedVnicProfileList(OTHER_VNIC_PROFILE_NAME, OTHER_GUID));
}
@Test
public void vnicProfileNameTakenByDifferentVnicProfile() throws Exception {
vnicProfileAvailableTest(failsWith(EngineMessage.ACTION_TYPE_FAILED_VNIC_PROFILE_NAME_IN_USE),
getSingletonNamedVnicProfileList(DEFAULT_VNIC_PROFILE_NAME, OTHER_GUID));
}
@Test
public void vnicProfileNameTakenCaseSensitivelyByDifferentVnicProfile() throws Exception {
vnicProfileAvailableTest(isValid(),
getSingletonNamedVnicProfileList(DEFAULT_VNIC_PROFILE_NAME.toUpperCase(), OTHER_GUID));
}
@Test
public void vnicProfileNameTakenBySameVnicProfile() throws Exception {
vnicProfileAvailableTest(isValid(),
getSingletonNamedVnicProfileList(DEFAULT_VNIC_PROFILE_NAME, DEFAULT_GUID));
}
private static Matcher<ValidationResult> failsWithVnicProfileInUse() {
return failsWith(EngineMessage.ACTION_TYPE_FAILED_VNIC_PROFILE_IN_ONE_USE);
}
@Test
public void networkChanged() throws Exception {
mockVnicProfileNetworkChange(DEFAULT_GUID, DEFAULT_GUID);
assertThat(validator.networkNotChanged(), isValid());
}
@Test
public void changingNetworkNotAllowed() throws Exception {
mockVnicProfileNetworkChange(DEFAULT_GUID, OTHER_GUID);
assertThat(validator.networkNotChanged(),
failsWith(EngineMessage.ACTION_TYPE_FAILED_CANNOT_CHANGE_VNIC_PROFILE_NETWORK));
}
@Test
public void portMirroringNotChanged() {
assertThat(validator.portMirroringNotChangedIfUsedByVms(), isValid());
}
@Test
public void portMirroringEnableSupported() {
mockVnicProfilePortMirroringChange(false);
mockVmsUsingVnicProfile(Collections.emptyList());
assertThat(validator.portMirroringNotChangedIfUsedByVms(), isValid());
}
@Test
public void portMirroringChangeNotSupported() {
mockVnicProfilePortMirroringChange(false);
mockVmsUsingVnicProfile(Collections.singletonList(mock(VM.class)));
assertThat(validator.portMirroringNotChangedIfUsedByVms(), failsWithVnicProfileInUse());
}
private void mockVnicProfileNetworkChange(Guid vnicProfileId, Guid oldVnicProfileId) {
VnicProfile vnicProfile = mock(VnicProfile.class);
when(this.vnicProfile.getNetworkId()).thenReturn(vnicProfileId);
when(vnicProfile.getNetworkId()).thenReturn(oldVnicProfileId);
when(vnicProfileDao.get(any())).thenReturn(vnicProfile);
}
private void vnicProfileNotUsedByVmsTest(Matcher<ValidationResult> matcher, List<VM> vms) {
mockVmsUsingVnicProfile(vms);
assertThat(validator.vnicProfileNotUsedByVms(), matcher);
}
private void mockVmsUsingVnicProfile(List<VM> vms) {
when(vmDao.getAllForVnicProfile(any())).thenReturn(vms);
}
private void mockVnicProfilePortMirroringChange(boolean portMirroring) {
VnicProfile vnicProfile = mock(VnicProfile.class);
when(this.vnicProfile.isPortMirroring()).thenReturn(portMirroring);
when(vnicProfile.isPortMirroring()).thenReturn(!portMirroring);
when(vnicProfileDao.get(any())).thenReturn(vnicProfile);
}
@Test
public void vnicProfileNotInUseByVms() throws Exception {
vnicProfileNotUsedByVmsTest(isValid(), Collections.emptyList());
}
@Test
public void vnicProfileInUseByVms() throws Exception {
VM vm = mock(VM.class);
when(vm.getName()).thenReturn(NAMEABLE_NAME);
vnicProfileNotUsedByVmsTest(failsWithVnicProfileInUse(), Collections.singletonList(vm));
}
private void vnicProfileNotUsedByTemplatesTest(Matcher<ValidationResult> matcher, List<VmTemplate> templates) {
VmTemplateDao templateDao = mock(VmTemplateDao.class);
when(templateDao.getAllForVnicProfile(any())).thenReturn(templates);
when(dbFacade.getVmTemplateDao()).thenReturn(templateDao);
assertThat(validator.vnicProfileNotUsedByTemplates(), matcher);
}
@Test
public void vnicProfileNotInUseByTemplates() throws Exception {
vnicProfileNotUsedByTemplatesTest(isValid(), Collections.emptyList());
}
@Test
public void vnicProfileInUseByTemplates() throws Exception {
VmTemplate template = mock(VmTemplate.class);
when(template.getName()).thenReturn(NAMEABLE_NAME);
vnicProfileNotUsedByTemplatesTest(failsWithVnicProfileInUse(), Collections.singletonList(template));
}
@Test
public void vnicProfileForVmNetwork() {
vnicProfileForVmNetworkTest(true, isValid());
}
@Test
public void vnicProfileForNonVmNetwork() {
vnicProfileForVmNetworkTest(false,
failsWith(EngineMessage.ACTION_TYPE_FAILED_CANNOT_ADD_VNIC_PROFILE_TO_NON_VM_NETWORK));
}
private void vnicProfileForVmNetworkTest(boolean vmNetwork, Matcher<ValidationResult> matcher) {
when(network.isVmNetwork()).thenReturn(vmNetwork);
when(networkDao.get(any())).thenReturn(network);
assertThat(validator.vnicProfileForVmNetworkOnly(), matcher);
}
@Test
public void externalNetworkPortMirroring() throws Exception {
externalNetworkPortMirroringTest(true,
true,
failsWith(EngineMessage.ACTION_TYPE_FAILED_EXTERNAL_NETWORK_CANNOT_BE_PORT_MIRRORED));
}
@Test
public void externalNetworkNotPortMirroring() throws Exception {
externalNetworkPortMirroringTest(true, false, isValid());
}
@Test
public void internalNetworkPortMirroring() throws Exception {
externalNetworkPortMirroringTest(false, true, isValid());
}
@Test
public void internalNetworkNotPortMirroring() throws Exception {
externalNetworkPortMirroringTest(false, false, isValid());
}
private void externalNetworkPortMirroringTest(boolean externalNetwork,
boolean portMirroring,
Matcher<ValidationResult> matcher) {
when(networkDao.get(any())).thenReturn(network);
when(network.isExternal()).thenReturn(externalNetwork);
when(vnicProfile.isPortMirroring()).thenReturn(portMirroring);
assertThat(validator.portMirroringNotSetIfExternalNetwork(), matcher);
}
@Test
public void passthroughChangedUsedByVms() {
passthroughNotChangedIfUsedByVmsTest(true, false, true);
assertThat(validator.passthroughNotChangedIfUsedByVms(), failsWithVnicProfileInUse());
}
@Test
public void passthroughChangedNotUsedByVms() {
passthroughNotChangedIfUsedByVmsTest(false, true, false);
assertThat(validator.passthroughNotChangedIfUsedByVms(), isValid());
}
@Test
public void passthroughNotChangedUsedByVms() {
passthroughNotChangedIfUsedByVmsTest(true, true, true);
assertThat(validator.passthroughNotChangedIfUsedByVms(), isValid());
}
@Test
public void passthroughNotChangedNotUsedByVms() {
passthroughNotChangedIfUsedByVmsTest(false, false, true);
assertThat(validator.passthroughNotChangedIfUsedByVms(), isValid());
}
private void passthroughNotChangedIfUsedByVmsTest(boolean passthoughOld,
boolean pasthroughNew,
boolean profileUsedByVms) {
VnicProfile updatedVnicProfile = mock(VnicProfile.class);
when(vnicProfile.isPassthrough()).thenReturn(passthoughOld);
when(updatedVnicProfile.isPassthrough()).thenReturn(pasthroughNew);
when(vnicProfileDao.get(any())).thenReturn(updatedVnicProfile);
mockVmsUsingVnicProfile(profileUsedByVms ? Collections.singletonList(mock(VM.class))
: Collections.emptyList());
}
@Test
public void passthroughProfileContainsPortMirroring() {
passthroughProfileContainsSupportedPropertiesTest(true, true, null, null);
assertThat(validator.passthroughProfileContainsSupportedProperties(),
failsWith(EngineMessage.ACTION_TYPE_FAILED_PASSTHROUGH_PROFILE_CONTAINS_NOT_SUPPORTED_PROPERTIES));
}
@Test
public void passthroughProfileContainsQos() {
passthroughProfileContainsSupportedPropertiesTest(true, false, DEFAULT_GUID, null);
assertThat(validator.passthroughProfileContainsSupportedProperties(),
failsWith(EngineMessage.ACTION_TYPE_FAILED_PASSTHROUGH_PROFILE_CONTAINS_NOT_SUPPORTED_PROPERTIES));
}
@Test
public void passthroughProfileContainsFilterId() {
passthroughProfileContainsSupportedPropertiesTest(true, false, DEFAULT_GUID, INVALID_NETWORK_FILTER_ID);
assertThat(validator.passthroughProfileContainsSupportedProperties(),
failsWith(EngineMessage.ACTION_TYPE_FAILED_PASSTHROUGH_PROFILE_CONTAINS_NOT_SUPPORTED_PROPERTIES));
}
@Test
public void passthroughProfileValidProperties() {
passthroughProfileContainsSupportedPropertiesTest(true, false, null, null);
assertThat(validator.passthroughProfileContainsSupportedProperties(), isValid());
}
@Test
public void nonPassthroughProfileContainsPortMirroringAndQos() {
passthroughProfileContainsSupportedPropertiesTest(false, true, DEFAULT_GUID, VALID_NETWORK_FILTER_ID);
assertThat(validator.passthroughProfileContainsSupportedProperties(), isValid());
}
@Test
public void testValidNetworkFilterIdUseDefaultNoFilterId(){
assertThat(validator.validUseDefaultNetworkFilterFlag(true), isValid());
}
@Test
public void testValidNetworkFilterIdUseDefaultWithFilterId() {
initVnicProfileNetworkFilterId(VALID_NETWORK_FILTER_ID, DEFAULT_VNIC_PROFILE_NAME);
assertThat(validator.validUseDefaultNetworkFilterFlag(true),
failsWith(EngineMessage.ACTION_TYPE_FAILED_INVALID_VNIC_PROFILE_NETWORK_ID_CONFIGURATION,
ReplacementUtils.createSetVariableString(VnicProfileValidator.VAR_VNIC_PROFILE_NAME,
DEFAULT_VNIC_PROFILE_NAME),
ReplacementUtils.createSetVariableString(VnicProfileValidator.VAR_NETWORK_FILTER_ID,
VALID_NETWORK_FILTER_ID)));
}
@Test
public void testValidNetworkFilterIdNoDefaultNoFilterId(){
assertThat(validator.validUseDefaultNetworkFilterFlag(false), isValid());
}
@Test
public void testValidNetworkFilterIdNoDefaultWithFilterId(){
when(vnicProfile.getNetworkFilterId()).thenReturn(Guid.newGuid());
assertThat(validator.validUseDefaultNetworkFilterFlag(false), isValid());
}
@Test
public void validVnicProfileNullNetworkFilterId() {
when(vnicProfile.getNetworkFilterId()).thenReturn(null);
assertThat(validator.validNetworkFilterId(), isValid());
}
@Test
public void validVnicProfileNetworkFilterId() {
when(vnicProfile.getNetworkFilterId()).thenReturn(VALID_NETWORK_FILTER_ID);
assertThat(validator.validNetworkFilterId(), isValid());
}
@Test
public void invalidVnicProfileNetworkFilterId() {
initVnicProfileNetworkFilterId(INVALID_NETWORK_FILTER_ID, DEFAULT_VNIC_PROFILE_NAME);
assertThat(validator.validNetworkFilterId(),
failsWith(EngineMessage.ACTION_TYPE_FAILED_INVALID_VNIC_PROFILE_NETWORK_FILTER_ID,
ReplacementUtils.createSetVariableString(VnicProfileValidator.VAR_VNIC_PROFILE_NAME,
DEFAULT_VNIC_PROFILE_NAME),
ReplacementUtils.createSetVariableString(VnicProfileValidator.VAR_NETWORK_FILTER_ID,
INVALID_NETWORK_FILTER_ID)));
}
private void initVnicProfileNetworkFilterId(Guid networkFilterId, String name) {
when(vnicProfile.getNetworkFilterId()).thenReturn(networkFilterId);
when(vnicProfile.getName()).thenReturn(name);
}
private void passthroughProfileContainsSupportedPropertiesTest(boolean passthrough,
boolean portMirroring,
Guid qosId,
Guid networkFilterId) {
when(vnicProfile.isPassthrough()).thenReturn(passthrough);
when(vnicProfile.isPortMirroring()).thenReturn(portMirroring);
when(vnicProfile.getNetworkQosId()).thenReturn(qosId);
when(vnicProfile.getNetworkFilterId()).thenReturn(networkFilterId);
}
}