blob: 2737beb03b452ed97306c570e3763e8e23d0e4e5 [file] [log] [blame]
// 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;
import com.cloud.utils.net.NetUtils;
@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);
}
/**
* Returns a vlan by the network id and if the given IPv4 is in the network IP range.
*/
@Override
public VlanVO findByNetworkIdAndIpv4(long networkId, String ipv4Address) {
List<VlanVO> vlanVoList = listVlansByNetworkId(networkId);
for (VlanVO vlan : vlanVoList) {
String ipRange = vlan.getIpRange();
String[] ipRangeParts = ipRange.split("-");
String startIP = ipRangeParts[0];
String endIP = ipRangeParts[1];
if (NetUtils.isIpInRange(ipv4Address, startIP, endIP)) {
return vlan;
}
}
return null;
}
@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);
}
}