// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.dc.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.naming.ConfigurationException; import org.springframework.stereotype.Component; import com.cloud.dc.AccountVlanMapVO; import com.cloud.dc.DomainVlanMapVO; import com.cloud.dc.PodVlanMapVO; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; import com.cloud.network.dao.IPAddressDao; import com.cloud.utils.Pair; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.exception.CloudRuntimeException; @Component public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements VlanDao { private final String FindZoneWideVlans = "SELECT * FROM vlan WHERE data_center_id=? and vlan_type=? and vlan_id!=? and id not in (select vlan_db_id from account_vlan_map)"; protected SearchBuilder<VlanVO> ZoneVlanIdSearch; protected SearchBuilder<VlanVO> ZoneSearch; protected SearchBuilder<VlanVO> ZoneTypeSearch; protected SearchBuilder<VlanVO> ZoneTypeAllPodsSearch; protected SearchBuilder<VlanVO> ZoneTypePodSearch; protected SearchBuilder<VlanVO> ZoneVlanSearch; protected SearchBuilder<VlanVO> NetworkVlanSearch; protected SearchBuilder<VlanVO> PhysicalNetworkVlanSearch; protected SearchBuilder<VlanVO> ZoneWideNonDedicatedVlanSearch; protected SearchBuilder<VlanVO> VlanGatewaysearch; protected SearchBuilder<VlanVO> DedicatedVlanSearch; protected SearchBuilder<AccountVlanMapVO> AccountVlanMapSearch; protected SearchBuilder<DomainVlanMapVO> DomainVlanMapSearch; @Inject protected PodVlanMapDao _podVlanMapDao; @Inject protected AccountVlanMapDao _accountVlanMapDao; @Inject protected DomainVlanMapDao _domainVlanMapDao; @Inject protected IPAddressDao _ipAddressDao; @Override public VlanVO findByZoneAndVlanId(long zoneId, String vlanId) { SearchCriteria<VlanVO> sc = ZoneVlanIdSearch.create(); sc.setParameters("zoneId", zoneId); sc.setParameters("vlanId", vlanId); return findOneBy(sc); } @Override public List<VlanVO> listByZone(long zoneId) { SearchCriteria<VlanVO> sc = ZoneSearch.create(); sc.setParameters("zoneId", zoneId); return listBy(sc); } public VlanDaoImpl() { ZoneVlanIdSearch = createSearchBuilder(); ZoneVlanIdSearch.and("zoneId", ZoneVlanIdSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneVlanIdSearch.and("vlanId", ZoneVlanIdSearch.entity().getVlanTag(), SearchCriteria.Op.EQ); ZoneVlanIdSearch.done(); ZoneSearch = createSearchBuilder(); ZoneSearch.and("zoneId", ZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneSearch.done(); ZoneTypeSearch = createSearchBuilder(); ZoneTypeSearch.and("zoneId", ZoneTypeSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneTypeSearch.and("vlanType", ZoneTypeSearch.entity().getVlanType(), SearchCriteria.Op.EQ); ZoneTypeSearch.done(); NetworkVlanSearch = createSearchBuilder(); NetworkVlanSearch.and("networkId", NetworkVlanSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); NetworkVlanSearch.done(); PhysicalNetworkVlanSearch = createSearchBuilder(); PhysicalNetworkVlanSearch.and("physicalNetworkId", PhysicalNetworkVlanSearch.entity().getPhysicalNetworkId(), SearchCriteria.Op.EQ); PhysicalNetworkVlanSearch.done(); VlanGatewaysearch = createSearchBuilder(); VlanGatewaysearch.and("gateway", VlanGatewaysearch.entity().getVlanGateway(), SearchCriteria.Op.EQ); VlanGatewaysearch.and("networkid", VlanGatewaysearch.entity().getNetworkId(), SearchCriteria.Op.EQ); VlanGatewaysearch.done(); } @Override public List<VlanVO> listZoneWideVlans(long zoneId, VlanType vlanType, String vlanId) { SearchCriteria<VlanVO> sc = ZoneVlanSearch.create(); sc.setParameters("zoneId", zoneId); sc.setParameters("vlanId", vlanId); sc.setParameters("vlanType", vlanType); return listBy(sc); } @Override public List<VlanVO> listByZoneAndType(long zoneId, VlanType vlanType) { SearchCriteria<VlanVO> sc = ZoneTypeSearch.create(); sc.setParameters("zoneId", zoneId); sc.setParameters("vlanType", vlanType); return listBy(sc); } @Override public List<VlanVO> listByType(VlanType vlanType) { SearchCriteria<VlanVO> sc = ZoneTypeSearch.create(); sc.setParameters("vlanType", vlanType); return listBy(sc); } @Override public List<VlanVO> listVlansForPod(long podId) { //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two List<PodVlanMapVO> vlanMaps = _podVlanMapDao.listPodVlanMapsByPod(podId); List<VlanVO> result = new ArrayList<VlanVO>(); for (PodVlanMapVO pvmvo : vlanMaps) { result.add(findById(pvmvo.getVlanDbId())); } return result; } @Override public List<VlanVO> listVlansForPodByType(long podId, VlanType vlanType) { //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two) List<PodVlanMapVO> vlanMaps = _podVlanMapDao.listPodVlanMapsByPod(podId); List<VlanVO> result = new ArrayList<VlanVO>(); for (PodVlanMapVO pvmvo : vlanMaps) { VlanVO vlan = findById(pvmvo.getVlanDbId()); if (vlan.getVlanType() == vlanType) { result.add(vlan); } } return result; } @Override public List<VlanVO> listVlansForAccountByType(Long zoneId, long accountId, VlanType vlanType) { //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two) List<AccountVlanMapVO> vlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId); List<VlanVO> result = new ArrayList<VlanVO>(); for (AccountVlanMapVO acvmvo : vlanMaps) { VlanVO vlan = findById(acvmvo.getVlanDbId()); if (vlan.getVlanType() == vlanType && (zoneId == null || vlan.getDataCenterId() == zoneId)) { result.add(vlan); } } return result; } @Override public void addToPod(long podId, long vlanDbId) { PodVlanMapVO pvmvo = new PodVlanMapVO(podId, vlanDbId); _podVlanMapDao.persist(pvmvo); } @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { boolean result = super.configure(name, params); ZoneTypeAllPodsSearch = createSearchBuilder(); ZoneTypeAllPodsSearch.and("zoneId", ZoneTypeAllPodsSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneTypeAllPodsSearch.and("vlanType", ZoneTypeAllPodsSearch.entity().getVlanType(), SearchCriteria.Op.EQ); SearchBuilder<PodVlanMapVO> PodVlanSearch = _podVlanMapDao.createSearchBuilder(); PodVlanSearch.and("podId", PodVlanSearch.entity().getPodId(), SearchCriteria.Op.NNULL); ZoneTypeAllPodsSearch.join("vlan", PodVlanSearch, PodVlanSearch.entity().getVlanDbId(), ZoneTypeAllPodsSearch.entity().getId(), JoinBuilder.JoinType.INNER); ZoneTypeAllPodsSearch.done(); PodVlanSearch.done(); ZoneTypePodSearch = createSearchBuilder(); ZoneTypePodSearch.and("zoneId", ZoneTypePodSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneTypePodSearch.and("vlanType", ZoneTypePodSearch.entity().getVlanType(), SearchCriteria.Op.EQ); SearchBuilder<PodVlanMapVO> PodVlanSearch2 = _podVlanMapDao.createSearchBuilder(); PodVlanSearch2.and("podId", PodVlanSearch2.entity().getPodId(), SearchCriteria.Op.EQ); ZoneTypePodSearch.join("vlan", PodVlanSearch2, PodVlanSearch2.entity().getVlanDbId(), ZoneTypePodSearch.entity().getId(), JoinBuilder.JoinType.INNER); PodVlanSearch2.done(); ZoneTypePodSearch.done(); ZoneWideNonDedicatedVlanSearch = createSearchBuilder(); ZoneWideNonDedicatedVlanSearch.and("zoneId", ZoneWideNonDedicatedVlanSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); AccountVlanMapSearch = _accountVlanMapDao.createSearchBuilder(); AccountVlanMapSearch.and("accountId", AccountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.NULL); ZoneWideNonDedicatedVlanSearch.join("AccountVlanMapSearch", AccountVlanMapSearch, ZoneWideNonDedicatedVlanSearch.entity().getId(), AccountVlanMapSearch.entity() .getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER); DomainVlanMapSearch = _domainVlanMapDao.createSearchBuilder(); DomainVlanMapSearch.and("domainId", DomainVlanMapSearch.entity().getDomainId(), SearchCriteria.Op.NULL); ZoneWideNonDedicatedVlanSearch.join("DomainVlanMapSearch", DomainVlanMapSearch, ZoneWideNonDedicatedVlanSearch.entity().getId(), DomainVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER); ZoneWideNonDedicatedVlanSearch.done(); AccountVlanMapSearch.done(); DomainVlanMapSearch.done(); DedicatedVlanSearch = createSearchBuilder(); AccountVlanMapSearch = _accountVlanMapDao.createSearchBuilder(); AccountVlanMapSearch.and("accountId", AccountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ); DedicatedVlanSearch.join("AccountVlanMapSearch", AccountVlanMapSearch, DedicatedVlanSearch.entity().getId(), AccountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER); DedicatedVlanSearch.done(); AccountVlanMapSearch.done(); return result; } private VlanVO findNextVlan(long zoneId, Vlan.VlanType vlanType) { List<VlanVO> allVlans = listByZoneAndType(zoneId, vlanType); List<VlanVO> emptyVlans = new ArrayList<VlanVO>(); List<VlanVO> fullVlans = new ArrayList<VlanVO>(); // Try to find a VLAN that is partially allocated for (VlanVO vlan : allVlans) { long vlanDbId = vlan.getId(); int countOfAllocatedIps = _ipAddressDao.countIPs(zoneId, vlanDbId, true); int countOfAllIps = _ipAddressDao.countIPs(zoneId, vlanDbId, false); if ((countOfAllocatedIps > 0) && (countOfAllocatedIps < countOfAllIps)) { return vlan; } else if (countOfAllocatedIps == 0) { emptyVlans.add(vlan); } else if (countOfAllocatedIps == countOfAllIps) { fullVlans.add(vlan); } } if (emptyVlans.isEmpty()) { return null; } // Try to find an empty VLAN with the same tag/subnet as a VLAN that is full for (VlanVO fullVlan : fullVlans) { for (VlanVO emptyVlan : emptyVlans) { if (fullVlan.getVlanTag().equals(emptyVlan.getVlanTag()) && fullVlan.getVlanGateway().equals(emptyVlan.getVlanGateway()) && fullVlan.getVlanNetmask().equals(emptyVlan.getVlanNetmask())) { return emptyVlan; } } } // Return a random empty VLAN return emptyVlans.get(0); } @Override public boolean zoneHasDirectAttachUntaggedVlans(long zoneId) { SearchCriteria<VlanVO> sc = ZoneTypeAllPodsSearch.create(); sc.setParameters("zoneId", zoneId); sc.setParameters("vlanType", VlanType.DirectAttached); return listIncludingRemovedBy(sc).size() > 0; } public Pair<String, VlanVO> assignPodDirectAttachIpAddress(long zoneId, long podId, long accountId, long domainId) { SearchCriteria<VlanVO> sc = ZoneTypePodSearch.create(); sc.setParameters("zoneId", zoneId); sc.setParameters("vlanType", VlanType.DirectAttached); sc.setJoinParameters("vlan", "podId", podId); VlanVO vlan = findOneIncludingRemovedBy(sc); if (vlan == null) { return null; } return null; // String ipAddress = _ipAddressDao.assignIpAddress(accountId, domainId, vlan.getId(), false).getAddress(); // if (ipAddress == null) { // return null; // } // return new Pair<String, VlanVO>(ipAddress, vlan); } @Override @DB public List<VlanVO> searchForZoneWideVlans(long dcId, String vlanType, String vlanId) { StringBuilder sql = new StringBuilder(FindZoneWideVlans); TransactionLegacy txn = TransactionLegacy.currentTxn(); List<VlanVO> zoneWideVlans = new ArrayList<VlanVO>(); try(PreparedStatement pstmt = txn.prepareStatement(sql.toString());){ if(pstmt != null) { pstmt.setLong(1, dcId); pstmt.setString(2, vlanType); pstmt.setString(3, vlanId); try(ResultSet rs = pstmt.executeQuery();) { while (rs.next()) { zoneWideVlans.add(toEntityBean(rs, false)); } }catch (SQLException e) { throw new CloudRuntimeException("searchForZoneWideVlans:Exception:" + e.getMessage(), e); } } return zoneWideVlans; } catch (SQLException e) { throw new CloudRuntimeException("searchForZoneWideVlans:Exception:" + e.getMessage(), e); } } @Override public List<VlanVO> listVlansByNetworkId(long networkId) { SearchCriteria<VlanVO> sc = NetworkVlanSearch.create(); sc.setParameters("networkId", networkId); return listBy(sc); } @Override public List<VlanVO> listVlansByNetworkIdIncludingRemoved(long networkId) { SearchCriteria<VlanVO> sc = NetworkVlanSearch.create(); sc.setParameters("networkId", networkId); return listIncludingRemovedBy(sc); } @Override public List<VlanVO> listVlansByNetworkIdAndGateway(long networkid, String gateway) { SearchCriteria<VlanVO> sc = VlanGatewaysearch.create(); sc.setParameters("networkid", networkid); sc.setParameters("gateway", gateway); return listBy(sc); } @Override public List<VlanVO> listVlansByPhysicalNetworkId(long physicalNetworkId) { SearchCriteria<VlanVO> sc = PhysicalNetworkVlanSearch.create(); sc.setParameters("physicalNetworkId", physicalNetworkId); return listBy(sc); } @Override public List<VlanVO> listZoneWideNonDedicatedVlans(long zoneId) { SearchCriteria<VlanVO> sc = ZoneWideNonDedicatedVlanSearch.create(); sc.setParameters("zoneId", zoneId); return listBy(sc); } @Override public List<VlanVO> listDedicatedVlans(long accountId) { SearchCriteria<VlanVO> sc = DedicatedVlanSearch.create(); sc.setJoinParameters("AccountVlanMapSearch", "accountId", accountId); return listBy(sc); } }