package org.ovirt.engine.core.dao.network; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.ovirt.engine.core.common.businessentities.network.Bond; import org.ovirt.engine.core.common.businessentities.network.Ipv4BootProtocol; import org.ovirt.engine.core.common.businessentities.network.Ipv6BootProtocol; import org.ovirt.engine.core.common.businessentities.network.Nic; import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface; import org.ovirt.engine.core.common.businessentities.network.VdsNetworkStatistics; import org.ovirt.engine.core.common.businessentities.network.Vlan; import org.ovirt.engine.core.common.network.SwitchType; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.CustomMapSqlParameterSource; import org.ovirt.engine.core.dal.dbbroker.MapSqlParameterMapper; import org.ovirt.engine.core.dao.BaseDao; import org.ovirt.engine.core.dao.network.NetworkStatisticsDaoImpl.NetworkStatisticsParametersMapper; import org.ovirt.engine.core.dao.network.NetworkStatisticsDaoImpl.NetworkStatisticsRowMapper; import org.ovirt.engine.core.utils.SerializationFactory; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; @Named @Singleton public class InterfaceDaoImpl extends BaseDao implements InterfaceDao { @Inject private NetworkQoSDao networkQosDao; @Inject private HostNetworkQosDao hostNetworkQosDao; @Override public void saveStatisticsForVds(VdsNetworkStatistics stats) { MapSqlParameterSource parameterSource = createStatisticsParametersMapper(stats); getCallsHandler().executeModification("Insertvds_interface_statistics", parameterSource); } @Override public void massUpdateInterfacesForVds(List<VdsNetworkInterface> dbIfacesToBatch) { updateAllInBatch("Updatevds_interface", dbIfacesToBatch, this::createInterfaceParametersMapper); } @Override public void massClearNetworkFromNics(List<Guid> nicIds) { getCallsHandler().executeStoredProcAsBatch("Clear_network_from_nics", nicIds, id -> { CustomMapSqlParameterSource paramSource = getCustomMapSqlParameterSource(); paramSource.addValue("id", id); return paramSource; }); } public void updateAllInBatch(String procedureName, Collection<VdsNetworkInterface> paramValues, MapSqlParameterMapper<VdsNetworkInterface> mapper) { for (VdsNetworkInterface entity : paramValues) { hostNetworkQosDao.persistQosChanges(entity.getId(), entity.getQos()); } getCallsHandler().executeStoredProcAsBatch(procedureName, paramValues, mapper); } @Override public void saveInterfaceForVds(VdsNetworkInterface nic) { hostNetworkQosDao.persistQosChanges(nic.getId(), nic.getQos()); MapSqlParameterSource parameterSource = createInterfaceParametersMapper(nic); getCallsHandler().executeModification("Insertvds_interface", parameterSource); } @Override public void updateStatisticsForVds(VdsNetworkStatistics stats) { update(stats); } @Override public void massUpdateStatisticsForVds(Collection<VdsNetworkStatistics> statistics) { List<MapSqlParameterSource> executions = statistics.stream().map(this::createStatisticsParametersMapper).collect(Collectors.toList()); getCallsHandler().executeStoredProcAsBatch("Updatevds_interface_statistics", executions); } /** * Update the {@link VdsNetworkStatistics} in the DB * * @param stats * The host's network statistics data. */ private void update(VdsNetworkStatistics stats) { getCallsHandler().executeModification("Updatevds_interface_statistics", createStatisticsParametersMapper(stats)); } private MapSqlParameterSource createStatisticsParametersMapper(VdsNetworkStatistics stats) { NetworkStatisticsParametersMapper<VdsNetworkStatistics> mapper = new NetworkStatisticsParametersMapper<>(); return getCustomMapSqlParameterSource() .addValues(mapper.createParametersMap(stats)) .addValue("vds_id", stats.getVdsId()); } @Override public void updateInterfaceForVds(VdsNetworkInterface nic) { hostNetworkQosDao.persistQosChanges(nic.getId(), nic.getQos()); getCallsHandler().executeModification("Updatevds_interface", createInterfaceParametersMapper(nic)); } private MapSqlParameterSource createInterfaceParametersMapper(VdsNetworkInterface nic) { return getCustomMapSqlParameterSource() .addValue("addr", nic.getIpv4Address()) .addValue("ipv6_address", nic.getIpv6Address()) .addValue("bond_name", nic.getBondName()) .addValue("bond_type", nic.getBondType()) .addValue("gateway", nic.getIpv4Gateway()) .addValue("ipv6_gateway", nic.getIpv6Gateway()) .addValue("id", nic.getId()) .addValue("is_bond", nic.getBonded()) .addValue("bond_opts", nic.getBondOptions()) .addValue("mac_addr", nic.getMacAddress()) .addValue("name", nic.getName()) .addValue("network_name", nic.getNetworkName()) .addValue("speed", nic.getSpeed()) .addValue("subnet", nic.getIpv4Subnet()) .addValue("ipv6_prefix", nic.getIpv6Prefix()) .addValue("boot_protocol", nic.getIpv4BootProtocol()) .addValue("ipv6_boot_protocol", nic.getIpv6BootProtocol()) .addValue("type", nic.getType()) .addValue("vds_id", nic.getVdsId()) .addValue("vlan_id", nic.getVlanId()) .addValue("base_interface", nic.getBaseInterface()) .addValue("mtu", nic.getMtu()) .addValue("bridged", nic.isBridged()) .addValue("labels", SerializationFactory.getSerializer().serialize(nic.getLabels())) .addValue("ad_partner_mac", nic.getAdPartnerMac()) .addValue("ad_aggregator_id", nic.getAdAggregatorId()) .addValue("bond_active_slave", nic.isBond() ? ((Bond)nic).getActiveSlave() : null) .addValue("reported_switch_type", nic.getReportedSwitchType() == null ? null : nic.getReportedSwitchType().getOptionValue()); } @Override public List<VdsNetworkInterface> getAllInterfacesForVds(Guid id) { return getAllInterfacesForVds(id, null, false); } @Override public Map<Guid, List<String>> getHostNetworksByCluster(Guid clusterId) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("cluster_id", clusterId); List<Pair<Guid, String>> hostNetworks = getCallsHandler().executeReadList("GetHostNetworksByCluster", hostNetworkNameMapper, parameterSource); Map<Guid, List<String>> neworksByHost = new HashMap<>(); for (Pair<Guid, String> pair : hostNetworks) { if (!neworksByHost.containsKey(pair.getFirst())) { neworksByHost.put(pair.getFirst(), new ArrayList<>()); } neworksByHost.get(pair.getFirst()).add(pair.getSecond()); } return neworksByHost; } @Override public List<VdsNetworkInterface> getAllInterfacesWithIpAddress(Guid clusterId, String ipAddress) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("addr", ipAddress).addValue("cluster_id", clusterId); return getCallsHandler().executeReadList("Getinterface_viewByAddr", vdsNetworkInterfaceRowMapper, parameterSource); } @Override public List<VdsNetworkInterface> getAllInterfacesForVds(Guid id, Guid userID, boolean isFiltered) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("vds_id", id).addValue("user_id", userID).addValue("is_filtered", isFiltered); return getCallsHandler().executeReadList("Getinterface_viewByvds_id", vdsNetworkInterfaceRowMapper, parameterSource); } @Override public VdsNetworkInterface getManagedInterfaceForVds(Guid id, Guid userID, boolean isFiltered) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("vds_id", id).addValue("user_id", userID).addValue("is_filtered", isFiltered); return getCallsHandler().executeRead("GetVdsManagedInterfaceByVdsId", vdsNetworkInterfaceRowMapper, parameterSource); } @Override public void removeStatisticsForVds(Guid id) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("id", id); getCallsHandler().executeModification("Deletevds_interface_statistics", parameterSource); } @Override public void removeInterfaceFromVds(Guid id) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("id", id); networkQosDao.remove(id); getCallsHandler().executeModification("Deletevds_interface", parameterSource); } @Override public List<VdsNetworkInterface> getVdsInterfacesByNetworkId(Guid networkId) { return getCallsHandler().executeReadList("GetVdsInterfacesByNetworkId", vdsNetworkInterfaceRowMapper, getCustomMapSqlParameterSource().addValue("network_id", networkId)); } @Override public VdsNetworkInterface get(Guid id) { return getCallsHandler().executeRead("GetVdsInterfaceById", vdsNetworkInterfaceRowMapper, getCustomMapSqlParameterSource().addValue("vds_interface_id", id)); } @Override public VdsNetworkInterface get(Guid hostId, String name) { return getCallsHandler().executeRead("GetVdsInterfaceByName", vdsNetworkInterfaceRowMapper, getCustomMapSqlParameterSource() .addValue("host_id", hostId) .addValue("name", name)); } @Override public List<VdsNetworkInterface> getAllInterfacesByClusterId(Guid clusterId) { return getCallsHandler().executeReadList("GetInterfacesByClusterId", vdsNetworkInterfaceRowMapper, getCustomMapSqlParameterSource().addValue("cluster_id", clusterId)); } @Override public List<VdsNetworkInterface> getAllInterfacesByLabelForDataCenter(Guid dataCenterId, String label) { return nicsContainingLabel(getAllInterfacesByDataCenterId(dataCenterId), label); } @Override public List<VdsNetworkInterface> getAllInterfacesByLabelForCluster(Guid clusterId, String label) { return nicsContainingLabel(getAllInterfacesByClusterId(clusterId), label); } protected List<VdsNetworkInterface> nicsContainingLabel(List<VdsNetworkInterface> interfaces, String label) { return interfaces.stream() .filter(i -> i.getLabels() != null && i.getLabels().contains(label)) .collect(Collectors.toList()); } private List<VdsNetworkInterface> getAllInterfacesByDataCenterId(Guid dataCenterId) { return getCallsHandler().executeReadList("GetInterfacesByDataCenterId", vdsNetworkInterfaceRowMapper, getCustomMapSqlParameterSource().addValue("data_center_id", dataCenterId)); } @Override public Set<String> getAllNetworkLabelsForDataCenter(Guid dataCenterId) { return getAllInterfacesByDataCenterId(dataCenterId).stream() .filter(nic -> nic.getLabels() != null) .flatMap(nic -> nic.getLabels().stream()) .collect(Collectors.toSet()); } @Override public List<VdsNetworkInterface> getIscsiIfacesByHostIdAndStorageTargetId(Guid hostId, String storageTargetId) { return getCallsHandler().executeReadList("GetIscsiIfacesByHostIdAndStorageTargetId", vdsNetworkInterfaceRowMapper, getCustomMapSqlParameterSource().addValue("host_id", hostId).addValue("target_id", storageTargetId)); } @Override public Optional<VdsNetworkInterface> getActiveMigrationNetworkInterfaceForHost(Guid hostId) { return Optional.ofNullable(getCallsHandler().executeRead("getActiveMigrationNetworkInterfaceForHost", vdsNetworkInterfaceRowMapper, getCustomMapSqlParameterSource().addValue("host_id", hostId))); } private final RowMapper<VdsNetworkInterface> vdsNetworkInterfaceRowMapper = new RowMapper<VdsNetworkInterface>() { @SuppressWarnings("unchecked") @Override public VdsNetworkInterface mapRow(ResultSet rs, int rowNum) throws SQLException { VdsNetworkInterface entity = createInterface(rs); entity.setStatistics(HostNetworkStatisticsRowMapper.INSTANCE.mapRow(rs, rowNum)); entity.setType((Integer) rs.getObject("type")); entity.setIpv4Gateway(rs.getString("gateway")); entity.setIpv6Gateway(rs.getString("ipv6_gateway")); entity.setIpv4Subnet(rs.getString("subnet")); entity.setIpv6Prefix(getInteger(rs, "ipv6_prefix")); entity.setIpv4Address(rs.getString("addr")); entity.setIpv6Address(rs.getString("ipv6_address")); entity.setNetworkName(rs.getString("network_name")); entity.setName(rs.getString("name")); entity.setVdsId(getGuid(rs, "vds_id")); entity.setVdsName(rs.getString("vds_name")); entity.setId(getGuidDefaultEmpty(rs, "id")); entity.setIpv4BootProtocol(Ipv4BootProtocol.forValue(rs.getInt("boot_protocol"))); entity.setIpv6BootProtocol(Ipv6BootProtocol.forValue(rs.getInt("ipv6_boot_protocol"))); entity.setReportedSwitchType(SwitchType.parse(rs.getString("reported_switch_type"))); entity.setMtu(rs.getInt("mtu")); entity.setBridged(rs.getBoolean("bridged")); entity.setQos(hostNetworkQosDao.get(entity.getId())); entity.setLabels(SerializationFactory.getDeserializer().deserialize(rs.getString("labels"), HashSet.class)); entity.setAdPartnerMac(rs.getString("ad_partner_mac")); entity.setAdAggregatorId(getInteger(rs, "ad_aggregator_id")); return entity; } /** * Create the correct type according to the row. If the type can't be determined for whatever reason, * {@link VdsNetworkInterface} instance is created & initialized. * * @param rs * The row representing the entity. * @return The instance of the correct type as represented by the row. */ private VdsNetworkInterface createInterface(ResultSet rs) throws SQLException { VdsNetworkInterface iface; String macAddress = rs.getString("mac_addr"); Integer vlanId = (Integer) rs.getObject("vlan_id"); String baseInterface = rs.getString("base_interface"); Integer bondType = (Integer) rs.getObject("bond_type"); String bondName = rs.getString("bond_name"); Boolean isBond = (Boolean) rs.getObject("is_bond"); String bondOptions = rs.getString("bond_opts"); Integer speed = (Integer) rs.getObject("speed"); if (Boolean.TRUE.equals(isBond) && vlanId != null) { iface = new VdsNetworkInterface(); iface.setMacAddress(macAddress); iface.setVlanId(vlanId); iface.setBaseInterface(baseInterface); iface.setBondType(bondType); iface.setBondName(bondName); iface.setBonded(isBond); iface.setBondOptions(bondOptions); iface.setSpeed(speed); } else if (Boolean.TRUE.equals(isBond)) { Bond bond = new Bond(macAddress, bondOptions, bondType); String bondActiveSlave = rs.getString("bond_active_slave"); bond.setActiveSlave(bondActiveSlave); iface = bond; } else if (vlanId != null) { iface = new Vlan(vlanId, baseInterface); } else { iface = new Nic(macAddress, speed, bondName); } return iface; } }; private static final RowMapper<Pair<Guid, String>> hostNetworkNameMapper = (rs, rowNum) -> new Pair<>(getGuid(rs, "vds_id"), rs.getString("network_name")); private static class HostNetworkStatisticsRowMapper extends NetworkStatisticsRowMapper<VdsNetworkStatistics> { private static final HostNetworkStatisticsRowMapper INSTANCE = new HostNetworkStatisticsRowMapper(); @Override public VdsNetworkStatistics mapRow(ResultSet rs, int rowNum) throws SQLException { VdsNetworkStatistics entity = super.mapRow(rs, rowNum); entity.setVdsId(getGuidDefaultEmpty(rs, "vds_id")); return entity; } @Override protected VdsNetworkStatistics createEntity() { return new VdsNetworkStatistics(); } } }