package org.ovirt.engine.core.bll.network.host;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.ovirt.engine.core.bll.ValidationResult;
import org.ovirt.engine.core.bll.validator.HostInterfaceValidator;
import org.ovirt.engine.core.common.action.CreateOrUpdateBond;
import org.ovirt.engine.core.common.action.HostSetupNetworksParameters;
import org.ovirt.engine.core.common.businessentities.BusinessEntity;
import org.ovirt.engine.core.common.businessentities.BusinessEntityMap;
import org.ovirt.engine.core.common.businessentities.Nameable;
import org.ovirt.engine.core.common.businessentities.network.Bond;
import org.ovirt.engine.core.common.businessentities.network.NicLabel;
import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.utils.NetworkCommonUtils;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.utils.NetworkUtils;
import org.ovirt.engine.core.utils.ReplacementUtils;
public class NicLabelValidator {
private HostSetupNetworksParameters params;
private BusinessEntityMap<VdsNetworkInterface> existingInterfacesMap;
private BusinessEntityMap<CreateOrUpdateBond> createOrUpdateBondBusinessEntityMap;
private HostSetupNetworksValidatorHelper hostSetupNetworksValidatorHelper;
public NicLabelValidator(HostSetupNetworksParameters params,
BusinessEntityMap<VdsNetworkInterface> existingInterfacesMap,
BusinessEntityMap<CreateOrUpdateBond> createOrUpdateBondBusinessEntityMap,
HostSetupNetworksValidatorHelper hostSetupNetworksValidatorHelper) {
this.params = params;
this.existingInterfacesMap = existingInterfacesMap;
this.createOrUpdateBondBusinessEntityMap = createOrUpdateBondBusinessEntityMap;
this.hostSetupNetworksValidatorHelper = hostSetupNetworksValidatorHelper;
}
public ValidationResult validate() {
ValidationResult vr = ValidationResult.VALID;
vr = skipValidation(vr) ? vr : validNewOrModifiedLabels();
vr = skipValidation(vr) ? vr : validRemovedLabels();
vr = skipValidation(vr) ? vr : labelAppearsOnlyOnceInParams();
return vr;
}
public ValidationResult validNewOrModifiedLabels() {
ValidationResult vr = ValidationResult.VALID;
Iterator<NicLabel> iterator = params.getLabels().iterator();
while (iterator.hasNext() && vr.isValid()) {
NicLabel nicLabel = iterator.next();
vr = skipValidation(vr) ? vr : validateCoherentNicIdentification(nicLabel);
vr = skipValidation(vr) ? vr : nicActuallyExistsOrReferencesNewBond(nicLabel);
vr = skipValidation(vr) ? vr : labelBeingAttachedToNonVlanNonSlaveInterface(nicLabel);
vr = skipValidation(vr) ? vr : labelBeingAttachedToValidBond(nicLabel);
}
return vr;
}
ValidationResult validateCoherentNicIdentification(NicLabel nicLabel) {
return validateCoherentIdentification(nicLabel.getLabel(),
nicLabel.getNicId(),
nicLabel.getNicName(),
EngineMessage.NIC_LABEL_REFERENCES_NICS_INCOHERENTLY, existingInterfacesMap);
}
<T extends BusinessEntity<Guid> & Nameable> ValidationResult validateCoherentIdentification(String violatingEntityId,
Guid referringId,
String referringName,
EngineMessage message,
BusinessEntityMap<T> map) {
return hostSetupNetworksValidatorHelper.validateCoherentIdentification(violatingEntityId,
referringId,
referringName,
message,
map);
}
ValidationResult nicActuallyExistsOrReferencesNewBond(NicLabel nicLabel) {
if (nicLabel.getNicName() != null) {
boolean nicActuallyExistsOrReferencesNewBond =
isNicActuallyExistsOrReferencesNewBond(nicLabel.getNicName(), nicLabel.getNicId());
boolean nicIsBeingRemoved =
nicLabel.getNicId() != null && params.getRemovedBonds().contains(nicLabel.getNicId());
if (nicActuallyExistsOrReferencesNewBond && !nicIsBeingRemoved) {
return ValidationResult.VALID;
}
}
return new ValidationResult(EngineMessage.INTERFACE_ON_NIC_LABEL_NOT_EXIST,
ReplacementUtils.createSetVariableString("INTERFACE_ON_NIC_LABEL_NOT_EXIST_ENTITY",
nicLabel.getLabel()),
ReplacementUtils.createSetVariableString("interfaceName",
nicLabel.getNicName() != null ? nicLabel.getNicName() : nicLabel.getNicId()));
}
boolean isNicActuallyExistsOrReferencesNewBond(String nicName, Guid nicId) {
return hostSetupNetworksValidatorHelper.isNicActuallyExistsOrReferencesNewBond(existingInterfacesMap,
createOrUpdateBondBusinessEntityMap,
nicName,
nicId);
}
public ValidationResult validRemovedLabels() {
ValidationResult vr = ValidationResult.VALID;
Iterator<String> iterator = params.getRemovedLabels().iterator();
while (iterator.hasNext() && vr.isValid()) {
String label = iterator.next();
vr = skipValidation(vr) ? vr : removedLabelExistsOnTheHost(label);
}
return vr;
}
ValidationResult removedLabelExistsOnTheHost(String label) {
Set<String> exisitingHostLabels = new HashSet<>();
for (VdsNetworkInterface nic : existingInterfacesMap.unmodifiableEntitiesByIdMap().values()) {
if (NetworkUtils.isLabeled(nic)) {
exisitingHostLabels.addAll(nic.getLabels());
}
}
return ValidationResult.failWith(EngineMessage.LABEL_NOT_EXIST_IN_HOST,
ReplacementUtils.createSetVariableString("LABEL_NOT_EXIST_IN_HOST_ENTITY", label))
.unless(exisitingHostLabels.contains(label));
}
public ValidationResult labelAppearsOnlyOnceInParams() {
Set<String> existingLabels = new HashSet<>();
Set<String> duplicateLabels = new HashSet<>();
for (NicLabel nicLabel : params.getLabels()) {
String label = nicLabel.getLabel();
addLabelToList(existingLabels, duplicateLabels, label);
}
for (String label : params.getRemovedLabels()) {
addLabelToList(existingLabels, duplicateLabels, label);
}
return ValidationResult.failWith(EngineMessage.PARAMS_CONTAIN_DUPLICATE_LABELS,
ReplacementUtils.replaceWith("PARAMS_CONTAIN_DUPLICATE_LABELS_LIST", new ArrayList<>(duplicateLabels)))
.unless(duplicateLabels.isEmpty());
}
private void addLabelToList(Set<String> existingLabels, Set<String> duplicateLabels, String label) {
if (existingLabels.contains(label)) {
duplicateLabels.add(label);
} else {
existingLabels.add(label);
}
}
ValidationResult labelBeingAttachedToNonVlanNonSlaveInterface(NicLabel nicLabel) {
String interfaceName = nicLabel.getNicName();
boolean isBondSlave = shouldBeConfigureAsBondSlave(interfaceName);
VdsNetworkInterface existingNic = existingInterfacesMap.get(interfaceName);
boolean isVlanDevice = existingNic == null ? false : NetworkCommonUtils.isVlan(existingNic);
return ValidationResult.failWith(EngineMessage.LABEL_ATTACH_TO_IMPROPER_INTERFACE,
ReplacementUtils.createSetVariableString(
"LABEL_ATTACH_TO_IMPROPER_INTERFACE_ENTITY",
interfaceName)).when(isBondSlave || isVlanDevice);
}
private boolean shouldBeConfigureAsBondSlave(String interfaceName) {
// Check if the interface was updated to be a bond's slave
for (CreateOrUpdateBond createOrUpdateBond : params.getCreateOrUpdateBonds()) {
if (createOrUpdateBond.getSlaves().contains(interfaceName)) {
return true;
}
}
// The interface wasn't updated to be a slave, check if currently it is a slave.
VdsNetworkInterface existingNic = existingInterfacesMap.get(interfaceName);
if (existingNic == null) {
return false;
}
if (existingNic.isPartOfBond()) {
String bondName = existingNic.getBondName();
VdsNetworkInterface bond = existingInterfacesMap.get(bondName);
boolean bondWasRemoved = params.getRemovedBonds().contains(bond.getId());
boolean slaveWasRemovedFromBond =
createOrUpdateBondBusinessEntityMap.containsKey(bondName)
&& !createOrUpdateBondBusinessEntityMap.get(bondName).getSlaves().contains(interfaceName);
return !bondWasRemoved && !slaveWasRemovedFromBond;
}
return false;
}
ValidationResult labelBeingAttachedToValidBond(NicLabel nicLabel) {
String interfaceName = nicLabel.getNicName();
VdsNetworkInterface nic = existingInterfacesMap.get(interfaceName);
if (nic instanceof Bond) {
CreateOrUpdateBond createOrUpdateBond = createOrUpdateBondBusinessEntityMap.containsKey(interfaceName)
? createOrUpdateBondBusinessEntityMap.get(interfaceName)
: CreateOrUpdateBond.fromBond((Bond) nic);
if (createOrUpdateBond.getSlaves().size() < 2) {
return new ValidationResult(EngineMessage.IMPROPER_BOND_IS_LABELED,
ReplacementUtils.createSetVariableString(
HostInterfaceValidator.VAR_BOND_NAME,
createOrUpdateBond.getName()));
}
}
return ValidationResult.VALID;
}
private boolean skipValidation(ValidationResult validationResult) {
return !validationResult.isValid();
}
}