package org.ovirt.engine.core.vdsbroker.vdsbroker;
import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.ovirt.engine.core.common.businessentities.Entities;
import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface;
import org.ovirt.engine.core.common.vdscommands.UserOverriddenNicValues;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.network.InterfaceDao;
public class HostNetworkInterfacesPersisterImpl implements HostNetworkInterfacesPersister {
private final InterfaceDao interfaceDao;
private final List<VdsNetworkInterface> reportedNics;
private final Map<String, VdsNetworkInterface> reportedNicsByNames;
private final List<VdsNetworkInterface> dbNics;
private List<VdsNetworkInterface> nicsForUpdate;
private final Map<String, UserOverriddenNicValues> userOverriddenNicValuesByNicName;
public HostNetworkInterfacesPersisterImpl(InterfaceDao interfaceDao,
List<VdsNetworkInterface> reportedNics,
List<VdsNetworkInterface> dbNics,
Map<String, UserOverriddenNicValues> userOverriddenNicValuesByNicName) {
this.interfaceDao = interfaceDao;
this.reportedNics = reportedNics;
this.reportedNicsByNames = Entities.entitiesByName(reportedNics);
this.dbNics = dbNics;
this.userOverriddenNicValuesByNicName = userOverriddenNicValuesByNicName;
}
@Override
public void persistTopology() {
removeUnreportedInterfaces();
updateModifiedInterfaces();
createNewInterfaces();
}
private void removeUnreportedInterfaces() {
for (VdsNetworkInterface dbNic : dbNics) {
if (nicShouldBeRemoved(dbNic.getName())) {
interfaceDao.removeInterfaceFromVds(dbNic.getId());
interfaceDao.removeStatisticsForVds(dbNic.getId());
}
}
}
private boolean nicShouldBeRemoved(String nicName) {
return !reportedNicsByNames.containsKey(nicName);
}
private void updateModifiedInterfaces() {
List<VdsNetworkInterface> nicsForUpdate = getNicsForUpdate();
List<Guid> updateNicsIds = nicsForUpdate.stream().map(VdsNetworkInterface::getId).collect(Collectors.toList());
if (!nicsForUpdate.isEmpty()) {
interfaceDao.massClearNetworkFromNics(updateNicsIds);
interfaceDao.massUpdateInterfacesForVds(nicsForUpdate);
}
}
private void createNewInterfaces() {
List<VdsNetworkInterface> nicsForCreate = prepareNicsForCreate();
for (VdsNetworkInterface nicForCreate : nicsForCreate) {
interfaceDao.saveInterfaceForVds(nicForCreate);
interfaceDao.saveStatisticsForVds(nicForCreate.getStatistics());
}
}
private List<VdsNetworkInterface> prepareNicsForCreate() {
List<VdsNetworkInterface> nicsForCreate = new ArrayList<>();
// nics for update contains (altered) subset of reportedNics, those related to existing dbNics, so if some
// reported nic is not present there, it must be reported nic to create.
List<VdsNetworkInterface> nicsForUpdate = getNicsForUpdate();
Set<String> nicsNamesForUpdate =
nicsForUpdate.stream().map(VdsNetworkInterface::getName).collect(Collectors.toSet());
for (VdsNetworkInterface reportedNic : reportedNics) {
String nicName = reportedNic.getName();
if (!nicsNamesForUpdate.contains(nicName)) {
reportedNic.overrideEngineManagedAttributes(userOverriddenNicValuesByNicName.get(nicName));
nicsForCreate.add(reportedNic);
}
}
return nicsForCreate;
}
/**
* @return subset of reportedNics, only nics with corresponding db record(dbNic) are returned. Each such reported
* nic is altered: id is overridden to one of corresponding db record
*/
private List<VdsNetworkInterface> prepareNicsForUpdate() {
return dbNics.stream()
.filter(dbNic -> reportedNicsByNames.containsKey(dbNic.getName()))
.map(this::mapDbNicToNicForUpdate)
.collect(toList());
}
/**
* @param dbNic dbNic used to find reportedNic.
* @return reportedNic of same name as dbNic has, with id taken from dbNic, and with user configuration taken
* from userOverriddenNicValuesByNicName if it exist or from db nic.
*/
private VdsNetworkInterface mapDbNicToNicForUpdate(VdsNetworkInterface dbNic) {
String nicName = dbNic.getName();
VdsNetworkInterface reportedNic = reportedNicsByNames.get(nicName);
boolean hasUserOverridingValues = userOverriddenNicValuesByNicName.containsKey(nicName);
reportedNic.setId(dbNic.getId());
if (hasUserOverridingValues) {
reportedNic.overrideEngineManagedAttributes(userOverriddenNicValuesByNicName.get(nicName));
} else {
reportedNic.overrideEngineManagedAttributes(dbNic);
}
return reportedNic;
}
private List<VdsNetworkInterface> getNicsForUpdate() {
if (nicsForUpdate == null) {
nicsForUpdate = prepareNicsForUpdate();
}
return nicsForUpdate;
}
}