/**
* 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.storage;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import com.abiquo.model.enumerator.StorageTechnologyType;
import com.abiquo.model.enumerator.VolumeState;
import com.abiquo.server.core.cloud.VirtualAppliance;
import com.abiquo.server.core.cloud.VirtualDatacenter;
import com.abiquo.server.core.cloud.VirtualMachine;
import com.abiquo.server.core.common.persistence.DefaultDAOBase;
import com.abiquo.server.core.infrastructure.management.Rasd;
import com.abiquo.server.core.infrastructure.management.RasdManagement;
import com.abiquo.server.core.util.FilterOptions;
import com.abiquo.server.core.util.PagedList;
import com.softwarementors.bzngine.entities.PersistentEntity;
@Repository("jpaVolumeManagementDAO")
/* package */class VolumeManagementDAO extends DefaultDAOBase<Integer, VolumeManagement>
{
public VolumeManagementDAO()
{
super(VolumeManagement.class);
}
public VolumeManagementDAO(final EntityManager entityManager)
{
super(VolumeManagement.class, entityManager);
}
/**
* HQL does not support UNION, but since Volume_management is only related to the Enterprise via
* the VirtualDataCenter, two queries are needed: - First one retrieves all volumes assigned to
* any VirtualDataCenter of the specified Enterprise; - Second one retrieves all volumes of a
* stateful image that is not in use (does not have a VirtualDataCenter) filtering by the
* enterprise of the stateful image.
**/
private final String SQL_VOLUME_MANAGEMENT_GET_VOLUMES_FROM_ENTERPRISE =
"select volman.idManagement as idman, vdc.name as vdcname, virtualapp.name as vaname, "
+ "virtualmachine.name as vmname, rasd.limitResource as size, "
+ "rasd.reservation as available, volman.usedSize as used, "
+ "rasd.elementName as elementname, volman.state as state, tier.name as tier "
+ "from (volume_management volman, virtualdatacenter vdc, rasd, rasd_management rasdm) "
+ "left join virtualmachine on rasdm.idVM = virtualmachine.idVM "
+ "left join virtualapp on rasdm.idVirtualApp = virtualapp.idVirtualApp "
+ "left join storage_pool on volman.idStorage = storage_pool.idStorage "
+ "left join tier on storage_pool.idTier = tier.id "
+ "where "
+ "volman.idManagement = rasdm.idManagement "
+ "and rasdm.idResource = rasd.instanceID "
+ "and rasdm.idVirtualDataCenter = vdc.idVirtualDataCenter "
+ "and vdc.idEnterprise = :idEnterprise "
+ "and ( "
+ "rasd.elementName like :filterLike "
+ "or virtualmachine.name like :filterLike "
+ "or virtualapp.name like :filterLike "
+ "or vdc.name like :filterLike "
+ "or tier.name like :filterLike "
+ ") "
+ "union "
+ "select volman.idManagement as idman, '' as vdcname, '' as vaname, '' as vmname, "
+ "rasd.limitResource as size, rasd.reservation as available, volman.usedSize as used, "
+ "rasd.elementName as elementname, volman.state as state, tier.name as tier "
+ "from (volume_management volman, virtualimage vi, rasd, rasd_management rasdm) "
+ "left join storage_pool on volman.idStorage = storage_pool.idStorage "
+ "left join tier on storage_pool.idTier = tier.id " + "where "
+ "volman.idImage = vi.idImage " + "and volman.idManagement = rasdm.idManagement "
+ "and rasdm.idResource = rasd.instanceID " + "and rasdm.idVirtualDataCenter is null "
+ "and rasdm.idVirtualApp is null " + "and rasdm.idVM is null "
+ "and vi.idEnterprise = :idEnterprise " + "and (rasd.elementName like :filterLike "
+ "or tier.name like :filterLike )";
public List<VolumeManagement> getVolumesByPool(final StoragePool sp)
{
Criteria criteria = createCriteria(samePool(sp));
return getResultList(criteria);
}
public List<VolumeManagement> getVolumesByVirtualDatacenter(final VirtualDatacenter vdc)
{
Criteria criteria = createCriteria(sameVirtualDatacenter(vdc));
return getResultList(criteria);
}
public VolumeManagement getVolumeByVirtualDatacenter(final VirtualDatacenter vdc,
final Integer volumeId)
{
Criteria criteria = createCriteria(sameId(volumeId), sameVirtualDatacenter(vdc));
return getSingleResultOrNull(criteria);
}
public List<VolumeManagement> getStatefulCandidates(final VirtualDatacenter vdc)
{
// Filters on the VolumeManagement entity
Criteria crit = createCriteria();
crit.createAlias(VolumeManagement.STORAGE_POOL_PROPERTY, "pool");
crit.createAlias("pool." + StoragePool.DEVICE_PROPERTY, "device");
crit.add(sameVirtualDatacenter(vdc));
crit.add(Restrictions.isNull(VolumeManagement.VIRTUAL_MACHINE_TEMPLATE_PROPERTY));
crit.add(Restrictions.eq(VolumeManagement.STATE_PROPERTY, VolumeState.DETACHED));
crit.add(Restrictions.eq("device." + StorageDevice.STORAGE_TECHNOLOGY_PROPERTY,
StorageTechnologyType.GENERIC_ISCSI));
return getResultList(crit);
}
public List<VolumeManagement> getVolumesFromEnterprise(final Integer idEnterprise)
{
Query query =
getSession().createSQLQuery(SQL_VOLUME_MANAGEMENT_GET_VOLUMES_FROM_ENTERPRISE);
query.setParameter("idEnterprise", idEnterprise);
query.setParameter("filterLike", "%");
return getSQLQueryResults(getSession(), query, VolumeManagement.class, 0);
}
@SuppressWarnings("unchecked")
public List<VolumeManagement> getVolumesByPool(final StoragePool sp, final FilterOptions filters)
{
// Check if the orderBy element is actually one of the available ones
VolumeManagement.OrderByEnum orderByEnum =
VolumeManagement.OrderByEnum.valueOf(filters.getOrderBy().toUpperCase());
String orderBy = defineOrderBy(orderByEnum.getColumnHQL(), filters.getAsc());
Query query = getSession().getNamedQuery(VolumeManagement.VOLUMES_BY_POOL);
String req = query.getQueryString() + orderBy;
// Add order filter to the query
Query queryWithOrder = getSession().createQuery(req);
queryWithOrder.setString("poolId", sp.getId());
queryWithOrder.setString("filterLike",
filters.getFilter().isEmpty() ? "%" : "%" + filters.getFilter() + "%");
Integer size = queryWithOrder.list().size();
queryWithOrder.setFirstResult(filters.getStartwith());
queryWithOrder.setMaxResults(filters.getLimit());
PagedList<VolumeManagement> volumesList =
new PagedList<VolumeManagement>(queryWithOrder.list());
volumesList.setTotalResults(size);
volumesList.setPageSize(filters.getLimit() > size ? size : filters.getLimit());
volumesList.setCurrentElement(filters.getStartwith());
return volumesList;
}
@SuppressWarnings("unchecked")
public List<VolumeManagement> getVolumesByVirtualDatacenter(final VirtualDatacenter vdc,
final FilterOptions filters)
{
// Check if the orderBy element is actually one of the available ones
VolumeManagement.OrderByEnum orderByEnum =
VolumeManagement.OrderByEnum.valueOf(filters.getOrderBy().toUpperCase());
String orderBy = defineOrderBy(orderByEnum.getColumnHQL(), filters.getAsc());
Query query = getSession().getNamedQuery(VolumeManagement.VOLUMES_BY_VDC);
String req = query.getQueryString() + orderBy;
// Add order filter to the query
Query queryWithOrder = getSession().createQuery(req);
queryWithOrder.setInteger("vdcId", vdc.getId());
queryWithOrder.setString("filterLike",
filters.getFilter().isEmpty() ? "%" : "%" + filters.getFilter() + "%");
Integer size = queryWithOrder.list().size();
queryWithOrder.setFirstResult(filters.getStartwith());
queryWithOrder.setMaxResults(filters.getLimit());
PagedList<VolumeManagement> volumesList =
new PagedList<VolumeManagement>(queryWithOrder.list());
volumesList.setTotalResults(size);
volumesList.setPageSize(filters.getLimit() > size ? size : filters.getLimit());
volumesList.setCurrentElement(filters.getStartwith());
return volumesList;
}
public List<VolumeManagement> getVolumesByEnterprise(final Integer id,
final FilterOptions filters)
{
// Check if the orderBy element is actually one of the available ones
VolumeManagement.OrderByEnum orderByEnum =
VolumeManagement.OrderByEnum.valueOf(filters.getOrderBy().toUpperCase());
Query query =
getSession().createSQLQuery(
SQL_VOLUME_MANAGEMENT_GET_VOLUMES_FROM_ENTERPRISE
+ defineOrderBy(orderByEnum.getColumnSQL(), filters.getAsc()));
query.setParameter("idEnterprise", id);
query.setParameter("filterLike",
filters.getFilter().isEmpty() ? "%" : "%" + filters.getFilter() + "%");
Integer size = getSQLQueryResults(getSession(), query, VolumeManagement.class, 0).size();
query.setFirstResult(filters.getStartwith());
query.setMaxResults(filters.getLimit());
PagedList<VolumeManagement> volumes =
new PagedList<VolumeManagement>(getSQLQueryResults(getSession(), query,
VolumeManagement.class, 0));
volumes.setTotalResults(size);
volumes.setPageSize(filters.getLimit() > size ? size : filters.getLimit());
volumes.setCurrentElement(filters.getStartwith());
return volumes;
}
@SuppressWarnings("unchecked")
public List<VolumeManagement> getAvailableVolumes(final VirtualDatacenter vdc,
final FilterOptions filters)
{
// Check if the orderBy element is actually one of the available ones
VolumeManagement.OrderByEnum orderByEnum =
VolumeManagement.OrderByEnum.valueOf(filters.getOrderBy().toUpperCase());
String orderBy = defineOrderBy(orderByEnum.getColumnHQL(), filters.getAsc());
Query query = getSession().getNamedQuery(VolumeManagement.VOLUMES_AVAILABLES);
String req = query.getQueryString() + orderBy;
// Add order filter to the query
Query queryWithOrder = getSession().createQuery(req);
queryWithOrder.setInteger("vdcId", vdc.getId());
queryWithOrder.setString("filterLike",
filters.getFilter().isEmpty() ? "%" : "%" + filters.getFilter() + "%");
Integer size = queryWithOrder.list().size();
// Limit 0 means no size filter
if (filters.getLimit() == 0)
{
filters.setLimit(size);
filters.setStartwith(0);
}
queryWithOrder.setFirstResult(filters.getStartwith());
queryWithOrder.setMaxResults(filters.getLimit());
PagedList<VolumeManagement> volumesList =
new PagedList<VolumeManagement>(queryWithOrder.list());
volumesList.setTotalResults(size);
volumesList.setPageSize(filters.getLimit() > size ? size : filters.getLimit());
volumesList.setCurrentElement(filters.getStartwith());
return volumesList;
}
public VolumeManagement getVolumeFromImage(final Integer idImage)
{
Criteria criteria =
createCriteria(
Restrictions.eq(VolumeManagement.VIRTUAL_MACHINE_TEMPLATE_PROPERTY + "."
+ PersistentEntity.ID_PROPERTY, idImage),
Restrictions.isNull(RasdManagement.TEMPORAL_PROPERTY));
Object obj = criteria.uniqueResult();
return (VolumeManagement) obj;
}
@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;
}
private String defineOrderBy(final String orderBy, final Boolean asc)
{
StringBuilder queryString = new StringBuilder();
queryString.append(" order by ");
if (orderBy.equalsIgnoreCase("vol.id"))
{
queryString.append("vol.rasd.id");
}
else
{
queryString.append(orderBy);
}
queryString.append(" ");
if (asc)
{
queryString.append("asc");
}
else
{
queryString.append("desc");
}
return queryString.toString();
}
private static Criterion sameVirtualDatacenter(final VirtualDatacenter vdc)
{
return Restrictions.eq(RasdManagement.VIRTUAL_DATACENTER_PROPERTY, vdc);
}
private static Criterion samePool(final StoragePool pool)
{
return Restrictions.eq(VolumeManagement.STORAGE_POOL_PROPERTY, pool);
}
private static Criterion sameId(final Integer id)
{
return Restrictions.eq(PersistentEntity.ID_PROPERTY, id);
}
@Deprecated
// use vm.getVolumes
public List<VolumeManagement> getVolumesByVirtualMachine(final VirtualMachine vm)
{
Criteria criteria = createCriteria(sameVirtualMachine(vm), sameState(VolumeState.ATTACHED));
return getResultList(criteria);
}
public List<VolumeManagement> getVolumesByVirtualMachine(final VirtualMachine vm,
final FilterOptions filters)
{
if (filters != null)
{
// Check if the orderBy element is actually one of the available ones
VolumeManagement.OrderByEnum orderByEnum =
VolumeManagement.OrderByEnum.valueOf(filters.getOrderBy().toUpperCase());
String orderBy = defineOrderBy(orderByEnum.getColumnHQL(), filters.getAsc());
Query query = getSession().getNamedQuery(VolumeManagement.VOLUMES_ATTACHED_TO_VM);
String req = query.getQueryString() + orderBy;
// Add order filter to the query
Query queryWithOrder = getSession().createQuery(req);
queryWithOrder.setInteger("vmId", vm.getId());
queryWithOrder.setParameter("state", VolumeState.ATTACHED);
queryWithOrder.setString("filterLike", filters.getFilter().isEmpty() ? "%" : "%"
+ filters.getFilter() + "%");
Integer size = queryWithOrder.list().size();
queryWithOrder.setFirstResult(filters.getStartwith());
queryWithOrder.setMaxResults(filters.getLimit());
PagedList<VolumeManagement> volumesList =
new PagedList<VolumeManagement>(queryWithOrder.list());
volumesList.setTotalResults(size);
volumesList.setPageSize(filters.getLimit() > size ? size : filters.getLimit());
volumesList.setCurrentElement(filters.getStartwith());
return volumesList;
}
else
{
Criteria criteria =
createCriteria(sameVirtualMachine(vm), sameState(VolumeState.ATTACHED));
return getResultList(criteria);
}
}
public List<VolumeManagement> getAttachedVolumes(final VirtualDatacenter vdc)
{
Criteria criteria =
createCriteria(sameVirtualDatacenter(vdc), sameState(VolumeState.ATTACHED));
return getResultList(criteria);
}
public List<VolumeManagement> getDetachedVolumes(final VirtualDatacenter vdc)
{
Criteria criteria =
createCriteria(sameVirtualDatacenter(vdc), sameState(VolumeState.DETACHED));
return getResultList(criteria);
}
private static Criterion sameVirtualMachine(final VirtualMachine vm)
{
return Restrictions.eq(RasdManagement.VIRTUAL_MACHINE_PROPERTY + ".id", vm.getId());
}
private static Criterion sameState(final VolumeState state)
{
return Restrictions.eq(VolumeManagement.STATE_PROPERTY, state);
}
public List<VolumeManagement> getVolumesByVirtualAppliance(final VirtualAppliance vapp)
{
Query query = getSession().createQuery(VolumeManagement.BY_VAPP);
query.setInteger("vappId", vapp.getId());
return query.list();
}
}