Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 3B3751036C for ; Tue, 7 May 2013 22:01:36 +0000 (UTC) Received: (qmail 56972 invoked by uid 500); 7 May 2013 22:01:20 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 56898 invoked by uid 500); 7 May 2013 22:01:20 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 55654 invoked by uid 99); 7 May 2013 22:01:19 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 May 2013 22:01:19 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 868E9888EE5; Tue, 7 May 2013 22:01:18 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: alena1108@apache.org To: commits@cloudstack.apache.org Date: Tue, 07 May 2013 22:01:49 -0000 Message-Id: <11b538554fb94d409e618b6e5a3bf15d@git.apache.org> In-Reply-To: <3e79178248384d298e6dc53296a07b1f@git.apache.org> References: <3e79178248384d298e6dc53296a07b1f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [33/72] [abbrv] [partial] Moved most of the VOs and DAOs from server package into engine-schema as well http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java new file mode 100644 index 0000000..5f212eb --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java @@ -0,0 +1,304 @@ +// 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.storage.dao; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.UpdateBuilder; + +@Component +@Local(value={VMTemplatePoolDao.class}) +public class VMTemplatePoolDaoImpl extends GenericDaoBase implements VMTemplatePoolDao { + public static final Logger s_logger = Logger.getLogger(VMTemplatePoolDaoImpl.class.getName()); + + protected final SearchBuilder PoolSearch; + protected final SearchBuilder TemplateSearch; + protected final SearchBuilder PoolTemplateSearch; + protected final SearchBuilder TemplateStatusSearch; + protected final SearchBuilder TemplatePoolStatusSearch; + protected final SearchBuilder TemplateStatesSearch; + protected final SearchBuilder updateStateSearch; + + protected static final String UPDATE_TEMPLATE_HOST_REF = + "UPDATE template_spool_ref SET download_state = ?, download_pct= ?, last_updated = ? " + + ", error_str = ?, local_path = ?, job_id = ? " + + "WHERE pool_id = ? and template_id = ?"; + + protected static final String DOWNLOADS_STATE_DC= + "SELECT * FROM template_spool_ref t, storage_pool p where t.pool_id = p.id and p.data_center_id=? " + + " and t.template_id=? and t.download_state = ?" ; + + protected static final String DOWNLOADS_STATE_DC_POD= + "SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.data_center_id=? and h.pod_id=? " + + " and tp.template_id=? and tp.download_state=?" ; + + protected static final String HOST_TEMPLATE_SEARCH= + "SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.id=? " + + " and tp.template_id=? " ; + + + public VMTemplatePoolDaoImpl () { + PoolSearch = createSearchBuilder(); + PoolSearch.and("pool_id", PoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + PoolSearch.done(); + + TemplateSearch = createSearchBuilder(); + TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateSearch.done(); + + PoolTemplateSearch = createSearchBuilder(); + PoolTemplateSearch.and("pool_id", PoolTemplateSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + PoolTemplateSearch.and("template_id", PoolTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + PoolTemplateSearch.done(); + + TemplateStatusSearch = createSearchBuilder(); + TemplateStatusSearch.and("template_id", TemplateStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateStatusSearch.and("download_state", TemplateStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ); + TemplateStatusSearch.done(); + + TemplatePoolStatusSearch = createSearchBuilder(); + TemplatePoolStatusSearch.and("pool_id", TemplatePoolStatusSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + TemplatePoolStatusSearch.and("template_id", TemplatePoolStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplatePoolStatusSearch.and("download_state", TemplatePoolStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ); + TemplatePoolStatusSearch.done(); + + TemplateStatesSearch = createSearchBuilder(); + TemplateStatesSearch.and("template_id", TemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateStatesSearch.and("states", TemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.IN); + TemplateStatesSearch.done(); + + updateStateSearch = this.createSearchBuilder(); + updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); + updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); + updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); + updateStateSearch.done(); + } + + @Override + public List listByPoolId(long id) { + SearchCriteria sc = PoolSearch.create(); + sc.setParameters("pool_id", id); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateId(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("template_id", templateId); + return listIncludingRemovedBy(sc); + } + + @Override + public VMTemplateStoragePoolVO findByPoolTemplate(long hostId, long templateId) { + SearchCriteria sc = PoolTemplateSearch.create(); + sc.setParameters("pool_id", hostId); + sc.setParameters("template_id", templateId); + return findOneIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState) { + SearchCriteria sc = TemplateStatusSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("download_state", downloadState.toString()); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId) { + SearchCriteria sc = TemplatePoolStatusSearch.create(); + sc.setParameters("pool_id", poolId); + sc.setParameters("template_id", templateId); + sc.setParameters("download_state", downloadState.toString()); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateStatus(long templateId, long datacenterId, VMTemplateStoragePoolVO.Status downloadState) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + List result = new ArrayList(); + try { + String sql = DOWNLOADS_STATE_DC; + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, datacenterId); + pstmt.setLong(2, templateId); + pstmt.setString(3, downloadState.toString()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + result.add(toEntityBean(rs, false)); + } + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } + return result; + + } + + @Override + public List listByTemplateStatus(long templateId, long datacenterId, long podId, VMTemplateStoragePoolVO.Status downloadState) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + List result = new ArrayList(); + ResultSet rs = null; + try { + String sql = DOWNLOADS_STATE_DC_POD; + pstmt = txn.prepareStatement(sql); + + pstmt.setLong(1, datacenterId); + pstmt.setLong(2, podId); + pstmt.setLong(3, templateId); + pstmt.setString(4, downloadState.toString()); + rs = pstmt.executeQuery(); + while (rs.next()) { + // result.add(toEntityBean(rs, false)); TODO: this is buggy in GenericDaoBase for hand constructed queries + long id = rs.getLong(1); //ID column + result.add(findById(id)); + } + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + return result; + + } + + public List listByHostTemplate(long hostId, long templateId) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + List result = new ArrayList(); + ResultSet rs = null; + try { + String sql = HOST_TEMPLATE_SEARCH; + pstmt = txn.prepareStatement(sql); + + pstmt.setLong(1, hostId); + pstmt.setLong(2, templateId); + rs = pstmt.executeQuery(); + while (rs.next()) { + // result.add(toEntityBean(rs, false)); TODO: this is buggy in GenericDaoBase for hand constructed queries + long id = rs.getLong(1); //ID column + result.add(findById(id)); + } + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + return result; + + } + + @Override + public boolean templateAvailable(long templateId, long hostId) { + VMTemplateStorageResourceAssoc tmpltPool = findByPoolTemplate(hostId, templateId); + if (tmpltPool == null) + return false; + + return tmpltPool.getDownloadState()==Status.DOWNLOADED; + } + + @Override + public List listByTemplateStates(long templateId, VMTemplateStoragePoolVO.Status... states) { + SearchCriteria sc = TemplateStatesSearch.create(); + sc.setParameters("states", (Object[])states); + sc.setParameters("template_id", templateId); + + return search(sc, null); + } + + @Override + public VMTemplateStoragePoolVO findByHostTemplate(Long hostId, Long templateId) { + List result = listByHostTemplate(hostId, templateId); + return (result.size() == 0)?null:result.get(1); + } + + @Override + public boolean updateState(State currentState, Event event, + State nextState, DataObjectInStore vo, Object data) { + VMTemplateStoragePoolVO templatePool = (VMTemplateStoragePoolVO)vo; + Long oldUpdated = templatePool.getUpdatedCount(); + Date oldUpdatedTime = templatePool.getUpdated(); + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", templatePool.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", templatePool.getUpdatedCount()); + + templatePool.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(vo); + builder.set(vo, "state", nextState); + builder.set(vo, "updated", new Date()); + + int rows = update((VMTemplateStoragePoolVO) vo, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VMTemplateStoragePoolVO dbVol = findByIdIncludingRemoved(templatePool.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + .append(dbVol.getUpdated()); + str.append(": New Data={id=").append(templatePool.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(templatePool.getUpdatedCount()) + .append("; updatedTime=").append(templatePool.getUpdated()); + str.append(": stale Data={id=").append(templatePool.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update objectIndatastore: id=" + templatePool.getId() + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VMTemplateS3Dao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateS3Dao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateS3Dao.java new file mode 100644 index 0000000..d36fb3a --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateS3Dao.java @@ -0,0 +1,36 @@ +/* + * 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.storage.dao; + +import com.cloud.storage.VMTemplateS3VO; +import com.cloud.utils.db.GenericDao; + +import java.util.List; + +public interface VMTemplateS3Dao extends GenericDao { + + List listByS3Id(long id); + + VMTemplateS3VO findOneByTemplateId(long id); + + VMTemplateS3VO findOneByS3Template(long s3Id, long templateId); + + void expungeAllByTemplateId(long templateId); + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java new file mode 100644 index 0000000..7cfd3b5 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java @@ -0,0 +1,105 @@ +/* + * 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.storage.dao; + +import static com.cloud.utils.db.SearchCriteria.Op.*; +import static com.cloud.storage.VMTemplateS3VO.*; + +import com.cloud.storage.VMTemplateS3VO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@Local(VMTemplateS3Dao.class) +public class VMTemplateS3DaoImpl extends GenericDaoBase + implements VMTemplateS3Dao { + + private final SearchBuilder searchBuilder; + + public VMTemplateS3DaoImpl() { + + super(); + + this.searchBuilder = createSearchBuilder(); + this.searchBuilder + .and(S3_ID_COLUMN_NAME, this.searchBuilder.entity().getS3Id(), + EQ) + .and(TEMPLATE_ID_COLUMN_NAME, + this.searchBuilder.entity().getTemplateId(), EQ).done(); + + } + + @Override + public List listByS3Id(final long s3id) { + + final SearchCriteria criteria = this.searchBuilder + .create(); + + criteria.setParameters(S3_ID_COLUMN_NAME, s3id); + + return this.listBy(criteria); + + } + + @Override + public VMTemplateS3VO findOneByTemplateId(final long templateId) { + + final SearchCriteria criteria = this.searchBuilder + .create(); + + criteria.setParameters(TEMPLATE_ID_COLUMN_NAME, templateId); + + return this.findOneBy(criteria); + + } + + @Override + public VMTemplateS3VO findOneByS3Template(final long s3Id, + final long templateId) { + + final SearchCriteria criteria = this.searchBuilder + .create(); + + criteria.setParameters(S3_ID_COLUMN_NAME, s3Id); + criteria.setParameters(TEMPLATE_ID_COLUMN_NAME, templateId); + + return this.findOneBy(criteria); + + } + + @Override + public void expungeAllByTemplateId(long templateId) { + + final SearchCriteria criteria = this.searchBuilder + .create(); + + criteria.setParameters(TEMPLATE_ID_COLUMN_NAME, templateId); + + this.expunge(criteria); + + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDao.java new file mode 100755 index 0000000..ec18189 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDao.java @@ -0,0 +1,37 @@ +// 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.storage.dao; + +import java.util.List; + +import com.cloud.storage.VMTemplateSwiftVO; +import com.cloud.utils.db.GenericDao; + +/** + * + * + */ + +public interface VMTemplateSwiftDao extends GenericDao { + List listBySwiftId(long id); + + List listByTemplateId(long templateId); + + VMTemplateSwiftVO findBySwiftTemplate(long swiftId, long templateId); + + VMTemplateSwiftVO findOneByTemplateId(long templateId); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDaoImpl.java new file mode 100755 index 0000000..c65527a --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateSwiftDaoImpl.java @@ -0,0 +1,87 @@ +// 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.storage.dao; + +import java.util.Collections; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.storage.VMTemplateSwiftVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +/** + * + * + */ + +@Component +@Local(value = { VMTemplateSwiftDao.class }) +public class VMTemplateSwiftDaoImpl extends GenericDaoBase implements VMTemplateSwiftDao { + public static final Logger s_logger = Logger.getLogger(VMTemplateSwiftDaoImpl.class.getName()); + + protected final SearchBuilder AllFieldSearch; + + public VMTemplateSwiftDaoImpl() { + AllFieldSearch = createSearchBuilder(); + AllFieldSearch.and("swift_id", AllFieldSearch.entity().getSwiftId(), SearchCriteria.Op.EQ); + AllFieldSearch.and("template_id", AllFieldSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + AllFieldSearch.done(); + + } + + @Override + public List listBySwiftId(long id) { + SearchCriteria sc = AllFieldSearch.create(); + sc.setParameters("swift_id", id); + return listBy(sc); + } + + @Override + public List listByTemplateId(long templateId) { + SearchCriteria sc = AllFieldSearch.create(); + sc.setParameters("template_id", templateId); + return listBy(sc); + } + + @Override + public VMTemplateSwiftVO findOneByTemplateId(long templateId) { + SearchCriteria sc = AllFieldSearch.create(); + sc.setParameters("template_id", templateId); + List list = listBy(sc); + if (list == null || list.size() < 1) { + return null; + } else { + Collections.shuffle(list); + return list.get(0); + } + } + + @Override + public VMTemplateSwiftVO findBySwiftTemplate(long swiftId, long templateId) { + SearchCriteria sc = AllFieldSearch.create(); + sc.setParameters("swift_id", swiftId); + sc.setParameters("template_id", templateId); + return findOneBy(sc); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java new file mode 100755 index 0000000..bb3aa01 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java @@ -0,0 +1,33 @@ +// 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.storage.dao; + +import java.util.List; + +import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.utils.db.GenericDao; + +public interface VMTemplateZoneDao extends GenericDao { + public List listByZoneId(long id); + + public List listByTemplateId(long templateId); + + public VMTemplateZoneVO findByZoneTemplate(long zoneId, long templateId); + + public List listByZoneTemplate(Long zoneId, long templateId); + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java new file mode 100644 index 0000000..916e0ac --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java @@ -0,0 +1,89 @@ +// 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.storage.dao; + +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Component +@Local(value={VMTemplateZoneDao.class}) +public class VMTemplateZoneDaoImpl extends GenericDaoBase implements VMTemplateZoneDao { + public static final Logger s_logger = Logger.getLogger(VMTemplateZoneDaoImpl.class.getName()); + + protected final SearchBuilder ZoneSearch; + protected final SearchBuilder TemplateSearch; + protected final SearchBuilder ZoneTemplateSearch; + + + public VMTemplateZoneDaoImpl () { + ZoneSearch = createSearchBuilder(); + ZoneSearch.and("zone_id", ZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + ZoneSearch.done(); + + TemplateSearch = createSearchBuilder(); + TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateSearch.done(); + + ZoneTemplateSearch = createSearchBuilder(); + ZoneTemplateSearch.and("zone_id", ZoneTemplateSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + ZoneTemplateSearch.and("template_id", ZoneTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + ZoneTemplateSearch.done(); + } + + + @Override + public List listByZoneId(long id) { + SearchCriteria sc = ZoneSearch.create(); + sc.setParameters("zone_id", id); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateId(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("template_id", templateId); + return listIncludingRemovedBy(sc); + } + + @Override + public VMTemplateZoneVO findByZoneTemplate(long zoneId, long templateId) { + SearchCriteria sc = ZoneTemplateSearch.create(); + sc.setParameters("zone_id", zoneId); + sc.setParameters("template_id", templateId); + return findOneIncludingRemovedBy(sc); + } + + @Override + public List listByZoneTemplate(Long zoneId, long templateId) { + SearchCriteria sc = ZoneTemplateSearch.create(); + if (zoneId != null) { + sc.setParameters("zone_id", zoneId); + } + sc.setParameters("template_id", templateId); + return listBy(sc); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VolumeDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VolumeDao.java b/engine/schema/src/com/cloud/storage/dao/VolumeDao.java new file mode 100755 index 0000000..2513181 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VolumeDao.java @@ -0,0 +1,92 @@ +// 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.storage.dao; + +import java.util.List; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeVO; +import com.cloud.utils.Pair; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.fsm.StateDao; + +public interface VolumeDao extends GenericDao, StateDao { + + List findDetachedByAccount(long accountId); + + List findByAccount(long accountId); + + Pair getCountAndTotalByPool(long poolId); + + Pair getNonDestroyedCountAndTotalByPool(long poolId); + + List findByInstance(long id); + + List findByInstanceAndType(long id, Volume.Type vType); + + List findByInstanceIdDestroyed(long vmId); + + List findByAccountAndPod(long accountId, long podId); + + List findByTemplateAndZone(long templateId, long zoneId); + + void deleteVolumesByInstance(long instanceId); + + void attachVolume(long volumeId, long vmId, long deviceId); + + void detachVolume(long volumeId); + + boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId); + + List findCreatedByInstance(long id); + + List findByPoolId(long poolId); + + List findByInstanceAndDeviceId(long instanceId, long deviceId); + + List findUsableVolumesForInstance(long instanceId); + + Long countAllocatedVolumesForAccount(long accountId); + + HypervisorType getHypervisorType(long volumeId); + + List listVolumesToBeDestroyed(); + + ImageFormat getImageFormat(Long volumeId); + + List findReadyRootVolumesByInstance(long instanceId); + + List listPoolIdsByVolumeCount(long dcId, Long podId, Long clusterId, long accountId); + + /** + * Gets the Total Primary Storage space allocated for an account + * + * @param account + * @return total Primary Storage space (in bytes) used + */ + long primaryStorageUsedForAccount(long accountId); + + /** + * Gets the Total Secondary Storage space used by volumes allocated for an account + * + * @param account + * @return total Secondary Storage space (in bytes) used + */ + long secondaryStorageUsedForAccount(long accountId); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VolumeDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VolumeDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VolumeDaoImpl.java new file mode 100755 index 0000000..12ca3c7 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VolumeDaoImpl.java @@ -0,0 +1,459 @@ +// 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.storage.dao; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.ejb.Local; +import javax.inject.Inject; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Volume; +import com.cloud.storage.Volume.Event; +import com.cloud.storage.Volume.State; +import com.cloud.storage.Volume.Type; +import com.cloud.storage.VolumeVO; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.utils.Pair; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.UpdateBuilder; +import com.cloud.utils.exception.CloudRuntimeException; + +@Component +@Local(value=VolumeDao.class) +public class VolumeDaoImpl extends GenericDaoBase implements VolumeDao { + private static final Logger s_logger = Logger.getLogger(VolumeDaoImpl.class); + protected final SearchBuilder DetachedAccountIdSearch; + protected final SearchBuilder TemplateZoneSearch; + protected final GenericSearchBuilder TotalSizeByPoolSearch; + protected final GenericSearchBuilder ActiveTemplateSearch; + protected final SearchBuilder InstanceStatesSearch; + protected final SearchBuilder AllFieldsSearch; + protected GenericSearchBuilder CountByAccount; + protected GenericSearchBuilder primaryStorageSearch; + protected GenericSearchBuilder secondaryStorageSearch; + @Inject ResourceTagDao _tagsDao; + + protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?"; + protected static final String SELECT_HYPERTYPE_FROM_VOLUME = "SELECT c.hypervisor_type from volumes v, storage_pool s, cluster c where v.pool_id = s.id and s.cluster_id = c.id and v.id = ?"; + + private static final String ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT = "SELECT pool.id, SUM(IF(vol.state='Ready' AND vol.account_id = ?, 1, 0)) FROM `cloud`.`storage_pool` pool LEFT JOIN `cloud`.`volumes` vol ON pool.id = vol.pool_id WHERE pool.data_center_id = ? " + + " AND pool.pod_id = ? AND pool.cluster_id = ? " + + " GROUP BY pool.id ORDER BY 2 ASC "; + + @Override + public List findDetachedByAccount(long accountId) { + SearchCriteria sc = DetachedAccountIdSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("destroyed", Volume.State.Destroy); + return listBy(sc); + } + + @Override + public List findByAccount(long accountId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("state", Volume.State.Ready); + return listBy(sc); + } + + @Override + public List findByInstance(long id) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", id); + return listBy(sc); + } + + @Override + public List findByInstanceAndDeviceId(long instanceId, long deviceId){ + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", instanceId); + sc.setParameters("deviceId", deviceId); + return listBy(sc); + } + + @Override + public List findByPoolId(long poolId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("poolId", poolId); + sc.setParameters("notDestroyed", Volume.State.Destroy); + sc.setParameters("vType", Volume.Type.ROOT.toString()); + return listBy(sc); + } + + @Override + public List findCreatedByInstance(long id) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", id); + sc.setParameters("state", Volume.State.Ready); + return listBy(sc); + } + + @Override + public List findUsableVolumesForInstance(long instanceId) { + SearchCriteria sc = InstanceStatesSearch.create(); + sc.setParameters("instance", instanceId); + sc.setParameters("states", Volume.State.Creating, Volume.State.Ready, Volume.State.Allocated); + + return listBy(sc); + } + + @Override + public List findByInstanceAndType(long id, Type vType) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", id); + sc.setParameters("vType", vType.toString()); + return listBy(sc); + } + + @Override + public List findByInstanceIdDestroyed(long vmId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", vmId); + sc.setParameters("destroyed", Volume.State.Destroy); + return listBy(sc); + } + + @Override + public List findReadyRootVolumesByInstance(long instanceId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", instanceId); + sc.setParameters("state", Volume.State.Ready); + sc.setParameters("vType", Volume.Type.ROOT); + return listBy(sc); + } + + @Override + public List findByAccountAndPod(long accountId, long podId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("pod", podId); + sc.setParameters("state", Volume.State.Ready); + + return listIncludingRemovedBy(sc); + } + + @Override + public List findByTemplateAndZone(long templateId, long zoneId) { + SearchCriteria sc = TemplateZoneSearch.create(); + sc.setParameters("template", templateId); + sc.setParameters("zone", zoneId); + + return listIncludingRemovedBy(sc); + } + + @Override + public boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId) { + SearchCriteria sc = ActiveTemplateSearch.create(); + sc.setParameters("template", templateId); + sc.setParameters("pool", poolId); + + List results = customSearchIncludingRemoved(sc, null); + assert results.size() > 0 : "How can this return a size of " + results.size(); + + return results.get(0) > 0; + } + + @Override + public void deleteVolumesByInstance(long instanceId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", instanceId); + expunge(sc); + } + + @Override + public void attachVolume(long volumeId, long vmId, long deviceId) { + VolumeVO volume = createForUpdate(volumeId); + volume.setInstanceId(vmId); + volume.setDeviceId(deviceId); + volume.setUpdated(new Date()); + volume.setAttached(new Date()); + update(volumeId, volume); + } + + @Override + public void detachVolume(long volumeId) { + VolumeVO volume = createForUpdate(volumeId); + volume.setInstanceId(null); + volume.setDeviceId(null); + volume.setUpdated(new Date()); + volume.setAttached(null); + update(volumeId, volume); + } + + @Override + @DB + public HypervisorType getHypervisorType(long volumeId) { + /*lookup from cluster of pool*/ + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + + try { + String sql = SELECT_HYPERTYPE_FROM_VOLUME; + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, volumeId); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) { + return HypervisorType.getType(rs.getString(1)); + } + return HypervisorType.None; + } catch (SQLException e) { + throw new CloudRuntimeException("DB Exception on: " + SELECT_HYPERTYPE_FROM_VOLUME, e); + } catch (Throwable e) { + throw new CloudRuntimeException("Caught: " + SELECT_HYPERTYPE_FROM_VOLUME, e); + } + } + + @Override + public ImageFormat getImageFormat(Long volumeId) { + HypervisorType type = getHypervisorType(volumeId); + if ( type.equals(HypervisorType.KVM)) { + return ImageFormat.QCOW2; + } else if ( type.equals(HypervisorType.XenServer)) { + return ImageFormat.VHD; + } else if ( type.equals(HypervisorType.VMware)) { + return ImageFormat.OVA; + } else { + s_logger.warn("Do not support hypervisor " + type.toString()); + return null; + } + } + + public VolumeDaoImpl() { + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); + AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ); + AllFieldsSearch.and("pod", AllFieldsSearch.entity().getPodId(), Op.EQ); + AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getInstanceId(), Op.EQ); + AllFieldsSearch.and("deviceId", AllFieldsSearch.entity().getDeviceId(), Op.EQ); + AllFieldsSearch.and("poolId", AllFieldsSearch.entity().getPoolId(), Op.EQ); + AllFieldsSearch.and("vType", AllFieldsSearch.entity().getVolumeType(), Op.EQ); + AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ); + AllFieldsSearch.and("destroyed", AllFieldsSearch.entity().getState(), Op.EQ); + AllFieldsSearch.and("notDestroyed", AllFieldsSearch.entity().getState(), Op.NEQ); + AllFieldsSearch.and("updatedCount", AllFieldsSearch.entity().getUpdatedCount(), Op.EQ); + AllFieldsSearch.done(); + + DetachedAccountIdSearch = createSearchBuilder(); + DetachedAccountIdSearch.and("accountId", DetachedAccountIdSearch.entity().getAccountId(), Op.EQ); + DetachedAccountIdSearch.and("destroyed", DetachedAccountIdSearch.entity().getState(), Op.NEQ); + DetachedAccountIdSearch.and("instanceId", DetachedAccountIdSearch.entity().getInstanceId(), Op.NULL); + DetachedAccountIdSearch.done(); + + TemplateZoneSearch = createSearchBuilder(); + TemplateZoneSearch.and("template", TemplateZoneSearch.entity().getTemplateId(), Op.EQ); + TemplateZoneSearch.and("zone", TemplateZoneSearch.entity().getDataCenterId(), Op.EQ); + TemplateZoneSearch.done(); + + TotalSizeByPoolSearch = createSearchBuilder(SumCount.class); + TotalSizeByPoolSearch.select("sum", Func.SUM, TotalSizeByPoolSearch.entity().getSize()); + TotalSizeByPoolSearch.select("count", Func.COUNT, (Object[])null); + TotalSizeByPoolSearch.and("poolId", TotalSizeByPoolSearch.entity().getPoolId(), Op.EQ); + TotalSizeByPoolSearch.and("removed", TotalSizeByPoolSearch.entity().getRemoved(), Op.NULL); + TotalSizeByPoolSearch.and("state", TotalSizeByPoolSearch.entity().getState(), Op.NEQ); + TotalSizeByPoolSearch.done(); + + ActiveTemplateSearch = createSearchBuilder(Long.class); + ActiveTemplateSearch.and("pool", ActiveTemplateSearch.entity().getPoolId(), Op.EQ); + ActiveTemplateSearch.and("template", ActiveTemplateSearch.entity().getTemplateId(), Op.EQ); + ActiveTemplateSearch.and("removed", ActiveTemplateSearch.entity().getRemoved(), Op.NULL); + ActiveTemplateSearch.select(null, Func.COUNT, null); + ActiveTemplateSearch.done(); + + InstanceStatesSearch = createSearchBuilder(); + InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), Op.EQ); + InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), Op.IN); + InstanceStatesSearch.done(); + + CountByAccount = createSearchBuilder(Long.class); + CountByAccount.select(null, Func.COUNT, null); + CountByAccount.and("account", CountByAccount.entity().getAccountId(), SearchCriteria.Op.EQ); + CountByAccount.and("state", CountByAccount.entity().getState(), SearchCriteria.Op.NIN); + CountByAccount.done(); + + primaryStorageSearch = createSearchBuilder(SumCount.class); + primaryStorageSearch.select("sum", Func.SUM, primaryStorageSearch.entity().getSize()); + primaryStorageSearch.and("accountId", primaryStorageSearch.entity().getAccountId(), Op.EQ); + primaryStorageSearch.and("path", primaryStorageSearch.entity().getPath(), Op.NNULL); + primaryStorageSearch.and("isRemoved", primaryStorageSearch.entity().getRemoved(), Op.NULL); + primaryStorageSearch.done(); + + secondaryStorageSearch = createSearchBuilder(SumCount.class); + secondaryStorageSearch.select("sum", Func.SUM, secondaryStorageSearch.entity().getSize()); + secondaryStorageSearch.and("accountId", secondaryStorageSearch.entity().getAccountId(), Op.EQ); + secondaryStorageSearch.and("path", secondaryStorageSearch.entity().getPath(), Op.NULL); + secondaryStorageSearch.and("isRemoved", secondaryStorageSearch.entity().getRemoved(), Op.NULL); + secondaryStorageSearch.done(); + } + + @Override @DB(txn=false) + public Pair getCountAndTotalByPool(long poolId) { + SearchCriteria sc = TotalSizeByPoolSearch.create(); + sc.setParameters("poolId", poolId); + List results = customSearch(sc, null); + SumCount sumCount = results.get(0); + return new Pair(sumCount.count, sumCount.sum); + } + + @Override + public Long countAllocatedVolumesForAccount(long accountId) { + SearchCriteria sc = CountByAccount.create(); + sc.setParameters("account", accountId); + sc.setParameters("state", Volume.State.Destroy); + return customSearch(sc, null).get(0); + } + + @Override + public long primaryStorageUsedForAccount(long accountId) { + SearchCriteria sc = primaryStorageSearch.create(); + sc.setParameters("accountId", accountId); + List storageSpace = customSearch(sc, null); + if (storageSpace != null) { + return storageSpace.get(0).sum; + } else { + return 0; + } + } + + @Override + public long secondaryStorageUsedForAccount(long accountId) { + SearchCriteria sc = secondaryStorageSearch.create(); + sc.setParameters("accountId", accountId); + List storageSpace = customSearch(sc, null); + if (storageSpace != null) { + return storageSpace.get(0).sum; + } else { + return 0; + } + } + + + public static class SumCount { + public long sum; + public long count; + public SumCount() { + } + } + + @Override + public List listVolumesToBeDestroyed() { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("state", Volume.State.Destroy); + + return listBy(sc); + } + + @Override + public boolean updateState(com.cloud.storage.Volume.State currentState, + Event event, com.cloud.storage.Volume.State nextState, Volume vo, + Object data) { + + Long oldUpdated = vo.getUpdatedCount(); + Date oldUpdatedTime = vo.getUpdated(); + + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("id", vo.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", vo.getUpdatedCount()); + + vo.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(vo); + builder.set(vo, "state", nextState); + builder.set(vo, "updated", new Date()); + + int rows = update((VolumeVO)vo, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VolumeVO dbVol = findByIdIncludingRemoved(vo.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=").append(dbVol.getUpdated()); + str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()).append("; updatedTime=").append(vo.getUpdated()); + str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated).append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update volume: id=" + vo.getId() + ", as there is no such volume exists in the database anymore"); + } + } + return rows > 0; + } + + @Override + public List listPoolIdsByVolumeCount(long dcId, Long podId, Long clusterId, long accountId) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + List result = new ArrayList(); + try { + String sql = ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT; + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, accountId); + pstmt.setLong(2, dcId); + pstmt.setLong(3, podId); + pstmt.setLong(4, clusterId); + + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + result.add(rs.getLong(1)); + } + return result; + } catch (SQLException e) { + throw new CloudRuntimeException("DB Exception on: " + ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT, e); + } catch (Throwable e) { + throw new CloudRuntimeException("Caught: " + ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT, e); + } + } + + @Override @DB(txn=false) + public Pair getNonDestroyedCountAndTotalByPool(long poolId) { + SearchCriteria sc = TotalSizeByPoolSearch.create(); + sc.setParameters("poolId", poolId); + sc.setParameters("state", State.Destroy); + List results = customSearch(sc, null); + SumCount sumCount = results.get(0); + return new Pair(sumCount.count, sumCount.sum); + } + + @Override + @DB + public boolean remove(Long id) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + VolumeVO entry = findById(id); + if (entry != null) { + _tagsDao.removeByIdAndType(id, TaggedResourceType.Volume); + } + boolean result = super.remove(id); + txn.commit(); + return result; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java b/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java new file mode 100755 index 0000000..39dda12 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java @@ -0,0 +1,40 @@ +// 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.storage.dao; + +import java.util.List; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.storage.VolumeHostVO; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.fsm.StateDao; + +public interface VolumeHostDao extends GenericDao, StateDao{ + + VolumeHostVO findByHostVolume(long hostId, long volumeId); + + VolumeHostVO findByVolumeId(long volumeId); + + List listBySecStorage(long sserverId); + + List listDestroyed(long hostId); + + VolumeHostVO findVolumeByZone(long zoneId, long volumeId); + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java new file mode 100755 index 0000000..2fd39e6 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java @@ -0,0 +1,165 @@ +// 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.storage.dao; + +import java.util.Date; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.storage.VolumeHostVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.UpdateBuilder; + +@Component +@Local(value={VolumeHostDao.class}) +public class VolumeHostDaoImpl extends GenericDaoBase implements VolumeHostDao { + private static final Logger s_logger = Logger.getLogger(VolumeHostDaoImpl.class); + protected final SearchBuilder HostVolumeSearch; + protected final SearchBuilder ZoneVolumeSearch; + protected final SearchBuilder VolumeSearch; + protected final SearchBuilder HostSearch; + protected final SearchBuilder HostDestroyedSearch; + protected final SearchBuilder updateStateSearch; + public VolumeHostDaoImpl(){ + HostVolumeSearch = createSearchBuilder(); + HostVolumeSearch.and("host_id", HostVolumeSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostVolumeSearch.and("volume_id", HostVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + HostVolumeSearch.and("destroyed", HostVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + HostVolumeSearch.done(); + + ZoneVolumeSearch = createSearchBuilder(); + ZoneVolumeSearch.and("zone_id", ZoneVolumeSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + ZoneVolumeSearch.and("volume_id", ZoneVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + ZoneVolumeSearch.and("destroyed", ZoneVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + ZoneVolumeSearch.done(); + + HostSearch = createSearchBuilder(); + HostSearch.and("host_id", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostSearch.and("destroyed", HostSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + HostSearch.done(); + + VolumeSearch = createSearchBuilder(); + VolumeSearch.and("volume_id", VolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + VolumeSearch.and("destroyed", VolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + VolumeSearch.done(); + + HostDestroyedSearch = createSearchBuilder(); + HostDestroyedSearch.and("host_id", HostDestroyedSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostDestroyedSearch.and("destroyed", HostDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + HostDestroyedSearch.done(); + + updateStateSearch = this.createSearchBuilder(); + updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); + updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); + updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); + updateStateSearch.done(); + } + + + + @Override + public VolumeHostVO findByHostVolume(long hostId, long volumeId) { + SearchCriteria sc = HostVolumeSearch.create(); + sc.setParameters("host_id", hostId); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + + @Override + public VolumeHostVO findVolumeByZone(long volumeId, long zoneId) { + SearchCriteria sc = ZoneVolumeSearch.create(); + sc.setParameters("zone_id", zoneId); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + + @Override + public VolumeHostVO findByVolumeId(long volumeId) { + SearchCriteria sc = VolumeSearch.create(); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneBy(sc); + } + + + + @Override + public List listBySecStorage(long ssHostId) { + SearchCriteria sc = HostSearch.create(); + sc.setParameters("host_id", ssHostId); + sc.setParameters("destroyed", false); + return listAll(); + } + + @Override + public List listDestroyed(long hostId){ + SearchCriteria sc = HostDestroyedSearch.create(); + sc.setParameters("host_id", hostId); + sc.setParameters("destroyed", true); + return listIncludingRemovedBy(sc); + } + + @Override + public boolean updateState(State currentState, Event event, + State nextState, DataObjectInStore vo, Object data) { + VolumeHostVO volHost = (VolumeHostVO) vo; + Long oldUpdated = volHost.getUpdatedCount(); + Date oldUpdatedTime = volHost.getUpdated(); + + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", volHost.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", volHost.getUpdatedCount()); + + volHost.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(vo); + builder.set(vo, "state", nextState); + builder.set(vo, "updated", new Date()); + + int rows = update((VolumeHostVO) vo, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VolumeHostVO dbVol = findByIdIncludingRemoved(volHost.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + .append(dbVol.getUpdated()); + str.append(": New Data={id=").append(volHost.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(volHost.getUpdatedCount()) + .append("; updatedTime=").append(volHost.getUpdated()); + str.append(": stale Data={id=").append(volHost.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update objectIndatastore: id=" + volHost.getId() + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/tags/ResourceTagVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/tags/ResourceTagVO.java b/engine/schema/src/com/cloud/tags/ResourceTagVO.java new file mode 100644 index 0000000..04ae757 --- /dev/null +++ b/engine/schema/src/com/cloud/tags/ResourceTagVO.java @@ -0,0 +1,160 @@ +// 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.tags; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.apache.cloudstack.api.Identity; +import com.cloud.server.ResourceTag; +import org.apache.cloudstack.api.InternalIdentity; + + +@Entity +@Table(name="resource_tags") +public class ResourceTagVO implements ResourceTag { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="key") + private String key; + + @Column(name="value") + String value; + + @Column(name="domain_id") + long domainId; + + @Column(name="account_id") + long accountId; + + @Column(name="resource_id") + long resourceId; + + @Column(name="resource_uuid") + private String resourceUuid; + + @Column(name="resource_type") + @Enumerated(value=EnumType.STRING) + private TaggedResourceType resourceType; + + @Column(name="customer") + String customer; + + + protected ResourceTagVO(){ + this.uuid = UUID.randomUUID().toString(); + } + + /** + * @param key + * @param value + * @param accountId + * @param domainId + * @param resourceId + * @param resourceType + * @param customer TODO + * @param resourceUuid TODO + */ + public ResourceTagVO(String key, String value, long accountId, long domainId, long resourceId, + TaggedResourceType resourceType, String customer, String resourceUuid) { + super(); + this.key = key; + this.value = value; + this.domainId = domainId; + this.accountId = accountId; + this.resourceId = resourceId; + this.resourceType = resourceType; + this.uuid = UUID.randomUUID().toString(); + this.customer = customer; + this.resourceUuid = resourceUuid; + } + + + @Override + public String toString() { + StringBuilder buf = new StringBuilder("Tag["); + buf.append(id).append("|key=").append(key).append("|value=").append(domainId).append("|value="). + append("|resourceType=").append(resourceType).append("|resourceId=").append(resourceId) + .append("|accountId=").append(accountId).append("]"); + return buf.toString(); + } + + @Override + public long getId() { + return id; + } + + @Override + public String getKey() { + return key; + } + + @Override + public String getValue() { + return value; + } + + @Override + public long getDomainId() { + return domainId; + } + + @Override + public long getAccountId() { + return accountId; + } + + @Override + public long getResourceId() { + return resourceId; + } + + @Override + public TaggedResourceType getResourceType() { + return resourceType; + } + + @Override + public String getUuid() { + return uuid; + } + + @Override + public String getCustomer() { + return customer; + } + + @Override + public String getResourceUuid() { + return resourceUuid; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java b/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java new file mode 100644 index 0000000..335c748 --- /dev/null +++ b/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java @@ -0,0 +1,37 @@ +// 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.tags.dao; + +import java.util.List; + +import com.cloud.server.ResourceTag; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.tags.ResourceTagVO; +import com.cloud.utils.db.GenericDao; + +public interface ResourceTagDao extends GenericDao{ + + /** + * @param resourceId + * @param resourceType + * @return + */ + boolean removeByIdAndType(long resourceId, TaggedResourceType resourceType); + + List listBy(long resourceId, TaggedResourceType resourceType); + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java b/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java new file mode 100644 index 0000000..a8e1393 --- /dev/null +++ b/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java @@ -0,0 +1,62 @@ +// 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.tags.dao; + +import java.util.List; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.server.ResourceTag; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.tags.ResourceTagVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Component +@Local(value = { ResourceTagDao.class }) +public class ResourceTagsDaoImpl extends GenericDaoBase implements ResourceTagDao{ + final SearchBuilder AllFieldsSearch; + + public ResourceTagsDaoImpl() { + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("resourceId", AllFieldsSearch.entity().getResourceId(), Op.EQ); + AllFieldsSearch.and("uuid", AllFieldsSearch.entity().getResourceUuid(), Op.EQ); + AllFieldsSearch.and("resourceType", AllFieldsSearch.entity().getResourceType(), Op.EQ); + AllFieldsSearch.done(); + } + + @Override + public boolean removeByIdAndType(long resourceId, ResourceTag.TaggedResourceType resourceType) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("resourceId", resourceId); + sc.setParameters("resourceType", resourceType); + remove(sc); + return true; + } + + @Override + public List listBy(long resourceId, TaggedResourceType resourceType) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("resourceId", resourceId); + sc.setParameters("resourceType", resourceType); + return listBy(sc); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d015fb35/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java b/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java new file mode 100755 index 0000000..9b1be6b --- /dev/null +++ b/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java @@ -0,0 +1,233 @@ +/* + * 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.upgrade; + +import java.io.*; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import com.cloud.utils.PropertiesUtil; + +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.component.SystemIntegrityChecker; +import com.cloud.utils.db.ScriptRunner; +import com.cloud.utils.db.Transaction; + +// Creates the CloudStack Database by using the 4.0 schema and apply +// upgrade steps to it. +public class DatabaseCreator { + + protected static void printHelp(String cmd) { + System.out.println( + "\nDatabaseCreator creates the database schema by removing the \n" + + "previous schema, creating the schema, and running \n" + + "through the database updaters."); + System.out.println("Usage: " + cmd + " [options] [db.properties file] [schema.sql files] [database upgrade class]\nOptions:" + + "\n --database=a,b comma separate databases to initialize, use the db name in db.properties defined as db.xyz.host, xyz should be passed" + + "\n --rootpassword=password, by default it will try with an empty password" + + "\n --dry or -d, this would not run any process, just does a dry run" + + "\n --verbose or -v to print running sql commands, by default it won't print them" + + "\n --help or -h for help"); + } + + private static boolean fileExists(String file) { + File f = new File(file); + if (!f.exists()) + System.out.println("========> WARNING: Provided file does not exist: " + file); + return f.exists(); + } + + private static void runScript(Connection conn, Reader reader, String filename, boolean verbosity) { + ScriptRunner runner = new ScriptRunner(conn, false, true, verbosity); + try { + runner.runScript(reader); + } catch (IOException e) { + System.err.println("Unable to read " + filename + ": " + e.getMessage()); + System.exit(1); + } catch (SQLException e) { + System.err.println("Unable to execute " + filename + ": " + e.getMessage()); + System.exit(1); + } + } + + private static void runQuery(String host, String port, String rootPassword, String query, boolean dryRun) { + System.out.println("============> Running query: " + query); + Connection conn = null; + try { + conn = DriverManager.getConnection(String.format("jdbc:mysql://%s:%s/", host, port), + "root", rootPassword); + Statement stmt = conn.createStatement(); + if (!dryRun) + stmt.executeUpdate(query); + conn.close(); + } catch (SQLException e) { + System.out.println("SQL exception in trying initDB: " + e); + System.exit(1); + } + } + + private static void initDB(String dbPropsFile, String rootPassword, String[] databases, boolean dryRun) { + Properties dbProperties = new Properties(); + try { + dbProperties.load(new FileInputStream(new File(dbPropsFile))); + } catch (IOException e) { + System.out.println("IOError: unable to load/read db properties file: " + e); + System.exit(1); + } + + for (String database: databases) { + String host = dbProperties.getProperty(String.format("db.%s.host", database)); + String port = dbProperties.getProperty(String.format("db.%s.port", database)); + String username = dbProperties.getProperty(String.format("db.%s.username", database)); + String password = dbProperties.getProperty(String.format("db.%s.password", database)); + String dbName = dbProperties.getProperty(String.format("db.%s.name", database)); + System.out.println(String.format("========> Initializing database=%s with host=%s port=%s username=%s password=%s", dbName, host, port, username, password)); + + List queries = new ArrayList(); + queries.add(String.format("drop database if exists `%s`", dbName)); + queries.add(String.format("create database `%s`", dbName)); + queries.add(String.format("GRANT ALL ON %s.* to '%s'@`localhost` identified by '%s'", dbName, username, password)); + queries.add(String.format("GRANT ALL ON %s.* to '%s'@`%%` identified by '%s'", dbName, username, password)); + + for (String query: queries) { + runQuery(host, port, rootPassword, query, dryRun); + } + } + } + + public static void main(String[] args) { + + ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext( + new String[] {"/com/cloud/upgrade/databaseCreatorContext.xml"}); + appContext.getBean(ComponentContext.class); + + String dbPropsFile = ""; + List sqlFiles = new ArrayList(); + List upgradeClasses = new ArrayList(); + String[] databases = new String[] {}; + String rootPassword = ""; + boolean verbosity = false; + boolean dryRun = false; + + // Process opts + for (String arg: args) { + if (arg.equals("--help") || arg.equals("-h")) { + printHelp("DatabaseCreator"); + System.exit(0); + } else if (arg.equals("--verbose") || arg.equals("-v")) { + verbosity = true; + } else if (arg.equals("--dry") || arg.equals("-d")) { + dryRun = true; + } else if (arg.startsWith("--rootpassword=")) { + rootPassword = arg.substring(arg.lastIndexOf("=") + 1, arg.length()); + } else if (arg.startsWith("--database=")) { + databases = arg.substring(arg.lastIndexOf("=") + 1, arg.length()).split(","); + } else if (arg.endsWith(".sql")) { + sqlFiles.add(arg); + } else if (arg.endsWith(".properties")) { + if (!dbPropsFile.endsWith("properties.override") && fileExists(arg)) + dbPropsFile = arg; + } else if (arg.endsWith("properties.override")) { + if (fileExists(arg)) + dbPropsFile = arg; + } else { + upgradeClasses.add(arg); + } + } + + if ((dbPropsFile.isEmpty()) + || (sqlFiles.size() == 0) && upgradeClasses.size() == 0) { + printHelp("DatabaseCreator"); + System.exit(1); + } + + try { + Transaction.initDataSource(dbPropsFile); + } catch (NullPointerException e) { + } + initDB(dbPropsFile, rootPassword, databases, dryRun); + + // Process sql files + for (String sqlFile: sqlFiles) { + File sqlScript = PropertiesUtil.findConfigFile(sqlFile); + if (sqlScript == null) { + System.err.println("Unable to find " + sqlFile); + printHelp("DatabaseCreator"); + System.exit(1); + } + + System.out.println("========> Processing SQL file at " + sqlScript.getAbsolutePath()); + Connection conn = Transaction.getStandaloneConnection(); + try { + FileReader reader = null; + try { + reader = new FileReader(sqlScript); + } catch (FileNotFoundException e) { + System.err.println("Unable to read " + sqlFile + ": " + e.getMessage()); + System.exit(1); + } + if (!dryRun) + runScript(conn, reader, sqlFile, verbosity); + } finally { + try { + conn.close(); + } catch (SQLException e) { + System.err.println("Unable to close DB connection: " + e.getMessage()); + } + } + } + + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + // Process db upgrade classes + for (String upgradeClass: upgradeClasses) { + System.out.println("========> Processing upgrade: " + upgradeClass); + Class clazz = null; + try { + clazz = Class.forName(upgradeClass); + if (!SystemIntegrityChecker.class.isAssignableFrom(clazz)) { + System.err.println("The class must be of SystemIntegrityChecker: " + clazz.getName()); + System.exit(1); + } + SystemIntegrityChecker checker = (SystemIntegrityChecker)clazz.newInstance(); + checker.check(); + } catch (ClassNotFoundException e) { + System.err.println("Unable to find " + upgradeClass + ": " + e.getMessage()); + System.exit(1); + } catch (InstantiationException e) { + System.err.println("Unable to instantiate " + upgradeClass + ": " + e.getMessage()); + System.exit(1); + } catch (IllegalAccessException e) { + System.err.println("Unable to access " + upgradeClass + ": " + e.getMessage()); + System.exit(1); + } + + } + } finally { + txn.close(); + } + } +}