mirror of https://github.com/apache/cloudstack.git
refactor snapshot
This commit is contained in:
parent
35264f7087
commit
37cbe8890f
|
|
@ -18,12 +18,13 @@ package com.cloud.storage;
|
|||
|
||||
import java.util.Date;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.utils.fsm.StateObject;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.api.Identity;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.utils.fsm.StateObject;
|
||||
|
||||
public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, StateObject<Snapshot.State> {
|
||||
public enum Type {
|
||||
MANUAL,
|
||||
|
|
@ -85,8 +86,6 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity,
|
|||
|
||||
long getVolumeId();
|
||||
|
||||
String getPath();
|
||||
|
||||
String getName();
|
||||
|
||||
Date getCreated();
|
||||
|
|
|
|||
|
|
@ -79,4 +79,7 @@ public interface VolumeApiService {
|
|||
Volume attachVolumeToVM(AttachVolumeCmd command);
|
||||
|
||||
Volume detachVolumeFromVM(DetachVolumeCmd cmmd);
|
||||
|
||||
Snapshot takeSnapshot(Long volumeId, Long policyId)
|
||||
throws ResourceAllocationException;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,6 @@ public class SnapshotVO implements Snapshot {
|
|||
@Column(name="disk_offering_id")
|
||||
Long diskOfferingId;
|
||||
|
||||
@Expose
|
||||
@Column(name="path")
|
||||
String path;
|
||||
|
||||
@Expose
|
||||
@Column(name="name")
|
||||
String name;
|
||||
|
|
@ -76,18 +72,6 @@ public class SnapshotVO implements Snapshot {
|
|||
@Column(name=GenericDao.REMOVED_COLUMN)
|
||||
Date removed;
|
||||
|
||||
@Column(name="backup_snap_id")
|
||||
String backupSnapshotId;
|
||||
|
||||
@Column(name="swift_id")
|
||||
Long swiftId;
|
||||
|
||||
@Column(name="s3_id")
|
||||
Long s3Id;
|
||||
|
||||
@Column(name="prev_snap_id")
|
||||
long prevSnapshotId;
|
||||
|
||||
@Column(name="hypervisor_type")
|
||||
@Enumerated(value=EnumType.STRING)
|
||||
HypervisorType hypervisorType;
|
||||
|
|
@ -103,19 +87,17 @@ public class SnapshotVO implements Snapshot {
|
|||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public SnapshotVO(long dcId, long accountId, long domainId, Long volumeId, Long diskOfferingId, String path, String name, short snapshotType, String typeDescription, long size, HypervisorType hypervisorType ) {
|
||||
public SnapshotVO(long dcId, long accountId, long domainId, Long volumeId, Long diskOfferingId, String name, short snapshotType, String typeDescription, long size, HypervisorType hypervisorType ) {
|
||||
this.dataCenterId = dcId;
|
||||
this.accountId = accountId;
|
||||
this.domainId = domainId;
|
||||
this.volumeId = volumeId;
|
||||
this.diskOfferingId = diskOfferingId;
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.snapshotType = snapshotType;
|
||||
this.typeDescription = typeDescription;
|
||||
this.size = size;
|
||||
this.state = State.Allocated;
|
||||
this.prevSnapshotId = 0;
|
||||
this.hypervisorType = hypervisorType;
|
||||
this.version = "2.2";
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
|
|
@ -153,14 +135,6 @@ public class SnapshotVO implements Snapshot {
|
|||
this.volumeId = volumeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
|
@ -179,14 +153,6 @@ public class SnapshotVO implements Snapshot {
|
|||
return Type.values()[snapshotType];
|
||||
}
|
||||
|
||||
public Long getSwiftId() {
|
||||
return swiftId;
|
||||
}
|
||||
|
||||
public void setSwiftId(Long swiftId) {
|
||||
this.swiftId = swiftId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HypervisorType getHypervisorType() {
|
||||
return hypervisorType;
|
||||
|
|
@ -242,22 +208,6 @@ public class SnapshotVO implements Snapshot {
|
|||
this.state = state;
|
||||
}
|
||||
|
||||
public String getBackupSnapshotId(){
|
||||
return backupSnapshotId;
|
||||
}
|
||||
|
||||
public long getPrevSnapshotId(){
|
||||
return prevSnapshotId;
|
||||
}
|
||||
|
||||
public void setBackupSnapshotId(String backUpSnapshotId){
|
||||
this.backupSnapshotId = backUpSnapshotId;
|
||||
}
|
||||
|
||||
public void setPrevSnapshotId(long prevSnapshotId){
|
||||
this.prevSnapshotId = prevSnapshotId;
|
||||
}
|
||||
|
||||
public static Type getSnapshotType(String snapshotType) {
|
||||
for ( Type type : Type.values()) {
|
||||
if ( type.equals(snapshotType)) {
|
||||
|
|
@ -275,13 +225,4 @@ public class SnapshotVO implements Snapshot {
|
|||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public Long getS3Id() {
|
||||
return s3Id;
|
||||
}
|
||||
|
||||
public void setS3Id(Long s3Id) {
|
||||
this.s3Id = s3Id;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import javax.persistence.TemporalType;
|
|||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
|
||||
|
|
@ -329,5 +330,10 @@ public class VMTemplateHostVO implements VMTemplateStorageResourceAssoc, DataObj
|
|||
return this.getHostId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getObjectInStoreState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -281,5 +281,10 @@ public class VMTemplateStoragePoolVO implements VMTemplateStorageResourceAssoc,
|
|||
return this.getPoolId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getObjectInStoreState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import javax.persistence.TemporalType;
|
|||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
|
|
@ -354,5 +355,10 @@ public class VolumeHostVO implements InternalIdentity, DataObjectInStore {
|
|||
return this.getHostId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getObjectInStoreState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,4 +26,5 @@ public interface DataObjectInStore extends StateObject<ObjectInDataStoreStateMac
|
|||
public void setInstallPath(String path);
|
||||
public long getObjectId();
|
||||
public long getDataStoreId();
|
||||
public ObjectInDataStoreStateMachine.State getObjectInStoreState();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@
|
|||
*/
|
||||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
|
||||
|
||||
public interface SnapshotDataFactory {
|
||||
public SnapshotInfo getSnapshot(long snapshotId, DataStore store);
|
||||
public SnapshotInfo getSnapshot(DataObject obj, DataStore store);
|
||||
public SnapshotInfo getSnapshot(long snapshotId);
|
||||
public SnapshotInfo getSnapshot(long snapshotId, DataStoreRole role);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,11 @@ import com.cloud.storage.Snapshot;
|
|||
|
||||
public interface SnapshotInfo extends DataObject, Snapshot {
|
||||
public SnapshotInfo getParent();
|
||||
public String getPath();
|
||||
public SnapshotInfo getChild();
|
||||
public VolumeInfo getBaseVolume();
|
||||
public void addPayload(Object data);
|
||||
Long getDataCenterId();
|
||||
public Long getPrevSnapshotId();
|
||||
ObjectInDataStoreStateMachine.State getStatus();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
||||
public class SnapshotResult extends CommandResult {
|
||||
private SnapshotInfo snashot;
|
||||
private Answer answer;
|
||||
public SnapshotResult(SnapshotInfo snapshot, Answer answer) {
|
||||
this.setSnashot(snapshot);
|
||||
this.setAnswer(answer);
|
||||
}
|
||||
public SnapshotInfo getSnashot() {
|
||||
return snashot;
|
||||
}
|
||||
public void setSnashot(SnapshotInfo snashot) {
|
||||
this.snashot = snashot;
|
||||
}
|
||||
public Answer getAnswer() {
|
||||
return answer;
|
||||
}
|
||||
public void setAnswer(Answer answer) {
|
||||
this.answer = answer;
|
||||
}
|
||||
}
|
||||
|
|
@ -18,8 +18,9 @@
|
|||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
|
||||
|
||||
public interface SnapshotService {
|
||||
public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId);
|
||||
public SnapshotResult takeSnapshot(SnapshotInfo snapshot);
|
||||
public SnapshotInfo backupSnapshot(SnapshotInfo snapshot);
|
||||
public boolean deleteSnapshot(SnapshotInfo snapshot);
|
||||
public boolean revertSnapshot(SnapshotInfo snapshot);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
import com.cloud.storage.Snapshot;
|
||||
|
||||
|
||||
public interface SnapshotStrategy {
|
||||
public SnapshotInfo takeSnapshot(SnapshotInfo snapshot);
|
||||
public SnapshotInfo backupSnapshot(SnapshotInfo snapshot);
|
||||
public boolean deleteSnapshot(Long snapshotId);
|
||||
public boolean canHandle(Snapshot snapshot);
|
||||
}
|
||||
|
|
@ -79,4 +79,6 @@ public interface VolumeService {
|
|||
|
||||
void handleVolumeSync(DataStore store);
|
||||
|
||||
SnapshotInfo takeSnapshot(VolumeInfo volume);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,31 +18,26 @@
|
|||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class CreateObjectAnswer extends Answer {
|
||||
private String path;
|
||||
private Long size;
|
||||
private DataTO data;
|
||||
protected CreateObjectAnswer() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CreateObjectAnswer(Command cmd, String path, Long size) {
|
||||
super(cmd);
|
||||
this.path = path;
|
||||
this.size = size;
|
||||
public CreateObjectAnswer(DataTO data) {
|
||||
super();
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public CreateObjectAnswer(Command cmd, boolean status, String result) {
|
||||
super(cmd, status, result);
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
public DataTO getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return this.size;
|
||||
}
|
||||
public CreateObjectAnswer(String errMsg) {
|
||||
super(null, false, errMsg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,14 +18,16 @@
|
|||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class CreateObjectCommand extends Command implements StorageSubSystemCommand {
|
||||
protected String objectUri;
|
||||
private DataTO data;
|
||||
|
||||
public CreateObjectCommand(String objectUri) {
|
||||
public CreateObjectCommand(DataTO obj) {
|
||||
super();
|
||||
this.objectUri = objectUri;
|
||||
this.data = obj;
|
||||
}
|
||||
|
||||
protected CreateObjectCommand() {
|
||||
|
|
@ -38,8 +40,8 @@ public class CreateObjectCommand extends Command implements StorageSubSystemComm
|
|||
return false;
|
||||
}
|
||||
|
||||
public String getObjectUri() {
|
||||
return this.objectUri;
|
||||
public DataTO getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,20 +23,19 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
|
||||
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.utils.fsm.StateDao;
|
||||
|
||||
public interface SnapshotDataStoreDao extends GenericDao<SnapshotDataStoreVO, Long>, StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Event, DataObjectInStore> {
|
||||
|
||||
public List<SnapshotDataStoreVO> listByStoreId(long id);
|
||||
public List<SnapshotDataStoreVO> listByStoreId(long id, DataStoreRole role);
|
||||
|
||||
public void deletePrimaryRecordsForStore(long id);
|
||||
|
||||
public SnapshotDataStoreVO findByStoreSnapshot(long storeId, long snapshotId);
|
||||
public SnapshotDataStoreVO findByStoreSnapshot(DataStoreRole role, long storeId, long snapshotId);
|
||||
|
||||
public SnapshotDataStoreVO findByStoreSnapshot(long storeId, long snapshotId, boolean lock);
|
||||
|
||||
public SnapshotDataStoreVO findBySnapshot(long snapshotId);
|
||||
|
||||
public List<SnapshotDataStoreVO> listDestroyed(long storeId);
|
||||
public SnapshotDataStoreVO findBySnapshot(long snapshotId, DataStoreRole role);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ import javax.persistence.TemporalType;
|
|||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.fsm.StateObject;
|
||||
|
||||
|
|
@ -51,6 +51,10 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
|||
|
||||
@Column(name="store_id")
|
||||
private long dataStoreId;
|
||||
|
||||
@Column(name="store_role")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private DataStoreRole role;
|
||||
|
||||
@Column(name="snapshot_id")
|
||||
private long snapshotId;
|
||||
|
|
@ -62,23 +66,23 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
|||
@Temporal(value=TemporalType.TIMESTAMP)
|
||||
private Date lastUpdated = null;
|
||||
|
||||
|
||||
@Column (name="size")
|
||||
private long size;
|
||||
|
||||
@Column (name="physical_size")
|
||||
private long physicalSize;
|
||||
|
||||
|
||||
@Column(name="parent_snapshot_id")
|
||||
private long parentSnapshotId;
|
||||
|
||||
@Column (name="job_id")
|
||||
private String jobId;
|
||||
|
||||
@Column (name="install_path")
|
||||
private String installPath;
|
||||
|
||||
|
||||
@Column(name="destroyed")
|
||||
boolean destroyed = false;
|
||||
@Column(name = GenericDao.REMOVED_COLUMN)
|
||||
Date removed;
|
||||
|
||||
@Column(name="update_count", updatable = true, nullable=false)
|
||||
protected long updatedCount;
|
||||
|
|
@ -201,14 +205,6 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
|||
return physicalSize;
|
||||
}
|
||||
|
||||
public void setDestroyed(boolean destroyed) {
|
||||
this.destroyed = destroyed;
|
||||
}
|
||||
|
||||
public boolean getDestroyed() {
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
public long getVolumeSize() {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -245,5 +241,24 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
|||
return this.getSnapshotId();
|
||||
}
|
||||
|
||||
public DataStoreRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(DataStoreRole role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getObjectInStoreState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public long getParentSnapshotId() {
|
||||
return parentSnapshotId;
|
||||
}
|
||||
|
||||
public void setParentSnapshotId(long parentSnapshotId) {
|
||||
this.parentSnapshotId = parentSnapshotId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import javax.persistence.TemporalType;
|
|||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
|
||||
|
|
@ -320,5 +321,8 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
|||
return this.getTemplateId();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public State getObjectInStoreState() {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import javax.persistence.TemporalType;
|
|||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
|
|
@ -351,5 +352,10 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
|
|||
return this.getVolumeId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getObjectInStoreState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package org.apache.cloudstack.storage.to;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
|
||||
public class SnapshotObjectTO implements DataTO {
|
||||
private String path;
|
||||
@Override
|
||||
public DataObjectType getObjectType() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStoreTO getDataStore() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
|
|
@ -398,62 +398,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||
StoragePoolVO poolvo = pools.get(0);
|
||||
StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(
|
||||
poolvo.getId(), DataStoreRole.Primary);
|
||||
if (snapshot.getVersion() != null
|
||||
&& snapshot.getVersion().equalsIgnoreCase("2.1")) {
|
||||
VolumeVO volume = this.volDao.findByIdIncludingRemoved(volumeId);
|
||||
if (volume == null) {
|
||||
throw new CloudRuntimeException("failed to upgrade snapshot "
|
||||
+ snapshotId + " due to unable to find orignal volume:"
|
||||
+ volumeId + ", try it later ");
|
||||
}
|
||||
if (volume.getTemplateId() == null) {
|
||||
snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2");
|
||||
} else {
|
||||
template = templateDao.findByIdIncludingRemoved(volume
|
||||
.getTemplateId());
|
||||
if (template == null) {
|
||||
throw new CloudRuntimeException(
|
||||
"failed to upgrade snapshot "
|
||||
+ snapshotId
|
||||
+ " due to unalbe to find orignal template :"
|
||||
+ volume.getTemplateId()
|
||||
+ ", try it later ");
|
||||
}
|
||||
Long origTemplateId = template.getId();
|
||||
Long origTmpltAccountId = template.getAccountId();
|
||||
if (!this.volDao.lockInLockTable(volumeId.toString(), 10)) {
|
||||
throw new CloudRuntimeException(
|
||||
"failed to upgrade snapshot " + snapshotId
|
||||
+ " due to volume:" + volumeId
|
||||
+ " is being used, try it later ");
|
||||
}
|
||||
UpgradeSnapshotCommand cmd = new UpgradeSnapshotCommand(null,
|
||||
secondaryStorageURL, dcId, accountId, volumeId,
|
||||
origTemplateId, origTmpltAccountId, null,
|
||||
snapshot.getBackupSnapshotId(), snapshot.getName(),
|
||||
"2.1");
|
||||
if (!this.volDao.lockInLockTable(volumeId.toString(), 10)) {
|
||||
throw new CloudRuntimeException(
|
||||
"Creating template failed due to volume:"
|
||||
+ volumeId
|
||||
+ " is being used, try it later ");
|
||||
}
|
||||
Answer answer = null;
|
||||
try {
|
||||
answer = this.storageMgr.sendToPool(pool, cmd);
|
||||
cmd = null;
|
||||
} catch (StorageUnavailableException e) {
|
||||
} finally {
|
||||
this.volDao.unlockFromLockTable(volumeId.toString());
|
||||
}
|
||||
if ((answer != null) && answer.getResult()) {
|
||||
snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2");
|
||||
} else {
|
||||
throw new CloudRuntimeException(
|
||||
"Unable to upgrade snapshot");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshot.getSwiftId() != null && snapshot.getSwiftId() != 0) {
|
||||
snapshotMgr.downloadSnapshotsFromSwift(snapshot);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
<artifactId>cloud-engine-storage</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-engine-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ import com.cloud.storage.DataStoreRole;
|
|||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.utils.db.SearchCriteria2;
|
||||
import com.cloud.utils.db.SearchCriteriaService;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Component
|
||||
|
|
@ -49,36 +52,30 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
|
|||
VolumeDataFactory volumeFactory;
|
||||
@Override
|
||||
public SnapshotInfo getSnapshot(long snapshotId, DataStore store) {
|
||||
SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
|
||||
SnapshotVO snapshot = snapshotDao.findById(snapshotId);
|
||||
SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store);
|
||||
return so;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo getSnapshot(long snapshotId) {
|
||||
SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
|
||||
SnapshotObject so = null;
|
||||
if (snapshot.getState() == Snapshot.State.BackedUp) {
|
||||
DataStore store = null;
|
||||
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findBySnapshot(snapshotId);
|
||||
if ( snapshotStore != null ){
|
||||
store = this.storeMgr.getDataStore(snapshotStore.getDataStoreId(), DataStoreRole.Image);
|
||||
}
|
||||
so = SnapshotObject.getSnapshotObject(snapshot, store);
|
||||
} else {
|
||||
VolumeInfo volume = this.volumeFactory.getVolume(snapshot.getVolumeId());
|
||||
so = SnapshotObject.getSnapshotObject(snapshot, volume.getDataStore());
|
||||
}
|
||||
return so;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo getSnapshot(DataObject obj, DataStore store) {
|
||||
SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(obj.getId());
|
||||
SnapshotVO snapshot = snapshotDao.findById(obj.getId());
|
||||
if (snapshot == null) {
|
||||
throw new CloudRuntimeException("Can't find snapshot: " + obj.getId());
|
||||
}
|
||||
SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store);
|
||||
return so;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo getSnapshot(long snapshotId, DataStoreRole role) {
|
||||
SnapshotVO snapshot = snapshotDao.findById(snapshotId);
|
||||
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findBySnapshot(snapshotId, role);
|
||||
if (snapshotStore == null) {
|
||||
return null;
|
||||
}
|
||||
DataStore store = this.storeMgr.getDataStore(snapshotStore.getDataStoreId(), role);
|
||||
SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store);
|
||||
return so;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,11 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
|
||||
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
|
@ -55,6 +59,8 @@ public class SnapshotObject implements SnapshotInfo {
|
|||
@Inject protected SnapshotStateMachineManager stateMachineMgr;
|
||||
@Inject
|
||||
ObjectInDataStoreManager ojbectInStoreMgr;
|
||||
@Inject
|
||||
SnapshotDataStoreDao snapshotStore;
|
||||
public SnapshotObject() {
|
||||
|
||||
}
|
||||
|
|
@ -76,6 +82,7 @@ public class SnapshotObject implements SnapshotInfo {
|
|||
|
||||
@Override
|
||||
public SnapshotInfo getParent() {
|
||||
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
|
@ -149,11 +156,7 @@ public class SnapshotObject implements SnapshotInfo {
|
|||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.snapshot.getPath();
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.snapshot.setPath(path);
|
||||
return this.ojbectInStoreMgr.findObject(this, getDataStore()).getInstallPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -196,9 +199,6 @@ public class SnapshotObject implements SnapshotInfo {
|
|||
return this.snapshot.getDomainId();
|
||||
}
|
||||
|
||||
public void setPrevSnapshotId(Long id) {
|
||||
this.snapshot.setPrevSnapshotId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getDataCenterId() {
|
||||
|
|
@ -212,15 +212,8 @@ public class SnapshotObject implements SnapshotInfo {
|
|||
|
||||
@Override
|
||||
public Long getPrevSnapshotId() {
|
||||
return this.snapshot.getPrevSnapshotId();
|
||||
}
|
||||
|
||||
public void setBackupSnapshotId(String id) {
|
||||
this.snapshot.setBackupSnapshotId(id);
|
||||
}
|
||||
|
||||
public String getBackupSnapshotId() {
|
||||
return this.snapshot.getBackupSnapshotId();
|
||||
SnapshotDataStoreVO snapshotStoreVO = this.snapshotStore.findBySnapshot(this.getId(), this.getDataStore().getRole());
|
||||
return snapshotStoreVO.getParentSnapshotId();
|
||||
}
|
||||
|
||||
public SnapshotVO getSnapshotVO(){
|
||||
|
|
@ -234,8 +227,28 @@ public class SnapshotObject implements SnapshotInfo {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void processEvent(org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event event, Answer answer) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) {
|
||||
SnapshotDataStoreVO snapshotStore = this.snapshotStore.findByStoreSnapshot(this.getDataStore().getRole(),
|
||||
this.getDataStore().getId(), this.getId());
|
||||
if (answer instanceof CreateObjectAnswer) {
|
||||
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)((CreateObjectAnswer) answer).getData();
|
||||
snapshotStore.setInstallPath(snapshotTO.getPath());
|
||||
this.snapshotStore.update(snapshotStore.getId(), snapshotStore);
|
||||
} else {
|
||||
throw new CloudRuntimeException("Unknown answer: " + answer.getClass());
|
||||
}
|
||||
this.processEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectInDataStoreStateMachine.State getStatus() {
|
||||
return this.ojbectInStoreMgr.findObject(this, store).getObjectInStoreState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPayload(Object data) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
|
|
@ -38,6 +37,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotResult;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
|
|
@ -51,30 +51,19 @@ import org.springframework.stereotype.Component;
|
|||
|
||||
import com.cloud.agent.api.BackupSnapshotAnswer;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.VolumeManager;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
|
||||
@Component
|
||||
|
|
@ -92,8 +81,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
protected SnapshotDao _snapshotDao;
|
||||
@Inject
|
||||
protected SnapshotDataStoreDao _snapshotStoreDao;
|
||||
@Inject
|
||||
private ResourceManager _resourceMgr;
|
||||
|
||||
@Inject
|
||||
protected SnapshotManager snapshotMgr;
|
||||
@Inject
|
||||
|
|
@ -164,81 +152,24 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
CreateSnapshotContext<CreateCmdResult> context) {
|
||||
CreateCmdResult result = callback.getResult();
|
||||
SnapshotObject snapshot = (SnapshotObject)context.snapshot;
|
||||
VolumeInfo volume = context.volume;
|
||||
AsyncCallFuture<SnapshotResult> future = context.future;
|
||||
SnapshotResult snapResult = new SnapshotResult(snapshot);
|
||||
SnapshotResult snapResult = new SnapshotResult(snapshot, result.getAnswer());
|
||||
if (result.isFailed()) {
|
||||
s_logger.debug("create snapshot " + context.snapshot.getName() + " failed: " + result.getResult());
|
||||
try {
|
||||
snapshot.processEvent(Snapshot.Event.OperationFailed);
|
||||
} catch (NoTransitionException nte) {
|
||||
s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
|
||||
snapshot.processEvent(Event.OperationFailed);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to update snapshot state due to " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
snapResult.setResult(result.getResult());
|
||||
future.complete(snapResult);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
SnapshotVO preSnapshotVO = this.snapshotMgr.getParentSnapshot(volume, snapshot);
|
||||
String preSnapshotPath = null;
|
||||
if (preSnapshotVO != null) {
|
||||
preSnapshotPath = preSnapshotVO.getPath();
|
||||
}
|
||||
SnapshotVO snapshotVO = this._snapshotDao.findById(snapshot.getId());
|
||||
// The snapshot was successfully created
|
||||
if (preSnapshotPath != null && preSnapshotPath.equals(result.getPath())) {
|
||||
// empty snapshot
|
||||
s_logger.debug("CreateSnapshot: this is empty snapshot ");
|
||||
|
||||
snapshotVO.setPath(preSnapshotPath);
|
||||
snapshotVO.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId());
|
||||
snapshotVO.setPrevSnapshotId(preSnapshotVO.getId());
|
||||
snapshot.processEvent(Snapshot.Event.OperationNotPerformed);
|
||||
} else {
|
||||
long preSnapshotId = 0;
|
||||
|
||||
if (preSnapshotVO != null && preSnapshotVO.getBackupSnapshotId() != null) {
|
||||
preSnapshotId = preSnapshotVO.getId();
|
||||
int _deltaSnapshotMax = NumbersUtil.parseInt(_configDao.getValue("snapshot.delta.max"), SnapshotManager.DELTAMAX);
|
||||
int deltaSnap = _deltaSnapshotMax;
|
||||
|
||||
int i;
|
||||
for (i = 1; i < deltaSnap; i++) {
|
||||
String prevBackupUuid = preSnapshotVO.getBackupSnapshotId();
|
||||
// previous snapshot doesn't have backup, create a full snapshot
|
||||
if (prevBackupUuid == null) {
|
||||
preSnapshotId = 0;
|
||||
break;
|
||||
}
|
||||
long preSSId = preSnapshotVO.getPrevSnapshotId();
|
||||
if (preSSId == 0) {
|
||||
break;
|
||||
}
|
||||
preSnapshotVO = _snapshotDao.findByIdIncludingRemoved(preSSId);
|
||||
}
|
||||
if (i >= deltaSnap) {
|
||||
preSnapshotId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//If the volume is moved around, backup a full snapshot to secondary storage
|
||||
if (volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId())) {
|
||||
preSnapshotId = 0;
|
||||
//TODO: fix this hack
|
||||
VolumeVO volumeVO = this.volumeDao.findById(volume.getId());
|
||||
volumeVO.setLastPoolId(volume.getPoolId());
|
||||
this.volumeDao.update(volume.getId(), volumeVO);
|
||||
}
|
||||
|
||||
snapshot.setPath(result.getPath());
|
||||
snapshot.setPrevSnapshotId(preSnapshotId);
|
||||
|
||||
snapshot.processEvent(Snapshot.Event.OperationSucceeded);
|
||||
snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(snapshot.getId()));
|
||||
}
|
||||
snapshot.processEvent(Event.OperationSuccessed, result.getAnswer());
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to create snapshot: ", e);
|
||||
snapResult.setResult(e.toString());
|
||||
|
|
@ -253,36 +184,49 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
return null;
|
||||
}
|
||||
|
||||
class SnapshotResult extends CommandResult {
|
||||
SnapshotInfo snashot;
|
||||
public SnapshotResult(SnapshotInfo snapshot) {
|
||||
this.snashot = snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected SnapshotInfo createSnapshotOnPrimary(VolumeInfo volume, Long snapshotId) {
|
||||
SnapshotObject snapshot = (SnapshotObject)this.snapshotfactory.getSnapshot(snapshotId);
|
||||
if (snapshot == null) {
|
||||
throw new CloudRuntimeException("Can not find snapshot " + snapshotId);
|
||||
@Override
|
||||
public SnapshotResult takeSnapshot(SnapshotInfo snap) {
|
||||
SnapshotObject snapshot = (SnapshotObject)snap;
|
||||
|
||||
SnapshotObject snapshotOnPrimary = null;
|
||||
try {
|
||||
snapshotOnPrimary = (SnapshotObject)snap.getDataStore().create(snapshot);
|
||||
} catch(Exception e) {
|
||||
s_logger.debug("Failed to create snapshot state on data store due to " + e.getMessage());
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
snapshot.processEvent(Snapshot.Event.CreateRequested);
|
||||
} catch (NoTransitionException nte) {
|
||||
s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
|
||||
throw new CloudRuntimeException("Failed to update snapshot state due to " + nte.getMessage());
|
||||
snapshotOnPrimary.processEvent(Snapshot.Event.CreateRequested);
|
||||
} catch (NoTransitionException e) {
|
||||
s_logger.debug("Failed to change snapshot state: " + e.toString());
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
snapshotOnPrimary.processEvent(Event.CreateOnlyRequested);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to change snapshot state: " + e.toString());
|
||||
try {
|
||||
snapshotOnPrimary.processEvent(Snapshot.Event.OperationFailed);
|
||||
} catch (NoTransitionException e1) {
|
||||
s_logger.debug("Failed to change snapshot state: " + e1.toString());
|
||||
}
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
|
||||
AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
|
||||
try {
|
||||
CreateSnapshotContext<CommandResult> context = new CreateSnapshotContext<CommandResult>(
|
||||
null, volume, snapshot, future);
|
||||
null, snap.getBaseVolume(), snapshotOnPrimary, future);
|
||||
AsyncCallbackDispatcher<SnapshotServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher
|
||||
.create(this);
|
||||
caller.setCallback(
|
||||
caller.getTarget().createSnapshotAsyncCallback(null, null))
|
||||
.setContext(context);
|
||||
PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver)volume.getDataStore().getDriver();
|
||||
PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver)snapshotOnPrimary.getDataStore().getDriver();
|
||||
primaryStore.takeSnapshot(snapshot, caller);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e);
|
||||
|
|
@ -302,7 +246,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
s_logger.debug("Failed to create snapshot:" + result.getResult());
|
||||
throw new CloudRuntimeException(result.getResult());
|
||||
}
|
||||
return result.snashot;
|
||||
return result;
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.debug("Failed to create snapshot", e);
|
||||
throw new CloudRuntimeException("Failed to create snapshot", e);
|
||||
|
|
@ -313,78 +257,11 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
|
||||
}
|
||||
|
||||
private boolean hostSupportSnapsthot(HostVO host) {
|
||||
if (host.getHypervisorType() != HypervisorType.KVM) {
|
||||
return true;
|
||||
}
|
||||
// Determine host capabilities
|
||||
String caps = host.getCapabilities();
|
||||
|
||||
if (caps != null) {
|
||||
String[] tokens = caps.split(",");
|
||||
for (String token : tokens) {
|
||||
if (token.contains("snapshot")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean supportedByHypervisor(VolumeInfo volume) {
|
||||
if (volume.getHypervisorType().equals(HypervisorType.KVM)) {
|
||||
StoragePool storagePool = (StoragePool)volume.getDataStore();
|
||||
ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId());
|
||||
List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cluster.getId());
|
||||
if (hosts != null && !hosts.isEmpty()) {
|
||||
HostVO host = hosts.get(0);
|
||||
if (!hostSupportSnapsthot(host)) {
|
||||
throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if volume is attached to a vm in destroyed or expunging state; disallow
|
||||
if (volume.getInstanceId() != null) {
|
||||
UserVmVO userVm = _vmDao.findById(volume.getInstanceId());
|
||||
if (userVm != null) {
|
||||
if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) {
|
||||
throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId() + " is associated with vm:" + userVm.getInstanceName() + " is in "
|
||||
+ userVm.getState().toString() + " state");
|
||||
}
|
||||
|
||||
if(userVm.getHypervisorType() == HypervisorType.VMware || userVm.getHypervisorType() == HypervisorType.KVM) {
|
||||
List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
|
||||
if(activeSnapshots.size() > 1)
|
||||
throw new CloudRuntimeException("There is other active snapshot tasks on the instance to which the volume is attached, please try again later");
|
||||
}
|
||||
|
||||
List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(),
|
||||
VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging);
|
||||
if (activeVMSnapshots.size() > 0) {
|
||||
throw new CloudRuntimeException(
|
||||
"There is other active vm snapshot tasks on the instance to which the volume is attached, please try again later");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId) {
|
||||
|
||||
supportedByHypervisor(volume);
|
||||
|
||||
SnapshotInfo snapshot = createSnapshotOnPrimary(volume, snapshotId);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
|
||||
SnapshotObject snapObj = (SnapshotObject)snapshot;
|
||||
AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
|
||||
SnapshotResult result = new SnapshotResult(snapshot);
|
||||
SnapshotResult result = new SnapshotResult(snapshot, null);
|
||||
try {
|
||||
|
||||
snapObj.processEvent(Snapshot.Event.BackupToSecondary);
|
||||
|
|
@ -420,7 +297,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
|
||||
try {
|
||||
SnapshotResult res = future.get();
|
||||
SnapshotInfo destSnapshot = res.snashot;
|
||||
SnapshotInfo destSnapshot = res.getSnashot();
|
||||
return destSnapshot;
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.debug("failed copy snapshot", e);
|
||||
|
|
@ -438,7 +315,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
SnapshotInfo destSnapshot = context.destSnapshot;
|
||||
SnapshotObject srcSnapshot = (SnapshotObject)context.srcSnapshot;
|
||||
AsyncCallFuture<SnapshotResult> future = context.future;
|
||||
SnapshotResult snapResult = new SnapshotResult(destSnapshot);
|
||||
SnapshotResult snapResult = new SnapshotResult(destSnapshot, result.getAnswer());
|
||||
if (result.isFailed()) {
|
||||
snapResult.setResult(result.getResult());
|
||||
future.complete(snapResult);
|
||||
|
|
@ -453,7 +330,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
objInStoreMgr.update(destSnapshot, Event.OperationSuccessed);
|
||||
|
||||
srcSnapshot.processEvent(Snapshot.Event.OperationSucceeded);
|
||||
snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(destSnapshot.getId()));
|
||||
snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(destSnapshot.getId(), destSnapshot.getDataStore()), answer);
|
||||
future.complete(snapResult);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to update snapshot state", e);
|
||||
|
|
@ -465,7 +342,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
|
||||
@DB
|
||||
protected boolean destroySnapshotBackUp(SnapshotVO snapshot) {
|
||||
SnapshotDataStoreVO snapshotStore = this._snapshotStoreDao.findBySnapshot(snapshot.getId());
|
||||
SnapshotDataStoreVO snapshotStore = this._snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Image);
|
||||
if ( snapshotStore == null ){
|
||||
s_logger.debug("Can't find snapshot" + snapshot.getId() + " backed up into image store");
|
||||
return false;
|
||||
|
|
@ -510,81 +387,19 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
if (result.isFailed()) {
|
||||
s_logger.debug("delete snapshot failed" + result.getResult());
|
||||
snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
|
||||
SnapshotResult res = new SnapshotResult(context.snapshot);
|
||||
SnapshotResult res = new SnapshotResult(context.snapshot, null);
|
||||
future.complete(res);
|
||||
return null;
|
||||
}
|
||||
snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
|
||||
SnapshotResult res = new SnapshotResult(context.snapshot);
|
||||
SnapshotResult res = new SnapshotResult(context.snapshot, null);
|
||||
future.complete(res);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteSnapshot(SnapshotInfo snapInfo) {
|
||||
Long snapshotId = snapInfo.getId();
|
||||
SnapshotObject snapshot = (SnapshotObject)snapInfo;
|
||||
|
||||
if (!Snapshot.State.BackedUp.equals(snapshot.getState())) {
|
||||
throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is not in BackedUp Status");
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId);
|
||||
}
|
||||
SnapshotVO lastSnapshot = null;
|
||||
if (snapshot.getBackupSnapshotId() != null) {
|
||||
List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(snapshot.getVolumeId(), snapshot.getBackupSnapshotId());
|
||||
if (snaps != null && snaps.size() > 1) {
|
||||
snapshot.setBackupSnapshotId(null);
|
||||
SnapshotVO snapshotVO = this._snapshotDao.findById(snapshotId);
|
||||
_snapshotDao.update(snapshot.getId(), snapshotVO);
|
||||
}
|
||||
}
|
||||
|
||||
_snapshotDao.remove(snapshotId);
|
||||
|
||||
long lastId = snapshotId;
|
||||
boolean destroy = false;
|
||||
while (true) {
|
||||
lastSnapshot = _snapshotDao.findNextSnapshot(lastId);
|
||||
if (lastSnapshot == null) {
|
||||
// if all snapshots after this snapshot in this chain are removed, remove those snapshots.
|
||||
destroy = true;
|
||||
break;
|
||||
}
|
||||
if (lastSnapshot.getRemoved() == null) {
|
||||
// if there is one child not removed, then can not remove back up snapshot.
|
||||
break;
|
||||
}
|
||||
lastId = lastSnapshot.getId();
|
||||
}
|
||||
if (destroy) {
|
||||
lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
|
||||
while (lastSnapshot.getRemoved() != null) {
|
||||
String BackupSnapshotId = lastSnapshot.getBackupSnapshotId();
|
||||
if (BackupSnapshotId != null) {
|
||||
List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(lastSnapshot.getVolumeId(), BackupSnapshotId);
|
||||
if (snaps != null && snaps.size() > 1) {
|
||||
lastSnapshot.setBackupSnapshotId(null);
|
||||
_snapshotDao.update(lastSnapshot.getId(), lastSnapshot);
|
||||
} else {
|
||||
if (destroySnapshotBackUp(lastSnapshot)) {
|
||||
|
||||
} else {
|
||||
s_logger.debug("Destroying snapshot backup failed " + lastSnapshot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastId = lastSnapshot.getPrevSnapshotId();
|
||||
if (lastId == 0) {
|
||||
break;
|
||||
}
|
||||
lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package org.apache.cloudstack.storage.snapshot;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
|
||||
|
||||
public abstract class SnapshotStrategyBase implements SnapshotStrategy {
|
||||
@Inject
|
||||
SnapshotService snapshotSvr;
|
||||
//the default strategy is:
|
||||
//create snapshot,
|
||||
//backup, then delete snapshot on primary storage
|
||||
@Override
|
||||
public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
|
||||
return snapshotSvr.takeSnapshot(snapshot).getSnashot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
|
||||
return snapshotSvr.backupSnapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
package org.apache.cloudstack.storage.snapshot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
|
||||
@Component
|
||||
public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
||||
private static final Logger s_logger = Logger
|
||||
.getLogger(XenserverSnapshotStrategy.class);
|
||||
|
||||
@Inject
|
||||
SnapshotManager snapshotMgr;
|
||||
@Inject
|
||||
SnapshotService snapshotSvr;
|
||||
@Inject
|
||||
DataStoreManager dataStoreMgr;
|
||||
@Inject
|
||||
SnapshotDataStoreDao snapshotStoreDao;
|
||||
@Inject
|
||||
ConfigurationDao configDao;
|
||||
@Inject
|
||||
SnapshotDataFactory snapshotDataFactory;
|
||||
|
||||
@Override
|
||||
public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
|
||||
SnapshotInfo parentSnapshot = snapshot.getParent();
|
||||
if (parentSnapshot.getPath().equalsIgnoreCase(snapshot.getPath())) {
|
||||
s_logger.debug("backup an empty snapshot");
|
||||
//don't need to backup this snapshot
|
||||
SnapshotDataStoreVO parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), DataStoreRole.Image);
|
||||
if (parentSnapshotOnBackupStore != null &&
|
||||
parentSnapshotOnBackupStore.getState() == State.Ready) {
|
||||
DataStore store = dataStoreMgr.getDataStore(parentSnapshotOnBackupStore.getDataStoreId(),
|
||||
parentSnapshotOnBackupStore.getRole());
|
||||
|
||||
SnapshotInfo snapshotOnImageStore = (SnapshotInfo)store.create(snapshot);
|
||||
snapshotOnImageStore.processEvent(Event.CreateOnlyRequested);
|
||||
|
||||
SnapshotObjectTO snapTO = new SnapshotObjectTO();
|
||||
snapTO.setPath(parentSnapshotOnBackupStore.getInstallPath());
|
||||
CreateObjectAnswer createSnapshotAnswer = new CreateObjectAnswer(snapTO);
|
||||
|
||||
snapshotOnImageStore.processEvent(Event.OperationSuccessed, createSnapshotAnswer);
|
||||
SnapshotObject snapObj = (SnapshotObject)snapshot;
|
||||
try {
|
||||
snapObj.processEvent(Snapshot.Event.OperationNotPerformed);
|
||||
} catch (NoTransitionException e) {
|
||||
s_logger.debug("Failed to change state: " + snapshot.getId() + ": " +e.toString());
|
||||
throw new CloudRuntimeException(e.toString());
|
||||
}
|
||||
return this.snapshotDataFactory.getSnapshot(snapObj.getId(), store);
|
||||
} else {
|
||||
s_logger.debug("parent snapshot hasn't been backed up yet");
|
||||
}
|
||||
}
|
||||
|
||||
//determine full snapshot backup or not
|
||||
|
||||
boolean fullBackup = false;
|
||||
long preSnapshotId = 0;
|
||||
if (parentSnapshot != null) {
|
||||
|
||||
preSnapshotId = parentSnapshot.getId();
|
||||
int _deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"), SnapshotManager.DELTAMAX);
|
||||
int deltaSnap = _deltaSnapshotMax;
|
||||
|
||||
int i;
|
||||
SnapshotDataStoreVO parentSnapshotOnBackupStore = null;
|
||||
for (i = 1; i < deltaSnap; i++) {
|
||||
parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), DataStoreRole.Image);
|
||||
|
||||
Long prevBackupId = parentSnapshotOnBackupStore.getParentSnapshotId();
|
||||
|
||||
if (prevBackupId == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(prevBackupId, DataStoreRole.Image);
|
||||
}
|
||||
if (i >= deltaSnap) {
|
||||
fullBackup = true;
|
||||
}
|
||||
}
|
||||
|
||||
snapshot.addPayload(fullBackup);
|
||||
return this.snapshotSvr.backupSnapshot(snapshot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteSnapshot(SnapshotInfo snapshot) {
|
||||
Long snapshotId = snapshot.getId();
|
||||
SnapshotObject snapObj = (SnapshotObject)snapshot;
|
||||
|
||||
if (!Snapshot.State.BackedUp.equals(snapshot.getState()) || !Snapshot) {
|
||||
throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is not in BackedUp Status");
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId);
|
||||
}
|
||||
SnapshotVO lastSnapshot = null;
|
||||
if (snapshot.getPrevSnapshotId() != null) {
|
||||
List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(snapshot.getVolumeId(), snapshot.getBackupSnapshotId());
|
||||
if (snaps != null && snaps.size() > 1) {
|
||||
snapshot.setBackupSnapshotId(null);
|
||||
SnapshotVO snapshotVO = this._snapshotDao.findById(snapshotId);
|
||||
_snapshotDao.update(snapshot.getId(), snapshotVO);
|
||||
}
|
||||
}
|
||||
|
||||
_snapshotDao.remove(snapshotId);
|
||||
|
||||
long lastId = snapshotId;
|
||||
boolean destroy = false;
|
||||
while (true) {
|
||||
lastSnapshot = _snapshotDao.findNextSnapshot(lastId);
|
||||
if (lastSnapshot == null) {
|
||||
// if all snapshots after this snapshot in this chain are removed, remove those snapshots.
|
||||
destroy = true;
|
||||
break;
|
||||
}
|
||||
if (lastSnapshot.getRemoved() == null) {
|
||||
// if there is one child not removed, then can not remove back up snapshot.
|
||||
break;
|
||||
}
|
||||
lastId = lastSnapshot.getId();
|
||||
}
|
||||
if (destroy) {
|
||||
lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
|
||||
while (lastSnapshot.getRemoved() != null) {
|
||||
String BackupSnapshotId = lastSnapshot.getBackupSnapshotId();
|
||||
if (BackupSnapshotId != null) {
|
||||
List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(lastSnapshot.getVolumeId(), BackupSnapshotId);
|
||||
if (snaps != null && snaps.size() > 1) {
|
||||
lastSnapshot.setBackupSnapshotId(null);
|
||||
_snapshotDao.update(lastSnapshot.getId(), lastSnapshot);
|
||||
} else {
|
||||
if (destroySnapshotBackUp(lastSnapshot)) {
|
||||
|
||||
} else {
|
||||
s_logger.debug("Destroying snapshot backup failed " + lastSnapshot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastId = lastSnapshot.getPrevSnapshotId();
|
||||
if (lastId == 0) {
|
||||
break;
|
||||
}
|
||||
lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(SnapshotInfo snapshot) {
|
||||
if (snapshot.getHypervisorType() == HypervisorType.XenServer) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
|
||||
snapshot = snapshotSvr.takeSnapshot(snapshot).getSnashot();
|
||||
//TODO: add async
|
||||
return this.backupSnapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
|
@ -120,6 +120,12 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
|
|||
if ( obj.getType() == DataObjectType.TEMPLATE){
|
||||
VMTemplateStoragePoolVO vo = new VMTemplateStoragePoolVO(dataStore.getId(), obj.getId());
|
||||
vo = templatePoolDao.persist(vo);
|
||||
} else if (obj.getType() == DataObjectType.SNAPSHOT) {
|
||||
SnapshotDataStoreVO ss = new SnapshotDataStoreVO();
|
||||
ss.setSnapshotId(obj.getId());
|
||||
ss.setDataStoreId(dataStore.getId());
|
||||
ss.setRole(dataStore.getRole());
|
||||
ss = snapshotDataStoreDao.persist(ss);
|
||||
}
|
||||
} else {
|
||||
// Image store
|
||||
|
|
@ -137,6 +143,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
|
|||
SnapshotDataStoreVO ss = new SnapshotDataStoreVO();
|
||||
ss.setSnapshotId(obj.getId());
|
||||
ss.setDataStoreId(dataStore.getId());
|
||||
ss.setRole(dataStore.getRole());
|
||||
if (dataStore.getRole() == DataStoreRole.ImageCache) {
|
||||
ss.setInstallPath("/snapshots/" + snapshotDao.findById(obj.getId()).getAccountId() + "/" + obj.getId());
|
||||
}
|
||||
|
|
@ -185,7 +192,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
|
|||
return true;
|
||||
}
|
||||
case SNAPSHOT:
|
||||
SnapshotDataStoreVO destSnapshotStore = snapshotDataStoreDao.findByStoreSnapshot(dataStore.getId(), objId);
|
||||
SnapshotDataStoreVO destSnapshotStore = snapshotDataStoreDao.findByStoreSnapshot(dataStore.getRole(), dataStore.getId(), objId);
|
||||
if ( destSnapshotStore != null ){
|
||||
return snapshotDataStoreDao.remove(destSnapshotStore.getId());
|
||||
}
|
||||
|
|
@ -262,24 +269,17 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
|
|||
public DataObjectInStore findObject(long objId, DataObjectType type,
|
||||
long dataStoreId, DataStoreRole role) {
|
||||
DataObjectInStore vo = null;
|
||||
if (role == DataStoreRole.Image) {
|
||||
if (role == DataStoreRole.Image || role == DataStoreRole.ImageCache) {
|
||||
switch (type){
|
||||
case TEMPLATE:
|
||||
vo = templateDataStoreDao.findByStoreTemplate(dataStoreId, objId);
|
||||
case SNAPSHOT:
|
||||
vo = snapshotDataStoreDao.findByStoreSnapshot(dataStoreId, objId);
|
||||
vo = snapshotDataStoreDao.findByStoreSnapshot(role, dataStoreId, objId);
|
||||
case VOLUME:
|
||||
vo = volumeDataStoreDao.findByStoreVolume(dataStoreId, objId);
|
||||
}
|
||||
} else if (type == DataObjectType.TEMPLATE && role == DataStoreRole.Primary) {
|
||||
vo = templatePoolDao.findByPoolTemplate(dataStoreId, objId);
|
||||
} else if (role == DataStoreRole.ImageCache) {
|
||||
SearchCriteriaService<ObjectInDataStoreVO, ObjectInDataStoreVO> sc = SearchCriteria2.create(ObjectInDataStoreVO.class);
|
||||
sc.addAnd(sc.getEntity().getObjectId(), Op.EQ, objId);
|
||||
sc.addAnd(sc.getEntity().getObjectType(), Op.EQ, type);
|
||||
sc.addAnd(sc.getEntity().getDataStoreId(), Op.EQ, dataStoreId);
|
||||
sc.addAnd(sc.getEntity().getDataStoreRole(), Op.EQ, role);
|
||||
vo = sc.find();
|
||||
} else {
|
||||
s_logger.debug("Invalid data or store type: " + type + " " + role);
|
||||
throw new CloudRuntimeException("Invalid data or store type: " + type + " " + role);
|
||||
|
|
@ -298,7 +298,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
|
|||
case TEMPLATE:
|
||||
vo = templateDataStoreDao.findByTemplate(objId);
|
||||
case SNAPSHOT:
|
||||
vo = snapshotDataStoreDao.findBySnapshot(objId);
|
||||
vo = snapshotDataStoreDao.findBySnapshot(objId, role);
|
||||
case VOLUME:
|
||||
vo = volumeDataStoreDao.findByVolume(objId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import javax.persistence.TemporalType;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Storage;
|
||||
|
|
@ -191,4 +192,9 @@ public class ObjectInDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
|||
public void setDataStoreId(long dataStoreId) {
|
||||
this.dataStoreId = dataStoreId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getObjectInStoreState() {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.StoragePoolHostVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
|
|
@ -52,7 +53,8 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
|
||||
storeSearch = createSearchBuilder();
|
||||
storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
|
||||
storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
storeSearch.and("store_role", storeSearch.entity().getRole(), SearchCriteria.Op.EQ);
|
||||
|
||||
storeSearch.done();
|
||||
|
||||
updateStateSearch = this.createSearchBuilder();
|
||||
|
|
@ -63,13 +65,13 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
|
||||
snapshotSearch = createSearchBuilder();
|
||||
snapshotSearch.and("snapshot_id", snapshotSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
|
||||
snapshotSearch.and("destroyed", snapshotSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
snapshotSearch.and("store_role", storeSearch.entity().getRole(), SearchCriteria.Op.EQ);
|
||||
snapshotSearch.done();
|
||||
|
||||
storeSnapshotSearch = createSearchBuilder();
|
||||
storeSnapshotSearch.and("snapshot_id", storeSnapshotSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
|
||||
storeSnapshotSearch.and("store_id", storeSnapshotSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
|
||||
storeSnapshotSearch.and("destroyed", storeSnapshotSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
storeSnapshotSearch.and("store_role", storeSearch.entity().getRole(), SearchCriteria.Op.EQ);
|
||||
storeSnapshotSearch.done();
|
||||
|
||||
return true;
|
||||
|
|
@ -114,11 +116,11 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
|
||||
|
||||
@Override
|
||||
public List<SnapshotDataStoreVO> listByStoreId(long id) {
|
||||
public List<SnapshotDataStoreVO> listByStoreId(long id, DataStoreRole role) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = storeSearch.create();
|
||||
sc.setParameters("store_id", id);
|
||||
sc.setParameters("destroyed", false);
|
||||
return listIncludingRemovedBy(sc);
|
||||
sc.setParameters("store_role", role);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -132,40 +134,19 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
}
|
||||
|
||||
@Override
|
||||
public SnapshotDataStoreVO findByStoreSnapshot(long storeId, long snapshotId) {
|
||||
public SnapshotDataStoreVO findByStoreSnapshot(DataStoreRole role, long storeId, long snapshotId) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = storeSnapshotSearch.create();
|
||||
sc.setParameters("store_id", storeId);
|
||||
sc.setParameters("snapshot_id", snapshotId);
|
||||
sc.setParameters("destroyed", false);
|
||||
sc.setParameters("store_role", role);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SnapshotDataStoreVO findByStoreSnapshot(long storeId, long snapshotId, boolean lock) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = storeSnapshotSearch.create();
|
||||
sc.setParameters("store_id", storeId);
|
||||
sc.setParameters("snapshot_id", snapshotId);
|
||||
sc.setParameters("destroyed", false);
|
||||
if (!lock)
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
else
|
||||
return lockOneRandomRow(sc, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotDataStoreVO findBySnapshot(long snapshotId) {
|
||||
public SnapshotDataStoreVO findBySnapshot(long snapshotId, DataStoreRole role) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = snapshotSearch.create();
|
||||
sc.setParameters("snapshot_id", snapshotId);
|
||||
sc.setParameters("destroyed", false);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotDataStoreVO> listDestroyed(long id) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = storeSearch.create();
|
||||
sc.setParameters("store_id", id);
|
||||
sc.setParameters("destroyed", true);
|
||||
return listIncludingRemovedBy(sc);
|
||||
sc.setParameters("store_role", role);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
// 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.snapshot;
|
||||
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.SnapshotEntity;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
|
||||
public interface SnapshotService {
|
||||
public SnapshotEntity getSnapshotEntity(long snapshotId);
|
||||
public boolean takeSnapshot(SnapshotInfo snapshot);
|
||||
public boolean revertSnapshot(SnapshotInfo snapshot);
|
||||
public boolean deleteSnapshot(SnapshotInfo snapshot);
|
||||
}
|
||||
|
|
@ -245,7 +245,8 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (obj.getType() == DataObjectType.SNAPSHOT) {
|
||||
return objectInStoreMgr.create(obj, this);
|
||||
}
|
||||
|
||||
return objectInStoreMgr.get(obj, this);
|
||||
|
|
|
|||
|
|
@ -840,5 +840,26 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo takeSnapshot(VolumeInfo volume) {
|
||||
VolumeObject vol = (VolumeObject)volume;
|
||||
vol.stateTransit(Volume.Event.SnapshotRequested);
|
||||
|
||||
SnapshotInfo snapshot = null;
|
||||
try {
|
||||
snapshot = this.snapshotMgr.takeSnapshot(volume);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Take snapshot: " + volume.getId() + " failed: " + e.toString());
|
||||
} finally {
|
||||
if (snapshot != null) {
|
||||
vol.stateTransit(Volume.Event.OperationSucceeded);
|
||||
} else {
|
||||
vol.stateTransit(Volume.Event.OperationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,58 +141,22 @@ public class XenServerStorageResource {
|
|||
}
|
||||
|
||||
protected CreateObjectAnswer getTemplateSize(CreateObjectCommand cmd, String templateUrl) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
/*Connection conn = hypervisorResource.getConnection();
|
||||
long size = this.getTemplateSize(conn, templateUrl);
|
||||
return new CreateObjectAnswer(cmd, templateUrl, size);
|
||||
return new CreateObjectAnswer(cmd, templateUrl, size);*/
|
||||
return null;
|
||||
}
|
||||
protected CreateObjectAnswer execute(CreateObjectCommand cmd) {
|
||||
String uriString = cmd.getObjectUri();
|
||||
DecodedDataObject obj = null;
|
||||
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
VDI vdi = null;
|
||||
boolean result = false;
|
||||
String errorMsg = null;
|
||||
|
||||
try {
|
||||
obj = Decoder.decode(uriString);
|
||||
|
||||
DecodedDataStore store = obj.getStore();
|
||||
if (obj.getObjType().equalsIgnoreCase("template") && store.getRole().equalsIgnoreCase("image")) {
|
||||
return getTemplateSize(cmd, obj.getPath());
|
||||
}
|
||||
|
||||
long size = obj.getSize();
|
||||
String name = obj.getName();
|
||||
String storeUuid = store.getUuid();
|
||||
SR primaryDataStoreSR = getSRByNameLabel(conn, storeUuid);
|
||||
vdi = createVdi(conn, name, primaryDataStoreSR, size);
|
||||
VDI.Record record = vdi.getRecord(conn);
|
||||
result = true;
|
||||
return new CreateObjectAnswer(cmd, record.uuid, record.virtualSize);
|
||||
} catch (BadServerResponse e) {
|
||||
s_logger.debug("Failed to create volume", e);
|
||||
errorMsg = e.toString();
|
||||
} catch (XenAPIException e) {
|
||||
s_logger.debug("Failed to create volume", e);
|
||||
errorMsg = e.toString();
|
||||
} catch (XmlRpcException e) {
|
||||
s_logger.debug("Failed to create volume", e);
|
||||
errorMsg = e.toString();
|
||||
} catch (URISyntaxException e) {
|
||||
s_logger.debug("Failed to create volume", e);
|
||||
errorMsg = e.toString();
|
||||
} finally {
|
||||
if (!result && vdi != null) {
|
||||
try {
|
||||
deleteVDI(conn, vdi);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Faled to delete vdi: " + vdi.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new CreateObjectAnswer(cmd, false, errorMsg);
|
||||
DataTO data = cmd.getData();
|
||||
try {
|
||||
if (data.getObjectType() == DataObjectType.VOLUME) {
|
||||
return createVolume(data);
|
||||
}
|
||||
return new CreateObjectAnswer("not supported type");
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString());
|
||||
return new CreateObjectAnswer(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(DeleteVolumeCommand cmd) {
|
||||
|
|
@ -735,20 +699,30 @@ public class XenServerStorageResource {
|
|||
return new CopyCmdAnswer("not implemented yet");
|
||||
}
|
||||
|
||||
protected CreateObjectAnswer createVolume(DataTO data) {
|
||||
/*
|
||||
protected CreateObjectAnswer createVolume(DataTO data) throws BadServerResponse, XenAPIException, XmlRpcException {
|
||||
VolumeObjectTO volume = (VolumeObjectTO)data;
|
||||
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
|
||||
SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
|
||||
VDI.Record vdir = new VDI.Record();
|
||||
vdir.nameLabel = dskch.getName();
|
||||
vdir.nameLabel = volume.getName();
|
||||
vdir.SR = poolSr;
|
||||
vdir.type = Types.VdiType.USER;
|
||||
|
||||
vdir.virtualSize = dskch.getSize();
|
||||
vdir.virtualSize = volume.getSize();
|
||||
VDI vdi;
|
||||
|
||||
vdi = VDI.create(conn, vdir);
|
||||
VDI.Record vdir;
|
||||
vdir = vdi.getRecord(conn);
|
||||
s_logger.debug("Succesfully created VDI for " + cmd + ". Uuid = " + vdir.uuid);*/
|
||||
return null;
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setName(vdir.nameLabel);
|
||||
newVol.setSize(vdir.virtualSize);
|
||||
newVol.setPath(vdir.uuid);
|
||||
|
||||
return new CreateObjectAnswer(newVol);
|
||||
}
|
||||
|
||||
protected CopyCmdAnswer cloneVolumeFromBaseTemplate(DataTO srcData, DataTO destData) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
|
||||
|
|
|
|||
|
|
@ -96,12 +96,12 @@ public class SampleImageStoreDriverImpl implements ImageStoreDriver {
|
|||
callback.complete(result);
|
||||
return;
|
||||
}
|
||||
CreateObjectCommand createCmd = new CreateObjectCommand(data.getUri());
|
||||
CreateObjectCommand createCmd = new CreateObjectCommand(data.getTO());
|
||||
CreateObjectAnswer answer = (CreateObjectAnswer)ep.sendMessage(createCmd);
|
||||
if (answer.getResult()) {
|
||||
//update imagestorevo
|
||||
|
||||
result = new CreateCmdResult(answer.getPath(), null);
|
||||
result = new CreateCmdResult(null, null);
|
||||
} else {
|
||||
result.setResult(answer.getDetails());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectCommand;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.volume.VolumeObject;
|
||||
import org.apache.log4j.Logger;
|
||||
|
|
@ -108,46 +109,15 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean createVolume(
|
||||
public Answer createVolume(
|
||||
VolumeInfo volume) throws StorageUnavailableException {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Creating volume: " + volume);
|
||||
}
|
||||
|
||||
DiskOfferingVO offering = diskOfferingDao.findById(volume.getDiskOfferingId());
|
||||
DiskProfile diskProfile = new DiskProfile(volume, offering,
|
||||
null);
|
||||
|
||||
StoragePool pool = (StoragePool)volume.getDataStore();
|
||||
VolumeVO vol = volumeDao.findById(volume.getId());
|
||||
if (pool != null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Trying to create in " + pool);
|
||||
}
|
||||
vol.setPoolId(pool.getId());
|
||||
|
||||
CreateCommand cmd = new CreateCommand(diskProfile, new StorageFilerTO(
|
||||
pool));
|
||||
|
||||
Answer answer = storageMgr.sendToPool(pool, null, cmd);
|
||||
if (answer.getResult()) {
|
||||
CreateAnswer createAnswer = (CreateAnswer) answer;
|
||||
vol.setFolder(pool.getPath());
|
||||
vol.setPath(createAnswer.getVolume().getPath());
|
||||
vol.setSize(createAnswer.getVolume().getSize());
|
||||
vol.setPoolType(pool.getPoolType());
|
||||
vol.setPoolId(pool.getId());
|
||||
vol.setPodId(pool.getPodId());
|
||||
this.volumeDao.update(vol.getId(), vol);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Unable to create volume " + volume.getId());
|
||||
}
|
||||
return false;
|
||||
|
||||
CreateObjectCommand cmd = new CreateObjectCommand(volume.getTO());
|
||||
Answer answer = storageMgr.sendToPool((StoragePool)volume.getDataStore(), null, cmd);
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -155,9 +125,10 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
|
|||
AsyncCompletionCallback<CreateCmdResult> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
String errMsg = null;
|
||||
Answer answer = null;
|
||||
if (data.getType() == DataObjectType.VOLUME) {
|
||||
try {
|
||||
createVolume((VolumeInfo)data);
|
||||
answer = createVolume((VolumeInfo)data);
|
||||
} catch (StorageUnavailableException e) {
|
||||
s_logger.debug("failed to create volume", e);
|
||||
errMsg = e.toString();
|
||||
|
|
@ -166,13 +137,12 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
|
|||
errMsg = e.toString();
|
||||
}
|
||||
}
|
||||
CreateCmdResult result = new CreateCmdResult(null, null);
|
||||
CreateCmdResult result = new CreateCmdResult(null, answer);
|
||||
if (errMsg != null) {
|
||||
result.setResult(errMsg);
|
||||
}
|
||||
|
||||
callback.complete(result);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.cloud.storage;
|
||||
|
||||
public class CreateSnapshotPayload {
|
||||
private Long snapshotPolicyId;
|
||||
|
||||
public Long getSnapshotPolicyId() {
|
||||
return snapshotPolicyId;
|
||||
}
|
||||
|
||||
public void setSnapshotPolicyId(Long snapshotPolicyId) {
|
||||
this.snapshotPolicyId = snapshotPolicyId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1931,7 +1931,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
_accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), store.getDataCenterId());
|
||||
|
||||
// Verify that there are no live snapshot, template, volume on the image store to be deleted
|
||||
List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId);
|
||||
List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId, DataStoreRole.Image);
|
||||
if ( snapshots != null && snapshots.size() > 0 ){
|
||||
throw new CloudRuntimeException("Cannot delete image store with active snapshots backup!");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import com.cloud.configuration.Resource.ResourceType;
|
|||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.consoleproxy.ConsoleProxyManager;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
|
|
@ -166,6 +167,7 @@ import com.cloud.vm.dao.DomainRouterDao;
|
|||
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
|
||||
|
|
@ -2463,5 +2465,47 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
|||
throw new CloudRuntimeException("Failed to destroy volume" + volume.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Snapshot takeSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException {
|
||||
Account caller = UserContext.current().getCaller();
|
||||
|
||||
VolumeInfo volume = this.volFactory.getVolume(volumeId);
|
||||
if (volume == null) {
|
||||
throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
|
||||
}
|
||||
DataCenter zone = _dcDao.findById(volume.getDataCenterId());
|
||||
if (zone == null) {
|
||||
throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId());
|
||||
}
|
||||
|
||||
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
|
||||
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zone.getName());
|
||||
}
|
||||
|
||||
if (volume.getState() != Volume.State.Ready) {
|
||||
throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
|
||||
}
|
||||
|
||||
if ( volume.getTemplateId() != null ) {
|
||||
VMTemplateVO template = _templateDao.findById(volume.getTemplateId());
|
||||
if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM ) {
|
||||
throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for System VM , Creating snapshot against System VM volumes is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
StoragePool storagePool = (StoragePool)volume.getDataStore();
|
||||
if (storagePool == null) {
|
||||
throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach this volume to a VM before create snapshot for it");
|
||||
}
|
||||
|
||||
CreateSnapshotPayload payload = new CreateSnapshotPayload();
|
||||
payload.setSnapshotPolicyId(policyId);
|
||||
return this.volService.takeSnapshot(volume);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
package com.cloud.storage.dao;
|
||||
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.Snapshot.Type;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
|
|
@ -29,7 +30,7 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long>, StateDao<Snap
|
|||
List<SnapshotVO> listByVolumeId(long volumeId);
|
||||
List<SnapshotVO> listByVolumeId(Filter filter, long volumeId);
|
||||
SnapshotVO findNextSnapshot(long parentSnapId);
|
||||
long getLastSnapshot(long volumeId, long snapId);
|
||||
long getLastSnapshot(long volumeId, DataStoreRole role);
|
||||
List<SnapshotVO> listByVolumeIdType(long volumeId, Type type);
|
||||
List<SnapshotVO> listByVolumeIdIncludingRemoved(long volumeId);
|
||||
List<SnapshotVO> listByBackupUuid(long volumeId, String backupUuid);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.apache.log4j.Logger;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.server.ResourceTag.TaggedResourceType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.Snapshot.Event;
|
||||
import com.cloud.storage.Snapshot.State;
|
||||
|
|
@ -55,7 +56,7 @@ import com.cloud.vm.dao.VMInstanceDao;
|
|||
public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements SnapshotDao {
|
||||
public static final Logger s_logger = Logger.getLogger(SnapshotDaoImpl.class.getName());
|
||||
//TODO: we should remove these direct sqls
|
||||
private static final String GET_LAST_SNAPSHOT = "SELECT id FROM snapshots where volume_id = ? AND id != ? AND path IS NOT NULL ORDER BY created DESC";
|
||||
private static final String GET_LAST_SNAPSHOT = "SELECT snapshots.id FROM snapshot_store_ref, snapshots where snapshots.id = snapshot_store_ref.snapshot_id AND snapshosts.volume_id = ? AND snapshot_store_ref.role = ? ORDER BY created DESC";
|
||||
private static final String UPDATE_SNAPSHOT_VERSION = "UPDATE snapshots SET version = ? WHERE volume_id = ? AND version = ?";
|
||||
private static final String GET_SECHOST_ID = "SELECT store_id FROM snapshots, snapshot_store_ref where snapshots.id = snapshot_store_ref.snapshot_id AND volume_id = ? AND backup_snap_id IS NOT NULL AND sechost_id IS NOT NULL LIMIT 1";
|
||||
private static final String UPDATE_SECHOST_ID = "UPDATE snapshots SET sechost_id = ? WHERE data_center_id = ?";
|
||||
|
|
@ -212,14 +213,14 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
|
|||
return null;
|
||||
}
|
||||
@Override
|
||||
public long getLastSnapshot(long volumeId, long snapId) {
|
||||
public long getLastSnapshot(long volumeId, DataStoreRole role) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
String sql = GET_LAST_SNAPSHOT;
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setLong(1, volumeId);
|
||||
pstmt.setLong(2, snapId);
|
||||
pstmt.setString(2, role.toString());
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
if (rs.next()) {
|
||||
return rs.getLong(1);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package com.cloud.storage.snapshot;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
|
@ -68,7 +69,10 @@ public interface SnapshotManager {
|
|||
|
||||
Answer sendToPool(Volume vol, Command cmd);
|
||||
|
||||
SnapshotVO getParentSnapshot(VolumeInfo volume, Snapshot snapshot);
|
||||
SnapshotVO getParentSnapshot(VolumeInfo volume);
|
||||
|
||||
Snapshot backupSnapshot(Long snapshotId);
|
||||
|
||||
SnapshotInfo takeSnapshot(VolumeInfo volume)
|
||||
throws ResourceAllocationException;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
|
||||
|
|
@ -82,7 +83,9 @@ import com.cloud.host.dao.HostDao;
|
|||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.org.Grouping;
|
||||
import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.server.ResourceTag.TaggedResourceType;
|
||||
import com.cloud.storage.CreateSnapshotPayload;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.Snapshot.Type;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
|
|
@ -128,8 +131,12 @@ import com.cloud.utils.db.JoinBuilder;
|
|||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
|
||||
@Component
|
||||
|
|
@ -202,6 +209,10 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
@Inject VolumeDataFactory volFactory;
|
||||
@Inject SnapshotDataFactory snapshotFactory;
|
||||
@Inject EndPointSelector _epSelector;
|
||||
@Inject
|
||||
private ResourceManager _resourceMgr;
|
||||
@Inject
|
||||
protected List<SnapshotStrategy> snapshotStrategies;
|
||||
|
||||
|
||||
private int _totalRetries;
|
||||
|
|
@ -278,32 +289,25 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
throw new InvalidParameterValueException("Volume is not in ready state");
|
||||
}
|
||||
|
||||
SnapshotInfo snapshot = null;
|
||||
|
||||
|
||||
boolean backedUp = false;
|
||||
// does the caller have the authority to act on this volume
|
||||
_accountMgr.checkAccess(UserContext.current().getCaller(), null, true, volume);
|
||||
|
||||
|
||||
SnapshotInfo snap = this.snapshotFactory.getSnapshot(snapshotId);
|
||||
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary);
|
||||
|
||||
try {
|
||||
snapshot = this.snapshotSrv.takeSnapshot(volume, snapshotId);
|
||||
if (snapshot != null) {
|
||||
postCreateSnapshot(volumeId, snapshot.getId(), policyId);
|
||||
//Check if the snapshot was removed while backingUp. If yes, do not log snapshot create usage event
|
||||
SnapshotVO freshSnapshot = _snapshotDao.findById(snapshot.getId());
|
||||
if ((freshSnapshot != null) && backedUp) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
|
||||
snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
|
||||
volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
|
||||
}
|
||||
postCreateSnapshot(volumeId, snapshot.getId(), policyId);
|
||||
//Check if the snapshot was removed while backingUp. If yes, do not log snapshot create usage event
|
||||
SnapshotVO freshSnapshot = _snapshotDao.findById(snapshot.getId());
|
||||
if ((freshSnapshot != null) && backedUp) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
|
||||
snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
|
||||
volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
|
||||
}
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
|
||||
}
|
||||
if (backup) {
|
||||
this.backupSnapshot(snapshotId);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
s_logger.debug("Failed to create snapshot", e);
|
||||
if (backup) {
|
||||
|
|
@ -337,16 +341,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
|
||||
@Override
|
||||
public Snapshot backupSnapshot(Long snapshotId) {
|
||||
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId);
|
||||
if (snapshot == null) {
|
||||
throw new CloudRuntimeException("Can't find snapshot:" + snapshotId);
|
||||
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Image);
|
||||
if (snapshot != null) {
|
||||
throw new CloudRuntimeException("Already in the backup snapshot:" + snapshotId);
|
||||
}
|
||||
|
||||
if (snapshot.getState() == Snapshot.State.BackedUp) {
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
|
||||
return this.snapshotSrv.backupSnapshot(snapshot);
|
||||
}
|
||||
|
||||
|
|
@ -436,8 +435,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
}
|
||||
|
||||
@Override
|
||||
public SnapshotVO getParentSnapshot(VolumeInfo volume, Snapshot snapshot) {
|
||||
long preId = _snapshotDao.getLastSnapshot(volume.getId(), snapshot.getId());
|
||||
public SnapshotVO getParentSnapshot(VolumeInfo volume) {
|
||||
long preId = _snapshotDao.getLastSnapshot(volume.getId(), DataStoreRole.Primary);
|
||||
|
||||
SnapshotVO preSnapshotVO = null;
|
||||
if (preId != 0 && !(volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId()))) {
|
||||
|
|
@ -500,15 +499,21 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
Account caller = UserContext.current().getCaller();
|
||||
|
||||
// Verify parameters
|
||||
SnapshotInfo snapshotCheck = this.snapshotFactory.getSnapshot(snapshotId);
|
||||
SnapshotVO snapshotCheck = this._snapshotDao.findById(snapshotId);
|
||||
if (snapshotCheck == null) {
|
||||
throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId);
|
||||
}
|
||||
|
||||
_accountMgr.checkAccess(caller, null, true, snapshotCheck);
|
||||
|
||||
SnapshotStrategy snapshotStrategy = null;
|
||||
for (SnapshotStrategy strategy : this.snapshotStrategies) {
|
||||
if (strategy.canHandle(snapshotCheck)) {
|
||||
snapshotStrategy = strategy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
boolean result = this.snapshotSrv.deleteSnapshot(snapshotCheck);
|
||||
boolean result = snapshotStrategy.deleteSnapshot(snapshotId);
|
||||
if (result) {
|
||||
if (snapshotCheck.getState() == Snapshot.State.BackedUp) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshotCheck.getAccountId(),
|
||||
|
|
@ -529,7 +534,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
|
||||
@Override
|
||||
public String getSecondaryStorageURL(SnapshotVO snapshot) {
|
||||
SnapshotDataStoreVO snapshotStore = this._snapshotStoreDao.findBySnapshot(snapshot.getId());
|
||||
SnapshotDataStoreVO snapshotStore = this._snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Image);
|
||||
if (snapshotStore != null){
|
||||
DataStore store = this.dataStoreMgr.getDataStore(snapshotStore.getDataStoreId(), DataStoreRole.Image);
|
||||
if ( store != null ){
|
||||
|
|
@ -904,44 +909,76 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotVO allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException {
|
||||
Account caller = UserContext.current().getCaller();
|
||||
|
||||
|
||||
private boolean hostSupportSnapsthot(HostVO host) {
|
||||
if (host.getHypervisorType() != HypervisorType.KVM) {
|
||||
return true;
|
||||
}
|
||||
// Determine host capabilities
|
||||
String caps = host.getCapabilities();
|
||||
|
||||
VolumeVO volume = _volsDao.findById(volumeId);
|
||||
if (volume == null) {
|
||||
throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
|
||||
}
|
||||
DataCenter zone = _dcDao.findById(volume.getDataCenterId());
|
||||
if (zone == null) {
|
||||
throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId());
|
||||
}
|
||||
|
||||
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
|
||||
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zone.getName());
|
||||
}
|
||||
|
||||
if (volume.getState() != Volume.State.Ready) {
|
||||
throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
|
||||
}
|
||||
|
||||
if ( volume.getTemplateId() != null ) {
|
||||
VMTemplateVO template = _templateDao.findById(volume.getTemplateId());
|
||||
if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM ) {
|
||||
throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for System VM , Creating snapshot against System VM volumes is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
StoragePoolVO storagePoolVO = _storagePoolDao.findById(volume.getPoolId());
|
||||
if (storagePoolVO == null) {
|
||||
throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach this volume to a VM before create snapshot for it");
|
||||
}
|
||||
|
||||
ClusterVO cluster = _clusterDao.findById(storagePoolVO.getClusterId());
|
||||
if (caps != null) {
|
||||
String[] tokens = caps.split(",");
|
||||
for (String token : tokens) {
|
||||
if (token.contains("snapshot")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean supportedByHypervisor(VolumeInfo volume) {
|
||||
StoragePool storagePool = (StoragePool)volume.getDataStore();
|
||||
ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId());
|
||||
if (cluster != null && cluster.getHypervisorType() == HypervisorType.Ovm) {
|
||||
throw new InvalidParameterValueException("Ovm won't support taking snapshot");
|
||||
}
|
||||
|
||||
if (volume.getHypervisorType().equals(HypervisorType.KVM)) {
|
||||
List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cluster.getId());
|
||||
if (hosts != null && !hosts.isEmpty()) {
|
||||
HostVO host = hosts.get(0);
|
||||
if (!hostSupportSnapsthot(host)) {
|
||||
throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if volume is attached to a vm in destroyed or expunging state; disallow
|
||||
if (volume.getInstanceId() != null) {
|
||||
UserVmVO userVm = _vmDao.findById(volume.getInstanceId());
|
||||
if (userVm != null) {
|
||||
if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) {
|
||||
throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId() + " is associated with vm:" + userVm.getInstanceName() + " is in "
|
||||
+ userVm.getState().toString() + " state");
|
||||
}
|
||||
|
||||
if(userVm.getHypervisorType() == HypervisorType.VMware || userVm.getHypervisorType() == HypervisorType.KVM) {
|
||||
List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
|
||||
if(activeSnapshots.size() > 1)
|
||||
throw new CloudRuntimeException("There is other active snapshot tasks on the instance to which the volume is attached, please try again later");
|
||||
}
|
||||
|
||||
List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(),
|
||||
VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging);
|
||||
if (activeVMSnapshots.size() > 0) {
|
||||
throw new CloudRuntimeException(
|
||||
"There is other active vm snapshot tasks on the instance to which the volume is attached, please try again later");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException {
|
||||
Account caller = UserContext.current().getCaller();
|
||||
|
||||
supportedByHypervisor(volume);
|
||||
CreateSnapshotPayload snapInfo = (CreateSnapshotPayload)volume.getpayload();
|
||||
Long policyId = snapInfo.getSnapshotPolicyId();
|
||||
// Verify permissions
|
||||
_accountMgr.checkAccess(caller, null, true, volume);
|
||||
Type snapshotType = getSnapshotType(policyId);
|
||||
|
|
@ -975,14 +1012,13 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
}
|
||||
String snapshotName = vmDisplayName + "_" + volume.getName() + "_" + timeString;
|
||||
|
||||
// Create the Snapshot object and save it so we can return it to the
|
||||
// user
|
||||
HypervisorType hypervisorType = this._volsDao.getHypervisorType(volumeId);
|
||||
SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), null, snapshotName,
|
||||
HypervisorType hypervisorType = volume.getHypervisorType();
|
||||
SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), snapshotName,
|
||||
(short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), hypervisorType);
|
||||
|
||||
SnapshotVO snapshot = _snapshotDao.persist(snapshotVO);
|
||||
if (snapshot == null) {
|
||||
throw new CloudRuntimeException("Failed to create snapshot for volume: "+volumeId);
|
||||
throw new CloudRuntimeException("Failed to create snapshot for volume: " + volume.getId());
|
||||
}
|
||||
if (backup) {
|
||||
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage,
|
||||
|
|
@ -991,7 +1027,19 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
|
||||
new Long(volume.getSize()));
|
||||
}
|
||||
return snapshot;
|
||||
SnapshotInfo snap = this.snapshotFactory.getSnapshot(snapshot.getId(), volume.getDataStore());
|
||||
boolean processed = false;
|
||||
for (SnapshotStrategy strategy : snapshotStrategies) {
|
||||
if (strategy.canHandle(snap)) {
|
||||
processed = true;
|
||||
snap = strategy.takeSnapshot(snap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!processed) {
|
||||
throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshot.getId());
|
||||
}
|
||||
return snap;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue