/** * 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(); } }