Yevgeny Zaspitsky has uploaded a new change for review.

Change subject: engine: refactor CollectVdsNetworkDataVDSCommand
......................................................................

engine: refactor CollectVdsNetworkDataVDSCommand

Refactor CollectVdsNetworkDataVDSCommand: extract the network topology
persistence logic into its own class with non-static methods.

Change-Id: I798abe6597c06df873ac94f61981ff1dccc07bc8
Signed-off-by: Yevgeny Zaspitsky <yzasp...@redhat.com>
---
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/CollectVdsNetworkDataVDSCommand.java
A 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersister.java
A 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersisterImpl.java
4 files changed, 344 insertions(+), 291 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/05/33905/1

diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
index 750a029..fa7df46 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
@@ -58,8 +58,9 @@
 import org.ovirt.engine.core.vdsbroker.irsbroker.IrsBrokerCommand;
 import org.ovirt.engine.core.vdsbroker.jsonrpc.JsonRpcVdsServer;
 import org.ovirt.engine.core.vdsbroker.jsonrpc.TransportFactory;
-import 
org.ovirt.engine.core.vdsbroker.vdsbroker.CollectVdsNetworkDataVDSCommand;
 import org.ovirt.engine.core.vdsbroker.vdsbroker.GetCapabilitiesVDSCommand;
+import org.ovirt.engine.core.vdsbroker.vdsbroker.HostNetworkTopologyPersister;
+import 
org.ovirt.engine.core.vdsbroker.vdsbroker.HostNetworkTopologyPersisterImpl;
 import org.ovirt.engine.core.vdsbroker.vdsbroker.IVdsServer;
 import org.ovirt.engine.core.vdsbroker.vdsbroker.VDSNetworkException;
 import org.ovirt.engine.core.vdsbroker.vdsbroker.VDSRecoveringException;
@@ -67,6 +68,9 @@
 import org.ovirt.engine.core.vdsbroker.xmlrpc.XmlRpcUtils;
 
 public class VdsManager {
+
+    private final HostNetworkTopologyPersister hostNetworkTopologyPersister;
+
     private VDS _vds;
     private long lastUpdate;
     private long updateStartTime;
@@ -152,6 +156,7 @@
         mUnrespondedAttempts = new AtomicInteger();
         mFailedToRunVmAttempts = new AtomicInteger();
         sshSoftFencingExecuted = new AtomicBoolean(false);
+        hostNetworkTopologyPersister = 
HostNetworkTopologyPersisterImpl.getInstance();
         monitoringLock = new 
EngineLock(Collections.singletonMap(_vdsId.toString(),
                 new Pair<String, String>(LockingGroup.VDS_INIT.name(), "")), 
null);
 
@@ -595,7 +600,7 @@
 
             VDSStatus returnStatus = vds.getStatus();
             NonOperationalReason nonOperationalReason =
-                    
CollectVdsNetworkDataVDSCommand.persistAndEnforceNetworkCompliance(vds);
+                    
hostNetworkTopologyPersister.persistAndEnforceNetworkCompliance(vds);
 
             if (nonOperationalReason != NonOperationalReason.NONE) {
                 setIsSetNonOperationalExecuted(true);
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/CollectVdsNetworkDataVDSCommand.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/CollectVdsNetworkDataVDSCommand.java
index 6f125bb..c45c19c 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/CollectVdsNetworkDataVDSCommand.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/CollectVdsNetworkDataVDSCommand.java
@@ -1,41 +1,18 @@
 package org.ovirt.engine.core.vdsbroker.vdsbroker;
 
-import static 
org.ovirt.engine.core.common.businessentities.network.NetworkStatus.OPERATIONAL;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang.StringUtils;
-import org.ovirt.engine.core.common.AuditLogType;
 import org.ovirt.engine.core.common.businessentities.Entities;
-import org.ovirt.engine.core.common.businessentities.NonOperationalReason;
-import org.ovirt.engine.core.common.businessentities.VDS;
-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.VdsNetworkInterface;
-import 
org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface.NetworkImplementationDetails;
 import 
org.ovirt.engine.core.common.vdscommands.CollectHostNetworkDataVdsCommandParameters;
-import org.ovirt.engine.core.compat.Guid;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
-import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
-import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
-import org.ovirt.engine.core.dao.network.InterfaceDao;
-import org.ovirt.engine.core.dao.network.NetworkQoSDao;
-import org.ovirt.engine.core.utils.NetworkUtils;
-import org.ovirt.engine.core.utils.linq.LinqUtils;
 import org.ovirt.engine.core.utils.transaction.TransactionMethod;
 import org.ovirt.engine.core.utils.transaction.TransactionSupport;
-import org.ovirt.engine.core.vdsbroker.ResourceManager;
-import 
org.ovirt.engine.core.vdsbroker.vdsbroker.predicates.DisplayInterfaceEqualityPredicate;
-import 
org.ovirt.engine.core.vdsbroker.vdsbroker.predicates.IsNetworkOnInterfacePredicate;
 
 public class CollectVdsNetworkDataVDSCommand extends 
GetCapabilitiesVDSCommand<CollectHostNetworkDataVdsCommandParameters> {
+
+    private final HostNetworkTopologyPersister hostNetworkTopologyPersister;
+
     public 
CollectVdsNetworkDataVDSCommand(CollectHostNetworkDataVdsCommandParameters 
parameters) {
         super(parameters);
+        hostNetworkTopologyPersister = 
HostNetworkTopologyPersisterImpl.getInstance();
     }
 
     @Override
@@ -49,7 +26,7 @@
 
     protected void persistCollectedData() {
         updateNetConfigDirtyFlag();
-        persistAndEnforceNetworkCompliance(getVds(),
+        
hostNetworkTopologyPersister.persistAndEnforceNetworkCompliance(getVds(),
                 skipManagementNetwork(),
                 Entities.entitiesByName(getParameters().getInterfaces()));
     }
@@ -77,266 +54,5 @@
                 return null;
             }
         });
-    }
-
-    /**
-     * Persist this VDS network topology to DB. Set this host to 
non-operational in case networks doesn't comply with
-     * cluster rules:
-     * <ul>
-     * <li>All mandatory networks(optional=false) should be implemented by the 
host.
-     * <li>All VM networks must be implemented with bridges.
-     *
-     * @param vds
-     * @param skipManagementNetwork
-     *            if <code>true</code> skip validations for the management 
network (existence on the host or configured
-     *            properly)
-     * @param nicsByName
-     *            a map of names to their network interfaces
-     * @return The reason for non-operability of the host or 
<code>NonOperationalReason.NONE</code>
-     */
-    public static NonOperationalReason persistAndEnforceNetworkCompliance(VDS 
vds,
-            boolean skipManagementNetwork,
-            Map<String, VdsNetworkInterface> nicsByName) {
-        List<VdsNetworkInterface> dbIfaces =
-                
DbFacade.getInstance().getInterfaceDao().getAllInterfacesForVds(vds.getId());
-        persistTopology(vds, nicsByName, dbIfaces);
-
-        if (vds.getStatus() != VDSStatus.Maintenance) {
-
-            List<Network> clusterNetworks = 
DbFacade.getInstance().getNetworkDao()
-                    .getAllForCluster(vds.getVdsGroupId());
-            if (skipManagementNetwork) {
-                skipManagementNetworkCheck(vds.getInterfaces(), 
clusterNetworks);
-            }
-
-            Map<String, String> customLogValues;
-
-            // here we check if the vds networks match it's cluster networks
-            String networks = getMissingOperationalClusterNetworks(vds, 
clusterNetworks);
-            if (networks.length() > 0) {
-                customLogValues = new HashMap<String, String>();
-                customLogValues.put("Networks", networks);
-
-                setNonOperationl(vds, 
NonOperationalReason.NETWORK_UNREACHABLE, customLogValues);
-                return NonOperationalReason.NETWORK_UNREACHABLE;
-            }
-
-            // Check that VM networks are implemented above a bridge.
-            networks = getVmNetworksImplementedAsBridgeless(vds, 
clusterNetworks);
-            if (networks.length() > 0) {
-                customLogValues = new HashMap<String, String>();
-                customLogValues.put("Networks", networks);
-
-                setNonOperationl(vds, 
NonOperationalReason.VM_NETWORK_IS_BRIDGELESS, customLogValues);
-                return NonOperationalReason.VM_NETWORK_IS_BRIDGELESS;
-            }
-
-            final Map<String, Network> clusterNetworksByName = 
Entities.entitiesByName(clusterNetworks);
-            final Collection<Network> dbHostNetworks = 
findNetworksOnInterfaces(dbIfaces, clusterNetworksByName);
-            logChangedDisplayNetwork(vds, dbHostNetworks, dbIfaces);
-            logUnsynchronizedNetworks(vds, clusterNetworksByName);
-        }
-        return NonOperationalReason.NONE;
-    }
-
-    public static NonOperationalReason persistAndEnforceNetworkCompliance(VDS 
host) {
-        return persistAndEnforceNetworkCompliance(host, false, null);
-    }
-
-    private static void skipManagementNetworkCheck(List<VdsNetworkInterface> 
ifaces, List<Network> clusterNetworks) {
-        String managementNetworkName = 
NetworkUtils.getDefaultManagementNetworkName();
-        for (VdsNetworkInterface iface : ifaces) {
-            if (managementNetworkName.equals(iface.getNetworkName())) {
-                return;
-            }
-        }
-
-        for (Iterator<Network> iterator = clusterNetworks.iterator(); 
iterator.hasNext();) {
-            Network network = iterator.next();
-            if (managementNetworkName.equals(network.getName())) {
-                iterator.remove();
-                break;
-            }
-        }
-    }
-
-    private static void logChangedDisplayNetwork(
-            VDS vds,
-            Collection<Network> engineHostNetworks,
-            Collection<VdsNetworkInterface> engineInterfaces) {
-
-        if (isVmRunningOnHost(vds.getId())) {
-            final Network engineDisplayNetwork = 
findDisplayNetwork(engineHostNetworks);
-
-            if (engineDisplayNetwork == null) {
-                return;
-            }
-
-            final IsNetworkOnInterfacePredicate isNetworkOnInterfacePredicate =
-                    new 
IsNetworkOnInterfacePredicate(engineDisplayNetwork.getName());
-            final VdsNetworkInterface vdsmDisplayInterface = 
LinqUtils.firstOrNull(
-                    vds.getInterfaces(),
-                    isNetworkOnInterfacePredicate);
-            final VdsNetworkInterface engineDisplayInterface = 
LinqUtils.firstOrNull(
-                    engineInterfaces,
-                    isNetworkOnInterfacePredicate);
-            final DisplayInterfaceEqualityPredicate 
displayIneterfaceEqualityPredicate =
-                    new 
DisplayInterfaceEqualityPredicate(engineDisplayInterface);
-            if (vdsmDisplayInterface == null // the display interface is't on 
host anymore
-                    || 
!displayIneterfaceEqualityPredicate.eval(vdsmDisplayInterface)) {
-                final AuditLogableBase loggable = new 
AuditLogableBase(vds.getId());
-                AuditLogDirector.log(loggable, 
AuditLogType.NETWORK_UPDATE_DISPLAY_FOR_HOST_WITH_ACTIVE_VM);
-            }
-        }
-    }
-
-    private static boolean isVmRunningOnHost(Guid hostId) {
-        return 
!DbFacade.getInstance().getVmDynamicDao().getAllRunningForVds(hostId).isEmpty();
-    }
-
-    private static Collection<Network> findNetworksOnInterfaces(
-            Collection<VdsNetworkInterface> ifaces,
-            Map<String, Network> clusterNetworksByName) {
-        final Collection<Network> networks = new ArrayList<Network>();
-        for (VdsNetworkInterface iface : ifaces) {
-            final String interfaceNetworkName = iface.getNetworkName();
-            if (clusterNetworksByName.containsKey(interfaceNetworkName)) {
-                final Network network = 
clusterNetworksByName.get(interfaceNetworkName);
-                networks.add(network);
-            }
-        }
-        return networks;
-    }
-
-    private static Network findDisplayNetwork(Collection<Network> networks) {
-        Network managementNetwork = null;
-        for (Network network : networks) {
-            if (network.getCluster().isDisplay()) {
-                return network;
-            }
-            if (NetworkUtils.isManagementNetwork(network)) {
-                managementNetwork = network;
-            }
-        }
-        return managementNetwork;
-    }
-
-    private static void logUnsynchronizedNetworks(VDS vds, Map<String, 
Network> networks) {
-        List<String> networkNames = new ArrayList<String>();
-        NetworkQoSDao qosDao = DbFacade.getInstance().getNetworkQosDao();
-
-        for (VdsNetworkInterface iface : vds.getInterfaces()) {
-            Network network = networks.get(iface.getNetworkName());
-            NetworkImplementationDetails networkImplementationDetails =
-                    NetworkUtils.calculateNetworkImplementationDetails(network,
-                            network == null ? null : 
qosDao.get(network.getQosId()),
-                            iface);
-
-            if (networkImplementationDetails != null
-                    && !networkImplementationDetails.isInSync()
-                    && networkImplementationDetails.isManaged()) {
-                networkNames.add(iface.getNetworkName());
-            }
-        }
-
-        if (!networkNames.isEmpty()) {
-            AuditLogableBase logable = new AuditLogableBase(vds.getId());
-            logable.addCustomValue("Networks", StringUtils.join(networkNames, 
","));
-            AuditLogDirector.log(logable, 
AuditLogType.VDS_NETWORKS_OUT_OF_SYNC);
-        }
-    }
-
-    private static void persistTopology(
-            VDS vds,
-            Map<String, VdsNetworkInterface> nicsByName,
-            List<VdsNetworkInterface> dbIfaces) {
-        InterfaceDao interfaceDAO = DbFacade.getInstance().getInterfaceDao();
-        List<String> updatedIfaces = new ArrayList<String>();
-        List<VdsNetworkInterface> dbIfacesToBatch = new ArrayList<>();
-        Map<String, VdsNetworkInterface> hostNicsByNames = 
Entities.entitiesByName(vds.getInterfaces());
-
-        // First we check what interfaces need to update/delete
-        for (VdsNetworkInterface dbIface : dbIfaces) {
-            if (hostNicsByNames.containsKey(dbIface.getName())) {
-                VdsNetworkInterface vdsIface = 
hostNicsByNames.get(dbIface.getName());
-
-                // we preserve only the ID and the labels from the Database
-                // everything else is what we got from getVdsCapabilities
-                vdsIface.setId(dbIface.getId());
-                vdsIface.setLabels(dbIface.getLabels());
-                vdsIface.setQosOverridden(dbIface.isQosOverridden());
-                vdsIface.setCustomProperties(dbIface.getCustomProperties());
-                dbIfacesToBatch.add(vdsIface);
-                updatedIfaces.add(vdsIface.getName());
-            } else {
-                interfaceDAO.removeInterfaceFromVds(dbIface.getId());
-                interfaceDAO.removeStatisticsForVds(dbIface.getId());
-            }
-        }
-
-        if (nicsByName != null) {
-            updateInterfacesWithUserConfiguration(dbIfacesToBatch, nicsByName);
-            updateInterfacesWithUserConfiguration(vds.getInterfaces(), 
nicsByName);
-        }
-
-        if (!dbIfacesToBatch.isEmpty()) {
-            interfaceDAO.massUpdateInterfacesForVds(dbIfacesToBatch);
-        }
-
-        // now all that left is add the interfaces that not exists in the 
Database
-        for (VdsNetworkInterface vdsIface : vds.getInterfaces()) {
-            if (!updatedIfaces.contains(vdsIface.getName())) {
-                interfaceDAO.saveInterfaceForVds(vdsIface);
-                interfaceDAO.saveStatisticsForVds(vdsIface.getStatistics());
-            }
-        }
-    }
-
-    private static void 
updateInterfacesWithUserConfiguration(List<VdsNetworkInterface> nicsForUpdate,
-            Map<String, VdsNetworkInterface> nicsByName) {
-        for (VdsNetworkInterface nicForUpdate : nicsForUpdate) {
-            if (nicsByName.containsKey(nicForUpdate.getName())) {
-                VdsNetworkInterface nic = 
nicsByName.get(nicForUpdate.getName());
-                nicForUpdate.setLabels(nic.getLabels());
-                nicForUpdate.setQosOverridden(nic.isQosOverridden());
-                nicForUpdate.setCustomProperties(nic.getCustomProperties());
-            }
-        }
-    }
-
-    private static String getVmNetworksImplementedAsBridgeless(VDS vds, 
List<Network> clusterNetworks) {
-        Map<String, VdsNetworkInterface> interfacesByNetworkName =
-                Entities.hostInterfacesByNetworkName(vds.getInterfaces());
-        List<String> networkNames = new ArrayList<String>();
-
-        for (Network net : clusterNetworks) {
-            if (net.isVmNetwork()
-                    && interfacesByNetworkName.containsKey(net.getName())
-                    && 
!interfacesByNetworkName.get(net.getName()).isBridged()) {
-                networkNames.add(net.getName());
-            }
-        }
-
-        return StringUtils.join(networkNames, ",");
-    }
-
-    private static String getMissingOperationalClusterNetworks(VDS vds, 
List<Network> clusterNetworks) {
-        Map<String, Network> vdsNetworksByName = 
Entities.entitiesByName(vds.getNetworks());
-        List<String> networkNames = new ArrayList<String>();
-
-        for (Network net : clusterNetworks) {
-            if (net.getCluster().getStatus() == OPERATIONAL &&
-                    net.getCluster().isRequired() &&
-                    !vdsNetworksByName.containsKey(net.getName())) {
-                networkNames.add(net.getName());
-            }
-        }
-        return StringUtils.join(networkNames, ",");
-    }
-
-    private static void setNonOperationl(VDS vds, NonOperationalReason reason, 
Map<String, String> customLogValues) {
-        ResourceManager.getInstance()
-                .getEventListener()
-                .vdsNonOperational(vds.getId(), reason, true, Guid.Empty, 
customLogValues);
     }
 }
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersister.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersister.java
new file mode 100644
index 0000000..3cbf054
--- /dev/null
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersister.java
@@ -0,0 +1,33 @@
+package org.ovirt.engine.core.vdsbroker.vdsbroker;
+
+import java.util.Map;
+
+import org.ovirt.engine.core.common.businessentities.NonOperationalReason;
+import org.ovirt.engine.core.common.businessentities.VDS;
+import 
org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface;
+
+public interface HostNetworkTopologyPersister {
+
+    /**
+     * Persist this VDS network topology to DB. Set this host to 
non-operational in case networks doesn't comply with
+     * cluster rules:
+     * <ul>
+     * <li>All mandatory networks(optional=false) should be implemented by the 
host.
+     * <li>All VM networks must be implemented with bridges.
+     * </ul>
+     *
+     * @param host
+     * @param skipManagementNetwork
+     *            if <code>true</code> skip validations for the management 
network (existence on the host or configured
+     *            properly)
+     * @param nicsByName
+     *            a map of names to their network interfaces. Those nics 
engine-side properties will not be changed.
+     * @return The reason for non-operability of the host or 
<code>NonOperationalReason.NONE</code>
+     */
+    NonOperationalReason persistAndEnforceNetworkCompliance(VDS host,
+                                                            boolean 
skipManagementNetwork,
+                                                            Map<String, 
VdsNetworkInterface> nicsByName);
+
+    NonOperationalReason persistAndEnforceNetworkCompliance(VDS host);
+
+}
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersisterImpl.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersisterImpl.java
new file mode 100644
index 0000000..92649aa
--- /dev/null
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HostNetworkTopologyPersisterImpl.java
@@ -0,0 +1,299 @@
+package org.ovirt.engine.core.vdsbroker.vdsbroker;
+
+import static 
org.ovirt.engine.core.common.businessentities.network.NetworkStatus.OPERATIONAL;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.ovirt.engine.core.common.AuditLogType;
+import org.ovirt.engine.core.common.businessentities.Entities;
+import org.ovirt.engine.core.common.businessentities.NonOperationalReason;
+import org.ovirt.engine.core.common.businessentities.VDS;
+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.VdsNetworkInterface;
+import 
org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface.NetworkImplementationDetails;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
+import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
+import org.ovirt.engine.core.dao.network.InterfaceDao;
+import org.ovirt.engine.core.dao.network.NetworkQoSDao;
+import org.ovirt.engine.core.utils.NetworkUtils;
+import org.ovirt.engine.core.utils.linq.LinqUtils;
+import org.ovirt.engine.core.vdsbroker.ResourceManager;
+import 
org.ovirt.engine.core.vdsbroker.vdsbroker.predicates.DisplayInterfaceEqualityPredicate;
+import 
org.ovirt.engine.core.vdsbroker.vdsbroker.predicates.IsNetworkOnInterfacePredicate;
+
+public final class HostNetworkTopologyPersisterImpl implements 
HostNetworkTopologyPersister {
+
+    private static final HostNetworkTopologyPersister instance = new 
HostNetworkTopologyPersisterImpl();
+
+    // TODO: replace with CDI + make the class package protected
+    public static HostNetworkTopologyPersister getInstance() {
+        return instance;
+    }
+
+    // Don't new me - use getInstance method
+    private HostNetworkTopologyPersisterImpl() {
+        super();
+    }
+
+    @Override
+    public NonOperationalReason persistAndEnforceNetworkCompliance(VDS host,
+                                                                   boolean 
skipManagementNetwork,
+                                                                   Map<String, 
VdsNetworkInterface> nicsByName) {
+        List<VdsNetworkInterface> dbIfaces =
+                
DbFacade.getInstance().getInterfaceDao().getAllInterfacesForVds(host.getId());
+        persistTopology(host.getInterfaces(), dbIfaces, nicsByName);
+
+        return enforceNetworkCompliance(host, skipManagementNetwork, dbIfaces);
+    }
+
+    private NonOperationalReason enforceNetworkCompliance(VDS host,
+                                                          boolean 
skipManagementNetwork,
+                                                          
List<VdsNetworkInterface> dbIfaces) {
+        if (host.getStatus() != VDSStatus.Maintenance) {
+
+            List<Network> clusterNetworks = 
DbFacade.getInstance().getNetworkDao()
+                    .getAllForCluster(host.getVdsGroupId());
+            if (skipManagementNetwork) {
+                skipManagementNetworkCheck(host.getInterfaces(), 
clusterNetworks);
+            }
+
+            Map<String, String> customLogValues;
+
+            // here we check if the vds networks match it's cluster networks
+            String networks = getMissingOperationalClusterNetworks(host, 
clusterNetworks);
+            if (networks.length() > 0) {
+                customLogValues = new HashMap<String, String>();
+                customLogValues.put("Networks", networks);
+
+                setNonOperational(host, 
NonOperationalReason.NETWORK_UNREACHABLE, customLogValues);
+                return NonOperationalReason.NETWORK_UNREACHABLE;
+            }
+
+            // Check that VM networks are implemented above a bridge.
+            networks = getVmNetworksImplementedAsBridgeless(host, 
clusterNetworks);
+            if (networks.length() > 0) {
+                customLogValues = new HashMap<String, String>();
+                customLogValues.put("Networks", networks);
+
+                setNonOperational(host, 
NonOperationalReason.VM_NETWORK_IS_BRIDGELESS, customLogValues);
+                return NonOperationalReason.VM_NETWORK_IS_BRIDGELESS;
+            }
+
+            final Map<String, Network> clusterNetworksByName = 
Entities.entitiesByName(clusterNetworks);
+            final Collection<Network> dbHostNetworks = 
findNetworksOnInterfaces(dbIfaces, clusterNetworksByName);
+            logChangedDisplayNetwork(host, dbHostNetworks, dbIfaces);
+            logUnsynchronizedNetworks(host, clusterNetworksByName);
+        }
+        return NonOperationalReason.NONE;
+    }
+
+    @Override
+    public NonOperationalReason persistAndEnforceNetworkCompliance(VDS host) {
+        return persistAndEnforceNetworkCompliance(host, false, null);
+    }
+
+    private void skipManagementNetworkCheck(List<VdsNetworkInterface> ifaces, 
List<Network> clusterNetworks) {
+        String managementNetworkName = 
NetworkUtils.getDefaultManagementNetworkName();
+        for (VdsNetworkInterface iface : ifaces) {
+            if (managementNetworkName.equals(iface.getNetworkName())) {
+                return;
+            }
+        }
+
+        for (Iterator<Network> iterator = clusterNetworks.iterator(); 
iterator.hasNext();) {
+            Network network = iterator.next();
+            if (managementNetworkName.equals(network.getName())) {
+                iterator.remove();
+                break;
+            }
+        }
+    }
+
+    private void logChangedDisplayNetwork(
+                                          VDS vds,
+                                          Collection<Network> 
engineHostNetworks,
+                                          Collection<VdsNetworkInterface> 
engineInterfaces) {
+
+        if (isVmRunningOnHost(vds.getId())) {
+            final Network engineDisplayNetwork = 
findDisplayNetwork(engineHostNetworks);
+
+            if (engineDisplayNetwork == null) {
+                return;
+            }
+
+            final IsNetworkOnInterfacePredicate isNetworkOnInterfacePredicate =
+                    new 
IsNetworkOnInterfacePredicate(engineDisplayNetwork.getName());
+            final VdsNetworkInterface vdsmDisplayInterface = 
LinqUtils.firstOrNull(
+                    vds.getInterfaces(),
+                    isNetworkOnInterfacePredicate);
+            final VdsNetworkInterface engineDisplayInterface = 
LinqUtils.firstOrNull(
+                    engineInterfaces,
+                    isNetworkOnInterfacePredicate);
+            final DisplayInterfaceEqualityPredicate 
displayIneterfaceEqualityPredicate =
+                    new 
DisplayInterfaceEqualityPredicate(engineDisplayInterface);
+            if (vdsmDisplayInterface == null // the display interface is't on 
host anymore
+                || 
!displayIneterfaceEqualityPredicate.eval(vdsmDisplayInterface)) {
+                final AuditLogableBase loggable = new 
AuditLogableBase(vds.getId());
+                AuditLogDirector.log(loggable, 
AuditLogType.NETWORK_UPDATE_DISPLAY_FOR_HOST_WITH_ACTIVE_VM);
+            }
+        }
+    }
+
+    private boolean isVmRunningOnHost(Guid hostId) {
+        return 
!DbFacade.getInstance().getVmDynamicDao().getAllRunningForVds(hostId).isEmpty();
+    }
+
+    private Collection<Network> findNetworksOnInterfaces(
+                                                         
Collection<VdsNetworkInterface> ifaces,
+                                                         Map<String, Network> 
clusterNetworksByName) {
+        final Collection<Network> networks = new ArrayList<Network>();
+        for (VdsNetworkInterface iface : ifaces) {
+            final String interfaceNetworkName = iface.getNetworkName();
+            if (clusterNetworksByName.containsKey(interfaceNetworkName)) {
+                final Network network = 
clusterNetworksByName.get(interfaceNetworkName);
+                networks.add(network);
+            }
+        }
+        return networks;
+    }
+
+    private Network findDisplayNetwork(Collection<Network> networks) {
+        Network managementNetwork = null;
+        for (Network network : networks) {
+            if (network.getCluster().isDisplay()) {
+                return network;
+            }
+            if (NetworkUtils.isManagementNetwork(network)) {
+                managementNetwork = network;
+            }
+        }
+        return managementNetwork;
+    }
+
+    private void logUnsynchronizedNetworks(VDS vds, Map<String, Network> 
networks) {
+        List<String> networkNames = new ArrayList<String>();
+        NetworkQoSDao qosDao = DbFacade.getInstance().getNetworkQosDao();
+
+        for (VdsNetworkInterface iface : vds.getInterfaces()) {
+            Network network = networks.get(iface.getNetworkName());
+            NetworkImplementationDetails networkImplementationDetails =
+                    NetworkUtils.calculateNetworkImplementationDetails(network,
+                            network == null ? null : 
qosDao.get(network.getQosId()),
+                            iface);
+
+            if (networkImplementationDetails != null
+                && !networkImplementationDetails.isInSync()
+                && networkImplementationDetails.isManaged()) {
+                networkNames.add(iface.getNetworkName());
+            }
+        }
+
+        if (!networkNames.isEmpty()) {
+            AuditLogableBase logable = new AuditLogableBase(vds.getId());
+            logable.addCustomValue("Networks", StringUtils.join(networkNames, 
","));
+            AuditLogDirector.log(logable, 
AuditLogType.VDS_NETWORKS_OUT_OF_SYNC);
+        }
+    }
+
+    private void persistTopology(List<VdsNetworkInterface> reportedNics,
+                                 List<VdsNetworkInterface> dbNics,
+                                 Map<String, VdsNetworkInterface> nicsByName) {
+        InterfaceDao interfaceDAO = DbFacade.getInstance().getInterfaceDao();
+        List<String> updatedIfaces = new ArrayList<String>();
+        List<VdsNetworkInterface> dbIfacesToBatch = new ArrayList<>();
+        Map<String, VdsNetworkInterface> hostNicsByNames = 
Entities.entitiesByName(reportedNics);
+
+        // First we check what interfaces need to update/delete
+        for (VdsNetworkInterface dbIface : dbNics) {
+            if (hostNicsByNames.containsKey(dbIface.getName())) {
+                VdsNetworkInterface vdsIface = 
hostNicsByNames.get(dbIface.getName());
+
+                // we preserve only the ID and the labels from the Database
+                // everything else is what we got from getVdsCapabilities
+                vdsIface.setId(dbIface.getId());
+                vdsIface.setLabels(dbIface.getLabels());
+                vdsIface.setQosOverridden(dbIface.isQosOverridden());
+                vdsIface.setCustomProperties(dbIface.getCustomProperties());
+                dbIfacesToBatch.add(vdsIface);
+                updatedIfaces.add(vdsIface.getName());
+            } else {
+                interfaceDAO.removeInterfaceFromVds(dbIface.getId());
+                interfaceDAO.removeStatisticsForVds(dbIface.getId());
+            }
+        }
+
+        if (nicsByName != null) {
+            updateInterfacesWithUserConfiguration(dbIfacesToBatch, nicsByName);
+            updateInterfacesWithUserConfiguration(reportedNics, nicsByName);
+        }
+
+        if (!dbIfacesToBatch.isEmpty()) {
+            interfaceDAO.massUpdateInterfacesForVds(dbIfacesToBatch);
+        }
+
+        // now all that left is add the interfaces that not exists in the 
Database
+        for (VdsNetworkInterface vdsIface : reportedNics) {
+            if (!updatedIfaces.contains(vdsIface.getName())) {
+                interfaceDAO.saveInterfaceForVds(vdsIface);
+                interfaceDAO.saveStatisticsForVds(vdsIface.getStatistics());
+            }
+        }
+    }
+
+    private void 
updateInterfacesWithUserConfiguration(List<VdsNetworkInterface> nicsForUpdate,
+                                                       Map<String, 
VdsNetworkInterface> nicsByName) {
+        for (VdsNetworkInterface nicForUpdate : nicsForUpdate) {
+            if (nicsByName.containsKey(nicForUpdate.getName())) {
+                VdsNetworkInterface nic = 
nicsByName.get(nicForUpdate.getName());
+                nicForUpdate.setLabels(nic.getLabels());
+                nicForUpdate.setQosOverridden(nic.isQosOverridden());
+                nicForUpdate.setCustomProperties(nic.getCustomProperties());
+            }
+        }
+    }
+
+    private String getVmNetworksImplementedAsBridgeless(VDS vds, List<Network> 
clusterNetworks) {
+        Map<String, VdsNetworkInterface> interfacesByNetworkName =
+                Entities.hostInterfacesByNetworkName(vds.getInterfaces());
+        List<String> networkNames = new ArrayList<String>();
+
+        for (Network net : clusterNetworks) {
+            if (net.isVmNetwork()
+                && interfacesByNetworkName.containsKey(net.getName())
+                && !interfacesByNetworkName.get(net.getName()).isBridged()) {
+                networkNames.add(net.getName());
+            }
+        }
+
+        return StringUtils.join(networkNames, ",");
+    }
+
+    private String getMissingOperationalClusterNetworks(VDS vds, List<Network> 
clusterNetworks) {
+        Map<String, Network> vdsNetworksByName = 
Entities.entitiesByName(vds.getNetworks());
+        List<String> networkNames = new ArrayList<String>();
+
+        for (Network net : clusterNetworks) {
+            if (net.getCluster().getStatus() == OPERATIONAL &&
+                net.getCluster().isRequired() &&
+                !vdsNetworksByName.containsKey(net.getName())) {
+                networkNames.add(net.getName());
+            }
+        }
+        return StringUtils.join(networkNames, ",");
+    }
+
+    private void setNonOperational(VDS vds, NonOperationalReason reason, 
Map<String, String> customLogValues) {
+        ResourceManager.getInstance()
+                .getEventListener()
+                .vdsNonOperational(vds.getId(), reason, true, Guid.Empty, 
customLogValues);
+    }
+}


-- 
To view, visit http://gerrit.ovirt.org/33905
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I798abe6597c06df873ac94f61981ff1dccc07bc8
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Yevgeny Zaspitsky <yzasp...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to