package org.zstack.storage.backup;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.transaction.annotation.Transactional;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.core.workflow.NoRollbackFlow;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.storage.backup.*;
import org.zstack.header.storage.backup.BackupStorageConstant.AllocatorParams;
import static org.zstack.core.Platform.operr;
import javax.persistence.TypedQuery;
import java.util.List;
import java.util.Map;
/**
*/
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class BackupStorageMainAllocatorFlow extends NoRollbackFlow {
@Autowired
private DatabaseFacade dbf;
@Autowired
private ErrorFacade errf;
private class Result {
String error;
List<BackupStorageVO> result;
}
@Transactional(readOnly = true)
private Result allocate(Map data) {
BackupStorageAllocationSpec spec = (BackupStorageAllocationSpec) data.get(AllocatorParams.SPEC);
TypedQuery<BackupStorageVO> query = null;
String error;
if (spec.getRequiredBackupStorageUuid() != null && spec.getRequiredZoneUuid() != null) {
String sql = "select bs from BackupStorageVO bs, BackupStorageZoneRefVO ref where ref.backupStorageUuid = bs.uuid and ref.zoneUuid = :zoneUuid and bs.uuid = :uuid and bs.availableCapacity > :size and bs.status = :status and bs.state = :state";
query = dbf.getEntityManager().createQuery(sql, BackupStorageVO.class);
query.setParameter("uuid", spec.getRequiredBackupStorageUuid());
query.setParameter("zoneUuid", spec.getRequiredZoneUuid());
query.setParameter("size", spec.getSize());
query.setParameter("status", BackupStorageStatus.Connected);
query.setParameter("state", BackupStorageState.Enabled);
error = String.format("backup storage[uuid:%s] can not satisfy one or more conditions[available capacity > %s bytes, status = %s, state = %s], or it doesn't attach to zone[uuid:%s]",
spec.getRequiredBackupStorageUuid(), spec.getSize(), BackupStorageStatus.Connected, BackupStorageState.Enabled, spec.getRequiredZoneUuid());
} else if (spec.getRequiredBackupStorageUuid() != null) {
String sql = "select bs from BackupStorageVO bs where bs.uuid = :uuid and bs.availableCapacity > :size and bs.status = :status and bs.state = :state";
query = dbf.getEntityManager().createQuery(sql, BackupStorageVO.class);
query.setParameter("uuid", spec.getRequiredBackupStorageUuid());
query.setParameter("size", spec.getSize());
query.setParameter("status", BackupStorageStatus.Connected);
query.setParameter("state", BackupStorageState.Enabled);
error = String.format("backup storage[uuid:%s] can not satisfy one or more conditions[available capacity > %s bytes, status = %s, state = %s]",
spec.getRequiredBackupStorageUuid(), spec.getSize(), BackupStorageStatus.Connected, BackupStorageState.Enabled);
} else if (spec.getRequiredZoneUuid() != null) {
String sql = "select bs from BackupStorageVO bs, BackupStorageZoneRefVO ref where bs.availableCapacity > :size and bs.status = :status and bs.state = :state and bs.uuid = ref.backupStorageUuid and ref.zoneUuid = :zoneUuid";
query = dbf.getEntityManager().createQuery(sql, BackupStorageVO.class);
query.setParameter("size", spec.getSize());
query.setParameter("status", BackupStorageStatus.Connected);
query.setParameter("state", BackupStorageState.Enabled);
query.setParameter("zoneUuid", spec.getRequiredZoneUuid());
error = String.format("no backup storage that satisfies conditions[available capacity > %s bytes, status = %s, state = %s, attached zone uuid=%s] found",
spec.getSize(), BackupStorageStatus.Connected, BackupStorageState.Enabled, spec.getRequiredZoneUuid());
} else {
String sql = "select bs from BackupStorageVO bs where bs.availableCapacity > :size and bs.status = :status and bs.state = :state";
query = dbf.getEntityManager().createQuery(sql, BackupStorageVO.class);
query.setParameter("size", spec.getSize());
query.setParameter("status", BackupStorageStatus.Connected);
query.setParameter("state", BackupStorageState.Enabled);
error = String.format("no backup storage that satisfies conditions[available capacity > %s bytes, status = %s, state = %s] found",
spec.getSize(), BackupStorageStatus.Connected, BackupStorageState.Enabled);
}
Result ret = new Result();
ret.result = query.getResultList();
ret.error = error;
return ret;
}
@Override
public void run(FlowTrigger trigger, Map data) {
Result ret = allocate(data);
if (ret.result.isEmpty()) {
throw new OperationFailureException(operr(ret.error));
}
data.put(AllocatorParams.CANDIDATES, ret.result);
trigger.next();
}
}