diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreDao.java b/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreDao.java new file mode 100644 index 00000000000..8a62766fa8f --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreDao.java @@ -0,0 +1,27 @@ +// 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 org.apache.cloudstack.storage.db; + + +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.fsm.StateDao; + +public interface SnapshotDataStoreDao extends GenericDao, StateDao { + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreDaoImpl.java new file mode 100644 index 00000000000..1c291db1bd4 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreDaoImpl.java @@ -0,0 +1,86 @@ +// 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 org.apache.cloudstack.storage.db; +import java.util.Date; +import java.util.Map; + +import javax.naming.ConfigurationException; + +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.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 +public class SnapshotDataStoreDaoImpl extends GenericDaoBase implements VolumeDataStoreDao { + private static final Logger s_logger = Logger.getLogger(SnapshotDataStoreDaoImpl.class); + private SearchBuilder updateStateSearch; + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + 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(); + return true; + } + @Override + public boolean updateState(State currentState, Event event, + State nextState, VolumeDataStoreVO dataObj, Object data) { + Long oldUpdated = dataObj.getUpdatedCount(); + Date oldUpdatedTime = dataObj.getUpdated(); + + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", dataObj.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", dataObj.getUpdatedCount()); + + dataObj.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(dataObj); + builder.set(dataObj, "state", nextState); + builder.set(dataObj, "updated", new Date()); + + int rows = update(dataObj, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VolumeDataStoreVO dbVol = findByIdIncludingRemoved(dataObj.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(dataObj.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(dataObj.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(dataObj.getUpdatedCount()) + .append("; updatedTime=").append(dataObj.getUpdated()); + str.append(": stale Data={id=").append(dataObj.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=" + dataObj.getId() + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreVO.java new file mode 100644 index 00000000000..527385f4be3 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/SnapshotDataStoreVO.java @@ -0,0 +1,242 @@ +// 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 org.apache.cloudstack.storage.db; + +import java.util.Date; + +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 javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.storage.Storage; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.fsm.StateObject; + +/** + * Join table for image_data_store and snapshots + * + */ +@Entity +@Table(name="snapshot_store_ref") +public class SnapshotDataStoreVO implements StateObject, DataObjectInStore { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + Long id; + + @Column(name="store_id") + private long dataStoreId; + + @Column(name="snapshot_id") + private long snapshotId; + + @Column(name=GenericDaoBase.CREATED_COLUMN) + private Date created = null; + + @Column(name="last_updated") + @Temporal(value=TemporalType.TIMESTAMP) + private Date lastUpdated = null; + + + @Column (name="size") + private long size; + + @Column (name="physical_size") + private long physicalSize; + + + @Column (name="job_id") + private String jobId; + + @Column (name="install_path") + private String installPath; + + + @Column(name="destroyed") + boolean destroyed = false; + + @Column(name="update_count", updatable = true, nullable=false) + protected long updatedCount; + + @Column(name = "updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date updated; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + public String getInstallPath() { + return installPath; + } + + public long getDataStoreId() { + return dataStoreId; + } + + public void setHostId(long hostId) { + this.dataStoreId = hostId; + } + + + public long getSnapshotId() { + return snapshotId; + } + + + public void setSnapshotId(long snapshotId) { + this.snapshotId = snapshotId; + } + + + + + public long getId() { + return id; + } + + + public Date getCreated() { + return created; + } + + + public Date getLastUpdated() { + return lastUpdated; + } + + + public void setLastUpdated(Date date) { + lastUpdated = date; + } + + + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + + + public SnapshotDataStoreVO(long hostId, long snapshotId) { + super(); + this.dataStoreId = hostId; + this.snapshotId = snapshotId; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + } + + + + protected SnapshotDataStoreVO() { + + } + + + + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + + public String getJobId() { + return jobId; + } + + + public boolean equals(Object obj) { + if (obj instanceof SnapshotDataStoreVO) { + SnapshotDataStoreVO other = (SnapshotDataStoreVO)obj; + return (this.snapshotId==other.getSnapshotId() && this.dataStoreId==other.getDataStoreId()); + } + return false; + } + + + public int hashCode() { + Long tid = new Long(snapshotId); + Long hid = new Long(dataStoreId); + return tid.hashCode()+hid.hashCode(); + } + + public void setSize(long size) { + this.size = size; + } + + public long getSize() { + return size; + } + + + public void setPhysicalSize(long physicalSize) { + this.physicalSize = physicalSize; + } + + public long getPhysicalSize() { + return physicalSize; + } + + public void setDestroyed(boolean destroyed) { + this.destroyed = destroyed; + } + + public boolean getDestroyed() { + return destroyed; + } + + public long getVolumeSize() { + return -1; + } + + + public String toString() { + return new StringBuilder("VolumeHost[").append(id).append("-").append(snapshotId).append("-").append(dataStoreId).append(installPath).append("]").toString(); + } + + public long getUpdatedCount() { + return this.updatedCount; + } + + public void incrUpdatedCount() { + this.updatedCount++; + } + + public void decrUpdatedCount() { + this.updatedCount--; + } + + public Date getUpdated() { + return updated; + } + + @Override + public ObjectInDataStoreStateMachine.State getState() { + // TODO Auto-generated method stub + return this.state; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreDao.java b/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreDao.java new file mode 100644 index 00000000000..2faf3c729c9 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreDao.java @@ -0,0 +1,27 @@ +// 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 org.apache.cloudstack.storage.db; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.fsm.StateDao; + +public interface TemplateDataStoreDao extends GenericDao, StateDao { + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreDaoImpl.java new file mode 100644 index 00000000000..c40b8ba0cd3 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreDaoImpl.java @@ -0,0 +1,86 @@ +// 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 org.apache.cloudstack.storage.db; +import java.util.Date; +import java.util.Map; + +import javax.naming.ConfigurationException; + +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.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 +public class TemplateDataStoreDaoImpl extends GenericDaoBase implements TemplateDataStoreDao { + private static final Logger s_logger = Logger.getLogger(TemplateDataStoreDaoImpl.class); + private SearchBuilder updateStateSearch; + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + 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(); + return true; + } + @Override + public boolean updateState(State currentState, Event event, + State nextState, TemplateDataStoreVO dataObj, Object data) { + Long oldUpdated = dataObj.getUpdatedCount(); + Date oldUpdatedTime = dataObj.getUpdated(); + + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", dataObj.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", dataObj.getUpdatedCount()); + + dataObj.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(dataObj); + builder.set(dataObj, "state", nextState); + builder.set(dataObj, "updated", new Date()); + + int rows = update(dataObj, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + TemplateDataStoreVO dbVol = findByIdIncludingRemoved(dataObj.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(dataObj.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(dataObj.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(dataObj.getUpdatedCount()) + .append("; updatedTime=").append(dataObj.getUpdated()); + str.append(": stale Data={id=").append(dataObj.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=" + dataObj.getId() + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreVO.java new file mode 100755 index 00000000000..af393a5221d --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/TemplateDataStoreVO.java @@ -0,0 +1,310 @@ +// 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 org.apache.cloudstack.storage.db; + +import java.util.Date; + +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 javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.fsm.StateObject; + +/** + * Join table for image_data_store and templates + * + */ +@Entity +@Table(name="template_store_ref") +public class TemplateDataStoreVO implements StateObject, DataObjectInStore { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + Long id; + + @Column(name="store_id") + private long dataStoreId; + + @Column(name="template_id") + private long templateId; + + @Column(name=GenericDaoBase.CREATED_COLUMN) + private Date created = null; + + @Column(name="last_updated") + @Temporal(value=TemporalType.TIMESTAMP) + private Date lastUpdated = null; + + @Column (name="download_pct") + private int downloadPercent; + + @Column (name="size") + private long size; + + @Column (name="physical_size") + private long physicalSize; + + @Column (name="download_state") + @Enumerated(EnumType.STRING) + private Status downloadState; + + @Column (name="local_path") + private String localDownloadPath; + + @Column (name="error_str") + private String errorString; + + @Column (name="job_id") + private String jobId; + + @Column (name="install_path") + private String installPath; + + @Column (name="url") + private String downloadUrl; + + @Column(name="is_copy") + private boolean isCopy = false; + + @Column(name="destroyed") + boolean destroyed = false; + + @Column(name="update_count", updatable = true, nullable=false) + protected long updatedCount; + + @Column(name = "updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date updated; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + + @Override + public String getInstallPath() { + return installPath; + } + + + public long getDataStoreId() { + return dataStoreId; + } + + public void setHostId(long hostId) { + this.dataStoreId = hostId; + } + + public long getTemplateId() { + return templateId; + } + + public void setTemplateId(long templateId) { + this.templateId = templateId; + } + + public int getDownloadPercent() { + return downloadPercent; + } + + public void setDownloadPercent(int downloadPercent) { + this.downloadPercent = downloadPercent; + } + + public void setDownloadState(Status downloadState) { + this.downloadState = downloadState; + } + + public long getId() { + return id; + } + + public Date getCreated() { + return created; + } + + public Date getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Date date) { + lastUpdated = date; + } + + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + public Status getDownloadState() { + return downloadState; + } + + public TemplateDataStoreVO(long hostId, long templateId) { + super(); + this.dataStoreId = hostId; + this.templateId = templateId; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + } + + public TemplateDataStoreVO(long hostId, long templateId, Date lastUpdated, + int downloadPercent, Status downloadState, + String localDownloadPath, String errorString, String jobId, + String installPath, String downloadUrl) { + super(); + this.dataStoreId = hostId; + this.templateId = templateId; + this.lastUpdated = lastUpdated; + this.downloadPercent = downloadPercent; + this.downloadState = downloadState; + this.localDownloadPath = localDownloadPath; + this.errorString = errorString; + this.jobId = jobId; + this.installPath = installPath; + this.setDownloadUrl(downloadUrl); + } + + protected TemplateDataStoreVO() { + + } + + + public void setLocalDownloadPath(String localPath) { + this.localDownloadPath = localPath; + } + + public String getLocalDownloadPath() { + return localDownloadPath; + } + + public void setErrorString(String errorString) { + this.errorString = errorString; + } + + public String getErrorString() { + return errorString; + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public String getJobId() { + return jobId; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TemplateDataStoreVO) { + TemplateDataStoreVO other = (TemplateDataStoreVO)obj; + return (this.templateId==other.getTemplateId() && this.dataStoreId==other.getDataStoreId()); + } + return false; + } + + @Override + public int hashCode() { + Long tid = new Long(templateId); + Long hid = new Long(dataStoreId); + return tid.hashCode()+hid.hashCode(); + } + + public void setSize(long size) { + this.size = size; + } + + public long getSize() { + return size; + } + + + public void setPhysicalSize(long physicalSize) { + this.physicalSize = physicalSize; + } + + public long getPhysicalSize() { + return physicalSize; + } + + public void setDestroyed(boolean destroyed) { + this.destroyed = destroyed; + } + + public boolean getDestroyed() { + return destroyed; + } + + public void setDownloadUrl(String downloadUrl) { + this.downloadUrl = downloadUrl; + } + + public String getDownloadUrl() { + return downloadUrl; + } + + public void setCopy(boolean isCopy) { + this.isCopy = isCopy; + } + + public boolean isCopy() { + return isCopy; + } + + public long getTemplateSize() { + return -1; + } + + @Override + public String toString() { + return new StringBuilder("TmplHost[").append(id).append("-").append(templateId).append("-").append(dataStoreId).append(installPath).append("]").toString(); + } + + @Override + public ObjectInDataStoreStateMachine.State getState() { + // TODO Auto-generated method stub + return this.state; + } + + public long getUpdatedCount() { + return this.updatedCount; + } + + public void incrUpdatedCount() { + this.updatedCount++; + } + + public void decrUpdatedCount() { + this.updatedCount--; + } + + public Date getUpdated() { + return updated; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreDao.java b/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreDao.java new file mode 100644 index 00000000000..e687d88082f --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreDao.java @@ -0,0 +1,27 @@ +// 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 org.apache.cloudstack.storage.db; + + +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.fsm.StateDao; + +public interface VolumeDataStoreDao extends GenericDao, StateDao { + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreDaoImpl.java new file mode 100644 index 00000000000..1f7b278d9bf --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreDaoImpl.java @@ -0,0 +1,86 @@ +// 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 org.apache.cloudstack.storage.db; +import java.util.Date; +import java.util.Map; + +import javax.naming.ConfigurationException; + +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.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 +public class VolumeDataStoreDaoImpl extends GenericDaoBase implements VolumeDataStoreDao { + private static final Logger s_logger = Logger.getLogger(VolumeDataStoreDaoImpl.class); + private SearchBuilder updateStateSearch; + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + 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(); + return true; + } + @Override + public boolean updateState(State currentState, Event event, + State nextState, VolumeDataStoreVO dataObj, Object data) { + Long oldUpdated = dataObj.getUpdatedCount(); + Date oldUpdatedTime = dataObj.getUpdated(); + + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", dataObj.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", dataObj.getUpdatedCount()); + + dataObj.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(dataObj); + builder.set(dataObj, "state", nextState); + builder.set(dataObj, "updated", new Date()); + + int rows = update(dataObj, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VolumeDataStoreVO dbVol = findByIdIncludingRemoved(dataObj.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(dataObj.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(dataObj.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(dataObj.getUpdatedCount()) + .append("; updatedTime=").append(dataObj.getUpdated()); + str.append(": stale Data={id=").append(dataObj.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=" + dataObj.getId() + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreVO.java new file mode 100755 index 00000000000..b27a4baa902 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/db/VolumeDataStoreVO.java @@ -0,0 +1,348 @@ +// 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 org.apache.cloudstack.storage.db; + +import java.util.Date; + +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 javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.storage.Storage; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.fsm.StateObject; + +/** + * Join table for image_data_store and volumes + * + */ +@Entity +@Table(name="volume_store_ref") +public class VolumeDataStoreVO implements StateObject, DataObjectInStore { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + Long id; + + @Column(name="store_id") + private long dataStoreId; + + @Column(name="volume_id") + private long volumeId; + + @Column(name="zone_id") + private long zoneId; + + @Column(name=GenericDaoBase.CREATED_COLUMN) + private Date created = null; + + @Column(name="last_updated") + @Temporal(value=TemporalType.TIMESTAMP) + private Date lastUpdated = null; + + @Column (name="download_pct") + private int downloadPercent; + + @Column (name="size") + private long size; + + @Column (name="physical_size") + private long physicalSize; + + @Column (name="download_state") + @Enumerated(EnumType.STRING) + private Status downloadState; + + @Column(name="checksum") + private String checksum; + + @Column (name="local_path") + private String localDownloadPath; + + @Column (name="error_str") + private String errorString; + + @Column (name="job_id") + private String jobId; + + @Column (name="install_path") + private String installPath; + + @Column (name="url") + private String downloadUrl; + + @Column(name="format") + private Storage.ImageFormat format; + + @Column(name="destroyed") + boolean destroyed = false; + + @Column(name="update_count", updatable = true, nullable=false) + protected long updatedCount; + + @Column(name = "updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date updated; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + public String getInstallPath() { + return installPath; + } + + public long getDataStoreId() { + return dataStoreId; + } + + public void setHostId(long hostId) { + this.dataStoreId = hostId; + } + + + public long getVolumeId() { + return volumeId; + } + + + public void setVolumeId(long volumeId) { + this.volumeId = volumeId; + } + + + public long getZoneId() { + return zoneId; + } + + public void setZoneId(long zoneId) { + this.zoneId = zoneId; + } + + public int getDownloadPercent() { + return downloadPercent; + } + + + public void setDownloadPercent(int downloadPercent) { + this.downloadPercent = downloadPercent; + } + + + public void setDownloadState(Status downloadState) { + this.downloadState = downloadState; + } + + + public long getId() { + return id; + } + + + public Date getCreated() { + return created; + } + + + public Date getLastUpdated() { + return lastUpdated; + } + + + public void setLastUpdated(Date date) { + lastUpdated = date; + } + + + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + + public Status getDownloadState() { + return downloadState; + } + + public String getChecksum() { + return checksum; + } + + public void setChecksum(String checksum) { + this.checksum = checksum; + } + + public VolumeDataStoreVO(long hostId, long volumeId) { + super(); + this.dataStoreId = hostId; + this.volumeId = volumeId; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + } + + public VolumeDataStoreVO(long hostId, long volumeId, long zoneId, Date lastUpdated, + int downloadPercent, Status downloadState, + String localDownloadPath, String errorString, String jobId, + String installPath, String downloadUrl, String checksum, ImageFormat format) { + //super(); + this.dataStoreId = hostId; + this.volumeId = volumeId; + this.zoneId = zoneId; + this.lastUpdated = lastUpdated; + this.downloadPercent = downloadPercent; + this.downloadState = downloadState; + this.localDownloadPath = localDownloadPath; + this.errorString = errorString; + this.jobId = jobId; + this.installPath = installPath; + this.setDownloadUrl(downloadUrl); + this.checksum = checksum; + this.format = format; + } + + protected VolumeDataStoreVO() { + + } + + + public void setLocalDownloadPath(String localPath) { + this.localDownloadPath = localPath; + } + + + public String getLocalDownloadPath() { + return localDownloadPath; + } + + + public void setErrorString(String errorString) { + this.errorString = errorString; + } + + + public String getErrorString() { + return errorString; + } + + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + + public String getJobId() { + return jobId; + } + + + public boolean equals(Object obj) { + if (obj instanceof VolumeDataStoreVO) { + VolumeDataStoreVO other = (VolumeDataStoreVO)obj; + return (this.volumeId==other.getVolumeId() && this.dataStoreId==other.getDataStoreId()); + } + return false; + } + + + public int hashCode() { + Long tid = new Long(volumeId); + Long hid = new Long(dataStoreId); + return tid.hashCode()+hid.hashCode(); + } + + public void setSize(long size) { + this.size = size; + } + + public long getSize() { + return size; + } + + + public void setPhysicalSize(long physicalSize) { + this.physicalSize = physicalSize; + } + + public long getPhysicalSize() { + return physicalSize; + } + + public void setDestroyed(boolean destroyed) { + this.destroyed = destroyed; + } + + public boolean getDestroyed() { + return destroyed; + } + + public void setDownloadUrl(String downloadUrl) { + this.downloadUrl = downloadUrl; + } + + public String getDownloadUrl() { + return downloadUrl; + } + + public Storage.ImageFormat getFormat() { + return format; + } + + public void setFormat(Storage.ImageFormat format) { + this.format = format; + } + + public long getVolumeSize() { + return -1; + } + + + public String toString() { + return new StringBuilder("VolumeHost[").append(id).append("-").append(volumeId).append("-").append(dataStoreId).append(installPath).append("]").toString(); + } + + public long getUpdatedCount() { + return this.updatedCount; + } + + public void incrUpdatedCount() { + this.updatedCount++; + } + + public void decrUpdatedCount() { + this.updatedCount--; + } + + public Date getUpdated() { + return updated; + } + + @Override + public ObjectInDataStoreStateMachine.State getState() { + // TODO Auto-generated method stub + return this.state; + } + +} diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index ab9df05103b..a3a756ed085 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -61,12 +61,12 @@ CREATE TABLE `cloud`.`object_datastore_ref` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -CREATE TABLE `cloud`.`data_store_provider` ( - `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', - `name` varchar(255) NOT NULL COMMENT 'name of primary data store provider', - `uuid` varchar(255) NOT NULL COMMENT 'uuid of primary data store provider', - PRIMARY KEY(`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- CREATE TABLE `cloud`.`data_store_provider` ( +-- `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', +-- `name` varchar(255) NOT NULL COMMENT 'name of primary data store provider', +-- `uuid` varchar(255) NOT NULL COMMENT 'uuid of primary data store provider', +-- PRIMARY KEY(`id`) +-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`image_data_store` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', @@ -79,8 +79,86 @@ CREATE TABLE `cloud`.`image_data_store` ( PRIMARY KEY(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`template_store_ref` ( + `id` bigint unsigned NOT NULL auto_increment, + `store_id` bigint unsigned NOT NULL, + `template_id` bigint unsigned NOT NULL, + `created` DATETIME NOT NULL, + `last_updated` DATETIME, + `job_id` varchar(255), + `download_pct` int(10) unsigned, + `size` bigint unsigned, + `physical_size` bigint unsigned DEFAULT 0, + `download_state` varchar(255), + `error_str` varchar(255), + `local_path` varchar(255), + `install_path` varchar(255), + `url` varchar(255), + `state` varchar(255) NOT NULL, + `destroyed` tinyint(1) COMMENT 'indicates whether the template_store entry was destroyed by the user or not', + `is_copy` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'indicates whether this was copied ', + PRIMARY KEY (`id`), + CONSTRAINT `fk_template_store_ref__store_id` FOREIGN KEY `fk_template_store_ref__store_id` (`store_id`) REFERENCES `image_data_store` (`id`) ON DELETE CASCADE, + INDEX `i_template_store_ref__store_id`(`store_id`), + CONSTRAINT `fk_template_store_ref__template_id` FOREIGN KEY `fk_template_store_ref__template_id` (`template_id`) REFERENCES `vm_template` (`id`), + INDEX `i_template_store_ref__template_id`(`template_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + ALTER TABLE `cloud`.`vm_template` ADD COLUMN `image_data_store_id` bigint unsigned; +-- Do we still need these columns? TODO, to delete them, remove FK constraints from snapshots table +-- ALTER TABLE `cloud`.`snapshots` DROP COLUMN `swift_id`; +-- ALTER TABLE `cloud`.`snapshots` DROP COLUMN `s3_id`; +-- ALTER TABLE `cloud`.`snapshots` DROP COLUMN `sechost_id`; + +CREATE TABLE `cloud`.`snapshot_store_ref` ( + `id` bigint unsigned NOT NULL auto_increment, + `store_id` bigint unsigned NOT NULL, + `snapshot_id` bigint unsigned NOT NULL, + `created` DATETIME NOT NULL, + `last_updated` DATETIME, + `job_id` varchar(255), + `size` bigint unsigned, + `physical_size` bigint unsigned DEFAULT 0, + `install_path` varchar(255), + `state` varchar(255) NOT NULL, + `destroyed` tinyint(1) COMMENT 'indicates whether the snapshot_store entry was destroyed by the user or not', + PRIMARY KEY (`id`), + CONSTRAINT `fk_snapshot_store_ref__store_id` FOREIGN KEY `fk_snapshot_store_ref__store_id` (`store_id`) REFERENCES `image_data_store` (`id`) ON DELETE CASCADE, + INDEX `i_snapshot_store_ref__store_id`(`store_id`), + CONSTRAINT `fk_snapshot_store_ref__snapshot_id` FOREIGN KEY `fk_snapshot_store_ref__snapshot_id` (`snapshot_id`) REFERENCES `snapshots` (`id`), + INDEX `i_snapshot_store_ref__snapshot_id`(`snapshot_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`volume_store_ref` ( + `id` bigint unsigned NOT NULL auto_increment, + `store_id` bigint unsigned NOT NULL, + `volume_id` bigint unsigned NOT NULL, + `zone_id` bigint unsigned NOT NULL, + `created` DATETIME NOT NULL, + `last_updated` DATETIME, + `job_id` varchar(255), + `download_pct` int(10) unsigned, + `size` bigint unsigned, + `physical_size` bigint unsigned DEFAULT 0, + `download_state` varchar(255), + `checksum` varchar(255) COMMENT 'checksum for the data disk', + `error_str` varchar(255), + `local_path` varchar(255), + `install_path` varchar(255), + `url` varchar(255), + `state` varchar(255) NOT NULL, + `format` varchar(32) NOT NULL COMMENT 'format for the volume', + `destroyed` tinyint(1) COMMENT 'indicates whether the volume_host entry was destroyed by the user or not', + PRIMARY KEY (`id`), + CONSTRAINT `fk_volume_store_ref__store_id` FOREIGN KEY `fk_volume_store_ref__store_id` (`store_id`) REFERENCES `image_data_store` (`id`) ON DELETE CASCADE, + INDEX `i_volume_store_ref__store_id`(`store_id`), + CONSTRAINT `fk_volume_store_ref__volume_id` FOREIGN KEY `fk_volume_store_ref__volume_id` (`volume_id`) REFERENCES `volumes` (`id`), + INDEX `i_volume_store_ref__volume_id`(`volume_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + + ALTER TABLE `cloud`.`service_offering` ADD COLUMN `is_volatile` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the vm needs to be volatile, i.e., on every reboot of vm from API root disk is discarded and creates a new root disk'; ALTER TABLE `cloud`.`networks` ADD COLUMN `network_cidr` VARCHAR(18) COMMENT 'The network cidr for the isolated guest network which uses IP Reservation facility.For networks not using IP reservation, network_cidr is always null.';