/**
* Abiquo community edition
* cloud management application for hybrid clouds
* Copyright (C) 2008-2010 - Abiquo Holdings S.L.
*
* This application is free software; you can redistribute it and/or
* modify it under the terms of the GNU LESSER GENERAL PUBLIC
* LICENSE as published by the Free Software Foundation under
* version 3 of the License
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* LESSER GENERAL PUBLIC LICENSE v.3 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package com.abiquo.server.core.infrastructure;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import com.abiquo.model.enumerator.MachineState;
import com.abiquo.server.core.common.persistence.DefaultDAOBase;
import com.softwarementors.bzngine.entities.PersistentEntity;
@Repository("jpaRackDAO")
/* package */class RackDAO extends DefaultDAOBase<Integer, Rack>
{
public RackDAO()
{
super(Rack.class);
}
public RackDAO(final EntityManager entityManager)
{
super(Rack.class, entityManager);
}
private static Criterion sameDatacenter(final Datacenter datacenter)
{
assert datacenter != null;
return Restrictions.eq(Rack.DATACENTER_PROPERTY, datacenter);
}
private static Criterion equalName(final String name)
{
assert !StringUtils.isEmpty(name);
return Restrictions.eq(Rack.NAME_PROPERTY, name);
}
public List<Rack> findRacks(final Datacenter datacenter)
{
return findRacks(datacenter, null);
}
private final static String QUERY_GET_FILTERED_RACKS = //
"SELECT r.idRack, r.idDataCenter, r.name, r.shortDescription, r.largeDescription, r.vlan_id_min, r.vlan_id_max, "
+ "r.vlans_id_avoided, r.vlan_per_vdc_expected, r.nrsq, r.haEnabled, r.version_c FROM " //
+ "rack r LEFT OUTER JOIN datacenter dc ON r.idDatacenter = dc.idDatacenter "
+ "WHERE dc.idDatacenter = :idDatacenter " //
+ "AND (r.name like :filter "
+ "OR r.idRack in (SELECT pms.idRack FROM physicalmachine pms LEFT OUTER JOIN enterprise ent ON pms.idEnterprise = ent.idEnterprise "
+ "WHERE ent.name like :filter OR pms.name like :filter ) " + ")";
public List<Rack> findRacks(final Datacenter datacenter, final String filter)
{
assert datacenter != null;
assert isManaged2(datacenter);
if (filter != null && !filter.isEmpty())
{
Query query = getSession().createSQLQuery(QUERY_GET_FILTERED_RACKS);
query.setParameter("idDatacenter", datacenter.getId());
query.setString("filter", "%" + filter + "%");
List<Rack> racks = getSQLQueryResults(getSession(), query, Rack.class, 0);
return racks;
}
Criteria criteria = createCriteria(sameDatacenter(datacenter));
criteria.addOrder(Order.asc(Rack.NAME_PROPERTY));
List<Rack> result = getResultList(criteria);
return result;
}
@SuppressWarnings("unchecked")
private <T> List<T> getSQLQueryResults(final Session session, final Query query,
final Class<T> objectClass, final int idFieldPosition)
{
List<T> result = new ArrayList<T>();
List<Object[]> sqlResult = query.list();
if (sqlResult != null && !sqlResult.isEmpty())
{
for (Object[] res : sqlResult)
{
T obj = (T) session.get(objectClass, (Integer) res[idFieldPosition]);
result.add(obj);
}
}
return result;
}
public List<Rack> findRacksWithHAEnabled(final Datacenter datacenter)
{
Criteria criteria = createCriteria(sameDatacenter(datacenter));
criteria.add(Restrictions.eq(Rack.HAENABLED_PROPERTY, true));
criteria.addOrder(Order.asc(Rack.NAME_PROPERTY));
List<Rack> result = getResultList(criteria);
return result;
}
public boolean existsAnyWithDatacenterAndName(final Datacenter datacenter, final String name)
{
assert datacenter != null;
assert !StringUtils.isEmpty(name);
return existsAnyByCriterions(sameDatacenter(datacenter), equalName(name));
}
public boolean existsAnyOtherWithDatacenterAndName(final Rack rack, final String name)
{
assert rack != null;
assert !StringUtils.isEmpty(name);
return existsAnyOtherByCriterions(rack, sameDatacenter(rack.getDatacenter()),
equalName(name));
}
private final static String SQL_RACK_IDS_BY_MIN_VLAN_COUNT = //
//
"SELECT rack_filtered_dc.idRack FROM "
+ //
"(SELECT r.idRack, r.idDatacenter, r.vlan_id_min, r.vlan_id_max, r.vlan_per_vdc_expected, r.nrsq, count(vn.id) as vlans_used "
+ //
"FROM rack r LEFT JOIN vlan_network_assignment vn ON r.idRack = vn.idRack GROUP BY r.idRack ) as rack_filtered_dc "
+ //
"WHERE rack_filtered_dc.idDataCenter = :idDatacenter AND rack_filtered_dc.vlans_used + rack_filtered_dc.vlan_per_vdc_expected + (((rack_filtered_dc.vlan_id_max - rack_filtered_dc.vlan_id_min +1 ) * (rack_filtered_dc.nrsq)) / 100) <= ((rack_filtered_dc.vlan_id_max - rack_filtered_dc.vlan_id_min) + 1) "
+ //
"ORDER BY rack_filtered_dc.vlans_used + rack_filtered_dc.vlan_per_vdc_expected ASC";
private final static String SQL_RACK_IDS_BY_MIN_VLAN_COUNT_LITE = //
//
"SELECT r.idRack " + //
"FROM rack r, virtualapp va, virtualdatacenter vdc, datacenter dc " + //
"WHERE va.idVirtualApp = :idVApp " + //
"AND vdc.idVirtualDataCenter = va.idVirtualDataCenter " + //
"AND vdc.idDataCenter = r.idDatacenter";//
/**
* Obtains the racks (prefiltered by target datacenter and virtualdatacenter) with minimal VLANS
* // and with vms deployed
*/
public List<Integer> getRackIdByMinVLANCount(final int idDatacenter)
{
SQLQuery query = getSession().createSQLQuery(SQL_RACK_IDS_BY_MIN_VLAN_COUNT);
query.setInteger("idDatacenter", idDatacenter);
return query.list();
}
private final static String COUNT_DEPLOYED_VLA = //
"SELECT COUNT(vn.id) " + //
"FROM NetworkAssignment vn WHERE " + //
"vn.rack.id = :idRack";
public Long getNumberOfDeployedVlanNetworks(final Integer rackId)
{
Query query = getSession().createQuery(COUNT_DEPLOYED_VLA);
query.setInteger("idRack", rackId);
Long numberOfDeployedNetworks = (Long) query.uniqueResult();
return numberOfDeployedNetworks;
}
/**
* Return the Rack by datacenter id and rack id.
*
* @param datacenterId
* @param rackId
* @return
*/
public Rack findByIds(final Integer datacenterId, final Integer rackId)
{
return findUniqueByCriterions(Restrictions.eq("datacenter.id", datacenterId), Restrictions
.eq(PersistentEntity.ID_PROPERTY, rackId));
}
private final static String HQL_NOT_MANAGED_RACKS_BY_DATACENTER = //
"SELECT nmr " + //
"FROM Rack nmr WHERE " + //
"nmr.datacenter.id = :idDatacenter and nmr.class = " + Rack.class.getName();
/**
* Returns all not managed racks.
*
* @param datacenter
* @return List<Rack>
*/
public List<Rack> findAllNotManagedRacksByDatacenter(final Integer datacenterId)
{
return findAllNotManagedRacksByDatacenter(datacenterId, null);
}
public List<Rack> findAllNotManagedRacksByDatacenter(final Integer datacenterId,
final String filter)
{
String hql = HQL_NOT_MANAGED_RACKS_BY_DATACENTER;
if (filter != null && !filter.isEmpty())
{
hql += " AND nmr.name like :filter";
}
Query q = getSession().createQuery(hql);
q.setInteger("idDatacenter", datacenterId);
if (filter != null && !filter.isEmpty())
{
q.setString("filter", "%" + filter + "%");
}
return q.list();
}
private final String QUERY_USED_VDRP = "SELECT vm.vdrpPort " + //
"FROM com.abiquo.server.core.cloud.VirtualMachine vm " + //
"WHERE vm.hypervisor.machine.rack = :rack ";
@SuppressWarnings("unchecked")
public List<Integer> findUsedVrdpPorts(final Rack rack)
{
Query query = getSession().createQuery(QUERY_USED_VDRP);
query.setParameter("rack", rack);
return query.list();
}
private final static String HQL_EMPTY_OFF_MACHINES_IN_RACK =
"select m from Machine m where m.rack.id = :rackId and m.state = "
+ MachineState.HALTED_FOR_SAVE.ordinal()
+ " order by (case when exists (select n from Hypervisor n where n.machine = m) then 0 else 1 end)";
private final static String HQL_EMPTY_ON_MACHINES_IN_RACK =
"select m from Machine m where m.rack.id = :rackId and m.state = "
+ MachineState.MANAGED.ordinal()
+ " and not exists (select vm from VirtualMachine vm where vm.hypervisor.machine = m)";
/**
* Return all machines in a rack that are empty of VM and powered off.
*
* @param rackId rack.
* @return Integer
*/
public Integer getEmptyOffMachines(final Integer rackId)
{
Query q =
getSession().createQuery(HQL_EMPTY_OFF_MACHINES_IN_RACK).setInteger("rackId", rackId);
return q.list().size();
}
/**
* Return all machines in a rack that are empty of VM.
*
* @param rackId rack.
* @return Integer
*/
public Integer getEmptyOnMachines(final Integer rackId)
{
Query q =
getSession().createQuery(HQL_EMPTY_ON_MACHINES_IN_RACK).setInteger("rackId", rackId);
return q.list().size();
}
/**
* Returns any machine that is in the rack in HALTED_FOR_SAVE. If howMany <= 0 an empty list is
* returned.
*
* @param rackId rack.
* @return Machine
*/
public List<Machine> getRandomMachinesToStartFromRack(final Integer rackId,
final Integer howMany)
{
if (howMany <= 0)
{
return new ArrayList<Machine>();
}
Query q =
getSession().createQuery(HQL_EMPTY_OFF_MACHINES_IN_RACK).setInteger("rackId", rackId);
List<Machine> machines = q.setMaxResults(howMany).list();
return machines;
}
/**
* Returns any machine that is in the rack in MANAGED. If howMany <= 0 an empty list is
* returned.
*
* @param rackId rack.
* @return Machine
*/
public List<Machine> getRandomMachinesToShutDownFromRack(final Integer rackId,
final Integer howMany)
{
if (howMany <= 0)
{
return new ArrayList<Machine>();
}
Query q =
getSession().createQuery(HQL_EMPTY_ON_MACHINES_IN_RACK).setInteger("rackId", rackId);
List<Machine> machines = q.setMaxResults(howMany).list();
return machines;
}
/**
* Returns all machine that is in the rack in MANAGED.
*
* @param rackId rack.
* @return Machine
*/
public List<Machine> getAllMachinesToShutDownFromRack(final Integer rackId)
{
Query q =
getSession().createQuery(HQL_EMPTY_ON_MACHINES_IN_RACK).setInteger("rackId", rackId);
return q.list();
}
}