package org.ovirt.engine.core.bll.network.cluster; import java.util.Collection; import java.util.Collections; import java.util.Objects; import javax.inject.Inject; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.network.Network; import org.ovirt.engine.core.common.businessentities.network.NetworkCluster; import org.ovirt.engine.core.common.businessentities.network.NetworkClusterId; import org.ovirt.engine.core.common.businessentities.network.NetworkStatus; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.VdsDynamicDao; import org.ovirt.engine.core.dao.VdsStaticDao; import org.ovirt.engine.core.dao.network.NetworkAttachmentDao; import org.ovirt.engine.core.dao.network.NetworkClusterDao; /** * Class to hold common methods that are used in several different places. */ public class NetworkClusterHelper { private final NetworkClusterDao networkClusterDao; private final NetworkAttachmentDao networkAttachmentDao; private final VdsStaticDao vdsStaticDao; private final VdsDynamicDao vdsDynamicDao; private final ManagementNetworkUtil managementNetworkUtil; @Inject public NetworkClusterHelper(NetworkClusterDao networkClusterDao, NetworkAttachmentDao networkAttachmentDao, VdsStaticDao vdsStaticDao, VdsDynamicDao vdsDynamicDao, ManagementNetworkUtil managementNetworkUtil) { this.networkClusterDao = Objects.requireNonNull(networkClusterDao); this.networkAttachmentDao = Objects.requireNonNull(networkAttachmentDao); this.vdsStaticDao = Objects.requireNonNull(vdsStaticDao); this.vdsDynamicDao = Objects.requireNonNull(vdsDynamicDao); this.managementNetworkUtil = Objects.requireNonNull(managementNetworkUtil); } private NetworkCluster getManagementNetworkCluster(NetworkCluster networkCluster) { Guid clusterId = networkCluster.getClusterId(); Network mgmt = managementNetworkUtil.getManagementNetwork(clusterId); return networkClusterDao.get(new NetworkClusterId(clusterId, mgmt.getId())); } public void removeNetworkAndReassignRoles(NetworkCluster networkCluster) { NetworkCluster oldNetworkCluster = networkClusterDao.get(networkCluster.getId()); networkClusterDao.remove(networkCluster.getClusterId(), networkCluster.getNetworkId()); networkAttachmentDao.removeByNetworkId(networkCluster.getNetworkId()); boolean updateManagementNetwork = false; final NetworkCluster managementNetworkCluster = getManagementNetworkCluster(networkCluster); if (oldNetworkCluster.isDisplay()) { managementNetworkCluster.setDisplay(true); updateManagementNetwork = true; } if (oldNetworkCluster.isMigration()) { managementNetworkCluster.setMigration(true); updateManagementNetwork = true; } if (updateManagementNetwork) { networkClusterDao.update(managementNetworkCluster); } } /** * Updates status of network. Update is performed only if there's at least one host in cluster, which [host] * has status {@link VDSStatus#Up}. If network is nonrequired, it set to {@link NetworkStatus#OPERATIONAL}. * Otherwise all hosts having status {@link VDSStatus#Up} in given cluster are scanned, whether all of them has * network of <em>networkName</em> attached to some nic. If so, <em>networkCluster</em> is marked as * {@link NetworkStatus#OPERATIONAL}, if not it's marked as {@link NetworkStatus#NON_OPERATIONAL}. * * @param clusterId clusterId of cluster to which <em>network</em> belongs. * @param network network to update. */ public void setStatus(Guid clusterId, final Network network) { setStatus(clusterId, Collections.singletonList(network)); } public void setStatus(Guid clusterId, final Collection<Network> networks) { final RequiredNetworkClusterStatusUpdater requiredNetworkClusterStatusUpdater = new RequiredNetworkClusterStatusUpdater(clusterId); for (Network network : networks) { NetworkCluster networkCluster = networkClusterDao.get(new NetworkClusterId(clusterId, network.getId())); boolean doUpdateNetworkClusterStatus = networkCluster != null; if (doUpdateNetworkClusterStatus) { if (networkCluster.isRequired()) { requiredNetworkClusterStatusUpdater.update(networkCluster, network.getName()); } else { updateNetworkClusterStatus(networkCluster, NetworkStatus.OPERATIONAL); } } } } /** * Updates <em>networkCluster</em> with new <em>networkStatus</em> and persists passed <em>networkCluster</em> if * <em>newStatus</em> is different from current one saving DB roundtrip if no update is needed. * * @param networkCluster NetworkCluster record to update * @param newStatus network status to be set */ private void updateNetworkClusterStatus(NetworkCluster networkCluster, NetworkStatus newStatus) { if (networkCluster.getStatus() != newStatus) { networkCluster.setStatus(newStatus); networkClusterDao.updateStatus(networkCluster); } } private class RequiredNetworkClusterStatusUpdater { private final Guid clusterId; private Boolean atLeastOneHostIsUp; private RequiredNetworkClusterStatusUpdater(Guid clusterId) { this.clusterId = clusterId; } /** * Updates status of the required network in the cluster. See {@link #setStatus(Guid, Network)} for details. */ public void update(NetworkCluster networkCluster, String networkName) { if (isAtLeastOneHostIsUp()) { final NetworkStatus networkStatusToSet = vdsStaticDao.checkIfExistsHostThatMissesNetworkInCluster( clusterId, networkName, VDSStatus.Up) ? NetworkStatus.NON_OPERATIONAL : NetworkStatus.OPERATIONAL; updateNetworkClusterStatus(networkCluster, networkStatusToSet); } } private boolean isAtLeastOneHostIsUp() { if (atLeastOneHostIsUp == null) { atLeastOneHostIsUp = vdsDynamicDao.checkIfExistsHostWithStatusInCluster(clusterId, VDSStatus.Up); } return atLeastOneHostIsUp; } } }