bug 8714: support paraleel recursive snapshot

snapshot doesn't depend on volume any more, volume can be removed even there are snapshots on this volume

status 8714: resolved fixed
This commit is contained in:
anthony 2011-02-25 22:17:13 -08:00
parent 913903cbe6
commit 1970161844
34 changed files with 524 additions and 478 deletions

View File

@ -26,7 +26,20 @@ public interface Snapshot {
public enum Type {
MANUAL,
RECURRING,
TEMPLATE;
TEMPLATE,
HOURLY,
DAILY,
WEEKLY,
MONTHLY;
private int max = 8;
public void setMax(int max) {
this.max = max;
}
public int getMax() {
return max;
}
public String toString() {
return this.name();
@ -52,7 +65,7 @@ public interface Snapshot {
}
}
public static final long MANUAL_POLICY_ID = 1L;
public static final long MANUAL_POLICY_ID = 0L;
Long getId();
long getAccountId();
@ -60,7 +73,10 @@ public interface Snapshot {
String getPath();
String getName();
Date getCreated();
short getSnapshotType();
Type getType();
Status getStatus();
HypervisorType getHypervisorType();
boolean isRecursive();
short getsnapshotType();
}

View File

@ -56,7 +56,7 @@ public class DiskProfile {
}
public DiskProfile(Volume vol, DiskOffering offering, HypervisorType hyperType) {
this(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.getUseLocalStorage(), vol.getSize());
this(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.isCustomized(), null);
this.hyperType = hyperType;
}

View File

@ -26,6 +26,7 @@ import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.utils.DateUtil.IntervalType;
@Entity
@Table(name="snapshot_policy")
@ -56,11 +57,11 @@ public class SnapshotPolicyVO implements SnapshotPolicy {
public SnapshotPolicyVO() { }
public SnapshotPolicyVO(long volumeId, String schedule, String timezone, short interval, int maxSnaps) {
public SnapshotPolicyVO(long volumeId, String schedule, String timezone, IntervalType intvType, int maxSnaps) {
this.volumeId = volumeId;
this.schedule = schedule;
this.timezone = timezone;
this.interval = interval;
this.interval = (short)intvType.ordinal();
this.maxSnaps = maxSnaps;
this.active = true;
}

View File

@ -98,7 +98,7 @@ public class SnapshotScheduleVO implements SnapshotSchedule {
return asyncJobId;
}
public void setAsyncJobId(long asyncJobId) {
public void setAsyncJobId(Long asyncJobId) {
this.asyncJobId = asyncJobId;
}

View File

@ -19,7 +19,6 @@
package com.cloud.storage;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
@ -29,7 +28,6 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.db.GenericDao;
@ -42,10 +40,16 @@ public class SnapshotVO implements Snapshot {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private long id = -1;
private long id = -1;
@Column(name="data_center_id")
long dataCenterId;
@Column(name="account_id")
long accountId;
long accountId;
@Column(name="domain_id")
long domainId;
@Column(name="volume_id")
Long volumeId;
@ -67,8 +71,11 @@ public class SnapshotVO implements Snapshot {
short snapshotType;
@Column(name="type_description")
String typeDescription;
String typeDescription;
@Column(name="size")
long size;
@Column(name=GenericDao.CREATED_COLUMN)
Date created;
@ -87,13 +94,16 @@ public class SnapshotVO implements Snapshot {
public SnapshotVO() { }
public SnapshotVO(long accountId, Long volumeId, String path, String name, short snapshotType, String typeDescription, HypervisorType hypervisorType) {
this.accountId = accountId;
public SnapshotVO(long dcId, long accountId, long domainId, Long volumeId, String path, String name, short snapshotType, String typeDescription, long size, HypervisorType hypervisorType) {
this.dataCenterId = dcId;
this.accountId = accountId;
this.domainId = domainId;
this.volumeId = volumeId;
this.path = path;
this.name = name;
this.snapshotType = snapshotType;
this.typeDescription = typeDescription;
this.typeDescription = typeDescription;
this.size = size;
this.status = Status.Creating;
this.prevSnapshotId = 0;
this.hypervisorType = hypervisorType;
@ -104,11 +114,19 @@ public class SnapshotVO implements Snapshot {
return id;
}
public long getDataCenterId() {
return dataCenterId;
}
@Override
public long getAccountId() {
return accountId;
}
public long getDomainId() {
return domainId;
}
@Override
public long getVolumeId() {
return volumeId;
@ -131,12 +149,19 @@ public class SnapshotVO implements Snapshot {
public String getName() {
return name;
}
@Override
public short getSnapshotType() {
return snapshotType;
@Override
public short getsnapshotType() {
return snapshotType;
}
@Override
public Type getType() {
if (snapshotType < 0 || snapshotType >= Type.values().length) {
return null;
}
return Type.values()[snapshotType];
}
@Override
public HypervisorType getHypervisorType() {
return hypervisorType;
@ -144,8 +169,20 @@ public class SnapshotVO implements Snapshot {
public void setSnapshotType(short snapshotType) {
this.snapshotType = snapshotType;
}
@Override
public boolean isRecursive(){
if ( snapshotType >= Type.DAILY.ordinal() && snapshotType <= Type.MONTHLY.ordinal() ) {
return true;
}
return false;
}
public long getSize() {
return size;
}
public String getTypeDescription() {
return typeDescription;
}
@ -185,25 +222,14 @@ public class SnapshotVO implements Snapshot {
public void setPrevSnapshotId(long prevSnapshotId){
this.prevSnapshotId = prevSnapshotId;
}
public static Type getSnapshotType(Long policyId) {
if (policyId.equals(MANUAL_POLICY_ID)) {
return Type.MANUAL;
} else {
return Type.RECURRING;
}
}
public static Type getSnapshotType(String snapshotType) {
if (Type.MANUAL.equals(snapshotType)) {
return Type.MANUAL;
}
if (Type.RECURRING.equals(snapshotType)) {
return Type.RECURRING;
}
if (Type.TEMPLATE.equals(snapshotType)) {
return Type.TEMPLATE;
for ( Type type : Type.values()) {
if ( type.equals(snapshotType)) {
return type;
}
}
return null;
}
}
}

View File

@ -428,54 +428,6 @@ public class VolumeVO implements Volume {
this.updated = updated;
}
public Lun getLun() {
return new Lun(hostip, iscsiName);
}
public class Lun {
private final String ip;
private String iqn;
private String lun;
protected Lun(String ip, String iscsiName) {
this.ip = ip;
String[] str = iscsiName.split(":lu:");
if (str != null && str.length == 2) {
iqn = str[0];
lun = str[1];
} else {
iqn = null;
lun = null;
}
}
public Lun(String ip, String iqn, String lun) {
this.ip = ip;
this.iqn = iqn;
this.lun = lun;
}
public String getIp() {
return ip;
}
public String getIqn() {
return iqn;
}
public String getLun() {
return lun;
}
public boolean isIscsi() {
return lun != null;
}
protected String getIscsiName() {
return iqn + ":lu:" + lun;
}
}
@Override
public String toString() {
return new StringBuilder("Vol[").append(id).append("|vm=").append(instanceId).append("|").append(volumeType).append("]").toString();

View File

@ -37,7 +37,7 @@ public interface SnapshotSchedule {
Long getAsyncJobId();
void setAsyncJobId(long asyncJobId);
void setAsyncJobId(Long asyncJobId);
Long getSnapshotId();

View File

@ -37,6 +37,7 @@ import com.cloud.host.HostStats;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.Status.Event;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.ServiceOffering;
import com.cloud.resource.ServerResource;
import com.cloud.service.ServiceOfferingVO;
@ -226,4 +227,6 @@ public interface AgentManager extends Manager {
boolean isHostNativeHAEnabled(long hostId);
Answer sendTo(Long dcId, HypervisorType type, Command cmd);
}

View File

@ -108,6 +108,7 @@ import com.cloud.exception.DiscoveryException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.exception.UnsupportedVersionException;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.ha.HighAvailabilityManager.WorkType;
@ -138,9 +139,11 @@ import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
@ -961,6 +964,30 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory,
}
}
@Override
public Answer sendTo(Long dcId, HypervisorType type, Command cmd) {
List<ClusterVO> clusters = _clusterDao.listByDcHyType(dcId, type.toString());
int retry = 0;
for( ClusterVO cluster : clusters ) {
List<HostVO> hosts = _hostDao.listBy(Host.Type.Routing, cluster.getId(), null, dcId);
for ( HostVO host : hosts ) {
retry++;
if ( retry > _retry ) {
return null;
}
Answer answer = null;
try {
answer = easySend( host.getId(), cmd);
} catch (Exception e ) {
}
if ( answer != null ) {
return answer;
}
}
}
return null;
}
@Override
@DB
public boolean deleteHost(long hostId) {

View File

@ -258,25 +258,8 @@ public class ApiDBUtils {
}
public static String getSnapshotIntervalTypes(long snapshotId) {
String intervalTypes = "";
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
if (snapshot.getSnapshotType() == Snapshot.Type.MANUAL.ordinal()) {
return "MANUAL";
}
List<SnapshotPolicyVO> policies = _snapMgr.listPoliciesforVolume(snapshot.getVolumeId());
for (SnapshotPolicyVO policy : policies) {
if (!intervalTypes.isEmpty()) {
intervalTypes += ",";
}
if (policy.getId() == Snapshot.MANUAL_POLICY_ID) {
intervalTypes += "MANUAL";
} else {
intervalTypes += DateUtil.getIntervalType(policy.getInterval()).toString();
}
}
return intervalTypes;
return snapshot.getType().name();
}
public static String getStoragePoolTags(long poolId) {

View File

@ -444,7 +444,7 @@ public class ApiResponseHelper implements ResponseGenerator {
}
VolumeVO volume = findVolumeById(snapshot.getVolumeId());
String snapshotTypeStr = Type.values()[snapshot.getSnapshotType()].name();
String snapshotTypeStr = snapshot.getType().name();
snapshotResponse.setSnapshotType(snapshotTypeStr);
snapshotResponse.setVolumeId(snapshot.getVolumeId());
if( volume != null ) {

View File

@ -29,4 +29,5 @@ public interface ClusterDao extends GenericDao<ClusterVO, Long> {
List<ClusterVO> listByHyTypeWithoutGuid(String hyType);
List<ClusterVO> listByZoneId(long zoneId);
List<HypervisorType> getAvailableHypervisorInZone(long zoneId);
List<ClusterVO> listByDcHyType(long dcId, String hyType);
}

View File

@ -35,6 +35,7 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
protected final SearchBuilder<ClusterVO> HyTypeWithoutGuidSearch;
protected final SearchBuilder<ClusterVO> AvailHyperSearch;
protected final SearchBuilder<ClusterVO> ZoneSearch;
protected final SearchBuilder<ClusterVO> ZoneHyTypeSearch;
protected ClusterDaoImpl() {
super();
@ -43,6 +44,11 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
HyTypeWithoutGuidSearch.and("guid", HyTypeWithoutGuidSearch.entity().getGuid(), SearchCriteria.Op.NULL);
HyTypeWithoutGuidSearch.done();
ZoneHyTypeSearch = createSearchBuilder();
ZoneHyTypeSearch.and("hypervisorType", ZoneHyTypeSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ);
ZoneHyTypeSearch.and("dataCenterId", ZoneHyTypeSearch.entity().getPodId(), SearchCriteria.Op.EQ);
ZoneHyTypeSearch.done();
PodSearch = createSearchBuilder();
PodSearch.and("pod", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
PodSearch.and("name", PodSearch.entity().getName(), SearchCriteria.Op.EQ);
@ -90,6 +96,14 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
return listBy(sc);
}
@Override
public List<ClusterVO> listByDcHyType(long dcId, String hyType) {
SearchCriteria<ClusterVO> sc = ZoneHyTypeSearch.create();
sc.setParameters("dataCenterId", dcId);
sc.setParameters("hypervisorType", hyType);
return listBy(sc);
}
@Override
public List<HypervisorType> getAvailableHypervisorInZone(long zoneId) {
SearchCriteria<ClusterVO> sc = AvailHyperSearch.create();

View File

@ -299,15 +299,17 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
@Override
public List<HostVO> listBy(Host.Type type, Long clusterId, Long podId, long dcId) {
SearchCriteria<HostVO> sc = TypePodDcStatusSearch.create();
sc.setParameters("type", type.toString());
if (podId != null) {
sc.setParameters("pod", podId);
SearchCriteria<HostVO> sc = TypePodDcStatusSearch.create();
if ( type != null ) {
sc.setParameters("type", type.toString());
}
if (clusterId != null) {
sc.setParameters("cluster", clusterId);
}
sc.setParameters("dc", dcId);
}
if (podId != null ) {
sc.setParameters("pod", podId);
}
sc.setParameters("dc", dcId);
sc.setParameters("status", Status.Up.toString());
return listBy(sc);
@ -333,7 +335,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
sc.setParameters("cluster", clusterId);
return listBy(sc);
}
}
@Override
public List<HostVO> listBy(Host.Type type, long dcId) {

View File

@ -184,10 +184,6 @@ public class ConfigurationServerImpl implements ConfigurationServer {
createDiskOffering(DomainVO.ROOT_DOMAIN, "Large", "Large Disk, 100 GB", 100, null);
//_configMgr.createDiskOffering(User.UID_SYSTEM, DomainVO.ROOT_DOMAIN, "Private", "Private Disk", 0, null);
//Add default manual snapshot policy
SnapshotPolicyVO snapPolicy = new SnapshotPolicyVO(0L, "00", "GMT", (short)4, 0);
_snapPolicyDao.persist(snapPolicy);
// Save the mount parent to the configuration table
String mountParent = getMountParent();
if (mountParent != null) {

View File

@ -410,7 +410,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
}
@DB
protected Pair<VolumeVO, String> createVolumeFromSnapshot(VolumeVO volume, SnapshotVO snapshot, long virtualsize) {
protected Pair<VolumeVO, String> createVolumeFromSnapshot(VolumeVO volume, SnapshotVO snapshot) {
VolumeVO createdVolume = null;
Long volumeId = volume.getId();
@ -466,7 +466,6 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
}
}
s_logger.warn("Unable to create volume on pool " + pool.getName() + ", reason: " + details);
}
@ -515,18 +514,20 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
// By default, assume failure.
VolumeVO createdVolume = null;
SnapshotVO snapshot = _snapshotDao.findById(snapshotId); // Precondition: snapshot is not null and not removed.
Long origVolumeId = snapshot.getVolumeId();
VolumeVO originalVolume = _volsDao.findById(origVolumeId); // NOTE: Original volume could be destroyed and removed.
Pair<VolumeVO, String> volumeDetails = createVolumeFromSnapshot(volume, snapshot, originalVolume.getSize());
Pair<VolumeVO, String> volumeDetails = createVolumeFromSnapshot(volume, snapshot);
createdVolume = volumeDetails.first();
Transaction txn = Transaction.currentTxn();
txn.start();
<<<<<<< Updated upstream
// Create an event
Long templateId = originalVolume.getTemplateId();
;
Long diskOfferingId = originalVolume.getDiskOfferingId();
=======
Long diskOfferingId = volume.getDiskOfferingId();
>>>>>>> Stashed changes
if (createdVolume.getPath() != null) {
Long offeringId = null;
@ -537,9 +538,15 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
}
}
<<<<<<< Updated upstream
// UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(),
// volume.getId(), volume.getName(), offeringId, templateId, createdVolume.getSize());
// _usageEventDao.persist(usageEvent);
=======
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(),
volume.getId(), volume.getName(), offeringId, null, createdVolume.getSize());
_usageEventDao.persist(usageEvent);
>>>>>>> Stashed changes
}
txn.commit();
return createdVolume;
@ -809,17 +816,15 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
Long vmId = volume.getInstanceId();
if (vmId != null) {
UserVm vm = _userVmDao.findById(vmId);
if (vm == null) {
return false;
return true;
}
if (!vm.getState().equals(State.Stopped)) {
return false;
State state = vm.getState();
if (state.equals(State.Stopped) || state.equals(State.Destroyed) ) {
return true;
}
}
return true;
return false;
}
@Override
@ -1449,17 +1454,28 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
}
} else {
Long snapshotId = cmd.getSnapshotId();
<<<<<<< Updated upstream
Snapshot snapshotCheck = _snapshotDao.findById(snapshotId);
=======
SnapshotVO snapshotCheck = _snapshotDao.findById(snapshotId);
diskOfferingId = cmd.getDiskOfferingId();
>>>>>>> Stashed changes
if (snapshotCheck == null) {
throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId);
}
<<<<<<< Updated upstream
VolumeVO vol = _volsDao.findByIdIncludingRemoved(snapshotCheck.getVolumeId());
zoneId = vol.getDataCenterId();
size = vol.getSize(); //we maintain size from org vol ; disk offering is used for tags purposes
diskOfferingId = vol.getDiskOfferingId();
=======
zoneId = snapshotCheck.getDataCenterId();
size = snapshotCheck.getSize(); //we maintain size from org vol ; disk offering is used for tags purposes
>>>>>>> Stashed changes
if (account != null) {
if (isAdmin(account.getType())) {
Account snapshotOwner = _accountDao.findById(snapshotCheck.getAccountId());
@ -1531,7 +1547,6 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
if (cmd.getSnapshotId() != null) {
return createVolumeFromSnapshot(volume, cmd.getSnapshotId());
} else {
DiskOfferingVO diskOffering = _diskOfferingDao.findById(cmd.getDiskOfferingId());
_accountMgr.incrementResourceCount(volume.getAccountId(), ResourceType.volume);
volume.setStatus(AsyncInstanceCreateStatus.Created);
_volsDao.update(volume.getId(), volume);

View File

@ -21,6 +21,7 @@ package com.cloud.storage.dao;
import java.util.List;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Snapshot.Type;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
@ -29,7 +30,7 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long> {
List<SnapshotVO> listByVolumeId(Filter filter, long volumeId);
SnapshotVO findNextSnapshot(long parentSnapId);
long getLastSnapshot(long volumeId, long snapId);
List<SnapshotVO> listByVolumeIdType(long volumeId, String type);
List<SnapshotVO> listByVolumeIdType(long volumeId, Type type);
List<SnapshotVO> listByVolumeIdIncludingRemoved(long volumeId);
List<SnapshotVO> listByBackupUuid(long volumeId, String backupUuid);

View File

@ -27,6 +27,7 @@ import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Snapshot.Type;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
@ -58,7 +59,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
}
@Override
public List<SnapshotVO> listByVolumeIdType(long volumeId, String type ) {
public List<SnapshotVO> listByVolumeIdType(long volumeId, Type type ) {
return listByVolumeIdType(null, volumeId, type);
}
@ -81,10 +82,10 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
return listIncludingRemovedBy(sc, null);
}
public List<SnapshotVO> listByVolumeIdType(Filter filter, long volumeId, String type ) {
public List<SnapshotVO> listByVolumeIdType(Filter filter, long volumeId, Type type ) {
SearchCriteria<SnapshotVO> sc = VolumeIdTypeSearch.create();
sc.setParameters("volumeId", volumeId);
sc.setParameters("type", type);
sc.setParameters("type", type.ordinal());
return listBy(sc, filter);
}
@ -95,7 +96,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
VolumeIdTypeSearch = createSearchBuilder();
VolumeIdTypeSearch.and("volumeId", VolumeIdTypeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
VolumeIdTypeSearch.and("type", VolumeIdTypeSearch.entity().getTypeDescription(), SearchCriteria.Op.EQ);
VolumeIdTypeSearch.and("type", VolumeIdTypeSearch.entity().getsnapshotType(), SearchCriteria.Op.EQ);
VolumeIdTypeSearch.done();
ParentIdSearch = createSearchBuilder();

View File

@ -21,6 +21,7 @@ package com.cloud.storage.dao;
import java.util.List;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
@ -30,7 +31,7 @@ import com.cloud.utils.db.GenericDao;
public interface SnapshotPolicyDao extends GenericDao<SnapshotPolicyVO, Long> {
List<SnapshotPolicyVO> listByVolumeId(long volumeId);
List<SnapshotPolicyVO> listByVolumeId(long volumeId, Filter filter);
SnapshotPolicyVO findOneByVolumeInterval(long volumeId, short interval);
SnapshotPolicyVO findOneByVolumeInterval(long volumeId, IntervalType intvType);
List<SnapshotPolicyVO> listActivePolicies();
SnapshotPolicyVO findOneByVolume(long volumeId);
}

View File

@ -24,6 +24,7 @@ import java.util.List;
import javax.ejb.Local;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
@ -36,11 +37,11 @@ public class SnapshotPolicyDaoImpl extends GenericDaoBase<SnapshotPolicyVO, Long
private final SearchBuilder<SnapshotPolicyVO> ActivePolicySearch;
@Override
public SnapshotPolicyVO findOneByVolumeInterval(long volumeId, short interval) {
public SnapshotPolicyVO findOneByVolumeInterval(long volumeId, IntervalType intvType) {
SearchCriteria<SnapshotPolicyVO> sc = VolumeIdIntervalSearch.create();
sc.setParameters("volumeId", volumeId);
sc.setParameters("interval", interval);
return findOneIncludingRemovedBy(sc);
sc.setParameters("interval", intvType.ordinal());
return findOneBy(sc);
}
@Override

View File

@ -39,4 +39,6 @@ public interface SnapshotScheduleDao extends GenericDao<SnapshotScheduleVO, Long
SnapshotScheduleVO findOneByVolume(long volumeId);
SnapshotScheduleVO findOneByVolumePolicy(long volumeId, long policyId);
}

View File

@ -38,6 +38,7 @@ public class SnapshotScheduleDaoImpl extends GenericDaoBase<SnapshotScheduleVO,
protected final SearchBuilder<SnapshotScheduleVO> executableSchedulesSearch;
protected final SearchBuilder<SnapshotScheduleVO> coincidingSchedulesSearch;
private final SearchBuilder<SnapshotScheduleVO> VolumeIdSearch;
private final SearchBuilder<SnapshotScheduleVO> VolumeIdPolicyIdSearch;
// DB constraint: For a given volume and policyId, there will only be one entry in this table.
@ -57,6 +58,11 @@ public class SnapshotScheduleDaoImpl extends GenericDaoBase<SnapshotScheduleVO,
VolumeIdSearch = createSearchBuilder();
VolumeIdSearch.and("volumeId", VolumeIdSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
VolumeIdSearch.done();
VolumeIdPolicyIdSearch = createSearchBuilder();
VolumeIdPolicyIdSearch.and("volumeId", VolumeIdPolicyIdSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
VolumeIdPolicyIdSearch.and("policyId", VolumeIdPolicyIdSearch.entity().getPolicyId(), SearchCriteria.Op.EQ);
VolumeIdPolicyIdSearch.done();
}
@ -80,6 +86,15 @@ public class SnapshotScheduleDaoImpl extends GenericDaoBase<SnapshotScheduleVO,
sc.setParameters("volumeId", volumeId);
return findOneBy(sc);
}
@Override
public SnapshotScheduleVO findOneByVolumePolicy(long volumeId, long policyId) {
SearchCriteria<SnapshotScheduleVO> sc = VolumeIdPolicyIdSearch.create();
sc.setParameters("volumeId", volumeId);
sc.setParameters("policyId", policyId);
return findOneBy(sc);
}
/**
* {@inheritDoc}
*/
@ -87,8 +102,6 @@ public class SnapshotScheduleDaoImpl extends GenericDaoBase<SnapshotScheduleVO,
public List<SnapshotScheduleVO> getSchedulesToExecute(Date currentTimestamp) {
SearchCriteria<SnapshotScheduleVO> sc = executableSchedulesSearch.create();
sc.setParameters("scheduledTimestamp", currentTimestamp);
// Don't return manual snapshots. They will be executed through another code path.
sc.addAnd("policyId", SearchCriteria.Op.NEQ, 1L);
return listBy(sc);
}

View File

@ -158,7 +158,7 @@ public class StoragePoolDaoImpl extends GenericDaoBase<StoragePoolVO, Long> imp
public List<StoragePoolVO> listByDataCenterId(long datacenterId) {
SearchCriteria<StoragePoolVO> sc = DatacenterSearch.create();
sc.setParameters("datacenterId", datacenterId);
return listIncludingRemovedBy(sc);
return listBy(sc);
}

View File

@ -23,6 +23,7 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericDao;
@ -55,4 +56,5 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long> {
HypervisorType getHypervisorType(long volumeId);
List<VolumeVO> listVolumesToBeDestroyed();
ImageFormat getImageFormat(Long volumeId);
}

View File

@ -29,9 +29,12 @@ import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.dc.ClusterVO;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeVO;
import com.cloud.utils.Pair;
@ -264,6 +267,21 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
}
}
@Override
public ImageFormat getImageFormat(Long volumeId) {
HypervisorType type = getHypervisorType(volumeId);
if ( type.equals(HypervisorType.KVM)) {
return ImageFormat.QCOW2;
} else if ( type.equals(HypervisorType.XenServer)) {
return ImageFormat.VHD;
} else if ( type.equals(HypervisorType.VMware)) {
return ImageFormat.OVA;
} else {
s_logger.warn("Do not support hypervisor " + type.toString());
return null;
}
}
protected VolumeDaoImpl() {
AllFieldsSearch = createSearchBuilder();
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ);

View File

@ -24,6 +24,7 @@ import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.VolumeVO;
import com.cloud.utils.db.Filter;
/**
*
@ -35,7 +36,7 @@ public interface SnapshotManager {
public static final int HOURLYMAX = 8;
public static final int DAILYMAX = 8;
public static final int WEEKLYMAX = 8;
public static final int MONTHLYMAX = 8;
public static final int MONTHLYMAX = 12;
public static final int DELTAMAX = 16;
/**
@ -101,8 +102,6 @@ public interface SnapshotManager {
*/
List<SnapshotVO> listSnapsforVolume(long volumeId);
SnapshotPolicyVO getPolicyForVolumeByInterval(long volumeId, short interval);
void deletePoliciesForVolume(Long volumeId);
/**
@ -116,11 +115,9 @@ public interface SnapshotManager {
void validateSnapshot(Long userId, SnapshotVO snapshot);
ImageFormat getImageFormat(Long volumeId);
SnapshotPolicyVO getPolicyForVolume(long volumeId);
boolean destroySnapshotBackUp(long snapshotId, long policyId);
boolean destroySnapshotBackUp(long snapshotId);
/**
* Create a snapshot of a volume
@ -128,4 +125,8 @@ public interface SnapshotManager {
* @return the Snapshot that was created
*/
SnapshotVO createSnapshotOnPrimary(VolumeVO volume, Long polocyId, Long snapshotId) throws ResourceAllocationException;
List<SnapshotPolicyVO> listPoliciesforSnapshot(long snapshotId);
List<SnapshotVO> listSnapsforPolicy(long policyId, Filter filter);
}

View File

@ -26,7 +26,6 @@ import java.util.TimeZone;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import javax.persistence.EntityExistsException;
import org.apache.log4j.Logger;
@ -74,11 +73,9 @@ import com.cloud.storage.Snapshot.Type;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotScheduleVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
@ -86,9 +83,6 @@ import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.SnapshotScheduleDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@ -133,9 +127,6 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
@Inject protected SnapshotPolicyDao _snapshotPolicyDao = null;
@Inject protected SnapshotScheduleDao _snapshotScheduleDao;
@Inject protected DetailsDao _detailsDao;
@Inject protected VMTemplateDao _templateDao;
@Inject protected VMTemplatePoolDao _templatePoolDao;
@Inject protected VMTemplateHostDao _templateHostDao;
@Inject protected DomainDao _domainDao;
@Inject protected StorageManager _storageMgr;
@Inject protected AgentManager _agentMgr;
@ -188,19 +179,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
return runSnap;
}
@Override
public ImageFormat getImageFormat(Long volumeId) {
ImageFormat format = null;
VolumeVO volume = _volsDao.findById(volumeId);
Long templateId = volume.getTemplateId();
if (templateId != null) {
VMTemplateVO template = _templateDao.findById(templateId);
format = template.getFormat();
}
return format;
}
protected Answer sendToPool(Volume vol, Command cmd) {
StoragePool pool = _storagePoolDao.findById(vol.getPoolId());
VMInstanceVO vm = _vmDao.findById(vol.getInstanceId());
@ -523,25 +502,18 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), volume.getDataCenterId(), snapshotId, snapshot.getName(), null, null, volume.getSize());
_usageEventDao.persist(usageEvent);
if (snapshot.getSnapshotType() == Type.RECURRING.ordinal()) {
if (snapshot.getType() == Type.RECURRING ) {
_accountMgr.incrementResourceCount(snapshot.getAccountId(), ResourceType.snapshot);
}
}
else {
// Just mark it as removed in the database. When the next snapshot it taken,
// validate previous snapshot will fix the state.
// It will
// 1) Call backupSnapshotToSecondaryStorage and try again.
// 2) Create the next Snapshot pretending this is a valid snapshot.
// 3) backupSnapshotToSecondaryStorage of the next snapshot
// will take care of cleaning up the state of this snapshot
if (snapshot.getSnapshotType() == Type.RECURRING.ordinal()) {
if (snapshot.getType() == Type.MANUAL ) {
_accountMgr.decrementResourceCount(snapshot.getAccountId(), ResourceType.snapshot);
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(), 0L, snapshotId, snapshot.getName(), null, null, 0L);
_usageEventDao.persist(usageEvent);
}
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(), 0L, snapshotId, snapshot.getName(), null, null, 0L);
_usageEventDao.persist(usageEvent);
_snapshotDao.remove(snapshotId);
}
txn.commit();
@ -566,45 +538,42 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
@DB
public void postCreateSnapshot(Long volumeId, Long snapshotId, Long policyId, boolean backedUp) {
Long userId = getSnapshotUserId();
SnapshotVO snapshot = _snapshotDao.findByIdIncludingRemoved(snapshotId);
// Update the snapshot_policy_ref table with the created snapshot
// Get the list of policies for this snapshot
Transaction txn = Transaction.currentTxn();
txn.start();
if (backedUp) {
// This is a manual create, so increment the count of snapshots for
// this account
if (policyId == Snapshot.MANUAL_POLICY_ID) {
Snapshot snapshot = _snapshotDao.findByIdIncludingRemoved(snapshotId);
if ( snapshot.getType() == Type.MANUAL) {
_accountMgr.incrementResourceCount(snapshot.getAccountId(), ResourceType.snapshot);
}
}
// Even if the current snapshot failed, we should schedule the next
// recurring snapshot for this policy.
if (policyId != Snapshot.MANUAL_POLICY_ID) {
if ( snapshot.isRecursive()) {
postCreateRecurringSnapshotForPolicy(userId, volumeId, snapshotId, policyId);
}
txn.commit();
}
private void postCreateRecurringSnapshotForPolicy(long userId, long volumeId, long snapshotId, long policyId) {
//Use count query
List<SnapshotVO> snaps = listSnapsforVolumeType(volumeId, Type.RECURRING.name());
SnapshotVO spstVO = _snapshotDao.findById(snapshotId);
Type type = spstVO.getType();
int maxSnaps = type.getMax();
List<SnapshotVO> snaps = listSnapsforVolumeType(volumeId, type);
SnapshotPolicyVO policy = _snapshotPolicyDao.findById(policyId);
while(snaps.size() > policy.getMaxSnaps() && snaps.size() > 1) {
//Delete the oldest snap ref in snap_policy_ref
if ( policy != null && policy.getMaxSnaps() < maxSnaps ) {
maxSnaps = policy.getMaxSnaps();
}
while(snaps.size() > maxSnaps && snaps.size() > 1) {
SnapshotVO oldestSnapshot = snaps.get(0);
long oldSnapId = oldestSnapshot.getId();
s_logger.debug("Max snaps: "+ policy.getMaxSnaps() + " exceeded for snapshot policy with Id: " + policyId + ". Deleting oldest snapshot: " + oldSnapId);
// Excess snapshot. delete it asynchronously
//destroySnapshotAsync(userId, volumeId, oldSnapId, policyId);
// create the event
deleteSnapshotInternal(oldSnapId, policyId);
deleteSnapshotInternal(oldSnapId);
snaps.remove(oldestSnapshot);
}
}
private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) {
@ -648,33 +617,18 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
checkAccountPermissions(snapshotOwner.getId(), snapshotOwner.getDomainId(), "snapshot", snapshotId);
boolean status = true;
if (Type.MANUAL.ordinal() == snapshotCheck.getSnapshotType()) {
status = deleteSnapshotInternal(snapshotId, Snapshot.MANUAL_POLICY_ID);
if (!status) {
s_logger.warn("Failed to delete snapshot");
throw new CloudRuntimeException("Failed to delete snapshot:"+snapshotId);
}
} else {
List<SnapshotPolicyVO> policies = listPoliciesforVolume(snapshotCheck.getVolumeId());
for (SnapshotPolicyVO policy : policies) {
status = deleteSnapshotInternal(snapshotId, policy.getId());
if (!status) {
s_logger.warn("Failed to delete snapshot");
throw new CloudRuntimeException("Failed to delete snapshot:"+snapshotId);
}
}
boolean status = deleteSnapshotInternal(snapshotId);
if (!status) {
s_logger.warn("Failed to delete snapshot");
throw new CloudRuntimeException("Failed to delete snapshot:" + snapshotId);
}
return status;
}
private boolean deleteSnapshotInternal(Long snapshotId, Long policyId) {
private boolean deleteSnapshotInternal(Long snapshotId) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId + " and policyId " + policyId);
s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId );
}
SnapshotVO lastSnapshot = null;
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
@ -713,7 +667,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
lastSnapshot.setBackupSnapshotId(null);
_snapshotDao.update(lastSnapshot.getId(), lastSnapshot);
} else {
if (destroySnapshotBackUp(lastId, policyId)) {
if (destroySnapshotBackUp(lastId)) {
} else {
s_logger.debug("Destroying snapshot backup failed " + lastSnapshot);
@ -721,7 +675,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
}
}
postDeleteSnapshot(lastId, policyId);
postDeleteSnapshot(lastId);
lastId = lastSnapshot.getPrevSnapshotId();
if (lastId == 0) {
break;
@ -738,60 +692,58 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
@Override @DB
public boolean destroySnapshotBackUp(long snapshotId, long policyId) {
public boolean destroySnapshotBackUp(long snapshotId) {
boolean success = false;
String details = null;
String details;
SnapshotVO snapshot = _snapshotDao.findByIdIncludingRemoved(snapshotId);
VolumeVO volume = _volsDao.findByIdIncludingRemoved(snapshot.getVolumeId());
if ( volume == null ) {
throw new CloudRuntimeException("Destroying snapshot " + snapshotId + " backup failed due to unable to find volume " + snapshot.getVolumeId());
if ( snapshot == null ) {
throw new CloudRuntimeException("Destroying snapshot " + snapshotId + " backup failed due to unable to find snapshot ");
}
String primaryStoragePoolNameLabel = _storageMgr.getPrimaryStorageNameLabel(volume);
String secondaryStoragePoolUrl = _storageMgr.getSecondaryStorageURL(volume.getDataCenterId());
Long dcId = volume.getDataCenterId();
Long accountId = volume.getAccountId();
Long volumeId = volume.getId();
String secondaryStoragePoolUrl = _storageMgr.getSecondaryStorageURL(snapshot.getDataCenterId());
Long dcId = snapshot.getDataCenterId();
Long accountId = snapshot.getAccountId();
Long volumeId = snapshot.getVolumeId();
HypervisorType hvType = snapshot.getHypervisorType();
String backupOfSnapshot = snapshot.getBackupSnapshotId();
if ( backupOfSnapshot == null ) {
return true;
}
DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand(primaryStoragePoolNameLabel,
DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand(null,
secondaryStoragePoolUrl, dcId, accountId, volumeId, backupOfSnapshot, snapshot.getName());
snapshot.setBackupSnapshotId(null);
_snapshotDao.update(snapshotId, snapshot);
details = "Failed to destroy snapshot id:" + snapshotId + " for volume: " + volume.getId();
Answer answer = sendToPool(volume, cmd);
Answer answer = _agentMgr.sendTo(dcId, hvType, cmd);
if ((answer != null) && answer.getResult()) {
// This is not the last snapshot.
success = true;
details = "Successfully deleted snapshot " + snapshotId + " for volumeId: " + volumeId + " and policyId "
+ policyId;
details = "Successfully deleted snapshot " + snapshotId + " for volumeId: " + volumeId ;
s_logger.debug(details);
} else if (answer != null) {
details = "Failed to destroy snapshot id:" + snapshotId + " for volume: " + volumeId + " due to ";
if (answer.getDetails() != null) {
details = answer.getDetails();
details += answer.getDetails();
}
s_logger.error(details);
}
return success;
}
@DB
protected void postDeleteSnapshot(long snapshotId, long policyId) {
protected void postDeleteSnapshot(long snapshotId) {
// Remove the snapshot from the snapshots table and the snap_policy_ref table.
Transaction txn = Transaction.currentTxn();
txn.start();
SnapshotVO snapshot = _snapshotDao.findByIdIncludingRemoved(snapshotId);
// If this is a manual delete, decrement the count of snapshots for this account
if (policyId == Snapshot.MANUAL_POLICY_ID) {
if (snapshot.getType() == Type.MANUAL) {
_accountMgr.decrementResourceCount(snapshot.getAccountId(), ResourceType.snapshot);
}
@ -807,10 +759,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
// Verify parameters
if(volumeId != null){
VolumeVO volume = _volsDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
if (volume != null) {
checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
}
checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
}
Account account = UserContext.current().getCaller();
@ -855,8 +807,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("snapshotTypeEQ", sb.entity().getSnapshotType(), SearchCriteria.Op.EQ);
sb.and("snapshotTypeNEQ", sb.entity().getSnapshotType(), SearchCriteria.Op.NEQ);
sb.and("snapshotTypeEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.IN);
sb.and("snapshotTypeNEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.NEQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
@ -912,9 +864,17 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
if (snapshotType == null) {
throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
}
sc.setParameters("snapshotTypeEQ", snapshotType.ordinal());
if ( snapshotType == Type.RECURRING ) {
sc.setParameters("snapshotTypeEQ", Type.HOURLY.ordinal(), Type.DAILY.ordinal(), Type.WEEKLY.ordinal(), Type.MONTHLY.ordinal() );
} else {
sc.setParameters("snapshotTypeEQ", snapshotType.ordinal());
}
} else if (intervalTypeStr != null && volumeId != null) {
sc.setParameters("snapshotTypeEQ", Snapshot.Type.RECURRING.ordinal());
Type type = SnapshotVO.getSnapshotType((String)intervalTypeStr);
if ( type == null ) {
throw new InvalidParameterValueException("Unsupported snapstho interval type " + intervalTypeStr);
}
sc.setParameters("snapshotTypeEQ", type.ordinal());
} else {
// Show only MANUAL and RECURRING snapshot types
sc.setParameters("snapshotTypeNEQ", Snapshot.Type.TEMPLATE.ordinal());
@ -973,7 +933,9 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
List<SnapshotVO> snapshots = listSnapsforVolume(volumeId);
for (SnapshotVO snapshot: snapshots) {
if(_snapshotDao.expunge(snapshot.getId())){
_accountMgr.decrementResourceCount(accountId, ResourceType.snapshot);
if ( snapshot.getType() == Type.MANUAL ) {
_accountMgr.decrementResourceCount(accountId, ResourceType.snapshot);
}
//Log event after successful deletion
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(), volume.getDataCenterId(), snapshot.getId(), snapshot.getName(), null, null, volume.getSize());
@ -1008,32 +970,32 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
throw new InvalidParameterValueException("Failed to create snapshot policy, snapshots of volumes attached to System or router VM are not allowed");
}
}
IntervalType type = DateUtil.IntervalType.getIntervalType(cmd.getIntervalType());
if (type == null) {
IntervalType intvType = DateUtil.IntervalType.getIntervalType(cmd.getIntervalType());
if (intvType == null) {
throw new InvalidParameterValueException("Unsupported interval type " + cmd.getIntervalType());
}
Type type = getSnapshotType(intvType);
TimeZone timeZone = TimeZone.getTimeZone(cmd.getTimezone());
String timezoneId = timeZone.getID();
if (!timezoneId.equals(cmd.getTimezone())) {
s_logger.warn("Using timezone: " + timezoneId + " for running this snapshot policy as an equivalent of " + cmd.getTimezone());
}
try {
DateUtil.getNextRunTime(type, cmd.getSchedule(), timezoneId, null);
DateUtil.getNextRunTime(intvType, cmd.getSchedule(), timezoneId, null);
} catch (Exception e){
throw new InvalidParameterValueException("Invalid schedule: "+ cmd.getSchedule() +" for interval type: " + cmd.getIntervalType());
}
if (cmd.getMaxSnaps() <=0) {
throw new InvalidParameterValueException("maxSnaps should be greater than 0");
}
int intervalMaxSnaps = type.getMax();
if (cmd.getMaxSnaps() > intervalMaxSnaps) {
throw new InvalidParameterValueException("maxSnaps exceeds limit: " + intervalMaxSnaps + " for interval type: " + cmd.getIntervalType());
}
if (cmd.getMaxSnaps() <=0) {
throw new InvalidParameterValueException("maxSnaps should be greater than 0");
}
//Verify that max doesn't exceed domain and account snapshot limits
long accountLimit = _accountMgr.findCorrectResourceLimit(owner, ResourceType.snapshot);
long domainLimit = _accountMgr.findCorrectResourceLimit(domain, ResourceType.snapshot);
@ -1042,17 +1004,17 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
throw new InvalidParameterValueException("Max number of snapshots shouldn't exceed the domain/account level snapshot limit");
}
SnapshotPolicyVO policy = new SnapshotPolicyVO(volumeId, cmd.getSchedule(), timezoneId, (short)type.ordinal(), cmd.getMaxSnaps());
// Create an event
try{
SnapshotPolicyVO policy = _snapshotPolicyDao.findOneByVolumeInterval(volumeId, intvType);
if ( policy == null ) {
policy = new SnapshotPolicyVO(volumeId, cmd.getSchedule(), timezoneId, intvType, cmd.getMaxSnaps());
policy = _snapshotPolicyDao.persist(policy);
} catch (EntityExistsException e ) {
policy = _snapshotPolicyDao.findOneByVolume(volumeId);
_snapSchedMgr.scheduleNextSnapshotJob(policy);
} else {
try {
policy = _snapshotPolicyDao.acquireInLockTable(policy.getId());
policy.setSchedule(cmd.getSchedule());
policy.setTimezone(timezoneId);
policy.setInterval((short)type.ordinal());
policy.setInterval((short) type.ordinal());
policy.setMaxSnaps(cmd.getMaxSnaps());
policy.setActive(true);
_snapshotPolicyDao.update(policy.getId(), policy);
@ -1061,8 +1023,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
_snapshotPolicyDao.releaseFromLockTable(policy.getId());
}
}
}
_snapSchedMgr.scheduleNextSnapshotJob(policy);
return policy;
}
@ -1088,7 +1050,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
public List<SnapshotPolicyVO> listPoliciesforVolume(long volumeId) {
return _snapshotPolicyDao.listByVolumeId(volumeId);
}
/*
@Override
public List<SnapshotPolicyVO> listPoliciesforSnapshot(long snapshotId) {
SearchCriteria<SnapshotPolicyVO> sc = PoliciesForSnapSearch.create();
@ -1102,14 +1064,14 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
sc.setJoinParameters("policy", "policyId", policyId);
return _snapshotDao.search(sc, filter);
}
*/
@Override
public List<SnapshotVO> listSnapsforVolume(long volumeId) {
return _snapshotDao.listByVolumeId(volumeId);
}
public List<SnapshotVO> listSnapsforVolumeType(long volumeId, String type) {
public List<SnapshotVO> listSnapsforVolumeType(long volumeId, Type type) {
return _snapshotDao.listByVolumeIdType(volumeId, type);
}
@ -1170,16 +1132,35 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
return snapshotSchedules;
}
@Override
public SnapshotPolicyVO getPolicyForVolumeByInterval(long volumeId, short interval) {
return _snapshotPolicyDao.findOneByVolumeInterval(volumeId, interval);
}
@Override
public SnapshotPolicyVO getPolicyForVolume(long volumeId) {
return _snapshotPolicyDao.findOneByVolume(volumeId);
}
public Type getSnapshotType(Long policyId) {
if (policyId.equals(Snapshot.MANUAL_POLICY_ID)) {
return Type.MANUAL;
} else {
SnapshotPolicyVO spstPolicyVO = _snapshotPolicyDao.findById(policyId);
IntervalType intvType = DateUtil.getIntervalType(spstPolicyVO.getInterval());
return getSnapshotType(intvType);
}
}
public Type getSnapshotType(IntervalType intvType) {
if (intvType.equals(IntervalType.HOURLY)) {
return Type.HOURLY;
} else if (intvType.equals(IntervalType.DAILY)) {
return Type.DAILY;
} else if (intvType.equals(IntervalType.WEEKLY)) {
return Type.WEEKLY;
} else if (intvType.equals(IntervalType.MONTHLY)) {
return Type.MONTHLY;
}
return null;
}
@Override
public SnapshotVO allocSnapshot(CreateSnapshotCmd cmd) {
Long volumeId = cmd.getVolumeId();
@ -1208,10 +1189,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
// Create the Snapshot object and save it so we can return it to the
// user
Type snapshotType = SnapshotVO.getSnapshotType(policyId);
Type snapshotType = getSnapshotType(policyId);
HypervisorType hypervisorType = this._volsDao.getHypervisorType(volumeId);
SnapshotVO snapshotVO = new SnapshotVO(volume.getAccountId(), volume.getId(), null, snapshotName,
(short) snapshotType.ordinal(), snapshotType.name(), hypervisorType);
SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), null, snapshotName,
(short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), hypervisorType);
return _snapshotDao.persist(snapshotVO);
}
@ -1226,10 +1207,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
throw new ConfigurationException("Unable to get the configuration dao.");
}
DateUtil.IntervalType.HOURLY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.hourly"), HOURLYMAX));
DateUtil.IntervalType.DAILY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.daily"), DAILYMAX));
DateUtil.IntervalType.WEEKLY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.weekly"), WEEKLYMAX));
DateUtil.IntervalType.MONTHLY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.monthly"), MONTHLYMAX));
Type.HOURLY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.hourly"), HOURLYMAX));
Type.DAILY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.daily"), DAILYMAX));
Type.WEEKLY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.weekly"), WEEKLYMAX));
Type.MONTHLY.setMax(NumbersUtil.parseInt(configDao.getValue("snapshot.max.monthly"), MONTHLYMAX));
_deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"), DELTAMAX);
_totalRetries = NumbersUtil.parseInt(configDao.getValue("total.retries"), 4);
_pauseInterval = 2*NumbersUtil.parseInt(configDao.getValue("ping.interval"), 60);

View File

@ -26,7 +26,6 @@ import java.util.TimerTask;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import javax.persistence.EntityExistsException;
import org.apache.log4j.Logger;
@ -133,7 +132,7 @@ public class SnapshotSchedulerImpl implements SnapshotScheduler {
}
} finally {
scanLock.releaseRef();
}
}
}
private void checkStatusOfCurrentlyExecutingSnapshots() {
@ -182,7 +181,7 @@ public class SnapshotSchedulerImpl implements SnapshotScheduler {
// If the snapshot was taken successfully on primary, it will retry backing it up.
// and cleanup the previous snapshot
// Set the userId to that of system.
_snapshotManager.validateSnapshot(1L, snapshot);
//_snapshotManager.validateSnapshot(1L, snapshot);
// In all cases, schedule the next snapshot job
scheduleNextSnapshotJob(snapshotSchedule);
}
@ -222,6 +221,9 @@ public class SnapshotSchedulerImpl implements SnapshotScheduler {
// this volume is not attached
continue;
}
if ( _snapshotPolicyDao.findById(policyId) == null ) {
_snapshotScheduleDao.remove(snapshotToBeExecuted.getId());
}
if (s_logger.isDebugEnabled()) {
Date scheduledTimestamp = snapshotToBeExecuted.getScheduledTimestamp();
displayTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, scheduledTimestamp);
@ -270,38 +272,46 @@ public class SnapshotSchedulerImpl implements SnapshotScheduler {
}
private Date scheduleNextSnapshotJob(SnapshotScheduleVO snapshotSchedule) {
Long policyId = snapshotSchedule.getPolicyId();
Long expectedId = snapshotSchedule.getId();
if (_snapshotScheduleDao.findById(expectedId) != null) {
// We need to acquire a lock and delete it, then release the lock.
// But I don't know how to.
_snapshotScheduleDao.expunge(expectedId);
if ( snapshotSchedule == null ) {
return null;
}
Long policyId = snapshotSchedule.getPolicyId();
if (policyId.longValue() == Snapshot.MANUAL_POLICY_ID) {
// Don't need to schedule the next job for this.
return null;
}
SnapshotPolicyVO snapshotPolicy = _snapshotPolicyDao.findById(policyId);
if ( snapshotPolicy == null ) {
_snapshotScheduleDao.expunge(snapshotSchedule.getId());
}
return scheduleNextSnapshotJob(snapshotPolicy);
}
@Override @DB
public Date scheduleNextSnapshotJob(SnapshotPolicyVO policyInstance) {
long policyId = policyInstance.getId();
Date nextSnapshotTimestamp = getNextScheduledTime(policyId, new Date());
SnapshotScheduleVO snapshotScheduleVO = new SnapshotScheduleVO(policyInstance.getVolumeId(), policyId, nextSnapshotTimestamp);
try{
_snapshotScheduleDao.persist(snapshotScheduleVO);
} catch (EntityExistsException e ) {
snapshotScheduleVO = _snapshotScheduleDao.findOneByVolume(policyInstance.getVolumeId());
try {
snapshotScheduleVO = _snapshotScheduleDao.acquireInLockTable(snapshotScheduleVO.getId());
snapshotScheduleVO.setPolicyId(policyId);
snapshotScheduleVO.setScheduledTimestamp(nextSnapshotTimestamp);
_snapshotScheduleDao.update(snapshotScheduleVO.getId(), snapshotScheduleVO);
public Date scheduleNextSnapshotJob(SnapshotPolicyVO policy) {
if ( policy == null) {
return null;
}
long policyId = policy.getId();
if ( policyId == Snapshot.MANUAL_POLICY_ID ) {
return null;
}
Date nextSnapshotTimestamp = getNextScheduledTime(policyId, _currentTimestamp);
SnapshotScheduleVO spstSchedVO = _snapshotScheduleDao.findOneByVolumePolicy(policy.getVolumeId(), policy.getId());
if ( spstSchedVO == null ) {
spstSchedVO = new SnapshotScheduleVO(policy.getVolumeId(), policyId, nextSnapshotTimestamp);
_snapshotScheduleDao.persist(spstSchedVO);
} else {
try{
spstSchedVO = _snapshotScheduleDao.acquireInLockTable(spstSchedVO.getId());
spstSchedVO.setPolicyId(policyId);
spstSchedVO.setScheduledTimestamp(nextSnapshotTimestamp);
spstSchedVO.setAsyncJobId(null);
spstSchedVO.setSnapshotId(null);
_snapshotScheduleDao.update(spstSchedVO.getId(), spstSchedVO);
} finally {
if(snapshotScheduleVO != null ) {
_snapshotScheduleDao.releaseFromLockTable(snapshotScheduleVO.getId());
if(spstSchedVO != null ) {
_snapshotScheduleDao.releaseFromLockTable(spstSchedVO.getId());
}
}
}
@ -316,7 +326,7 @@ public class SnapshotSchedulerImpl implements SnapshotScheduler {
SnapshotScheduleVO schedule = _snapshotScheduleDao.getCurrentSchedule(volumeId, policyId, false);
boolean success = true;
if (schedule != null) {
success = _snapshotScheduleDao.expunge(schedule.getId());
success = _snapshotScheduleDao.remove(schedule.getId());
}
if(!success){
s_logger.debug("Error while deleting Snapshot schedule with Id: "+schedule.getId());

View File

@ -19,7 +19,6 @@ package com.cloud.vm;
import java.util.ArrayList;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -133,7 +132,6 @@ import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.StorageResourceType;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateHostVO;
@ -1194,106 +1192,107 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
if (user == null) {
throw new InvalidParameterValueException("User " + userId + " does not exist");
}
Long volumeId = cmd.getVolumeId();
Long snapshotId = cmd.getSnapshotId();
if (volumeId == null) {
if (snapshotId == null) {
throw new InvalidParameterValueException("Failed to create private template record, neither volume ID nor snapshot ID were specified.");
}
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
if (snapshot == null) {
throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId);
}
volumeId = snapshot.getVolumeId();
} else {
if (snapshotId != null) {
throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId + ") and snapshot ID (" + snapshotId + ")");
}
}
VolumeVO volume = _volsDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("Volume with ID: " + volumeId + " does not exist");
}
if (!isAdmin) {
if (account.getId() != volume.getAccountId()) {
throw new PermissionDeniedException("Unable to create a template from volume with id " + volumeId + ", permission denied.");
}
} else if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), volume.getDomainId())) {
throw new PermissionDeniedException("Unable to create a template from volume with id " + volumeId + ", permission denied.");
}
}
String name = cmd.getTemplateName();
if ((name == null) || (name.length() > 32)) {
throw new InvalidParameterValueException("Template name cannot be null and should be less than 32 characters");
}
String uniqueName = Long.valueOf((userId == null)?1:userId).toString() + Long.valueOf(volumeId).toString() + UUID.nameUUIDFromBytes(name.getBytes()).toString();
VMTemplateVO existingTemplate = _templateDao.findByTemplateNameAccountId(name, volume.getAccountId());
if (existingTemplate != null) {
throw new InvalidParameterValueException("Failed to create private template " + name + ", a template with that name already exists.");
}
AccountVO ownerAccount = _accountDao.findById(volume.getAccountId());
if (_accountMgr.resourceLimitExceeded(ownerAccount, ResourceType.template)) {
ResourceAllocationException rae = new ResourceAllocationException("Maximum number of templates and ISOs for account: " + account.getAccountName() + " has been exceeded.");
rae.setResourceType("template");
throw rae;
}
// do some parameter defaulting
Integer bits = cmd.getBits();
Boolean requiresHvm = cmd.getRequiresHvm();
Boolean passwordEnabled = cmd.isPasswordEnabled();
Boolean isPublic = cmd.isPublic();
Boolean featured = cmd.isFeatured();
HypervisorType hyperType = _volsDao.getHypervisorType(volumeId);
int bitsValue = ((bits == null) ? 64 : bits.intValue());
boolean requiresHvmValue = ((requiresHvm == null) ? true : requiresHvm.booleanValue());
boolean passwordEnabledValue = ((passwordEnabled == null) ? false : passwordEnabled.booleanValue());
Integer bits = cmd.getBits();
Boolean requiresHvm = cmd.getRequiresHvm();
Boolean passwordEnabled = cmd.isPasswordEnabled();
Boolean isPublic = cmd.isPublic();
Boolean featured = cmd.isFeatured();
int bitsValue = ((bits == null) ? 64 : bits.intValue());
boolean requiresHvmValue = ((requiresHvm == null) ? true : requiresHvm.booleanValue());
boolean passwordEnabledValue = ((passwordEnabled == null) ? false : passwordEnabled.booleanValue());
if (isPublic == null) {
isPublic = Boolean.FALSE;
}
if (!isAdmin || featured == null) {
featured = Boolean.FALSE;
}
boolean allowPublicUserTemplates = Boolean.parseBoolean(_configDao.getValue("allow.public.user.templates"));
if (!isAdmin && !allowPublicUserTemplates && isPublic) {
throw new PermissionDeniedException("Failed to create template " + name + ", only private templates can be created.");
}
// if the volume is a root disk, try to find out requiresHvm and bits if possible
if (Volume.VolumeType.ROOT.equals(volume.getVolumeType())) {
Long instanceId = volume.getInstanceId();
if (instanceId != null) {
UserVm vm = _vmDao.findById(instanceId);
if (vm != null) {
VMTemplateVO origTemplate = _templateDao.findById(vm.getTemplateId());
if (!ImageFormat.ISO.equals(origTemplate.getFormat()) && !ImageFormat.RAW.equals(origTemplate.getFormat())) {
bitsValue = origTemplate.getBits();
requiresHvmValue = origTemplate.requiresHvm();
}
}
Long volumeId = cmd.getVolumeId();
Long snapshotId = cmd.getSnapshotId();
if ( (volumeId == null) && (snapshotId == null) ) {
throw new InvalidParameterValueException("Failed to create private template record, neither volume ID nor snapshot ID were specified.");
}
if ( (volumeId != null) && (snapshotId != null) ) {
throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId + ") and snapshot ID (" + snapshotId + ")");
}
long domainId;
long accountId;
HypervisorType hyperType;
VolumeVO volume = null;
if (volumeId != null) { // create template from volume
volume = _volsDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("Failed to create private template record, unable to find volume " + volumeId);
}
// If private template is created from Volume, check that the volume will not be active when the private template is created
if (!_storageMgr.volumeInactive(volume)) {
String msg = "Unable to create private template for volume: " + volume.getName() + "; volume is attached to a non-stopped VM, please stop the VM first" ;
if (s_logger.isInfoEnabled()) {
s_logger.info(msg);
}
throw new CloudRuntimeException(msg);
}
domainId = volume.getDomainId();
accountId = volume.getAccountId();
hyperType = _volsDao.getHypervisorType(volumeId);
} else { // create template from snapshot
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
if (snapshot == null) {
throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId);
}
domainId = snapshot.getDomainId();
accountId = snapshot.getAccountId();
hyperType = snapshot.getHypervisorType();
volume = _volsDao.findById(snapshot.getVolumeId());
}
if (!isAdmin) {
if (account.getId() != accountId) {
throw new PermissionDeniedException("Unable to create a template permission denied.");
}
} else if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Unable to create a template permission denied.");
}
VMTemplateVO existingTemplate = _templateDao.findByTemplateNameAccountId(name, accountId);
if (existingTemplate != null) {
throw new InvalidParameterValueException("Failed to create private template " + name + ", a template with that name already exists.");
}
AccountVO ownerAccount = _accountDao.findById(accountId);
if (_accountMgr.resourceLimitExceeded(ownerAccount, ResourceType.template)) {
ResourceAllocationException rae = new ResourceAllocationException("Maximum number of templates and ISOs for account: " + account.getAccountName() + " has been exceeded.");
rae.setResourceType("template");
throw rae;
}
if (!isAdmin || featured == null) {
featured = Boolean.FALSE;
}
Long guestOSId = cmd.getOsTypeId();
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
if (guestOS == null) {
throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist.");
}
String uniqueName = Long.valueOf((userId == null)?1:userId).toString() + UUID.nameUUIDFromBytes(name.getBytes()).toString();
Long nextTemplateId = _templateDao.getNextInSequence(Long.class, "id");
String description = cmd.getDisplayText();
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
boolean isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM ;
boolean isExtractable = false;
if ( volume != null ) {
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM ;
}
privateTemplate = new VMTemplateVO(nextTemplateId,
uniqueName,
name,
@ -1306,7 +1305,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
null,
requiresHvmValue,
bitsValue,
volume.getAccountId(),
accountId,
null,
description,
passwordEnabledValue,
@ -1326,66 +1325,48 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
long templateId = command.getEntityId();
Long volumeId = command.getVolumeId();
Long snapshotId = command.getSnapshotId();
SnapshotVO snapshot = null;
// Verify input parameters
if (snapshotId != null) {
snapshot = _snapshotDao.findById(snapshotId);
// Set the volumeId to that of the snapshot. All further input parameter checks will be done w.r.t the volume.
volumeId = snapshot.getVolumeId();
}
// The volume below could be destroyed or removed.
VolumeVO volume = _volsDao.findById(volumeId);
String vmName = _storageMgr.getVmNameOnVolume(volume);
// If private template is created from Volume, check that the volume will not be active when the private template is created
if (snapshotId == null && !_storageMgr.volumeInactive(volume)) {
String msg = "Unable to create private template for volume: " + volume.getName() + "; volume is attached to a non-stopped VM.";
if (s_logger.isInfoEnabled()) {
s_logger.info(msg);
}
throw new CloudRuntimeException(msg);
}
SnapshotCommand cmd = null;
VMTemplateVO privateTemplate = null;
long zoneId = volume.getDataCenterId();
String uniqueName = getRandomPrivateTemplateName();
HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(zoneId);
String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId);
if (secondaryStorageHost == null || secondaryStorageURL == null) {
throw new CloudRuntimeException("Did not find the secondary storage URL in the database for zoneId "
+ zoneId);
}
if (snapshotId != null) {
volume = _volsDao.findById(volumeId);
StringBuilder userFolder = new StringBuilder();
Formatter userFolderFormat = new Formatter(userFolder);
userFolderFormat.format("u%06d", snapshot.getAccountId());
StoragePoolVO pool = null;
HostVO secondaryStorageHost = null;
long zoneId;
Long accountId = null;
if (snapshotId != null) { // create template from snapshot
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
if( snapshot == null ) {
throw new CloudRuntimeException("Unable to find Snapshot for Id " + snapshotId);
}
zoneId = snapshot.getDataCenterId();
secondaryStorageHost = _storageMgr.getSecondaryStorageHost(zoneId);
if ( secondaryStorageHost == null ) {
throw new CloudRuntimeException("Can not find the secondary storage for zoneId " + zoneId);
}
String secondaryStorageURL = secondaryStorageHost.getStorageUrl();
String name = command.getTemplateName();
String backupSnapshotUUID = snapshot.getBackupSnapshotId();
if (backupSnapshotUUID == null) {
throw new CloudRuntimeException("Unable to create private template from snapshot " + snapshotId + " due to there is no backupSnapshotUUID for this snapshot");
}
// We are creating a private template from a snapshot which has been
// backed up to secondary storage.
Long dcId = volume.getDataCenterId();
Long accountId = volume.getAccountId();
Long dcId = snapshot.getDataCenterId();
accountId = snapshot.getAccountId();
volumeId = snapshot.getVolumeId();
String origTemplateInstallPath = null;
cmd = new CreatePrivateTemplateFromSnapshotCommand(_storageMgr.getPrimaryStorageNameLabel(volume),
List<StoragePoolVO> storagePools = _storagePoolDao.listByDataCenterId(zoneId);
if( storagePools == null || storagePools.size() == 0) {
throw new CloudRuntimeException("Unable to find storage pools in zone " + zoneId);
}
pool = storagePools.get(0);
cmd = new CreatePrivateTemplateFromSnapshotCommand(pool.getUuid(),
secondaryStorageURL, dcId, accountId, snapshot.getVolumeId(), backupSnapshotUUID, snapshot.getName(),
origTemplateInstallPath, templateId, name);
} else if (volumeId != null) {
volume = _volsDao.findById(volumeId);
} else if (volumeId != null) {
VolumeVO volume = _volsDao.findById(volumeId);
if( volume == null ) {
throw new CloudRuntimeException("Unable to find volume for Id " + volumeId);
}
@ -1393,14 +1374,15 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
_templateDao.remove(templateId);
throw new CloudRuntimeException("Volume " + volumeId + " is empty, can't create template on it");
}
Long instanceId = volume.getInstanceId();
if (instanceId != null){
VMInstanceVO vm = _vmDao.findById(instanceId);
State vmState = vm.getState();
if( !vmState.equals(State.Stopped) && !vmState.equals(State.Destroyed)) {
throw new CloudRuntimeException("Please put VM " + vm.getName() + " into Stopped state first");
}
}
String vmName = _storageMgr.getVmNameOnVolume(volume);
zoneId = volume.getDataCenterId();
secondaryStorageHost = _storageMgr.getSecondaryStorageHost(zoneId);
if ( secondaryStorageHost == null ) {
throw new CloudRuntimeException("Can not find the secondary storage for zoneId " + zoneId);
}
String secondaryStorageURL = secondaryStorageHost.getStorageUrl();
pool = _storagePoolDao.findById(volume.getPoolId());
cmd = new CreatePrivateTemplateFromVolumeCommand(secondaryStorageURL, templateId, volume.getAccountId(),
command.getTemplateName(), uniqueName, volume.getPath(), vmName);
@ -1411,35 +1393,18 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
// on the storage server to create the template
// This can be sent to a KVM host too.
StoragePool pool = _storagePoolDao.findById(volume.getPoolId());
CreatePrivateTemplateAnswer answer = null;
volume = _volsDao.acquireInLockTable(volumeId, 10);
if( volume == null ) {
if( ! _volsDao.lockInLockTable(volumeId.toString(), 10)) {
throw new CloudRuntimeException("Creating template failed due to volume:" + volumeId + " is being used, try it later ");
}
try {
answer = (CreatePrivateTemplateAnswer)_storageMgr.sendToPool(pool, cmd);
} catch (StorageUnavailableException e) {
} finally {
_volsDao.releaseFromLockTable(volumeId);
_volsDao.unlockFromLockTable(volumeId.toString());
}
if ((answer != null) && answer.getResult()) {
privateTemplate = _templateDao.findById(templateId);
Long origTemplateId = volume.getTemplateId();
VMTemplateVO origTemplate = null;
if (origTemplateId != null) {
origTemplate = _templateDao.findById(origTemplateId);
}
if ((origTemplate != null) && !Storage.ImageFormat.ISO.equals(origTemplate.getFormat())) {
privateTemplate.setRequiresHvm(origTemplate.requiresHvm());
privateTemplate.setBits(origTemplate.getBits());
} else {
privateTemplate.setRequiresHvm(true);
privateTemplate.setBits(64);
}
String answerUniqueName = answer.getUniqueName();
if (answerUniqueName != null) {
privateTemplate.setUniqueName(answerUniqueName);
@ -1454,11 +1419,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
// Specify RAW format makes it unusable for snapshots.
privateTemplate.setFormat(ImageFormat.RAW);
}
if(snapshot != null) {
privateTemplate.setHypervisorType(snapshot.getHypervisorType());
}
_templateDao.update(templateId, privateTemplate);
// add template zone ref for this template
@ -1476,7 +1437,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
_usageEventDao.persist(usageEvent);
// Increment the number of templates
_accountMgr.incrementResourceCount(volume.getAccountId(), ResourceType.template);
_accountMgr.incrementResourceCount(accountId, ResourceType.template);
} else {

View File

@ -351,7 +351,6 @@ INSERT INTO `cloud`.`sequence` (name, value) VALUES ('private_mac_address_seq',
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('storage_pool_seq', 200);
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('volume_seq', 1);
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('networks_seq', 200);
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('snapshots_seq', 1);
CREATE TABLE `cloud`.`volumes` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
@ -398,13 +397,16 @@ CREATE TABLE `cloud`.`volumes` (
CREATE TABLE `cloud`.`snapshots` (
`id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`data_center_id` bigint unsigned NOT NULL,
`account_id` bigint unsigned NOT NULL COMMENT 'owner. foreign key to account table',
`domain_id` bigint unsigned NOT NULL COMMENT 'the domain that the owner belongs to',
`volume_id` bigint unsigned NOT NULL COMMENT 'volume it belongs to. foreign key to volume table',
`status` varchar(32) COMMENT 'snapshot creation status',
`path` varchar(255) COMMENT 'Path',
`name` varchar(255) NOT NULL COMMENT 'snapshot name',
`snapshot_type` int(4) NOT NULL COMMENT 'type of snapshot, e.g. manual, recurring',
`type_description` varchar(25) COMMENT 'description of the type of snapshot, e.g. manual, recurring',
`size` bigint unsigned NOT NULL COMMENT 'original disk size of snapshot',
`created` datetime COMMENT 'Date Created',
`removed` datetime COMMENT 'Date removed. not null if removed',
`backup_snap_id` varchar(255) COMMENT 'Back up uuid of the snapshot',
@ -1242,7 +1244,7 @@ CREATE TABLE `cloud`.`launch_permission` (
CREATE TABLE `cloud`.`snapshot_policy` (
`id` bigint unsigned NOT NULL auto_increment,
`volume_id` bigint unsigned NOT NULL unique,
`volume_id` bigint unsigned NOT NULL,
`schedule` varchar(100) NOT NULL COMMENT 'schedule time of execution',
`timezone` varchar(100) NOT NULL COMMENT 'the timezone in which the schedule time is specified',
`interval` int(4) NOT NULL default 4 COMMENT 'backup schedule, e.g. hourly, daily, etc.',
@ -1260,11 +1262,12 @@ CREATE TABLE `cloud`.`snapshot_policy_ref` (
CREATE TABLE `cloud`.`snapshot_schedule` (
`id` bigint unsigned NOT NULL auto_increment,
`volume_id` bigint unsigned NOT NULL unique COMMENT 'The volume for which this snapshot is being taken',
`volume_id` bigint unsigned NOT NULL COMMENT 'The volume for which this snapshot is being taken',
`policy_id` bigint unsigned NOT NULL COMMENT 'One of the policyIds for which this snapshot was taken',
`scheduled_timestamp` datetime NOT NULL COMMENT 'Time at which the snapshot was scheduled for execution',
`async_job_id` bigint unsigned COMMENT 'If this schedule is being executed, it is the id of the create aysnc_job. Before that it is null',
`snapshot_id` bigint unsigned COMMENT 'If this schedule is being executed, then the corresponding snapshot has this id. Before that it is null',
UNIQUE (volume_id, policy_id),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -2,7 +2,6 @@
-- Schema upgrade from 2.1 to 2.2;
--;
ALTER TABLE `cloud`.`template_host_ref` ADD COLUMN `physical_size` bigint unsigned NOT NULL DEFAULT 0;
ALTER TABLE `cloud`.`snapshots` MODIFY COLUMN `id` bigint unsigned UNIQUE NOT NULL;
ALTER TABLE `cloud`.`vm_instance` DROP COLUMN `group`;
ALTER TABLE `cloud`.`cluster` ADD COLUMN `guid` varchar(255) UNIQUE DEFAULT NULL;
ALTER TABLE `cloud`.`cluster` ADD COLUMN `cluster_type` varchar(64) DEFAULT 'CloudManaged';
@ -335,6 +334,10 @@ CREATE TABLE `cloud`.`upload` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`snapshots` ADD COLUMN `data_center_id` bigint unsigned NOT NULL;
ALTER TABLE `cloud`.`snapshots` ADD COLUMN `domain_id` bigint unsigned NOT NULL;
ALTER TABLE `cloud`.`snapshots` ADD COLUMN `size` bigint unsigned NOT NULL ;
ALTER TABLE `cloud`.`template_host_ref` ADD COLUMN `physical size` bigint unsigned DEFAULT 0;
ALTER TABLE `cloud`.`console_proxy` MODIFY COLUMN `public_mac_address` varchar(17);
@ -518,4 +521,3 @@ CREATE TABLE `cloud`.`storage_pool_work` (
-- Insert stuff?;
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('volume_seq', (SELECT max(id) + 1 or 200 from volumes));
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('networks_seq', 200);
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('snapshots_seq', (SELECT max(id) + 1 or 200 from snapshots));

View File

@ -91,17 +91,7 @@ public class DateUtil {
DAILY,
WEEKLY,
MONTHLY;
private int max = 8;
public void setMax(int max) {
this.max = max;
}
public int getMax() {
return max;
}
boolean equals(String intervalType) {
return super.toString().equalsIgnoreCase(intervalType);
}

View File

@ -228,5 +228,11 @@ public interface GenericDao<T, ID extends Serializable> {
boolean configure(String name, Map<String, Object> params) throws ConfigurationException;
<M> List<M> customSearch(SearchCriteria<M> sc, Filter filter);
boolean lockInLockTable(String id);
boolean lockInLockTable(String id, int seconds);
boolean unlockFromLockTable(String id);
}

View File

@ -923,6 +923,23 @@ public abstract class GenericDaoBase<T, ID extends Serializable> implements Gene
final Transaction txn = Transaction.currentTxn();
return txn.release(_table + id);
}
@Override @DB(txn=false)
public boolean lockInLockTable(final String id) {
return lockInLockTable(id, _timeoutSeconds);
}
@Override
public boolean lockInLockTable(final String id, int seconds) {
Transaction txn = Transaction.currentTxn();
return txn.lock(_table + id, seconds);
}
@Override
public boolean unlockFromLockTable(final String id) {
final Transaction txn = Transaction.currentTxn();
return txn.release(_table + id);
}
@Override @DB(txn=false)
public List<T> listAllIncludingRemoved() {