package org.ovirt.engine.core.bll; import java.util.List; import java.util.Objects; import javax.inject.Inject; import javax.inject.Singleton; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.network.macpool.MacPool; import org.ovirt.engine.core.bll.network.macpool.MacPoolPerCluster; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.ClusterDao; import org.ovirt.engine.core.dao.network.VmNicDao; @Singleton public class MoveMacs { @Inject VmNicDao vmNicDao; @Inject private MacPoolPerCluster poolPerCluster; @Inject private ClusterDao clusterDao; /** * All MACs of given cluster are found, and all of them are {@link MacPool#freeMac(String) freed} * from source {@link MacPool macPool} and are * {@link MacPool#forceAddMac(String) added} * to target {@link MacPool macPool}. Because source macPool may contain duplicates and/or allow * duplicates, {@link MacPool#forceAddMac(String)} is used to add them override * <em>allowDuplicates</em> setting of target macPool. * @param sourceCluster {@link Cluster} cluster instance before update. * @param targetMacPoolId macPool Id of updated cluster. * @param commandContext {@link CommandContext} instance of calling command. * */ public void moveMacsOfUpdatedCluster(Cluster sourceCluster, Guid targetMacPoolId, CommandContext commandContext) { Objects.requireNonNull(sourceCluster); Objects.requireNonNull(targetMacPoolId); Guid sourceMacPoolId = sourceCluster.getMacPoolId(); Guid clusterId = sourceCluster.getId(); Objects.requireNonNull(sourceMacPoolId); Objects.requireNonNull(clusterId); if (needToMigrateMacs(sourceMacPoolId, targetMacPoolId)) { List<String> macsToMigrate = vmNicDao.getAllMacsByClusterId(clusterId); migrateMacsToAnotherMacPool(sourceMacPoolId, targetMacPoolId, macsToMigrate, false, commandContext); } } private boolean needToMigrateMacs(Guid oldMacPoolId, Guid newMacPoolId) { return !oldMacPoolId.equals(newMacPoolId); } public void migrateMacsToAnotherMacPool(Guid sourceMacPoolId, Guid targetMacPoolId, List<String> macsToMigrate, boolean checkForDuplicity, CommandContext commandContext) { Objects.requireNonNull(macsToMigrate); if (macsToMigrate.isEmpty()) { return; } MacPool sourcePool = poolPerCluster.getMacPoolById(sourceMacPoolId, commandContext); MacPool targetPool = poolPerCluster.getMacPoolById(targetMacPoolId, commandContext); sourcePool.freeMacs(macsToMigrate); if (checkForDuplicity) { List<String> notAddedMacs = targetPool.addMacs(macsToMigrate); boolean allMacsWereAdded = notAddedMacs.isEmpty(); if (!allMacsWereAdded) { /* exception is thrown, because this is the easiest way, how to nullify updated VM data * and return macs to original pool. */ throw new IllegalStateException(createMessageCannotChangeClusterDueToDuplicatesInTargetPool(notAddedMacs)); } } else { targetPool.forceAddMacs(macsToMigrate); } } String createMessageCannotChangeClusterDueToDuplicatesInTargetPool(List<String> notAddedMacs) { return "Cannot change cluster, some mac is already used in target cluster Mac Pool: " + notAddedMacs.toString(); } public void updateClusterAndMoveMacs(Cluster cluster, Guid newMacPoolId, CommandContext commandContext) { Guid oldMacPoolId = cluster.getMacPoolId(); moveMacsOfUpdatedCluster(cluster, newMacPoolId, commandContext); if (needToMigrateMacs(oldMacPoolId, newMacPoolId)) { cluster.setMacPoolId(newMacPoolId); clusterDao.update(cluster); } } }