package org.ovirt.engine.core.dao; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.inject.Named; import javax.inject.Singleton; import org.ovirt.engine.core.common.businessentities.ActionGroup; import org.ovirt.engine.core.common.businessentities.ArchitectureType; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.ClusterHostsAndVMs; import org.ovirt.engine.core.common.businessentities.MigrateOnErrorOptions; import org.ovirt.engine.core.common.businessentities.MigrationBandwidthLimitType; import org.ovirt.engine.core.common.businessentities.SerialNumberPolicy; import org.ovirt.engine.core.common.businessentities.VmRngDevice; import org.ovirt.engine.core.common.network.SwitchType; import org.ovirt.engine.core.common.scheduling.OptimizationType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.DbFacadeUtils; import org.ovirt.engine.core.utils.SerializationFactory; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.SingleColumnRowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; /** * {@code ClusterDaoImpl} provides an implementation of {@link ClusterDao}. * */ @Named @Singleton public class ClusterDaoImpl extends BaseDao implements ClusterDao { @Override public Cluster get(Guid id) { return get(id, null, false); } @Override public Cluster get(Guid id, Guid userID, boolean isFiltered) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_id", id).addValue("user_id", userID).addValue("is_filtered", isFiltered); return getCallsHandler().executeRead("GetClusterByClusterId", clusterRowMapper, parameterSource); } @Override public Cluster getWithRunningVms(Guid id) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_id", id); return getCallsHandler().executeRead("GetClusterWithRunningVms", clusterRowMapper, parameterSource); } @Override public Boolean getIsEmpty(Guid id) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_id", id); return getCallsHandler().executeRead ("GetIsClusterEmpty", SingleColumnRowMapper.newInstance(Boolean.class), parameterSource); } @Override public Cluster getByName(String name) { return (Cluster) DbFacadeUtils.asSingleResult(getByName(name, true)); } @Override public List<Cluster> getByName(String name, boolean isCaseSensitive) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_name", name) .addValue("is_case_sensitive", isCaseSensitive); return getCallsHandler().executeReadList("GetClusterByClusterName", clusterRowMapper, parameterSource); } @Override public Cluster getByName(String name, Guid userID, boolean isFiltered) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_name", name).addValue("user_id", userID).addValue("is_filtered", isFiltered); return (Cluster) DbFacadeUtils.asSingleResult( getCallsHandler().executeReadList("GetClusterForUserByClusterName", clusterRowMapper, parameterSource)); } @Override public List<Cluster> getAllForStoragePool(Guid id) { return getAllForStoragePool(id, null, false); } @Override public List<Cluster> getAllForStoragePool(Guid id, Guid userID, boolean isFiltered) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("storage_pool_id", id).addValue("user_id", userID).addValue("is_filtered", isFiltered); return getCallsHandler().executeReadList("GetClustersByStoragePoolId", clusterRowMapper, parameterSource); } @Override public List<Cluster> getAllWithQuery(String query) { List<Cluster> clusters = getJdbcTemplate().query(query, clusterRowMapper); return getHostsAndVmsForClusters(clusters); } @Override public List<Cluster> getAll() { return getAll(null, false); } @Override public List<Cluster> getAll(Guid userID, boolean isFiltered) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource().addValue("user_id", userID).addValue("is_filtered", isFiltered); return getCallsHandler().executeReadList("GetAllFromCluster", clusterRowMapper, parameterSource); } @Override public void save(Cluster cluster) { Guid id = cluster.getId(); if (Guid.isNullOrEmpty(id)) { id = Guid.newGuid(); cluster.setId(id); } getCallsHandler().executeModification("InsertCluster", getClusterParamSource(cluster)); } @Override public void update(Cluster cluster) { getCallsHandler().executeModification("UpdateCluster", getClusterParamSource(cluster)); } @Override public void remove(Guid id) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_id", id); getCallsHandler().executeModification("DeleteCluster", parameterSource); } @Override public List<Cluster> getClustersWithPermittedAction(Guid userId, ActionGroup actionGroup) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("user_id", userId).addValue("action_group_id", actionGroup.getId()); return getCallsHandler().executeReadList("fn_perms_get_clusters_with_permitted_action", clusterRowMapper, parameterSource); } @Override public List<Cluster> getClustersHavingHosts() { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource(); return getCallsHandler().executeReadList("GetClustersHavingHosts", clusterRowMapper, parameterSource); } @Override public List<Cluster> getWithoutMigratingVms() { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource(); return getCallsHandler().executeReadList("GetClustersWithoutMigratingVms", clusterRowMapper, parameterSource); } @Override public void setEmulatedMachine(Guid clusterId, String emulatedMachine, boolean detectEmulatedMachine) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_id", clusterId) .addValue("emulated_machine", emulatedMachine) .addValue("detect_emulated_machine", detectEmulatedMachine); getCallsHandler().executeModification("UpdateClusterEmulatedMachine", parameterSource); } @Override public int getVmsCountByClusterId(Guid clusterId) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource().addValue("cluster_id", clusterId); return getCallsHandler().executeRead("GetNumberOfVmsInCluster", SingleColumnRowMapper.newInstance(Integer.class), parameterSource); } @Override public List<Cluster> getTrustedClusters() { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("trusted_service", true); return getCallsHandler().executeReadList("GetTrustedClusters", clusterRowMapper, parameterSource); } private MapSqlParameterSource getClusterParamSource(Cluster cluster) { return getCustomMapSqlParameterSource() .addValue("description", cluster.getDescription()) .addValue("name", cluster.getName()) .addValue("free_text_comment", cluster.getComment()) .addValue("cluster_id", cluster.getId()) .addValue("cpu_name", cluster.getCpuName()) .addValue("storage_pool_id", cluster.getStoragePoolId()) .addValue("max_vds_memory_over_commit", cluster.getMaxVdsMemoryOverCommit()) .addValue("count_threads_as_cores", cluster.getCountThreadsAsCores()) .addValue("transparent_hugepages", cluster.getTransparentHugepages()) .addValue("compatibility_version", cluster.getCompatibilityVersion()) .addValue("migrate_on_error", cluster.getMigrateOnError()) .addValue("virt_service", cluster.supportsVirtService()) .addValue("gluster_service", cluster.supportsGlusterService()) .addValue("gluster_cli_based_snapshot_scheduled", cluster.isGlusterCliBasedSchedulingOn()) .addValue("tunnel_migration", cluster.isTunnelMigration()) .addValue("additional_rng_sources", VmRngDevice.sourcesToCsv(cluster.getAdditionalRngSources())) .addValue("emulated_machine", cluster.getEmulatedMachine()) .addValue("detect_emulated_machine", cluster.isDetectEmulatedMachine()) .addValue("trusted_service", cluster.supportsTrustedService()) .addValue("ha_reservation", cluster.supportsHaReservation()) .addValue("optional_reason", cluster.isOptionalReasonRequired()) .addValue("maintenance_reason_required", cluster.isMaintenanceReasonRequired()) .addValue("cluster_policy_id", cluster.getClusterPolicyId()) .addValue("cluster_policy_custom_properties", SerializationFactory.getSerializer().serialize(cluster.getClusterPolicyProperties())) .addValue("architecture", cluster.getArchitecture()) .addValue("enable_balloon", cluster.isEnableBallooning()) .addValue("optimization_type", cluster.getOptimizationType()) .addValue("enable_ksm", cluster.isEnableKsm()) .addValue("spice_proxy", cluster.getSpiceProxy()) .addValue("serial_number_policy", cluster.getSerialNumberPolicy() == null ? null : cluster.getSerialNumberPolicy().getValue()) .addValue("custom_serial_number", cluster.getCustomSerialNumber()) .addValue("skip_fencing_if_sd_active", cluster.getFencingPolicy().isSkipFencingIfSDActive()) .addValue("skip_fencing_if_connectivity_broken", cluster.getFencingPolicy().isSkipFencingIfConnectivityBroken()) .addValue("hosts_with_broken_connectivity_threshold", cluster.getFencingPolicy().getHostsWithBrokenConnectivityThreshold()) .addValue("fencing_enabled", cluster.getFencingPolicy().isFencingEnabled()) .addValue("is_auto_converge", cluster.getAutoConverge()) .addValue("is_migrate_compressed", cluster.getMigrateCompressed()) .addValue("gluster_tuned_profile", cluster.getGlusterTunedProfile()) .addValue("ksm_merge_across_nodes", cluster.isKsmMergeAcrossNumaNodes()) .addValue("migration_bandwidth_limit_type", cluster.getMigrationBandwidthLimitType().name()) .addValue("custom_migration_bandwidth_limit", cluster.getCustomMigrationNetworkBandwidth()) .addValue("migration_policy_id", cluster.getMigrationPolicyId()) .addValue("mac_pool_id", cluster.getMacPoolId()) .addValue("switch_type", cluster.getRequiredSwitchTypeForCluster().getOptionValue()) .addValue("skip_fencing_if_gluster_bricks_up", cluster.getFencingPolicy().isSkipFencingIfGlusterBricksUp()) .addValue("skip_fencing_if_gluster_quorum_not_met", cluster.getFencingPolicy().isSkipFencingIfGlusterQuorumNotMet()); } private static final RowMapper<ClusterHostsAndVMs> clusterHostsAndVMsRowMapper = (rs, rowNum) -> { ClusterHostsAndVMs entity = new ClusterHostsAndVMs(); entity.setHosts(rs.getInt("hosts")); entity.setVms(rs.getInt("vms")); entity.setClusterId(getGuid(rs, "cluster_id")); return entity; }; private static final RowMapper<Cluster> clusterRowMapper = (rs, rowNum) -> { Cluster entity = new Cluster(); entity.setDescription(rs.getString("description")); entity.setName(rs.getString("name")); entity.setId(getGuidDefaultEmpty(rs, "cluster_id")); entity.setComment(rs.getString("free_text_comment")); entity.setCpuName(rs.getString("cpu_name")); entity.setStoragePoolId(getGuid(rs, "storage_pool_id")); entity.setStoragePoolName(rs.getString("storage_pool_name")); entity.setMaxVdsMemoryOverCommit(rs.getInt("max_vds_memory_over_commit")); entity.setCountThreadsAsCores(rs.getBoolean("count_threads_as_cores")); entity.setTransparentHugepages(rs.getBoolean("transparent_hugepages")); entity.setCompatibilityVersion(new VersionRowMapper("compatibility_version").mapRow(rs, rowNum)); entity.setMigrateOnError(MigrateOnErrorOptions.forValue(rs.getInt("migrate_on_error"))); entity.setVirtService(rs.getBoolean("virt_service")); entity.setGlusterService(rs.getBoolean("gluster_service")); entity.setGlusterCliBasedSchedulingOn(rs.getBoolean("gluster_cli_based_snapshot_scheduled")); entity.setTunnelMigration(rs.getBoolean("tunnel_migration")); entity.getAdditionalRngSources().addAll(VmRngDevice.csvToSourcesSet(rs.getString("additional_rng_sources"))); entity.setEmulatedMachine(rs.getString("emulated_machine")); entity.setDetectEmulatedMachine(rs.getBoolean("detect_emulated_machine")); entity.setTrustedService(rs.getBoolean("trusted_service")); entity.setHaReservation(rs.getBoolean("ha_reservation")); entity.setOptionalReasonRequired(rs.getBoolean("optional_reason")); entity.setMaintenanceReasonRequired(rs.getBoolean("maintenance_reason_required")); entity.setClusterPolicyId(Guid.createGuidFromString(rs.getString("cluster_policy_id"))); entity.setClusterPolicyName(rs.getString("cluster_policy_name")); entity.setClusterPolicyProperties(SerializationFactory.getDeserializer() .deserializeOrCreateNew(rs.getString("cluster_policy_custom_properties"), LinkedHashMap.class)); entity.setEnableBallooning(rs.getBoolean("enable_balloon")); entity.setEnableKsm(rs.getBoolean("enable_ksm")); entity.setArchitecture(ArchitectureType.forValue(rs.getInt("architecture"))); entity.setOptimizationType(OptimizationType.from(rs.getInt("optimization_type"))); entity.setSpiceProxy(rs.getString("spice_proxy")); entity.setSerialNumberPolicy(SerialNumberPolicy.forValue((Integer) rs.getObject("serial_number_policy"))); entity.setCustomSerialNumber(rs.getString("custom_serial_number")); entity.getFencingPolicy().setSkipFencingIfSDActive(rs.getBoolean("skip_fencing_if_sd_active")); entity.getFencingPolicy().setSkipFencingIfConnectivityBroken(rs.getBoolean("skip_fencing_if_connectivity_broken")); entity.getFencingPolicy().setSkipFencingIfGlusterBricksUp(rs.getBoolean("skip_fencing_if_gluster_bricks_up")); entity.getFencingPolicy().setSkipFencingIfGlusterQuorumNotMet(rs.getBoolean("skip_fencing_if_gluster_quorum_not_met")); entity.getFencingPolicy().setHostsWithBrokenConnectivityThreshold(rs.getInt("hosts_with_broken_connectivity_threshold")); entity.getFencingPolicy().setFencingEnabled(rs.getBoolean("fencing_enabled")); entity.setAutoConverge((Boolean) rs.getObject("is_auto_converge")); entity.setMigrateCompressed((Boolean) rs.getObject("is_migrate_compressed")); entity.setGlusterTunedProfile(rs.getString("gluster_tuned_profile")); entity.setKsmMergeAcrossNumaNodes(rs.getBoolean("ksm_merge_across_nodes")); entity.setMigrationBandwidthLimitType(MigrationBandwidthLimitType.valueOf(rs.getString("migration_bandwidth_limit_type"))); entity.setCustomMigrationNetworkBandwidth(getInteger(rs, "custom_migration_bandwidth_limit")); entity.setMigrationPolicyId(getGuid(rs, "migration_policy_id")); entity.setMacPoolId(getGuid(rs, "mac_pool_id")); entity.setRequiredSwitchTypeForCluster(SwitchType.parse(rs.getString("switch_type"))); return entity; }; @Override public List<Cluster> getClustersByClusterPolicyId(Guid clusterPolicyId) { return getCallsHandler().executeReadList("GetClustersByClusterPolicyId", clusterRowMapper, getCustomMapSqlParameterSource() .addValue("cluster_policy_id", clusterPolicyId)); } protected List<Cluster> getHostsAndVmsForClusters(List<Cluster> clusters) { Map<Guid, Cluster> clustersById = new HashMap<>(); for (Cluster cluster : clusters) { clustersById.put(cluster.getId(), cluster); } List<ClusterHostsAndVMs> dataList = getCallsHandler().executeReadList("GetHostsAndVmsForClusters", clusterHostsAndVMsRowMapper, getCustomMapSqlParameterSource() .addValue("cluster_ids", createArrayOf("uuid", clustersById.keySet().toArray()))); for (ClusterHostsAndVMs clusterDetail : dataList) { clustersById.get(clusterDetail.getClusterId()).setClusterHostsAndVms(clusterDetail); } //The VDS clusters have been updated, but we want to keep the order, so return the original list which is //in the right order. return clusters; } @Override public List<Cluster> getClustersByServiceAndCompatibilityVersion(boolean glusterService, boolean virtService, String compatibilityVersion) { return getCallsHandler().executeReadList("GetClustersByServiceAndCompatibilityVersion", clusterRowMapper, getCustomMapSqlParameterSource().addValue("gluster_service", glusterService) .addValue("virt_service", virtService) .addValue("compatibility_version", compatibilityVersion)); } @Override public List<Cluster> getAllClustersByMacPoolId(Guid macPoolId) { return getCallsHandler().executeReadList("GetAllClustersByMacPoolId", clusterRowMapper, getCustomMapSqlParameterSource().addValue("id", macPoolId)); } }