/** * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. * * This software is licensed under the GNU General Public License v3 or later. * * It is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or any later version. * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package com.cloud.vm.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Date; import java.util.List; import javax.ejb.Local; import org.apache.log4j.Logger; import com.cloud.utils.db.Attribute; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.db.UpdateBuilder; import com.cloud.vm.State; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; @Local(value = { VMInstanceDao.class }) public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implements VMInstanceDao { public static final Logger s_logger = Logger.getLogger(VMInstanceDaoImpl.class.getName()); private static final String COUNT_ROUTERS_AND_PROXIES = "SELECT count(*) from `cloud`.`vm_instance` where host_id = ? AND type = 'DomainRouter'" + " UNION ALL" + " SELECT count(*) from `cloud`.`vm_instance` where host_id = ? AND type = 'ConsoleProxy'"; protected final SearchBuilder<VMInstanceVO> IdStatesSearch; protected final SearchBuilder<VMInstanceVO> HostSearch; protected final SearchBuilder<VMInstanceVO> LastHostSearch; protected final SearchBuilder<VMInstanceVO> ZoneSearch; protected final SearchBuilder<VMInstanceVO> ZoneTemplateNonExpungedSearch; protected final SearchBuilder<VMInstanceVO> NameLikeSearch; protected final SearchBuilder<VMInstanceVO> StateChangeSearch; protected final SearchBuilder<VMInstanceVO> TransitionSearch; protected final SearchBuilder<VMInstanceVO> TypesSearch; protected final SearchBuilder<VMInstanceVO> IdTypesSearch; protected final SearchBuilder<VMInstanceVO> HostIdTypesSearch; protected final SearchBuilder<VMInstanceVO> HostIdUpTypesSearch; protected final Attribute _updateTimeAttr; protected VMInstanceDaoImpl() { IdStatesSearch = createSearchBuilder(); IdStatesSearch.and("id", IdStatesSearch.entity().getId(), SearchCriteria.Op.EQ); IdStatesSearch.and("states", IdStatesSearch.entity().getState(), SearchCriteria.Op.IN); IdStatesSearch.done(); HostSearch = createSearchBuilder(); HostSearch.and("host", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostSearch.done(); LastHostSearch = createSearchBuilder(); LastHostSearch.and("lastHost", LastHostSearch.entity().getLastHostId(), SearchCriteria.Op.EQ); LastHostSearch.done(); ZoneSearch = createSearchBuilder(); ZoneSearch.and("zone", ZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneSearch.done(); ZoneTemplateNonExpungedSearch = createSearchBuilder(); ZoneTemplateNonExpungedSearch.and("zone", ZoneTemplateNonExpungedSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneTemplateNonExpungedSearch.and("template", ZoneTemplateNonExpungedSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); ZoneTemplateNonExpungedSearch.and("state", ZoneTemplateNonExpungedSearch.entity().getState(), SearchCriteria.Op.NEQ); ZoneTemplateNonExpungedSearch.done(); NameLikeSearch = createSearchBuilder(); NameLikeSearch.and("name", NameLikeSearch.entity().getName(), SearchCriteria.Op.LIKE); NameLikeSearch.done(); StateChangeSearch = createSearchBuilder(); StateChangeSearch.and("id", StateChangeSearch.entity().getId(), SearchCriteria.Op.EQ); StateChangeSearch.and("states", StateChangeSearch.entity().getState(), SearchCriteria.Op.EQ); StateChangeSearch.and("host", StateChangeSearch.entity().getHostId(), SearchCriteria.Op.EQ); StateChangeSearch.and("update", StateChangeSearch.entity().getUpdated(), SearchCriteria.Op.EQ); StateChangeSearch.done(); TransitionSearch = createSearchBuilder(); TransitionSearch.and("updateTime", TransitionSearch.entity().getUpdateTime(), SearchCriteria.Op.LT); TransitionSearch.and("states", TransitionSearch.entity().getState(), SearchCriteria.Op.IN); TransitionSearch.done(); TypesSearch = createSearchBuilder(); TypesSearch.and("types", TypesSearch.entity().getType(), SearchCriteria.Op.IN); TypesSearch.done(); IdTypesSearch = createSearchBuilder(); IdTypesSearch.and("id", IdTypesSearch.entity().getId(), SearchCriteria.Op.EQ); IdTypesSearch.and("types", IdTypesSearch.entity().getType(), SearchCriteria.Op.IN); IdTypesSearch.done(); HostIdTypesSearch = createSearchBuilder(); HostIdTypesSearch.and("hostid", HostIdTypesSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostIdTypesSearch.and("types", HostIdTypesSearch.entity().getType(), SearchCriteria.Op.IN); HostIdTypesSearch.done(); HostIdUpTypesSearch = createSearchBuilder(); HostIdUpTypesSearch.and("hostid", HostIdUpTypesSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostIdUpTypesSearch.and("types", HostIdUpTypesSearch.entity().getType(), SearchCriteria.Op.IN); HostIdUpTypesSearch.and("states", HostIdUpTypesSearch.entity().getState(), SearchCriteria.Op.NIN); HostIdUpTypesSearch.done(); _updateTimeAttr = _allAttributes.get("updateTime"); assert _updateTimeAttr != null : "Couldn't get this updateTime attribute"; } @Override public List<VMInstanceVO> findVMInstancesLike(String name) { SearchCriteria sc = NameLikeSearch.create(); sc.setParameters("name", "%" + name + "%"); return listActiveBy(sc); } @Override public boolean updateIf(VMInstanceVO vm, VirtualMachine.Event event, Long hostId) { State oldState = vm.getState(); State newState = oldState.getNextState(event); if (newState == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("There's no way to transition from old state: " + oldState.toString() + " event: " + event.toString()); } return false; } SearchCriteria sc = StateChangeSearch.create(); sc.setParameters("id", vm.getId()); sc.setParameters("states", oldState); sc.setParameters("host", vm.getHostId()); sc.setParameters("update", vm.getUpdated()); vm.incrUpdated(); UpdateBuilder ub = getUpdateBuilder(vm); ub.set(vm, "state", newState); ub.set(vm, "hostId", hostId); ub.set(vm, _updateTimeAttr, new Date()); int result = update(vm, sc); if (result == 0 && s_logger.isDebugEnabled()) { VMInstanceVO vo = findById(vm.getId()); StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append(vo.getUpdated()); str.append("} Stale Data: {Host=").append(vm.getHostId()).append("; State=").append(vm.getState().toString()).append("; updated=").append(vm.getUpdated()).append("}"); s_logger.debug(str.toString()); } return result > 0; } @Override public void updateVM(long id, String displayName, String group, boolean enable) { VMInstanceVO vo = createForUpdate(); vo.setDisplayName(displayName); vo.setGroup(group); vo.setHaEnabled(enable); update(id, vo); } @Override public List<VMInstanceVO> listByHostId(long hostid) { SearchCriteria sc = HostSearch.create(); sc.setParameters("host", hostid); return listActiveBy(sc); } @Override public List<VMInstanceVO> listByLastHostId(long hostId) { SearchCriteria sc = LastHostSearch.create(); sc.setParameters("lastHost", hostId); return listActiveBy(sc); } @Override public List<VMInstanceVO> listByZoneId(long zoneId) { SearchCriteria sc = ZoneSearch.create(); sc.setParameters("zone", zoneId); return listActiveBy(sc); } @Override public List<VMInstanceVO> listNonExpungedByZoneAndTemplate(long zoneId, long templateId) { SearchCriteria sc = ZoneTemplateNonExpungedSearch.create(); sc.setParameters("zone", zoneId); sc.setParameters("template", templateId); sc.setParameters("state", State.Expunging); return listActiveBy(sc); } @Override public List<VMInstanceVO> findVMInTransition(Date time, State... states) { SearchCriteria sc = TransitionSearch.create(); sc.setParameters("states", (Object[]) states); sc.setParameters("updateTime", time); return search(sc, null); } public Integer[] countRoutersAndProxies(Long hostId) { Transaction txn = Transaction.currentTxn(); PreparedStatement pstmt = null; Integer[] routerAndProxyCount = new Integer[] { null, null }; try { String sql = COUNT_ROUTERS_AND_PROXIES; pstmt = txn.prepareAutoCloseStatement(sql); pstmt.setLong(1, hostId); pstmt.setLong(2, hostId); ResultSet rs = pstmt.executeQuery(); int i = 0; while (rs.next()) { routerAndProxyCount[i++] = rs.getInt(1); } } catch (Exception e) { s_logger.warn("Exception searching for routers and proxies", e); } return routerAndProxyCount; } @Override public List<VMInstanceVO> listByHostIdTypes(long hostid, Type... types) { SearchCriteria sc = HostIdTypesSearch.create(); sc.setParameters("hostid", hostid); sc.setParameters("types", (Object[]) types); return listActiveBy(sc); } @Override public List<VMInstanceVO> listUpByHostIdTypes(long hostid, Type... types) { SearchCriteria sc = HostIdUpTypesSearch.create(); sc.setParameters("hostid", hostid); sc.setParameters("types", (Object[]) types); sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging}); return listActiveBy(sc); } @Override public List<VMInstanceVO> listByTypes(Type... types) { SearchCriteria sc = TypesSearch.create(); sc.setParameters("types", (Object[]) types); return listActiveBy(sc); } @Override public VMInstanceVO findByIdTypes(long id, Type... types) { SearchCriteria sc = IdTypesSearch.create(); sc.setParameters("id", id); sc.setParameters("types", (Object[]) types); return findOneBy(sc); } @Override public void updateProxyId(long id, Long proxyId, Date time) { VMInstanceVO vo = createForUpdate(); vo.setProxyId(proxyId); vo.setProxyAssignTime(time); update(id, vo); } }